diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint')
7 files changed, 119 insertions, 40 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index eba9448aa40..53c11e2a6a9 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1016,7 +1016,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) translation[1] = y; outline_alpha = 0.5; outline_col = brush->add_col; - final_radius = (BKE_brush_size_get(scene, brush) * zoomx) / U.pixelsize; + final_radius = (BKE_brush_size_get(scene, brush) * zoomx); /* don't calculate rake angles while a stroke is active because the rake variables are global and * we may get interference with the stroke itself. For line strokes, such interference is visible */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 689b89e7b69..bf344e1f721 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1342,7 +1342,7 @@ static int texture_paint_toggle_poll(bContext *C) Object *ob = CTX_data_active_object(C); if (ob == NULL || ob->type != OB_MESH) return 0; - if (!ob->data || ((ID *)ob->data)->lib) + if (!ob->data || ID_IS_LINKED_DATABLOCK(ob->data)) return 0; if (CTX_data_edit_object(C)) return 0; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 827f83aa425..6ed969cb270 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5858,7 +5858,9 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) Mesh *me = ob->data; bool synch_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; - BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default); + BMesh *bm = BM_mesh_create( + &bm_mesh_allocsize_default, + &((struct BMeshCreateParams){.use_toolflags = false,})); /* turn synch selection off, since we are not in edit mode we need to ensure only the uv flags are tested */ scene->toolsettings->uv_flag &= ~UV_SYNC_SELECTION; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index bf923415f01..f88b64129e7 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -69,7 +69,7 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) PaintMode mode = BKE_paintmode_get_active_from_context(C); if (br) - br = BKE_brush_copy(br); + br = BKE_brush_copy(bmain, br); else br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paint_mode(mode)); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 5a6e0fe30ea..e874a969963 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -246,7 +246,7 @@ static bool make_vertexcol(Object *ob) /* single ob */ { Mesh *me; - if ((ob->id.lib) || + if (ID_IS_LINKED_DATABLOCK(ob) || ((me = BKE_mesh_from_object(ob)) == NULL) || (me->totpoly == 0) || (me->edit_btmesh)) @@ -1840,7 +1840,7 @@ static int paint_poll_test(bContext *C) Object *ob = CTX_data_active_object(C); if (ob == NULL || ob->type != OB_MESH) return 0; - if (!ob->data || ((ID *)ob->data)->lib) + if (!ob->data || ID_IS_LINKED_DATABLOCK(ob->data)) return 0; if (CTX_data_edit_object(C)) return 0; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index c173156de3a..cc7531b9783 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5001,7 +5001,9 @@ void sculpt_dynamic_topology_enable(bContext *C) BKE_mesh_mselect_clear(me); /* Create triangles-only BMesh */ - ss->bm = BM_mesh_create(&allocsize); + ss->bm = BM_mesh_create( + &allocsize, + &((struct BMeshCreateParams){.use_toolflags = false,})); BM_mesh_bm_from_me( ss->bm, me, (&(struct BMeshFromMeshParams){ @@ -5011,7 +5013,9 @@ void sculpt_dynamic_topology_enable(bContext *C) BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK); sculpt_dyntopo_node_layers_add(ss); /* make sure the data for existing faces are initialized */ - BM_mesh_normals_update(ss->bm); + if (me->totpoly != ss->bm->totface) { + BM_mesh_normals_update(ss->bm); + } /* Enable dynamic topology */ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; @@ -5088,6 +5092,8 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(o Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; + WM_cursor_wait(1); + if (ss->bm) { sculpt_undo_push_begin("Dynamic topology disable"); sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); @@ -5100,16 +5106,24 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(o } sculpt_undo_push_end(C); + WM_cursor_wait(0); + return OPERATOR_FINISHED; } +enum eDynTopoWarnFlag { + DYNTOPO_WARN_VDATA = (1 << 0), + DYNTOPO_WARN_EDATA = (1 << 1), + DYNTOPO_WARN_LDATA = (1 << 2), + DYNTOPO_WARN_MODIFIER = (1 << 3), +}; -static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, bool vdata, bool modifiers) +static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoWarnFlag flag) { uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR); uiLayout *layout = UI_popup_menu_layout(pup); - if (vdata) { + if (flag & (DYNTOPO_WARN_VDATA | DYNTOPO_WARN_EDATA | DYNTOPO_WARN_LDATA)) { const char *msg_error = TIP_("Vertex Data Detected!"); const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata"); uiItemL(layout, msg_error, ICON_INFO); @@ -5117,7 +5131,7 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, bool vdata, bo uiItemS(layout); } - if (modifiers) { + if (flag & DYNTOPO_WARN_MODIFIER) { const char *msg_error = TIP_("Generative Modifiers Detected!"); const char *msg = TIP_("Keeping the modifiers will increase polycount when returning to object mode"); @@ -5133,33 +5147,35 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, bool vdata, bo return OPERATOR_INTERFACE; } - -static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static enum eDynTopoWarnFlag sculpt_dynamic_topology_check(bContext *C) { Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; SculptSession *ss = ob->sculpt; - if (!ss->bm) { - Scene *scene = CTX_data_scene(C); - ModifierData *md; - VirtualModifierData virtualModifierData; - int i; - bool vdata = false; - bool modifiers = false; - - for (i = 0; i < CD_NUMTYPES; i++) { - if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) && - (CustomData_has_layer(&me->vdata, i) || - CustomData_has_layer(&me->edata, i) || - CustomData_has_layer(&me->ldata, i))) - { - vdata = true; - break; + Scene *scene = CTX_data_scene(C); + enum eDynTopoWarnFlag flag = 0; + + BLI_assert(ss->bm == NULL); + UNUSED_VARS_NDEBUG(ss); + + for (int i = 0; i < CD_NUMTYPES; i++) { + if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) { + if (CustomData_has_layer(&me->vdata, i)) { + flag |= DYNTOPO_WARN_VDATA; + } + if (CustomData_has_layer(&me->edata, i)) { + flag |= DYNTOPO_WARN_EDATA; + } + if (CustomData_has_layer(&me->ldata, i)) { + flag |= DYNTOPO_WARN_LDATA; } } + } - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + { + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); /* exception for shape keys because we can edit those */ for (; md; md = md->next) { @@ -5167,14 +5183,26 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; if (mti->type == eModifierTypeType_Constructive) { - modifiers = true; + flag |= DYNTOPO_WARN_MODIFIER; break; } } + } - if (vdata || modifiers) { + return flag; +} + +static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + + if (!ss->bm) { + enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(C); + + if (flag) { /* The mesh has customdata that will be lost, let the user confirm this is OK */ - return dyntopo_warning_popup(C, op->type, vdata, modifiers); + return dyntopo_warning_popup(C, op->type, flag); } } @@ -5249,6 +5277,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE); BM_log_before_all_removed(ss->bm, ss->bm_log); + BM_mesh_toolflags_set(ss->bm, true); + /* Symmetrize and re-triangulate */ BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS, "symmetrize input=%avef direction=%i dist=%f", @@ -5258,6 +5288,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) /* bisect operator flags edges (keep tags clean for edge queue) */ BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false); + BM_mesh_toolflags_set(ss->bm, false); + /* Finish undo */ BM_log_all_added(ss->bm, ss->bm_log); sculpt_undo_push_end(C); @@ -5327,6 +5359,9 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) * mode to ensure the undo stack stays in a consistent * state */ sculpt_dynamic_topology_toggle_exec(C, NULL); + + /* store so we know to re-enable when entering sculpt mode */ + me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; } /* Leave sculptmode */ @@ -5340,12 +5375,6 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) /* Enter sculptmode */ ob->mode |= mode_flag; - /* Remove dynamic-topology flag; this will be enabled if the - * file was saved with dynamic topology on, but we don't - * automatically re-enter dynamic-topology mode when loading a - * file. */ - me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; - if (flush_recalc) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -5399,6 +5428,52 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT); paint_cursor_start(C, sculpt_poll_view3d); + + /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes, + * As long as no data was added that is not supported. */ + if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { + const char *message_unsupported = NULL; + if (me->totloop != me->totpoly * 3) { + message_unsupported = TIP_("non-triangle face"); + } + else if (mmd != NULL) { + message_unsupported = TIP_("multi-res modifier"); + } + else { + enum eDynTopoWarnFlag flag = sculpt_dynamic_topology_check(C); + if (flag == 0) { + /* pass */ + } + else if (flag & DYNTOPO_WARN_VDATA) { + message_unsupported = TIP_("vertex data"); + } + else if (flag & DYNTOPO_WARN_EDATA) { + message_unsupported = TIP_("edge data"); + } + else if (flag & DYNTOPO_WARN_LDATA) { + message_unsupported = TIP_("face data"); + } + else if (flag & DYNTOPO_WARN_MODIFIER) { + message_unsupported = TIP_("constructive modifier"); + } + else { + BLI_assert(0); + } + } + + if (message_unsupported == NULL) { + /* undo push is needed to prevent memory leak */ + sculpt_undo_push_begin("Dynamic topology enable"); + sculpt_dynamic_topology_enable(C); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); + } + else { + BKE_reportf(op->reports, RPT_WARNING, + "Dynamic Topology found: %s, disabled", + message_unsupported); + me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; + } + } } if (ob->derivedFinal) /* VBO no longer valid */ diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index ceefda99002..44bd872d107 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -366,7 +366,9 @@ static void sculpt_undo_bmesh_enable(Object *ob, sculpt_pbvh_clear(ob); /* Create empty BMesh and enable logging */ - ss->bm = BM_mesh_create(&bm_mesh_allocsize_default); + ss->bm = BM_mesh_create( + &bm_mesh_allocsize_default, + &((struct BMeshCreateParams){.use_toolflags = false,})); BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK); sculpt_dyntopo_node_layers_add(ss); me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; |