Merge branch 'master' into sculpt-dev

This commit is contained in:
Pablo Dobarro 2021-01-06 17:34:16 +01:00
commit 237b1f9d75
36 changed files with 305 additions and 103 deletions

View File

@ -1563,7 +1563,7 @@ def km_graph_editor(params):
("graph.sample", {"type": 'O', "value": 'PRESS', "shift": True, "alt": True}, None),
("graph.bake", {"type": 'C', "value": 'PRESS', "alt": True}, None),
op_menu("GRAPH_MT_delete", {"type": 'X', "value": 'PRESS'}),
op_menu("GRAPH_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True},
@ -2113,7 +2113,7 @@ def km_dopesheet(params):
("action.keyframe_type", {"type": 'R', "value": 'PRESS'}, None),
("action.sample", {"type": 'O', "value": 'PRESS', "shift": True, "alt": True}, None),
op_menu("DOPESHEET_MT_delete", {"type": 'X', "value": 'PRESS'}),
op_menu("DOPESHEET_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
("action.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("action.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("action.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
("action.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),

View File

@ -929,7 +929,7 @@ def km_graph_editor(params):
("graph.select_less", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True}, None),
("graph.select_linked", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, None),
op_menu("GRAPH_MT_delete", {"type": 'BACK_SPACE', "value": 'PRESS'}),
op_menu("GRAPH_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
*_template_items_context_menu("GRAPH_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
("graph.keyframe_insert", {"type": 'S', "value": 'PRESS'}, None),
@ -1416,7 +1416,7 @@ def km_dopesheet(params):
op_menu_pie("DOPESHEET_MT_snap_pie", {"type": 'X', "value": 'PRESS', "shift": True}),
*_template_items_context_menu("DOPESHEET_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
op_menu("DOPESHEET_MT_delete", {"type": 'BACK_SPACE', "value": 'PRESS'}),
op_menu("DOPESHEET_MT_delete", {"type": 'DEL', "value": 'PRESS'}),
("action.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
("action.duplicate_move", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
("action.keyframe_insert", {"type": 'S', "value": 'PRESS'}, None),
("action.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),

View File

@ -637,6 +637,8 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh);
void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object);
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
enum {

View File

@ -140,7 +140,11 @@ typedef struct UndoType {
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data);
bool use_context;
/**
* This undo type `encode` callback needs a valid context, it will fail otherwise.
* \note Callback is still supposed to properly deal with a NULL context pointer.
*/
bool use_context_for_encode;
/**
* The size of the undo struct 'inherited' from #UndoStep for that specific type. Used for

View File

@ -2021,6 +2021,51 @@ void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *su
BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg);
}
/**
* Ensures we do have expected mesh data in original mesh for the sculpt mode.
*
* \note IDs are expected to be original ones here, and calling code should ensure it updates its
* depsgraph properly after calling this function if it needs up-to-date evaluated data.
*/
void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
{
Mesh *mesh = BKE_mesh_from_object(object);
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, object);
BLI_assert(object->mode == OB_MODE_SCULPT);
/* Copy the current mesh visibility to the Face Sets. */
BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh);
if (object->sculpt != NULL) {
/* If a sculpt session is active, ensure we have its faceset data porperly up-to-date. */
object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
/* Note: In theory we could add that on the fly when required by sculpt code.
* But this then requires proper update of depsgraph etc. For now we play safe, optimization is
* always possible later if it's worth it. */
BKE_sculpt_mask_layers_ensure(object, mmd);
}
/* Tessfaces aren't used and will become invalid. */
BKE_mesh_tessface_clear(mesh);
/* We always need to flush updates from depsgraph here, since at the very least
* `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of
* the mesh.
*
* All known potential sources of updates:
* - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer
* (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`).
* - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
* - Object has any active modifier (modifier stack can be different in Sculpt mode).
* - Multires:
* + Differences of subdiv levels between sculpt and object modes
* (`mmd->sculptlvl != mmd->lvl`).
* + Addition of a `CD_GRID_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
*/
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
}
static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
{
PBVH *pbvh = BKE_pbvh_new();

View File

@ -501,6 +501,8 @@ UndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
const char *name,
const UndoType *ut)
{
BLI_assert(ut->use_context_for_encode == false || C != NULL);
UNDO_NESTED_ASSERT(false);
undosys_stack_validate(ustack, false);
bool is_not_empty = ustack->step_active != NULL;

View File

@ -669,6 +669,9 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
* Will use first clnors_data array, and fallback to cd_loop_clnors_offset
* (use NULL and -1 to not use clnors).
*
* \note This sets #BM_ELEM_TAG which is used in tool code (e.g. T84426).
* we could add a low-level API flag for this, see #BM_ELEM_API_FLAG_ENABLE and friends.
*/
static void bm_mesh_loops_calc_normals(BMesh *bm,
const float (*vcos)[3],
@ -1555,6 +1558,10 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
#endif
}
/**
* \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
* take care to run this before setting up tags.
*/
void BM_lnorspace_update(BMesh *bm)
{
if (bm->lnor_spacearr == NULL) {
@ -1889,6 +1896,10 @@ void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr)
MEM_freeN(lnors_ed_arr);
}
/**
* \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
* take care to run this before setting up tags.
*/
bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
{
BMFace *f;

View File

@ -239,6 +239,24 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
* Shape keys are also already integrated into the state of the evaluated
* mesh, so considering them here would kind of apply them twice. */
tot_shape_keys = BLI_listbase_count(&me->key->block);
/* Original meshes must never contain a shape-key custom-data layers.
*
* This may happen if and object's mesh data is accidentally
* set to the output from the modifier stack, causing it to be an "original" ID,
* even though the data isn't fully compatible (hence this assert).
*
* This results in:
* - The newly created #BMesh having twice the number of custom-data layers.
* - When converting the #BMesh back to a regular mesh,
* At least one of the extra shape-key blocks will be created in #Mesh.key
* depending on the value of #CustomDataLayer.uid.
*
* We could support mixing both kinds of data if there is a compelling use-case for it.
* At the moment it's simplest to assume all original meshes use the key-block and meshes
* that are evaluated (through the modifier stack for example) use custom-data layers.
*/
BLI_assert(!CustomData_has_layer(&me->vdata, CD_SHAPEKEY));
}
if (is_new == false) {
tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));

View File

@ -35,9 +35,9 @@ void SetAlphaMultiplyOperation::initExecution()
}
void SetAlphaMultiplyOperation::executePixelSampled(float output[4],
float x,
float y,
PixelSampler sampler)
float x,
float y,
PixelSampler sampler)
{
float color_input[4];
float alpha_input[4];

View File

@ -755,9 +755,9 @@ static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl,
}
static uint32_t gpencil_beztriple_vflag_get(char flag,
char col_id,
bool handle_point,
const bool handle_selected)
char col_id,
bool handle_point,
const bool handle_selected)
{
uint32_t vflag = 0;
SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED);

View File

@ -1203,7 +1203,12 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
* In this case the custom-data layers used wont always match in `me->runtime.batch_cache`.
* If we want to display regular mesh data, we should have a separate cache for the edit-mesh.
* See T77359. */
const bool is_editmode = (me->edit_mesh != NULL) /* && DRW_object_is_in_edit_mode(ob) */;
const bool is_editmode = (me->edit_mesh != NULL) &&
/* In rare cases we have the edit-mode data but not the generated cache.
* This can happen when switching an objects data to a mesh which
* happens to be in edit-mode in another scene, see: T82952. */
(me->edit_mesh->mesh_eval_final !=
NULL) /* && DRW_object_is_in_edit_mode(ob) */;
/* This could be set for paint mode too, currently it's only used for edit-mode. */
const bool is_mode_active = is_editmode && DRW_object_is_in_edit_mode(ob);

View File

@ -480,7 +480,7 @@ typedef struct DRWDebugSphere {
/* ------------- DRAW MANAGER ------------ */
#define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */
#define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
#define STENCIL_UNDEFINED 256
#define DRW_DRAWLIST_LEN 256

View File

@ -514,10 +514,10 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */
uint random = (DST.dupli_source) ?
DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
ob_infos->ob_random = random * (1.0f / (float)0xFFFFFFFF);
/* Object State. */
ob_infos->ob_flag = 1.0f; /* Required to have a correct sign */

View File

@ -249,7 +249,7 @@ void ED_armature_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = armature_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(ArmatureUndoStep);
}

View File

@ -309,7 +309,7 @@ void ED_curve_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(CurveUndoStep);
}

View File

@ -398,7 +398,7 @@ void ED_font_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(FontUndoStep);
}

View File

@ -283,7 +283,7 @@ void ED_lattice_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(LatticeUndoStep);
}

View File

@ -1790,6 +1790,8 @@ static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEdi
return false;
}
BM_custom_loop_normals_to_vector_layer(em->bm);
/* Flush from vertices to edges. */
BMIter iter;
BMEdge *eed;
@ -1809,8 +1811,6 @@ static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEdi
}
}
BM_custom_loop_normals_to_vector_layer(em->bm);
if (!EDBM_op_callf(em,
op,
"split_edges edges=%he verts=%hv use_verts=%b",
@ -5966,6 +5966,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
continue;
}
BM_custom_loop_normals_to_vector_layer(em->bm);
if (em->selectmode == SCE_SELECT_FACE) {
/* flush selection to tags and untag edges/verts with partially selected faces */
BMIter iter;
@ -5997,8 +5999,6 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
dissolve_flag = BM_ELEM_SELECT;
}
BM_custom_loop_normals_to_vector_layer(em->bm);
EDBM_op_call_and_selectf(
em,
op,

View File

@ -819,7 +819,7 @@ void ED_mesh_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = mesh_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(MeshUndoStep);
}

View File

@ -258,7 +258,7 @@ void ED_mball_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = mball_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(MBallUndoStep);
}

