Commit working code.

This commit is contained in:
Joseph Eagar 2021-10-03 14:25:38 -07:00
parent 7327e15630
commit 99b9c1bcad
22 changed files with 1480 additions and 269 deletions

View File

@ -140,16 +140,11 @@ def draw_vpaint_symmetry(layout, vpaint, obj):
# Most of these panels should not be visible in GP edit modes
def is_not_gpencil_edit_mode(context):
is_gpmode = (
context.active_object and
context.active_object.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}
)
is_gpmode = (context.active_object and context.active_object.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'})
return not is_gpmode
# ********** default tools for object mode ****************
class VIEW3D_PT_tools_object_options(View3DPanel, Panel):
bl_category = "Tool"
bl_context = ".objectmode" # dot on purpose (access from topbar)
@ -181,8 +176,6 @@ class VIEW3D_PT_tools_object_options_transform(View3DPanel, Panel):
# ********** default tools for editmode_mesh ****************
class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_category = "Tool"
bl_context = ".mesh_edit" # dot on purpose (access from topbar)
@ -256,8 +249,6 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
# ********** default tools for editmode_armature ****************
class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
bl_category = "Tool"
bl_context = ".armature_edit" # dot on purpose (access from topbar)
@ -270,7 +261,6 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
# ********** default tools for pose-mode ****************
class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
bl_category = "Tool"
bl_context = ".posemode" # dot on purpose (access from topbar)
@ -292,8 +282,6 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
layout.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
# ********** default tools for paint modes ****************
class TEXTURE_UL_texpaintslots(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
# mat = data
@ -461,8 +449,7 @@ class VIEW3D_PT_tools_brush_settings_channels_preview(Panel, View3DPaintBrushPan
brush_settings_channels(layout.column(), context, brush, show_reorder=True, ui_editing=False,
popover=self.is_popover,
prefix="VIEW3D_PT_brush_category_edit_",
parent="VIEW3D_PT_tools_brush_settings_channels_preview"
)
parent="VIEW3D_PT_tools_brush_settings_channels_preview")
class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
@ -538,14 +525,12 @@ class VIEW3D_PT_tools_persistent_base_channels(Panel, View3DPaintPanel):
brush = settings.brush
sculpt = context.tool_settings.sculpt
UnifiedPaintPanel.channel_unified(
layout,
UnifiedPaintPanel.channel_unified(layout,
context,
brush,
"use_persistent",
#text="Weight By Face Area",
ui_editing=False
)
ui_editing=False)
layout.operator("sculpt.set_persistent_base")
@ -740,10 +725,11 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
if (
(settings:= cls.paint_settings(context)) and
(brush:= settings.brush)
):
settings = cls.paint_settings(context)
if settings and settings.brush:
brush = settings.brush
if context.sculpt_object or context.vertex_paint_object:
return True
elif context.image_paint_object:
@ -935,34 +921,28 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
row.label(text="Remesher Options")
row.prop(ch, "inherit", text="", icon="BRUSHES_ALL")
else:
UnifiedPaintPanel.channel_unified(
layout,
UnifiedPaintPanel.channel_unified(layout,
context,
brush,
"dyntopo_mode",
text="Remesher Options",
expand=True
)
expand=True)
UnifiedPaintPanel.channel_unified(
layout,
UnifiedPaintPanel.channel_unified(layout,
context,
brush,
"dyntopo_detail_mode",
text="Detail Mode",
expand=False
)
expand=False)
keys = ["dyntopo_spacing", "dyntopo_detail_size", "dyntopo_detail_range", "dyntopo_detail_percent",
"dyntopo_constant_detail", "dyntopo_radius_scale", "dyntopo_disabled"]
for k in keys:
UnifiedPaintPanel.channel_unified(
layout,
UnifiedPaintPanel.channel_unified(layout,
context,
brush,
k,
slider=True
)
slider=True)
return
layout.use_property_split = True
@ -1017,17 +997,15 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
do_prop("radius_scale")
class SCULPT_OT_set_dyntopo_mode (Operator):
class SCULPT_OT_set_dyntopo_mode(Operator):
"""Set refine mode"""
bl_label = "Set Detail Mode"
bl_idname = "sculpt.set_dyntopo_mode"
mode: EnumProperty(items=[
("SC", "Subdivide Collapse", "", 1),
mode : EnumProperty(items=[("SC", "Subdivide Collapse", "", 1),
("S", "Subdivide Edges", "", 2),
("C", "Collapse Edges", "", 3)
])
("C", "Collapse Edges", "", 3)])
def execute(self, context):
brush = context.tool_settings.sculpt.brush
@ -1083,12 +1061,10 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
def draw_header(self, context):
is_popover = self.is_popover
layout = self.layout
layout.operator(
"sculpt.dynamic_topology_toggle",
layout.operator("sculpt.dynamic_topology_toggle",
icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
text="",
emboss=is_popover,
)
emboss=is_popover,)
def draw(self, context):
layout = self.layout
@ -1113,51 +1089,43 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
if detail_mode in {'CONSTANT', 'MANUAL'}:
row = sub.row(align=True)
#row.prop(sculpt, "constant_detail_resolution")
UnifiedPaintPanel.channel_unified(
row,
UnifiedPaintPanel.channel_unified(row,
context,
brush,
"dyntopo_constant_detail",
text="Constant Resolution",
# slider=True,
ui_editing=False,
pressure=False
)
pressure=False)
props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
props.mode = 'DYNTOPO'
elif detail_mode == 'BRUSH':
UnifiedPaintPanel.channel_unified(
sub,
UnifiedPaintPanel.channel_unified(sub,
context,
brush,
"dyntopo_detail_percent",
text="Detail Percent",
# slider=True,
ui_editing=False,
pressure=False
)
pressure=False)
else:
UnifiedPaintPanel.channel_unified(
sub,
UnifiedPaintPanel.channel_unified(sub,
context,
brush,
"dyntopo_detail_size",
text="Detail Size",
# slider=True,
ui_editing=False,
pressure=False
)
pressure=False)
# """
UnifiedPaintPanel.channel_unified(
sub,
UnifiedPaintPanel.channel_unified(sub,
context,
brush,
"dyntopo_detail_mode",
text="Detailing",
expand=False,
ui_editing=False
)
ui_editing=False)
set_dyntopo_mode_button(sub, context)
@ -1189,10 +1157,16 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_spacing", slider=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_radius_scale", slider=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(sub,
context,
brush,
"dyntopo_disable_smooth",
expand=False,
text="No Dyntopo Smooth",
ui_editing=False)
#col.prop(sculpt, "dyntopo_spacing")
#col.prop(sculpt, "dyntopo_radius_scale")
class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Remesh"
@ -1255,8 +1229,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
col.prop(sculpt, "use_deform_only")
col.prop(sculpt, "show_sculpt_pivot")
UnifiedPaintPanel.channel_unified(
layout.column(),
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"smooth_strength_factor", ui_editing=False, slider=True)
@ -1265,19 +1238,16 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
col.separator()
UnifiedPaintPanel.channel_unified(
layout.column(),
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"automasking", toolsettings_only=True, expand=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(
layout.column(),
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"automasking_boundary_edges_propagation_steps",
toolsettings_only=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(
layout.column(),
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"concave_mask_factor",
@ -1327,11 +1297,9 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
return (
(context.sculpt_object and context.tool_settings.sculpt) and
# When used in the tool header, this is explicitly included next to the XYZ symmetry buttons.
(context.region.type != 'TOOL_HEADER')
)
return ((context.sculpt_object and context.tool_settings.sculpt) and # When used in the tool header, this is explicitly included next to
# the XYZ symmetry buttons.
(context.region.type != 'TOOL_HEADER'))
def draw(self, context):
layout = self.layout
@ -1387,7 +1355,8 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
# When used in the tool header, this is explicitly included next to the XYZ symmetry buttons.
# When used in the tool header, this is explicitly included next to the
# XYZ symmetry buttons.
return (context.region.type != 'TOOL_HEADER')
def draw(self, context):
@ -1451,7 +1420,8 @@ class VIEW3D_PT_tools_vertexpaint_options(Panel, View3DPaintPanel):
@classmethod
def poll(cls, _context):
# This is currently unused, since there aren't any Vertex Paint mode specific options.
# This is currently unused, since there aren't any Vertex Paint mode
# specific options.
return False
def draw(self, _context):
@ -1468,7 +1438,8 @@ class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
# When used in the tool header, this is explicitly included next to the XYZ symmetry buttons.
# When used in the tool header, this is explicitly included next to the
# XYZ symmetry buttons.
return (context.region.type != 'TOOL_HEADER')
def draw(self, context):
@ -1529,7 +1500,8 @@ class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
# When used in the tool header, this is explicitly included next to the XYZ symmetry buttons.
# When used in the tool header, this is explicitly included next to the
# XYZ symmetry buttons.
return (context.region.type != 'TOOL_HEADER')
def draw(self, context):
@ -1608,9 +1580,11 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
@classmethod
def poll(cls, _context):
# This is currently unused, since there aren't any Vertex Paint mode specific options.
# This is currently unused, since there aren't any Vertex Paint mode
# specific options.
return False
# return (context.image_paint_object and context.tool_settings.image_paint)
# return (context.image_paint_object and
# context.tool_settings.image_paint)
def draw(self, _context):
layout = self.layout
@ -1741,7 +1715,6 @@ class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel):
# ********** grease pencil object tool panels ****************
# Grease Pencil drawing brushes
def tool_use_brush(context):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
@ -1801,7 +1774,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePen
bl_label = "Brush Settings"
bl_options = {'DEFAULT_CLOSED'}
# What is the point of brush presets? Seems to serve the exact same purpose as brushes themselves??
# What is the point of brush presets? Seems to serve the exact same
# purpose as brushes themselves??
def draw_header_preset(self, _context):
VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
@ -1888,12 +1862,10 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
elif brush.gpencil_tool == 'FILL':
row = col.row(align=True)
row.prop(gp_settings, "fill_draw_mode", text="Boundary")
row.prop(
gp_settings,
row.prop(gp_settings,
"show_fill_boundary",
icon='HIDE_OFF' if gp_settings.show_fill_boundary else 'HIDE_ON',
text="",
)
text="",)
col.separator()
row = col.row(align=True)
@ -1902,12 +1874,10 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel):
col.separator()
row = col.row(align=True)
row.prop(gp_settings, "extend_stroke_factor")
row.prop(
gp_settings,
row.prop(gp_settings,
"show_fill_extend",
icon='HIDE_OFF' if gp_settings.show_fill_extend else 'HIDE_ON',
text="",
)
text="",)
col.separator()
col.prop(gp_settings, "fill_leak", text="Leak Size")
@ -2612,8 +2582,7 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
preset_add_operator = "scene.gpencil_brush_preset_add"
classes = (
VIEW3D_MT_brush_context_menu,
classes = (VIEW3D_MT_brush_context_menu,
VIEW3D_MT_brush_gpencil_context_menu,
VIEW3D_MT_brush_context_menu_paint_modes,
VIEW3D_PT_tools_object_options,
@ -2705,8 +2674,7 @@ classes = (
VIEW3D_PT_tools_brush_swatches_channels,
VIEW3D_PT_tools_persistent_base_channels,
VIEW3D_PT_sculpt_dyntopo_advanced,
SCULPT_OT_set_dyntopo_mode
)
SCULPT_OT_set_dyntopo_mode)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class

View File

@ -475,7 +475,8 @@ bool BKE_pbvh_bmesh_update_topology(
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data,
int custom_max_steps); // if 0, will use defaul hueristics for max steps
int custom_max_steps, // if 0, will use defaul hueristics for max steps
bool disable_surface_relax);
bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
bool (*searchcb)(PBVHNode *node, void *data),
@ -490,7 +491,8 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
int sym_axis,
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data);
void *mask_cb_data,
bool disable_surface_relax);
/* Node Access */
void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node);
@ -801,8 +803,20 @@ void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
symmetrize.*/
void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh);
/* saves all bmesh references to internal indices, to be restored later */
void BKE_pbvh_bmesh_save_indices(PBVH *pbvh);
/* restore bmesh references from previously indices saved by BKE_pbvh_bmesh_save_indices */
void BKE_pbvh_bmesh_from_saved_indices(PBVH *pbvh);
/* wraps calls to BM_mesh_toolflags_set in BKE_pbvh_bmesh_save_indices and
* BKE_pbvh_bmesh_from_saved_indices */
void BKE_pbvh_bmesh_set_toolflags(PBVH *pbvh, bool use_toolflags);
void BKE_pbvh_bmesh_remove_face(PBVH *pbvh, struct BMFace *f, bool log_face);
void BKE_pbvh_bmesh_remove_edge(PBVH *pbvh, struct BMEdge *e, bool log_vert);
void BKE_pbvh_bmesh_remove_vertex(PBVH *pbvh, struct BMVert *v, bool log_vert);
void BKE_pbvh_bmesh_add_face(PBVH *pbvh, struct BMFace *f, bool log_face, bool force_tree_walk);
// note that e_tri and f_example are allowed to be NULL

