Sculpt: enable dyntopo on paint brushes
* Paint brushes will now support dyntopo if "dyntopo disabled" (the one in their brush settings, not the global setting in the "Dynamic Topology" panel) is unchecked. * Fixed dyntopo undo not properly handling pushing more then one undo type.
This commit is contained in:
parent
cbaa9f723b
commit
7293c2b5e5
|
@ -364,6 +364,7 @@ void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData
|
|||
void BKE_brush_check_toolsettings(struct Sculpt *sd);
|
||||
void BKE_brush_channelset_ui_init(struct Brush *brush, int tool);
|
||||
void BKE_brush_channelset_check_radius(BrushChannelSet *chset);
|
||||
void BKE_builtin_apply_hard_edge_mode(BrushChannelSet *chset, bool do_apply);
|
||||
|
||||
const char *BKE_brush_channel_category_get(BrushChannel *ch);
|
||||
void BKE_brush_channel_category_set(BrushChannel *ch, const char *str);
|
||||
|
|
|
@ -1450,6 +1450,31 @@ void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chset)
|
|||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static void commandlist_add_dyntopo(BrushChannelSet *chset,
|
||||
BrushCommandList *cl,
|
||||
Brush *brush,
|
||||
int tool,
|
||||
bool hard_edge_mode,
|
||||
float radius_base)
|
||||
{
|
||||
|
||||
if (!BKE_brush_channelset_get_int(chset, "dyntopo_disabled", NULL)) {
|
||||
BrushCommand *cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true),
|
||||
SCULPT_TOOL_DYNTOPO);
|
||||
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
|
||||
|
||||
float spacing = BKE_brush_channelset_get_float(chset, "dyntopo_spacing", NULL);
|
||||
float radius2 = BKE_brush_channelset_get_float(chset, "dyntopo_radius_scale", NULL);
|
||||
|
||||
radius2 *= radius_base;
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, spacing, spacing);
|
||||
float_set_uninherit(cmd->params, radius, radius2);
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
}
|
||||
}
|
||||
static void bke_builtin_commandlist_create_paint(Brush *brush,
|
||||
BrushChannelSet *chset,
|
||||
BrushCommandList *cl,
|
||||
|
@ -1460,6 +1485,7 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
|
||||
cmd = BKE_brush_commandlist_add(cl, chset, true);
|
||||
BKE_brush_command_init(cmd, tool);
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
|
||||
float radius = BRUSHSET_GET_FLOAT(chset, radius, NULL);
|
||||
|
||||
|
@ -1496,6 +1522,8 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
float_set_uninherit(cmd->params, radius, radius * autosmooth_scale);
|
||||
float_set_uninherit(cmd->params, projection, autosmooth_projection);
|
||||
float_set_uninherit(cmd->params, spacing, autosmooth_spacing);
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
}
|
||||
|
||||
float vcol_boundary = BKE_brush_channelset_get_float(chset, "vcol_boundary_factor", NULL);
|
||||
|
@ -1508,11 +1536,15 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
|
|||
float_set_uninherit(cmd->params, radius, radius * GETF("vcol_boundary_radius_scale"));
|
||||
float_set_uninherit(cmd->params, spacing, GETF("vcol_boundary_spacing"));
|
||||
float_set_uninherit(cmd->params, strength, vcol_boundary);
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
}
|
||||
|
||||
#undef GETF
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
bool hard_edge_mode = BRUSHSET_GET_INT(chset, hard_edge_mode, NULL);
|
||||
commandlist_add_dyntopo(chset, cl, brush, tool, hard_edge_mode, radius);
|
||||
|
||||
// float
|
||||
}
|
||||
|
||||
|
@ -1567,6 +1599,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
cmd = BKE_brush_commandlist_add(cl, chset, true);
|
||||
BKE_brush_command_init(cmd, tool);
|
||||
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
|
||||
float radius = BKE_brush_channelset_get_float(chset, "radius", NULL);
|
||||
|
||||
|
@ -1603,6 +1636,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
if (!no_autosmooth && autosmooth > 0.0f) {
|
||||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true), SCULPT_TOOL_SMOOTH);
|
||||
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
|
||||
BrushChannel *ch = BRUSHSET_ENSURE_BUILTIN(cmd->params, falloff_curve);
|
||||
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, autosmooth_falloff_curve);
|
||||
|
@ -1667,25 +1701,12 @@ void BKE_builtin_commandlist_create(Brush *brush,
|
|||
float_set_uninherit(cmd->params, radius, radius * topology_rake_scale);
|
||||
float_set_uninherit(cmd->params, projection, topology_rake_projection);
|
||||
float_set_uninherit(cmd->params, spacing, topology_rake_spacing);
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
}
|
||||
|
||||
/* build dyntopo command */
|
||||
|
||||
if (!BKE_brush_channelset_get_int(chset, "dyntopo_disabled", NULL)) {
|
||||
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true), SCULPT_TOOL_DYNTOPO);
|
||||
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
|
||||
|
||||
float spacing = BKE_brush_channelset_get_float(chset, "dyntopo_spacing", NULL);
|
||||
float radius2 = BKE_brush_channelset_get_float(chset, "dyntopo_radius_scale", NULL);
|
||||
|
||||
radius2 *= radius;
|
||||
|
||||
int_set_uninherit(cmd->params, use_ctrl_invert, false);
|
||||
float_set_uninherit(cmd->params, spacing, spacing);
|
||||
float_set_uninherit(cmd->params, radius, radius2);
|
||||
}
|
||||
|
||||
BKE_brush_commandset_inherit_all_mappings(cmd->params);
|
||||
commandlist_add_dyntopo(chset, cl, brush, tool, hard_edge_mode, radius);
|
||||
}
|
||||
|
||||
void BKE_brush_channelset_read_lib(BlendLibReader *reader, ID *id, BrushChannelSet *chset)
|
||||
|
|
|
@ -1461,6 +1461,9 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
break;
|
||||
case SCULPT_TOOL_PAINT:
|
||||
SHOWWRK(color);
|
||||
SHOWWRK(dyntopo_disabled);
|
||||
SHOWCTX(dyntopo_disabled);
|
||||
|
||||
SHOWWRK(secondary_color);
|
||||
SHOWWRK(wet_mix);
|
||||
SHOWWRK(wet_persistence);
|
||||
|
@ -1614,6 +1617,7 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
|
|||
GETCH(slide_deform_type)->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
|
||||
break;
|
||||
case SCULPT_TOOL_PAINT:
|
||||
BRUSHSET_SET_BOOL(chset, dyntopo_disabled, true);
|
||||
BRUSHSET_SET_FLOAT(chset, hardness, 0.4f);
|
||||
BRUSHSET_SET_FLOAT(chset, spacing, 10.0f);
|
||||
BRUSHSET_SET_FLOAT(chset, strength, 0.6f);
|
||||
|
|
|
@ -1842,6 +1842,11 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
if (brush->channels && brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
|
||||
BKE_brush_channelset_ui_init(brush, brush->sculpt_tool);
|
||||
}
|
||||
else if (brush->channels &&
|
||||
ELEM(brush->sculpt_plane, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) {
|
||||
BKE_brush_channelset_ui_init(brush, brush->sculpt_tool);
|
||||
BRUSHSET_SET_BOOL(brush->channels, dyntopo_disabled, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -930,8 +930,11 @@ typedef struct SculptUndoNode {
|
|||
/* Sculpt Face Sets */
|
||||
int *face_sets;
|
||||
|
||||
bool *nodemap;
|
||||
// dyntopo stuff
|
||||
|
||||
int *nodemap;
|
||||
int nodemap_size;
|
||||
int typemask;
|
||||
|
||||
size_t undo_size;
|
||||
// int gen, lasthash;
|
||||
|
|
|
@ -121,13 +121,13 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
const float bstrength = fabsf(ss->cache->bstrength);
|
||||
|
||||
PBVHVertexIter vd;
|
||||
PBVHColorBufferNode *color_buffer;
|
||||
// PBVHColorBufferNode *color_buffer;
|
||||
|
||||
SculptOrigVertData orig_data;
|
||||
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
|
||||
orig_data.datatype = SCULPT_UNDO_COLOR;
|
||||
|
||||
color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]);
|
||||
// color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
|
@ -187,16 +187,19 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
float wet_mix_color[4];
|
||||
float buffer_color[4];
|
||||
|
||||
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vd.vertex);
|
||||
float *color_buffer = mv->origcolor;
|
||||
|
||||
mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow);
|
||||
mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow);
|
||||
|
||||
/* Interpolate with the wet_mix color for wet paint mixing. */
|
||||
blend_color_interpolate_float(
|
||||
paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix);
|
||||
blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color);
|
||||
blend_color_mix_float(color_buffer, color_buffer, paint_color);
|
||||
|
||||
/* Final mix over the original color using brush alpha. */
|
||||
mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], alpha);
|
||||
mul_v4_v4fl(buffer_color, color_buffer, alpha);
|
||||
|
||||
IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend);
|
||||
|
||||
|
@ -421,7 +424,9 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
|
|||
float current_disp[3];
|
||||
float current_disp_norm[3];
|
||||
float interp_color[4];
|
||||
copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]);
|
||||
float *prev_color = (float *)SCULPT_temp_cdata_get(vd.vertex, data->scl);
|
||||
|
||||
copy_v4_v4(interp_color, prev_color);
|
||||
|
||||
switch (brush->smear_deform_type) {
|
||||
case BRUSH_SMEAR_DEFORM_DRAG:
|
||||
|
@ -442,7 +447,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
|
|||
float vertex_disp[3];
|
||||
float vertex_disp_norm[3];
|
||||
sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.vertex), vd.co);
|
||||
const float *neighbor_color = ss->cache->prev_colors[ni.index];
|
||||
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;
|
||||
|
@ -456,8 +461,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
|
|||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
|
||||
blend_color_interpolate_float(
|
||||
vd.col, ss->cache->prev_colors[vd.index], interp_color, fade * blend);
|
||||
blend_color_interpolate_float(vd.col, prev_color, interp_color, fade * blend);
|
||||
|
||||
if (vd.mvert) {
|
||||
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
|
||||
|
@ -475,7 +479,10 @@ static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
|
|||
|
||||
PBVHVertexIter vd;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.vertex));
|
||||
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));
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
}
|
||||
|
@ -489,6 +496,12 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
return;
|
||||
}
|
||||
|
||||
SculptCustomLayer prev_scl;
|
||||
SculptLayerParams params = {.permanent = false, .simple_array = false};
|
||||
SCULPT_temp_customlayer_ensure(ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "smear_previous", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "smear_previous", &prev_scl, ¶ms);
|
||||
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
@ -509,6 +522,7 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
SculptThreadedTaskData data = {
|
||||
.sd = sd,
|
||||
.ob = ob,
|
||||
.scl = &prev_scl,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
};
|
||||
|
|
|
@ -1927,17 +1927,24 @@ bool SCULPT_ensure_dyntopo_node_undo(Object *ob,
|
|||
UndoSculpt *usculpt = sculpt_undo_get_nodes();
|
||||
SculptUndoNode *unode = usculpt->nodes.first;
|
||||
|
||||
if (!unode || unode->type != type) {
|
||||
if (!unode) {
|
||||
unode = sculpt_undo_alloc_node_type(ob, type);
|
||||
|
||||
BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
|
||||
|
||||
unode->type = type;
|
||||
unode->typemask = 1 << type;
|
||||
unode->applied = true;
|
||||
unode->bm_entry = BM_log_entry_add(ss->bm, ss->bm_log);
|
||||
|
||||
return SCULPT_ensure_dyntopo_node_undo(ob, node, type, extraType);
|
||||
}
|
||||
else if (!(unode->typemask & (1 << type))) {
|
||||
unode->typemask |= 1 << type;
|
||||
|
||||
/* add a log sub-entry */
|
||||
BM_log_entry_add_ex(ss->bm, ss->bm_log, true);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
return false;
|
||||
|
@ -1946,7 +1953,8 @@ bool SCULPT_ensure_dyntopo_node_undo(Object *ob,
|
|||
int n = BKE_pbvh_get_node_id(ss->pbvh, node);
|
||||
|
||||
if (unode->nodemap_size <= n) {
|
||||
int newsize = (n + 1) * 2;
|
||||
int newsize = (n + 1);
|
||||
newsize += newsize >> 1;
|
||||
|
||||
if (!unode->nodemap) {
|
||||
unode->nodemap = MEM_callocN(sizeof(*unode->nodemap) * newsize, "unode->nodemap");
|
||||
|
@ -1958,11 +1966,11 @@ bool SCULPT_ensure_dyntopo_node_undo(Object *ob,
|
|||
unode->nodemap_size = newsize;
|
||||
}
|
||||
|
||||
if (unode->nodemap[n]) {
|
||||
if (unode->nodemap[n] & (1 << type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unode->nodemap[n] = 1;
|
||||
unode->nodemap[n] |= 1 << type;
|
||||
sculpt_undo_bmesh_push(ob, node, type);
|
||||
|
||||
if (extraType >= 0) {
|
||||
|
|
|
@ -551,8 +551,6 @@ typedef enum eBrushUVSculptTool {
|
|||
SCULPT_TOOL_BOUNDARY, \
|
||||
SCULPT_TOOL_POSE, \
|
||||
SCULPT_TOOL_DRAW_FACE_SETS, \
|
||||
SCULPT_TOOL_PAINT, \
|
||||
SCULPT_TOOL_SMEAR, \
|
||||
\
|
||||
/* These brushes could handle dynamic topology, \ \
|
||||
* but user feedback indicates it's better not to */ \
|
||||
|
|
Loading…
Reference in New Issue