summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--core/dictionary.cpp23
-rw-r--r--doc/classes/CanvasItem.xml22
-rw-r--r--doc/classes/EditorSpinSlider.xml22
-rw-r--r--doc/classes/OS.xml2
-rw-r--r--doc/classes/RichTextLabel.xml30
-rw-r--r--doc/classes/TextEdit.xml2
-rw-r--r--doc/classes/VideoPlayer.xml2
-rw-r--r--doc/classes/VisualShader.xml3
-rw-r--r--doc/classes/VisualShaderNodeCubeMap.xml6
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp6
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp6
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp14
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp6
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp67
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h4
-rw-r--r--drivers/unix/file_access_unix.cpp27
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp15
-rw-r--r--editor/plugins/asset_library_editor_plugin.h1
-rw-r--r--editor/plugins/curve_editor_plugin.cpp3
-rw-r--r--editor/project_settings_editor.cpp7
-rwxr-xr-xmisc/travis/android-tools-linux.sh3
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml8
-rw-r--r--scene/2d/canvas_item.cpp12
-rw-r--r--scene/gui/text_edit.cpp4
-rw-r--r--servers/visual/shader_language.cpp29
-rw-r--r--servers/visual/shader_language.h2
28 files changed, 250 insertions, 88 deletions
diff --git a/.travis.yml b/.travis.yml
index 49d1059360..8a6f80002b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -71,6 +71,10 @@ matrix:
env: PLATFORM=android TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes"
os: linux
compiler: clang
+ addons:
+ apt:
+ packages:
+ - openjdk-8-jdk
- name: macOS editor (debug, Clang)
stage: build
@@ -116,14 +120,14 @@ before_install:
install:
- pip install --user scons;
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$PLATFORM" = "android" ]; then
+ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64;
+ export PATH=/usr/lib/jvm/java-8-openjdk-amd64/jre/bin:${PATH};
+ java -version;
misc/travis/android-tools-linux.sh;
fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export PATH=${PATH}:/Users/travis/Library/Python/2.7/bin;
fi
- - if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$PLATFORM" = "android" ]; then
- misc/travis/android-tools-osx.sh;
- fi
before_script:
- if [ "$PLATFORM" = "android" ]; then
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index 5e4dfb9a5a..0d9945991e 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -192,13 +192,9 @@ uint32_t Dictionary::hash() const {
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
- List<Variant> keys;
- get_key_list(&keys);
-
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
-
- h = hash_djb2_one_32(E->get().hash(), h);
- h = hash_djb2_one_32(operator[](E->get()).hash(), h);
+ for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ h = hash_djb2_one_32(E.key().hash(), h);
+ h = hash_djb2_one_32(E.value().hash(), h);
}
return h;
@@ -207,10 +203,11 @@ uint32_t Dictionary::hash() const {
Array Dictionary::keys() const {
Array varr;
- varr.resize(size());
if (_p->variant_map.empty())
return varr;
+ varr.resize(size());
+
int i = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
varr[i] = E.key();
@@ -223,10 +220,11 @@ Array Dictionary::keys() const {
Array Dictionary::values() const {
Array varr;
- varr.resize(size());
if (_p->variant_map.empty())
return varr;
+ varr.resize(size());
+
int i = 0;
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
varr[i] = E.get();
@@ -255,11 +253,8 @@ Dictionary Dictionary::duplicate(bool p_deep) const {
Dictionary n;
- List<Variant> keys;
- get_key_list(&keys);
-
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- n[E->get()] = p_deep ? operator[](E->get()).duplicate(p_deep) : operator[](E->get());
+ for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+ n[E.key()] = p_deep ? E.value().duplicate(true) : E.value();
}
return n;
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 87b8f5c83d..a920001de4 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -22,6 +22,28 @@
Called (if exists) to draw the canvas item.
</description>
</method>
+ <method name="draw_arc">
+ <return type="void">
+ </return>
+ <argument index="0" name="center" type="Vector2">
+ </argument>
+ <argument index="1" name="radius" type="float">
+ </argument>
+ <argument index="2" name="start_angle" type="float">
+ </argument>
+ <argument index="3" name="end_angle" type="float">
+ </argument>
+ <argument index="4" name="point_count" type="int">
+ </argument>
+ <argument index="5" name="color" type="Color">
+ </argument>
+ <argument index="6" name="width" type="float" default="1.0">
+ </argument>
+ <argument index="7" name="antialiased" type="bool" default="false">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="draw_char">
<return type="float">
</return>
diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml
new file mode 100644
index 0000000000..bf01ebfe82
--- /dev/null
+++ b/doc/classes/EditorSpinSlider.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorSpinSlider" inherits="Range" category="Core" version="3.2">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false">
+ </member>
+ <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" />
+ <member name="label" type="String" setter="set_label" getter="get_label" default="&quot;&quot;">
+ </member>
+ <member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 13a2fc2602..b6eeed4a21 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -217,7 +217,7 @@
Returns the path to the current engine executable.
</description>
</method>
- <method name="get_granted_permissions">
+ <method name="get_granted_permissions" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 01c8ee4779..2962391b99 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -133,6 +133,18 @@
Adds an [code][align][/code] tag based on the given [code]align[/code] value. See [enum Align] for possible values.
</description>
</method>
+ <method name="push_bold">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="push_bold_italics">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="push_cell">
<return type="void">
</return>
@@ -167,6 +179,12 @@
Adds an [code][indent][/code] tag to the tag stack. Multiplies "level" by current tab_size to determine new margin length.
</description>
</method>
+ <method name="push_italics">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="push_list">
<return type="void">
</return>
@@ -185,6 +203,18 @@
Adds a [code][meta][/code] tag to the tag stack. Similar to the BBCode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types.
</description>
</method>
+ <method name="push_mono">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="push_normal">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="push_strikethrough">
<return type="void">
</return>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 27eab85301..0dd2d75cd5 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -530,7 +530,7 @@
</constant>
</constants>
<theme_items>
- <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 1 )">
+ <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )">
Sets the background [Color] of this [TextEdit]. [member syntax_highlighting] has to be enabled.
</theme_item>
<theme_item name="bookmark_color" type="Color" default="Color( 0.08, 0.49, 0.98, 1 )">
diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml
index 2215f26c23..804489f7f1 100644
--- a/doc/classes/VideoPlayer.xml
+++ b/doc/classes/VideoPlayer.xml
@@ -16,7 +16,7 @@
Returns the video stream's name.
</description>
</method>
- <method name="get_video_texture">
+ <method name="get_video_texture" qualifiers="const">
<return type="Texture">
</return>
<description>
diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml
index f0f03b6c21..15216948e4 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShader" inherits="Shader" category="Core" version="3.2">
<brief_description>
+ A custom shader program with a visual editor.
</brief_description>
<description>
+ This class allows you to define a custom shader program that can be used for various materials to render objects.
+ The visual shader editor creates the shader.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeCubeMap.xml b/doc/classes/VisualShaderNodeCubeMap.xml
index 36465a6b4d..29ebe95086 100644
--- a/doc/classes/VisualShaderNodeCubeMap.xml
+++ b/doc/classes/VisualShaderNodeCubeMap.xml
@@ -12,10 +12,16 @@
<member name="cube_map" type="CubeMap" setter="set_cube_map" getter="get_cube_map">
</member>
<member name="default_input_values" type="Array" setter="_set_default_input_values" getter="_get_default_input_values" override="true" default="[ ]" />
+ <member name="source" type="int" setter="set_source" getter="get_source" enum="VisualShaderNodeCubeMap.Source" default="0">
+ </member>
<member name="texture_type" type="int" setter="set_texture_type" getter="get_texture_type" enum="VisualShaderNodeCubeMap.TextureType" default="0">
</member>
</members>
<constants>
+ <constant name="SOURCE_TEXTURE" value="0" enum="Source">
+ </constant>
+ <constant name="SOURCE_PORT" value="1" enum="Source">
+ </constant>
<constant name="TYPE_DATA" value="0" enum="TextureType">
</constant>
<constant name="TYPE_COLOR" value="1" enum="TextureType">
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index e34705f7b7..16e5e92abd 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -494,8 +494,10 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (line->width <= 1) {
Vector2 verts[2] = {
- Vector2(line->from.x, line->from.y),
- Vector2(line->to.x, line->to.y)
+ // Offset the line slightly to make sure we always draw the pixel at the from coordinate.
+ // Without this, corners of rectangles might be missing a pixel. (See diamond exit rule and #32657)
+ Vector2(Math::floor(line->from.x) + 0.5, Math::floor(line->from.y) + 0.5),
+ Vector2(Math::floor(line->to.x) + 0.5, Math::floor(line->to.y) + 0.5)
};
#ifdef GLES_OVER_GL
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 088ce3d198..f712219a64 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -131,7 +131,7 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
//maximum compatibility, renderbuffer and RGBA shadow
glGenRenderbuffers(1, &shadow_atlas->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, shadow_atlas->depth);
glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth);
@@ -3769,6 +3769,10 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
glEnable(GL_SCISSOR_TEST);
glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
+ if (storage->config.use_rgba_3d_shadows) {
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
glDisable(GL_SCISSOR_TEST);
if (light->reverse_cull) {
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 451d6adaa9..1259c550d6 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -114,7 +114,7 @@ void RasterizerStorageGLES2::bind_quad_array() const {
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
}
-Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_will_need_resize) const {
+Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
r_gl_format = 0;
Ref<Image> image = p_image;
@@ -261,7 +261,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT1: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -273,7 +273,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT3: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -285,7 +285,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT5: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -424,7 +424,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_ETC: {
- if (config.etc1_supported && !p_will_need_resize) {
+ if (config.etc1_supported) {
r_gl_internal_format = _EXT_ETC1_RGB8_OES;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -467,7 +467,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
}
}
- if (need_decompress) {
+ if (need_decompress || p_force_decompress) {
if (!image.is_null()) {
@@ -5771,7 +5771,7 @@ void RasterizerStorageGLES2::initialize() {
config.support_depth_cubemaps = true;
#else
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
- config.support_depth_texture = config.extensions.has("GL_OES_depth_texture");
+ config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture");
config.use_rgba_3d_shadows = !config.support_depth_texture;
config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map");
#endif
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 2e78910614..27f06074ed 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -337,7 +337,7 @@ public:
mutable RID_Owner<Texture> texture_owner;
- Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_will_need_resize) const;
+ Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const;
virtual RID texture_create();
virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index edffe852a2..e09ba755ea 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -548,8 +548,10 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
if (line->width <= 1) {
Vector2 verts[2] = {
- Vector2(line->from.x, line->from.y),
- Vector2(line->to.x, line->to.y)
+ // Offset the line slightly to make sure we always draw the pixel at the from coordinate.
+ // Without this, corners of rectangles might be missing a pixel. (See diamond exit rule and #32657)
+ Vector2(Math::floor(line->from.x) + 0.5, Math::floor(line->from.y) + 0.5),
+ Vector2(Math::floor(line->to.x) + 0.5, Math::floor(line->to.y) + 0.5)
};
#ifdef GLES_OVER_GL
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 95be67a5b7..d3348cdc6d 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -135,13 +135,13 @@ void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat,
GLuint RasterizerStorageGLES3::system_fbo = 0;
-Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const {
+Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const {
r_compressed = false;
r_gl_format = 0;
r_real_format = p_format;
Ref<Image> image = p_image;
- srgb = false;
+ r_srgb = false;
bool need_decompress = false;
@@ -188,7 +188,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8 : GL_RGB8;
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_BYTE;
- srgb = true;
+ r_srgb = true;
} break;
case Image::FORMAT_RGBA8: {
@@ -196,7 +196,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_internal_format = (config.srgb_decode_supported || (p_flags & VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
r_gl_type = GL_UNSIGNED_BYTE;
- srgb = true;
+ r_srgb = true;
} break;
case Image::FORMAT_RGBA4444: {
@@ -278,7 +278,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -294,7 +294,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -310,7 +310,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -355,7 +355,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -395,7 +395,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -410,7 +410,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -426,7 +426,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -442,7 +442,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -527,7 +527,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -542,7 +542,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -557,7 +557,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
- srgb = true;
+ r_srgb = true;
} else {
@@ -570,7 +570,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
}
}
- if (need_decompress) {
+ if (need_decompress || p_force_decompress) {
if (!image.is_null()) {
image = image->duplicate();
@@ -584,7 +584,7 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = false;
r_real_format = Image::FORMAT_RGBA8;
- srgb = true;
+ r_srgb = true;
return image;
}
@@ -677,8 +677,22 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
} break;
}
+ texture->is_npot_repeat_mipmap = false;
+#ifdef JAVASCRIPT_ENABLED
+ // WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT)
+ // textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec.
+ // Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058).
+ int po2_width = next_power_of_2(p_width);
+ int po2_height = next_power_of_2(p_height);
+ bool is_po2 = p_width == po2_width && p_height == po2_height;
+
+ if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
+ texture->is_npot_repeat_mipmap = true;
+ }
+#endif // JAVASCRIPT_ENABLED
+
Image::Format real_format;
- _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb);
+ _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
@@ -753,13 +767,9 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
texture->images.write[p_layer] = p_image;
}
-#ifndef GLES_OVER_GL
- if (p_image->is_compressed() && p_image->has_mipmaps() && !p_image->is_size_po2()) {
- ERR_PRINTS("Texuture '" + texture->path + "' is compressed, has mipmaps but is not of powerf-of-2 size. This does not work on OpenGL ES 3.0.");
- }
-#endif
+
Image::Format real_format;
- Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb);
+ Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
@@ -992,7 +1002,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
}
Image::Format real_format;
- Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb);
+ Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
GLenum blit_target = GL_TEXTURE_2D;
@@ -1091,7 +1101,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
gl_internal_format,
gl_type,
compressed,
- srgb);
+ srgb,
+ texture->is_npot_repeat_mipmap);
PoolVector<uint8_t> data;
@@ -1197,7 +1208,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
GLenum gl_type;
bool compressed;
bool srgb;
- _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb);
+ _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, false);
PoolVector<uint8_t> data;
@@ -1267,7 +1278,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
GLenum gl_type;
bool compressed;
bool srgb;
- _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb);
+ _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb, texture->is_npot_repeat_mipmap);
PoolVector<uint8_t> data;
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 84632308b4..6fe2f123f2 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -266,6 +266,8 @@ public:
int mipmaps;
+ bool is_npot_repeat_mipmap;
+
bool active;
GLuint tex_id;
@@ -342,7 +344,7 @@ public:
mutable RID_Owner<Texture> texture_owner;
- Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) const;
+ Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const;
virtual RID texture_create();
virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 8be1d5d8f3..99425d5002 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -56,6 +56,12 @@
#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.");
@@ -123,11 +129,24 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
} break;
}
return last_error;
- } else {
- last_error = OK;
- flags = p_mode_flags;
- return OK;
}
+
+ // Set close on exec to avoid leaking it to subprocesses.
+ 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;
+ flags = p_mode_flags;
+ return OK;
}
void FileAccessUnix::close() {
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index d5b1f46333..95767a96d8 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -1137,9 +1137,12 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
initial_loading = false;
- // The loading text only needs to be displayed before the first page is loaded
+ // The loading text only needs to be displayed before the first page is loaded.
+ // Therefore, we don't need to show it again.
library_loading->hide();
+ library_error->hide();
+
if (asset_items) {
memdelete(asset_items);
}
@@ -1187,6 +1190,11 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
asset_bottom_page = _make_pages(page, pages, page_len, total_items, result.size());
library_vb->add_child(asset_bottom_page);
+ if (result.empty()) {
+ library_error->set_text(vformat(TTR("No results for \"%s\"."), filter->get_text()));
+ library_error->show();
+ }
+
for (int i = 0; i < result.size(); i++) {
Dictionary r = result[i];
@@ -1453,6 +1461,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
library_loading->set_align(Label::ALIGN_CENTER);
library_vb->add_child(library_loading);
+ library_error = memnew(Label);
+ library_error->set_align(Label::ALIGN_CENTER);
+ library_error->hide();
+ library_vb->add_child(library_error);
+
asset_top_page = memnew(HBoxContainer);
library_vb->add_child(asset_top_page);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 94289f3b49..70ffbd9eed 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -184,6 +184,7 @@ class EditorAssetLibrary : public PanelContainer {
ScrollContainer *library_scroll;
VBoxContainer *library_vb;
Label *library_loading;
+ Label *library_error;
LineEdit *filter;
OptionButton *categories;
OptionButton *repository;
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 9160920c50..727d92ba05 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -736,6 +736,9 @@ void CurveEditor::_draw() {
if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
text_color.a *= 0.4;
draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color);
+ } else if (curve.get_point_count() == 0) {
+ text_color.a *= 0.4;
+ draw_string(font, Vector2(50, font_height), TTR("Right click to add point"), text_color);
}
}
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 803c806028..f56f7ef7ca 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -845,9 +845,10 @@ void ProjectSettingsEditor::_item_adds(String) {
void ProjectSettingsEditor::_item_add() {
- // Initialize the property with the default value for the given type
+ // Initialize the property with the default value for the given type.
+ // The type list starts at 1 (as we exclude Nil), so add 1 to the selected value.
Variant::CallError ce;
- const Variant value = Variant::construct(Variant::Type(type->get_selected()), NULL, 0, ce);
+ const Variant value = Variant::construct(Variant::Type(type->get_selected() + 1), NULL, 0, ce);
String catname = category->get_text().strip_edges();
String propname = property->get_text().strip_edges();
@@ -1835,7 +1836,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
// Start at 1 to avoid adding "Nil" as an option
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
- type->add_item(Variant::get_type_name(Variant::Type(i)), i);
+ type->add_item(Variant::get_type_name(Variant::Type(i)));
}
Button *add = memnew(Button);
diff --git a/misc/travis/android-tools-linux.sh b/misc/travis/android-tools-linux.sh
index 215b9fd159..d0c123ee6c 100755
--- a/misc/travis/android-tools-linux.sh
+++ b/misc/travis/android-tools-linux.sh
@@ -70,9 +70,10 @@ if [ ! -d $ANDROID_NDK_DIR ]; then
echo
fi
-echo "Installing: Android Tools ..."
mkdir -p ~/.android && echo "count=0" > ~/.android/repositories.cfg
+echo "Installing: Accepting Licenses ..."
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager --licenses > /dev/null
+echo "Installing: Android Build and Platform Tools ..."
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'tools' > /dev/null
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'platform-tools' > /dev/null
yes | $ANDROID_SDK_DIR/tools/bin/sdkmanager 'build-tools;28.0.3' > /dev/null
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 1bd3d72066..b762868f2c 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -217,6 +217,14 @@
Deprecated, use [member mesh_library] instead.
</member>
</members>
+ <signals>
+ <signal name="cell_size_changed">
+ <argument index="0" name="cell_size" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </signal>
+ </signals>
<constants>
<constant name="INVALID_CELL_ITEM" value="-1">
Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]).
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index d584492737..29a0cd5ba0 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -790,29 +790,29 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
VisualServer::get_singleton()->canvas_item_add_line(
canvas_item,
- p_rect.position + Point2(-offset, 0),
+ p_rect.position + Size2(-offset, 0),
p_rect.position + Size2(p_rect.size.width + offset, 0),
p_color,
p_width,
p_antialiased);
VisualServer::get_singleton()->canvas_item_add_line(
canvas_item,
- p_rect.position + Point2(0, offset),
- p_rect.position + Size2(0, p_rect.size.height - offset),
+ p_rect.position + Size2(p_rect.size.width, offset),
+ p_rect.position + Size2(p_rect.size.width, p_rect.size.height - offset),
p_color,
p_width,
p_antialiased);
VisualServer::get_singleton()->canvas_item_add_line(
canvas_item,
- p_rect.position + Point2(-offset, p_rect.size.height),
p_rect.position + Size2(p_rect.size.width + offset, p_rect.size.height),
+ p_rect.position + Size2(-offset, p_rect.size.height),
p_color,
p_width,
p_antialiased);
VisualServer::get_singleton()->canvas_item_add_line(
canvas_item,
- p_rect.position + Point2(p_rect.size.width, offset),
- p_rect.position + Size2(p_rect.size.width, p_rect.size.height - offset),
+ p_rect.position + Size2(0, p_rect.size.height - offset),
+ p_rect.position + Size2(0, offset),
p_color,
p_width,
p_antialiased);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a7e87a28ae..ae9c7c88d8 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -958,6 +958,10 @@ void TextEdit::_notification(int p_what) {
}
}
+ if (minimap_line < 0 || minimap_line >= (int)text.size()) {
+ break;
+ }
+
Map<int, HighlighterInfo> color_map;
if (syntax_coloring) {
color_map = _get_line_syntax_highlighting(minimap_line);
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 5b5ba56ebe..41a6b27b84 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -4610,19 +4610,34 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
return OK;
}
+String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) const {
+
+ // Return a list of shader types as an human-readable string
+ String valid_types;
+ for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
+ if (valid_types != String()) {
+ valid_types += ", ";
+ }
+
+ valid_types += "'" + E->get() + "'";
+ }
+
+ return valid_types;
+}
+
Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
if (tk.type != TK_SHADER_TYPE) {
- _set_error("Expected 'shader_type' at the beginning of shader.");
+ _set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier after 'shader_type', indicating type of shader.");
+ _set_error("Expected identifier after 'shader_type', indicating type of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
return ERR_PARSE_ERROR;
}
@@ -4631,15 +4646,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
shader_type_identifier = tk.text;
if (!p_shader_types.has(shader_type_identifier)) {
-
- String valid;
- for (Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
- if (valid != String()) {
- valid += ", ";
- }
- valid += "'" + E->get() + "'";
- }
- _set_error("Invalid shader type, valid types are: " + valid);
+ _set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types));
return ERR_PARSE_ERROR;
}
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 3a5630ef42..ceeaaf8872 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -750,6 +750,8 @@ private:
Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
+ String _get_shader_type_list(const Set<String> &p_shader_types) const;
+
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);