View File

@ -205,6 +205,7 @@ places in rna_engine_codebase are relevent:
"used for topology rake", 1.0f, 0.001f, 5.0f, 0.01f, 2.0f, false)
MAKE_FLOAT_EX_FLAG(dyntopo_radius_scale, "Radius Scale", "Ratio between the brush radius and the radius that is going to be "
"used for DynTopo", 1.0f, 0.001f, 5.0f, 0.01f, 2.0f, false, BRUSH_CHANNEL_INHERIT)
MAKE_BOOL(dyntopo_disable_smooth, "Disable Dyntopo Smooth", "Disable the small amount of smoothing dyntopo applies to improve numerical stability", false)
MAKE_FLOAT_EX(projection, "Projection", "Amount of volume preserving projection", 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT_EX(autosmooth_projection, "Auto-Smooth Projection", "Amount of volume preserving projection", 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, false)
MAKE_FLOAT_EX(topology_rake_projection, "Rake Projection", "Amount of volume preserving projection", 0.975f, 0.0f, 1.0f, 0.0f, 1.0f, false)

View File

@ -1002,6 +1002,7 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(concave_mask_factor);
ADDCH(dyntopo_disabled);
ADDCH(dyntopo_disable_smooth);
ADDCH(dyntopo_detail_mode);
ADDCH(dyntopo_mode)->flag;

View File

@ -1257,6 +1257,14 @@ void BKE_pbvh_bmesh_remove_face(PBVH *pbvh, BMFace *f, bool log_face)
pbvh_bmesh_face_remove(pbvh, f, log_face, true, true);
}
void BKE_pbvh_bmesh_remove_edge(PBVH *pbvh, BMEdge *e, bool log_vert)
{
if (log_vert) {
BM_log_edge_removed(pbvh->bm_log, e);
}
}
void BKE_pbvh_bmesh_remove_vertex(PBVH *pbvh, BMVert *v, bool log_vert)
{
pbvh_bmesh_vert_remove(pbvh, v);
@ -1973,9 +1981,9 @@ BLI_INLINE int dyntopo_thread_rand(int seed)
return (seed * multiplier + addend) & mask;
}
static void long_edge_queue_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
ATTR_NO_OPT static void long_edge_queue_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
EdgeQueueThreadData *tdata = ((EdgeQueueThreadData *)userdata) + n;
PBVHNode *node = tdata->node;
@ -1989,6 +1997,7 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
BMFace *f, **faces = NULL;
BLI_array_declare(faces);
const int cd_dyn_vert = tdata->pbvh->cd_dyn_vert;
bool do_smooth = eq_ctx->surface_smooth_fac > 0.0f;
#if 1
# if 0
@ -2052,7 +2061,7 @@ static void long_edge_queue_task_cb(void *__restrict userdata,
// but tangentially to surface.
int randval = (seed = dyntopo_thread_rand(seed)) & 255;
if (randval > 127) {
if (do_smooth && randval > 127) {
surface_smooth_v_safe(tdata->pbvh, l_iter->v, eq_ctx->surface_smooth_fac);
}
@ -5269,7 +5278,8 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data,
int custom_max_steps)
int custom_max_steps,
bool disable_surface_relax)
{
/* 2 is enough for edge faces - manifold edge */
@ -5322,7 +5332,10 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
float safe_smooth;
if ((mode & PBVH_Subdivide) && (!(mode & PBVH_Collapse) || (mode & PBVH_LocalCollapse))) {
if (disable_surface_relax) {
safe_smooth = 0.0f;
}
else if ((mode & PBVH_Subdivide) && (!(mode & PBVH_Collapse) || (mode & PBVH_LocalCollapse))) {
safe_smooth = DYNTOPO_SAFE_SMOOTH_SUBD_ONLY_FAC;
}
else {

View File

@ -1885,7 +1885,8 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
int sym_axis,
bool updatePBVH,
DyntopoMaskCB mask_cb,
void *mask_cb_data)
void *mask_cb_data,
bool disable_surface_relax)
{
bool modified = false;
@ -1915,7 +1916,8 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
updatePBVH,
mask_cb,
mask_cb_data,
0);
0,
disable_surface_relax);
return modified;
}
@ -5151,3 +5153,208 @@ void pbvh_bmesh_do_cache_test()
// pbvh_bmesh_cache_test_default_params(&params);
// pbvh_bmesh_cache_test(&params, &bm, &pbvh);
}
/* saves all bmesh references to internal indices, to be restored later */
ATTR_NO_OPT void BKE_pbvh_bmesh_save_indices(PBVH *pbvh)
{
BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT | BM_EDGE | BM_FACE);
BMFace *f;
BMVert *v;
BMIter iter;
int j = 0;
BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
do {
l->head.index = j++;
} while ((l = l->next) != f->l_first);
}
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
if (!(node->flag & PBVH_Leaf)) {
continue;
}
node->prim_indices = MEM_calloc_arrayN(1 + node->bm_faces->length +
node->bm_unique_verts->length,
sizeof(int),
"saved bmesh indices");
int j = 0;
TGSET_ITER (f, node->bm_faces) {
node->prim_indices[j++] = f->head.index;
}
TGSET_ITER_END;
// flag start of vertex array
node->prim_indices[j++] = -1;
TGSET_ITER (v, node->bm_unique_verts) {
node->prim_indices[j++] = v->head.index;
}
TGSET_ITER_END;
node->totprim = j;
// don't try to save invalid triangulation
if (node->flag & PBVH_UpdateTris) {
continue;
}
// now do tribufs
for (j = 0; j < node->tot_tri_buffers + 1; j++) {
PBVHTriBuf *tribuf = j == node->tot_tri_buffers ? node->tribuf : node->tri_buffers + j;
if (!tribuf) {
break;
}
for (int k = 0; k < tribuf->totvert; k++) {
if (i == 35 && k == 12) {
printf("eek!");
}
tribuf->verts[k].i = ((BMVert *)tribuf->verts[k].i)->head.index;
}
for (int k = 0; k < tribuf->totloop; k++) {
tribuf->loops[k] = ((BMLoop *)tribuf->loops[k])->head.index;
}
for (int k = 0; k < tribuf->tottri; k++) {
PBVHTri *tri = tribuf->tris + k;
BMFace *f = (BMFace *)tri->f.i;
tri->f.i = f->head.index;
for (int l = 0; l < 3; l++) {
tri->l[l] = ((BMLoop *)tri->l[l])->head.index;
}
}
}
}
}
/* restore bmesh references from previously indices saved by BKE_pbvh_bmesh_save_indices */
ATTR_NO_OPT void BKE_pbvh_bmesh_from_saved_indices(PBVH *pbvh)
{
BM_mesh_elem_table_ensure(pbvh->bm, BM_VERT | BM_EDGE | BM_FACE);
BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT | BM_EDGE | BM_FACE);
BMLoop **ltable = NULL;
BLI_array_declare(ltable);
BMFace *f;
BMIter iter;
int i = 0;
BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
BMLoop *l = f->l_first;
do {
l->head.index = i++;
BLI_array_append(ltable, l);
} while ((l = l->next) != f->l_first);
}
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
if (!(node->flag & PBVH_Leaf)) {
continue;
}
BLI_table_gset_free(node->bm_unique_verts, NULL);
BLI_table_gset_free(node->bm_faces, NULL);
if (node->bm_other_verts) {
BLI_table_gset_free(node->bm_other_verts, NULL);
}
node->bm_other_verts = BLI_table_gset_new("bm_other_verts");
node->flag |= PBVH_UpdateOtherVerts;
node->bm_faces = BLI_table_gset_new("bm_faces");
node->bm_unique_verts = BLI_table_gset_new("bm_verts");
int j = 0;
int *data = node->prim_indices;
while (data[j] != -1 && j < node->totprim) {
BMFace *f = pbvh->bm->ftable[data[j]];
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, i);
BLI_table_gset_insert(node->bm_faces, f);
j++;
}
j++;
while (j < node->totprim) {
if (data[j] < 0 || data[j] >= pbvh->bm->totvert) {
printf("%s: bad vertex at index %d!\n", __func__, data[j]);
continue;
}
BMVert *v = pbvh->bm->vtable[data[j]];
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, i);
BLI_table_gset_insert(node->bm_unique_verts, v);
j++;
}
MEM_SAFE_FREE(node->prim_indices);
// don't try to load invalid triangulation
if (node->flag & PBVH_UpdateTris) {
continue;
}
for (j = 0; j < node->tot_tri_buffers + 1; j++) {
PBVHTriBuf *tribuf = j == node->tot_tri_buffers ? node->tribuf : node->tri_buffers + j;
if (!tribuf) {
break;
}
for (int k = 0; k < tribuf->totvert; k++) {
tribuf->verts[k].i = (intptr_t)pbvh->bm->vtable[tribuf->verts[k].i];
}
for (int k = 0; k < tribuf->totloop; k++) {
tribuf->loops[k] = (uintptr_t)ltable[tribuf->loops[k]];
}
for (int k = 0; k < tribuf->tottri; k++) {
PBVHTri *tri = tribuf->tris + k;
for (int l = 0; l < 3; l++) {
tri->l[l] = (uintptr_t)ltable[tri->l[l]];
}
tri->f.i = (intptr_t)pbvh->bm->ftable[tri->f.i];
}
}
node->prim_indices = NULL;
node->totprim = 0;
}
BLI_array_free(ltable);
}
void BKE_pbvh_bmesh_set_toolflags(PBVH *pbvh, bool use_toolflags)
{
if (use_toolflags == pbvh->bm->use_toolflags) {
return;
}
BKE_pbvh_bmesh_save_indices(pbvh);
BM_mesh_toolflags_set(pbvh->bm, use_toolflags);
BKE_pbvh_bmesh_from_saved_indices(pbvh);
}

