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:
authorDalai Felinto <dfelinto@gmail.com>2016-10-20 19:03:44 +0300
committerDalai Felinto <dfelinto@gmail.com>2016-10-20 20:00:49 +0300
commit418b24551e1b8a4458deceedca945a631f0684ac (patch)
treecfb1f42ff1eb58e36f714132d3ed623c18bfc6f7 /source/blender/editors/sculpt_paint
parenta84794b39960029a61d7c2c79e4ad7e2fda06bb7 (diff)
parent9269574089a742130f02c0a1184a19d94f0e665d (diff)
Merge commit '9269574089a742130f02c0a1184a19d94f0e665d' into pbr-online
Merge conflicts fixes include fix on ob->reflectionplane for write and read, and a few manual fixes to account for the ID remap changes Conflicts: source/blender/blenkernel/intern/object.c source/blender/blenkernel/intern/world.c source/blender/blenloader/intern/writefile.c source/blender/editors/space_view3d/view3d_draw.c source/blender/gpu/GPU_draw.h source/blender/gpu/intern/gpu_draw.c source/blender/gpu/intern/gpu_material.c source/blender/gpu/intern/gpu_texture.c source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h4
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c240
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c49
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c138
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c4
8 files changed, 414 insertions, 47 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index a716cae56dd..941f19ca0f0 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -401,7 +401,7 @@ static void image_undo_end(void)
UndoImageTile *tmp_tile = tile->next;
deallocsize += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
MEM_freeN(tile->rect.pt);
- BLI_freelinkN (lb, tile);
+ BLI_freelinkN(lb, tile);
tile = tmp_tile;
}
else {
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d273f8320a1..6ed969cb270 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -202,7 +202,7 @@ typedef struct ProjPaintImage {
*/
typedef struct ProjStrokeHandle {
/* Support for painting from multiple views at once,
- * currently used to impliment summetry painting,
+ * currently used to impliment symmetry painting,
* we can assume at least the first is set while painting. */
struct ProjPaintState *ps_views[8];
int ps_views_tot;
@@ -717,7 +717,7 @@ static bool project_paint_PickColor(
}
/**
- * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
+ * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusion test)
* \return
* - `0`: no occlusion
* - `-1`: no occlusion but 2D intersection is true
@@ -3717,7 +3717,7 @@ static void project_paint_prepare_all_faces(
}
/* tfbase here should be non-null! */
- BLI_assert (mloopuv_base != NULL);
+ BLI_assert(mloopuv_base != NULL);
if (is_face_sel && tpage) {
ProjPaintFaceCoSS coSS;
@@ -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_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index b6a7d671882..7e05ab929ae 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -101,6 +101,10 @@ bool ED_wpaint_fill(struct VPaint *wp, struct Object *ob, float paintweight);
bool ED_vpaint_smooth(struct Object *ob);
+typedef void (*VPaintTransform_Callback)(const float col[3], const void *user_data, float r_col[3]);
+
+bool ED_vpaint_color_transform(struct Object *ob, VPaintTransform_Callback vpaint_tx_fn, const void *user_data);
+
void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_weight_paint(struct wmOperatorType *ot);
void PAINT_OT_weight_set(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index da7667c775e..bf923415f01 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -315,6 +315,241 @@ static void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \name Vertex Color Transformations
+ * \{ */
+
+struct VPaintTx_BrightContrastData {
+ /* pre-calculated */
+ float gain;
+ float offset;
+};
+
+static void vpaint_tx_brightness_contrast(const float col[3], const void *user_data, float r_col[3])
+{
+ const struct VPaintTx_BrightContrastData *data = user_data;
+
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = data->gain * col[i] + data->offset;
+ }
+}
+
+static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ float gain, offset;
+ {
+ float brightness = RNA_float_get(op->ptr, "brightness");
+ float contrast = RNA_float_get(op->ptr, "contrast");
+ brightness /= 100.0f;
+ float delta = contrast / 200.0f;
+ gain = 1.0f - delta * 2.0f;
+ /*
+ * The algorithm is by Werner D. Streidt
+ * (http://visca.com/ffactory/archives/5-99/msg00021.html)
+ * Extracted of OpenCV demhist.c
+ */
+ if (contrast > 0) {
+ gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
+ offset = gain * (brightness - delta);
+ }
+ else {
+ delta *= -1;
+ offset = gain * (brightness + delta);
+ }
+ }
+
+ const struct VPaintTx_BrightContrastData user_data = {
+ .gain = gain,
+ .offset = offset,
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Vertex Paint Bright/Contrast";
+ ot->idname = "PAINT_OT_vertex_color_brightness_contrast";
+ ot->description = "Adjust vertex color brightness/contrast";
+
+ /* api callbacks */
+ ot->exec = vertex_color_brightness_contrast_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ const float min = -100, max = +100;
+ prop = RNA_def_float(ot->srna, "brightness", 0.0f, min, max, "Brightness", "", min, max);
+ prop = RNA_def_float(ot->srna, "contrast", 0.0f, min, max, "Contrast", "", min, max);
+ RNA_def_property_ui_range(prop, min, max, 1, 1);
+}
+
+struct VPaintTx_HueSatData {
+ float hue;
+ float sat;
+ float val;
+};
+
+static void vpaint_tx_hsv(const float col[3], const void *user_data, float r_col[3])
+{
+ const struct VPaintTx_HueSatData *data = user_data;
+ float hsv[3];
+ rgb_to_hsv_v(col, hsv);
+
+ hsv[0] += (data->hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= data->sat;
+ hsv[2] *= data->val;
+
+ hsv_to_rgb_v(hsv, r_col);
+}
+
+static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ const struct VPaintTx_HueSatData user_data = {
+ .hue = RNA_float_get(op->ptr, "h"),
+ .sat = RNA_float_get(op->ptr, "s"),
+ .val = RNA_float_get(op->ptr, "v"),
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Hue Saturation Value";
+ ot->idname = "PAINT_OT_vertex_color_hsv";
+ ot->description = "Adjust vertex color HSV values";
+
+ /* api callbacks */
+ ot->exec = vertex_color_hsv_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ RNA_def_float(ot->srna, "h", 0.5f, 0.0f, 1.0f, "Hue", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "s", 1.0f, 0.0f, 2.0f, "Saturation", "", 0.0f, 2.0f);
+ RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
+}
+
+static void vpaint_tx_invert(const float col[3], const void *UNUSED(user_data), float r_col[3])
+{
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = 1.0f - col[i];
+ }
+}
+
+static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obact = CTX_data_active_object(C);
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_invert, NULL)) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Invert";
+ ot->idname = "PAINT_OT_vertex_color_invert";
+ ot->description = "Invert RGB values";
+
+ /* api callbacks */
+ ot->exec = vertex_color_invert_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+struct VPaintTx_LevelsData {
+ float gain;
+ float offset;
+};
+
+static void vpaint_tx_levels(const float col[3], const void *user_data, float r_col[3])
+{
+ const struct VPaintTx_LevelsData *data = user_data;
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = data->gain * (col[i] + data->offset);
+ }
+}
+
+static int vertex_color_levels_exec(bContext *C, wmOperator *op)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ const struct VPaintTx_LevelsData user_data = {
+ .gain = RNA_float_get(op->ptr, "gain"),
+ .offset = RNA_float_get(op->ptr, "offset"),
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void PAINT_OT_vertex_color_levels(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Levels";
+ ot->idname = "PAINT_OT_vertex_color_levels";
+ ot->description = "Adjust levels of vertex colors";
+
+ /* api callbacks */
+ ot->exec = vertex_color_levels_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ RNA_def_float(ot->srna, "offset", 0.0f, -1.0f, 1.0f, "Offset", "Value to add to colors", -1.0f, 1.0f);
+ RNA_def_float(ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply colors by", 0.0f, 10.0f);
+}
+
+/** \} */
+
+
static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = BKE_paint_get_active_from_context(C);
@@ -1112,6 +1347,11 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_vertex_color_set);
WM_operatortype_append(PAINT_OT_vertex_color_smooth);
+ WM_operatortype_append(PAINT_OT_vertex_color_brightness_contrast);
+ WM_operatortype_append(PAINT_OT_vertex_color_hsv);
+ WM_operatortype_append(PAINT_OT_vertex_color_invert);
+ WM_operatortype_append(PAINT_OT_vertex_color_levels);
+
/* face-select */
WM_operatortype_append(PAINT_OT_face_select_linked);
WM_operatortype_append(PAINT_OT_face_select_linked_pick);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 65857cccb15..aa17cb02fe5 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_basic_shader.h"
+
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -160,11 +162,11 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(3, 0xAAAA);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ GPU_basic_shader_line_width(3.0);
glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
- glLineWidth(3.0);
if (stroke->constrain_line) {
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
stroke->constrained_pos[0], stroke->constrained_pos[1]);
@@ -175,7 +177,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
}
glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
- glLineWidth(1.0);
+ GPU_basic_shader_line_width(1.0);
if (stroke->constrain_line) {
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
stroke->constrained_pos[0], stroke->constrained_pos[1]);
@@ -185,7 +187,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
x, y);
}
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -1156,7 +1158,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (event->val == KM_RELEASE) {
copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
paint_stroke_line_constrain(stroke, mouse);
- paint_stroke_line_end (C, op, stroke, mouse);
+ paint_stroke_line_end(C, op, stroke, mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 15ab4ca04a7..87855879ec5 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -502,6 +502,51 @@ bool ED_vpaint_smooth(Object *ob)
return true;
}
+/**
+ * Apply callback to each vertex of the active vertex color layer.
+ */
+bool ED_vpaint_color_transform(
+ struct Object *ob,
+ VPaintTransform_Callback vpaint_tx_fn,
+ const void *user_data)
+{
+ Mesh *me;
+ const MPoly *mp;
+
+ if (((me = BKE_mesh_from_object(ob)) == NULL) ||
+ (me->mloopcol == NULL && (make_vertexcol(ob) == false)))
+ {
+ return false;
+ }
+
+ const bool do_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ mp = me->mpoly;
+
+ for (int i = 0; i < me->totpoly; i++, mp++) {
+ MLoopCol *lcol = &me->mloopcol[mp->loopstart];
+
+ if (do_face_sel && !(mp->flag & ME_FACE_SEL)) {
+ continue;
+ }
+
+ for (int j = 0; j < mp->totloop; j++, lcol++) {
+ float col[3];
+ rgb_uchar_to_float(col, &lcol->r);
+
+ vpaint_tx_fn(col, user_data, col);
+
+ rgb_float_to_uchar(&lcol->r, col);
+ }
+ }
+
+ /* remove stale me->mcol, will be added later */
+ BKE_mesh_tessface_clear(me);
+
+ DAG_id_tag_update(&me->id, 0);
+
+ return true;
+}
+
/* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator */
#if 0
void vpaint_dogamma(Scene *scene)
@@ -1323,7 +1368,7 @@ static bool do_weight_paint_normalize_all_locked(
/**
* \note same as function above except it does a second pass without active group
- * if nomalize fails with it.
+ * if normalize fails with it.
*/
static void do_weight_paint_normalize_all_locked_try_active(
MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
@@ -1340,7 +1385,7 @@ static void do_weight_paint_normalize_all_locked_try_active(
* - With 1.0 weight painted into active:
* nonzero locked weight; first pass zeroed out unlocked weight; scale 1 down to fit.
* - With 0.0 weight painted into active:
- * no unlocked groups; first pass did nothing; increaze 0 to fit.
+ * no unlocked groups; first pass did nothing; increase 0 to fit.
*/
do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index c173156de3a..0931456058d 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,49 @@ 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) {
+ sculpt_dynamic_topology_enable(C);
+ }
+ 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;