diff options
Diffstat (limited to 'source/blender/editors/object')
18 files changed, 660 insertions, 75 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index eaef9313431..aabfa78cf58 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRC object_collection.c object_constraint.c object_data_transfer.c + object_data_transform.c object_edit.c object_facemap_ops.c object_gpencil_modifier.c @@ -57,6 +58,7 @@ set(SRC object_ops.c object_random.c object_relations.c + object_remesh.c object_select.c object_shader_fx.c object_shapekey.c diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 137af917f9a..80d150506ad 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -103,6 +103,7 @@ #include "ED_mesh.h" #include "ED_node.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_physics.h" #include "ED_render.h" #include "ED_screen.h" @@ -232,29 +233,17 @@ void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_ax } } -void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], const float rot[3]) +void ED_object_base_init_transform_on_add(Object *object, const float loc[3], const float rot[3]) { - Object *ob = base->object; - Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - - if (!scene) { - return; - } - if (loc) { - copy_v3_v3(ob->loc, loc); + copy_v3_v3(object->loc, loc); } if (rot) { - copy_v3_v3(ob->rot, rot); + copy_v3_v3(object->rot, rot); } - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_transform_copy(object_eval, ob); - BKE_object_where_is_calc(depsgraph, scene_eval, object_eval); - BKE_object_transform_copy(ob, object_eval); + BKE_object_to_mat4(object, object->obmat); } /* Uses context to figure out transform for primitive. @@ -494,7 +483,7 @@ Object *ED_object_add_type(bContext *C, ED_object_base_activate(C, view_layer->basact); /* more editor stuff */ - ED_object_base_init_transform(C, view_layer->basact, loc, rot); + ED_object_base_init_transform_on_add(ob, loc, rot); /* TODO(sergey): This is weird to manually tag objects for update, better to * use DEG_id_tag_update here perhaps. @@ -514,6 +503,8 @@ Object *ED_object_add_type(bContext *C, /* TODO(sergey): Use proper flag for tagging here. */ DEG_id_tag_update(&scene->id, 0); + ED_outliner_select_sync_from_object_tag(C); + return ob; } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 7343dba420f..14813f9a936 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -493,8 +493,12 @@ static void test_constraint( CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) { if (ct->tar) { + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the curve is missing). + * + * In other cases it should be impossible to have a type missmatch. + */ if (ct->tar->type != OB_CURVE) { - ct->tar = NULL; con->flag |= CONSTRAINT_DISABLE; } else { @@ -507,8 +511,12 @@ static void test_constraint( } else if (con->type == CONSTRAINT_TYPE_ARMATURE) { if (ct->tar) { + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the armature is missing). + * + * In other cases it should be impossible to have a type missmatch. + */ if (ct->tar->type != OB_ARMATURE) { - ct->tar = NULL; con->flag |= CONSTRAINT_DISABLE; } else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar), @@ -636,7 +644,7 @@ static const EnumPropertyItem constraint_owner_items[] = { static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ptr.data) { CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'"); @@ -648,7 +656,7 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) return 0; } - if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) { + if (ID_IS_LINKED(ob) || (ptr.owner_id && ID_IS_LINKED(ptr.owner_id))) { CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); return 0; } @@ -680,7 +688,7 @@ static void edit_constraint_properties(wmOperatorType *ot) static int edit_constraint_invoke_properties(bContext *C, wmOperator *op) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); bConstraint *con; ListBase *list; @@ -1422,14 +1430,14 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr static bool constraint_poll(bContext *C) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - return (ptr.id.data && ptr.data); + return (ptr.owner_id && ptr.data); } static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - Object *ob = ptr.id.data; + Object *ob = (Object *)ptr.owner_id; bConstraint *con = ptr.data; ListBase *lb = get_constraint_lb(ob, con, NULL); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 79aafc6978f..0a5db782892 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -495,12 +495,16 @@ static int data_transfer_exec(bContext *C, wmOperator *op) NULL, false, op->reports)) { + + if (data_type == DT_TYPE_LNOR && use_create) { + ((Mesh *)ob_dst->data)->flag |= ME_AUTOSMOOTH; + } + + DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY); changed = true; } } - DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY); - if (reverse_transfer) { SWAP(Object *, ob_src, ob_dst); } diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c new file mode 100644 index 00000000000..ee86c79ead5 --- /dev/null +++ b/source/blender/editors/object/object_data_transform.c @@ -0,0 +1,333 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup edobj + * + * Use to transform object origins only. + * + * This is a small API to store & apply transformations to object data, + * where a transformation matrix can be continually applied ontop of the original values + * so we don't loose precision over time. + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_collection_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_math.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "BKE_curve.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" +#include "BKE_armature.h" +#include "BKE_lattice.h" + +#include "DEG_depsgraph.h" + +#include "WM_types.h" + +#include "ED_object.h" + +#include "MEM_guardedalloc.h" + +/* -------------------------------------------------------------------- */ +/** \name Internal Transform Get/Apply + * + * Some object data types don't have utility functions to access their transformation data. + * Define these locally. + * + * \{ */ + +/* Armature */ + +struct ElemData_Armature { + float tail[3]; + float head[3]; + float roll; + float arm_tail[3]; + float arm_head[3]; + float arm_roll; + float rad_tail; + float rad_head; + float dist; + float xwidth; + float zwidth; +}; + +static struct ElemData_Armature *armature_coords_and_quats_get_recurse( + const ListBase *bone_base, struct ElemData_Armature *elem_array) +{ + struct ElemData_Armature *elem = elem_array; + for (const Bone *bone = bone_base->first; bone; bone = bone->next) { + +#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member)) +#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member)) + COPY_PTR(head); + COPY_PTR(tail); + COPY_VAL(roll); + COPY_PTR(arm_head); + COPY_PTR(arm_tail); + COPY_VAL(arm_roll); + COPY_VAL(rad_tail); + COPY_VAL(rad_head); + COPY_VAL(dist); + COPY_VAL(xwidth); + COPY_VAL(zwidth); +#undef COPY_PTR +#undef COPY_VAL + + elem = armature_coords_and_quats_get_recurse(&bone->childbase, elem + 1); + } + return elem; +} + +static void armature_coords_and_quats_get(const bArmature *arm, + struct ElemData_Armature *elem_array) +{ + armature_coords_and_quats_get_recurse(&arm->bonebase, elem_array); +} + +static const struct ElemData_Armature *armature_coords_and_quats_apply_with_mat4_recurse( + ListBase *bone_base, const struct ElemData_Armature *elem_array, const float mat[4][4]) +{ + const struct ElemData_Armature *elem = elem_array; + for (Bone *bone = bone_base->first; bone; bone = bone->next) { + +#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member)) +#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member)) + COPY_PTR(head); + COPY_PTR(tail); + COPY_VAL(roll); + COPY_PTR(arm_head); + COPY_PTR(arm_tail); + COPY_VAL(arm_roll); + COPY_VAL(rad_tail); + COPY_VAL(rad_head); + COPY_VAL(dist); + COPY_VAL(xwidth); + COPY_VAL(zwidth); +#undef COPY_PTR +#undef COPY_VAL + + elem = armature_coords_and_quats_apply_with_mat4_recurse(&bone->childbase, elem + 1, mat); + } + return elem; +} + +static void armature_coords_and_quats_apply_with_mat4(bArmature *arm, + const struct ElemData_Armature *elem_array, + const float mat[4][4]) +{ + armature_coords_and_quats_apply_with_mat4_recurse(&arm->bonebase, elem_array, mat); + BKE_armature_transform(arm, mat, true); +} + +/* MetaBall */ + +struct ElemData_MetaBall { + float co[3]; + float quat[4]; + float exp[3]; + float rad; +}; + +static void metaball_coords_and_quats_get(const MetaBall *mb, struct ElemData_MetaBall *elem_array) +{ + struct ElemData_MetaBall *elem = elem_array; + for (const MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) { + copy_v3_v3(elem->co, &ml->x); + copy_qt_qt(elem->quat, ml->quat); + copy_v3_v3(elem->exp, &ml->expx); + elem->rad = ml->rad; + } +} + +static void metaball_coords_and_quats_apply_with_mat4(MetaBall *mb, + const struct ElemData_MetaBall *elem_array, + const float mat[4][4]) +{ + const struct ElemData_MetaBall *elem = elem_array; + for (MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) { + copy_v3_v3(&ml->x, elem->co); + copy_qt_qt(ml->quat, elem->quat); + copy_v3_v3(&ml->expx, elem->exp); + ml->rad = elem->rad; + } + BKE_mball_transform(mb, mat, true); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Object Data Storage API + * + * Used for interactively transforming object data. + * + * Store object data transformation in an opaque struct. + * \{ */ + +struct XFormObjectData { + ID *id; +}; + +struct XFormObjectData_Mesh { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Lattice { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Curve { + struct XFormObjectData base; + float elem_array[0][3]; +}; + +struct XFormObjectData_Armature { + struct XFormObjectData base; + struct ElemData_Armature elem_array[0]; +}; + +struct XFormObjectData_MetaBall { + struct XFormObjectData base; + struct ElemData_MetaBall elem_array[0]; +}; + +struct XFormObjectData *ED_object_data_xform_create(ID *id) +{ + struct XFormObjectData *xod_base = NULL; + switch (GS(id->name)) { + case ID_ME: { + Mesh *me = (Mesh *)id; + const int elem_array_len = me->totvert; + struct XFormObjectData_Mesh *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_mesh_vert_coords_get(me, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_LT: { + Lattice *lt = (Lattice *)id; + const int elem_array_len = lt->pntsu * lt->pntsv * lt->pntsw; + struct XFormObjectData_Lattice *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_lattice_vert_coords_get(lt, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_CU: { + Curve *cu = (Curve *)id; + const short ob_type = BKE_curve_type_get(cu); + if (ob_type == OB_FONT) { + /* We could support translation. */ + break; + } + const int elem_array_len = BKE_nurbList_verts_count(&cu->nurb); + struct XFormObjectData_Curve *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_curve_nurbs_vert_coords_get(&cu->nurb, xod->elem_array, elem_array_len); + xod_base = &xod->base; + break; + } + case ID_AR: { + bArmature *arm = (bArmature *)id; + const int elem_array_len = BKE_armature_bonelist_count(&arm->bonebase); + struct XFormObjectData_Armature *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + armature_coords_and_quats_get(arm, xod->elem_array); + xod_base = &xod->base; + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)id; + const int elem_array_len = BLI_listbase_count(&mb->elems); + struct XFormObjectData_MetaBall *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + metaball_coords_and_quats_get(mb, xod->elem_array); + xod_base = &xod->base; + break; + } + default: { + break; + } + } + if (xod_base) { + xod_base->id = id; + } + return xod_base; +} + +void ED_object_data_xform_destroy(struct XFormObjectData *xod) +{ + MEM_freeN(xod); +} + +void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float mat[4][4]) +{ + switch (GS(xod_base->id->name)) { + case ID_ME: { + Mesh *me = (Mesh *)xod_base->id; + struct XFormObjectData_Mesh *xod = (struct XFormObjectData_Mesh *)xod_base; + BKE_mesh_vert_coords_apply_with_mat4(me, xod->elem_array, mat); + break; + } + case ID_LT: { + Lattice *lt = (Lattice *)xod_base->id; + struct XFormObjectData_Lattice *xod = (struct XFormObjectData_Lattice *)xod_base; + BKE_lattice_vert_coords_apply_with_mat4(lt, xod->elem_array, mat); + break; + } + case ID_CU: { + Curve *cu = (Curve *)xod_base->id; + struct XFormObjectData_Curve *xod = (struct XFormObjectData_Curve *)xod_base; + BKE_curve_nurbs_vert_coords_apply_with_mat4(&cu->nurb, xod->elem_array, mat, true); + break; + } + case ID_AR: { + bArmature *arm = (bArmature *)xod_base->id; + struct XFormObjectData_Armature *xod = (struct XFormObjectData_Armature *)xod_base; + armature_coords_and_quats_apply_with_mat4(arm, xod->elem_array, mat); + break; + } + case ID_MB: { + MetaBall *mb = (MetaBall *)xod_base->id; + struct XFormObjectData_MetaBall *xod = (struct XFormObjectData_MetaBall *)xod_base; + metaball_coords_and_quats_apply_with_mat4(mb, xod->elem_array, mat); + break; + } + default: { + break; + } + } +} + +/** \} */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index ed40a4eb948..0c2b5292716 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -116,6 +116,7 @@ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); +static ListBase selected_objects_get(bContext *C); /* ************* XXX **************** */ static void error(const char *UNUSED(arg)) @@ -593,7 +594,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag if (LIKELY(em)) { /* order doesn't matter */ EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); } WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL); @@ -1199,7 +1200,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(ob, !clear); + BKE_mesh_smooth_flag_set(ob->data, !clear); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -1460,6 +1461,23 @@ void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static ListBase selected_objects_get(bContext *C) +{ + ListBase objects = {NULL}; + + if (CTX_wm_space_outliner(C) != NULL) { + ED_outliner_selected_objects_get(C, &objects); + } + else { + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + BLI_addtail(&objects, BLI_genericNodeN(ob)); + } + CTX_DATA_END; + } + + return objects; +} + static bool move_to_collection_poll(bContext *C) { if (CTX_wm_space_outliner(C) != NULL) { @@ -1472,7 +1490,7 @@ static bool move_to_collection_poll(bContext *C) return false; } - return ED_operator_object_active_editable(C); + return ED_operator_objectmode(C); } } @@ -1498,15 +1516,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (CTX_wm_space_outliner(C) != NULL) { - ED_outliner_selected_objects_get(C, &objects); - } - else { - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - BLI_addtail(&objects, BLI_genericNodeN(ob)); - } - CTX_DATA_END; - } + objects = selected_objects_get(C); if (is_new) { char new_collection_name[MAX_NAME]; @@ -1650,6 +1660,13 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent { Scene *scene = CTX_data_scene(C); + ListBase objects = selected_objects_get(C); + if (BLI_listbase_is_empty(&objects)) { + BKE_report(op->reports, RPT_ERROR, "No objects selected"); + return OPERATOR_CANCELLED; + } + BLI_freelistN(&objects); + /* Reset the menus data for the current master collection, and free previously allocated data. */ move_to_collection_menus_free(&master_collection_menu); diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 075cd5acad6..9138e65dd2f 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -390,7 +390,7 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot) static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ob || ID_IS_LINKED(ob)) { return 0; @@ -398,7 +398,7 @@ static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 15c5ea40991..bcbf7ddf9a6 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -352,7 +352,7 @@ static bool object_hook_index_array(Main *bmain, em = me->edit_mesh; EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); /* check selected vertices first */ if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) { @@ -436,7 +436,7 @@ static void object_hook_from_context( HookModifierData *hmd; if (ptr->data) { /* if modifier context is available, use that */ - ob = ptr->id.data; + ob = (Object *)ptr->owner_id; hmd = ptr->data; } else { /* use the provided property */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index e697c25b37f..4b369c10e4d 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -279,6 +279,9 @@ void OBJECT_OT_bake(wmOperatorType *ot); /* object_random.c */ void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot); +/* object_remesh.c */ +void OBJECT_OT_voxel_remesh(struct wmOperatorType *ot); + /* object_transfer_data.c */ void OBJECT_OT_data_transfer(struct wmOperatorType *ot); void OBJECT_OT_datalayout_transfer(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 271d8effd30..80e7e6312aa 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -186,6 +186,19 @@ void ED_object_mode_set(bContext *C, eObjectMode mode) wm->op_undo_depth--; } +void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph) +{ + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + FOREACH_OBJECT_BEGIN (view_layer, ob) { + if (ob->mode & OB_MODE_ALL_MODE_DATA) { + ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); + } + } + FOREACH_OBJECT_END; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 8818fd71190..f77d9874c06 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -714,9 +714,9 @@ static int modifier_apply_obdata( RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); - vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts); + vertexCos = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts); mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); - BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos); + BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false); MEM_freeN(vertexCos); @@ -918,7 +918,7 @@ bool edit_modifier_poll_generic(bContext *C, const bool is_editmode_allowed) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ob || ID_IS_LINKED(ob)) { return 0; @@ -926,7 +926,7 @@ bool edit_modifier_poll_generic(bContext *C, if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index b653c7fa70c..38c06319450 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -257,6 +257,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_hide_view_clear); WM_operatortype_append(OBJECT_OT_hide_view_set); WM_operatortype_append(OBJECT_OT_hide_collection); + + WM_operatortype_append(OBJECT_OT_voxel_remesh); } void ED_operatormacros_object(void) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index a69f4872e72..67364f275dd 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -149,7 +149,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) em = me->edit_mesh; EDBM_mesh_normals_update(em); - BKE_editmesh_tessface_calc(em); + BKE_editmesh_looptri_calc(em); /* Make sure the evaluated mesh is updated. * @@ -1744,7 +1744,7 @@ static Collection *single_object_users_collection(Main *bmain, } /* Since master collection has already be duplicated as part of scene copy, - * we do not duplictae it here. + * we do not duplicate it here. * However, this means its children need to be re-added manually here, * otherwise their parent lists are empty (which will lead to crashes, see T63101). */ CollectionChild *child_next, *child = collection->children.first; @@ -2471,7 +2471,11 @@ static int make_override_library_exec(bContext *C, wmOperator *op) DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } /* parent to 'collection' empty */ - if (new_ob->parent == NULL) { + /* Disabled for now, according to some artist this is probably not really useful anyway. + * And it breaks things like objects parented to bones + * (most likely due to missing proper setting of inverse parent matrix?)... */ + /* Note: we might even actually want to get rid of that instanciating empty... */ + if (0 && new_ob->parent == NULL) { new_ob->parent = obcollection; } if (new_ob == (Object *)obact->id.newid) { @@ -2706,7 +2710,7 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - id = pprop.ptr.id.data; + id = pprop.ptr.owner_id; if (GS(id->name) == ID_OB) { Object *ob = (Object *)id; diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c new file mode 100644 index 00000000000..5f464084a9b --- /dev/null +++ b/source/blender/editors/object/object_remesh.c @@ -0,0 +1,158 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation + * All rights reserved. + */ + +/** \file + * \ingroup edobj + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> +#include <ctype.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_customdata.h" +#include "BKE_mesh_remesh_voxel.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + +#include "ED_mesh.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_sculpt.h" +#include "ED_undo.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "WM_message.h" +#include "WM_toolsystem.h" + +#include "object_intern.h" // own include + +static bool object_remesh_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + + if (BKE_object_is_in_editmode(ob)) { + CTX_wm_operator_poll_msg_set(C, "The voxel remesher cannot run from edit mode."); + return false; + } + + if (ob->mode == OB_MODE_SCULPT && ob->sculpt->bm) { + CTX_wm_operator_poll_msg_set(C, "The voxel remesher cannot run with dyntopo activated."); + } + + return ED_operator_object_active_editable_mesh(C); +} + +static int voxel_remesh_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + Main *bmain = CTX_data_main(C); + + Mesh *mesh = ob->data; + Mesh *new_mesh; + + if (mesh->remesh_voxel_size <= 0.0f) { + BKE_report(op->reports, RPT_ERROR, "Voxel remesher cannot run with a voxel size of 0.0."); + return OPERATOR_CANCELLED; + } + + if (ob->mode == OB_MODE_SCULPT) { + ED_sculpt_undo_geometry_begin(ob); + } + + new_mesh = BKE_mesh_remesh_voxel_to_mesh_nomain(mesh, mesh->remesh_voxel_size); + + if (!new_mesh) { + return OPERATOR_CANCELLED; + } + + Mesh *obj_mesh_copy = NULL; + if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) { + obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0); + CustomData_copy( + &mesh->vdata, &obj_mesh_copy->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert); + for (int i = 0; i < mesh->totvert; i++) { + copy_v3_v3(obj_mesh_copy->mvert[i].co, mesh->mvert[i].co); + } + } + + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + + if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) { + BKE_remesh_reproject_paint_mask(mesh, obj_mesh_copy); + BKE_mesh_free(obj_mesh_copy); + } + + if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { + BKE_mesh_smooth_flag_set(ob->data, true); + } + + if (ob->mode == OB_MODE_SCULPT) { + ED_sculpt_undo_geometry_end(ob); + } + + BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_voxel_remesh(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Voxel Remesh"; + ot->description = + "Calculates a new manifold mesh based on the volume of the current mesh. All data layers " + "will be lost"; + ot->idname = "OBJECT_OT_voxel_remesh"; + + /* api callbacks */ + ot->poll = object_remesh_poll; + ot->exec = voxel_remesh_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index da06707ebac..28242b986f1 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -69,6 +69,7 @@ #include "ED_armature.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_select_utils.h" #include "ED_keyframing.h" @@ -436,6 +437,8 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -717,6 +720,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) if (changed) { DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; } @@ -1100,6 +1104,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) if (changed) { DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; } @@ -1150,6 +1155,8 @@ static int object_select_all_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else if (any_visible == false) { @@ -1218,6 +1225,8 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -1281,6 +1290,8 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -1369,6 +1380,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else { @@ -1399,6 +1413,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } else { @@ -1448,6 +1465,8 @@ static int object_select_random_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 6212269c099..db0c8c54186 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -282,8 +282,9 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot) ot->prop = RNA_def_enum( ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", ""); RNA_def_enum_funcs(ot->prop, shaderfx_add_itemf); - RNA_def_property_translation_context(ot->prop, - BLT_I18NCONTEXT_ID_ID); /* Abused, for "Light"... */ + + /* Abused, for "Light"... */ + RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID); } /* -------------------------------------------------------------------- */ @@ -293,7 +294,7 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot) static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) { PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type); - Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); + Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); if (!ptr.data) { CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'"); @@ -306,7 +307,7 @@ static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obt if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { return 0; } - if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) { + if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { return 0; } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 5934eab62bb..2a8b306b085 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -77,7 +77,9 @@ #include "object_intern.h" -/*************************** Clear Transformation ****************************/ +/* -------------------------------------------------------------------- */ +/** \name Clear Transformation Utilities + * \{ */ /* clear location of object */ static void object_clear_loc(Object *ob, const bool clear_delta) @@ -284,8 +286,6 @@ static void object_clear_scale(Object *ob, const bool clear_delta) } } -/* --------------- */ - /* generic exec for clear-transform operators */ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, @@ -329,7 +329,11 @@ static int object_clear_transform_generic_exec(bContext *C, return OPERATOR_FINISHED; } -/* --------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Location Operator + * \{ */ static int object_location_clear_exec(bContext *C, wmOperator *op) { @@ -359,6 +363,12 @@ void OBJECT_OT_location_clear(wmOperatorType *ot) "Clear delta location in addition to clearing the normal location transform"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Rotation Operator + * \{ */ + static int object_rotation_clear_exec(bContext *C, wmOperator *op) { return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID); @@ -387,6 +397,12 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot) "Clear delta rotation in addition to clearing the normal rotation transform"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Scale Operator + * \{ */ + static int object_scale_clear_exec(bContext *C, wmOperator *op) { return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID); @@ -415,7 +431,11 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot) "Clear delta scale in addition to clearing the normal scale transform"); } -/* --------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Origin Operator + * \{ */ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -457,7 +477,11 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/*************************** Apply Transformation ****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply Transformation Operator + * \{ */ /* use this when the loc/size/rot of the parent has changed but the children * should stay in the same place, e.g. for apply-size-rot or object center */ @@ -744,7 +768,8 @@ static int apply_objects_internal(bContext *C, BKE_mesh_calc_normals(me); } else if (ob->type == OB_ARMATURE) { - ED_armature_transform_apply(bmain, ob, mat, do_props); + bArmature *arm = ob->data; + BKE_armature_transform(arm, mat, do_props); } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; @@ -960,7 +985,11 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) "Modify properties such as curve vertex radius, font size and bone envelope"); } -/********************* Set Object Center ************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Object Center Operator + * \{ */ enum { GEOMETRY_TO_ORIGIN = 0, @@ -1152,7 +1181,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_curve_center_median(cu, cent); @@ -1244,7 +1274,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_mball_center_median(mb, cent); @@ -1270,7 +1301,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ + if (centermode == ORIGIN_TO_CURSOR) { + /* done */ } else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_lattice_center_median(lt, cent); @@ -1323,11 +1355,6 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) invert_m4_m4(inverse_diff_mat, diff_mat); for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float mpt[3]; mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x); @@ -1337,12 +1364,13 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } } } - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - tot_change++; if (centermode == ORIGIN_TO_GEOMETRY) { copy_v3_v3(ob->loc, gpcenter); } + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + ob->id.tag |= LIB_TAG_DOIT; do_inverse_offset = true; } @@ -1508,6 +1536,8 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", ""); } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Transform Axis Target * diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index a43ac59c9b8..08fe5e818b2 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1139,7 +1139,7 @@ static bool vgroup_normalize(Object *ob) int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return false; @@ -1623,7 +1623,7 @@ static bool vgroup_normalize_all(Object *ob, int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); if (subset_count == 0) { BKE_report(reports, RPT_ERROR, "No vertex groups to operate on"); @@ -2047,7 +2047,7 @@ static int vgroup_limit_total_subset(Object *ob, { MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); int remove_tot = 0; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); |