View File

@ -38,6 +38,8 @@ extern "C" {
struct MemArena;
typedef struct MemArena MemArena;
int BLI_memarena_size(const struct MemArena *ma);
struct MemArena *BLI_memarena_new(const size_t bufsize,
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
ATTR_NONNULL(2) ATTR_MALLOC;

View File

@ -53,6 +53,8 @@ typedef struct {
unsigned int i;
} SmallHashIter;
int BLI_smallhash_memuse(SmallHash *sh);
void BLI_smallhash_init_ex(SmallHash *sh, const unsigned int nentries_reserve) ATTR_NONNULL(1);
void BLI_smallhash_init(SmallHash *sh) ATTR_NONNULL(1);
void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);

View File

@ -64,6 +64,17 @@ struct MemArena {
bool use_calloc;
};
int BLI_memarena_size(const struct MemArena *ma)
{
int ret = 0;
for (struct MemBuf *buf = ma->bufs; buf; buf = buf->next) {
ret += (int)ma->bufsize;
}
return ret;
}
static void memarena_buf_free_all(struct MemBuf *mb)
{
while (mb != NULL) {

View File

@ -118,6 +118,11 @@ BLI_INLINE bool smallhash_val_is_used(const void *val)
extern const uint BLI_ghash_hash_sizes[];
#define hashsizes BLI_ghash_hash_sizes
int BLI_smallhash_memuse(SmallHash *sh)
{
return (int)sh->nbuckets * sizeof(SmallHashEntry) + (int)sizeof(SmallHash);
}
BLI_INLINE uintptr_t smallhash_key(const uintptr_t key)
{
#if 1

View File

@ -1248,3 +1248,78 @@ void bm_update_idmap_cdlayers(BMesh *bm)
bm->idmap.cd_id_off[BM_LOOP] = CustomData_get_offset(&bm->ldata, CD_MESH_ID);
bm->idmap.cd_id_off[BM_FACE] = CustomData_get_offset(&bm->pdata, CD_MESH_ID);
}
ATTR_NO_OPT void bm_rebuild_idmap(BMesh *bm)
{
CustomData *cdatas[4] = {
&bm->vdata,
&bm->edata,
&bm->ldata,
&bm->pdata,
};
if (bm->idmap.flag & BM_HAS_ID_MAP) {
if (bm->idmap.flag & BM_NO_REUSE_IDS) {
if (bm->idmap.ghash) {
BLI_ghash_clear(bm->idmap.ghash, NULL, NULL);
}
else {
bm->idmap.ghash = BLI_ghash_ptr_new("bm->idmap.ghash");
}
}
else if (bm->idmap.map) {
memset(bm->idmap.map, 0, sizeof(void *) * bm->idmap.map_size);
}
}
for (int i = 0; i < 4; i++) {
int type = 1 << i;
if (!(bm->idmap.flag & type)) {
continue;
}
int cd_off = bm->idmap.cd_id_off[type];
cd_off = CustomData_get_offset(cdatas[i], CD_MESH_ID);
if (bm->idmap.flag & BM_NO_REUSE_IDS) {
BLI_mempool_iter iter;
BLI_mempool_iternew((&bm->vpool)[i], &iter);
BMElem *elem = (BMElem *)BLI_mempool_iterstep(&iter);
for (; elem; elem = (BMElem *)BLI_mempool_iterstep(&iter)) {
void **val;
if (!BLI_ghash_ensure_p(bm->idmap.ghash, (void *)elem, &val)) {
*val = POINTER_FROM_INT(BM_ELEM_CD_GET_INT(elem, cd_off));
}
}
}
else {
BLI_mempool_iter iter;
BLI_mempool_iternew((&bm->vpool)[i], &iter);
BMElem *elem = (BMElem *)BLI_mempool_iterstep(&iter);
for (; elem; elem = (BMElem *)BLI_mempool_iterstep(&iter)) {
void **val;
int id = BM_ELEM_CD_GET_INT(elem, cd_off);
if (!bm->idmap.map || bm->idmap.map_size <= id) {
int size = (2 + id);
size += size >> 1;
if (!bm->idmap.map) {
bm->idmap.map = MEM_calloc_arrayN(size, sizeof(*bm->idmap.map), "bm->idmap.map");
}
else {
bm->idmap.map = MEM_recallocN(bm->idmap.map, sizeof(void *) * size);
}
bm->idmap.map_size = size;
}
bm->idmap.map[BM_ELEM_CD_GET_INT(elem, cd_off)] = elem;
}
}
}
}

View File

@ -39,6 +39,7 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_mempool.h"
#include "BLI_smallhash.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@ -57,6 +58,66 @@
#define CUSTOMDATA
#define BM_LOG_USE_SMALLHASH
#ifdef BM_LOG_USE_SMALLHASH
static SmallHash *new_smallhash()
{
SmallHash *sh = MEM_callocN(sizeof(*sh), "smallhash for dyntopo");
BLI_smallhash_init(sh);
return sh;
}
static void free_smallhash(SmallHash *sh)
{
BLI_smallhash_release(sh);
MEM_freeN(sh);
}
static void smallhash_reserve(SmallHash *sh, int n)
{
}
typedef struct myiter {
SmallHashIter iter;
uintptr_t key;
void *data;
} myiter;
# ifdef GHASH_ITER
# undef GHASH_ITER
# endif
# define GHashIterator myiter
# define BLI_ghash_free(sh, a, b) free_smallhash(sh)
# define BLI_ghash_int_new_ex(a, b) new_smallhash()
# define BLI_ghash_reserve(sh, n) smallhash_reserve(sh, n)
# define BLI_ghash_new(a, b, c) new_smallhash()
# define BLI_ghash_insert(sh, key, val) BLI_smallhash_insert((sh), (uintptr_t)(key), (val))
# define BLI_ghash_remove(sh, key, a, b) BLI_smallhash_remove((sh), (uintptr_t)(key))
# define BLI_ghash_lookup(sh, key) BLI_smallhash_lookup((sh), (uintptr_t)(key))
# define BLI_ghash_lookup_p(sh, key) BLI_smallhash_lookup_p((sh), (uintptr_t)(key))
# define BLI_ghash_haskey(sh, key) BLI_smallhash_haskey((sh), (uintptr_t)(key))
# define GHASH_ITER(iter1, sh) \
for (iter1.data = BLI_smallhash_iternew(sh, &iter1.iter, &iter1.key); iter1.data; \
iter1.data = BLI_smallhash_iternext(&iter1.iter, &iter1.key))
# define BLI_ghashIterator_getKey(iter) ((void *)(iter)->key)
# define BLI_ghashIterator_getValue(iter) ((void *)(iter)->data)
# define BLI_ghash_ensure_p(sh, key, val) BLI_smallhash_ensure_p(sh, (uintptr_t)(key), val)
# define BLI_ghash_reinsert(sh, key, val, a, b) BLI_smallhash_reinsert(sh, (uintptr_t)(key), val)
# define BLI_ghash_len(sh) (int)sh->nentries
# define GHash SmallHash
# ifdef BM_ELEM_FROM_ID
# undef BM_ELEM_FROM_ID
# endif
# define BM_ELEM_FROM_ID(bm, id) bm->idmap.map[id]
#endif
//#define DEBUG_LOG_REFCOUNTNG
//#define PRINT_LOG_REF_COUNTING
@ -2406,6 +2467,40 @@ void BM_log_face_modified(BMLog *log, BMFace *f)
bm_log_face_customdata(log->bm, log, f, lf);
}
bool BM_log_has_vert(BMLog *log, BMVert *v)
{
int id = BM_ELEM_GET_ID(log->bm, v);
bool ret = BLI_ghash_haskey(log->current_entry->added_verts, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_verts, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->modified_verts, POINTER_FROM_INT(id));
return ret;
}
bool BM_log_has_edge(BMLog *log, BMEdge *e)
{
int id = BM_ELEM_GET_ID(log->bm, e);
bool ret = BLI_ghash_haskey(log->current_entry->added_edges, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_edges, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->modified_edges, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_edges_post, POINTER_FROM_INT(id));
return ret;
}
bool BM_log_has_face(BMLog *log, BMFace *f)
{
int id = BM_ELEM_GET_ID(log->bm, f);
bool ret = BLI_ghash_haskey(log->current_entry->added_faces, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->deleted_faces, POINTER_FROM_INT(id));
ret = ret || BLI_ghash_haskey(log->current_entry->modified_faces, POINTER_FROM_INT(id));
return ret;
}
/* Log a new face as added to the BMesh
*
* The new face gets a unique ID assigned. It is then added to a map
@ -2875,7 +2970,7 @@ void bm_log_print(const BMLog *log, const char *description)
}
#endif
static int bmlog_entry_memsize(BMLogEntry *entry)
ATTR_NO_OPT static int bmlog_entry_memsize(BMLogEntry *entry)
{
int ret = 0;
@ -2888,6 +2983,11 @@ static int bmlog_entry_memsize(BMLogEntry *entry)
ret += entry->ldata.pool ? (int)BLI_mempool_get_size(entry->ldata.pool) : 0;
ret += entry->pdata.pool ? (int)BLI_mempool_get_size(entry->pdata.pool) : 0;
ret += BLI_memarena_size(entry->arena);
if (BLI_memarena_size(entry->arena)) {
printf("%d\n", BLI_memarena_size(entry->arena));
}
// estimate ghash memory usage
ret += (int)BLI_ghash_len(entry->added_verts) * (int)sizeof(void *) * 4;
ret += (int)BLI_ghash_len(entry->added_edges) * (int)sizeof(void *) * 4;

View File

@ -156,3 +156,7 @@ void BM_log_undo_skip(BMesh *bm, BMLog *log);
BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, float t);
int BM_log_entry_size(BMLogEntry *entry);
bool BM_log_has_vert(BMLog *log, BMVert *v);
bool BM_log_has_edge(BMLog *log, BMEdge *e);
bool BM_log_has_face(BMLog *log, BMFace *f);

View File

@ -1642,6 +1642,8 @@ void BM_mesh_rebuild(BMesh *bm,
BLI_mempool_destroy(bm->fpool);
bm->fpool = fpool_dst;
}
bm_rebuild_idmap(bm);
}
/**

View File

@ -1058,6 +1058,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
},
/* slots_out */
{{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
{"side_geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
{{'\0'}},
},
bmo_extrude_face_region_exec,
@ -2111,89 +2112,87 @@ static BMOpDefine bmo_symmetrize_def = {
#undef BM_EDGE
#undef BM_VERT
const BMOpDefine *bmo_opdefines[] = {
&bmo_average_vert_facedata_def,
&bmo_beautify_fill_def,
&bmo_bevel_def,
&bmo_bisect_edges_def,
&bmo_bmesh_to_mesh_def,
&bmo_bridge_loops_def,
&bmo_collapse_def,
&bmo_collapse_uvs_def,
&bmo_connect_verts_def,
&bmo_connect_verts_concave_def,
&bmo_connect_verts_nonplanar_def,
&bmo_connect_vert_pair_def,
&bmo_contextual_create_def,
const BMOpDefine *bmo_opdefines[] = {&bmo_average_vert_facedata_def,
&bmo_beautify_fill_def,
&bmo_bevel_def,
&bmo_bisect_edges_def,
&bmo_bmesh_to_mesh_def,
&bmo_bridge_loops_def,
&bmo_collapse_def,
&bmo_collapse_uvs_def,
&bmo_connect_verts_def,
&bmo_connect_verts_concave_def,
&bmo_connect_verts_nonplanar_def,
&bmo_connect_vert_pair_def,
&bmo_contextual_create_def,
#ifdef WITH_BULLET
&bmo_convex_hull_def,
&bmo_convex_hull_def,
#endif
&bmo_create_circle_def,
&bmo_create_cone_def,
&bmo_create_cube_def,
&bmo_create_grid_def,
&bmo_create_icosphere_def,
&bmo_create_monkey_def,
&bmo_create_uvsphere_def,
&bmo_create_vert_def,
&bmo_delete_def,
&bmo_dissolve_edges_def,
&bmo_dissolve_faces_def,
&bmo_dissolve_verts_def,
&bmo_dissolve_limit_def,
&bmo_dissolve_degenerate_def,
&bmo_duplicate_def,
&bmo_holes_fill_def,
&bmo_face_attribute_fill_def,
&bmo_offset_edgeloops_def,
&bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
&bmo_extrude_discrete_faces_def,
&bmo_extrude_edge_only_def,
&bmo_extrude_face_region_def,
&bmo_extrude_vert_indiv_def,
&bmo_find_doubles_def,
&bmo_grid_fill_def,
&bmo_inset_individual_def,
&bmo_inset_region_def,
&bmo_join_triangles_def,
&bmo_mesh_to_bmesh_def,
&bmo_mirror_def,
&bmo_object_load_bmesh_def,
&bmo_pointmerge_def,
&bmo_pointmerge_facedata_def,
&bmo_poke_def,
&bmo_recalc_face_normals_def,
&bmo_planar_faces_def,
&bmo_region_extend_def,
&bmo_remove_doubles_def,
&bmo_reverse_colors_def,
&bmo_reverse_faces_def,
&bmo_reverse_uvs_def,
&bmo_rotate_colors_def,
&bmo_rotate_def,
&bmo_rotate_edges_def,
&bmo_rotate_uvs_def,
&bmo_scale_def,
&bmo_smooth_vert_def,
&bmo_smooth_laplacian_vert_def,
&bmo_solidify_def,
&bmo_spin_def,
&bmo_split_def,
&bmo_split_edges_def,
&bmo_subdivide_edges_def,
&bmo_subdivide_edgering_def,
&bmo_bisect_plane_def,
&bmo_symmetrize_def,
&bmo_transform_def,
&bmo_translate_def,
&bmo_triangle_fill_def,
&bmo_triangulate_def,
&bmo_unsubdivide_def,
&bmo_weld_verts_def,
&bmo_wireframe_def,
&bmo_test_mres_smooth_def
};
&bmo_create_circle_def,
&bmo_create_cone_def,
&bmo_create_cube_def,
&bmo_create_grid_def,
&bmo_create_icosphere_def,
&bmo_create_monkey_def,
&bmo_create_uvsphere_def,
&bmo_create_vert_def,
&bmo_delete_def,
&bmo_dissolve_edges_def,
&bmo_dissolve_faces_def,
&bmo_dissolve_verts_def,
&bmo_dissolve_limit_def,
&bmo_dissolve_degenerate_def,
&bmo_duplicate_def,
&bmo_holes_fill_def,
&bmo_face_attribute_fill_def,
&bmo_offset_edgeloops_def,
&bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
&bmo_extrude_discrete_faces_def,
&bmo_extrude_edge_only_def,
&bmo_extrude_face_region_def,
&bmo_extrude_vert_indiv_def,
&bmo_find_doubles_def,
&bmo_grid_fill_def,
&bmo_inset_individual_def,
&bmo_inset_region_def,
&bmo_join_triangles_def,
&bmo_mesh_to_bmesh_def,
&bmo_mirror_def,
&bmo_object_load_bmesh_def,
&bmo_pointmerge_def,
&bmo_pointmerge_facedata_def,
&bmo_poke_def,
&bmo_recalc_face_normals_def,
&bmo_planar_faces_def,
&bmo_region_extend_def,
&bmo_remove_doubles_def,
&bmo_reverse_colors_def,
&bmo_reverse_faces_def,
&bmo_reverse_uvs_def,
&bmo_rotate_colors_def,
&bmo_rotate_def,
&bmo_rotate_edges_def,
&bmo_rotate_uvs_def,
&bmo_scale_def,
&bmo_smooth_vert_def,
&bmo_smooth_laplacian_vert_def,
&bmo_solidify_def,
&bmo_spin_def,
&bmo_split_def,
&bmo_split_edges_def,
&bmo_subdivide_edges_def,
&bmo_subdivide_edgering_def,
&bmo_bisect_plane_def,
&bmo_symmetrize_def,
&bmo_transform_def,
&bmo_translate_def,
&bmo_triangle_fill_def,
&bmo_triangulate_def,
&bmo_unsubdivide_def,
&bmo_weld_verts_def,
&bmo_wireframe_def,
&bmo_test_mres_smooth_def};
const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines);

View File

@ -52,6 +52,7 @@ int bmesh_elem_check(void *element, const char htype);
int bmesh_radial_length(const BMLoop *l);
int bmesh_disk_count_at_most(const BMVert *v, const int count_max);
int bmesh_disk_count(const BMVert *v);
void bm_rebuild_idmap(BMesh *bm);
/**
* Internal BMHeader.api_flag

View File

@ -35,12 +35,7 @@
#define USE_EDGE_REGION_FLAGS
enum {
EXT_INPUT = 1,
EXT_KEEP = 2,
EXT_DEL = 4,
EXT_TAG = 8,
};
enum { EXT_INPUT = 1, EXT_KEEP = 2, EXT_DEL = 4, EXT_TAG = 8, EXT_ALT = 16 };
#define VERT_MARK 1
#define EDGE_MARK 1
@ -332,13 +327,17 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BMFace *f;
bool found, delorig = false;
BMOpSlot *slot_facemap_out;
BMOpSlot *slot_sidemap_out;
BMOpSlot *slot_edges_exclude;
const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in,
"use_normal_from_adjacent");
const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in,
"use_dissolve_ortho_edges");
bool side_tag = EXT_ALT;
/* initialize our sub-operators */
BMO_op_initf(bm,
&dupeop,
@ -552,29 +551,37 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
char e_hflag[2];
bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag);
f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP);
if (e_hflag_ok) {
BM_elem_flag_enable(f_edges[1], e_hflag[0]);
BM_elem_flag_disable(f_edges[1], e_hflag[1]);
}
}
BMO_elem_flag_set(bm, f_edges[1], side_tag, true);
f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]);
if (f_edges[3] == NULL) {
char e_hflag[2];
bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag);
f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP);
if (e_hflag_ok) {
BM_elem_flag_enable(f_edges[3], e_hflag[0]);
BM_elem_flag_disable(f_edges[3], e_hflag[1]);
}
}
BMO_elem_flag_set(bm, f_edges[3], side_tag, true);
f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP);
#else
f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
#endif
bm_extrude_copy_face_loop_attributes(bm, f);
BMO_elem_flag_set(bm, (BMElem *)f, side_tag, true);
if (join_face) {
BMVert *v1 = e->v1;
BMVert *v2 = e->v2;
@ -605,7 +612,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
}
BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_set(bm, BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE), side_tag, true);
}
if (dissolve_verts) {
@ -626,6 +633,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
MEM_freeN(dissolve_verts);
}
BMO_slot_buffer_from_enabled_flag(
bm, op, op->slots_out, "side_geom.out", BM_FACE | BM_EDGE, side_tag);
/* cleanup */
if (delorig) {
BMO_op_finish(bm, &delop);

View File

@ -8460,7 +8460,7 @@ typedef struct DynTopoAutomaskState {
bool free_automasking;
} DynTopoAutomaskState;
static float sculpt_topology_automasking_cb(SculptVertRef vertex, void *vdata)
ATTR_NO_OPT static float sculpt_topology_automasking_cb(SculptVertRef vertex, void *vdata)
{
DynTopoAutomaskState *state = (DynTopoAutomaskState *)vdata;
float mask = SCULPT_automasking_factor_get(state->cache, state->ss, vertex);
@ -8469,7 +8469,7 @@ static float sculpt_topology_automasking_cb(SculptVertRef vertex, void *vdata)
return mask * mask2;
}
static float sculpt_topology_automasking_mask_cb(SculptVertRef vertex, void *vdata)
ATTR_NO_OPT static float sculpt_topology_automasking_mask_cb(SculptVertRef vertex, void *vdata)
{
DynTopoAutomaskState *state = (DynTopoAutomaskState *)vdata;
return 1.0f - SCULPT_vertex_mask_get(state->ss, vertex);
@ -8614,7 +8614,8 @@ static void sculpt_topology_update(Sculpt *sd,
symidx,
DYNTOPO_HAS_DYNAMIC_SPLIT(brush->sculpt_tool),
mask_cb,
mask_cb_data);
mask_cb_data,
SCULPT_get_int(ss, dyntopo_disable_smooth, sd, brush));
SCULPT_dyntopo_automasking_end(mask_cb_data);

View File

@ -30,6 +30,7 @@
#include "DNA_mesh_types.h"
#include "BKE_brush_engine.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
@ -72,8 +73,10 @@ static bool sculpt_and_constant_or_manual_detail_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
return SCULPT_mode_poll(C) && ob->sculpt->bm &&
(sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL));
/*checking for constant/manual mode isn't necassary since we do this on the python side
in the ui scripts*/
return SCULPT_mode_poll(C) && ob->sculpt->bm; /*&&
(sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL));*/
}
static bool sculpt_and_dynamic_topology_poll(bContext *C)
@ -87,6 +90,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
float size;
float bb_min[3], bb_max[3], center[3], dim[3];
@ -109,9 +114,17 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
sub_v3_v3v3(dim, bb_max, bb_min);
size = max_fff(dim[0], dim[1], dim[2]);
float constant_detail = BRUSHSET_GET_FINAL_FLOAT(
brush ? brush->channels : NULL, sd->channels, dyntopo_constant_detail, NULL);
float detail_range = BRUSHSET_GET_FINAL_FLOAT(
brush ? brush->channels : NULL, sd->channels, dyntopo_detail_range, NULL);
/* Update topology size. */
float object_space_constant_detail = 1.0f / (sd->constant_detail * mat4_to_scale(ob->obmat));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail, sd->detail_range);
float object_space_constant_detail = 1.0f / (constant_detail * mat4_to_scale(ob->obmat));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail, detail_range);
bool enable_surface_relax = BRUSHSET_GET_FINAL_INT(
brush ? brush->channels : NULL, sd->channels, dyntopo_disable_smooth, NULL);
SCULPT_undo_push_begin(ob, "Dynamic topology flood fill");
SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_COORDS);
@ -140,7 +153,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
false,
mask_cb,
mask_cb_data,
max_dyntopo_steps_coll);
max_dyntopo_steps_coll,
enable_surface_relax);
for (int j = 0; j < totnodes; j++) {
BKE_pbvh_node_mark_topology_update(nodes[j]);
@ -157,7 +171,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
false,
mask_cb,
mask_cb_data,
max_dyntopo_steps_subd);
max_dyntopo_steps_subd,
enable_surface_relax);
for (int j = 0; j < totnodes; j++) {
BKE_pbvh_node_mark_topology_update(nodes[j]);
}
@ -184,7 +199,8 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
false,
mask_cb,
mask_cb_data,
max_dyntopo_steps_coll);
max_dyntopo_steps_coll,
enable_surface_relax);
}
SCULPT_dyntopo_automasking_end(mask_cb_data);

