Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c225
1 files changed, 152 insertions, 73 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 67cd6e433c3..8df3d4e9f90 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -56,7 +56,6 @@
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
@@ -72,6 +71,8 @@
#include "BKE_subsurf.h"
#include "BKE_colortools.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -499,8 +500,7 @@ bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
return 1;
}
-void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
- RegionView3D *rv3d, Object *ob)
+void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
{
PBVH *pbvh = ob->sculpt->pbvh;
/* copy here, original will be used below */
@@ -508,7 +508,7 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
sculpt_extend_redraw_rect_previous(ob, &rect);
- paint_calc_redraw_planes(planes, ar, rv3d, ob, &rect);
+ paint_calc_redraw_planes(planes, ar, ob, &rect);
/* we will draw this rect, so now we can set it as the previous partial rect.
* Note that we don't update with the union of previous/current (rect), only with
@@ -2098,6 +2098,10 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
+ /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ * initialize before threads so they can do curve mapping */
+ curvemapping_initialize(brush->curve);
+
/* threaded loop over nodes */
SculptThreadedTaskData data = {
.sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
@@ -4078,8 +4082,9 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
int sculpt_mode_poll(bContext *C)
{
+ const WorkSpace *workspace = CTX_wm_workspace(C);
Object *ob = CTX_data_active_object(C);
- return ob && ob->mode & OB_MODE_SCULPT;
+ return ob && workspace->object_mode & OB_MODE_SCULPT;
}
int sculpt_mode_poll_view3d(bContext *C)
@@ -4596,10 +4601,12 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const B
SculptSession *ss = ob->sculpt;
if (ss->kb || ss->modifiers_active) {
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
Scene *scene = CTX_data_scene(C);
Sculpt *sd = scene->toolsettings->sculpt;
bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
- BKE_sculpt_update_mesh_elements(scene, sd, ob, need_pmap, false);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, need_pmap, false);
}
}
@@ -4684,7 +4691,7 @@ static float sculpt_raycast_init(
RegionView3D *rv3d = vc->ar->regiondata;
/* TODO: what if the segment is totally clipped? (return == 0) */
- ED_view3d_win_to_segment(vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
+ ED_view3d_win_to_segment(vc->depsgraph, vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
invert_m4_m4(obimat, ob->obmat);
mul_m4_v3(obimat, ray_start);
@@ -4805,12 +4812,15 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ EvaluationContext eval_ctx;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
int mode = RNA_enum_get(op->ptr, "mode");
bool is_smooth;
bool need_mask = false;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
need_mask = true;
}
@@ -4819,7 +4829,7 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
sculpt_brush_init_tex(scene, sd, ss);
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
- BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, is_smooth, need_mask);
return 1;
}
@@ -4863,7 +4873,7 @@ static void sculpt_flush_update(bContext *C)
GPU_drawobject_free(ob->derivedFinal);
if (ss->kb || ss->modifiers_active) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ED_region_tag_redraw(ar);
}
else {
@@ -4893,6 +4903,9 @@ static void sculpt_flush_update(bContext *C)
ED_region_tag_redraw_partial(ar, &r);
}
}
+
+ /* 2.8x - avoid full mesh update! */
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
}
/* Returns whether the mouse/stylus is over the mesh (1)
@@ -4976,7 +4989,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
* Could be optimized later, but currently don't think it's so
* much common scenario.
*
- * Same applies to the DAG_id_tag_update() invoked from
+ * Same applies to the DEG_id_tag_update() invoked from
* sculpt_flush_update().
*/
if (ss->modifiers_active) {
@@ -5034,7 +5047,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_cache_free(ss->cache);
ss->cache = NULL;
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
@@ -5050,7 +5063,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
/* try to avoid calling this, only for e.g. linked duplicates now */
if (((Mesh *)ob->data)->id.us > 1)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
@@ -5206,7 +5219,7 @@ void sculpt_pbvh_clear(Object *ob)
BKE_pbvh_free(ss->pbvh);
ss->pbvh = NULL;
if (dm)
- dm->getPBVH(NULL, dm);
+ dm->getPBVH(NULL, dm, OB_MODE_OBJECT);
BKE_object_free_derived_caches(ob);
}
@@ -5242,21 +5255,21 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
}
-void sculpt_update_after_dynamic_topology_toggle(bContext *C)
+void sculpt_update_after_dynamic_topology_toggle(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
Sculpt *sd = scene->toolsettings->sculpt;
/* Create the PBVH */
- BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, sd, ob, false, false);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
-void sculpt_dynamic_topology_enable(bContext *C)
+void sculpt_dynamic_topology_enable_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
@@ -5292,17 +5305,17 @@ void sculpt_dynamic_topology_enable(bContext *C)
ss->bm_log = BM_log_create(ss->bm);
/* Refresh */
- sculpt_update_after_dynamic_topology_toggle(C);
+ sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob);
}
/* Free the sculpt BMesh and BMLog
*
* If 'unode' is given, the BMesh's data is copied out to the unode
* before the BMesh is deleted so that it can be restored from */
-void sculpt_dynamic_topology_disable(bContext *C,
- SculptUndoNode *unode)
+void sculpt_dynamic_topology_disable_ex(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob, SculptUndoNode *unode)
{
- Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
@@ -5351,28 +5364,59 @@ void sculpt_dynamic_topology_disable(bContext *C,
}
/* Refresh */
- sculpt_update_after_dynamic_topology_toggle(C);
+ sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob);
+}
+
+void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ sculpt_dynamic_topology_disable_ex(&eval_ctx, scene, ob, unode);
+}
+
+static void sculpt_dynamic_topology_disable_with_undo(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm) {
+ sculpt_undo_push_begin("Dynamic topology disable");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+ sculpt_dynamic_topology_disable_ex(eval_ctx, scene, ob, NULL);
+ sculpt_undo_push_end();
+ }
}
+static void sculpt_dynamic_topology_enable_with_undo(
+ const EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ if (ss->bm == NULL) {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable_ex(eval_ctx, scene, ob);
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ sculpt_undo_push_end();
+ }
+}
static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
WM_cursor_wait(1);
if (ss->bm) {
- sculpt_undo_push_begin("Dynamic topology disable");
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
- sculpt_dynamic_topology_disable(C, NULL);
+ sculpt_dynamic_topology_disable_with_undo(&eval_ctx, scene, ob);
}
else {
- sculpt_undo_push_begin("Dynamic topology enable");
- sculpt_dynamic_topology_enable(C);
- sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ sculpt_dynamic_topology_enable_with_undo(&eval_ctx, scene, ob);
}
- sculpt_undo_push_end(C);
WM_cursor_wait(0);
@@ -5560,7 +5604,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
/* Finish undo */
BM_log_all_added(ss->bm, ss->bm_log);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
/* Redraw */
sculpt_pbvh_clear(ob);
@@ -5583,28 +5627,81 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
/**** Toggle operator for turning sculpt mode on or off ****/
-static void sculpt_init_session(Scene *scene, Object *ob)
+static void sculpt_init_session(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
/* Create persistent sculpt mode data */
BKE_sculpt_toolsettings_data_ensure(scene);
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false);
+ ob->sculpt->mode_type = OB_MODE_SCULPT;
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
}
+void ED_object_sculptmode_exit_ex(
+ const EvaluationContext *eval_ctx,
+ WorkSpace *workspace, Scene *scene, Object *ob)
+{
+ const int mode_flag = OB_MODE_SCULPT;
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ if (mmd) {
+ multires_force_update(ob);
+ }
+
+ /* Always for now, so leaving sculpt mode always ensures scene is in
+ * a consistent state.
+ */
+ if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ /* Dynamic topology must be disabled before exiting sculpt
+ * mode to ensure the undo stack stays in a consistent
+ * state */
+ sculpt_dynamic_topology_disable_with_undo(eval_ctx, scene, ob);
+
+ /* store so we know to re-enable when entering sculpt mode */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+ }
+
+ /* Leave sculptmode */
+ workspace->object_mode &= ~mode_flag;
+
+ BKE_sculptsession_free(ob);
+
+ paint_cursor_delete_textures();
+
+ /* VBO no longer valid */
+ if (ob->derivedFinal) {
+ GPU_drawobject_free(ob->derivedFinal);
+ }
+}
+
+void ED_object_sculptmode_exit(bContext *C)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob);
+}
static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
{
+ WorkSpace *workspace = CTX_wm_workspace(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_SCULPT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ const bool is_mode_set = (workspace->object_mode & mode_flag) != 0;
Mesh *me;
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
int flush_recalc = 0;
if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ if (!ED_object_mode_compat_set(C, workspace, mode_flag, op->reports)) {
return OPERATOR_CANCELLED;
}
}
@@ -5617,45 +5714,25 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
flush_recalc |= sculpt_has_active_modifiers(scene, ob);
if (is_mode_set) {
- if (mmd)
- multires_force_update(ob);
-
- /* Always for now, so leaving sculpt mode always ensures scene is in
- * a consistent state.
- */
- if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
- /* Dynamic topology must be disabled before exiting sculpt
- * 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 */
- ob->mode &= ~mode_flag;
-
- BKE_sculptsession_free(ob);
-
- paint_cursor_delete_textures();
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob);
}
else {
/* Enter sculptmode */
- ob->mode |= mode_flag;
+ workspace->object_mode |= mode_flag;
if (flush_recalc)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* Create sculpt mode session data */
- if (ob->sculpt)
+ if (ob->sculpt) {
BKE_sculptsession_free(ob);
+ }
- sculpt_init_session(scene, ob);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+ sculpt_init_session(&eval_ctx, scene, ob);
/* Mask layer is required */
if (mmd) {
@@ -5712,7 +5789,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
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_dynamic_topology_enable_ex(&eval_ctx, scene, ob);
sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
}
else {
@@ -5722,10 +5799,12 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
}
}
- }
- if (ob->derivedFinal) /* VBO no longer valid */
- GPU_drawobject_free(ob->derivedFinal);
+ /* VBO no longer valid */
+ if (ob->derivedFinal) {
+ GPU_drawobject_free(ob->derivedFinal);
+ }
+ }
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -5795,7 +5874,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
}
MEM_freeN(nodes);
- sculpt_undo_push_end(C);
+ sculpt_undo_push_end();
/* force rebuild of pbvh for better BB placement */
sculpt_pbvh_clear(ob);