[Bf-blender-cvs] [b827ca7] override_static: Final bits to get first (very raw, limited and experimental) override working.

Bastien Montagne noreply at git.blender.org
Wed Dec 14 16:10:33 CET 2016


Commit: b827ca78c781a3962e049a439b838eab4020576a
Author: Bastien Montagne
Date:   Mon Dec 12 13:59:49 2016 +0100
Branches: override_static
https://developer.blender.org/rBb827ca78c781a3962e049a439b838eab4020576a

Final bits to get first (very raw, limited and experimental) override working.

Mostly code using override data to selectively update a copy of linked one
with local data.

As said, still totally hackish and experimental, but it works - you can
create overrides of linked Objects, and override their position, yeha! :P

===================================================================

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/BKE_library_override.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/library_override.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/rna_access.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 2d9c35f..26f9b83 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -85,6 +85,7 @@ void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_
 bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
 bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
 bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
+void BKE_id_swap(struct ID *id_a, struct ID *id_b);
 void id_sort_by_name(struct ListBase *lb, struct ID *id);
 void BKE_id_expand_local(struct ID *id);
 void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h
index c26155a..1fb4b92 100644
--- a/source/blender/blenkernel/BKE_library_override.h
+++ b/source/blender/blenkernel/BKE_library_override.h
@@ -44,7 +44,10 @@ void BKE_override_free(struct IDOverride **override);
 bool BKE_override_status_check_local(struct ID *local);
 bool BKE_override_status_check_reference(struct ID *local);
 
-bool BKE_override_synchronize_update(struct ID *local);
+bool BKE_override_operations_update(struct ID *local);
+
+void BKE_override_update(struct ID *local);
+void BKE_main_override_update(struct Main *bmain);
 
 
 #endif  /* __BKE_LIBRARY_OVERRIDE_H__ */
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 65f37d0..b0d60ff 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -582,6 +582,69 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
 	return false;
 }
 