File diff suppressed because it is too large Load Diff

View File

@ -622,6 +622,10 @@ static void update_unode_bmesh_memsize(SculptUndoNode *unode)
// update memory size
UndoSculpt *usculpt = sculpt_undo_get_nodes();
if (!usculpt) {
return;
}
// subtract old size
if (usculpt->undo_size >= unode->undo_size) {
usculpt->undo_size -= unode->undo_size;
@ -1932,6 +1936,10 @@ bool SCULPT_ensure_dyntopo_node_undo(Object *ob,
return SCULPT_ensure_dyntopo_node_undo(ob, node, type, extraType);
}
if (!node) {
return;
}
int n = BKE_pbvh_get_node_id(ss->pbvh, node);
if (unode->nodemap_size <= n) {

View File

@ -2572,6 +2572,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, brush_curve_preset_items);
RNA_def_property_ui_text(prop, "Curve Preset", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "deform_target", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_deformation_target_items);
@ -2678,6 +2679,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, falloff_shape_unit_items);
RNA_def_property_ui_text(prop, "Falloff Shape", "Use projected or spherical falloff");
RNA_def_property_update(prop, 0, "rna_Brush_update");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
/* number values */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
@ -3695,6 +3697,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_ui_text(prop, "Curve", "Editable falloff curve");
RNA_def_property_update(prop, 0, "rna_Brush_update");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "pressure_size_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);