Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
committerAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
commit2204bfcf9e1c3a38e60830bd97775dd72158f4d6 (patch)
tree4f9c827389a23a431f8771b4ca02f410860c0242 /source/blender/editors/object/object_add.c
parentf64db794ee690f05905ace0a66d81d2e75549b90 (diff)
parent34ad6da4a06ef46cd19945f61cc5f968538546a8 (diff)
Merge branch 'master' into temp-gpencil-drw-engine
Diffstat (limited to 'source/blender/editors/object/object_add.c')
-rw-r--r--source/blender/editors/object/object_add.c161
1 files changed, 114 insertions, 47 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 0fdb1cec16f..f8cf55933aa 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1658,54 +1658,80 @@ static void copy_object_set_idnew(bContext *C)
/** \name Make Instanced Objects Real Operator
* \{ */
+/* XXX TODO That whole hierarchy handling based on persistent_id tricks is
+ * very confusing and convoluted, and it will fail in many cases besides basic ones.
+ * Think this should be replaced by a proper tree-like representation of the instantiations,
+ * should help a lot in both readability, and precise consistent rebuilding of hierarchy.
+ */
+
/**
- * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * \note regarding hashing dupli-objects which come from OB_DUPLICOLLECTION,
* skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same
* dupli-group instance.
+ *
+ * \note regarding hashing dupli-objects which come from non-OB_DUPLICOLLECTION,
+ * include the first member of #DupliObject.persistent_id
+ * since its the index of the vertex/face the object is instantiated on and we want to identify
+ * objects on the same vertex/face.
+ * In other words, we consider each group of objects from a same item as being
+ * the 'local group' where to check for parents.
*/
-static unsigned int dupliobject_group_hash(const void *ptr)
+static unsigned int dupliobject_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- unsigned int i;
- for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
- hash ^= (dob->persistent_id[i] ^ i);
+
+ if (dob->type == OB_DUPLICOLLECTION) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ }
+ else {
+ hash ^= (dob->persistent_id[0] ^ 0);
}
return hash;
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION,
- * include the first member of #DupliObject.persistent_id
- * since its the index of the vertex/face the object is instantiated on and we want to identify
- * objects on the same vertex/face.
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * skip the first member of #DupliObject.persistent_id
+ * since its a unique index and we only want to know if the group objects are from the same
+ * dupli-group instance.
*/
-static unsigned int dupliobject_hash(const void *ptr)
+static unsigned int dupliobject_instancer_hash(const void *ptr)
{
const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- hash ^= (dob->persistent_id[0] ^ 0);
+ unsigned int hash = BLI_ghashutil_inthash(dob->persistent_id[0]);
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
return hash;
}
-/* Compare function that matches dupliobject_group_hash */
-static bool dupliobject_group_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_hash */
+static bool dupliobject_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- unsigned int i;
if (a->ob != b->ob) {
return true;
}
- for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
- if (a->persistent_id[i] != b->persistent_id[i]) {
- return true;
+ if (ELEM(a->type, b->type, OB_DUPLICOLLECTION)) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
- else if (a->persistent_id[i] == INT_MAX) {
- break;
+ }
+ else {
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
}
}
@@ -1713,18 +1739,19 @@ static bool dupliobject_group_cmp(const void *a_, const void *b_)
return false;
}
-/* Compare function that matches dupliobject_hash */
-static bool dupliobject_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_instancer_hash. */
+static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- if (a->ob != b->ob) {
- return true;
- }
-
- if (a->persistent_id[0] != b->persistent_id[0]) {
- return true;
+ for (int i = 0; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
/* matching */
@@ -1739,7 +1766,7 @@ static void make_object_duplilist_real(
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase *lb_duplis;
DupliObject *dob;
- GHash *dupli_gh, *parent_gh = NULL;
+ GHash *dupli_gh, *parent_gh = NULL, *instancer_gh = NULL;
if (!(base->object->transflag & OB_DUPLI)) {
return;
@@ -1750,11 +1777,11 @@ static void make_object_duplilist_real(
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+
+ if (use_base_parent) {
+ instancer_gh = BLI_ghash_new(
+ dupliobject_instancer_hash, dupliobject_instancer_cmp, __func__);
}
}
@@ -1788,7 +1815,12 @@ static void make_object_duplilist_real(
ob_dst->parent = NULL;
BKE_constraints_free(&ob_dst->constraints);
ob_dst->runtime.curve_cache = NULL;
+ const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0;
ob_dst->transflag &= ~OB_DUPLI;
+ /* Remove instantiated collection, it's annoying to keep it here
+ * (and get potentially a lot of usages of it then...). */
+ id_us_min((ID *)ob_dst->instance_collection);
+ ob_dst->instance_collection = NULL;
copy_m4_m4(ob_dst->obmat, dob->mat);
BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
@@ -1802,6 +1834,13 @@ static void make_object_duplilist_real(
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
*val = ob_dst;
}
+
+ if (is_dupli_instancer && instancer_gh) {
+ /* Same as above, we may have several 'hits'. */
+ if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) {
+ *val = ob_dst;
+ }
+ }
}
}
@@ -1825,7 +1864,8 @@ static void make_object_duplilist_real(
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLICOLLECTION) {
+ dob_key.type = dob->type;
+ if (dob->type == OB_DUPLICOLLECTION) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1848,15 +1888,30 @@ static void make_object_duplilist_real(
ob_dst->parent = ob_dst_par;
}
- else if (use_base_parent) {
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
}
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- ob_dst->parent = base->object;
+ if (use_base_parent && ob_dst->parent == NULL) {
+ Object *ob_dst_par = NULL;
+
+ if (instancer_gh != NULL) {
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ /* We are looking one step upper in hierarchy, so we need to 'shift' the persitent_id,
+ * ignoring the first item.
+ * We only check on persistent_id here, since we have no idea what object it might be. */
+ memcpy(&dob_key.persistent_id[0],
+ &dob->persistent_id[1],
+ sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
+ ob_dst_par = BLI_ghash_lookup(instancer_gh, &dob_key);
+ }
+
+ if (ob_dst_par == NULL) {
+ /* Default to parenting to root object...
+ * Always the case when use_hierarchy is false. */
+ ob_dst_par = base->object;
+ }
+
+ ob_dst->parent = ob_dst_par;
ob_dst->partype = PAROBJECT;
}
@@ -1878,12 +1933,16 @@ static void make_object_duplilist_real(
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
}
+ base->object->instance_collection = NULL;
}
BLI_ghash_free(dupli_gh, NULL, NULL);
if (parent_gh) {
BLI_ghash_free(parent_gh, NULL, NULL);
}
+ if (instancer_gh) {
+ BLI_ghash_free(instancer_gh, NULL, NULL);
+ }
free_object_duplilist(lb_duplis);
@@ -1977,7 +2036,13 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Curve *curve = ob->data;
+
Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
+ if (mesh == NULL) {
+ /* Unable to convert the curve to a mesh. */
+ return;
+ }
+
BKE_object_free_modifiers(ob, 0);
/* Replace curve used by the object itself. */
ob->data = mesh;
@@ -2066,7 +2131,7 @@ static Base *duplibase_for_convert(
static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *basen = NULL, *basact = NULL;
@@ -2285,8 +2350,9 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2309,8 +2375,9 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2826,7 +2893,7 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Join as Shapes";
- ot->description = "Merge selected objects to shapes of active object";
+ ot->description = "Copy the current resulting shape of another selected object to this one";
ot->idname = "OBJECT_OT_join_shapes";
/* api callbacks */