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:
authorAntonio Vazquez <blendergit@gmail.com>2020-08-18 17:13:08 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-08-18 17:13:08 +0300
commit77efb597cee8efafd9584fcd511e6111651c6512 (patch)
tree08b3ea14968cf06c06039170bce24f44d4f63706 /source/blender/editors
parentde7470645a30e7bc6db67eff64d11778fb5ee3f2 (diff)
parent872efd8d73a3820680379230d83a0aadf5fc29ca (diff)
Merge branch 'master' into greasepencil-edit-curve
Conflicts: source/blender/editors/gpencil/gpencil_edit.c
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c15
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.c4
-rw-r--r--source/blender/editors/include/ED_sculpt.h4
-rw-r--r--source/blender/editors/interface/interface.c4
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c16
-rw-r--r--source/blender/editors/object/object_bake_api.c2
-rw-r--r--source/blender/editors/object/object_constraint.c41
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/render/render_opengl.c8
-rw-r--r--source/blender/editors/scene/scene_edit.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c27
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c317
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c250
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c51
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c78
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h48
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_transform.c2
-rw-r--r--source/blender/editors/sound/sound_ops.c5
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c8
-rw-r--r--source/blender/editors/space_node/node_draw.c10
-rw-r--r--source/blender/editors/space_node/node_edit.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c12
-rw-r--r--source/blender/editors/transform/transform_convert_object.c2
30 files changed, 601 insertions, 352 deletions
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 4c10c66dfa6..2a37302872a 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -69,9 +69,9 @@ typedef struct MPathTarget {
/* ........ */
/* update scene for current frame */
-static void motionpaths_calc_update_scene(Main *bmain, struct Depsgraph *depsgraph)
+static void motionpaths_calc_update_scene(struct Depsgraph *depsgraph)
{
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
}
Depsgraph *animviz_depsgraph_build(Main *bmain,
@@ -91,11 +91,11 @@ Depsgraph *animviz_depsgraph_build(Main *bmain,
}
/* Build graph from all requested IDs. */
- DEG_graph_build_from_ids(depsgraph, bmain, scene, view_layer, ids, num_ids);
+ DEG_graph_build_from_ids(depsgraph, ids, num_ids);
MEM_freeN(ids);
/* Update once so we can access pointers of evaluated animation data. */
- motionpaths_calc_update_scene(bmain, depsgraph);
+ motionpaths_calc_update_scene(depsgraph);
return depsgraph;
}
@@ -471,7 +471,7 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
}
else {
/* Update relevant data for new frame. */
- motionpaths_calc_update_scene(bmain, depsgraph);
+ motionpaths_calc_update_scene(depsgraph);
}
/* perform baking for targets */
@@ -484,7 +484,7 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
* We always have to restore the current frame though. */
CFRA = cfra;
if (range != ANIMVIZ_CALC_RANGE_CURRENT_FRAME && restore) {
- motionpaths_calc_update_scene(bmain, depsgraph);
+ motionpaths_calc_update_scene(depsgraph);
}
if (is_active_depsgraph) {
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 82a09a63039..733d1ef8ffe 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4200,7 +4200,6 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ARegion *region = CTX_wm_region(C);
int oldframe = (int)DEG_get_ctime(depsgraph);
@@ -4226,12 +4225,12 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
- /* update frame to get the new location of objects */
- if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) {
- cfra_prv = gpf_->framenum;
- CFRA = gpf_->framenum;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
- }
+ /* update frame to get the new location of objects */
+ if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) {
+ cfra_prv = gpf_->framenum;
+ CFRA = gpf_->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ }
ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf_, gps, mode, keep_original);
@@ -4243,7 +4242,7 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
/* return frame state and DB to original state */
CFRA = oldframe;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
if (sctx != NULL) {
ED_transform_snap_object_context_destroy(sctx);
diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c
index a6088e31ff8..f4e40c2670f 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.c
+++ b/source/blender/editors/gpencil/gpencil_mesh.c
@@ -246,7 +246,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Move scene to new frame. */
CFRA = i;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
/* Loop all objects in the list. */
LISTBASE_FOREACH (GpBakeOb *, elem, &list) {
@@ -287,7 +287,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Return scene frame state and DB to original state. */
CFRA = oldframe;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
/* Remove unused materials. */
int actcol = ob_gpencil->actcol;
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index c3abde479f1..bfc46534b99 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -53,6 +53,10 @@ void ED_sculpt_undosys_type(struct UndoType *ut);
void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name);
void ED_sculpt_undo_geometry_end(struct Object *ob);
+/* Face sets. */
+int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh);
+void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id);
+
/* Undo for changes happening on a base mesh for multires sculpting.
* if there is no multires sculpt active regular undo is used. */
void ED_sculpt_undo_push_multires_mesh_begin(struct bContext *C, const char *str);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 41e7db3a38c..478ef216421 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -44,6 +44,8 @@
#include "BLI_utildefines.h"
+#include "BLO_readfile.h"
+
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -6973,6 +6975,8 @@ void UI_init_userdef(Main *bmain)
/* fix saved themes */
init_userdef_do_versions(bmain);
uiStyleInit();
+
+ BLO_sanitize_experimental_features_userpref_blend(&U);
}
void UI_reinit_font(void)
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 8eeba5007e1..34fcee779de 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -354,10 +354,6 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
if (ob->mode == OB_MODE_SCULPT) {
ED_sculpt_undo_geometry_begin(ob, "mask slice");
- /* TODO: The ideal functionality would be to preserve the current face sets and add a new one
- * for the new triangles, but this data-layer needs to be rebuild in order to make sculpt mode
- * not crash when modifying the geometry. */
- CustomData_free_layers(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly);
}
BMesh *bm;
@@ -429,14 +425,14 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
BKE_mesh_calc_normals(ob->data);
if (ob->mode == OB_MODE_SCULPT) {
- ED_sculpt_undo_geometry_end(ob);
SculptSession *ss = ob->sculpt;
- /* Rebuild a new valid Face Set layer for the object. */
- ss->face_sets = CustomData_add_layer(
- &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, mesh->totpoly);
- for (int i = 0; i < mesh->totpoly; i++) {
- ss->face_sets[i] = 1;
+ ss->face_sets = CustomData_get_layer(&((Mesh *)ob->data)->pdata, CD_SCULPT_FACE_SETS);
+ if (ss->face_sets) {
+ /* Assign a new Face Set ID to the new faces created by the slice operation. */
+ const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data);
+ ED_sculpt_face_sets_initialize_none_to_id(ob->data, next_face_set_id);
}
+ ED_sculpt_undo_geometry_end(ob);
}
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index eb8b976320f..4d55aff1d1f 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -745,7 +745,7 @@ static int bake(Render *re,
/* We build a depsgraph for the baking,
* so we don't need to change the original data to adjust visibility and modifiers. */
Depsgraph *depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
- DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+ DEG_graph_build_from_view_layer(depsgraph);
int op_result = OPERATOR_CANCELLED;
bool ok = false;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index bcb1b8afbdd..70404af6433 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -663,10 +663,13 @@ static const EnumPropertyItem constraint_owner_items[] = {
{0, NULL, 0, NULL, NULL},
};
-static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
+static bool edit_constraint_poll_generic(bContext *C,
+ StructRNA *rna_type,
+ const bool is_liboverride_allowed)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+ bConstraint *con = ptr.data;
if (!ob) {
CTX_wm_operator_poll_msg_set(C, "Context missing active object");
@@ -678,9 +681,11 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
return false;
}
- if (ID_IS_OVERRIDE_LIBRARY(ob) && ptr.data != NULL) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override");
- return (((bConstraint *)ptr.data)->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0;
+ if (ID_IS_OVERRIDE_LIBRARY(ob) && !is_liboverride_allowed) {
+ if ((con == NULL) || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override");
+ return false;
+ }
}
return true;
@@ -688,7 +693,14 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
static bool edit_constraint_poll(bContext *C)
{
- return edit_constraint_poll_generic(C, &RNA_Constraint);
+ return edit_constraint_poll_generic(C, &RNA_Constraint, false);
+}
+
+/* Used by operators performing actions allowed also on constraints from the overridden linked
+ * object (not only from added 'local' ones). */
+static bool edit_constraint_liboverride_allowed_poll(bContext *C)
+{
+ return edit_constraint_poll_generic(C, &RNA_Constraint, true);
}
static void edit_constraint_properties(wmOperatorType *ot)
@@ -864,7 +876,7 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
/* callbacks */
ot->invoke = stretchto_reset_invoke;
ot->exec = stretchto_reset_exec;
- ot->poll = edit_constraint_poll;
+ ot->poll = edit_constraint_liboverride_allowed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -919,7 +931,7 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* callbacks */
ot->invoke = limitdistance_reset_invoke;
ot->exec = limitdistance_reset_exec;
- ot->poll = edit_constraint_poll;
+ ot->poll = edit_constraint_liboverride_allowed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -997,7 +1009,7 @@ void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot)
/* callbacks */
ot->invoke = childof_set_inverse_invoke;
ot->exec = childof_set_inverse_exec;
- ot->poll = edit_constraint_poll;
+ ot->poll = edit_constraint_liboverride_allowed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1046,7 +1058,7 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
/* callbacks */
ot->invoke = childof_clear_inverse_invoke;
ot->exec = childof_clear_inverse_exec;
- ot->poll = edit_constraint_poll;
+ ot->poll = edit_constraint_liboverride_allowed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1693,8 +1705,8 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
/* callbacks */
ot->exec = pose_constraints_clear_exec;
- ot->poll =
- ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
+ ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected
+ // bones too?
}
static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1942,7 +1954,8 @@ static bool get_new_constraint_target(
/* perform some special operations on the target */
if (only_curve) {
- /* Curve-Path option must be enabled for follow-path constraints to be able to work */
+ /* Curve-Path option must be enabled for follow-path constraints to be able to work
+ */
Curve *cu = (Curve *)ob->data;
cu->flag |= CU_PATH;
}
@@ -2214,8 +2227,8 @@ void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
/* identifiers */
ot->name = "Add Constraint (with Targets)";
ot->description =
- "Add a constraint to the active object, with target (where applicable) set to the selected "
- "Objects/Bones";
+ "Add a constraint to the active object, with target (where applicable) set to the "
+ "selected Objects/Bones";
ot->idname = "OBJECT_OT_constraint_add_with_targets";
/* api callbacks */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index ceb6553bdf6..14882ab8ffc 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -107,7 +107,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
BKE_object_eval_reset(ob_eval);
if (ob->type == OB_MESH) {
- Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ Mesh *me_eval = mesh_create_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
BKE_mesh_eval_delete(me_eval);
}
else if (ob->type == OB_LATTICE) {
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index f75dd428968..52a7b92217b 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -879,7 +879,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = oglrender->scene;
int i;
@@ -929,7 +928,7 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
if (oglrender->timer) { /* exec will not have a timer */
Depsgraph *depsgraph = oglrender->depsgraph;
scene->r.cfra = oglrender->cfrao;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
}
@@ -1119,7 +1118,6 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
Scene *scene = oglrender->scene;
Depsgraph *depsgraph = oglrender->depsgraph;
@@ -1134,7 +1132,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
CFRA++;
}
while (CFRA < oglrender->nfra) {
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
CFRA++;
}
@@ -1161,7 +1159,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
WM_cursor_time(oglrender->win, scene->r.cfra);
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
if (view_context) {
if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera &&
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index fa63a890de7..d599c1cbcf0 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -119,7 +119,7 @@ void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer)
Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, layer, true);
BKE_scene_set_background(bmain, scene);
- DEG_graph_relations_update(depsgraph, bmain, scene, layer);
+ DEG_graph_relations_update(depsgraph);
DEG_on_visible_update(bmain, false);
ED_render_engine_changed(bmain, false);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 06e800433b1..dbf84cad80b 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1594,7 +1594,7 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph)
ED_clip_update_frame(bmain, scene->r.cfra);
/* this function applies the changes too */
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
}
/*
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index d4379262666..63b4516b1cc 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1762,9 +1762,6 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont
GPU_matrix_pop();
- /* This Cloth brush cursor overlay always works in cursor space. */
- paint_cursor_drawing_setup_cursor_space(pcontext);
-
GPU_matrix_pop_projection();
wmWindowViewport(pcontext->win);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index db7de01bee5..456c1f61cb1 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -407,7 +407,6 @@ typedef struct ProjPaintState {
SpinLock *tile_lock;
Mesh *me_eval;
- bool me_eval_free;
int totlooptri_eval;
int totloop_eval;
int totpoly_eval;
@@ -4033,27 +4032,14 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
CustomData_MeshMasks cddata_masks = scene_eval->customdata_mask;
cddata_masks.fmask |= CD_MASK_MTFACE;
cddata_masks.lmask |= CD_MASK_MLOOPUV;
-
- /* Workaround for subsurf selection, try the display mesh first */
- if (ps->source == PROJ_SRC_IMAGE_CAM) {
- /* using render mesh, assume only camera was rendered from */
- ps->me_eval = mesh_create_eval_final_render(depsgraph, scene_eval, ob_eval, &cddata_masks);
- ps->me_eval_free = true;
- }
- else {
- if (ps->do_face_sel) {
- cddata_masks.vmask |= CD_MASK_ORIGINDEX;
- cddata_masks.emask |= CD_MASK_ORIGINDEX;
- cddata_masks.pmask |= CD_MASK_ORIGINDEX;
- }
- ps->me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
- ps->me_eval_free = false;
+ if (ps->do_face_sel) {
+ cddata_masks.vmask |= CD_MASK_ORIGINDEX;
+ cddata_masks.emask |= CD_MASK_ORIGINDEX;
+ cddata_masks.pmask |= CD_MASK_ORIGINDEX;
}
+ ps->me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
- if (ps->me_eval_free) {
- BKE_id_free(NULL, ps->me_eval);
- }
ps->me_eval = NULL;
return false;
}
@@ -4636,9 +4622,6 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->cavities);
}
- if (ps->me_eval_free) {
- BKE_id_free(NULL, ps->me_eval);
- }
ps->me_eval = NULL;
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 90b0f017bd6..071042e6728 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -997,7 +997,19 @@ static void stroke_done(bContext *C, wmOperator *op)
/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
{
- return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode);
+ if ((br->flag & BRUSH_SPACE) == 0) {
+ return false;
+ }
+
+ if (br->sculpt_tool == SCULPT_TOOL_CLOTH) {
+ /* The Cloth Brush is a special case for stroke spacing. Even if it has grab modes which do
+ * not support dynamic size, stroke spacing needs to be enabled so it is possible to control
+ * whether the simulation runs constantly or only when the brush moves when using the cloth
+ * grab brushes. */
+ return true;
+ }
+
+ return paint_supports_dynamic_size(br, mode);
}
static bool sculpt_is_grab_tool(Brush *br)
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2fdf04a8b46..03d079ba0e1 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -6371,8 +6371,8 @@ void SCULPT_cache_free(StrokeCache *cache)
}
for (int i = 0; i < PAINT_SYMM_AREAS; i++) {
- if (cache->bdata[i]) {
- SCULPT_boundary_data_free(cache->bdata[i]);
+ if (cache->boundaries[i]) {
+ SCULPT_boundary_data_free(cache->boundaries[i]);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index f65c64d6d78..a188d6a678c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -130,38 +130,39 @@ static int sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss,
* deformations usually need in the boundary. */
static int BOUNDARY_INDICES_BLOCK_SIZE = 300;
-static void sculpt_boundary_index_add(SculptBoundary *bdata,
+static void sculpt_boundary_index_add(SculptBoundary *boundary,
const int new_index,
const float distance,
GSet *included_vertices)
{
- bdata->vertices[bdata->num_vertices] = new_index;
- if (bdata->distance) {
- bdata->distance[new_index] = distance;
+ boundary->vertices[boundary->num_vertices] = new_index;
+ if (boundary->distance) {
+ boundary->distance[new_index] = distance;
}
if (included_vertices) {
BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index));
}
- bdata->num_vertices++;
- if (bdata->num_vertices >= bdata->vertices_capacity) {
- bdata->vertices_capacity += BOUNDARY_INDICES_BLOCK_SIZE;
- bdata->vertices = MEM_reallocN_id(
- bdata->vertices, bdata->vertices_capacity * sizeof(int), "boundary indices");
+ boundary->num_vertices++;
+ if (boundary->num_vertices >= boundary->vertices_capacity) {
+ boundary->vertices_capacity += BOUNDARY_INDICES_BLOCK_SIZE;
+ boundary->vertices = MEM_reallocN_id(
+ boundary->vertices, boundary->vertices_capacity * sizeof(int), "boundary indices");
}
};
-static void sculpt_boundary_preview_edge_add(SculptBoundary *bdata, const int v1, const int v2)
+static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const int v1, const int v2)
{
- bdata->edges[bdata->num_edges].v1 = v1;
- bdata->edges[bdata->num_edges].v2 = v2;
- bdata->num_edges++;
+ boundary->edges[boundary->num_edges].v1 = v1;
+ boundary->edges[boundary->num_edges].v2 = v2;
+ boundary->num_edges++;
- if (bdata->num_edges >= bdata->edges_capacity) {
- bdata->edges_capacity += BOUNDARY_INDICES_BLOCK_SIZE;
- bdata->edges = MEM_reallocN_id(
- bdata->edges, bdata->edges_capacity * sizeof(SculptBoundaryPreviewEdge), "boundary edges");
+ if (boundary->num_edges >= boundary->edges_capacity) {
+ boundary->edges_capacity += BOUNDARY_INDICES_BLOCK_SIZE;
+ boundary->edges = MEM_reallocN_id(boundary->edges,
+ boundary->edges_capacity * sizeof(SculptBoundaryPreviewEdge),
+ "boundary edges");
}
};
@@ -203,7 +204,7 @@ static bool sculpt_boundary_is_vertex_in_editable_boundary(SculptSession *ss,
*/
typedef struct BoundaryFloodFillData {
- SculptBoundary *bdata;
+ SculptBoundary *boundary;
GSet *included_vertices;
EdgeSet *preview_edges;
@@ -215,15 +216,16 @@ static bool boundary_floodfill_cb(
SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
{
BoundaryFloodFillData *data = userdata;
- SculptBoundary *bdata = data->bdata;
+ SculptBoundary *boundary = data->boundary;
if (SCULPT_vertex_is_boundary(ss, to_v)) {
const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v),
SCULPT_vertex_co_get(ss, to_v));
- const float distance_boundary_to_dst = bdata->distance ? bdata->distance[from_v] + edge_len :
- 0.0f;
- sculpt_boundary_index_add(bdata, to_v, distance_boundary_to_dst, data->included_vertices);
+ const float distance_boundary_to_dst = boundary->distance ?
+ boundary->distance[from_v] + edge_len :
+ 0.0f;
+ sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices);
if (!is_duplicate) {
- sculpt_boundary_preview_edge_add(bdata, from_v, to_v);
+ sculpt_boundary_preview_edge_add(boundary, from_v, to_v);
}
return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v);
}
@@ -231,31 +233,32 @@ static bool boundary_floodfill_cb(
}
static void sculpt_boundary_indices_init(SculptSession *ss,
- SculptBoundary *bdata,
+ SculptBoundary *boundary,
const bool init_boundary_distances,
const int initial_boundary_index)
{
const int totvert = SCULPT_vertex_count_get(ss);
- bdata->vertices = MEM_malloc_arrayN(
+ boundary->vertices = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(int), "boundary indices");
if (init_boundary_distances) {
- bdata->distance = MEM_calloc_arrayN(totvert, sizeof(float), "boundary distances");
+ boundary->distance = MEM_calloc_arrayN(totvert, sizeof(float), "boundary distances");
}
- bdata->edges = MEM_malloc_arrayN(
+ boundary->edges = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), "boundary edges");
GSet *included_vertices = BLI_gset_int_new_ex("included vertices", BOUNDARY_INDICES_BLOCK_SIZE);
SculptFloodFill flood;
SCULPT_floodfill_init(ss, &flood);
- bdata->initial_vertex = initial_boundary_index;
- copy_v3_v3(bdata->initial_vertex_position, SCULPT_vertex_co_get(ss, bdata->initial_vertex));
- sculpt_boundary_index_add(bdata, initial_boundary_index, 0.0f, included_vertices);
+ boundary->initial_vertex = initial_boundary_index;
+ copy_v3_v3(boundary->initial_vertex_position,
+ SCULPT_vertex_co_get(ss, boundary->initial_vertex));
+ sculpt_boundary_index_add(boundary, initial_boundary_index, 0.0f, included_vertices);
SCULPT_floodfill_add_initial(&flood, initial_boundary_index);
BoundaryFloodFillData fdata = {
- .bdata = bdata,
+ .boundary = boundary,
.included_vertices = included_vertices,
.last_visited_vertex = BOUNDARY_VERTEX_NONE,
@@ -271,8 +274,8 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, fdata.last_visited_vertex, ni) {
if (BLI_gset_haskey(included_vertices, POINTER_FROM_INT(ni.index)) &&
sculpt_boundary_is_vertex_in_editable_boundary(ss, ni.index)) {
- sculpt_boundary_preview_edge_add(bdata, fdata.last_visited_vertex, ni.index);
- bdata->forms_loop = true;
+ sculpt_boundary_preview_edge_add(boundary, fdata.last_visited_vertex, ni.index);
+ boundary->forms_loop = true;
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
@@ -288,7 +291,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
* the closest one.
*/
static void sculpt_boundary_edit_data_init(SculptSession *ss,
- SculptBoundary *bdata,
+ SculptBoundary *boundary,
const int initial_vertex,
const float radius)
{
@@ -296,12 +299,12 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
const bool has_duplicates = BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS;
- bdata->edit_info = MEM_malloc_arrayN(
+ boundary->edit_info = MEM_malloc_arrayN(
totvert, sizeof(SculptBoundaryEditInfo), "Boundary edit info");
for (int i = 0; i < totvert; i++) {
- bdata->edit_info[i].original_vertex = BOUNDARY_VERTEX_NONE;
- bdata->edit_info[i].num_propagation_steps = BOUNDARY_STEPS_NONE;
+ boundary->edit_info[i].original_vertex = BOUNDARY_VERTEX_NONE;
+ boundary->edit_info[i].num_propagation_steps = BOUNDARY_STEPS_NONE;
}
GSQueue *current_iteration = BLI_gsqueue_new(sizeof(int));
@@ -310,23 +313,23 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
/* Initialized the first iteration with the vertices already in the boundary. This is propagation
* step 0. */
BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices");
- for (int i = 0; i < bdata->num_vertices; i++) {
- bdata->edit_info[bdata->vertices[i]].original_vertex = bdata->vertices[i];
- bdata->edit_info[bdata->vertices[i]].num_propagation_steps = 0;
+ for (int i = 0; i < boundary->num_vertices; i++) {
+ boundary->edit_info[boundary->vertices[i]].original_vertex = boundary->vertices[i];
+ boundary->edit_info[boundary->vertices[i]].num_propagation_steps = 0;
/* This ensures that all duplicate vertices in the boundary have the same original_vertex
* index, so the deformation for them will be the same. */
if (has_duplicates) {
SculptVertexNeighborIter ni_duplis;
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, bdata->vertices[i], ni_duplis) {
+ SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, boundary->vertices[i], ni_duplis) {
if (ni_duplis.is_duplicate) {
- bdata->edit_info[ni_duplis.index].original_vertex = bdata->vertices[i];
+ boundary->edit_info[ni_duplis.index].original_vertex = boundary->vertices[i];
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
}
- BLI_gsqueue_push(current_iteration, &bdata->vertices[i]);
+ BLI_gsqueue_push(current_iteration, &boundary->vertices[i]);
}
int num_propagation_steps = 0;
@@ -336,7 +339,7 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
/* This steps is further away from the boundary than the brush radius, so stop adding more
* steps. */
if (accum_distance > radius) {
- bdata->max_propagation_steps = num_propagation_steps;
+ boundary->max_propagation_steps = num_propagation_steps;
break;
}
@@ -346,19 +349,20 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
- if (bdata->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) {
- bdata->edit_info[ni.index].original_vertex = bdata->edit_info[from_v].original_vertex;
+ if (boundary->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) {
+ boundary->edit_info[ni.index].original_vertex =
+ boundary->edit_info[from_v].original_vertex;
BLI_BITMAP_ENABLE(visited_vertices, ni.index);
if (ni.is_duplicate) {
/* Grids duplicates handling. */
- bdata->edit_info[ni.index].num_propagation_steps =
- bdata->edit_info[from_v].num_propagation_steps;
+ boundary->edit_info[ni.index].num_propagation_steps =
+ boundary->edit_info[from_v].num_propagation_steps;
}
else {
- bdata->edit_info[ni.index].num_propagation_steps =
- bdata->edit_info[from_v].num_propagation_steps + 1;
+ boundary->edit_info[ni.index].num_propagation_steps =
+ boundary->edit_info[from_v].num_propagation_steps + 1;
BLI_gsqueue_push(next_iteration, &ni.index);
@@ -370,10 +374,10 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
SculptVertexNeighborIter ni_duplis;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) {
if (ni_duplis.is_duplicate) {
- bdata->edit_info[ni_duplis.index].original_vertex =
- bdata->edit_info[from_v].original_vertex;
- bdata->edit_info[ni_duplis.index].num_propagation_steps =
- bdata->edit_info[from_v].num_propagation_steps + 1;
+ boundary->edit_info[ni_duplis.index].original_vertex =
+ boundary->edit_info[from_v].original_vertex;
+ boundary->edit_info[ni_duplis.index].num_propagation_steps =
+ boundary->edit_info[from_v].num_propagation_steps + 1;
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis);
@@ -381,9 +385,9 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
/* Check the distance using the vertex that was propagated from the initial vertex that
* was used to initialize the boundary. */
- if (bdata->edit_info[from_v].original_vertex == initial_vertex) {
- bdata->pivot_vertex = ni.index;
- copy_v3_v3(bdata->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index));
+ if (boundary->edit_info[from_v].original_vertex == initial_vertex) {
+ boundary->pivot_vertex = ni.index;
+ copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index));
accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v),
SCULPT_vertex_co_get(ss, ni.index));
}
@@ -419,7 +423,7 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
* on the brush curve and its propagation steps. The falloff goes from the boundary into the mesh.
*/
static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
- SculptBoundary *bdata,
+ SculptBoundary *boundary,
Brush *brush,
const float radius)
{
@@ -427,24 +431,24 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
BKE_curvemapping_init(brush->curve);
for (int i = 0; i < totvert; i++) {
- if (bdata->edit_info[i].num_propagation_steps != -1) {
- bdata->edit_info[i].strength_factor = BKE_brush_curve_strength(
- brush, bdata->edit_info[i].num_propagation_steps, bdata->max_propagation_steps);
+ if (boundary->edit_info[i].num_propagation_steps != -1) {
+ boundary->edit_info[i].strength_factor = BKE_brush_curve_strength(
+ brush, boundary->edit_info[i].num_propagation_steps, boundary->max_propagation_steps);
}
- if (bdata->edit_info[i].original_vertex == bdata->initial_vertex) {
+ if (boundary->edit_info[i].original_vertex == boundary->initial_vertex) {
/* All vertices that are propagated from the original vertex won't be affected by the
* boundary falloff, so there is no need to calculate anything else. */
continue;
}
- if (!bdata->distance) {
+ if (!boundary->distance) {
/* There are falloff modes that do not require to modify the previously calculated falloff
* based on boundary distances. */
continue;
}
- const float boundary_distance = bdata->distance[bdata->edit_info[i].original_vertex];
+ const float boundary_distance = boundary->distance[boundary->edit_info[i].original_vertex];
float falloff_distance = 0.0f;
float direction = 1.0f;
@@ -471,8 +475,8 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
BLI_assert(false);
}
- bdata->edit_info[i].strength_factor *= direction * BKE_brush_curve_strength(
- brush, falloff_distance, radius);
+ boundary->edit_info[i].strength_factor *= direction * BKE_brush_curve_strength(
+ brush, falloff_distance, radius);
}
}
@@ -501,116 +505,118 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
return NULL;
}
- SculptBoundary *bdata = MEM_callocN(sizeof(SculptBoundary), "Boundary edit data");
+ SculptBoundary *boundary = MEM_callocN(sizeof(SculptBoundary), "Boundary edit data");
const bool init_boundary_distances = brush->boundary_falloff_type !=
BRUSH_BOUNDARY_FALLOFF_CONSTANT;
- sculpt_boundary_indices_init(ss, bdata, init_boundary_distances, boundary_initial_vertex);
+ sculpt_boundary_indices_init(ss, boundary, init_boundary_distances, boundary_initial_vertex);
const float boundary_radius = radius * (1.0f + brush->boundary_offset);
- sculpt_boundary_edit_data_init(ss, bdata, boundary_initial_vertex, boundary_radius);
+ sculpt_boundary_edit_data_init(ss, boundary, boundary_initial_vertex, boundary_radius);
- return bdata;
+ return boundary;
}
-void SCULPT_boundary_data_free(SculptBoundary *bdata)
+void SCULPT_boundary_data_free(SculptBoundary *boundary)
{
- MEM_SAFE_FREE(bdata->vertices);
- MEM_SAFE_FREE(bdata->distance);
- MEM_SAFE_FREE(bdata->edit_info);
- MEM_SAFE_FREE(bdata->bend.pivot_positions);
- MEM_SAFE_FREE(bdata->bend.pivot_rotation_axis);
- MEM_SAFE_FREE(bdata->slide.directions);
- MEM_SAFE_FREE(bdata);
+ MEM_SAFE_FREE(boundary->vertices);
+ MEM_SAFE_FREE(boundary->distance);
+ MEM_SAFE_FREE(boundary->edit_info);
+ MEM_SAFE_FREE(boundary->bend.pivot_positions);
+ MEM_SAFE_FREE(boundary->bend.pivot_rotation_axis);
+ MEM_SAFE_FREE(boundary->slide.directions);
+ MEM_SAFE_FREE(boundary);
}
/* These functions initialize the required vectors for the desired deformation using the
* SculptBoundaryEditInfo. They calculate the data using the vertices that have the
* max_propagation_steps value and them this data is copied to the rest of the vertices using the
* original vertex index. */
-static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bdata)
+static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *boundary)
{
const int totvert = SCULPT_vertex_count_get(ss);
- bdata->bend.pivot_rotation_axis = MEM_calloc_arrayN(
+ boundary->bend.pivot_rotation_axis = MEM_calloc_arrayN(
totvert, 3 * sizeof(float), "pivot rotation axis");
- bdata->bend.pivot_positions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "pivot positions");
+ boundary->bend.pivot_positions = MEM_calloc_arrayN(
+ totvert, 3 * sizeof(float), "pivot positions");
for (int i = 0; i < totvert; i++) {
- if (bdata->edit_info[i].num_propagation_steps == bdata->max_propagation_steps) {
+ if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) {
float dir[3];
float normal[3];
SCULPT_vertex_normal_get(ss, i, normal);
sub_v3_v3v3(dir,
- SCULPT_vertex_co_get(ss, bdata->edit_info[i].original_vertex),
+ SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
SCULPT_vertex_co_get(ss, i));
cross_v3_v3v3(
- bdata->bend.pivot_rotation_axis[bdata->edit_info[i].original_vertex], dir, normal);
- normalize_v3(bdata->bend.pivot_rotation_axis[bdata->edit_info[i].original_vertex]);
- copy_v3_v3(bdata->bend.pivot_positions[bdata->edit_info[i].original_vertex],
+ boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal);
+ normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]);
+ copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex],
SCULPT_vertex_co_get(ss, i));
}
}
for (int i = 0; i < totvert; i++) {
- if (bdata->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
- copy_v3_v3(bdata->bend.pivot_positions[i],
- bdata->bend.pivot_positions[bdata->edit_info[i].original_vertex]);
- copy_v3_v3(bdata->bend.pivot_rotation_axis[i],
- bdata->bend.pivot_rotation_axis[bdata->edit_info[i].original_vertex]);
+ if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
+ copy_v3_v3(boundary->bend.pivot_positions[i],
+ boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]);
+ copy_v3_v3(boundary->bend.pivot_rotation_axis[i],
+ boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]);
}
}
}
-static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *bdata)
+static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *boundary)
{
const int totvert = SCULPT_vertex_count_get(ss);
- bdata->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions");
+ boundary->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions");
for (int i = 0; i < totvert; i++) {
- if (bdata->edit_info[i].num_propagation_steps == bdata->max_propagation_steps) {
- sub_v3_v3v3(bdata->slide.directions[bdata->edit_info[i].original_vertex],
- SCULPT_vertex_co_get(ss, bdata->edit_info[i].original_vertex),
+ if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) {
+ sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex],
+ SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
SCULPT_vertex_co_get(ss, i));
- normalize_v3(bdata->slide.directions[bdata->edit_info[i].original_vertex]);
+ normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]);
}
}
for (int i = 0; i < totvert; i++) {
- if (bdata->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
- copy_v3_v3(bdata->slide.directions[i],
- bdata->slide.directions[bdata->edit_info[i].original_vertex]);
+ if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) {
+ copy_v3_v3(boundary->slide.directions[i],
+ boundary->slide.directions[boundary->edit_info[i].original_vertex]);
}
}
}
-static void sculpt_boundary_twist_data_init(SculptSession *ss, SculptBoundary *bdata)
+static void sculpt_boundary_twist_data_init(SculptSession *ss, SculptBoundary *boundary)
{
- zero_v3(bdata->twist.pivot_position);
- float(*poly_verts)[3] = MEM_malloc_arrayN(bdata->num_vertices, sizeof(float) * 3, "poly verts");
- for (int i = 0; i < bdata->num_vertices; i++) {
- add_v3_v3(bdata->twist.pivot_position, SCULPT_vertex_co_get(ss, bdata->vertices[i]));
- copy_v3_v3(poly_verts[i], SCULPT_vertex_co_get(ss, bdata->vertices[i]));
+ zero_v3(boundary->twist.pivot_position);
+ float(*poly_verts)[3] = MEM_malloc_arrayN(
+ boundary->num_vertices, sizeof(float) * 3, "poly verts");
+ for (int i = 0; i < boundary->num_vertices; i++) {
+ add_v3_v3(boundary->twist.pivot_position, SCULPT_vertex_co_get(ss, boundary->vertices[i]));
+ copy_v3_v3(poly_verts[i], SCULPT_vertex_co_get(ss, boundary->vertices[i]));
}
- mul_v3_fl(bdata->twist.pivot_position, 1.0f / bdata->num_vertices);
- if (bdata->forms_loop) {
- normal_poly_v3(bdata->twist.rotation_axis, poly_verts, bdata->num_vertices);
+ mul_v3_fl(boundary->twist.pivot_position, 1.0f / boundary->num_vertices);
+ if (boundary->forms_loop) {
+ normal_poly_v3(boundary->twist.rotation_axis, poly_verts, boundary->num_vertices);
}
else {
- sub_v3_v3v3(bdata->twist.rotation_axis,
- SCULPT_vertex_co_get(ss, bdata->pivot_vertex),
- SCULPT_vertex_co_get(ss, bdata->initial_vertex));
- normalize_v3(bdata->twist.rotation_axis);
+ sub_v3_v3v3(boundary->twist.rotation_axis,
+ SCULPT_vertex_co_get(ss, boundary->pivot_vertex),
+ SCULPT_vertex_co_get(ss, boundary->initial_vertex));
+ normalize_v3(boundary->twist.rotation_axis);
}
MEM_freeN(poly_verts);
}
static float sculpt_boundary_displacement_from_grab_delta_get(SculptSession *ss,
- SculptBoundary *bdata)
+ SculptBoundary *boundary)
{
float plane[4];
float pos[3];
float normal[3];
- sub_v3_v3v3(normal, ss->cache->initial_location, bdata->initial_pivot_position);
+ sub_v3_v3v3(normal, ss->cache->initial_location, boundary->initial_pivot_position);
normalize_v3(normal);
plane_from_point_normal_v3(plane, ss->cache->initial_location, normal);
add_v3_v3v3(pos, ss->cache->initial_location, ss->cache->grab_delta_symmetry);
@@ -625,7 +631,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const int symm_area = ss->cache->mirror_symmetry_pass;
- SculptBoundary *bdata = ss->cache->bdata[symm_area];
+ SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
const float strength = ss->cache->bstrength;
@@ -634,7 +640,7 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
- const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, bdata);
+ const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
float angle_factor = disp / ss->cache->radius;
/* Angle Snapping when inverting the brush. */
if (ss->cache->invert) {
@@ -645,17 +651,18 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (bdata->edit_info[vd.index].num_propagation_steps != -1) {
+ if (boundary->edit_info[vd.index].num_propagation_steps != -1) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
- if (SCULPT_check_vertex_pivot_symmetry(orig_data.co, bdata->initial_vertex_position, symm)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float t_orig_co[3];
- sub_v3_v3v3(t_orig_co, orig_data.co, bdata->bend.pivot_positions[vd.index]);
+ sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]);
rotate_v3_v3v3fl(vd.co,
t_orig_co,
- bdata->bend.pivot_rotation_axis[vd.index],
- angle * bdata->edit_info[vd.index].strength_factor * mask);
- add_v3_v3(vd.co, bdata->bend.pivot_positions[vd.index]);
+ boundary->bend.pivot_rotation_axis[vd.index],
+ angle * boundary->edit_info[vd.index].strength_factor * mask);
+ add_v3_v3(vd.co, boundary->bend.pivot_positions[vd.index]);
}
}
@@ -673,7 +680,7 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const int symm_area = ss->cache->mirror_symmetry_pass;
- SculptBoundary *bdata = ss->cache->bdata[symm_area];
+ SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
const float strength = ss->cache->bstrength;
@@ -682,19 +689,20 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
- const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, bdata);
+ const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (bdata->edit_info[vd.index].num_propagation_steps != -1) {
+ if (boundary->edit_info[vd.index].num_propagation_steps != -1) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
- if (SCULPT_check_vertex_pivot_symmetry(orig_data.co, bdata->initial_vertex_position, symm)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
madd_v3_v3v3fl(vd.co,
orig_data.co,
- bdata->slide.directions[vd.index],
- bdata->edit_info[vd.index].strength_factor * disp * mask * strength);
+ boundary->slide.directions[vd.index],
+ boundary->edit_info[vd.index].strength_factor * disp * mask * strength);
}
}
@@ -712,7 +720,7 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const int symm_area = ss->cache->mirror_symmetry_pass;
- SculptBoundary *bdata = ss->cache->bdata[symm_area];
+ SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
const float strength = ss->cache->bstrength;
@@ -721,21 +729,22 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
- const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, bdata);
+ const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (bdata->edit_info[vd.index].num_propagation_steps != -1) {
+ if (boundary->edit_info[vd.index].num_propagation_steps != -1) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
- if (SCULPT_check_vertex_pivot_symmetry(orig_data.co, bdata->initial_vertex_position, symm)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float normal[3];
normal_short_to_float_v3(normal, orig_data.no);
madd_v3_v3v3fl(vd.co,
orig_data.co,
normal,
- bdata->edit_info[vd.index].strength_factor * disp * mask * strength);
+ boundary->edit_info[vd.index].strength_factor * disp * mask * strength);
}
}
@@ -753,7 +762,7 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const int symm_area = ss->cache->mirror_symmetry_pass;
- SculptBoundary *bdata = ss->cache->bdata[symm_area];
+ SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
const float strength = ss->cache->bstrength;
@@ -765,14 +774,15 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (bdata->edit_info[vd.index].num_propagation_steps != -1) {
+ if (boundary->edit_info[vd.index].num_propagation_steps != -1) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
- if (SCULPT_check_vertex_pivot_symmetry(orig_data.co, bdata->initial_vertex_position, symm)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
madd_v3_v3v3fl(vd.co,
orig_data.co,
ss->cache->grab_delta_symmetry,
- bdata->edit_info[vd.index].strength_factor * mask * strength);
+ boundary->edit_info[vd.index].strength_factor * mask * strength);
}
}
@@ -790,7 +800,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
const int symm_area = ss->cache->mirror_symmetry_pass;
- SculptBoundary *bdata = ss->cache->bdata[symm_area];
+ SculptBoundary *boundary = ss->cache->boundaries[symm_area];
const ePaintSymmetryFlags symm = data->sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
const float strength = ss->cache->bstrength;
@@ -799,7 +809,7 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
SculptOrigVertData orig_data;
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
- const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, bdata);
+ const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
float angle_factor = disp / ss->cache->radius;
/* Angle Snapping when inverting the brush. */
if (ss->cache->invert) {
@@ -810,17 +820,18 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (bdata->edit_info[vd.index].num_propagation_steps != -1) {
+ if (boundary->edit_info[vd.index].num_propagation_steps != -1) {
SCULPT_orig_vert_data_update(&orig_data, &vd);
- if (SCULPT_check_vertex_pivot_symmetry(orig_data.co, bdata->initial_vertex_position, symm)) {
+ if (SCULPT_check_vertex_pivot_symmetry(
+ orig_data.co, boundary->initial_vertex_position, symm)) {
const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
float t_orig_co[3];
- sub_v3_v3v3(t_orig_co, orig_data.co, bdata->twist.pivot_position);
+ sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position);
rotate_v3_v3v3fl(vd.co,
t_orig_co,
- bdata->twist.rotation_axis,
- angle * mask * bdata->edit_info[vd.index].strength_factor);
- add_v3_v3(vd.co, bdata->twist.pivot_position);
+ boundary->twist.rotation_axis,
+ angle * mask * boundary->edit_info[vd.index].strength_factor);
+ add_v3_v3(vd.co, boundary->twist.pivot_position);
}
}
@@ -851,20 +862,20 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
sd, ob, location, ss->cache->radius_squared, false);
}
- ss->cache->bdata[symm_area] = SCULPT_boundary_data_init(
+ ss->cache->boundaries[symm_area] = SCULPT_boundary_data_init(
ob, brush, initial_vertex, ss->cache->initial_radius);
- if (ss->cache->bdata[symm_area]) {
+ if (ss->cache->boundaries[symm_area]) {
switch (brush->boundary_deform_type) {
case BRUSH_BOUNDARY_DEFORM_BEND:
- sculpt_boundary_bend_data_init(ss, ss->cache->bdata[symm_area]);
+ sculpt_boundary_bend_data_init(ss, ss->cache->boundaries[symm_area]);
break;
case BRUSH_BOUNDARY_DEFORM_EXPAND:
- sculpt_boundary_slide_data_init(ss, ss->cache->bdata[symm_area]);
+ sculpt_boundary_slide_data_init(ss, ss->cache->boundaries[symm_area]);
break;
case BRUSH_BOUNDARY_DEFORM_TWIST:
- sculpt_boundary_twist_data_init(ss, ss->cache->bdata[symm_area]);
+ sculpt_boundary_twist_data_init(ss, ss->cache->boundaries[symm_area]);
break;
case BRUSH_BOUNDARY_DEFORM_INFLATE:
case BRUSH_BOUNDARY_DEFORM_GRAB:
@@ -873,12 +884,12 @@ void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totn
}
sculpt_boundary_falloff_factor_init(
- ss, ss->cache->bdata[symm_area], brush, ss->cache->initial_radius);
+ ss, ss->cache->boundaries[symm_area], brush, ss->cache->initial_radius);
}
}
/* No active boundary under the cursor. */
- if (!ss->cache->bdata[symm_area]) {
+ if (!ss->cache->boundaries[symm_area]) {
return;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 4070822a0a8..acfa04022cb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -505,49 +505,6 @@ static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph)
return cache;
}
-static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
- Brush *brush,
- const float cloth_mass,
- const float cloth_damping,
- const bool use_collisions)
-{
- const int totverts = SCULPT_vertex_count_get(ss);
- SculptClothSimulation *cloth_sim;
-
- cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
-
- cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
- CLOTH_LENGTH_CONSTRAINTS_BLOCK,
- "cloth length constraints");
- cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
-
- cloth_sim->acceleration = MEM_calloc_arrayN(
- totverts, sizeof(float[3]), "cloth sim acceleration");
- cloth_sim->pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim pos");
- cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim prev pos");
- cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
- totverts, sizeof(float[3]), "cloth sim last iteration pos");
- cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
- cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
- totverts, sizeof(float), "cloth sim length tweak");
-
- /* Brush can be NULL for tools that need the solver but don't rely on constraint to deformation
- * positions. */
- if (brush && SCULPT_is_cloth_deform_brush(brush)) {
- cloth_sim->deformation_pos = MEM_calloc_arrayN(
- totverts, sizeof(float[3]), "cloth sim deformation positions");
- }
-
- cloth_sim->mass = cloth_mass;
- cloth_sim->damping = cloth_damping;
-
- if (use_collisions) {
- cloth_sim->collider_list = cloth_brush_collider_cache_create(ss->depsgraph);
- }
-
- return cloth_sim;
-}
-
typedef struct ClothBrushCollision {
CollisionModifierData *col_data;
struct IsectRayPrecalc isect_precalc;
@@ -699,43 +656,6 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
BKE_pbvh_vertex_iter_end;
}
-static void cloth_brush_build_nodes_constraints(
- Sculpt *sd,
- Object *ob,
- PBVHNode **nodes,
- int totnode,
- SculptClothSimulation *cloth_sim,
- /* Cannot be const, because it is assigned to a non-const variable.
- * NOLINTNEXTLINE: readability-non-const-parameter. */
- float initial_location[3],
- const float radius)
-{
- Brush *brush = BKE_paint_brush(&sd->paint);
-
- /* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
- * storing the constraints per node. */
- /* Currently all constrains are added to the same global array which can't be accessed from
- * different threads. */
- TaskParallelSettings settings;
- BKE_pbvh_parallel_range_settings(&settings, false, totnode);
-
- cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
-
- SculptThreadedTaskData build_constraints_data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .cloth_sim = cloth_sim,
- .cloth_sim_initial_location = initial_location,
- .cloth_sim_radius = radius,
- };
- BLI_task_parallel_range(
- 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
-
- BLI_edgeset_free(cloth_sim->created_length_constraints);
-}
-
static void cloth_brush_satisfy_constraints(SculptSession *ss,
Brush *brush,
SculptClothSimulation *cloth_sim)
@@ -897,6 +817,107 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod
}
/* Public functions. */
+SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
+ Brush *brush,
+ const float cloth_mass,
+ const float cloth_damping,
+ const bool use_collisions)
+{
+ const int totverts = SCULPT_vertex_count_get(ss);
+ SculptClothSimulation *cloth_sim;
+
+ cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
+
+ cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
+ CLOTH_LENGTH_CONSTRAINTS_BLOCK,
+ "cloth length constraints");
+ cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
+
+ cloth_sim->acceleration = MEM_calloc_arrayN(
+ totverts, sizeof(float[3]), "cloth sim acceleration");
+ cloth_sim->pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim pos");
+ cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim prev pos");
+ cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
+ totverts, sizeof(float[3]), "cloth sim last iteration pos");
+ cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
+ cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
+ totverts, sizeof(float), "cloth sim length tweak");
+
+ /* Brush can be NULL for tools that need the solver but don't rely on constraint to deformation
+ * positions. */
+ if (brush && SCULPT_is_cloth_deform_brush(brush)) {
+ cloth_sim->deformation_pos = MEM_calloc_arrayN(
+ totverts, sizeof(float[3]), "cloth sim deformation positions");
+ }
+
+ cloth_sim->mass = cloth_mass;
+ cloth_sim->damping = cloth_damping;
+
+ if (use_collisions) {
+ cloth_sim->collider_list = cloth_brush_collider_cache_create(ss->depsgraph);
+ }
+
+ return cloth_sim;
+}
+
+void SCULPT_cloth_brush_build_nodes_constraints(
+ Sculpt *sd,
+ Object *ob,
+ PBVHNode **nodes,
+ int totnode,
+ SculptClothSimulation *cloth_sim,
+ /* Cannot be const, because it is assigned to a non-const variable.
+ * NOLINTNEXTLINE: readability-non-const-parameter. */
+ float initial_location[3],
+ const float radius)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ /* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
+ * storing the constraints per node. */
+ /* Currently all constrains are added to the same global array which can't be accessed from
+ * different threads. */
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, false, totnode);
+
+ cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
+
+ SculptThreadedTaskData build_constraints_data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ .cloth_sim = cloth_sim,
+ .cloth_sim_initial_location = initial_location,
+ .cloth_sim_radius = radius,
+ };
+ BLI_task_parallel_range(
+ 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
+
+ BLI_edgeset_free(cloth_sim->created_length_constraints);
+}
+
+void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation *cloth_sim)
+{
+ const int totverts = SCULPT_vertex_count_get(ss);
+ const bool has_deformation_pos = cloth_sim->deformation_pos != NULL;
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
+ if (has_deformation_pos) {
+ copy_v3_v3(cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+ }
+}
+
+void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss, SculptClothSimulation *cloth_sim)
+{
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+}
/* Main Brush Function. */
void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@@ -914,27 +935,19 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
/* The simulation structure only needs to be created on the first symmetry pass. */
if (SCULPT_stroke_is_first_brush_step(ss->cache) || !ss->cache->cloth_sim) {
- const bool is_cloth_deform_brush = SCULPT_is_cloth_deform_brush(brush);
- ss->cache->cloth_sim = cloth_brush_simulation_create(
+ ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss,
brush,
brush->cloth_mass,
brush->cloth_damping,
(brush->flag2 & BRUSH_CLOTH_USE_COLLISION));
- for (int i = 0; i < totverts; i++) {
- copy_v3_v3(ss->cache->cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
- if (is_cloth_deform_brush) {
- copy_v3_v3(ss->cache->cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
- }
- }
+ SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
}
/* Build the constraints. */
const float radius = ss->cache->initial_radius;
const float limit = radius + (radius * brush->cloth_sim_limit);
- cloth_brush_build_nodes_constraints(
+ SCULPT_cloth_brush_build_nodes_constraints(
sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit);
return;
@@ -1047,6 +1060,19 @@ static EnumPropertyItem prop_cloth_filter_type[] = {
{0, NULL, 0, NULL, NULL},
};
+typedef enum eClothFilterForceAxis {
+ CLOTH_FILTER_FORCE_X = 1 << 0,
+ CLOTH_FILTER_FORCE_Y = 1 << 1,
+ CLOTH_FILTER_FORCE_Z = 1 << 2,
+} eClothFilterForceAxis;
+
+static EnumPropertyItem prop_cloth_filter_force_axis_items[] = {
+ {CLOTH_FILTER_FORCE_X, "X", 0, "X", "Apply force in the X axis"},
+ {CLOTH_FILTER_FORCE_Y, "Y", 0, "Y", "Apply force in the Y axis"},
+ {CLOTH_FILTER_FORCE_Z, "Z", 0, "Z", "Apply force in the Z axis"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
const int i,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -1101,6 +1127,12 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
break;
}
+ for (int axis = 0; axis < 3; axis++) {
+ if (!ss->filter_cache->enabled_force_axis[axis]) {
+ force[axis] = 0.0f;
+ }
+ }
+
add_v3_v3(force, sculpt_gravity);
cloth_brush_apply_force_to_vertex(ss, cloth_sim, force, vd.index);
@@ -1187,31 +1219,26 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
SCULPT_undo_push_begin("Cloth filter");
- SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS);
+ SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
const bool use_collisions = RNA_boolean_get(op->ptr, "use_collisions");
- ss->filter_cache->cloth_sim = cloth_brush_simulation_create(
+ ss->filter_cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
ss, NULL, cloth_mass, cloth_damping, use_collisions);
copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
- const int totverts = SCULPT_vertex_count_get(ss);
- for (int i = 0; i < totverts; i++) {
- copy_v3_v3(ss->filter_cache->cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
- copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
- }
+ SCULPT_cloth_brush_simulation_init(ss, ss->filter_cache->cloth_sim);
float origin[3] = {0.0f, 0.0f, 0.0f};
- cloth_brush_build_nodes_constraints(sd,
- ob,
- ss->filter_cache->nodes,
- ss->filter_cache->totnode,
- ss->filter_cache->cloth_sim,
- origin,
- FLT_MAX);
+ SCULPT_cloth_brush_build_nodes_constraints(sd,
+ ob,
+ ss->filter_cache->nodes,
+ ss->filter_cache->totnode,
+ ss->filter_cache->cloth_sim,
+ origin,
+ FLT_MAX);
const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
if (use_face_sets) {
@@ -1221,6 +1248,11 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
}
+ const int force_axis = RNA_enum_get(op->ptr, "force_axis");
+ ss->filter_cache->enabled_force_axis[0] = force_axis & CLOTH_FILTER_FORCE_X;
+ ss->filter_cache->enabled_force_axis[1] = force_axis & CLOTH_FILTER_FORCE_Y;
+ ss->filter_cache->enabled_force_axis[2] = force_axis & CLOTH_FILTER_FORCE_Z;
+
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1248,6 +1280,12 @@ void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
"Operation that is going to be applied to the mesh");
RNA_def_float(
ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ RNA_def_enum_flag(ot->srna,
+ "force_axis",
+ prop_cloth_filter_force_axis_items,
+ CLOTH_FILTER_FORCE_X | CLOTH_FILTER_FORCE_Y | CLOTH_FILTER_FORCE_Z,
+ "Force axis",
+ "Apply the force in the selected axis");
RNA_def_float(ot->srna,
"cloth_mass",
1.0f,
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 2afa3556dd9..b9265380a35 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -71,6 +71,37 @@
#include <math.h>
#include <stdlib.h>
+/* Utils. */
+int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
+{
+ int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ if (!face_sets) {
+ return SCULPT_FACE_SET_NONE;
+ }
+
+ int next_face_set_id = 0;
+ for (int i = 0; i < mesh->totpoly; i++) {
+ next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i]));
+ }
+ next_face_set_id++;
+
+ return next_face_set_id;
+}
+
+void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
+{
+ int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+ if (!face_sets) {
+ return;
+ }
+
+ for (int i = 0; i < mesh->totpoly; i++) {
+ if (face_sets[i] == SCULPT_FACE_SET_NONE) {
+ face_sets[i] = new_id;
+ }
+ }
+}
+
/* Draw Face Sets Brush. */
static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
@@ -901,6 +932,25 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int sculpt_face_sets_change_visibility_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ /* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
+ * cursor updates. */
+ SculptCursorGeometryInfo sgi;
+ float mouse[2];
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_vertex_random_access_ensure(ss);
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+
+ return sculpt_face_sets_change_visibility_exec(C, op);
+}
+
void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
{
/* Identifiers. */
@@ -910,6 +960,7 @@ void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
/* Api callbacks. */
ot->exec = sculpt_face_sets_change_visibility_exec;
+ ot->invoke = sculpt_face_sets_change_visibility_invoke;
ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 576536cac03..c5acf736f3e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -289,7 +289,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_CANCELLED;
}
- SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COLOR);
+ SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COLOR);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index f9ae91fce7f..0da4297450f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -50,6 +50,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
+#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -63,6 +64,39 @@
#include <math.h>
#include <stdlib.h>
+/* Filter orientation utils. */
+void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache)
+{
+ switch (filter_cache->orientation) {
+ case SCULPT_FILTER_ORIENTATION_LOCAL:
+ /* Do nothing, Sculpt Mode already works in object space. */
+ break;
+ case SCULPT_FILTER_ORIENTATION_WORLD:
+ mul_mat3_m4_v3(filter_cache->obmat, r_v);
+ break;
+ case SCULPT_FILTER_ORIENTATION_VIEW:
+ mul_mat3_m4_v3(filter_cache->obmat, r_v);
+ mul_mat3_m4_v3(filter_cache->viewmat, r_v);
+ break;
+ }
+}
+
+void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache)
+{
+ switch (filter_cache->orientation) {
+ case SCULPT_FILTER_ORIENTATION_LOCAL:
+ /* Do nothing, Sculpt Mode already works in object space. */
+ break;
+ case SCULPT_FILTER_ORIENTATION_WORLD:
+ mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
+ break;
+ case SCULPT_FILTER_ORIENTATION_VIEW:
+ mul_mat3_m4_v3(filter_cache->viewmat_inv, r_v);
+ mul_mat3_m4_v3(filter_cache->obmat_inv, r_v);
+ break;
+ }
+}
+
static void filter_cache_init_task_cb(void *__restrict userdata,
const int i,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -73,7 +107,7 @@ static void filter_cache_init_task_cb(void *__restrict userdata,
SCULPT_undo_push_node(data->ob, node, data->filter_undo_type);
}
-void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type)
+void SCULPT_filter_cache_init(bContext *C, Object *ob, Sculpt *sd, const int undo_type)
{
SculptSession *ss = ob->sculpt;
PBVH *pbvh = ob->sculpt->pbvh;
@@ -117,6 +151,16 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type)
BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
BLI_task_parallel_range(
0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings);
+
+ /* Setup orientation matrices. */
+ copy_m4_m4(ss->filter_cache->obmat, ob->obmat);
+ invert_m4_m4(ss->filter_cache->obmat_inv, ob->obmat);
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc, depsgraph);
+ copy_m4_m4(ss->filter_cache->viewmat, vc.rv3d->viewmat);
+ copy_m4_m4(ss->filter_cache->viewmat_inv, vc.rv3d->viewinv);
}
void SCULPT_filter_cache_free(SculptSession *ss)
@@ -182,6 +226,25 @@ static EnumPropertyItem prop_mesh_filter_deform_axis_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static EnumPropertyItem prop_mesh_filter_orientation_items[] = {
+ {SCULPT_FILTER_ORIENTATION_LOCAL,
+ "LOCAL",
+ 0,
+ "Local",
+ "Use the local axis to limit the displacement"},
+ {SCULPT_FILTER_ORIENTATION_WORLD,
+ "WORLD",
+ 0,
+ "World",
+ "Use the global axis to limit the displacement"},
+ {SCULPT_FILTER_ORIENTATION_VIEW,
+ "VIEW",
+ 0,
+ "View",
+ "Use the view axis to limit the displacement"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static bool sculpt_mesh_filter_needs_pmap(int filter_type, bool use_face_sets)
{
return use_face_sets || ELEM(filter_type,
@@ -372,11 +435,13 @@ static void mesh_filter_task_cb(void *__restrict userdata,
}
}
+ SCULPT_filter_to_orientation_space(disp, ss->filter_cache);
for (int it = 0; it < 3; it++) {
if (!ss->filter_cache->enabled_axis[it]) {
disp[it] = 0.0f;
}
}
+ SCULPT_filter_to_object_space(disp, ss->filter_cache);
if (ELEM(filter_type, MESH_FILTER_SURFACE_SMOOTH, MESH_FILTER_SHARPEN)) {
madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
@@ -584,7 +649,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_boundary_info_ensure(ob);
}
- SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS);
+ SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
if (use_face_sets) {
ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
@@ -620,6 +685,9 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z;
+ SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
+ ss->filter_cache->orientation = orientation;
+
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -653,6 +721,12 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
MESH_FILTER_DEFORM_X | MESH_FILTER_DEFORM_Y | MESH_FILTER_DEFORM_Z,
"Deform axis",
"Apply the deformation in the selected axis");
+ RNA_def_enum(ot->srna,
+ "orientation",
+ prop_mesh_filter_orientation_items,
+ SCULPT_FILTER_ORIENTATION_LOCAL,
+ "Orientation",
+ "Orientation of the axis to limit the filter displacement");
ot->prop = RNA_def_boolean(ot->srna,
"use_face_sets",
false,
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index ee0eaeb28f3..65006031bb3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -337,7 +337,7 @@ float *SCULPT_boundary_automasking_init(Object *ob,
float *automask_factor);
/* Filters. */
-void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type);
+void SCULPT_filter_cache_init(struct bContext *C, Object *ob, Sculpt *sd, const int undo_type);
void SCULPT_filter_cache_free(SculptSession *ss);
void SCULPT_mask_filter_smooth_apply(
@@ -352,6 +352,30 @@ void SCULPT_do_cloth_brush(struct Sculpt *sd,
int totnode);
void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim);
+struct SculptClothSimulation *SCULPT_cloth_brush_simulation_create(struct SculptSession *ss,
+ struct Brush *brush,
+ const float cloth_mass,
+ const float cloth_damping,
+ const bool use_collisions);
+void SCULPT_cloth_brush_simulation_init(struct SculptSession *ss,
+ struct SculptClothSimulation *cloth_sim);
+void SCULPT_cloth_brush_store_simulation_state(struct SculptSession *ss,
+ struct SculptClothSimulation *cloth_sim);
+
+void SCULPT_cloth_brush_do_simulation_step(struct Sculpt *sd,
+ struct Object *ob,
+ struct SculptClothSimulation *cloth_sim,
+ struct PBVHNode **nodes,
+ int totnode);
+
+void SCULPT_cloth_brush_build_nodes_constraints(struct Sculpt *sd,
+ struct Object *ob,
+ struct PBVHNode **nodes,
+ int totnode,
+ struct SculptClothSimulation *cloth_sim,
+ float initial_location[3],
+ const float radius);
+
void SCULPT_cloth_simulation_limits_draw(const uint gpuattr,
const struct Brush *brush,
const float location[3],
@@ -401,7 +425,7 @@ struct SculptBoundary *SCULPT_boundary_data_init(Object *object,
Brush *brush,
const int initial_vertex,
const float radius);
-void SCULPT_boundary_data_free(struct SculptBoundary *bdata);
+void SCULPT_boundary_data_free(struct SculptBoundary *boundary);
void SCULPT_do_boundary_brush(struct Sculpt *sd,
struct Object *ob,
struct PBVHNode **nodes,
@@ -880,7 +904,7 @@ typedef struct StrokeCache {
float true_initial_normal[3];
/* Boundary brush */
- struct SculptBoundary *bdata[PAINT_SYMM_AREAS];
+ struct SculptBoundary *boundaries[PAINT_SYMM_AREAS];
/* Surface Smooth Brush */
/* Stores the displacement produced by the laplacian step of HC smooth. */
@@ -920,8 +944,19 @@ typedef struct StrokeCache {
} StrokeCache;
+/* Sculpt Filters */
+typedef enum SculptFilterOrientation {
+ SCULPT_FILTER_ORIENTATION_LOCAL = 0,
+ SCULPT_FILTER_ORIENTATION_WORLD = 1,
+ SCULPT_FILTER_ORIENTATION_VIEW = 2,
+} SculptFilterOrientation;
+
+void SCULPT_filter_to_orientation_space(float r_v[3], struct FilterCache *filter_cache);
+void SCULPT_filter_to_object_space(float r_v[3], struct FilterCache *filter_cache);
+
typedef struct FilterCache {
bool enabled_axis[3];
+ bool enabled_force_axis[3];
int random_seed;
/* Used for alternating between filter operations in filters that need to apply different ones to
@@ -940,6 +975,13 @@ typedef struct FilterCache {
float *sharpen_factor;
float (*sharpen_detail_directions)[3];
+ /* Filter orientaiton. */
+ SculptFilterOrientation orientation;
+ float obmat[4][4];
+ float obmat_inv[4][4];
+ float viewmat[4][4];
+ float viewmat_inv[4][4];
+
/* unmasked nodes */
PBVHNode **nodes;
int totnode;
diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c
index 4c54a0465b9..bdada4d2565 100644
--- a/source/blender/editors/sculpt_paint/sculpt_transform.c
+++ b/source/blender/editors/sculpt_paint/sculpt_transform.c
@@ -76,7 +76,7 @@ void ED_sculpt_init_transform(struct bContext *C)
ss->pivot_rot[3] = 1.0f;
SCULPT_vertex_random_access_ensure(ss);
- SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS);
+ SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
}
static void sculpt_transform_task_cb(void *__restrict userdata,
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 050dca07c34..e8eddc014db 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -306,7 +306,6 @@ static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
/* NOTE: We will be forcefully evaluating dependency graph at every frame, so no need to ensure
* current scene state is evaluated as it will be lost anyway. */
@@ -318,11 +317,11 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
scene->r.cfra = cfra;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
}
scene->r.cfra = oldfra;
- BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ BKE_scene_graph_update_for_newframe(depsgraph);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index 25ff6bbd098..75d91174470 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -54,4 +54,9 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_EXPERIMENTAL_FEATURES)
+ add_definitions(-DWITH_PARTICLE_NODES)
+ add_definitions(-DWITH_HAIR_NODES)
+endif()
+
blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 5885d3dcbb0..3976e18d70c 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -249,12 +249,16 @@ static bool buttons_context_path_data(ButsContextPath *path, int type)
if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (type == -1 || type == OB_GPENCIL)) {
return true;
}
+#ifdef WITH_HAIR_NODES
if (RNA_struct_is_a(ptr->type, &RNA_Hair) && (type == -1 || type == OB_HAIR)) {
return true;
}
+#endif
+#ifdef WITH_PARTICLE_NODES
if (RNA_struct_is_a(ptr->type, &RNA_PointCloud) && (type == -1 || type == OB_POINTCLOUD)) {
return true;
}
+#endif
if (RNA_struct_is_a(ptr->type, &RNA_Volume) && (type == -1 || type == OB_VOLUME)) {
return true;
}
@@ -871,14 +875,18 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_LightProbe);
return 1;
}
+#ifdef WITH_HAIR_NODES
if (CTX_data_equals(member, "hair")) {
set_pointer_type(path, result, &RNA_Hair);
return 1;
}
+#endif
+#ifdef WITH_PARTICLE_NODES
if (CTX_data_equals(member, "pointcloud")) {
set_pointer_type(path, result, &RNA_PointCloud);
return 1;
}
+#endif
if (CTX_data_equals(member, "volume")) {
set_pointer_type(path, result, &RNA_Volume);
return 1;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 9d048bf7c3c..0a754b6ec2a 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -52,6 +52,7 @@
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
+#include "GPU_viewport.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -1755,10 +1756,15 @@ void drawnodespace(const bContext *C, ARegion *region)
SpaceNode *snode = CTX_wm_space_node(C);
View2D *v2d = &region->v2d;
- UI_ThemeClearColor(TH_BACK);
- GPU_clear(GPU_COLOR_BIT);
+ /* Setup offscreen buffers. */
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+
+ GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
+ GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
UI_view2d_view_ortho(v2d);
+ UI_ThemeClearColor(TH_BACK);
+ GPU_clear(GPU_COLOR_BIT);
/* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */
UI_view2d_region_to_view(&region->v2d,
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index c88b6a1b297..5f5f6467c8a 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -207,8 +207,7 @@ static void compo_initjob(void *cjv)
ViewLayer *view_layer = cj->view_layer;
cj->compositor_depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
- DEG_graph_build_for_compositor_preview(
- cj->compositor_depsgraph, bmain, scene, view_layer, cj->ntree);
+ DEG_graph_build_for_compositor_preview(cj->compositor_depsgraph, cj->ntree);
/* NOTE: Don't update animation to preserve unkeyed changes, this means can not use
* evaluate_on_framechange. */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 0f4690c11d5..908ead31724 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -56,6 +56,7 @@
#include "GPU_matrix.h"
#include "GPU_state.h"
#include "GPU_vertex_buffer.h"
+#include "GPU_viewport.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -1537,7 +1538,7 @@ static void sequencer_preview_clear(void)
float col[3];
UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
+ GPU_clear_color(col[0], col[1], col[2], 1.0f);
GPU_clear(GPU_COLOR_BIT);
}
@@ -1775,6 +1776,12 @@ void sequencer_draw_preview(const bContext *C,
return;
}
+ /* Setup offscreen buffers. */
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
+
+ GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
+ GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
+
if (sseq->render_size == SEQ_PROXY_RENDER_SIZE_NONE) {
sequencer_preview_clear();
return;
@@ -1798,6 +1805,9 @@ void sequencer_draw_preview(const bContext *C,
ibuf = sequencer_ibuf_get(
bmain, depsgraph, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
+ /* sequencer_ibuf_get can call GPU_framebuffer_bind. So disable srgb framebuffer again. */
+ GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
+
if (ibuf) {
scope = sequencer_get_scope(scene, sseq, ibuf, draw_backdrop);
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c
index 2e92b4e5c09..61af4ebbe46 100644
--- a/source/blender/editors/transform/transform_convert_object.c
+++ b/source/blender/editors/transform/transform_convert_object.c
@@ -357,7 +357,7 @@ static void set_trans_object_base_flags(TransInfo *t)
/* Makes sure base flags and object flags are identical. */
BKE_scene_base_flag_to_objects(t->view_layer);
/* Make sure depsgraph is here. */
- DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ DEG_graph_relations_update(depsgraph);
/* Clear all flags we need. It will be used to detect dependencies. */
trans_object_base_deps_flag_prepare(view_layer);
/* Traverse all bases and set all possible flags. */