summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/object/object.h22
-rw-r--r--core/templates/rid_owner.h11
-rw-r--r--doc/classes/DirAccess.xml4
-rw-r--r--drivers/gles3/shaders/canvas.glsl4
-rw-r--r--drivers/gles3/storage/material_storage.cpp2
-rw-r--r--drivers/unix/dir_access_unix.cpp12
-rw-r--r--drivers/unix/dir_access_unix.h4
-rw-r--r--drivers/unix/file_access_unix.cpp23
-rw-r--r--drivers/unix/file_access_unix.h4
-rw-r--r--drivers/unix/net_socket_posix.cpp28
-rw-r--r--drivers/unix/os_unix.cpp3
-rw-r--r--drivers/unix/os_unix.h2
-rw-r--r--drivers/windows/dir_access_windows.cpp28
-rw-r--r--editor/editor_fonts.cpp22
-rw-r--r--editor/editor_log.cpp25
-rw-r--r--editor/import/collada.cpp8
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp19
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp80
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/plugins/text_shader_editor.cpp2
-rw-r--r--editor/scene_tree_editor.cpp4
-rw-r--r--methods.py5
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp32
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h1
-rw-r--r--modules/gdscript/language_server/godot_lsp.h2
-rw-r--r--modules/gltf/config.py1
-rw-r--r--modules/gltf/doc_classes/GLTFState.xml13
-rw-r--r--modules/gltf/doc_classes/GLTFTexture.xml3
-rw-r--r--modules/gltf/doc_classes/GLTFTextureSampler.xml25
-rw-r--r--modules/gltf/gltf_defines.h2
-rw-r--r--modules/gltf/gltf_document.cpp138
-rw-r--r--modules/gltf/gltf_document.h9
-rw-r--r--modules/gltf/gltf_state.cpp11
-rw-r--r--modules/gltf/gltf_state.h6
-rw-r--r--modules/gltf/register_types.cpp2
-rw-r--r--modules/gltf/structures/gltf_texture.cpp11
-rw-r--r--modules/gltf/structures/gltf_texture.h3
-rw-r--r--modules/gltf/structures/gltf_texture_sampler.cpp47
-rw-r--r--modules/gltf/structures/gltf_texture_sampler.h163
-rw-r--r--modules/mono/csharp_script.h10
-rw-r--r--platform/android/detect.py16
-rw-r--r--platform/linuxbsd/display_server_x11.cpp15
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp4
-rw-r--r--platform/macos/dir_access_macos.h10
-rw-r--r--platform/macos/dir_access_macos.mm4
-rw-r--r--platform/macos/display_server_macos.mm2
-rw-r--r--platform/uwp/os_uwp.h2
-rw-r--r--platform/windows/display_server_windows.cpp2
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--platform/windows/os_windows.h3
-rw-r--r--scene/3d/mesh_instance_3d.cpp30
-rw-r--r--scene/3d/mesh_instance_3d.h1
-rw-r--r--scene/gui/scroll_container.cpp2
-rw-r--r--scene/main/node.cpp10
-rw-r--r--scene/main/viewport.cpp12
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/main/window.cpp14
58 files changed, 650 insertions, 274 deletions
diff --git a/core/object/object.h b/core/object/object.h
index 8ade5a204a..33a5afc9aa 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -733,34 +733,12 @@ public:
template <class T>
static T *cast_to(Object *p_object) {
-#ifndef NO_SAFE_CAST
return dynamic_cast<T *>(p_object);
-#else
- if (!p_object) {
- return nullptr;
- }
- if (p_object->is_class_ptr(T::get_class_ptr_static())) {
- return static_cast<T *>(p_object);
- } else {
- return nullptr;
- }
-#endif
}
template <class T>
static const T *cast_to(const Object *p_object) {
-#ifndef NO_SAFE_CAST
return dynamic_cast<const T *>(p_object);
-#else
- if (!p_object) {
- return nullptr;
- }
- if (p_object->is_class_ptr(T::get_class_ptr_static())) {
- return static_cast<const T *>(p_object);
- } else {
- return nullptr;
- }
-#endif
}
enum {
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index 320faebe98..a83ffa575f 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -335,15 +335,8 @@ public:
~RID_Alloc() {
if (alloc_count) {
- if (description) {
- print_error("ERROR: " + itos(alloc_count) + " RID allocations of type '" + description + "' were leaked at exit.");
- } else {
-#ifdef NO_SAFE_CAST
- print_error("ERROR: " + itos(alloc_count) + " RID allocations of type 'unknown' were leaked at exit.");
-#else
- print_error("ERROR: " + itos(alloc_count) + " RID allocations of type '" + typeid(T).name() + "' were leaked at exit.");
-#endif
- }
+ print_error(vformat("ERROR: %d RID allocations of type '%s' were leaked at exit.",
+ alloc_count, description ? description : typeid(T).name()));
for (size_t i = 0; i < max_alloc; i++) {
uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk];
diff --git a/doc/classes/DirAccess.xml b/doc/classes/DirAccess.xml
index 554ef9e2da..7d1612e59c 100644
--- a/doc/classes/DirAccess.xml
+++ b/doc/classes/DirAccess.xml
@@ -80,7 +80,7 @@
<param index="2" name="chmod_flags" type="int" default="-1" />
<description>
Copies the [param from] file to the [param to] destination. Both arguments should be paths to files, either relative or absolute. If the destination file exists and is not access-protected, it will be overwritten.
- If [param chmod_flags] is different than [code]-1[/code], the unix permissions for the destination path will be set to the provided value, if available on the current operating system.
+ If [param chmod_flags] is different than [code]-1[/code], the Unix permissions for the destination path will be set to the provided value, if available on the current operating system.
Returns one of the [enum Error] code constants ([code]OK[/code] on success).
</description>
</method>
@@ -199,7 +199,7 @@
<method name="get_space_left">
<return type="int" />
<description>
- On UNIX desktop systems, returns the available space on the current directory's disk. On other platforms, this information is not available and the method returns 0 or -1.
+ Returns the available space on the current directory's disk, in bytes. Returns [code]0[/code] if the platform-specific method to query the available space fails.
</description>
</method>
<method name="list_dir_begin">
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 7334100575..8dae28b6ef 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -127,6 +127,8 @@ void main() {
}
#endif
+ vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+
#ifdef USE_POINT_SIZE
float point_size = 1.0;
#endif
@@ -393,6 +395,8 @@ void main() {
vec2 screen_uv = vec2(0.0);
#endif
+ vec2 color_texture_pixel_size = draw_data[draw_data_instance].color_texture_pixel_size.xy;
+
vec3 light_vertex = vec3(vertex, 0.0);
vec2 shadow_vertex = vertex;
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index d9a797778c..bbbad50b14 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -1393,7 +1393,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_MAP"] = "normal_map";
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["TEXTURE"] = "color_texture";
- actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size";
+ actions.renames["TEXTURE_PIXEL_SIZE"] = "color_texture_pixel_size";
actions.renames["NORMAL_TEXTURE"] = "normal_texture";
actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture";
actions.renames["SPECULAR_SHININESS"] = "specular_shininess";
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 55ea952696..c25ceba44d 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -30,7 +30,7 @@
#include "dir_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/os/memory.h"
#include "core/os/os.h"
@@ -41,10 +41,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#ifndef ANDROID_ENABLED
#include <sys/statvfs.h>
-#endif
#ifdef HAVE_MNTENT
#include <mntent.h>
@@ -475,17 +472,12 @@ Error DirAccessUnix::create_link(String p_source, String p_target) {
}
uint64_t DirAccessUnix::get_space_left() {
-#ifndef NO_STATVFS
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
}
return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
-#else
- // FIXME: Implement this.
- return 0;
-#endif
}
String DirAccessUnix::get_filesystem_type() const {
@@ -516,4 +508,4 @@ DirAccessUnix::~DirAccessUnix() {
list_dir_end();
}
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index f5dca7c282..4db24a27b9 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -31,7 +31,7 @@
#ifndef DIR_ACCESS_UNIX_H
#define DIR_ACCESS_UNIX_H
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/io/dir_access.h"
@@ -90,6 +90,6 @@ public:
~DirAccessUnix();
};
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
#endif // DIR_ACCESS_UNIX_H
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 300fbcdcfd..0df645c4e5 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -30,24 +30,20 @@
#include "file_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <errno.h>
-
#if defined(UNIX_ENABLED)
#include <unistd.h>
#endif
-#ifndef ANDROID_ENABLED
-#include <sys/statvfs.h>
-#endif
-
#ifdef MSVC
#define S_ISREG(m) ((m)&_S_IFREG)
#include <io.h>
@@ -56,12 +52,6 @@
#define S_ISREG(m) ((m)&S_IFREG)
#endif
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
void FileAccessUnix::check_errors() const {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
@@ -131,13 +121,8 @@ Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) {
int fd = fileno(f);
if (fd != -1) {
-#if defined(NO_FCNTL)
- unsigned long par = 0;
- ioctl(fd, FIOCLEX, &par);
-#else
int opts = fcntl(fd, F_GETFD);
fcntl(fd, F_SETFD, opts | FD_CLOEXEC);
-#endif
}
last_error = OK;
@@ -339,4 +324,4 @@ FileAccessUnix::~FileAccessUnix() {
_close();
}
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index e1311a80f8..8c9afe75e7 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -36,7 +36,7 @@
#include <stdio.h>
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
typedef void (*CloseNotificationFunc)(const String &p_file, int p_flags);
@@ -86,6 +86,6 @@ public:
virtual ~FileAccessUnix();
};
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
#endif // FILE_ACCESS_UNIX_H
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 86adf33d62..72ae609fb4 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -30,32 +30,30 @@
#include "net_socket_posix.h"
+// Some proprietary Unix-derived platforms don't expose Unix sockets
+// so this allows skipping this file to reimplement this API differently.
#ifndef UNIX_SOCKET_UNAVAILABLE
+
#if defined(UNIX_ENABLED)
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-#include <netinet/in.h>
-#include <sys/socket.h>
#ifdef WEB_ENABLED
#include <arpa/inet.h>
#endif
-#include <netinet/tcp.h>
-
// BSD calls this flag IPV6_JOIN_GROUP
#if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP)
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -93,7 +91,7 @@
#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15)
#endif
-#endif
+#endif // UNIX_ENABLED
size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) {
memset(p_addr, 0, sizeof(struct sockaddr_storage));
@@ -309,14 +307,9 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_
void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) {
#ifndef WINDOWS_ENABLED
// Enable close on exec to avoid sharing with subprocesses. Off by default on Windows.
-#if defined(NO_FCNTL)
- unsigned long par = p_enabled ? 1 : 0;
- SOCK_IOCTL(_sock, FIOCLEX, &par);
-#else
int opts = fcntl(_sock, F_GETFD);
fcntl(_sock, F_SETFD, opts | FD_CLOEXEC);
#endif
-#endif
}
Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
@@ -658,7 +651,7 @@ void NetSocketPosix::set_blocking_enabled(bool p_enabled) {
ERR_FAIL_COND(!is_open());
int ret = 0;
-#if defined(WINDOWS_ENABLED) || defined(NO_FCNTL)
+#if defined(WINDOWS_ENABLED)
unsigned long par = p_enabled ? 0 : 1;
ret = SOCK_IOCTL(_sock, FIONBIO, &par);
#else
@@ -781,4 +774,5 @@ Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, Str
Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) {
return _change_multicast_group(p_multi_address, p_if_name, false);
}
-#endif
+
+#endif // UNIX_SOCKET_UNAVAILABLE
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 1151c2232e..748b48d316 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -135,10 +135,8 @@ void OS_Unix::initialize_core() {
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
-#ifndef NO_NETWORK
NetSocketPosix::make_default();
IPUnix::make_default();
-#endif
_setup_clock();
}
@@ -168,6 +166,7 @@ Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
left -= chunk;
ofs += chunk;
} while (left > 0);
+// Define this yourself if you don't want to fall back to /dev/urandom.
#elif !defined(NO_URANDOM)
int r = open("/dev/urandom", O_RDONLY);
ERR_FAIL_COND_V(r < 0, FAILED);
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index b35f161524..ce81ca0aca 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -53,7 +53,7 @@ public:
virtual String get_stdin_string(bool p_block) override;
- virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
+ virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 7dd294c7a1..3660e956e3 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -309,39 +309,13 @@ Error DirAccessWindows::remove(String p_path) {
}
}
-/*
-
-FileType DirAccessWindows::get_file_type(const String& p_file) const {
- WCHAR real_current_dir_name[2048];
- GetCurrentDirectoryW(2048, real_current_dir_name);
- String prev_dir = Strong::utf16((const char16_t *)real_current_dir_name);
-
- bool worked = SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data()));
-
- DWORD attr;
- if (worked) {
- WIN32_FILE_ATTRIBUTE_DATA fileInfo;
- attr = GetFileAttributesExW((LPCWSTR)(p_file.utf16().get_data()), GetFileExInfoStandard, &fileInfo);
- }
-
- SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data()));
-
- if (!worked) {
- return FILE_TYPE_NONE;
- }
-
- return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FILE_TYPE_
-}
-
-*/
-
uint64_t DirAccessWindows::get_space_left() {
uint64_t bytes = 0;
if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) {
return 0;
}
- //this is either 0 or a value in bytes.
+ // This is either 0 or a value in bytes.
return bytes;
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index c31d13d122..0262284cdf 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -317,6 +317,24 @@ void editor_register_fonts(Ref<Theme> p_theme) {
mono_other_fc->set_opentype_features(ftrs);
}
+ // Use fake bold/italics to style the editor log's `print_rich()` output.
+ // Use stronger embolden strength to make bold easier to distinguish from regular text.
+ Ref<FontVariation> mono_other_fc_bold = mono_other_fc->duplicate();
+ mono_other_fc_bold->set_variation_embolden(0.8);
+
+ Ref<FontVariation> mono_other_fc_italic = mono_other_fc->duplicate();
+ mono_other_fc_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
+
+ Ref<FontVariation> mono_other_fc_bold_italic = mono_other_fc->duplicate();
+ mono_other_fc_bold_italic->set_variation_embolden(0.8);
+ mono_other_fc_bold_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
+
+ Ref<FontVariation> mono_other_fc_mono = mono_other_fc->duplicate();
+ // Use a different font style to distinguish `[code]` in rich prints.
+ // This emulates the "faint" styling used in ANSI escape codes by using a slightly thinner font.
+ mono_other_fc_mono->set_variation_embolden(-0.25);
+ mono_other_fc_mono->set_variation_transform(Transform2D(1.0, 0.1, 0.0, 1.0, 0.0, 0.0));
+
Ref<FontVariation> italic_fc = default_fc->duplicate();
italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
@@ -386,6 +404,10 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font_size("output_source_size", "EditorFonts", int(EDITOR_GET("run/output/font_size")) * EDSCALE);
p_theme->set_font("output_source", "EditorFonts", mono_other_fc);
+ p_theme->set_font("output_source_bold", "EditorFonts", mono_other_fc_bold);
+ p_theme->set_font("output_source_italic", "EditorFonts", mono_other_fc_italic);
+ p_theme->set_font("output_source_bold_italic", "EditorFonts", mono_other_fc_bold_italic);
+ p_theme->set_font("output_source_mono", "EditorFonts", mono_other_fc_mono);
p_theme->set_font_size("status_source_size", "EditorFonts", default_font_size);
p_theme->set_font("status_source", "EditorFonts", mono_other_fc);
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 6e6a898757..0f2543f708 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -65,19 +65,34 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f
}
void EditorLog::_update_theme() {
- Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts"));
+ const Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts"));
if (normal_font.is_valid()) {
log->add_theme_font_override("normal_font", normal_font);
}
- log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
- log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
-
- Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ const Ref<Font> bold_font = get_theme_font(SNAME("output_source_bold"), SNAME("EditorFonts"));
if (bold_font.is_valid()) {
log->add_theme_font_override("bold_font", bold_font);
}
+ const Ref<Font> italics_font = get_theme_font(SNAME("output_source_italic"), SNAME("EditorFonts"));
+ if (italics_font.is_valid()) {
+ log->add_theme_font_override("italics_font", italics_font);
+ }
+
+ const Ref<Font> bold_italics_font = get_theme_font(SNAME("output_source_bold_italic"), SNAME("EditorFonts"));
+ if (bold_italics_font.is_valid()) {
+ log->add_theme_font_override("bold_italics_font", bold_italics_font);
+ }
+
+ const Ref<Font> mono_font = get_theme_font(SNAME("output_source_mono"), SNAME("EditorFonts"));
+ if (mono_font.is_valid()) {
+ log->add_theme_font_override("mono_font", mono_font);
+ }
+
+ log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
+ log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
+
type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons")));
type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp
index 5d8e453395..7cf35c519b 100644
--- a/editor/import/collada.cpp
+++ b/editor/import/collada.cpp
@@ -2036,11 +2036,7 @@ void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) {
ERR_CONTINUE(!state.scene_map.has(nodeid)); //weird, it should have it...
-#ifdef NO_SAFE_CAST
- NodeJoint *nj = static_cast<NodeJoint *>(state.scene_map[nodeid]);
-#else
NodeJoint *nj = dynamic_cast<NodeJoint *>(state.scene_map[nodeid]);
-#endif
ERR_CONTINUE(!nj); //broken collada
ERR_CONTINUE(!nj->owner); //weird, node should have a skeleton owner
@@ -2197,11 +2193,7 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L
String nodeid = ng->skeletons[0];
ERR_FAIL_COND_V(!state.scene_map.has(nodeid), false); //weird, it should have it...
-#ifdef NO_SAFE_CAST
- NodeJoint *nj = static_cast<NodeJoint *>(state.scene_map[nodeid]);
-#else
NodeJoint *nj = dynamic_cast<NodeJoint *>(state.scene_map[nodeid]);
-#endif
ERR_FAIL_COND_V(!nj, false);
ERR_FAIL_COND_V(!nj->owner, false); //weird, node should have a skeleton owner
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index c502d47669..d5cdb70ccf 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -270,6 +270,24 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
case MENU_OPTION_CREATE_OUTLINE_MESH: {
outline_dialog->popup_centered(Vector2(200, 90));
} break;
+ case MENU_OPTION_CREATE_DEBUG_TANGENTS: {
+ Ref<EditorUndoRedoManager> ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Create Debug Tangents"));
+
+ MeshInstance3D *tangents = node->create_debug_tangents_node();
+
+ if (tangents) {
+ Node *owner = get_tree()->get_edited_scene_root();
+
+ ur->add_do_reference(tangents);
+ ur->add_do_method(node, "add_child", tangents, true);
+ ur->add_do_method(tangents, "set_owner", owner);
+
+ ur->add_undo_method(node, "remove_child", tangents);
+ }
+
+ ur->commit_action();
+ } break;
case MENU_OPTION_CREATE_UV2: {
Ref<ArrayMesh> mesh2 = node->get_mesh();
if (!mesh2.is_valid()) {
@@ -511,6 +529,7 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Outline Mesh..."), MENU_OPTION_CREATE_OUTLINE_MESH);
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a static outline mesh. The outline mesh will have its normals flipped automatically.\nThis can be used instead of the StandardMaterial Grow property when using that property isn't possible."));
+ options->get_popup()->add_item(TTR("Create Debug Tangents"), MENU_OPTION_CREATE_DEBUG_TANGENTS);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("View UV1"), MENU_OPTION_DEBUG_UV1);
options->get_popup()->add_item(TTR("View UV2"), MENU_OPTION_DEBUG_UV2);
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 7968176744..88800227d1 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -46,6 +46,7 @@ class MeshInstance3DEditor : public Control {
MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES,
MENU_OPTION_CREATE_NAVMESH,
MENU_OPTION_CREATE_OUTLINE_MESH,
+ MENU_OPTION_CREATE_DEBUG_TANGENTS,
MENU_OPTION_CREATE_UV2,
MENU_OPTION_DEBUG_UV1,
MENU_OPTION_DEBUG_UV2,
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index f70f0dc0aa..a3f2c2509f 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1301,26 +1301,15 @@ void ScriptEditor::_menu_option(int p_option) {
break;
}
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- if (EditorHelp::get_doc_data()->has_doc(doc.name)) {
- EditorHelp::get_doc_data()->remove_doc(doc.name);
- }
- }
+ if (script.is_valid()) {
+ clear_docs_from_script(script);
}
EditorNode::get_singleton()->push_item(resource.ptr());
EditorNode::get_singleton()->save_resource_as(resource);
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- EditorHelp::get_doc_data()->add_doc(doc);
- update_doc(doc.name);
- }
+ if (script.is_valid()) {
+ update_docs_from_script(script);
}
} break;
@@ -2418,14 +2407,8 @@ void ScriptEditor::save_current_script() {
return;
}
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- if (EditorHelp::get_doc_data()->has_doc(doc.name)) {
- EditorHelp::get_doc_data()->remove_doc(doc.name);
- }
- }
+ if (script.is_valid()) {
+ clear_docs_from_script(script);
}
if (resource->is_built_in()) {
@@ -2440,13 +2423,8 @@ void ScriptEditor::save_current_script() {
EditorNode::get_singleton()->save_resource(resource);
}
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- EditorHelp::get_doc_data()->add_doc(doc);
- update_doc(doc.name);
- }
+ if (script.is_valid()) {
+ update_docs_from_script(script);
}
}
@@ -2491,25 +2469,14 @@ void ScriptEditor::save_all_scripts() {
continue;
}
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- if (EditorHelp::get_doc_data()->has_doc(doc.name)) {
- EditorHelp::get_doc_data()->remove_doc(doc.name);
- }
- }
+ if (script.is_valid()) {
+ clear_docs_from_script(script);
}
EditorNode::get_singleton()->save_resource(edited_res); //external script, save it
- if (script != nullptr) {
- Vector<DocData::ClassDoc> documentations = script->get_documentation();
- for (int j = 0; j < documentations.size(); j++) {
- const DocData::ClassDoc &doc = documentations.get(j);
- EditorHelp::get_doc_data()->add_doc(doc);
- update_doc(doc.name);
- }
+ if (script.is_valid()) {
+ update_docs_from_script(script);
}
} else {
// For built-in scripts, save their scenes instead.
@@ -3331,6 +3298,29 @@ void ScriptEditor::update_doc(const String &p_name) {
}
}
+void ScriptEditor::clear_docs_from_script(const Ref<Script> &p_script) {
+ ERR_FAIL_COND(p_script.is_null());
+
+ Vector<DocData::ClassDoc> documentations = p_script->get_documentation();
+ for (int j = 0; j < documentations.size(); j++) {
+ const DocData::ClassDoc &doc = documentations.get(j);
+ if (EditorHelp::get_doc_data()->has_doc(doc.name)) {
+ EditorHelp::get_doc_data()->remove_doc(doc.name);
+ }
+ }
+}
+
+void ScriptEditor::update_docs_from_script(const Ref<Script> &p_script) {
+ ERR_FAIL_COND(p_script.is_null());
+
+ Vector<DocData::ClassDoc> documentations = p_script->get_documentation();
+ for (int j = 0; j < documentations.size(); j++) {
+ const DocData::ClassDoc &doc = documentations.get(j);
+ EditorHelp::get_doc_data()->add_doc(doc);
+ update_doc(doc.name);
+ }
+}
+
void ScriptEditor::_update_selected_editor_menu() {
for (int i = 0; i < tab_container->get_tab_count(); i++) {
bool current = tab_container->get_current_tab() == i;
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 233baa9bd3..aab713c9a3 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -508,6 +508,8 @@ public:
void goto_help(const String &p_desc) { _help_class_goto(p_desc); }
void update_doc(const String &p_name);
+ void clear_docs_from_script(const Ref<Script> &p_script);
+ void update_docs_from_script(const Ref<Script> &p_script);
bool can_take_away_focus() const;
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index dfd5e76ba6..ef3f451079 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -715,7 +715,7 @@ void TextShaderEditor::_notification(int p_what) {
popup->set_item_icon(popup->get_item_index(HELP_DOCS), get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
} break;
- case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
+ case NOTIFICATION_APPLICATION_FOCUS_IN: {
_check_for_external_edit();
} break;
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 7bcc8aa078..689570bcf6 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -804,6 +804,10 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_
TreeItem *item = Object::cast_to<TreeItem>(p_object);
ERR_FAIL_COND(!item);
+ if (!item->is_visible()) {
+ return;
+ }
+
NodePath np = item->get_metadata(0);
Node *n = get_node(np);
diff --git a/methods.py b/methods.py
index 7feffb2848..bec1b803e9 100644
--- a/methods.py
+++ b/methods.py
@@ -742,7 +742,7 @@ def generate_vs_project(env, num_jobs):
PLATFORMS = ["Win32", "x64"]
PLATFORM_IDS = ["x86_32", "x86_64"]
CONFIGURATIONS = ["editor", "template_release", "template_debug"]
- DEV_SUFFIX = ["", ".dev"]
+ DEV_SUFFIX = ".dev" if env["dev_build"] else ""
@staticmethod
def for_every_variant(value):
@@ -777,10 +777,9 @@ def generate_vs_project(env, num_jobs):
for platform in ModuleConfigs.PLATFORMS
]
self.arg_dict["runfile"] += [
- f'bin\\godot.windows.{config}{dev}.{plat_id}{f".{name}" if name else ""}.exe'
+ f'bin\\godot.windows.{config}{ModuleConfigs.DEV_SUFFIX}.{plat_id}{f".{name}" if name else ""}.exe'
for config in ModuleConfigs.CONFIGURATIONS
for plat_id in ModuleConfigs.PLATFORM_IDS
- for dev in ModuleConfigs.DEV_SUFFIX
]
self.arg_dict["cpppaths"] += ModuleConfigs.for_every_variant(env["CPPPATH"] + [includes])
self.arg_dict["cppdefines"] += ModuleConfigs.for_every_variant(env["CPPDEFINES"] + defines)
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index ccde0521f2..189e7fcc71 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -42,6 +42,7 @@ void GDScriptTextDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen);
ClassDB::bind_method(D_METHOD("didClose"), &GDScriptTextDocument::didClose);
ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange);
+ ClassDB::bind_method(D_METHOD("willSaveWaitUntil"), &GDScriptTextDocument::willSaveWaitUntil);
ClassDB::bind_method(D_METHOD("didSave"), &GDScriptTextDocument::didSave);
ClassDB::bind_method(D_METHOD("nativeSymbol"), &GDScriptTextDocument::nativeSymbol);
ClassDB::bind_method(D_METHOD("documentSymbol"), &GDScriptTextDocument::documentSymbol);
@@ -81,6 +82,16 @@ void GDScriptTextDocument::didChange(const Variant &p_param) {
sync_script_content(doc.uri, doc.text);
}
+void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) {
+ lsp::TextDocumentItem doc = load_document_item(p_param);
+
+ String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri);
+ Ref<Script> script = ResourceLoader::load(path);
+ if (script.is_valid()) {
+ ScriptEditor::get_singleton()->clear_docs_from_script(script);
+ }
+}
+
void GDScriptTextDocument::didSave(const Variant &p_param) {
lsp::TextDocumentItem doc = load_document_item(p_param);
Dictionary dict = p_param;
@@ -88,11 +99,16 @@ void GDScriptTextDocument::didSave(const Variant &p_param) {
sync_script_content(doc.uri, text);
- /*String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri);
-
+ String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri);
Ref<GDScript> script = ResourceLoader::load(path);
- script->load_source_code(path);
- script->reload(true);*/
+ if (script.is_valid() && (script->load_source_code(path) == OK)) {
+ if (script->is_tool()) {
+ script->get_language()->reload_tool_script(script, true);
+ } else {
+ script->reload(true);
+ }
+ ScriptEditor::get_singleton()->update_docs_from_script(script);
+ }
}
lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) {
@@ -417,14 +433,6 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin
GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content);
EditorFileSystem::get_singleton()->update_file(path);
- Error error;
- Ref<GDScript> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error);
- if (error == OK) {
- if (script->load_source_code(path) == OK) {
- script->reload(true);
- ScriptEditor::get_singleton()->reload_scripts(true); // Refresh scripts opened in the internal editor.
- }
- }
}
void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) {
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index 87bc08a34e..456c7d71fe 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -45,6 +45,7 @@ protected:
void didOpen(const Variant &p_param);
void didClose(const Variant &p_param);
void didChange(const Variant &p_param);
+ void willSaveWaitUntil(const Variant &p_param);
void didSave(const Variant &p_param);
void sync_script_content(const String &p_path, const String &p_content);
diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h
index fbd40796c4..024da1cab7 100644
--- a/modules/gdscript/language_server/godot_lsp.h
+++ b/modules/gdscript/language_server/godot_lsp.h
@@ -546,7 +546,7 @@ struct TextDocumentSyncOptions {
* If present will save wait until requests are sent to the server. If omitted the request should not be
* sent.
*/
- bool willSaveWaitUntil = false;
+ bool willSaveWaitUntil = true;
/**
* If present save notifications are sent to the server. If omitted the notification should not be
diff --git a/modules/gltf/config.py b/modules/gltf/config.py
index 189b5a831a..130c06d264 100644
--- a/modules/gltf/config.py
+++ b/modules/gltf/config.py
@@ -26,6 +26,7 @@ def get_doc_classes():
"GLTFSpecGloss",
"GLTFState",
"GLTFTexture",
+ "GLTFTextureSampler",
]
diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml
index 6c2f488c1c..56f3a70631 100644
--- a/modules/gltf/doc_classes/GLTFState.xml
+++ b/modules/gltf/doc_classes/GLTFState.xml
@@ -93,6 +93,12 @@
<description>
</description>
</method>
+ <method name="get_texture_samplers">
+ <return type="GLTFTextureSampler[]" />
+ <description>
+ Retrieves the array of texture samplers that are used by the textures contained in the GLTF.
+ </description>
+ </method>
<method name="get_textures">
<return type="GLTFTexture[]" />
<description>
@@ -180,6 +186,13 @@
<description>
</description>
</method>
+ <method name="set_texture_samplers">
+ <return type="void" />
+ <param index="0" name="texture_samplers" type="GLTFTextureSampler[]" />
+ <description>
+ Sets the array of texture samplers that are used by the textures contained in the GLTF.
+ </description>
+ </method>
<method name="set_textures">
<return type="void" />
<param index="0" name="textures" type="GLTFTexture[]" />
diff --git a/modules/gltf/doc_classes/GLTFTexture.xml b/modules/gltf/doc_classes/GLTFTexture.xml
index c0bc424168..f4486fd504 100644
--- a/modules/gltf/doc_classes/GLTFTexture.xml
+++ b/modules/gltf/doc_classes/GLTFTexture.xml
@@ -7,6 +7,9 @@
<tutorials>
</tutorials>
<members>
+ <member name="sampler" type="int" setter="set_sampler" getter="get_sampler" default="-1">
+ ID of the texture sampler to use when sampling the image. If -1, then the default texture sampler is used (linear filtering, and repeat wrapping in both axes).
+ </member>
<member name="src_image" type="int" setter="set_src_image" getter="get_src_image" default="0">
</member>
</members>
diff --git a/modules/gltf/doc_classes/GLTFTextureSampler.xml b/modules/gltf/doc_classes/GLTFTextureSampler.xml
new file mode 100644
index 0000000000..1cc69bfe73
--- /dev/null
+++ b/modules/gltf/doc_classes/GLTFTextureSampler.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="GLTFTextureSampler" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ Represents a GLTF texture sampler
+ </brief_description>
+ <description>
+ Represents a texture sampler as defined by the base GLTF spec. Texture samplers in GLTF specify how to sample data from the texture's base image, when rendering the texture on an object.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="mag_filter" type="int" setter="set_mag_filter" getter="get_mag_filter" default="9729">
+ Texture's magnification filter, used when texture appears larger on screen than the source image.
+ </member>
+ <member name="min_filter" type="int" setter="set_min_filter" getter="get_min_filter" default="9987">
+ Texture's minification filter, used when the texture appears smaller on screen than the source image.
+ </member>
+ <member name="wrap_s" type="int" setter="set_wrap_s" getter="get_wrap_s" default="10497">
+ Wrapping mode to use for S-axis (horizontal) texture coordinates.
+ </member>
+ <member name="wrap_t" type="int" setter="set_wrap_t" getter="get_wrap_t" default="10497">
+ Wrapping mode to use for T-axis (vertical) texture coordinates.
+ </member>
+ </members>
+</class>
diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h
index 9ee2397968..23bf33869e 100644
--- a/modules/gltf/gltf_defines.h
+++ b/modules/gltf/gltf_defines.h
@@ -58,6 +58,7 @@ class GLTFSkin;
class GLTFSpecGloss;
class GLTFState;
class GLTFTexture;
+class GLTFTextureSampler;
// GLTF index aliases.
using GLTFAccessorIndex = int;
@@ -73,6 +74,7 @@ using GLTFNodeIndex = int;
using GLTFSkeletonIndex = int;
using GLTFSkinIndex = int;
using GLTFTextureIndex = int;
+using GLTFTextureSamplerIndex = int;
enum GLTFType {
TYPE_SCALAR,
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 8d2e37be3a..35358734d6 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -145,6 +145,12 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
return Error::FAILED;
}
+ /* STEP SERIALIZE TEXTURE SAMPLERS */
+ err = _serialize_texture_samplers(state);
+ if (err != OK) {
+ return Error::FAILED;
+ }
+
/* STEP SERIALIZE ANIMATIONS */
err = _serialize_animations(state);
if (err != OK) {
@@ -3219,6 +3225,11 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t = state->textures[i];
ERR_CONTINUE(t->get_src_image() == -1);
d["source"] = t->get_src_image();
+
+ GLTFTextureSamplerIndex sampler_index = t->get_sampler();
+ if (sampler_index != -1) {
+ d["sampler"] = sampler_index;
+ }
textures.push_back(d);
}
state->json["textures"] = textures;
@@ -3240,13 +3251,18 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t;
t.instantiate();
t->set_src_image(d["source"]);
+ if (d.has("sampler")) {
+ t->set_sampler(d["sampler"]);
+ } else {
+ t->set_sampler(-1);
+ }
state->textures.push_back(t);
}
return OK;
}
-GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture) {
+GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
ERR_FAIL_COND_V(p_texture.is_null(), -1);
Ref<GLTFTexture> gltf_texture;
gltf_texture.instantiate();
@@ -3254,6 +3270,7 @@ GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D>
GLTFImageIndex gltf_src_image_i = state->images.size();
state->images.push_back(p_texture);
gltf_texture->set_src_image(gltf_src_image_i);
+ gltf_texture->set_sampler(_set_sampler_for_mode(state, p_filter_mode, p_repeats));
GLTFTextureIndex gltf_texture_i = state->textures.size();
state->textures.push_back(gltf_texture);
return gltf_texture_i;
@@ -3268,6 +3285,102 @@ Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextur
return state->images[image];
}
+GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) {
+ for (int i = 0; i < state->texture_samplers.size(); ++i) {
+ if (state->texture_samplers[i]->get_filter_mode() == p_filter_mode) {
+ return i;
+ }
+ }
+
+ GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size();
+ Ref<GLTFTextureSampler> gltf_sampler;
+ gltf_sampler.instantiate();
+ gltf_sampler->set_filter_mode(p_filter_mode);
+ gltf_sampler->set_wrap_mode(p_repeats);
+ state->texture_samplers.push_back(gltf_sampler);
+ return gltf_sampler_i;
+}
+
+Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
+ ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>());
+ const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler();
+
+ if (sampler == -1) {
+ return state->default_texture_sampler;
+ } else {
+ ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref<GLTFTextureSampler>());
+
+ return state->texture_samplers[sampler];
+ }
+}
+
+Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) {
+ if (!state->texture_samplers.size()) {
+ return OK;
+ }
+
+ Array samplers;
+ for (int32_t i = 0; i < state->texture_samplers.size(); ++i) {
+ Dictionary d;
+ Ref<GLTFTextureSampler> s = state->texture_samplers[i];
+ d["magFilter"] = s->get_mag_filter();
+ d["minFilter"] = s->get_min_filter();
+ d["wrapS"] = s->get_wrap_s();
+ d["wrapT"] = s->get_wrap_t();
+ samplers.push_back(d);
+ }
+ state->json["samplers"] = samplers;
+
+ return OK;
+}
+
+Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) {
+ state->default_texture_sampler.instantiate();
+ state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
+ state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
+ state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
+ state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
+
+ if (!state->json.has("samplers")) {
+ return OK;
+ }
+
+ const Array &samplers = state->json["samplers"];
+ for (int i = 0; i < samplers.size(); ++i) {
+ const Dictionary &d = samplers[i];
+
+ Ref<GLTFTextureSampler> sampler;
+ sampler.instantiate();
+
+ if (d.has("minFilter")) {
+ sampler->set_min_filter(d["minFilter"]);
+ } else {
+ sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
+ }
+ if (d.has("magFilter")) {
+ sampler->set_mag_filter(d["magFilter"]);
+ } else {
+ sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
+ }
+
+ if (d.has("wrapS")) {
+ sampler->set_wrap_s(d["wrapS"]);
+ } else {
+ sampler->set_wrap_s(GLTFTextureSampler::WrapMode::DEFAULT);
+ }
+
+ if (d.has("wrapT")) {
+ sampler->set_wrap_t(d["wrapT"]);
+ } else {
+ sampler->set_wrap_t(GLTFTextureSampler::WrapMode::DEFAULT);
+ }
+
+ state->texture_samplers.push_back(sampler);
+ }
+
+ return OK;
+}
+
Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
Array materials;
for (int32_t i = 0; i < state->materials.size(); i++) {
@@ -3299,7 +3412,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
albedo_texture->set_name(material->get_name() + "_albedo");
- gltf_texture_index = _set_texture(state, albedo_texture);
+ gltf_texture_index = _set_texture(state, albedo_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
if (gltf_texture_index != -1) {
bct["index"] = gltf_texture_index;
@@ -3429,7 +3542,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
GLTFTextureIndex orm_texture_index = -1;
if (has_ao || has_roughness || has_metalness) {
orm_texture->set_name(material->get_name() + "_orm");
- orm_texture_index = _set_texture(state, orm_texture);
+ orm_texture_index = _set_texture(state, orm_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
if (has_ao) {
Dictionary occt;
@@ -3484,7 +3597,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
GLTFTextureIndex gltf_texture_index = -1;
if (tex.is_valid() && tex->get_image().is_valid()) {
tex->set_name(material->get_name() + "_normal");
- gltf_texture_index = _set_texture(state, tex);
+ gltf_texture_index = _set_texture(state, tex, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
nt["scale"] = material->get_normal_scale();
if (gltf_texture_index != -1) {
@@ -3507,7 +3620,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
GLTFTextureIndex gltf_texture_index = -1;
if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) {
emission_texture->set_name(material->get_name() + "_emission");
- gltf_texture_index = _set_texture(state, emission_texture);
+ gltf_texture_index = _set_texture(state, emission_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
}
if (gltf_texture_index != -1) {
@@ -3566,6 +3679,11 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (sgm.has("diffuseTexture")) {
const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"];
if (diffuse_texture_dict.has("index")) {
+ Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(state, diffuse_texture_dict["index"]);
+ if (diffuse_sampler.is_valid()) {
+ material->set_texture_filter(diffuse_sampler->get_filter_mode());
+ material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, diffuse_sampler->get_wrap_mode());
+ }
Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]);
if (diffuse_texture.is_valid()) {
spec_gloss->diffuse_img = diffuse_texture->get_image();
@@ -3614,6 +3732,9 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (mr.has("baseColorTexture")) {
const Dictionary &bct = mr["baseColorTexture"];
if (bct.has("index")) {
+ Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(state, bct["index"]);
+ material->set_texture_filter(bct_sampler->get_filter_mode());
+ material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, bct_sampler->get_wrap_mode());
material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"]));
}
if (!mr.has("baseColorFactor")) {
@@ -6477,8 +6598,10 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
err = ext->import_preflight(state);
ERR_FAIL_COND_V(err != OK, err);
}
+
err = _parse_gltf_state(state, p_path, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
+
return OK;
}
@@ -6834,6 +6957,11 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+ /* PARSE TEXTURE SAMPLERS */
+ err = _parse_texture_samplers(state);
+
+ ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+
/* PARSE TEXTURES */
err = _parse_textures(state);
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 750d3d403e..62b6e29fe0 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -95,9 +95,14 @@ private:
String _gen_unique_bone_name(Ref<GLTFState> state,
const GLTFSkeletonIndex skel_i,
const String &p_name);
- GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture);
+ GLTFTextureIndex _set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture,
+ StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats);
Ref<Texture2D> _get_texture(Ref<GLTFState> state,
const GLTFTextureIndex p_texture);
+ GLTFTextureSamplerIndex _set_sampler_for_mode(Ref<GLTFState> state,
+ StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats);
+ Ref<GLTFTextureSampler> _get_sampler_for_texture(Ref<GLTFState> state,
+ const GLTFTextureIndex p_texture);
Error _parse_json(const String &p_path, Ref<GLTFState> state);
Error _parse_glb(Ref<FileAccess> f, Ref<GLTFState> state);
void _compute_node_heights(Ref<GLTFState> state);
@@ -145,10 +150,12 @@ private:
const bool p_for_vertex);
Error _parse_meshes(Ref<GLTFState> state);
Error _serialize_textures(Ref<GLTFState> state);
+ Error _serialize_texture_samplers(Ref<GLTFState> state);
Error _serialize_images(Ref<GLTFState> state, const String &p_path);
Error _serialize_lights(Ref<GLTFState> state);
Error _parse_images(Ref<GLTFState> state, const String &p_base_path);
Error _parse_textures(Ref<GLTFState> state);
+ Error _parse_texture_samplers(Ref<GLTFState> state);
Error _parse_materials(Ref<GLTFState> state);
void _set_texture_transform_uv1(const Dictionary &d, Ref<BaseMaterial3D> material);
void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss,
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index a23fb39503..60192c67e6 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -64,6 +64,8 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes);
ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures);
ClassDB::bind_method(D_METHOD("set_textures", "textures"), &GLTFState::set_textures);
+ ClassDB::bind_method(D_METHOD("get_texture_samplers"), &GLTFState::get_texture_samplers);
+ ClassDB::bind_method(D_METHOD("set_texture_samplers", "texture_samplers"), &GLTFState::set_texture_samplers);
ClassDB::bind_method(D_METHOD("get_images"), &GLTFState::get_images);
ClassDB::bind_method(D_METHOD("set_images", "images"), &GLTFState::set_images);
ClassDB::bind_method(D_METHOD("get_skins"), &GLTFState::get_skins);
@@ -101,6 +103,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_path"), "set_base_path", "get_base_path"); // String
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector<int>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector<Ref<GLTFTexture>>
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "texture_samplers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_texture_samplers", "get_texture_samplers"); //Vector<Ref<GLTFTextureSampler>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector<Ref<Texture>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector<Ref<GLTFSkin>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>>
@@ -236,6 +239,14 @@ void GLTFState::set_textures(TypedArray<GLTFTexture> p_textures) {
GLTFTemplateConvert::set_from_array(textures, p_textures);
}
+TypedArray<GLTFTextureSampler> GLTFState::get_texture_samplers() {
+ return GLTFTemplateConvert::to_array(texture_samplers);
+}
+
+void GLTFState::set_texture_samplers(TypedArray<GLTFTextureSampler> p_texture_samplers) {
+ GLTFTemplateConvert::set_from_array(texture_samplers, p_texture_samplers);
+}
+
TypedArray<Texture2D> GLTFState::get_images() {
return GLTFTemplateConvert::to_array(images);
}
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index 791431f376..afe7e82010 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -42,6 +42,7 @@
#include "structures/gltf_skeleton.h"
#include "structures/gltf_skin.h"
#include "structures/gltf_texture.h"
+#include "structures/gltf_texture_sampler.h"
#include "core/templates/rb_map.h"
#include "scene/animation/animation_player.h"
@@ -77,6 +78,8 @@ class GLTFState : public Resource {
String scene_name;
Vector<int> root_nodes;
Vector<Ref<GLTFTexture>> textures;
+ Vector<Ref<GLTFTextureSampler>> texture_samplers;
+ Ref<GLTFTextureSampler> default_texture_sampler;
Vector<Ref<Texture2D>> images;
Vector<String> extensions_used;
Vector<String> extensions_required;
@@ -149,6 +152,9 @@ public:
TypedArray<GLTFTexture> get_textures();
void set_textures(TypedArray<GLTFTexture> p_textures);
+ TypedArray<GLTFTextureSampler> get_texture_samplers();
+ void set_texture_samplers(TypedArray<GLTFTextureSampler> p_texture_samplers);
+
TypedArray<Texture2D> get_images();
void set_images(TypedArray<Texture2D> p_images);
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index 6e7f7d6fed..b9027f6e3d 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -47,6 +47,7 @@
#include "structures/gltf_skeleton.h"
#include "structures/gltf_skin.h"
#include "structures/gltf_texture.h"
+#include "structures/gltf_texture_sampler.h"
#ifdef TOOLS_ENABLED
#include "core/config/project_settings.h"
@@ -126,6 +127,7 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFSpecGloss);
GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFTexture);
+ GDREGISTER_CLASS(GLTFTextureSampler);
}
#ifdef TOOLS_ENABLED
diff --git a/modules/gltf/structures/gltf_texture.cpp b/modules/gltf/structures/gltf_texture.cpp
index 2a21cb3df8..5cc96e3221 100644
--- a/modules/gltf/structures/gltf_texture.cpp
+++ b/modules/gltf/structures/gltf_texture.cpp
@@ -33,8 +33,11 @@
void GLTFTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_src_image"), &GLTFTexture::get_src_image);
ClassDB::bind_method(D_METHOD("set_src_image", "src_image"), &GLTFTexture::set_src_image);
+ ClassDB::bind_method(D_METHOD("get_sampler"), &GLTFTexture::get_sampler);
+ ClassDB::bind_method(D_METHOD("set_sampler", "sampler"), &GLTFTexture::set_sampler);
ADD_PROPERTY(PropertyInfo(Variant::INT, "src_image"), "set_src_image", "get_src_image"); // int
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sampler"), "set_sampler", "get_sampler"); // int
}
GLTFImageIndex GLTFTexture::get_src_image() const {
@@ -44,3 +47,11 @@ GLTFImageIndex GLTFTexture::get_src_image() const {
void GLTFTexture::set_src_image(GLTFImageIndex val) {
src_image = val;
}
+
+GLTFTextureSamplerIndex GLTFTexture::get_sampler() const {
+ return sampler;
+}
+
+void GLTFTexture::set_sampler(GLTFTextureSamplerIndex val) {
+ sampler = val;
+}
diff --git a/modules/gltf/structures/gltf_texture.h b/modules/gltf/structures/gltf_texture.h
index b1d12dddfa..b26c8a7b07 100644
--- a/modules/gltf/structures/gltf_texture.h
+++ b/modules/gltf/structures/gltf_texture.h
@@ -39,6 +39,7 @@ class GLTFTexture : public Resource {
private:
GLTFImageIndex src_image = 0;
+ GLTFTextureSamplerIndex sampler = -1;
protected:
static void _bind_methods();
@@ -46,6 +47,8 @@ protected:
public:
GLTFImageIndex get_src_image() const;
void set_src_image(GLTFImageIndex val);
+ GLTFTextureSamplerIndex get_sampler() const;
+ void set_sampler(GLTFTextureSamplerIndex val);
};
#endif // GLTF_TEXTURE_H
diff --git a/modules/gltf/structures/gltf_texture_sampler.cpp b/modules/gltf/structures/gltf_texture_sampler.cpp
new file mode 100644
index 0000000000..6cf615b6cc
--- /dev/null
+++ b/modules/gltf/structures/gltf_texture_sampler.cpp
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* gltf_texture_sampler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gltf_texture_sampler.h"
+
+void GLTFTextureSampler::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_mag_filter"), &GLTFTextureSampler::get_mag_filter);
+ ClassDB::bind_method(D_METHOD("set_mag_filter", "filter_mode"), &GLTFTextureSampler::set_mag_filter);
+ ClassDB::bind_method(D_METHOD("get_min_filter"), &GLTFTextureSampler::get_min_filter);
+ ClassDB::bind_method(D_METHOD("set_min_filter", "filter_mode"), &GLTFTextureSampler::set_min_filter);
+ ClassDB::bind_method(D_METHOD("get_wrap_s"), &GLTFTextureSampler::get_wrap_s);
+ ClassDB::bind_method(D_METHOD("set_wrap_s", "wrap_mode"), &GLTFTextureSampler::set_wrap_s);
+ ClassDB::bind_method(D_METHOD("get_wrap_t"), &GLTFTextureSampler::get_wrap_t);
+ ClassDB::bind_method(D_METHOD("set_wrap_t", "wrap_mode"), &GLTFTextureSampler::set_wrap_t);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mag_filter"), "set_mag_filter", "get_mag_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "min_filter"), "set_min_filter", "get_min_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_s"), "set_wrap_s", "get_wrap_s");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_t"), "set_wrap_t", "get_wrap_t");
+}
diff --git a/modules/gltf/structures/gltf_texture_sampler.h b/modules/gltf/structures/gltf_texture_sampler.h
new file mode 100644
index 0000000000..3fad31bbee
--- /dev/null
+++ b/modules/gltf/structures/gltf_texture_sampler.h
@@ -0,0 +1,163 @@
+/*************************************************************************/
+/* gltf_texture_sampler.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GLTF_TEXTURE_SAMPLER_H
+#define GLTF_TEXTURE_SAMPLER_H
+
+#include "core/io/resource.h"
+#include "scene/resources/material.h"
+
+class GLTFTextureSampler : public Resource {
+ GDCLASS(GLTFTextureSampler, Resource);
+
+public:
+ enum FilterMode {
+ NEAREST = 9728,
+ LINEAR = 9729,
+ NEAREST_MIPMAP_NEAREST = 9984,
+ LINEAR_MIPMAP_NEAREST = 9985,
+ NEAREST_MIPMAP_LINEAR = 9986,
+ LINEAR_MIPMAP_LINEAR = 9987
+ };
+
+ enum WrapMode {
+ CLAMP_TO_EDGE = 33071,
+ MIRRORED_REPEAT = 33648,
+ REPEAT = 10497,
+ DEFAULT = REPEAT
+ };
+
+ int get_mag_filter() const {
+ return mag_filter;
+ }
+
+ void set_mag_filter(const int filter_mode) {
+ mag_filter = (FilterMode)filter_mode;
+ }
+
+ int get_min_filter() const {
+ return min_filter;
+ }
+
+ void set_min_filter(const int filter_mode) {
+ min_filter = (FilterMode)filter_mode;
+ }
+
+ int get_wrap_s() const {
+ return wrap_s;
+ }
+
+ void set_wrap_s(const int wrap_mode) {
+ wrap_s = (WrapMode)wrap_mode;
+ }
+
+ int get_wrap_t() const {
+ return wrap_t;
+ }
+
+ void set_wrap_t(const int wrap_mode) {
+ wrap_s = (WrapMode)wrap_mode;
+ }
+
+ StandardMaterial3D::TextureFilter get_filter_mode() const {
+ using TextureFilter = StandardMaterial3D::TextureFilter;
+
+ switch (min_filter) {
+ case NEAREST:
+ return TextureFilter::TEXTURE_FILTER_NEAREST;
+ case LINEAR:
+ return TextureFilter::TEXTURE_FILTER_LINEAR;
+ case NEAREST_MIPMAP_NEAREST:
+ case NEAREST_MIPMAP_LINEAR:
+ return TextureFilter::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS;
+ case LINEAR_MIPMAP_NEAREST:
+ case LINEAR_MIPMAP_LINEAR:
+ default:
+ return TextureFilter::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
+ }
+ }
+
+ void set_filter_mode(StandardMaterial3D::TextureFilter mode) {
+ using TextureFilter = StandardMaterial3D::TextureFilter;
+
+ switch (mode) {
+ case TextureFilter::TEXTURE_FILTER_NEAREST:
+ min_filter = FilterMode::NEAREST;
+ mag_filter = FilterMode::NEAREST;
+ break;
+ case TextureFilter::TEXTURE_FILTER_LINEAR:
+ min_filter = FilterMode::LINEAR;
+ mag_filter = FilterMode::LINEAR;
+ break;
+ case TextureFilter::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS:
+ case TextureFilter::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC:
+ min_filter = FilterMode::NEAREST_MIPMAP_LINEAR;
+ mag_filter = FilterMode::NEAREST;
+ break;
+ case TextureFilter::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS:
+ case TextureFilter::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC:
+ default:
+ min_filter = FilterMode::LINEAR_MIPMAP_LINEAR;
+ mag_filter = FilterMode::LINEAR;
+ break;
+ }
+ }
+
+ bool get_wrap_mode() const {
+ // BaseMaterial3D presents wrapping as a boolean property. Either the texture is repeated
+ // in both dimensions, non-mirrored, or it isn't repeated at all. This will cause oddities
+ // when people import models having other wrapping mode combinations.
+ return (wrap_s == WrapMode::REPEAT) && (wrap_t == WrapMode::REPEAT);
+ }
+
+ void set_wrap_mode(bool mat_repeats) {
+ if (mat_repeats) {
+ wrap_s = WrapMode::REPEAT;
+ wrap_t = WrapMode::REPEAT;
+ } else {
+ wrap_s = WrapMode::CLAMP_TO_EDGE;
+ wrap_t = WrapMode::CLAMP_TO_EDGE;
+ }
+ }
+
+protected:
+ static void _bind_methods();
+
+private:
+ FilterMode mag_filter = FilterMode::LINEAR;
+ FilterMode min_filter = FilterMode::LINEAR_MIPMAP_LINEAR;
+ WrapMode wrap_s = WrapMode::REPEAT;
+ WrapMode wrap_t = WrapMode::REPEAT;
+};
+
+VARIANT_ENUM_CAST(GLTFTextureSampler::FilterMode);
+VARIANT_ENUM_CAST(GLTFTextureSampler::WrapMode);
+
+#endif // GLTF_TEXTURE_SAMPLER_H
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index d469c28d4a..e5e53acb07 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -48,20 +48,10 @@ class CSharpScript;
class CSharpInstance;
class CSharpLanguage;
-#ifdef NO_SAFE_CAST
-template <typename TScriptInstance, typename TScriptLanguage>
-TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
- if (!p_inst) {
- return nullptr;
- }
- return p_inst->get_language() == TScriptLanguage::get_singleton() ? static_cast<TScriptInstance *>(p_inst) : nullptr;
-}
-#else
template <typename TScriptInstance, typename TScriptLanguage>
TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
return dynamic_cast<TScriptInstance *>(p_inst);
}
-#endif
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
diff --git a/platform/android/detect.py b/platform/android/detect.py
index e541aa0373..6eb8ba34ed 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -156,22 +156,16 @@ def configure(env: "Environment"):
env["RANLIB"] = compiler_path + "/llvm-ranlib"
env["AS"] = compiler_path + "/clang"
- # Disable exceptions and rtti on non-tools (template) builds
- if env.editor_build:
- env.Append(CXXFLAGS=["-frtti"])
- elif env["builtin_icu"]:
- env.Append(CXXFLAGS=["-frtti", "-fno-exceptions"])
- else:
- env.Append(CXXFLAGS=["-fno-rtti", "-fno-exceptions"])
- # Don't use dynamic_cast, necessary with no-rtti.
- env.Append(CPPDEFINES=["NO_SAFE_CAST"])
+ # Disable exceptions on template builds
+ if not env.editor_build:
+ env.Append(CXXFLAGS=["-fno-exceptions"])
env.Append(
CCFLAGS=(
"-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split()
)
)
- env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"])
+ env.Append(CPPDEFINES=["GLES_ENABLED"])
if get_min_sdk_version(env["ndk_platform"]) >= 24:
env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
@@ -193,7 +187,7 @@ def configure(env: "Environment"):
env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so")
env.Prepend(CPPPATH=["#platform/android"])
- env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED", "NO_FCNTL"])
+ env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])
env.Append(LIBS=["OpenSLES", "EGL", "GLESv2", "android", "log", "z", "dl"])
if env["vulkan"]:
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 81fc941608..1ef1deb971 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -49,10 +49,14 @@
#include "drivers/gles3/rasterizer_gles3.h"
#endif
+#include <dlfcn.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
@@ -66,17 +70,6 @@
#define _NET_WM_STATE_REMOVE 0L // remove/unset property
#define _NET_WM_STATE_ADD 1L // add/set property
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-//stupid linux.h
-#ifdef KEY_TAB
-#undef KEY_TAB
-#endif
-
#undef CursorShape
#include <X11/XKBlib.h>
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index f4e94f1a91..4cbd9722ad 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -42,12 +42,10 @@
#include <mntent.h>
#endif
+#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <dlfcn.h>
-#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
diff --git a/platform/macos/dir_access_macos.h b/platform/macos/dir_access_macos.h
index 920e69ef3e..c76b2835e8 100644
--- a/platform/macos/dir_access_macos.h
+++ b/platform/macos/dir_access_macos.h
@@ -31,16 +31,16 @@
#ifndef DIR_ACCESS_MACOS_H
#define DIR_ACCESS_MACOS_H
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
+
+#include "core/io/dir_access.h"
+#include "drivers/unix/dir_access_unix.h"
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
-#include "core/io/dir_access.h"
-#include "drivers/unix/dir_access_unix.h"
-
class DirAccessMacOS : public DirAccessUnix {
protected:
virtual String fix_unicode_name(const char *p_name) const override;
@@ -51,6 +51,6 @@ protected:
virtual bool is_hidden(const String &p_name) override;
};
-#endif // UNIX ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX ENABLED
#endif // DIR_ACCESS_MACOS_H
diff --git a/platform/macos/dir_access_macos.mm b/platform/macos/dir_access_macos.mm
index 3373cada1f..22ebac2db4 100644
--- a/platform/macos/dir_access_macos.mm
+++ b/platform/macos/dir_access_macos.mm
@@ -30,7 +30,7 @@
#include "dir_access_macos.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include <errno.h>
@@ -78,4 +78,4 @@ bool DirAccessMacOS::is_hidden(const String &p_name) {
return [hidden boolValue];
}
-#endif // UNIX_ENABLED || LIBC_FILEIO_ENABLED
+#endif // UNIX_ENABLED
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 1914c5f35d..f980129081 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -586,7 +586,7 @@ void DisplayServerMacOS::send_event(NSEvent *p_event) {
// Special case handling of command-period, which is traditionally a special
// shortcut in macOS and doesn't arrive at our regular keyDown handler.
if ([p_event type] == NSEventTypeKeyDown) {
- if (([p_event modifierFlags] & NSEventModifierFlagCommand) && [p_event keyCode] == 0x2f) {
+ if ((([p_event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == NSEventModifierFlagCommand) && [p_event keyCode] == 0x2f) {
Ref<InputEventKey> k;
k.instantiate();
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 0c1c4a793a..c1df7827cd 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -42,9 +42,9 @@
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
-#include <fcntl.h>
#include <io.h>
#include <stdio.h>
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 77b20dd924..9e958be26f 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -565,7 +565,7 @@ bool DisplayServerWindows::screen_is_touchscreen(int p_screen) const {
#ifndef _MSC_VER
#warning touchscreen not working
#endif
- return false;
+ return DisplayServer::screen_is_touchscreen(p_screen);
}
void DisplayServerWindows::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) {
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index d85d6364bd..3523e8b3d1 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -61,9 +61,9 @@
#include "gl_manager_windows.h"
#endif
-#include <fcntl.h>
#include <io.h>
#include <stdio.h>
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 491de2266f..419871f8bf 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -40,6 +40,7 @@
#include "drivers/winmidi/midi_driver_winmidi.h"
#include "key_mapping_windows.h"
#include "servers/audio_server.h"
+
#ifdef XAUDIO2_ENABLED
#include "drivers/xaudio2/audio_driver_xaudio2.h"
#endif
@@ -49,10 +50,10 @@
#include "platform/windows/vulkan_context_win.h"
#endif
-#include <fcntl.h>
#include <io.h>
#include <shellapi.h>
#include <stdio.h>
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index a76f4dd0d5..b0503c9c02 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -390,13 +390,13 @@ void MeshInstance3D::_mesh_changed() {
update_gizmos();
}
-void MeshInstance3D::create_debug_tangents() {
+MeshInstance3D *MeshInstance3D::create_debug_tangents_node() {
Vector<Vector3> lines;
Vector<Color> colors;
Ref<Mesh> mesh = get_mesh();
if (!mesh.is_valid()) {
- return;
+ return nullptr;
}
for (int i = 0; i < mesh->get_surface_count(); i++) {
@@ -457,15 +457,23 @@ void MeshInstance3D::create_debug_tangents() {
MeshInstance3D *mi = memnew(MeshInstance3D);
mi->set_mesh(am);
mi->set_name("DebugTangents");
- add_child(mi, true);
-#ifdef TOOLS_ENABLED
+ return mi;
+ }
- if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) {
- mi->set_owner(this);
- } else {
- mi->set_owner(get_owner());
- }
-#endif
+ return nullptr;
+}
+
+void MeshInstance3D::create_debug_tangents() {
+ MeshInstance3D *mi = create_debug_tangents_node();
+ if (!mi) {
+ return;
+ }
+
+ add_child(mi, true);
+ if (is_inside_tree() && this == get_tree()->get_edited_scene_root()) {
+ mi->set_owner(this);
+ } else {
+ mi->set_owner(get_owner());
}
}
@@ -495,8 +503,6 @@ void MeshInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_value", "blend_shape_idx", "value"), &MeshInstance3D::set_blend_shape_value);
ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance3D::create_debug_tangents);
- ClassDB::set_method_flags("MeshInstance3D", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_GROUP("Skeleton", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 48d76b9a88..caf7d25616 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -90,6 +90,7 @@ public:
Node *create_multiple_convex_collisions_node();
void create_multiple_convex_collisions();
+ MeshInstance3D *create_debug_tangents_node();
void create_debug_tangents();
virtual AABB get_aabb() const override;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 761072c5bc..a6aa4707ff 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -162,7 +162,7 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
drag_accum = Vector2();
last_drag_accum = Vector2();
drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value());
- drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
+ drag_touching = DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
drag_touching_deaccel = false;
beyond_deadzone = false;
time_since_motion = 0;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index a2b0f1a825..bbdba16cb5 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1466,20 +1466,10 @@ bool Node::is_greater_than(const Node *p_node) const {
ERR_FAIL_COND_V(data.depth < 0, false);
ERR_FAIL_COND_V(p_node->data.depth < 0, false);
-#ifdef NO_ALLOCA
-
- Vector<int> this_stack;
- Vector<int> that_stack;
- this_stack.resize(data.depth);
- that_stack.resize(p_node->data.depth);
-
-#else
int *this_stack = (int *)alloca(sizeof(int) * data.depth);
int *that_stack = (int *)alloca(sizeof(int) * p_node->data.depth);
-#endif
-
const Node *n = this;
int idx = data.depth - 1;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 05b4f181c2..0795d91035 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -499,6 +499,13 @@ void Viewport::_notification(int p_what) {
// exit event if the change in focus results in the mouse exiting
// the window.
} break;
+
+ case NOTIFICATION_PREDELETE: {
+ if (gui_parent) {
+ gui_parent->gui.tooltip_popup = nullptr;
+ gui_parent->gui.tooltip_label = nullptr;
+ }
+ } break;
}
}
@@ -1155,8 +1162,6 @@ void Viewport::_gui_cancel_tooltip() {
}
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
- gui.tooltip_popup = nullptr;
- gui.tooltip_label = nullptr;
}
}
@@ -1219,8 +1224,6 @@ void Viewport::_gui_show_tooltip() {
// Remove previous popup if we change something.
if (gui.tooltip_popup) {
memdelete(gui.tooltip_popup);
- gui.tooltip_popup = nullptr;
- gui.tooltip_label = nullptr;
}
if (!tooltip_owner) {
@@ -1252,6 +1255,7 @@ void Viewport::_gui_show_tooltip() {
panel->set_flag(Window::FLAG_POPUP, false);
panel->set_wrap_controls(true);
panel->add_child(base_tooltip);
+ panel->gui_parent = this;
gui.tooltip_popup = panel;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 471dc41246..6f67649ea3 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -208,6 +208,7 @@ private:
friend class ViewportTexture;
Viewport *parent = nullptr;
+ Viewport *gui_parent = nullptr; // Whose gui.tooltip_popup it is.
AudioListener2D *audio_listener_2d = nullptr;
Camera2D *camera_2d = nullptr;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 64869b2936..f7099f3765 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1264,12 +1264,16 @@ void Window::popup(const Rect2i &p_screen_rect) {
set_transient(true);
set_visible(true);
- int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id());
- Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id);
- if (screen_rect != Rect2i() && !screen_rect.intersects(Rect2i(position, size))) {
+ Rect2i parent_rect;
+ if (is_embedded()) {
+ parent_rect = _get_embedder()->get_visible_rect();
+ } else {
+ int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id());
+ parent_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id);
+ }
+ if (parent_rect != Rect2i() && !parent_rect.intersects(Rect2i(position, size))) {
ERR_PRINT(vformat("Window %d spawned at invalid position: %s.", get_window_id(), position));
- // Window appeared on unavailable screen area, so force it to the center.
- set_position(screen_rect.size / 2 - size / 2);
+ set_position((parent_rect.size - size) / 2);
}
_post_popup();