+/** Does a mere memory swap over the whole IDs data (including type-specific memory).
+ *  \note Most internal ID data itself is not swapped (only IDProperties are). */
+void BKE_id_swap(ID *id_a, ID *id_b)
+{
+	BLI_assert(GS(id_a->name) == GS(id_b->name));
+
+	const ID id_a_back = *id_a;
+	const ID id_b_back = *id_b;
+
+#define CASE_SWAP(_gs, _type) \
+	case _gs: \
+		SWAP(_type, *(_type *)id_a, *(_type *)id_b); \
+		break
+
+	switch ((ID_Type)GS(id_a->name)) {
+		CASE_SWAP(ID_SCE, Scene);
+		CASE_SWAP(ID_LI, Library);
+		CASE_SWAP(ID_OB, Object);
+		CASE_SWAP(ID_ME, Mesh);
+		CASE_SWAP(ID_CU, Curve);
+		CASE_SWAP(ID_MB, MetaBall);
+		CASE_SWAP(ID_MA, Material);
+		CASE_SWAP(ID_TE, Tex);
+		CASE_SWAP(ID_IM, Image);
+		CASE_SWAP(ID_LT, Lattice);
+		CASE_SWAP(ID_LA, Lamp);
+		CASE_SWAP(ID_CA, Camera);
+		CASE_SWAP(ID_KE, Key);
+		CASE_SWAP(ID_WO, World);
+		CASE_SWAP(ID_SCR, bScreen);
+		CASE_SWAP(ID_VF, VFont);
+		CASE_SWAP(ID_TXT, Text);
+		CASE_SWAP(ID_SPK, Speaker);
+		CASE_SWAP(ID_SO, bSound);
+		CASE_SWAP(ID_GR, Group);
+		CASE_SWAP(ID_AR, bArmature);
+		CASE_SWAP(ID_AC, bAction);
+		CASE_SWAP(ID_NT, bNodeTree);
+		CASE_SWAP(ID_BR, Brush);
+		CASE_SWAP(ID_PA, ParticleSettings);
+		CASE_SWAP(ID_WM, wmWindowManager);
+		CASE_SWAP(ID_GD, bGPdata);
+		CASE_SWAP(ID_MC, MovieClip);
+		CASE_SWAP(ID_MSK, Mask);
+		CASE_SWAP(ID_LS, FreestyleLineStyle);
+		CASE_SWAP(ID_PAL, Palette);
+		CASE_SWAP(ID_PC, PaintCurve);
+		CASE_SWAP(ID_CF, CacheFile);
+		case ID_IP:
+			break;  /* Deprecated. */
+	}
+
+#undef CASE_SWAP
+
+	/* Restore original ID's internal data. */
+	*id_a = id_a_back;
+	*id_b = id_b_back;
+
+	/* Exception: IDProperties. */
+	id_a->properties = id_b_back.properties;
+	id_b->properties = id_a_back.properties;
+}
+
 /** Does *not* set ID->newid pointer. */
 bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
 {
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c
index 07938e6..14528d3 100644
--- a/source/blender/blenkernel/intern/library_override.c
+++ b/source/blender/blenkernel/intern/library_override.c
@@ -33,8 +33,10 @@
 
 #include "DNA_ID.h"
 
+#include "BKE_global.h"  /* XXX Yuck! temp hack! */
 #include "BKE_library.h"
 #include "BKE_library_override.h"
+#include "BKE_main.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_listbase.h"
@@ -163,10 +165,73 @@ bool BKE_override_status_check_reference(ID *local)
 /** Compares local and reference data-blocks and create new override operations as needed,
  * or reset to reference values if overriding is not allowed.
  * \return true is new overriding op was created, or some local data was reset. */
-bool BKE_override_synchronize_update(ID *local)
+bool BKE_override_operations_update(ID *local)
 {
 	BLI_assert(local->override != NULL);
 	return false;
 }
+#include "DNA_object_types.h"
+/** Update given override from its reference (not touching to overriden properties). */
+void BKE_override_update(ID *local)
+{
+	if (local->override == NULL) {
+		return;
+	}
+
+	/* Recursively do 'ancestors' overrides first, if any. */
+	if (local->override->reference->override) {
+		BKE_override_update(local->override->reference);
+	}
+
+	/* We want to avoid having to remap here, however creating up-to-date override is much simpler if based
+	 * on reference than on current override.
+	 * So we work on temp copy of reference. */
+
+	/* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)!
+	 *     However, this is whole bunch of code work in itself, so for now plain stupid ID copy will do,
+	 *     as innefficient as it is. :/
+	 *     Actually, maybe not! Since we are swapping with original ID's local content, we want to keep
+	 *     usercount in correct state when freeing tmp_id (and that usercounts of IDs used by 'new' local data
+	 *     also remain correct). */
+
+	ID *tmp_id;
+	id_copy(G.main, local->override->reference, &tmp_id, false);  /* XXX ...and worse of all, this won't work with scene! */
+
+	if (tmp_id == NULL) {
+		return;
+	}
+
+	PointerRNA rnaptr_local, rnaptr_data;
+	RNA_id_pointer_create(local, &rnaptr_local);
+	RNA_id_pointer_create(tmp_id, &rnaptr_data);
 
+	RNA_struct_override_update(&rnaptr_local, &rnaptr_data, local->override);
 
+	/* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa. So when we'll free tmp_id,
+	 * we'll actually free old, outdated data from local. */
+	BKE_id_swap(local, tmp_id);
+
+	/* Again, horribly innefficient in our case, we need something off-Main and off-usercounting
+	 * (aka moar generic nolib copy/free stuff)! */
+	BKE_libblock_free_ex(G.main, tmp_id, true, false);
+}
+
+/** Update all overrides from given \a bmain. */
+void BKE_main_override_update(Main *bmain)
+{
+	ListBase *lbarray[MAX_LIBARRAY];
+	int base_count, i;
+
+	base_count = set_listbasepointers(bmain, lbarray);
+
+	for (i = 0; i < base_count; i++) {
+		ListBase *lb = lbarray[i];
+		ID *id;
+
+		for (id = lb->first; id; id = id->next) {
+			if (id->override != NULL && id->lib == NULL) {
+				BKE_override_update(id);
+			}
+		}
+	}
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index b57b720..651d2c8 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -127,6 +127,7 @@
 #include "BKE_group.h"
 #include "BKE_library.h" // for which_libbase
 #include "BKE_library_idmap.h"
+#include "BKE_library_override.h"
 #include "BKE_library_query.h"
 #include "BKE_idcode.h"
 #include "BKE_material.h"
@@ -8621,6 +8622,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
 	blo_join_main(&mainlist);
 	
 	lib_link_all(fd, bfd->main);
+
+	/* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */
+	BKE_main_override_update(bfd->main);
+
 	//do_versions_after_linking(fd, NULL, bfd->main); // XXX: not here (or even in this function at all)! this causes crashes on many files - Aligorith (July 04, 2010)
 	lib_verify_nodetree(bfd->main, true);
 	fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 2913477..0d64a8d 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -1217,6 +1217,8 @@ bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNAEqualsMod
 bool RNA_struct_override_matches(struct PointerRNA *local, struct PointerRNA *reference,
         struct IDOverride *override, const bool ignore_non_overridable, const bool ignore_overridden);
 
+void RNA_struct_override_update(struct PointerRNA *src, struct PointerRNA *dst, struct IDOverride *override);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index f0c3bca..b37dbb5 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -7127,6 +7127,30 @@ bool RNA_struct_override_matches(
 	return equals;
 }
 
+void RNA_struct_override_update(PointerRNA *src, PointerRNA *dst, IDOverride *override)
+{
+	for (IDOverrideProperty *op = override->properties.first; op; op = op->next) {
+		/* Simplified for now! */
+		PointerRNA src_data, dst_data;
+		PropertyRNA *src_prop, *dst_prop;
+
+		if (RNA_path_resolve_property(src, op->rna_path, &src_data, &src_prop) &&
+		    RNA_path_resolve_property(dst, op->rna_path, &dst_data, &dst_prop))
+		{
+			BLI_assert(src_prop == dst_prop);
+
+			for (IDOverridePropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+				switch (opop->operation) {
+					case IDOVERRIDE_REPLACE:
+						RNA_property_copy(&dst_data, &src_data, src_prop, -1);
+						break;
+					/* TODO other cases! */
+				}
+			}
+		}
+	}
+}
+
 
 bool RNA_path_resolved_create(
         PointerRNA *ptr, struct PropertyRNA *prop,




More information about the Bf-blender-cvs mailing list