View File

@ -188,6 +188,80 @@ static const EnumPropertyItem align_options[] = {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Local Helpers
* \{ */
/**
* Operator properties for creating an object under a screen space (2D) coordinate.
* Used for object dropping like behavior (drag object and drop into 3D View).
*/
static void object_add_drop_xy_props(wmOperatorType *ot)
{
PropertyRNA *prop;
prop = RNA_def_int(ot->srna,
"drop_x",
0,
INT_MIN,
INT_MAX,
"Drop X",
"X-coordinate (screen space) to place the new object under",
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna,
"drop_y",
0,
INT_MIN,
INT_MAX,
"Drop Y",
"Y-coordinate (screen space) to place the new object under",
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
static bool object_add_drop_xy_is_set(const wmOperator *op)
{
return RNA_struct_property_is_set(op->ptr, "drop_x") &&
RNA_struct_property_is_set(op->ptr, "drop_y");
}
/**
* Query the currently set X- and Y-coordinate to position the new object under.
* \param r_mval: Returned pointer to the coordinate in region-space.
*/
static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int (*r_mval)[2])
{
if (!object_add_drop_xy_is_set(op)) {
(*r_mval)[0] = 0.0f;
(*r_mval)[1] = 0.0f;
return false;
}
const ARegion *region = CTX_wm_region(C);
(*r_mval)[0] = RNA_int_get(op->ptr, "drop_x") - region->winrct.xmin;
(*r_mval)[1] = RNA_int_get(op->ptr, "drop_y") - region->winrct.ymin;
return true;
}
/**
* Set the drop coordinate to the mouse position (if not already set) and call the operator's
* `exec()` callback.
*/
static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!object_add_drop_xy_is_set(op)) {
RNA_int_set(op->ptr, "drop_x", event->x);
RNA_int_set(op->ptr, "drop_y", event->y);
}
return op->type->exec(C, op);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public Add Object API
*
@ -1447,10 +1521,8 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
RNA_property_string_get(op->ptr, prop_name, name);
collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
if (!RNA_property_is_set(op->ptr, prop_location)) {
const wmEvent *event = CTX_wm_window(C)->eventstate;
ARegion *region = CTX_wm_region(C);
const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
int mval[2];
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
ED_object_location_from_view(C, loc);
ED_view3d_cursor3d_position(C, mval, false, loc);
RNA_property_float_set_array(op->ptr, prop_location, loc);
@ -1493,6 +1565,19 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int object_instance_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!object_add_drop_xy_is_set(op)) {
RNA_int_set(op->ptr, "drop_x", event->x);
RNA_int_set(op->ptr, "drop_y", event->y);
}
if (!RNA_struct_property_is_set(op->ptr, "name")) {
return WM_enum_search_invoke(C, op, event);
}
return op->type->exec(C, op);
}
/* only used as menu */
void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
@ -1504,7 +1589,7 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
ot->idname = "OBJECT_OT_collection_instance_add";
/* api callbacks */
ot->invoke = WM_enum_search_invoke;
ot->invoke = object_instance_add_invoke;
ot->exec = collection_instance_add_exec;
ot->poll = ED_operator_objectmode;
@ -1519,6 +1604,8 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
ED_object_add_generic_props(ot, false);
object_add_drop_xy_props(ot);
}
/** \} */
@ -1556,10 +1643,8 @@ static int object_data_instance_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (!RNA_property_is_set(op->ptr, prop_location)) {
const wmEvent *event = CTX_wm_window(C)->eventstate;
ARegion *region = CTX_wm_region(C);
const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
int mval[2];
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
ED_object_location_from_view(C, loc);
ED_view3d_cursor3d_position(C, mval, false, loc);
RNA_property_float_set_array(op->ptr, prop_location, loc);
@ -1591,6 +1676,7 @@ void OBJECT_OT_data_instance_add(wmOperatorType *ot)
ot->idname = "OBJECT_OT_data_instance_add";
/* api callbacks */
ot->invoke = object_add_drop_xy_generic_invoke;
ot->exec = object_data_instance_add_exec;
ot->poll = ED_operator_objectmode;
@ -1602,6 +1688,8 @@ void OBJECT_OT_data_instance_add(wmOperatorType *ot)
PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_id_type_items, 0, "Type", "");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
ED_object_add_generic_props(ot, false);
object_add_drop_xy_props(ot);
}
/** \} */
@ -3228,8 +3316,6 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
static int object_add_named_exec(bContext *C, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@ -3258,9 +3344,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op)
basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT;
if (event) {
ARegion *region = CTX_wm_region(C);
const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
int mval[2];
if (object_add_drop_xy_get(C, op, &mval)) {
ED_object_location_from_view(C, basen->object->loc);
ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
}
@ -3290,6 +3375,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot)
ot->idname = "OBJECT_OT_add_named";
/* api callbacks */
ot->invoke = object_add_drop_xy_generic_invoke;
ot->exec = object_add_named_exec;
ot->poll = ED_operator_objectmode;
@ -3302,6 +3388,8 @@ void OBJECT_OT_add_named(wmOperatorType *ot)
"Linked",
"Duplicate object but not object data, linking to the original data");
RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
object_add_drop_xy_props(ot);
}
/** \} */

