diff --git a/core/object/object.h b/core/object/object.h
index adb50268d2ad..9feec227f0a3 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -65,7 +65,7 @@ enum PropertyHint {
PROPERTY_HINT_DIR, ///< a directory path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
- PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
+ PROPERTY_HINT_RESOURCE_TYPE, ///< a comma-separated resource object type, e.g. "NoiseTexture,GradientTexture2D". Subclasses can be excluded with a "-" prefix if placed *after* the base class, e.g. "Texture2D,-MeshTexture".
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_EXPRESSION, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml
index 7254a92e36d2..c153a796578d 100644
--- a/doc/classes/Texture2D.xml
+++ b/doc/classes/Texture2D.xml
@@ -124,7 +124,7 @@
Returns an [Image] that is a copy of data from this [Texture2D] (a new [Image] is created each time). [Image]s can be accessed and manipulated directly.
[b]Note:[/b] This will return [code]null[/code] if this [Texture2D] is invalid.
- [b]Note:[/b] This will fetch the texture data from the GPU, which might cause performance problems when overused.
+ [b]Note:[/b] This will fetch the texture data from the GPU, which might cause performance problems when overused. Avoid calling [method get_image] every frame, especially on large textures.
diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml
index ba2352ab610f..5943bd210ce5 100644
--- a/doc/classes/ViewportTexture.xml
+++ b/doc/classes/ViewportTexture.xml
@@ -8,6 +8,7 @@
To get a [ViewportTexture] in code, use the [method Viewport.get_texture] method on the target viewport.
[b]Note:[/b] A [ViewportTexture] is always local to its scene (see [member Resource.resource_local_to_scene]). If the scene root is not ready, it may return incorrect data (see [signal Node.ready]).
[b]Note:[/b] Instantiating scenes containing a high-resolution [ViewportTexture] may cause noticeable stutter.
+ [b]Note:[/b] Some nodes such as [Decal], [Light3D], and [PointLight2D] do not support using [ViewportTexture] directly. To use texture data from a [ViewportTexture] in these nodes, you need to create an [ImageTexture] by calling [method Texture2D.get_image] on the [ViewportTexture] and passing the result to [method ImageTexture.create_from_image]. This conversion is a slow operation, so it should not be performed every frame.
https://godotengine.org/asset-library/asset/2807
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 50820ac12f59..f13714819ea7 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -563,9 +563,9 @@ String EditorResourcePicker::_get_resource_type(const Ref &p_resource)
return res_type;
}
-static void _add_allowed_type(const StringName &p_type, HashSet *p_vector) {
- if (p_vector->has(p_type)) {
- // Already added
+static void _add_allowed_type(const StringName &p_type, List *p_vector) {
+ if (p_vector->find(p_type)) {
+ // Already added.
return;
}
@@ -573,7 +573,7 @@ static void _add_allowed_type(const StringName &p_type, HashSet *p_v
// Engine class,
if (!ClassDB::is_virtual(p_type)) {
- p_vector->insert(p_type);
+ p_vector->push_back(p_type);
}
List inheriters;
@@ -583,7 +583,7 @@ static void _add_allowed_type(const StringName &p_type, HashSet *p_v
}
} else {
// Script class.
- p_vector->insert(p_type);
+ p_vector->push_back(p_type);
}
List inheriters;
@@ -598,12 +598,22 @@ void EditorResourcePicker::_ensure_allowed_types() const {
return;
}
+ List final_allowed;
+
Vector allowed_types = base_type.split(",");
int size = allowed_types.size();
- for (int i = 0; i < size; i++) {
- const String base = allowed_types[i].strip_edges();
- _add_allowed_type(base, &allowed_types_without_convert);
+ for (const String &S : allowed_types) {
+ const String base = S.strip_edges();
+ if (base.begins_with("-")) {
+ final_allowed.erase(base.right(-1));
+ continue;
+ }
+ _add_allowed_type(base, &final_allowed);
+ }
+
+ for (const StringName &SN : final_allowed) {
+ allowed_types_without_convert.insert(SN);
}
allowed_types_with_convert = HashSet(allowed_types_without_convert);
diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected
index 6761512c15fb..d9f5306bfcf4 100644
--- a/misc/extension_api_validation/4.2-stable.expected
+++ b/misc/extension_api_validation/4.2-stable.expected
@@ -357,3 +357,15 @@ Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_it
Validate extension JSON: Error: Field 'classes/RenderingServer/methods/canvas_item_add_rect/arguments': size changed value in new API, from 3 to 4.
Optional arguments added. Compatibility methods registered.
+
+
+GH-88349
+--------
+Validate extension JSON: Error: Field 'classes/Decal/properties/texture_albedo': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+Validate extension JSON: Error: Field 'classes/Decal/properties/texture_emission': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+Validate extension JSON: Error: Field 'classes/Decal/properties/texture_normal': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+Validate extension JSON: Error: Field 'classes/Decal/properties/texture_orm': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+Validate extension JSON: Error: Field 'classes/Light3D/properties/light_projector': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+Validate extension JSON: Error: Field 'classes/PointLight2D/properties/texture': type changed value in new API, from "Texture2D" to "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture".
+
+Property hints modified to disallow resource types that don't work. The types allowed are now more restricted, but this change only impacts the editor and not the actual exposed API. No adjustments should be necessary.
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 5ce26b3ed49e..dcc581385df6 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -394,6 +394,19 @@ Rect2 PointLight2D::get_anchorable_rect() const {
void PointLight2D::set_texture(const Ref &p_texture) {
texture = p_texture;
if (texture.is_valid()) {
+#ifdef DEBUG_ENABLED
+ if (
+ p_texture->is_class("AnimatedTexture") ||
+ p_texture->is_class("AtlasTexture") ||
+ p_texture->is_class("CameraTexture") ||
+ p_texture->is_class("CanvasTexture") ||
+ p_texture->is_class("MeshTexture") ||
+ p_texture->is_class("Texture2DRD") ||
+ p_texture->is_class("ViewportTexture")) {
+ WARN_PRINT(vformat("%s cannot be used as a PointLight2D texture (%s). As a workaround, assign the value returned by %s's `get_image()` instead.", p_texture->get_class(), get_path(), p_texture->get_class()));
+ }
+#endif
+
RS::get_singleton()->canvas_light_set_texture(_get_light(), texture->get_rid());
} else {
RS::get_singleton()->canvas_light_set_texture(_get_light(), RID());
@@ -461,7 +474,8 @@ void PointLight2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &PointLight2D::set_texture_scale);
ClassDB::bind_method(D_METHOD("get_texture_scale"), &PointLight2D::get_texture_scale);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
+ // Only allow texture types that display correctly.
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_texture_offset", "get_texture_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texture_scale", PROPERTY_HINT_RANGE, "0.01,50,0.01"), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1024,1,or_greater,suffix:px"), "set_height", "get_height");
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 485599d0fb55..5f83c494e05b 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -44,6 +44,20 @@ void Decal::set_texture(DecalTexture p_type, const Ref &p_texture) {
ERR_FAIL_INDEX(p_type, TEXTURE_MAX);
textures[p_type] = p_texture;
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
+
+#ifdef DEBUG_ENABLED
+ if (
+ p_texture->is_class("AnimatedTexture") ||
+ p_texture->is_class("AtlasTexture") ||
+ p_texture->is_class("CameraTexture") ||
+ p_texture->is_class("CanvasTexture") ||
+ p_texture->is_class("MeshTexture") ||
+ p_texture->is_class("Texture2DRD") ||
+ p_texture->is_class("ViewportTexture")) {
+ WARN_PRINT(vformat("%s cannot be used as a Decal texture (%s). As a workaround, assign the value returned by %s's `get_image()` instead.", p_texture->get_class(), get_path(), p_texture->get_class()));
+ }
+#endif
+
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
update_configuration_warnings();
}
@@ -225,10 +239,12 @@ void Decal::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_size", "get_size");
ADD_GROUP("Textures", "texture_");
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ALBEDO);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ORM);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION);
+ // Only allow texture types that display correctly.
+ const String texture_hint = "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture";
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ALBEDO);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_normal", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_NORMAL);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_orm", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_ORM);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_emission", PROPERTY_HINT_RESOURCE_TYPE, texture_hint), "set_texture", "get_texture", TEXTURE_EMISSION);
ADD_GROUP("Parameters", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy");
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 7b70986adce9..61a591b23f39 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include "core/config/project_settings.h"
-
#include "light_3d.h"
+#include "core/config/project_settings.h"
+
void Light3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
param[p_param] = p_value;
@@ -191,6 +191,20 @@ Light3D::BakeMode Light3D::get_bake_mode() const {
void Light3D::set_projector(const Ref &p_texture) {
projector = p_texture;
RID tex_id = projector.is_valid() ? projector->get_rid() : RID();
+
+#ifdef DEBUG_ENABLED
+ if (
+ p_texture->is_class("AnimatedTexture") ||
+ p_texture->is_class("AtlasTexture") ||
+ p_texture->is_class("CameraTexture") ||
+ p_texture->is_class("CanvasTexture") ||
+ p_texture->is_class("MeshTexture") ||
+ p_texture->is_class("Texture2DRD") ||
+ p_texture->is_class("ViewportTexture")) {
+ WARN_PRINT(vformat("%s cannot be used as a Light3D projector texture (%s). As a workaround, assign the value returned by %s's `get_image()` instead.", p_texture->get_class(), get_path(), p_texture->get_class()));
+ }
+#endif
+
RS::get_singleton()->light_set_projector(light, tex_id);
update_configuration_warnings();
}
@@ -372,7 +386,8 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_volumetric_fog_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_VOLUMETRIC_FOG_ENERGY);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector");
+ // Only allow texture types that display correctly.
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D,-AnimatedTexture,-AtlasTexture,-CameraTexture,-CanvasTexture,-MeshTexture,-Texture2DRD,-ViewportTexture"), "set_projector", "get_projector");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,degrees"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");