diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2020-08-18 17:13:08 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2020-08-18 17:13:08 +0300 |
commit | 77efb597cee8efafd9584fcd511e6111651c6512 (patch) | |
tree | 08b3ea14968cf06c06039170bce24f44d4f63706 /source/blender/editors | |
parent | de7470645a30e7bc6db67eff64d11778fb5ee3f2 (diff) | |
parent | 872efd8d73a3820680379230d83a0aadf5fc29ca (diff) |
Merge branch 'master' into greasepencil-edit-curve
Conflicts:
source/blender/editors/gpencil/gpencil_edit.c
Diffstat (limited to 'source/blender/editors')
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 = ®ion->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(®ion->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. */ |