View File

@ -190,6 +190,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
}
if (ob->mode == OB_MODE_SCULPT) {
BKE_sculpt_ensure_orig_mesh_data(CTX_data_scene(C), ob);
ED_sculpt_undo_geometry_end(ob);
}
@ -645,6 +646,7 @@ typedef struct QuadriFlowJob {
short *stop, *do_update;
float *progress;
Scene *scene;
int target_faces;
int seed;
bool use_mesh_symmetry;
@ -892,6 +894,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
}
if (ob->mode == OB_MODE_SCULPT) {
BKE_sculpt_ensure_orig_mesh_data(qj->scene, ob);
ED_sculpt_undo_geometry_end(ob);
}
@ -935,6 +938,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op)
QuadriFlowJob *job = MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob");
job->owner = CTX_data_active_object(C);
job->scene = CTX_data_scene(C);
job->target_faces = RNA_int_get(op->ptr, "target_faces");
job->seed = RNA_int_get(op->ptr, "seed");

View File

@ -299,7 +299,7 @@ void ED_particle_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = particle_undosys_foreach_ID_ref;
ut->use_context = true;
ut->use_context_for_encode = true;
ut->step_size = sizeof(ParticleUndoStep);
}

View File

@ -102,9 +102,12 @@ static bool paintcurve_undosys_step_encode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p)
{
if (C == NULL || !paint_curve_poll(C)) {
/* FIXME Double check this, it should not be needed here at all? undo system is supposed to
* ensure that. */
if (!paint_curve_poll(C)) {
return false;
}
Paint *p = BKE_paint_get_active_from_context(C);
PaintCurve *pc = p ? (p->brush ? p->brush->paint_curve : NULL) : NULL;
if (pc == NULL) {
@ -156,7 +159,7 @@ void ED_paintcurve_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = paintcurve_undosys_foreach_ID_ref;
ut->use_context = false;
ut->use_context_for_encode = false;
ut->step_size = sizeof(PaintCurveUndoStep);
}

View File

@ -8698,14 +8698,23 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
/**** Toggle operator for turning sculpt mode on or off ****/
/** \warning Expects a fully evaluated depsgraph. */
static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
/* Create persistent sculpt mode data. */
BKE_sculpt_toolsettings_data_ensure(scene);
/* Create sculpt mode session data. */
if (ob->sculpt != NULL) {
BKE_sculptsession_free(ob);
}
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
ob->sculpt->mode_type = OB_MODE_SCULPT;
BKE_sculpt_ensure_orig_mesh_data(scene, ob);
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
/* This function expects a fully evaluated depsgraph. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
/* Here we can detect geometry that was just added to Sculpt Mode as it has the
@ -8740,40 +8749,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
/* Enter sculpt mode. */
ob->mode |= mode_flag;
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
/* Create sculpt mode session data. */
if (ob->sculpt) {
BKE_sculptsession_free(ob);
}
/* Copy the current mesh visibility to the Face Sets. */
BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me);
/* Mask layer is required for Multires. */
BKE_sculpt_mask_layers_ensure(ob, mmd);
/* Tessfaces aren't used and will become invalid. */
BKE_mesh_tessface_clear(me);
/* We always need to flush updates from depsgraph here, since at the very least
* `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of
* the mesh.
*
* All known potential sources of updates:
* - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer
* (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`).
* - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
* - Object has any active modifier (modifier stack can be different in Sculpt mode).
* - Multires:
* + Differences of subdiv levels between sculpt and object modes
* (`mmd->sculptlvl != mmd->lvl`).
* + Addition of a `CD_GRID_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
*/
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
sculpt_init_session(depsgraph, scene, ob);
sculpt_init_session(bmain, depsgraph, scene, ob);
if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f &&
fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f)) {
@ -8792,6 +8768,8 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
* As long as no data was added that is not supported. */
if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
const char *message_unsupported = NULL;
if (me->totloop != me->totpoly * 3) {
message_unsupported = TIP_("non-triangle face");

View File

@ -1576,7 +1576,7 @@ void ED_sculpt_undosys_type(UndoType *ut)
ut->step_decode = sculpt_undosys_step_decode;
ut->step_free = sculpt_undosys_step_free;
ut->use_context = true;
ut->use_context_for_encode = false;
ut->step_size = sizeof(SculptUndoStep);
}

View File

@ -1036,12 +1036,13 @@ void ACTION_OT_delete(wmOperatorType *ot)
ot->description = "Remove all selected keyframes";
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->invoke = WM_operator_confirm_or_exec;
ot->exec = actkeys_delete_exec;
ot->poll = ED_operator_action_active;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_confirm_or_exec(ot);
}
/* ******************** Clean Keyframes Operator ************************* */

