summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp15
-rw-r--r--core/core_bind.h11
-rw-r--r--core/input/input_event.cpp2
-rw-r--r--core/io/resource_loader.cpp4
-rw-r--r--doc/classes/ClassDB.xml24
-rw-r--r--doc/classes/FileDialog.xml1
-rw-r--r--doc/classes/RenderingServer.xml24
-rw-r--r--doc/classes/TextEdit.xml3
-rw-r--r--doc/classes/TextServer.xml2
-rw-r--r--drivers/gles3/storage/texture_storage.cpp18
-rw-r--r--drivers/gles3/storage/texture_storage.h6
-rw-r--r--editor/animation_bezier_editor.cpp14
-rw-r--r--editor/code_editor.cpp22
-rw-r--r--editor/code_editor.h3
-rw-r--r--editor/directory_create_dialog.cpp11
-rw-r--r--editor/editor_file_system.cpp59
-rw-r--r--editor/editor_file_system.h2
-rw-r--r--editor/filesystem_dock.cpp38
-rw-r--r--editor/filesystem_dock.h2
-rw-r--r--editor/gui/editor_dir_dialog.cpp1
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--methods.py24
-rw-r--r--modules/mono/csharp_script.cpp41
-rw-r--r--modules/openxr/extensions/platform/openxr_opengl_extension.cpp4
-rw-r--r--modules/webxr/webxr_interface_js.cpp4
-rw-r--r--platform/windows/detect.py18
-rw-r--r--scene/gui/file_dialog.cpp1
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp189
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h2
-rw-r--r--servers/rendering/rendering_server_default.h5
-rw-r--r--servers/rendering/storage/texture_storage.h2
-rw-r--r--servers/rendering_server.cpp5
-rw-r--r--servers/rendering_server.h9
34 files changed, 460 insertions, 110 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index b27981d56b..bbfbb6e3cd 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1419,6 +1419,11 @@ Variant ClassDB::instantiate(const StringName &p_class) const {
}
}
+ClassDB::APIType ClassDB::class_get_api_type(const StringName &p_class) const {
+ ::ClassDB::APIType api_type = ::ClassDB::get_api_type(p_class);
+ return (APIType)api_type;
+}
+
bool ClassDB::class_has_signal(const StringName &p_class, const StringName &p_signal) const {
return ::ClassDB::has_signal(p_class, p_signal);
}
@@ -1615,7 +1620,7 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
pf == "class_has_method" || pf == "class_get_method_list" ||
pf == "class_get_integer_constant_list" || pf == "class_has_integer_constant" || pf == "class_get_integer_constant" ||
pf == "class_has_enum" || pf == "class_get_enum_list" || pf == "class_get_enum_constants" || pf == "class_get_integer_constant_enum" ||
- pf == "is_class_enabled" || pf == "is_class_enum_bitfield");
+ pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
}
if (first_argument_is_class || pf == "is_parent_class") {
for (const String &E : get_class_list()) {
@@ -1636,6 +1641,8 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("can_instantiate", "class"), &ClassDB::can_instantiate);
::ClassDB::bind_method(D_METHOD("instantiate", "class"), &ClassDB::instantiate);
+ ::ClassDB::bind_method(D_METHOD("class_get_api_type", "class"), &ClassDB::class_get_api_type);
+
::ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &ClassDB::class_has_signal);
::ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &ClassDB::class_get_signal);
::ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &ClassDB::class_get_signal_list, DEFVAL(false));
@@ -1669,6 +1676,12 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("is_class_enum_bitfield", "class", "enum", "no_inheritance"), &ClassDB::is_class_enum_bitfield, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
+
+ BIND_ENUM_CONSTANT(API_CORE);
+ BIND_ENUM_CONSTANT(API_EDITOR);
+ BIND_ENUM_CONSTANT(API_EXTENSION);
+ BIND_ENUM_CONSTANT(API_EDITOR_EXTENSION);
+ BIND_ENUM_CONSTANT(API_NONE);
}
} // namespace special
diff --git a/core/core_bind.h b/core/core_bind.h
index 7e2686c848..2a31e64425 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -447,6 +447,14 @@ protected:
static void _bind_methods();
public:
+ enum APIType {
+ API_CORE,
+ API_EDITOR,
+ API_EXTENSION,
+ API_EDITOR_EXTENSION,
+ API_NONE,
+ };
+
PackedStringArray get_class_list() const;
PackedStringArray get_inheriters_from_class(const StringName &p_class) const;
StringName get_parent_class(const StringName &p_class) const;
@@ -455,6 +463,7 @@ public:
bool can_instantiate(const StringName &p_class) const;
Variant instantiate(const StringName &p_class) const;
+ APIType class_get_api_type(const StringName &p_class) const;
bool class_has_signal(const StringName &p_class, const StringName &p_signal) const;
Dictionary class_get_signal(const StringName &p_class, const StringName &p_signal) const;
TypedArray<Dictionary> class_get_signal_list(const StringName &p_class, bool p_no_inheritance = false) const;
@@ -634,4 +643,6 @@ VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
+VARIANT_ENUM_CAST(core_bind::special::ClassDB::APIType);
+
#endif // CORE_BIND_H
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index de3efa7a3a..905526bbbd 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -1088,7 +1088,7 @@ void InputEventMouseMotion::_bind_methods() {
///////////////////////////////////
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
- ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
+ ERR_FAIL_COND(p_axis < JoyAxis::INVALID || p_axis > JoyAxis::MAX);
axis = p_axis;
emit_changed();
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 94f6caf6eb..f026d5416c 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -303,10 +303,6 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
return res;
}
- if (r_error) {
- *r_error = ERR_FILE_UNRECOGNIZED;
- }
-
ERR_FAIL_COND_V_MSG(found, Ref<Resource>(),
vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
diff --git a/doc/classes/ClassDB.xml b/doc/classes/ClassDB.xml
index 99d0c9be84..d1b666097c 100644
--- a/doc/classes/ClassDB.xml
+++ b/doc/classes/ClassDB.xml
@@ -31,6 +31,13 @@
Returns whether the specified [param class] is available or not.
</description>
</method>
+ <method name="class_get_api_type" qualifiers="const">
+ <return type="int" enum="ClassDB.APIType" />
+ <param index="0" name="class" type="StringName" />
+ <description>
+ Returns the API type of [param class]. See [enum APIType].
+ </description>
+ </method>
<method name="class_get_enum_constants" qualifiers="const">
<return type="PackedStringArray" />
<param index="0" name="class" type="StringName" />
@@ -242,4 +249,21 @@
</description>
</method>
</methods>
+ <constants>
+ <constant name="API_CORE" value="0" enum="APIType">
+ Native Core class type.
+ </constant>
+ <constant name="API_EDITOR" value="1" enum="APIType">
+ Native Editor class type.
+ </constant>
+ <constant name="API_EXTENSION" value="2" enum="APIType">
+ GDExtension class type.
+ </constant>
+ <constant name="API_EDITOR_EXTENSION" value="3" enum="APIType">
+ GDExtension Editor class type.
+ </constant>
+ <constant name="API_NONE" value="4" enum="APIType">
+ Unknown class type.
+ </constant>
+ </constants>
</class>
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 38985e99ae..1ae889adc1 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -151,6 +151,7 @@
If [code]true[/code], the dialog will show hidden files.
[b]Note:[/b] This property is ignored by native file dialogs on Linux.
</member>
+ <member name="size" type="Vector2i" setter="set_size" getter="get_size" overrides="Window" default="Vector2i(640, 360)" />
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default="&quot;Save a File&quot;" />
<member name="use_native_dialog" type="bool" setter="set_use_native_dialog" getter="get_use_native_dialog" default="false">
If [code]true[/code], [member access] is set to [constant ACCESS_FILESYSTEM], and it is supported by the current [DisplayServer], OS native dialog will be used instead of custom one.
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 58e88a3bdc..3658dafea6 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -3583,6 +3583,21 @@
[b]Note:[/b] The [param texture] must have the same width, height, depth and format as the current texture data. Otherwise, an error will be printed and the original texture won't be modified. If you need to use different width, height, depth or format, use [method texture_replace] instead.
</description>
</method>
+ <method name="texture_create_from_native_handle">
+ <return type="RID" />
+ <param index="0" name="type" type="int" enum="RenderingServer.TextureType" />
+ <param index="1" name="format" type="int" enum="Image.Format" />
+ <param index="2" name="native_handle" type="int" />
+ <param index="3" name="width" type="int" />
+ <param index="4" name="height" type="int" />
+ <param index="5" name="depth" type="int" />
+ <param index="6" name="layers" type="int" default="1" />
+ <param index="7" name="layered_type" type="int" enum="RenderingServer.TextureLayeredType" default="0" />
+ <description>
+ Creates a texture based on a native handle that was created outside of Godot's renderer.
+ [b]Note:[/b] If using the rendering device renderer, using [method RenderingDevice.texture_create_from_extension] rather than this method is recommended. It will give you much more control over the texture's format and usage.
+ </description>
+ </method>
<method name="texture_get_format" qualifiers="const">
<return type="int" enum="Image.Format" />
<param index="0" name="texture" type="RID" />
@@ -4311,6 +4326,15 @@
<constant name="MAX_MESH_SURFACES" value="256">
The maximum number of surfaces a mesh can have.
</constant>
+ <constant name="TEXTURE_TYPE_2D" value="0" enum="TextureType">
+ 2D texture.
+ </constant>
+ <constant name="TEXTURE_TYPE_LAYERED" value="1" enum="TextureType">
+ Layered texture.
+ </constant>
+ <constant name="TEXTURE_TYPE_3D" value="2" enum="TextureType">
+ 3D texture.
+ </constant>
<constant name="TEXTURE_LAYERED_2D_ARRAY" value="0" enum="TextureLayeredType">
Array of 2-dimensional textures (see [Texture2DArray]).
</constant>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 6505e48fb9..9fada9db35 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1361,7 +1361,8 @@
Set additional options for BiDi override.
</member>
<member name="syntax_highlighter" type="SyntaxHighlighter" setter="set_syntax_highlighter" getter="get_syntax_highlighter">
- Sets the [SyntaxHighlighter] to use.
+ The syntax highlighter to use.
+ [b]Note:[/b] A [SyntaxHighlighter] instance should not be used across multiple [TextEdit] nodes.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
String value of the [TextEdit].
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 9d476691bf..aed041c5ad 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -1732,7 +1732,7 @@
Returns array of the composite character boundaries.
[codeblock]
var ts = TextServerManager.get_primary_interface()
- print(ts.string_get_word_breaks("Test ❤️‍🔥 Test")) # Prints [1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14]
+ print(ts.string_get_character_breaks("Test ❤️‍🔥 Test")) # Prints [1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14]
[/codeblock]
</description>
</method>
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 54012c20e9..bd824a076e 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -729,7 +729,7 @@ void TextureStorage::texture_free(RID p_texture) {
}
}
} else {
- must_free_data = t->tex_id != 0 && !t->is_external;
+ must_free_data = t->tex_id != 0 && !t->is_from_native_handle;
}
if (must_free_data) {
GLES3::Utilities::get_singleton()->texture_free_data(t->tex_id);
@@ -874,26 +874,28 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
texture_owner.initialize_rid(p_texture, proxy_tex);
}
-RID TextureStorage::texture_create_external(GLES3::Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
+RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
Texture texture;
texture.active = true;
- texture.is_external = true;
- texture.type = p_type;
+ texture.is_from_native_handle = true;
switch (p_type) {
- case Texture::TYPE_2D: {
+ case RS::TEXTURE_TYPE_2D: {
+ texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
} break;
- case Texture::TYPE_3D: {
+ case RS::TEXTURE_TYPE_3D: {
+ texture.type = Texture::TYPE_3D;
texture.target = GL_TEXTURE_3D;
} break;
- case Texture::TYPE_LAYERED: {
+ case RS::TEXTURE_TYPE_LAYERED: {
+ texture.type = Texture::TYPE_LAYERED;
texture.target = GL_TEXTURE_2D_ARRAY;
} break;
}
texture.real_format = texture.format = p_format;
- texture.tex_id = p_image;
+ texture.tex_id = p_native_handle;
texture.alloc_width = texture.width = p_width;
texture.alloc_height = texture.height = p_height;
texture.depth = p_depth;
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 5569abcc73..26864c2f3b 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -146,7 +146,7 @@ struct Texture {
RID self;
bool is_proxy = false;
- bool is_external = false;
+ bool is_from_native_handle = false;
bool is_render_target = false;
RID proxy_to;
@@ -209,7 +209,7 @@ struct Texture {
void copy_from(const Texture &o) {
proxy_to = o.proxy_to;
is_proxy = o.is_proxy;
- is_external = o.is_external;
+ is_from_native_handle = o.is_from_native_handle;
width = o.width;
height = o.height;
alloc_width = o.alloc_width;
@@ -514,7 +514,7 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
- RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY);
+ virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 66ebd07c2a..2e8c727849 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -1443,6 +1443,11 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
i++;
}
+ AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
+ if (ape) {
+ undo_redo->add_do_method(ape, "_animation_update_key_frame");
+ undo_redo->add_undo_method(ape, "_animation_update_key_frame");
+ }
undo_redo->commit_action();
} else if (select_single_attempt != IntPair(-1, -1)) {
@@ -1967,15 +1972,6 @@ void AnimationBezierTrackEdit::delete_selection() {
void AnimationBezierTrackEdit::_bezier_track_insert_key_at_anim(const Ref<Animation> &p_anim, int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const Animation::HandleMode p_handle_mode) {
int idx = p_anim->bezier_track_insert_key(p_track, p_time, p_value, p_in_handle, p_out_handle);
p_anim->bezier_track_set_key_handle_mode(p_track, idx, p_handle_mode);
-
- EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Animation Bezier Curve Change Call"));
- AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
- if (ape) {
- undo_redo->add_do_method(ape, "_animation_update_key_frame");
- undo_redo->add_undo_method(ape, "_animation_update_key_frame");
- }
- undo_redo->commit_action();
}
void AnimationBezierTrackEdit::_bind_methods() {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index dd8aa523c4..59783c58b5 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -108,6 +108,7 @@ void FindReplaceBar::_notification(int p_what) {
hide_button->set_texture_hover(get_editor_theme_icon(SNAME("Close")));
hide_button->set_texture_pressed(get_editor_theme_icon(SNAME("Close")));
hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size());
+ _update_toggle_replace_button(replace_text->is_visible_in_tree());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -539,6 +540,14 @@ void FindReplaceBar::_hide_bar(bool p_force_focus) {
hide();
}
+void FindReplaceBar::_update_toggle_replace_button(bool p_replace_visible) {
+ String tooltip = p_replace_visible ? TTR("Hide Replace") : TTR("Show Replace");
+ String shortcut = ED_GET_SHORTCUT(p_replace_visible ? "script_text_editor/find" : "script_text_editor/replace")->get_as_text();
+ toggle_replace_button->set_tooltip_text(vformat("%s (%s)", tooltip, shortcut));
+ StringName rtl_compliant_arrow = is_layout_rtl() ? SNAME("GuiTreeArrowLeft") : SNAME("GuiTreeArrowRight");
+ toggle_replace_button->set_icon(get_editor_theme_icon(p_replace_visible ? SNAME("GuiTreeArrowDown") : rtl_compliant_arrow));
+}
+
void FindReplaceBar::_show_search(bool p_with_replace, bool p_show_only) {
show();
if (p_show_only) {
@@ -582,6 +591,7 @@ void FindReplaceBar::popup_search(bool p_show_only) {
hbc_button_replace->hide();
hbc_option_replace->hide();
selection_only->set_pressed(false);
+ _update_toggle_replace_button(false);
_show_search(false, p_show_only);
}
@@ -591,6 +601,7 @@ void FindReplaceBar::popup_replace() {
replace_text->show();
hbc_button_replace->show();
hbc_option_replace->show();
+ _update_toggle_replace_button(true);
}
selection_only->set_pressed(text_editor->has_selection(0) && text_editor->get_selection_from_line(0) < text_editor->get_selection_to_line(0));
@@ -644,6 +655,11 @@ void FindReplaceBar::_replace_text_submitted(const String &p_text) {
}
}
+void FindReplaceBar::_toggle_replace_pressed() {
+ bool replace_visible = replace_text->is_visible_in_tree();
+ replace_visible ? popup_search(true) : popup_replace();
+}
+
String FindReplaceBar::get_search_text() const {
return search_text->get_text();
}
@@ -702,6 +718,12 @@ void FindReplaceBar::_bind_methods() {
}
FindReplaceBar::FindReplaceBar() {
+ toggle_replace_button = memnew(Button);
+ add_child(toggle_replace_button);
+ toggle_replace_button->set_flat(true);
+ toggle_replace_button->set_focus_mode(FOCUS_NONE);
+ toggle_replace_button->connect(SceneStringName(pressed), callable_mp(this, &FindReplaceBar::_toggle_replace_pressed));
+
vbc_lineedit = memnew(VBoxContainer);
add_child(vbc_lineedit);
vbc_lineedit->set_alignment(BoxContainer::ALIGNMENT_CENTER);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index e56405a4b2..c1c65a2a4a 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -70,6 +70,7 @@ class FindReplaceBar : public HBoxContainer {
SEARCH_PREV,
};
+ Button *toggle_replace_button = nullptr;
LineEdit *search_text = nullptr;
Label *matches_label = nullptr;
Button *find_prev = nullptr;
@@ -106,12 +107,14 @@ class FindReplaceBar : public HBoxContainer {
void _show_search(bool p_with_replace, bool p_show_only);
void _hide_bar(bool p_force_focus = false);
+ void _update_toggle_replace_button(bool p_replace_visible);
void _editor_text_changed();
void _search_options_changed(bool p_pressed);
void _search_text_changed(const String &p_text);
void _search_text_submitted(const String &p_text);
void _replace_text_submitted(const String &p_text);
+ void _toggle_replace_pressed();
protected:
void _notification(int p_what);
diff --git a/editor/directory_create_dialog.cpp b/editor/directory_create_dialog.cpp
index 604531f109..46baa2c6e1 100644
--- a/editor/directory_create_dialog.cpp
+++ b/editor/directory_create_dialog.cpp
@@ -31,6 +31,7 @@
#include "directory_create_dialog.h"
#include "core/io/dir_access.h"
+#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/themes/editor_scale.h"
@@ -100,15 +101,7 @@ void DirectoryCreateDialog::ok_pressed() {
const String error = _validate_path(path);
ERR_FAIL_COND_MSG(!error.is_empty(), error);
- Error err;
- Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-
- err = da->change_dir(base_dir);
- ERR_FAIL_COND_MSG(err != OK, "Cannot open directory '" + base_dir + "'.");
-
- print_verbose("Making folder " + path + " in " + base_dir);
- err = da->make_dir_recursive(path);
-
+ Error err = EditorFileSystem::get_singleton()->make_dir_recursive(path, base_dir);
if (err == OK) {
emit_signal(SNAME("dir_created"), base_dir.path_join(path));
} else {
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 87053acfb6..adae6599c1 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/extension/gdextension_manager.h"
+#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "core/object/worker_thread_pool.h"
@@ -1141,6 +1142,14 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
if (fi->uid != ResourceUID::INVALID_ID) {
if (ResourceUID::get_singleton()->has_id(fi->uid)) {
+ // Restrict UID dupe warning to first-scan since we know there are no file moves going on yet.
+ if (first_scan) {
+ // Warn if we detect files with duplicate UIDs.
+ const String other_path = ResourceUID::get_singleton()->get_id_path(fi->uid);
+ if (other_path != path) {
+ WARN_PRINT(vformat("UID duplicate detected between %s and %s.", path, other_path));
+ }
+ }
ResourceUID::get_singleton()->set_id(fi->uid, path);
} else {
ResourceUID::get_singleton()->add_id(fi->uid, path);
@@ -3067,33 +3076,51 @@ void EditorFileSystem::move_group_file(const String &p_path, const String &p_new
}
}
-void EditorFileSystem::add_new_directory(const String &p_path) {
- String path = p_path.get_base_dir();
- EditorFileSystemDirectory *parent = filesystem;
- int base = p_path.count("/");
- int max_bit = base + 1;
+Error EditorFileSystem::make_dir_recursive(const String &p_path, const String &p_base_path) {
+ Error err;
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (!p_base_path.is_empty()) {
+ err = da->change_dir(p_base_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open base directory '" + p_base_path + "'.");
+ }
- while (path != "res://") {
- EditorFileSystemDirectory *dir = get_filesystem_path(path);
- if (dir) {
- parent = dir;
- break;
- }
- path = path.get_base_dir();
- base--;
+ if (da->dir_exists(p_path)) {
+ return ERR_ALREADY_EXISTS;
+ }
+
+ err = da->make_dir_recursive(p_path);
+ if (err != OK) {
+ return err;
}
- for (int i = base; i < max_bit; i++) {
+ const String path = da->get_current_dir();
+ EditorFileSystemDirectory *parent = get_filesystem_path(path);
+ ERR_FAIL_NULL_V(parent, ERR_FILE_NOT_FOUND);
+
+ const PackedStringArray folders = p_path.trim_prefix(path).trim_suffix("/").split("/");
+ bool first = true;
+
+ for (const String &folder : folders) {
+ const int current = parent->find_dir_index(folder);
+ if (current > -1) {
+ parent = parent->get_subdir(current);
+ continue;
+ }
+
EditorFileSystemDirectory *efd = memnew(EditorFileSystemDirectory);
efd->parent = parent;
- efd->name = p_path.get_slice("/", i);
+ efd->name = folder;
parent->subdirs.push_back(efd);
- if (i == base) {
+ if (first) {
parent->subdirs.sort_custom<DirectoryComparator>();
+ first = false;
}
parent = efd;
}
+
+ emit_signal(SNAME("filesystem_changed"));
+ return OK;
}
ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) {
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index be299800d8..e02127cb13 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -370,7 +370,7 @@ public:
bool is_group_file(const String &p_path) const;
void move_group_file(const String &p_path, const String &p_new_path);
- void add_new_directory(const String &p_path);
+ Error make_dir_recursive(const String &p_path, const String &p_base_path = String());
static bool _should_skip_directory(const String &p_path);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 1082e4d0c2..a5c8fa3d6b 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -649,8 +649,7 @@ void FileSystemDock::_notification(int p_what) {
}
if (do_redraw) {
- _update_file_list(true);
- _update_tree(get_uncollapsed_paths());
+ update_all();
}
if (EditorThemeManager::is_generated_theme_outdated()) {
@@ -1343,13 +1342,7 @@ void FileSystemDock::_fs_changed() {
scanning_vb->hide();
split_box->show();
- if (tree->is_visible()) {
- _update_tree(get_uncollapsed_paths());
- }
-
- if (file_list_vb->is_visible()) {
- _update_file_list(true);
- }
+ update_all();
if (!select_after_scan.is_empty()) {
_navigate_to_path(select_after_scan);
@@ -1361,15 +1354,6 @@ void FileSystemDock::_fs_changed() {
set_process(false);
}
-void FileSystemDock::_directory_created(const String &p_path) {
- if (!DirAccess::exists(p_path)) {
- return;
- }
- EditorFileSystem::get_singleton()->add_new_directory(p_path);
- _update_tree(get_uncollapsed_paths());
- _update_file_list(true);
-}
-
void FileSystemDock::_set_scanning_mode() {
button_hist_prev->set_disabled(true);
button_hist_next->set_disabled(true);
@@ -2820,6 +2804,16 @@ void FileSystemDock::fix_dependencies(const String &p_for_file) {
deps_editor->edit(p_for_file);
}
+void FileSystemDock::update_all() {
+ if (tree->is_visible()) {
+ _update_tree(get_uncollapsed_paths());
+ }
+
+ if (file_list_vb->is_visible()) {
+ _update_file_list(true);
+ }
+}
+
void FileSystemDock::focus_on_path() {
current_path_line_edit->grab_focus();
current_path_line_edit->select_all();
@@ -3241,9 +3235,7 @@ void FileSystemDock::_folder_color_index_pressed(int p_index, PopupMenu *p_menu)
}
_update_folder_colors_setting();
-
- _update_tree(get_uncollapsed_paths());
- _update_file_list(true);
+ update_all();
emit_signal(SNAME("folder_color_changed"));
}
@@ -3951,8 +3943,7 @@ void FileSystemDock::set_file_sort(FileSortOption p_file_sort) {
file_sort = p_file_sort;
// Update everything needed.
- _update_tree(get_uncollapsed_paths());
- _update_file_list(true);
+ update_all();
}
void FileSystemDock::_file_sort_popup(int p_id) {
@@ -4342,7 +4333,6 @@ FileSystemDock::FileSystemDock() {
make_dir_dialog = memnew(DirectoryCreateDialog);
add_child(make_dir_dialog);
- make_dir_dialog->connect("dir_created", callable_mp(this, &FileSystemDock::_directory_created));
make_scene_dialog = memnew(SceneCreateDialog);
add_child(make_scene_dialog);
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 751fbed022..108b646029 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -270,7 +270,6 @@ private:
void _toggle_file_display();
void _set_file_display(bool p_active);
void _fs_changed();
- void _directory_created(const String &p_path);
void _select_file(const String &p_path, bool p_select_in_favorites = false);
void _tree_activate_file();
@@ -417,6 +416,7 @@ public:
ScriptCreateDialog *get_script_create_dialog() const;
void fix_dependencies(const String &p_for_file);
+ void update_all();
int get_h_split_offset() const { return split_box_offset_h; }
void set_h_split_offset(int p_offset) { split_box_offset_h = p_offset; }
diff --git a/editor/gui/editor_dir_dialog.cpp b/editor/gui/editor_dir_dialog.cpp
index e64761d5b5..b677ba1098 100644
--- a/editor/gui/editor_dir_dialog.cpp
+++ b/editor/gui/editor_dir_dialog.cpp
@@ -191,7 +191,6 @@ void EditorDirDialog::_make_dir_confirm(const String &p_path) {
}
new_dir_path = p_path + "/";
- EditorFileSystem::get_singleton()->scan_changes(); // We created a dir, so rescan changes.
}
void EditorDirDialog::_bind_methods() {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index ba9fd4e66c..dc86acd884 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -3997,7 +3997,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
xform.orthonormalize();
xform.basis.scale(scale);
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform);
- RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && transform_gizmo_visible && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
+ RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE));
}
void Node3DEditorViewport::set_state(const Dictionary &p_state) {
diff --git a/methods.py b/methods.py
index 36462fd30b..3f11d39bd0 100644
--- a/methods.py
+++ b/methods.py
@@ -467,16 +467,6 @@ def use_windows_spawn_fix(self, platform=None):
if os.name != "nt":
return # not needed, only for windows
- # On Windows, due to the limited command line length, when creating a static library
- # from a very high number of objects SCons will invoke "ar" once per object file;
- # that makes object files with same names to be overwritten so the last wins and
- # the library loses symbols defined by overwritten objects.
- # By enabling quick append instead of the default mode (replacing), libraries will
- # got built correctly regardless the invocation strategy.
- # Furthermore, since SCons will rebuild the library from scratch when an object file
- # changes, no multiple versions of the same object file will be present.
- self.Replace(ARFLAGS="q")
-
def mySubProcess(cmdline, env):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
@@ -500,19 +490,17 @@ def use_windows_spawn_fix(self, platform=None):
return rv
def mySpawn(sh, escape, cmd, args, env):
+ # Used by TEMPFILE.
+ if cmd == "del":
+ os.remove(args[1])
+ return 0
+
newargs = " ".join(args[1:])
cmdline = cmd + " " + newargs
rv = 0
env = {str(key): str(value) for key, value in iter(env.items())}
- if len(cmdline) > 32000 and cmd.endswith("ar"):
- cmdline = cmd + " " + args[1] + " " + args[2] + " "
- for i in range(3, len(args)):
- rv = mySubProcess(cmdline + args[i], env)
- if rv:
- break
- else:
- rv = mySubProcess(cmdline, env)
+ rv = mySubProcess(cmdline, env)
return rv
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index f47e6d209a..3d12994469 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1497,11 +1497,23 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
List<PropertyInfo> props;
- script->get_script_property_list(&props);
+ ERR_FAIL_COND(!script.is_valid());
+#ifdef TOOLS_ENABLED
+ for (const PropertyInfo &prop : script->exported_members_cache) {
+ props.push_back(prop);
+ }
+#else
+ for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
+ props.push_front(E.value);
+ }
+#endif
- // Call _get_property_list
+ for (PropertyInfo &prop : props) {
+ validate_property(prop);
+ p_properties->push_back(prop);
+ }
- ERR_FAIL_COND(!script.is_valid());
+ // Call _get_property_list
StringName method = SNAME("_get_property_list");
@@ -1524,10 +1536,25 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
}
}
- props.reverse();
- for (PropertyInfo &prop : props) {
- validate_property(prop);
- p_properties->push_front(prop);
+ CSharpScript *top = script.ptr()->base_script.ptr();
+ while (top != nullptr) {
+ props.clear();
+#ifdef TOOLS_ENABLED
+ for (const PropertyInfo &prop : top->exported_members_cache) {
+ props.push_back(prop);
+ }
+#else
+ for (const KeyValue<StringName, PropertyInfo> &E : top->member_info) {
+ props.push_front(E.value);
+ }
+#endif
+
+ for (PropertyInfo &prop : props) {
+ validate_property(prop);
+ p_properties->push_back(prop);
+ }
+
+ top = top->base_script.ptr();
}
}
diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp
index de4a9e4b8e..caded14ca7 100644
--- a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp
+++ b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp
@@ -240,8 +240,8 @@ bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
Vector<RID> texture_rids;
for (uint64_t i = 0; i < swapchain_length; i++) {
- RID texture_rid = texture_storage->texture_create_external(
- p_array_size == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED,
+ RID texture_rid = texture_storage->texture_create_from_native_handle(
+ p_array_size == 1 ? RS::TEXTURE_TYPE_2D : RS::TEXTURE_TYPE_LAYERED,
format,
images[i].image,
p_width,
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 78a9db9b19..352d495dd4 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -561,8 +561,8 @@ RID WebXRInterfaceJS::_get_texture(unsigned int p_texture_id) {
uint32_t view_count = godot_webxr_get_view_count();
Size2 texture_size = get_render_target_size();
- RID texture = texture_storage->texture_create_external(
- view_count == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED,
+ RID texture = texture_storage->texture_create_from_native_handle(
+ view_count == 1 ? RS::TEXTURE_TYPE_2D : RS::TEXTURE_TYPE_LAYERED,
Image::FORMAT_RGBA8,
p_texture_id,
(int)texture_size.width,
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 684a7c34a0..db4c743595 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -704,11 +704,29 @@ def get_is_ar_thin_supported(env):
return False
+WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)")
+
+
+def tempfile_arg_esc_func(arg):
+ from SCons.Subst import quote_spaces
+
+ arg = quote_spaces(arg)
+ # GCC requires double Windows slashes, let's use UNIX separator
+ return WINPATHSEP_RE.sub(r"/\1", arg)
+
+
def configure_mingw(env: "SConsEnvironment"):
# Workaround for MinGW. See:
# https://www.scons.org/wiki/LongCmdLinesOnWin32
env.use_windows_spawn_fix()
+ # In case the command line to AR is too long, use a response file.
+ env["ARCOM_ORIG"] = env["ARCOM"]
+ env["ARCOM"] = "${TEMPFILE('$ARCOM_ORIG', '$ARCOMSTR')}"
+ env["TEMPFILESUFFIX"] = ".rsp"
+ if os.name == "nt":
+ env["TEMPFILEARGESCFUNC"] = tempfile_arg_esc_func
+
## Build type
if not env["use_llvm"] and not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]):
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 1fc8586448..6f61295a91 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -1526,6 +1526,7 @@ FileDialog::FileDialog() {
update_dir();
set_hide_on_ok(false);
+ set_size(Size2(640, 360));
if (register_func) {
register_func(this);
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 43572b65e0..609f19589f 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -92,6 +92,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent
+ virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override { return RID(); }
+
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{};
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index be29716f45..81ab384edc 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1108,6 +1108,195 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
tex->proxies.push_back(p_texture);
}
+// Note: We make some big assumptions about format and usage. If developers need more control,
+// they should use RD::texture_create_from_extension() instead.
+RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
+ RD::TextureType type;
+ switch (p_type) {
+ case RS::TEXTURE_TYPE_2D:
+ type = RD::TEXTURE_TYPE_2D;
+ break;
+
+ case RS::TEXTURE_TYPE_3D:
+ type = RD::TEXTURE_TYPE_3D;
+ break;
+
+ case RS::TEXTURE_TYPE_LAYERED:
+ if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
+ type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else if (p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP) {
+ type = RD::TEXTURE_TYPE_CUBE;
+ } else if (p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {
+ type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ } else {
+ // Arbitrary fallback.
+ type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
+ break;
+
+ default:
+ // Arbitrary fallback.
+ type = RD::TEXTURE_TYPE_2D;
+ }
+
+ // Only a rough conversion - see note above.
+ RD::DataFormat format;
+ switch (p_format) {
+ case Image::FORMAT_L8:
+ case Image::FORMAT_R8:
+ format = RD::DATA_FORMAT_R8_UNORM;
+ break;
+
+ case Image::FORMAT_LA8:
+ case Image::FORMAT_RG8:
+ format = RD::DATA_FORMAT_R8G8_UNORM;
+ break;
+
+ case Image::FORMAT_RGB8:
+ format = RD::DATA_FORMAT_R8G8B8_UNORM;
+ break;
+
+ case Image::FORMAT_RGBA8:
+ format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ break;
+
+ case Image::FORMAT_RGBA4444:
+ format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16;
+ break;
+
+ case Image::FORMAT_RGB565:
+ format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16;
+ break;
+
+ case Image::FORMAT_RF:
+ format = RD::DATA_FORMAT_R32_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGF:
+ format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGBF:
+ format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGBAF:
+ format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ break;
+
+ case Image::FORMAT_RH:
+ format = RD::DATA_FORMAT_R16_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGH:
+ format = RD::DATA_FORMAT_R16G16_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGBH:
+ format = RD::DATA_FORMAT_R16G16B16_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGBAH:
+ format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ break;
+
+ case Image::FORMAT_RGBE9995:
+ format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
+ break;
+
+ case Image::FORMAT_DXT1:
+ format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_DXT3:
+ format = RD::DATA_FORMAT_BC2_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_DXT5:
+ format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_RGTC_R:
+ format = RD::DATA_FORMAT_BC4_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_RGTC_RG:
+ format = RD::DATA_FORMAT_BC5_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_BPTC_RGBA:
+ format = RD::DATA_FORMAT_BC7_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_BPTC_RGBF:
+ format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK;
+ break;
+
+ case Image::FORMAT_BPTC_RGBFU:
+ format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC:
+ format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_R11:
+ format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_R11S:
+ format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RG11:
+ format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RG11S:
+ format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RGB8:
+ format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RGBA8:
+ format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RGB8A1:
+ format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ETC2_RA_AS_RG:
+ format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_DXT5_RA_AS_RG:
+ format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ASTC_4x4:
+ case Image::FORMAT_ASTC_4x4_HDR:
+ format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK;
+ break;
+
+ case Image::FORMAT_ASTC_8x8:
+ case Image::FORMAT_ASTC_8x8_HDR:
+ format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK;
+ break;
+
+ default:
+ // Arbitrary fallback.
+ format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ // Assumed to be a color attachment - see note above.
+ uint64_t usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ return RD::get_singleton()->texture_create_from_extension(type, format, RD::TEXTURE_SAMPLES_1, usage_flags, p_native_handle, p_width, p_height, p_depth, p_layers);
+}
+
void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 704f5fb1bd..d352690fff 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -493,6 +493,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+ virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
+
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 60fa546e16..fb4f4aa756 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -179,6 +179,11 @@ public:
FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
FUNCRIDTEX1(texture_proxy, RID)
+ // Called directly, not through the command queue.
+ virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) override {
+ return RSG::texture_storage->texture_create_from_native_handle(p_type, p_format, p_native_handle, p_width, p_height, p_depth, p_layers, p_layered_type);
+ }
+
//these go through command queue if they are in another thread
FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index 72c4dd305b..7388307ac0 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -71,6 +71,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
+ virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0;
+
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 020fa94e9d..a1c05fa2e7 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2239,6 +2239,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_2d_layered_create", "layers", "layered_type"), &RenderingServer::_texture_2d_layered_create);
ClassDB::bind_method(D_METHOD("texture_3d_create", "format", "width", "height", "depth", "mipmaps", "data"), &RenderingServer::_texture_3d_create);
ClassDB::bind_method(D_METHOD("texture_proxy_create", "base"), &RenderingServer::texture_proxy_create);
+ ClassDB::bind_method(D_METHOD("texture_create_from_native_handle", "type", "format", "native_handle", "width", "height", "depth", "layers", "layered_type"), &RenderingServer::texture_create_from_native_handle, DEFVAL(1), DEFVAL(TEXTURE_LAYERED_2D_ARRAY));
ClassDB::bind_method(D_METHOD("texture_2d_update", "texture", "image", "layer"), &RenderingServer::texture_2d_update);
ClassDB::bind_method(D_METHOD("texture_3d_update", "texture", "data"), &RenderingServer::_texture_3d_update);
@@ -2265,6 +2266,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_get_rd_texture", "texture", "srgb"), &RenderingServer::texture_get_rd_texture, DEFVAL(false));
ClassDB::bind_method(D_METHOD("texture_get_native_handle", "texture", "srgb"), &RenderingServer::texture_get_native_handle, DEFVAL(false));
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_LAYERED);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
+
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 62ca6b3b6d..2b45b73f09 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -113,6 +113,12 @@ public:
/* TEXTURE API */
+ enum TextureType {
+ TEXTURE_TYPE_2D,
+ TEXTURE_TYPE_LAYERED,
+ TEXTURE_TYPE_3D,
+ };
+
enum TextureLayeredType {
TEXTURE_LAYERED_2D_ARRAY,
TEXTURE_LAYERED_CUBEMAP,
@@ -133,6 +139,8 @@ public:
virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent
virtual RID texture_proxy_create(RID p_base) = 0;
+ virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) = 0;
+
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0;
@@ -1793,6 +1801,7 @@ private:
};
// Make variant understand the enums.
+VARIANT_ENUM_CAST(RenderingServer::TextureType);
VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType);
VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer);
VARIANT_ENUM_CAST(RenderingServer::ShaderMode);