Browse Source

Implement a cleaner (and better) way to save imagedata from ImageTexture, fixes #18801

Juan Linietsky 6 years ago
parent
commit
8b231b96e3

+ 25 - 2
core/io/resource_format_binary.cpp

@@ -1666,7 +1666,20 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
 
 				if (E->get().usage & PROPERTY_USAGE_STORAGE) {
 
-					_find_resources(res->get(E->get().name));
+					Variant value = res->get(E->get().name);
+					if (E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+						RES sres = value;
+						if (sres.is_valid()) {
+							NonPersistentKey npk;
+							npk.base = res;
+							npk.property = E->get().name;
+							non_persistent_map[npk] = sres;
+							resource_set.insert(sres);
+							saved_resources.push_back(sres);
+						}
+					} else {
+						_find_resources(value);
+					}
 				}
 			}
 
@@ -1810,7 +1823,17 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
 				if ((F->get().usage & PROPERTY_USAGE_STORAGE)) {
 					Property p;
 					p.name_idx = get_string_index(F->get().name);
-					p.value = E->get()->get(F->get().name);
+
+					if (F->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+						NonPersistentKey npk;
+						npk.base = E->get();
+						npk.property = F->get().name;
+						if (non_persistent_map.has(npk)) {
+							p.value = non_persistent_map[npk];
+						}
+					} else {
+						p.value = E->get()->get(F->get().name);
+					}
 
 					Variant default_value = ClassDB::class_get_default_property_value(E->get()->get_class(), F->get().name);
 

+ 8 - 0
core/io/resource_format_binary.h

@@ -123,6 +123,14 @@ class ResourceFormatSaverBinaryInstance {
 	FileAccess *f;
 	String magic;
 	Set<RES> resource_set;
+
+	struct NonPersistentKey { //for resource properties generated on the fly
+		RES base;
+		StringName property;
+		bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; }
+	};
+
+	Map<NonPersistentKey, RES> non_persistent_map;
 	Map<StringName, int> string_map;
 	Vector<StringName> strings;
 

+ 1 - 0
core/object.h

@@ -119,6 +119,7 @@ enum PropertyUsageFlags {
 	PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated
 	PROPERTY_USAGE_HIGH_END_GFX = 1 << 22,
 	PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 23,
+	PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24,
 
 	PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
 	PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,

+ 0 - 2
editor/editor_node.cpp

@@ -4781,8 +4781,6 @@ EditorNode::EditorNode() {
 	ResourceLoader::clear_translation_remaps(); //no remaps using during editor
 	ResourceLoader::clear_path_remaps();
 
-	ImageTexture::set_keep_images_cached(true);
-
 	InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
 
 	if (id) {

+ 26 - 2
scene/resources/resource_format_text.cpp

@@ -1408,7 +1408,21 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
 				if (pi.usage & PROPERTY_USAGE_STORAGE) {
 
 					Variant v = res->get(I->get().name);
-					_find_resources(v);
+
+					if (pi.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+						RES sres = v;
+						if (sres.is_valid()) {
+							NonPersistentKey npk;
+							npk.base = res;
+							npk.property = pi.name;
+							non_persistent_map[npk] = sres;
+							resource_set.insert(sres);
+							saved_resources.push_back(sres);
+						}
+					} else {
+						_find_resources(v);
+					}
+
 				}
 
 				I = I->next();
@@ -1600,7 +1614,17 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
 			if (PE->get().usage & PROPERTY_USAGE_STORAGE) {
 
 				String name = PE->get().name;
-				Variant value = res->get(name);
+				Variant value;
+				if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+					NonPersistentKey npk;
+					npk.base = res;
+					npk.property = name;
+					if (non_persistent_map.has(npk)) {
+						value = non_persistent_map[npk];
+					}
+				} else {
+					value = res->get(name);
+				}
 				Variant default_value = ClassDB::class_get_default_property_value(res->get_class(), name);
 
 				if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) {

+ 9 - 0
scene/resources/resource_format_text.h

@@ -155,6 +155,15 @@ class ResourceFormatSaverTextInstance {
 	bool bundle_resources;
 	bool skip_editor;
 	FileAccess *f;
+
+	struct NonPersistentKey { //for resource properties generated on the fly
+		RES base;
+		StringName property;
+		bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; }
+	};
+
+	Map<NonPersistentKey, RES> non_persistent_map;
+
 	Set<RES> resource_set;
 	List<RES> saved_resources;
 	Map<RES, int> external_resources;

+ 6 - 17
scene/resources/texture.cpp

@@ -157,7 +157,7 @@ bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const {
 void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const {
 
 	p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat"));
-	p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image"));
+	p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT));
 	p_list->push_back(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, ""));
 }
 
@@ -178,12 +178,6 @@ void ImageTexture::_reload_hook(const RID &p_hook) {
 	_change_notify();
 }
 
-bool ImageTexture::keep_images_cached = false;
-
-void ImageTexture::set_keep_images_cached(bool p_enable) {
-	keep_images_cached = p_enable;
-}
-
 void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
 
 	flags = p_flags;
@@ -205,9 +199,7 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags
 	VisualServer::get_singleton()->texture_set_data(texture, p_image);
 	_change_notify();
 
-	if (keep_images_cached) {
-		image_cache = p_image;
-	}
+	image_stored = true;
 }
 
 void ImageTexture::set_flags(uint32_t p_flags) {
@@ -255,10 +247,7 @@ void ImageTexture::set_data(const Ref<Image> &p_image) {
 
 	_change_notify();
 	alpha_cache.unref();
-
-	if (keep_images_cached) {
-		image_cache = p_image;
-	}
+	image_stored = true;
 }
 
 void ImageTexture::_resource_path_changed() {
@@ -268,10 +257,10 @@ void ImageTexture::_resource_path_changed() {
 
 Ref<Image> ImageTexture::get_data() const {
 
-	if (image_cache.is_valid()) {
-		return image_cache;
-	} else {
+	if (image_stored) {
 		return VisualServer::get_singleton()->texture_get_data(texture);
+	} else {
+		return Ref<Image>();
 	}
 }
 

+ 1 - 5
scene/resources/texture.h

@@ -111,7 +111,7 @@ private:
 	Size2 size_override;
 	float lossy_storage_quality;
 	mutable Ref<BitMap> alpha_cache;
-	Ref<Image> image_cache;
+	bool image_stored;
 
 protected:
 	virtual void reload_from_file();
@@ -126,11 +126,7 @@ protected:
 
 	void _set_data(Dictionary p_data);
 
-	static bool keep_images_cached;
-
 public:
-	static void set_keep_images_cached(bool p_enable);
-
 	void create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT);
 	void create_from_image(const Ref<Image> &p_image, uint32_t p_flags = FLAGS_DEFAULT);