View File

@ -757,12 +757,13 @@ void GRAPH_OT_delete(wmOperatorType *ot)
ot->description = "Remove all selected keyframes";
/* API callbacks */
ot->invoke = WM_operator_confirm;
ot->invoke = WM_operator_confirm_or_exec;
ot->exec = graphkeys_delete_exec;
ot->poll = graphop_editable_keyframes_poll;
/* Flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
WM_operator_properties_confirm_or_exec(ot);
}
/** \} */

View File

@ -883,6 +883,7 @@ static bool image_undosys_step_encode(struct bContext *C,
}
}
else {
BLI_assert(C != NULL);
/* Happens when switching modes. */
ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
@ -995,7 +996,9 @@ void ED_image_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
ut->use_context = true;
/* NOTE this is actually a confusing case, since it expects a valid context, but only in a
* specific case, see `image_undosys_step_encode` code. */
ut->use_context_for_encode = false;
ut->step_size = sizeof(ImageUndoStep);
}

View File

@ -260,7 +260,7 @@ void ED_text_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
ut->use_context = false;
ut->use_context_for_encode = true;
ut->step_size = sizeof(TextUndoStep);
}

View File

@ -616,7 +616,6 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR);
drop->opcontext = WM_OP_EXEC_DEFAULT;
RNA_string_set(drop->ptr, "name", id->name + 2);
}

View File

@ -282,7 +282,7 @@ void ED_memfile_undosys_type(UndoType *ut)
ut->step_decode = memfile_undosys_step_decode;
ut->step_free = memfile_undosys_step_free;
ut->use_context = true;
ut->use_context_for_encode = false;
ut->step_size = sizeof(MemFileUndoStep);
}

View File

@ -152,6 +152,7 @@ struct PathSelectParams {
};
struct UserData_UV {
const SpaceImage *sima;
Scene *scene;
BMEditMesh *em;
uint cd_loop_uv_offset;
@ -239,7 +240,8 @@ static void looptag_set_cb(BMLoop *l, bool val, void *user_data_v)
}
}
static int mouse_mesh_uv_shortest_path_vert(Scene *scene,
static int mouse_mesh_uv_shortest_path_vert(const SpaceImage *sima,
Scene *scene,
Object *obedit,
const struct PathSelectParams *op_params,
BMLoop *l_src,
@ -281,6 +283,7 @@ static int mouse_mesh_uv_shortest_path_vert(Scene *scene,
}
struct UserData_UV user_data = {
.sima = sima,
.scene = scene,
.em = em,
.cd_loop_uv_offset = cd_loop_uv_offset,
@ -400,13 +403,15 @@ static bool facetag_test_cb(BMFace *f, void *user_data_v)
static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
{
struct UserData_UV *user_data = user_data_v;
const SpaceImage *sima = user_data->sima;
const Scene *scene = user_data->scene;
BMEditMesh *em = user_data->em;
const uint cd_loop_uv_offset = user_data->cd_loop_uv_offset;
uvedit_face_select_set(scene, em, f, val, false, cd_loop_uv_offset);
uvedit_face_select_set_with_sticky(sima, scene, em, f, val, false, cd_loop_uv_offset);
}
static int mouse_mesh_uv_shortest_path_face(Scene *scene,
static int mouse_mesh_uv_shortest_path_face(const SpaceImage *sima,
Scene *scene,
Object *obedit,
const struct PathSelectParams *op_params,
BMFace *f_src,
@ -419,6 +424,7 @@ static int mouse_mesh_uv_shortest_path_face(Scene *scene,
int flush = 0;
struct UserData_UV user_data = {
.sima = sima,
.scene = scene,
.em = em,
.cd_loop_uv_offset = cd_loop_uv_offset,
@ -497,7 +503,8 @@ static int mouse_mesh_uv_shortest_path_face(Scene *scene,
static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op);
static bool uv_shortest_path_pick_ex(Scene *scene,
static bool uv_shortest_path_pick_ex(const SpaceImage *sima,
Scene *scene,
Depsgraph *depsgraph,
Object *obedit,
const struct PathSelectParams *op_params,
@ -515,7 +522,8 @@ static bool uv_shortest_path_pick_ex(Scene *scene,
/* pass */
}
else if (ele_src->head.htype == BM_FACE) {
flush = mouse_mesh_uv_shortest_path_face(scene,
flush = mouse_mesh_uv_shortest_path_face(sima,
scene,
obedit,
op_params,
(BMFace *)ele_src,
@ -525,7 +533,8 @@ static bool uv_shortest_path_pick_ex(Scene *scene,
ok = true;
}
else if (ele_src->head.htype == BM_LOOP) {
flush = mouse_mesh_uv_shortest_path_vert(scene,
flush = mouse_mesh_uv_shortest_path_vert(sima,
scene,
obedit,
op_params,
(BMLoop *)ele_src,
@ -565,6 +574,7 @@ static bool uv_shortest_path_pick_ex(Scene *scene,
static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
const char uv_selectmode = ED_uvedit_select_mode_get(scene);
@ -671,7 +681,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
}
uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
sima, scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
/* To support redo. */
int index;
@ -695,6 +705,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
const SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const char uv_selectmode = ED_uvedit_select_mode_get(scene);
Object *obedit = CTX_data_edit_object(C);
@ -745,8 +756,15 @@ static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
path_select_params_from_op(op, &op_params);
op_params.track_active = true;
if (!uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset)) {
if (!uv_shortest_path_pick_ex(sima,
scene,
depsgraph,
obedit,
&op_params,
ele_src,
ele_dst,
aspect_y,
cd_loop_uv_offset)) {
return OPERATOR_CANCELLED;
}
@ -765,7 +783,7 @@ void UV_OT_shortest_path_pick(wmOperatorType *ot)
/* api callbacks */
ot->invoke = uv_shortest_path_pick_invoke;
ot->exec = uv_shortest_path_pick_exec;
ot->poll = ED_operator_uvedit;
ot->poll = ED_operator_uvedit_space_image;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -787,6 +805,7 @@ void UV_OT_shortest_path_pick(wmOperatorType *ot)
static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
const SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const char uv_selectmode = ED_uvedit_select_mode_get(scene);
bool found_valid_elements = false;
@ -835,8 +854,15 @@ static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
struct PathSelectParams op_params;
path_select_params_from_op(op, &op_params);
uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
uv_shortest_path_pick_ex(sima,
scene,
depsgraph,
obedit,
&op_params,
ele_src,
ele_dst,
aspect_y,
cd_loop_uv_offset);
found_valid_elements = true;
}
@ -861,7 +887,7 @@ void UV_OT_shortest_path_select(wmOperatorType *ot)
/* api callbacks */
ot->exec = uv_shortest_path_select_exec;
ot->poll = ED_operator_editmesh;
ot->poll = ED_operator_uvedit_space_image;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;

View File

@ -872,7 +872,7 @@ static void rna_def_bpoint(BlenderRNA *brna)
/* Boolean values */
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "f1", 0);
RNA_def_property_boolean_sdna(prop, NULL, "f1", SELECT);
RNA_def_property_ui_text(prop, "Select", "Selection status");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");

View File

@ -24,6 +24,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
@ -268,7 +269,7 @@ static void rna_def_latticepoint(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_LatticePoint_path");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "f1", 0);
RNA_def_property_boolean_sdna(prop, NULL, "f1", SELECT);
RNA_def_property_ui_text(prop, "Point selected", "Selection status");
prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION);

View File

@ -483,6 +483,17 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin
WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->owner_id);
}
void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *object = (Object *)ptr->data;
if (object->mode == OB_MODE_SCULPT) {
BKE_sculpt_ensure_orig_mesh_data(scene, object);
}
rna_Object_internal_update_data_dependency(bmain, scene, ptr);
}
static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
{
Object *ob = (Object *)ptr->data;
@ -2679,7 +2690,7 @@ static void rna_def_object(BlenderRNA *brna)
prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", "rna_Object_data_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Data", "Object data");
RNA_def_property_update(prop, 0, "rna_Object_internal_update_data_dependency");
RNA_def_property_update(prop, 0, "rna_Object_data_update");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");