summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt2
-rw-r--r--core/bind/core_bind.cpp15
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/core_string_names.cpp47
-rw-r--r--core/dvector.h12
-rw-r--r--core/func_ref.cpp5
-rw-r--r--core/io/file_access_compressed.cpp35
-rw-r--r--core/io/file_access_zip.cpp89
-rw-r--r--core/io/logger.cpp13
-rw-r--r--core/io/marshalls.cpp5
-rw-r--r--core/io/packet_peer.cpp7
-rw-r--r--core/io/packet_peer_udp.cpp13
-rw-r--r--core/io/resource_format_binary.cpp11
-rw-r--r--core/io/stream_peer_tcp.cpp11
-rw-r--r--core/io/tcp_server.cpp5
-rw-r--r--core/math/expression.cpp14
-rw-r--r--core/math/expression.h4
-rw-r--r--core/math/plane.h5
-rw-r--r--core/math/quat.h28
-rw-r--r--core/math/random_number_generator.cpp3
-rw-r--r--core/math/random_number_generator.h7
-rw-r--r--core/os/dir_access.cpp12
-rw-r--r--core/os/main_loop.cpp1
-rw-r--r--core/os/main_loop.h1
-rw-r--r--core/os/os.h4
-rw-r--r--core/reference.cpp4
-rw-r--r--core/variant_parser.h3
-rw-r--r--doc/classes/AudioServer.xml9
-rw-r--r--doc/classes/AudioStreamSample.xml3
-rw-r--r--doc/classes/ButtonGroup.xml4
-rw-r--r--doc/classes/ColorPicker.xml34
-rw-r--r--doc/classes/MainLoop.xml2
-rw-r--r--doc/classes/MenuButton.xml5
-rw-r--r--doc/classes/OS.xml24
-rw-r--r--doc/classes/RandomNumberGenerator.xml15
-rw-r--r--doc/classes/WorldEnvironment.xml2
-rwxr-xr-xdoc/tools/makerst.py2
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp37
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp26
-rw-r--r--drivers/coremidi/core_midi.cpp6
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp15
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h51
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h150
-rw-r--r--drivers/gles2/shaders/scene.glsl7
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h160
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h228
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp2
-rw-r--r--drivers/gles3/shaders/scene.glsl3
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp47
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp13
-rw-r--r--drivers/unix/file_access_unix.cpp9
-rw-r--r--drivers/unix/net_socket_posix.cpp8
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h22
-rw-r--r--drivers/windows/file_access_windows.cpp9
-rw-r--r--drivers/windows/thread_windows.cpp5
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp38
-rw-r--r--editor/code_editor.cpp1
-rw-r--r--editor/collada/collada.h41
-rw-r--r--editor/editor_audio_buses.cpp40
-rw-r--r--editor/editor_audio_buses.h4
-rw-r--r--editor/editor_export.cpp9
-rw-r--r--editor/editor_export.h6
-rw-r--r--editor/editor_help_search.cpp24
-rw-r--r--editor/editor_node.cpp30
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_plugin.cpp10
-rw-r--r--editor/editor_properties.cpp32
-rw-r--r--editor/editor_sectioned_inspector.cpp15
-rw-r--r--editor/editor_settings.cpp162
-rw-r--r--editor/editor_settings.h32
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp11
-rw-r--r--editor/import/editor_scene_importer_gltf.h28
-rw-r--r--editor/import/resource_importer_wav.cpp14
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp18
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/collision_polygon_editor_plugin.cpp2
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp94
-rw-r--r--editor/plugins/path_2d_editor_plugin.h2
-rw-r--r--editor/plugins/script_editor_plugin.cpp24
-rw-r--r--editor/plugins/script_text_editor.cpp8
-rw-r--r--editor/plugins/shader_editor_plugin.cpp9
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp40
-rw-r--r--editor/plugins/tile_set_editor_plugin.h3
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp26
-rw-r--r--editor/project_export.cpp2
-rw-r--r--main/main.cpp3
-rw-r--r--modules/bullet/shape_bullet.cpp57
-rw-r--r--modules/csg/csg_shape.cpp13
-rw-r--r--modules/csg/csg_shape.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp21
-rw-r--r--modules/mono/csharp_script.cpp31
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp21
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h7
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp27
-rw-r--r--modules/mono/mono_gd/gd_mono_method.h5
-rw-r--r--modules/visual_script/visual_script_editor.cpp1
-rw-r--r--modules/webp/SCsub2
-rw-r--r--platform/iphone/detect.py12
-rw-r--r--platform/osx/os_osx.h7
-rw-r--r--platform/osx/os_osx.mm39
-rw-r--r--platform/x11/os_x11.cpp10
-rw-r--r--scene/2d/canvas_item.cpp15
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/tile_map.cpp4
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/animation_tree_player.cpp10
-rw-r--r--scene/animation/animation_tree_player.h2
-rw-r--r--scene/gui/color_picker.cpp27
-rw-r--r--scene/gui/color_picker.h3
-rw-r--r--scene/gui/control.cpp18
-rw-r--r--scene/gui/line_edit.cpp16
-rw-r--r--scene/gui/line_edit.h1
-rw-r--r--scene/gui/menu_button.cpp19
-rw-r--r--scene/gui/menu_button.h3
-rw-r--r--scene/gui/spin_box.cpp34
-rw-r--r--scene/gui/spin_box.h4
-rw-r--r--scene/gui/text_edit.cpp57
-rw-r--r--scene/gui/text_edit.h6
-rw-r--r--scene/main/scene_tree.cpp1
-rw-r--r--scene/main/viewport.cpp7
-rw-r--r--scene/resources/audio_stream_sample.cpp7
-rw-r--r--scene/resources/audio_stream_sample.h3
-rw-r--r--scene/resources/default_theme/default_theme.cpp4
-rw-r--r--scene/resources/material.cpp61
-rw-r--r--scene/resources/material.h2
-rw-r--r--scene/resources/particles_material.cpp15
-rw-r--r--scene/resources/particles_material.h2
-rw-r--r--scene/resources/primitive_meshes.cpp44
-rw-r--r--scene/resources/surface_tool.cpp2
-rw-r--r--scene/resources/tile_set.cpp47
-rw-r--r--scene/resources/tile_set.h4
-rw-r--r--servers/audio_server.cpp8
-rw-r--r--servers/audio_server.h2
-rw-r--r--servers/visual/shader_types.cpp5
-rw-r--r--thirdparty/README.md4
-rw-r--r--thirdparty/libwebp/src/dec/alphai_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/buffer_dec.c3
-rw-r--r--thirdparty/libwebp/src/dec/common_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c9
-rw-r--r--thirdparty/libwebp/src/dec/idec_dec.c25
-rw-r--r--thirdparty/libwebp/src/dec/vp8_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h4
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c103
-rw-r--r--thirdparty/libwebp/src/dec/vp8li_dec.h2
-rw-r--r--thirdparty/libwebp/src/dec/webpi_dec.h2
-rw-r--r--thirdparty/libwebp/src/demux/demux.c2
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h6
-rw-r--r--thirdparty/libwebp/src/dsp/enc.c6
-rw-r--r--thirdparty/libwebp/src/dsp/enc_avx2.c21
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c2
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.h14
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc.c86
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_mips32.c79
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c44
-rw-r--r--thirdparty/libwebp/src/dsp/msa_macro.h2
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler.c4
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_mips32.c4
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c10
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_msa.c7
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_neon.c18
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_sse2.c35
-rw-r--r--thirdparty/libwebp/src/dsp/yuv.h2
-rw-r--r--thirdparty/libwebp/src/enc/analysis_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/backward_references_cost_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/backward_references_enc.c1
-rw-r--r--thirdparty/libwebp/src/enc/cost_enc.h2
-rw-r--r--thirdparty/libwebp/src/enc/delta_palettization_enc.c455
-rw-r--r--thirdparty/libwebp/src/enc/delta_palettization_enc.h25
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c196
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.h10
-rw-r--r--thirdparty/libwebp/src/enc/iterator_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_tools_enc.c41
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h6
-rw-r--r--thirdparty/libwebp/src/enc/vp8l_enc.c17
-rw-r--r--thirdparty/libwebp/src/enc/vp8li_enc.h2
-rw-r--r--thirdparty/libwebp/src/mux/animi.h2
-rw-r--r--thirdparty/libwebp/src/mux/muxedit.c18
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h18
-rw-r--r--thirdparty/libwebp/src/mux/muxinternal.c53
-rw-r--r--thirdparty/libwebp/src/mux/muxread.c61
-rw-r--r--thirdparty/libwebp/src/utils/bit_reader_inl_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/bit_reader_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/bit_writer_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/filters_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_dec_utils.c8
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_dec_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/quant_levels_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/random_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/rescaler_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/thread_utils.h2
-rw-r--r--thirdparty/libwebp/src/utils/utils.h2
-rw-r--r--thirdparty/libwebp/src/webp/decode.h2
-rw-r--r--thirdparty/libwebp/src/webp/demux.h2
-rw-r--r--thirdparty/libwebp/src/webp/encode.h2
-rw-r--r--thirdparty/libwebp/src/webp/format_constants.h2
-rw-r--r--thirdparty/libwebp/src/webp/mux.h2
-rw-r--r--thirdparty/libwebp/src/webp/mux_types.h2
-rw-r--r--thirdparty/libwebp/src/webp/types.h2
-rw-r--r--thirdparty/tinyexr/tinyexr.h253
206 files changed, 2411 insertions, 1998 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 894cd1a53a..2a1fe20477 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -382,7 +382,7 @@ License: Expat
Files: ./thirdparty/tinyexr/
Comment: TinyEXR
-Copyright: 2014-2017, Syoyo Fujita
+Copyright: 2014-2018, Syoyo Fujita
2002, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC
License: BSD-3-clause
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 0032c43179..8641af84d9 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -378,12 +378,20 @@ bool _OS::get_borderless_window() const {
void _OS::set_ime_active(const bool p_active) {
- return OS::get_singleton()->set_ime_active(p_active);
+ OS::get_singleton()->set_ime_active(p_active);
}
void _OS::set_ime_position(const Point2 &p_pos) {
- return OS::get_singleton()->set_ime_position(p_pos);
+ OS::get_singleton()->set_ime_position(p_pos);
+}
+
+Point2 _OS::get_ime_selection() const {
+ return OS::get_singleton()->get_ime_selection();
+}
+
+String _OS::get_ime_text() const {
+ return OS::get_singleton()->get_ime_text();
}
void _OS::set_use_file_access_save_and_swap(bool p_enable) {
@@ -1134,7 +1142,10 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_window_per_pixel_transparency_enabled"), &_OS::get_window_per_pixel_transparency_enabled);
ClassDB::bind_method(D_METHOD("set_window_per_pixel_transparency_enabled", "enabled"), &_OS::set_window_per_pixel_transparency_enabled);
+ ClassDB::bind_method(D_METHOD("set_ime_active", "active"), &_OS::set_ime_active);
ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &_OS::set_ime_position);
+ ClassDB::bind_method(D_METHOD("get_ime_selection"), &_OS::get_ime_selection);
+ ClassDB::bind_method(D_METHOD("get_ime_text"), &_OS::get_ime_text);
ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 720b14bf56..4cdf09d522 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -195,6 +195,8 @@ public:
virtual void set_ime_active(const bool p_active);
virtual void set_ime_position(const Point2 &p_pos);
+ virtual Point2 get_ime_selection() const;
+ virtual String get_ime_text() const;
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index ba596f7f16..8a3fdade64 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -47,28 +47,27 @@ CoreStringNames::CoreStringNames() :
#ifdef TOOLS_ENABLED
_sections_unfolded(StaticCString::create("_sections_unfolded")),
#endif
- _custom_features(StaticCString::create("_custom_features")) {
-
- x = StaticCString::create("x");
- y = StaticCString::create("y");
- z = StaticCString::create("z");
- w = StaticCString::create("w");
- r = StaticCString::create("r");
- g = StaticCString::create("g");
- b = StaticCString::create("b");
- a = StaticCString::create("a");
- position = StaticCString::create("position");
- size = StaticCString::create("size");
- end = StaticCString::create("end");
- basis = StaticCString::create("basis");
- origin = StaticCString::create("origin");
- normal = StaticCString::create("normal");
- d = StaticCString::create("d");
- h = StaticCString::create("h");
- s = StaticCString::create("s");
- v = StaticCString::create("v");
- r8 = StaticCString::create("r8");
- g8 = StaticCString::create("g8");
- b8 = StaticCString::create("b8");
- a8 = StaticCString::create("a8");
+ _custom_features(StaticCString::create("_custom_features")),
+ x(StaticCString::create("x")),
+ y(StaticCString::create("y")),
+ z(StaticCString::create("z")),
+ w(StaticCString::create("w")),
+ r(StaticCString::create("r")),
+ g(StaticCString::create("g")),
+ b(StaticCString::create("b")),
+ a(StaticCString::create("a")),
+ position(StaticCString::create("position")),
+ size(StaticCString::create("size")),
+ end(StaticCString::create("end")),
+ basis(StaticCString::create("basis")),
+ origin(StaticCString::create("origin")),
+ normal(StaticCString::create("normal")),
+ d(StaticCString::create("d")),
+ h(StaticCString::create("h")),
+ s(StaticCString::create("s")),
+ v(StaticCString::create("v")),
+ r8(StaticCString::create("r8")),
+ g8(StaticCString::create("g8")),
+ b8(StaticCString::create("b8")),
+ a8(StaticCString::create("a8")) {
}
diff --git a/core/dvector.h b/core/dvector.h
index 2830c57ec0..9760dcbcad 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -56,12 +56,12 @@ struct MemoryPool {
Alloc *free_list;
- Alloc() {
- mem = NULL;
- lock = 0;
- pool_id = POOL_ALLOCATOR_INVALID_ID;
- size = 0;
- free_list = NULL;
+ Alloc() :
+ lock(0),
+ mem(NULL),
+ pool_id(POOL_ALLOCATOR_INVALID_ID),
+ size(0),
+ free_list(NULL) {
}
};
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index c707f1c4cb..d9d1a2b799 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -69,7 +69,6 @@ void FuncRef::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function);
}
-FuncRef::FuncRef() {
-
- id = 0;
+FuncRef::FuncRef() :
+ id(0) {
}
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 645d97ae7e..a3633dc1f4 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -373,24 +373,23 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
return 0;
}
-FileAccessCompressed::FileAccessCompressed() {
-
- f = NULL;
- magic = "GCMP";
- cmode = Compression::MODE_ZSTD;
- writing = false;
- write_ptr = 0;
- write_buffer_size = 0;
- write_max = 0;
- block_size = 0;
- read_eof = false;
- at_end = false;
- read_total = 0;
- read_ptr = NULL;
- read_block = 0;
- read_block_count = 0;
- read_block_size = 0;
- read_pos = 0;
+FileAccessCompressed::FileAccessCompressed() :
+ cmode(Compression::MODE_ZSTD),
+ writing(false),
+ write_ptr(0),
+ write_buffer_size(0),
+ write_max(0),
+ block_size(0),
+ read_eof(false),
+ at_end(false),
+ read_ptr(NULL),
+ read_block(0),
+ read_block_count(0),
+ read_block_size(0),
+ read_pos(0),
+ read_total(0),
+ magic("GCMP"),
+ f(NULL) {
}
FileAccessCompressed::~FileAccessCompressed() {
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 7b6385c3ff..d99cdf0d86 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -43,31 +43,31 @@ static void *godot_open(void *data, const char *p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return NULL;
- };
+ }
FileAccess *f = (FileAccess *)data;
f->open(p_fname, FileAccess::READ);
return f->is_open() ? data : NULL;
-};
+}
static uLong godot_read(void *data, void *fdata, void *buf, uLong size) {
FileAccess *f = (FileAccess *)data;
f->get_buffer((uint8_t *)buf, size);
return size;
-};
+}
static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
return 0;
-};
+}
static long godot_tell(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
return f->get_position();
-};
+}
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@@ -84,36 +84,36 @@ static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
break;
default:
break;
- };
+ }
f->seek(pos);
return 0;
-};
+}
static int godot_close(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
f->close();
return 0;
-};
+}
static int godot_testerror(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
return f->get_error() != OK ? 1 : 0;
-};
+}
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
return memalloc(items * size);
-};
+}
static void godot_free(voidpf opaque, voidpf address) {
memfree(address);
-};
+}
-}; // extern "C"
+} // extern "C"
void ZipArchive::close_handle(unzFile p_file) const {
@@ -122,7 +122,7 @@ void ZipArchive::close_handle(unzFile p_file) const {
unzCloseCurrentFile(p_file);
unzClose(p_file);
memdelete(f);
-};
+}
unzFile ZipArchive::get_file_handle(String p_file) const {
@@ -155,10 +155,10 @@ unzFile ZipArchive::get_file_handle(String p_file) const {
unzClose(pkg);
ERR_FAIL_V(NULL);
- };
+ }
return pkg;
-};
+}
bool ZipArchive::try_open_pack(const String &p_path) {
@@ -215,36 +215,36 @@ bool ZipArchive::try_open_pack(const String &p_path) {
if ((i + 1) < gi.number_entry) {
unzGoToNextFile(zfile);
- };
- };
+ }
+ }
return true;
-};
+}
bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name);
-};
+}
FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessZip(p_path, *p_file));
-};
+}
ZipArchive *ZipArchive::get_singleton() {
if (instance == NULL) {
instance = memnew(ZipArchive);
- };
+ }
return instance;
-};
+}
ZipArchive::ZipArchive() {
instance = this;
//fa_create_func = FileAccess::get_create_func();
-};
+}
ZipArchive::~ZipArchive() {
@@ -253,10 +253,10 @@ ZipArchive::~ZipArchive() {
FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile);
unzClose(packages[i].zfile);
memdelete(f);
- };
+ }
packages.clear();
-};
+}
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
@@ -272,7 +272,7 @@ Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK;
-};
+}
void FileAccessZip::close() {
@@ -283,50 +283,50 @@ void FileAccessZip::close() {
ERR_FAIL_COND(!arch);
arch->close_handle(zfile);
zfile = NULL;
-};
+}
bool FileAccessZip::is_open() const {
return zfile != NULL;
-};
+}
void FileAccessZip::seek(size_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, p_position);
-};
+}
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, get_len() + p_position);
-};
+}
size_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
-};
+}
size_t FileAccessZip::get_len() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
-};
+}
bool FileAccessZip::eof_reached() const {
ERR_FAIL_COND_V(!zfile, true);
return at_eof;
-};
+}
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
-};
+}
int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
@@ -339,20 +339,20 @@ int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const {
if (read < p_length)
at_eof = true;
return read;
-};
+}
Error FileAccessZip::get_error() const {
if (!zfile) {
return ERR_UNCONFIGURED;
- };
+ }
if (eof_reached()) {
return ERR_FILE_EOF;
- };
+ }
return OK;
-};
+}
void FileAccessZip::flush() {
@@ -362,22 +362,21 @@ void FileAccessZip::flush() {
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
-};
+}
bool FileAccessZip::file_exists(const String &p_name) {
return false;
-};
-
-FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
+}
- zfile = NULL;
+FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) :
+ zfile(NULL) {
_open(p_path, FileAccess::READ);
-};
+}
FileAccessZip::~FileAccessZip() {
close();
-};
+}
#endif
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 01755c8ee9..3c4b4a1ac3 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -179,11 +179,10 @@ void RotatedFileLogger::rotate_file() {
file = FileAccess::open(base_path, FileAccess::WRITE);
}
-RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
- file = NULL;
- base_path = p_base_path.simplify_path();
- max_files = p_max_files > 0 ? p_max_files : 1;
-
+RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) :
+ base_path(p_base_path.simplify_path()),
+ max_files(p_max_files > 0 ? p_max_files : 1),
+ file(NULL) {
rotate_file();
}
@@ -240,8 +239,8 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
StdLogger::~StdLogger() {}
-CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
- loggers = p_loggers;
+CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) :
+ loggers(p_loggers) {
}
void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 6338cee39d..c71903c94d 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -55,9 +55,8 @@ ObjectID EncodedObjectAsID::get_object_id() const {
return id;
}
-EncodedObjectAsID::EncodedObjectAsID() {
-
- id = 0;
+EncodedObjectAsID::EncodedObjectAsID() :
+ id(0) {
}
#define ENCODE_MASK 0xFF
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index b6dd4eaf6f..aadcca01d5 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -35,10 +35,9 @@
/* helpers / binders */
-PacketPeer::PacketPeer() {
-
- allow_object_decoding = false;
- last_get_error = OK;
+PacketPeer::PacketPeer() :
+ last_get_error(OK),
+ allow_object_decoding(false) {
}
void PacketPeer::set_allow_object_decoding(bool p_enable) {
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index d33ba6f855..2e916d6a48 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -239,13 +239,12 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address);
}
-PacketPeerUDP::PacketPeerUDP() {
-
- _sock = Ref<NetSocket>(NetSocket::create());
- blocking = true;
- packet_port = 0;
- queue_count = 0;
- peer_port = 0;
+PacketPeerUDP::PacketPeerUDP() :
+ packet_port(0),
+ queue_count(0),
+ peer_port(0),
+ blocking(true),
+ _sock(Ref<NetSocket>(NetSocket::create())) {
rb.resize(16);
}
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 6f3a8c3d2e..b91268dab2 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -970,12 +970,11 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
return type;
}
-ResourceInteractiveLoaderBinary::ResourceInteractiveLoaderBinary() {
-
- f = NULL;
- stage = 0;
- error = OK;
- translation_remapped = false;
+ResourceInteractiveLoaderBinary::ResourceInteractiveLoaderBinary() :
+ translation_remapped(false),
+ f(NULL),
+ error(OK),
+ stage(0) {
}
ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() {
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 28561e8cbc..4b86735aa3 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -349,12 +349,11 @@ void StreamPeerTCP::_bind_methods() {
BIND_ENUM_CONSTANT(STATUS_ERROR);
}
-StreamPeerTCP::StreamPeerTCP() {
-
- _sock = Ref<NetSocket>(NetSocket::create());
- status = STATUS_NONE;
- peer_host = IP_Address();
- peer_port = 0;
+StreamPeerTCP::StreamPeerTCP() :
+ _sock(Ref<NetSocket>(NetSocket::create())),
+ status(STATUS_NONE),
+ peer_host(IP_Address()),
+ peer_port(0) {
}
StreamPeerTCP::~StreamPeerTCP() {
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index b8194cb17f..be9176779e 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -116,9 +116,8 @@ void TCP_Server::stop() {
}
}
-TCP_Server::TCP_Server() {
-
- _sock = Ref<NetSocket>(NetSocket::create());
+TCP_Server::TCP_Server() :
+ _sock(Ref<NetSocket>(NetSocket::create())) {
}
TCP_Server::~TCP_Server() {
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 0cfb54234c..7f3439e956 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -2157,13 +2157,13 @@ void Expression::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_error_text"), &Expression::get_error_text);
}
-Expression::Expression() {
- output_type = Variant::NIL;
- error_set = true;
- root = NULL;
- nodes = NULL;
- sequenced = false;
- execution_error = false;
+Expression::Expression() :
+ output_type(Variant::NIL),
+ sequenced(false),
+ error_set(true),
+ root(NULL),
+ nodes(NULL),
+ execution_error(false) {
}
Expression::~Expression() {
diff --git a/core/math/expression.h b/core/math/expression.h
index ac2416d0dd..7f81542480 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -116,7 +116,9 @@ private:
Variant::Type type;
String name;
- Input() { type = Variant::NIL; }
+ Input() :
+ type(Variant::NIL) {
+ }
};
Vector<Input> inputs;
diff --git a/core/math/plane.h b/core/math/plane.h
index 4eedebb79e..5182dc67dd 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -74,10 +74,11 @@ public:
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
operator String() const;
- _FORCE_INLINE_ Plane() { d = 0; }
+ _FORCE_INLINE_ Plane() :
+ d(0) {}
_FORCE_INLINE_ Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
normal(p_a, p_b, p_c),
- d(p_d){};
+ d(p_d) {}
_FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d);
_FORCE_INLINE_ Plane(const Vector3 &p_point, const Vector3 &p_normal);
diff --git a/core/math/quat.h b/core/math/quat.h
index c4f9b3a732..59a15f460b 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -115,20 +115,20 @@ public:
z = p_z;
w = p_w;
}
- inline Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
- x = p_x;
- y = p_y;
- z = p_z;
- w = p_w;
+ inline Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+ x(p_x),
+ y(p_y),
+ z(p_z),
+ w(p_w) {
}
Quat(const Vector3 &axis, const real_t &angle) { set_axis_angle(axis, angle); }
Quat(const Vector3 &euler) { set_euler(euler); }
- Quat(const Quat &q) {
- x = q.x;
- y = q.y;
- z = q.z;
- w = q.w;
+ Quat(const Quat &q) :
+ x(q.x),
+ y(q.y),
+ z(q.z),
+ w(q.w) {
}
Quat(const Vector3 &v0, const Vector3 &v1) // shortest arc
@@ -153,9 +153,11 @@ public:
}
}
- inline Quat() {
- x = y = z = 0;
- w = 1;
+ inline Quat() :
+ x(0),
+ y(0),
+ z(0),
+ w(1) {
}
};
diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp
index e4ec0dac99..9f0a5bc992 100644
--- a/core/math/random_number_generator.cpp
+++ b/core/math/random_number_generator.cpp
@@ -40,6 +40,7 @@ void RandomNumberGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi);
ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf);
- ClassDB::bind_method(D_METHOD("rand_range", "from", "to"), &RandomNumberGenerator::rand_range);
+ ClassDB::bind_method(D_METHOD("randf_range", "from", "to"), &RandomNumberGenerator::randf_range);
+ ClassDB::bind_method(D_METHOD("randi_range", "from", "to"), &RandomNumberGenerator::randi_range);
ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize);
}
diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h
index 557863fdbd..078bfbed60 100644
--- a/core/math/random_number_generator.h
+++ b/core/math/random_number_generator.h
@@ -53,7 +53,12 @@ public:
_FORCE_INLINE_ real_t randf() { return randbase.randf(); }
- _FORCE_INLINE_ real_t rand_range(real_t from, real_t to) { return randbase.random(from, to); }
+ _FORCE_INLINE_ real_t randf_range(real_t from, real_t to) { return randbase.random(from, to); }
+
+ _FORCE_INLINE_ int randi_range(int from, int to) {
+ unsigned int ret = randbase.rand();
+ return ret % (to - from + 1) + from;
+ }
RandomNumberGenerator();
};
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index daa3eacd5f..8f4f2b6920 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -349,9 +349,9 @@ class DirChanger {
String original_dir;
public:
- DirChanger(DirAccess *p_da, String p_dir) {
- da = p_da;
- original_dir = p_da->get_current_dir();
+ DirChanger(DirAccess *p_da, String p_dir) :
+ da(p_da),
+ original_dir(p_da->get_current_dir()) {
p_da->change_dir(p_dir);
}
@@ -431,8 +431,12 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
ERR_FAIL_COND_V(err, err);
}
+ if (!p_to.ends_with("/")) {
+ p_to = p_to + "/";
+ }
+
DirChanger dir_changer(this, p_from);
- Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags);
+ Error err = _copy_dir(target_da, p_to, p_chmod_flags);
memdelete(target_da);
return err;
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 0945cdd512..6e0b914367 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -60,6 +60,7 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
BIND_CONSTANT(NOTIFICATION_CRASH);
+ BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
};
void MainLoop::set_init_script(const Ref<Script> &p_init_script) {
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 43f74302a8..e9b331ee45 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -65,6 +65,7 @@ public:
NOTIFICATION_TRANSLATION_CHANGED = 90,
NOTIFICATION_WM_ABOUT = 91,
NOTIFICATION_CRASH = 92,
+ NOTIFICATION_OS_IME_UPDATE = 93,
};
virtual void input_event(const Ref<InputEvent> &p_event);
diff --git a/core/os/os.h b/core/os/os.h
index 7786ffb26e..05ec3ac424 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -242,7 +242,8 @@ public:
virtual void set_ime_active(const bool p_active) {}
virtual void set_ime_position(const Point2 &p_pos) {}
- virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp) {}
+ virtual Point2 get_ime_selection() const { return Point2(); }
+ virtual String get_ime_text() const { return String(); }
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; }
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
@@ -480,6 +481,7 @@ public:
enum EngineContext {
CONTEXT_EDITOR,
CONTEXT_PROJECTMAN,
+ CONTEXT_ENGINE,
};
virtual void set_context(int p_context);
diff --git a/core/reference.cpp b/core/reference.cpp
index b79ad0bf3d..6ccc444b93 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -139,8 +139,8 @@ void WeakRef::set_ref(const REF &p_ref) {
ref = p_ref.is_valid() ? p_ref->get_instance_id() : 0;
}
-WeakRef::WeakRef() {
- ref = 0;
+WeakRef::WeakRef() :
+ ref(0) {
}
void WeakRef::_bind_methods() {
diff --git a/core/variant_parser.h b/core/variant_parser.h
index 531c1d59cd..e183169ed8 100644
--- a/core/variant_parser.h
+++ b/core/variant_parser.h
@@ -45,7 +45,8 @@ public:
CharType saved;
- Stream() { saved = 0; }
+ Stream() :
+ saved(0) {}
virtual ~Stream() {}
};
diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml
index 3ae5454e65..e1939e679d 100644
--- a/doc/classes/AudioServer.xml
+++ b/doc/classes/AudioServer.xml
@@ -61,6 +61,15 @@
Generates an [AudioBusLayout] using the available busses and effects.
</description>
</method>
+ <method name="get_bus_channels" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="bus_idx" type="int">
+ </argument>
+ <description>
+ Returns the amount of channels of the bus at index [code]bus_idx[/code].
+ </description>
+ </method>
<method name="get_bus_count" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml
index 9e56cc6016..77d5f14ab7 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamSample.xml
@@ -62,5 +62,8 @@
<constant name="LOOP_PING_PONG" value="2" enum="LoopMode">
Audio loops the data between loop_begin and loop_end playing back and forth.
</constant>
+ <constant name="LOOP_BACKWARD" value="3" enum="LoopMode">
+ Audio loops the data between loop_begin and loop_end playing backward only.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/ButtonGroup.xml b/doc/classes/ButtonGroup.xml
index e839c3e750..0f5ea8e6bf 100644
--- a/doc/classes/ButtonGroup.xml
+++ b/doc/classes/ButtonGroup.xml
@@ -22,8 +22,4 @@
</methods>
<constants>
</constants>
- <theme_items>
- <theme_item name="panel" type="StyleBox">
- </theme_item>
- </theme_items>
</class>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index 554e6b5632..2659fd8a39 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -20,6 +20,22 @@
Adds the given color to a list of color presets. The presets are displayed in the color picker and the user will be able to select them. Note: the presets list is only for [i]this[/i] color picker.
</description>
</method>
+ <method name="erase_preset">
+ <return type="void">
+ </return>
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ Remove the given color from the list of color presets of this color picker.
+ </description>
+ </method>
+ <method name="get_presets">
+ <return type="PoolColorArray">
+ </return>
+ <description>
+ Return the list of colors in the presets of the color picker.
+ </description>
+ </method>
</methods>
<members>
<member name="color" type="Color" setter="set_pick_color" getter="get_pick_color">
@@ -44,6 +60,24 @@
</description>
</signal>
</signals>
+ <signals>
+ <signal name="preset_added">
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ Emitted when a preset is added.
+ </description>
+ </signal>
+ </signals>
+ <signals>
+ <signal name="preset_removed">
+ <argument index="0" name="color" type="Color">
+ </argument>
+ <description>
+ Emitted when a preset is removed.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
<theme_items>
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index ad763e6532..01836cff95 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -136,5 +136,7 @@
</constant>
<constant name="NOTIFICATION_CRASH" value="92">
</constant>
+ <constant name="NOTIFICATION_OS_IME_UPDATE" value="93">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml
index c9a8d3ce7a..636edd504b 100644
--- a/doc/classes/MenuButton.xml
+++ b/doc/classes/MenuButton.xml
@@ -27,6 +27,11 @@
</description>
</method>
</methods>
+ <members>
+ <member name="switch_on_hover" type="bool" setter="set_switch_on_hover" getter="is_switch_on_hover">
+ If [code]true[/code], when the cursor hovers above another MenuButton within the same parent which also has [code]switch_on_hover[/code] enabled, it will close the current MenuButton and open the other one.
+ </member>
+ </members>
<signals>
<signal name="about_to_show">
<description>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index e218949757..3cca19c6cb 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -210,6 +210,20 @@
Returns the path to the current engine executable.
</description>
</method>
+ <method name="get_ime_text" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ Returns IME intermediate text.
+ </description>
+ </method>
+ <method name="get_ime_selection" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ Returns IME selection range.
+ </description>
+ </method>
<method name="get_latin_keyboard_variant" qualifiers="const">
<return type="String">
</return>
@@ -663,12 +677,22 @@
Sets the game's icon.
</description>
</method>
+ <method name="set_ime_active">
+ <return type="void">
+ </return>
+ <argument index="0" name="active" type="bool">
+ </argument>
+ <description>
+ Sets whether IME input mode should be enabled.
+ </description>
+ </method>
<method name="set_ime_position">
<return type="void">
</return>
<argument index="0" name="position" type="Vector2">
</argument>
<description>
+ Sets position of IME suggestion list popup (in window coordinates).
</description>
</method>
<method name="set_thread_name">
diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml
index aee9654561..720acc16ba 100644
--- a/doc/classes/RandomNumberGenerator.xml
+++ b/doc/classes/RandomNumberGenerator.xml
@@ -10,7 +10,7 @@
<demos>
</demos>
<methods>
- <method name="rand_range">
+ <method name="randf_range">
<return type="float">
</return>
<argument index="0" name="from" type="float">
@@ -21,6 +21,17 @@
Generates pseudo-random float between [code]from[/code] and [code]to[/code].
</description>
</method>
+ <method name="randi_range">
+ <return type="int">
+ </return>
+ <argument index="0" name="from" type="int">
+ </argument>
+ <argument index="1" name="to" type="int">
+ </argument>
+ <description>
+ Generates pseudo-random 32-bit signed integer between [code]from[/code] and [code]to[/code](inclusive).
+ </description>
+ </method>
<method name="randf">
<return type="float">
</return>
@@ -32,7 +43,7 @@
<return type="int">
</return>
<description>
- Generates pseudo-random 32-bit integer between '0' and '4294967295'.
+ Generates pseudo-random 32-bit unsigned integer between '0' and '4294967295'.
</description>
</method>
<method name="randomize">
diff --git a/doc/classes/WorldEnvironment.xml b/doc/classes/WorldEnvironment.xml
index 45e1af4e42..8c212502d6 100644
--- a/doc/classes/WorldEnvironment.xml
+++ b/doc/classes/WorldEnvironment.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="WorldEnvironment" inherits="Node" category="Core" version="3.1">
<brief_description>
- Default environment properties for the entire scene (post-processing effects, lightning and background settings).
+ Default environment properties for the entire scene (post-processing effects, lighting and background settings).
</brief_description>
<description>
The [code]WorldEnvironment[/code] node is used to configure the default [Environment] for the scene.
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index 7b7cc52547..9e83dfb55e 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -280,7 +280,7 @@ def rstize_text(text, cclass):
escape_post = True
# Properly escape things like `[Node]s`
- if escape_post and post_text and post_text[0].isalnum(): # not punctuation, escape
+ if escape_post and post_text and (post_text[0].isalnum() or post_text[0] == "("): # not punctuation, escape
post_text = '\ ' + post_text
next_brac_pos = post_text.find('[', 0)
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 50697b8834..2e3861f500 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -159,7 +159,7 @@ Error AudioDriverALSA::init() {
}
return err;
-};
+}
void AudioDriverALSA::thread_func(void *p_udata) {
@@ -232,25 +232,25 @@ void AudioDriverALSA::thread_func(void *p_udata) {
ad->stop_counting_ticks();
ad->unlock();
- };
+ }
ad->thread_exited = true;
-};
+}
void AudioDriverALSA::start() {
active = true;
-};
+}
int AudioDriverALSA::get_mix_rate() const {
return mix_rate;
-};
+}
AudioDriver::SpeakerMode AudioDriverALSA::get_speaker_mode() const {
return speaker_mode;
-};
+}
Array AudioDriverALSA::get_device_list() {
@@ -302,14 +302,14 @@ void AudioDriverALSA::lock() {
if (!thread || !mutex)
return;
mutex->lock();
-};
+}
void AudioDriverALSA::unlock() {
if (!thread || !mutex)
return;
mutex->unlock();
-};
+}
void AudioDriverALSA::finish_device() {
@@ -337,18 +337,15 @@ void AudioDriverALSA::finish() {
finish_device();
}
-AudioDriverALSA::AudioDriverALSA() {
-
- mutex = NULL;
- thread = NULL;
- pcm_handle = NULL;
-
- device_name = "Default";
- new_device = "Default";
-};
-
-AudioDriverALSA::~AudioDriverALSA(){
+AudioDriverALSA::AudioDriverALSA() :
+ thread(NULL),
+ mutex(NULL),
+ pcm_handle(NULL),
+ device_name("Default"),
+ new_device("Default") {
+}
-};
+AudioDriverALSA::~AudioDriverALSA() {
+}
#endif
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 850b90d59b..726cee10a4 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -684,22 +684,18 @@ String AudioDriverCoreAudio::capture_get_device() {
#endif
-AudioDriverCoreAudio::AudioDriverCoreAudio() {
- audio_unit = NULL;
- input_unit = NULL;
- active = false;
- mutex = NULL;
-
- mix_rate = 0;
- channels = 2;
- capture_channels = 2;
-
- buffer_frames = 0;
-
+AudioDriverCoreAudio::AudioDriverCoreAudio() :
+ audio_unit(NULL),
+ input_unit(NULL),
+ active(false),
+ mutex(NULL),
+ device_name("Default"),
+ capture_device_name("Default"),
+ mix_rate(0),
+ channels(2),
+ capture_channels(2),
+ buffer_frames(0) {
samples_in.clear();
-
- device_name = "Default";
- capture_device_name = "Default";
}
AudioDriverCoreAudio::~AudioDriverCoreAudio(){};
diff --git a/drivers/coremidi/core_midi.cpp b/drivers/coremidi/core_midi.cpp
index 2ebbabaa38..a20aec04b5 100644
--- a/drivers/coremidi/core_midi.cpp
+++ b/drivers/coremidi/core_midi.cpp
@@ -112,13 +112,11 @@ PoolStringArray MIDIDriverCoreMidi::get_connected_inputs() {
return list;
}
-MIDIDriverCoreMidi::MIDIDriverCoreMidi() {
-
- client = 0;
+MIDIDriverCoreMidi::MIDIDriverCoreMidi() :
+ client(0) {
}
MIDIDriverCoreMidi::~MIDIDriverCoreMidi() {
-
close();
}
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index 7addbaa9fe..25d7df8ebc 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -2017,6 +2017,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ Vector2 viewport_size = state.viewport_size;
+
Vector2 screen_pixel_size = state.screen_pixel_size;
bool use_radiance_map = false;
@@ -2335,6 +2337,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+ state.scene_shader.set_uniform(SceneShaderGLES2::VIEWPORT_SIZE, viewport_size);
+
state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
@@ -2506,8 +2510,6 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
}
current_fb = probe->fbo[p_reflection_probe_pass];
- state.screen_pixel_size.x = 1.0 / probe->probe_ptr->resolution;
- state.screen_pixel_size.y = 1.0 / probe->probe_ptr->resolution;
viewport_width = probe->probe_ptr->resolution;
viewport_height = probe->probe_ptr->resolution;
@@ -2518,11 +2520,16 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
state.render_no_shadows = false;
current_fb = storage->frame.current_rt->fbo;
env = environment_owner.getornull(p_environment);
- state.screen_pixel_size.x = 1.0 / storage->frame.current_rt->width;
- state.screen_pixel_size.y = 1.0 / storage->frame.current_rt->height;
+
viewport_width = storage->frame.current_rt->width;
viewport_height = storage->frame.current_rt->height;
}
+
+ state.viewport_size.x = viewport_width;
+ state.viewport_size.y = viewport_height;
+ state.screen_pixel_size.x = 1.0 / viewport_width;
+ state.screen_pixel_size.y = 1.0 / viewport_height;
+
//push back the directional lights
if (p_light_cull_count) {
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index ba406183c7..4236554d9d 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -211,6 +211,8 @@ public:
bool render_no_shadows;
+ Vector2 viewport_size;
+
Vector2 screen_pixel_size;
} state;
@@ -369,33 +371,28 @@ public:
float fog_height_max;
float fog_height_curve;
- Environment() {
- bg_mode = VS::ENV_BG_CLEAR_COLOR;
- sky_custom_fov = 0.0;
- bg_energy = 1.0;
- sky_ambient = 0;
- ambient_energy = 1.0;
- ambient_sky_contribution = 0.0;
- canvas_max_layer = 0;
-
- fog_enabled = false;
- fog_color = Color(0.5, 0.5, 0.5);
- fog_sun_color = Color(0.8, 0.8, 0.0);
- fog_sun_amount = 0;
-
- fog_depth_enabled = true;
-
- fog_depth_begin = 10;
- fog_depth_end = 0;
- fog_depth_curve = 1;
-
- fog_transmit_enabled = true;
- fog_transmit_curve = 1;
-
- fog_height_enabled = false;
- fog_height_min = 0;
- fog_height_max = 100;
- fog_height_curve = 1;
+ Environment() :
+ bg_mode(VS::ENV_BG_CLEAR_COLOR),
+ sky_custom_fov(0.0),
+ bg_energy(1.0),
+ sky_ambient(0),
+ ambient_energy(1.0),
+ ambient_sky_contribution(0.0),
+ canvas_max_layer(0),
+ fog_enabled(false),
+ fog_color(Color(0.5, 0.5, 0.5)),
+ fog_sun_color(Color(0.8, 0.8, 0.0)),
+ fog_sun_amount(0),
+ fog_depth_enabled(true),
+ fog_depth_begin(10),
+ fog_depth_end(0),
+ fog_depth_curve(1),
+ fog_transmit_enabled(true),
+ fog_transmit_curve(1),
+ fog_height_enabled(false),
+ fog_height_min(0),
+ fog_height_max(100),
+ fog_height_curve(1) {
}
};
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 5bdc65a0b5..ec7616b9f3 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -131,10 +131,9 @@ public:
}
} render, render_final, snap;
- Info() {
-
- texture_mem = 0;
- vertex_mem = 0;
+ Info() :
+ texture_mem(0),
+ vertex_mem(0) {
render.reset();
render_final.reset();
}
@@ -254,30 +253,31 @@ public:
VisualServer::TextureDetectCallback detect_normal;
void *detect_normal_ud;
- Texture() {
- alloc_width = 0;
- alloc_height = 0;
- target = 0;
-
- stored_cube_sides = 0;
- ignore_mipmaps = false;
- render_target = NULL;
- flags = width = height = 0;
- tex_id = 0;
- data_size = 0;
- format = Image::FORMAT_L8;
- active = false;
- compressed = false;
- total_data_size = 0;
- mipmaps = 0;
- detect_3d = NULL;
- detect_3d_ud = NULL;
- detect_srgb = NULL;
- detect_srgb_ud = NULL;
- detect_normal = NULL;
- detect_normal_ud = NULL;
- proxy = NULL;
- redraw_if_visible = false;
+ Texture() :
+ proxy(NULL),
+ flags(0),
+ width(0),
+ height(0),
+ alloc_width(0),
+ alloc_height(0),
+ format(Image::FORMAT_L8),
+ target(0),
+ data_size(0),
+ total_data_size(0),
+ ignore_mipmaps(false),
+ compressed(false),
+ mipmaps(0),
+ active(false),
+ tex_id(0),
+ stored_cube_sides(0),
+ render_target(NULL),
+ redraw_if_visible(false),
+ detect_3d(NULL),
+ detect_3d_ud(NULL),
+ detect_srgb(NULL),
+ detect_srgb_ud(NULL),
+ detect_normal(NULL),
+ detect_normal_ud(NULL) {
}
_ALWAYS_INLINE_ Texture *get_ptr() {
@@ -615,20 +615,15 @@ public:
int total_data_size;
- Surface() {
- array_byte_size = 0;
- index_array_byte_size = 0;
-
- array_len = 0;
- index_array_len = 0;
-
- mesh = NULL;
-
- primitive = VS::PRIMITIVE_POINTS;
-
- active = false;
-
- total_data_size = 0;
+ Surface() :
+ mesh(NULL),
+ array_len(0),
+ index_array_len(0),
+ array_byte_size(0),
+ index_array_byte_size(0),
+ primitive(VS::PRIMITIVE_POINTS),
+ active(false),
+ total_data_size(0) {
}
};
@@ -658,9 +653,9 @@ public:
}
}
- Mesh() {
- blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
- blend_shape_count = 0;
+ Mesh() :
+ blend_shape_count(0),
+ blend_shape_mode(VS::BLEND_SHAPE_MODE_NORMALIZED) {
}
};
@@ -731,22 +726,18 @@ public:
bool dirty_data;
MultiMesh() :
+ size(0),
+ transform_format(VS::MULTIMESH_TRANSFORM_2D),
+ color_format(VS::MULTIMESH_COLOR_NONE),
+ custom_data_format(VS::MULTIMESH_CUSTOM_DATA_NONE),
update_list(this),
- mesh_list(this) {
- dirty_aabb = true;
- dirty_data = true;
-
- xform_floats = 0;
- color_floats = 0;
- custom_data_floats = 0;
-
- visible_instances = -1;
-
- size = 0;
-
- transform_format = VS::MULTIMESH_TRANSFORM_2D;
- color_format = VS::MULTIMESH_COLOR_NONE;
- custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE;
+ mesh_list(this),
+ visible_instances(-1),
+ xform_floats(0),
+ color_floats(0),
+ custom_data_floats(0),
+ dirty_aabb(true),
+ dirty_data(true) {
}
};
@@ -847,10 +838,10 @@ public:
Set<RasterizerScene::InstanceBase *> instances;
Skeleton() :
+ use_2d(false),
+ size(0),
+ tex_id(0),
update_list(this) {
- tex_id = 0;
- size = 0;
- use_2d = false;
}
};
@@ -1121,11 +1112,11 @@ public:
GLuint color;
- Effect() {
- fbo = 0;
- width = 0;
- height = 0;
- color = 0;
+ Effect() :
+ fbo(0),
+ width(0),
+ height(0),
+ color(0) {
}
};
@@ -1140,22 +1131,17 @@ public:
RID texture;
- RenderTarget() {
- fbo = 0;
-
- color = 0;
- depth = 0;
-
- width = 0;
- height = 0;
-
- for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
+ RenderTarget() :
+ fbo(0),
+ color(0),
+ depth(0),
+ width(0),
+ height(0),
+ used_in_frame(false),
+ msaa(VS::VIEWPORT_MSAA_DISABLED) {
+ for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) {
flags[i] = false;
}
-
- used_in_frame = false;
-
- msaa = VS::VIEWPORT_MSAA_DISABLED;
}
};
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 15b90a7771..30dc55cc4c 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -84,6 +84,8 @@ uniform highp mat4 world_transform;
uniform highp float time;
+uniform highp vec2 viewport_size;
+
#ifdef RENDER_DEPTH
uniform float light_bias;
uniform float light_normal_bias;
@@ -677,6 +679,8 @@ uniform highp mat4 world_transform;
uniform highp float time;
+uniform highp vec2 viewport_size;
+
#if defined(SCREEN_UV_USED)
uniform vec2 screen_pixel_size;
#endif
@@ -1380,6 +1384,7 @@ void main() {
discard;
#endif
highp vec3 vertex = vertex_interp;
+ vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
vec3 transmission = vec3(0.0);
float metallic = 0.0;
@@ -1453,7 +1458,7 @@ FRAGMENT_SHADER_CODE
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
- vec3 eye_position = -normalize(vertex_interp);
+ vec3 eye_position = view;
#if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 0e6027c4ad..1d84fb487b 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -450,89 +450,77 @@ public:
float fog_height_max;
float fog_height_curve;
- Environment() {
- bg_mode = VS::ENV_BG_CLEAR_COLOR;
- sky_custom_fov = 0.0;
- bg_energy = 1.0;
- sky_ambient = 0;
- ambient_energy = 1.0;
- ambient_sky_contribution = 0.0;
- canvas_max_layer = 0;
-
- ssr_enabled = false;
- ssr_max_steps = 64;
- ssr_fade_in = 0.15;
- ssr_fade_out = 2.0;
- ssr_depth_tolerance = 0.2;
- ssr_roughness = true;
-
- ssao_enabled = false;
- ssao_intensity = 1.0;
- ssao_radius = 1.0;
- ssao_intensity2 = 1.0;
- ssao_radius2 = 0.0;
- ssao_bias = 0.01;
- ssao_light_affect = 0;
- ssao_ao_channel_affect = 0;
- ssao_filter = VS::ENV_SSAO_BLUR_3x3;
- ssao_quality = VS::ENV_SSAO_QUALITY_LOW;
- ssao_bilateral_sharpness = 4;
-
- tone_mapper = VS::ENV_TONE_MAPPER_LINEAR;
- tone_mapper_exposure = 1.0;
- tone_mapper_exposure_white = 1.0;
- auto_exposure = false;
- auto_exposure_speed = 0.5;
- auto_exposure_min = 0.05;
- auto_exposure_max = 8;
- auto_exposure_grey = 0.4;
-
- glow_enabled = false;
- glow_levels = (1 << 2) | (1 << 4);
- glow_intensity = 0.8;
- glow_strength = 1.0;
- glow_bloom = 0.0;
- glow_blend_mode = VS::GLOW_BLEND_MODE_SOFTLIGHT;
- glow_hdr_bleed_threshold = 1.0;
- glow_hdr_bleed_scale = 2.0;
- glow_hdr_luminance_cap = 12.0;
- glow_bicubic_upscale = false;
-
- dof_blur_far_enabled = false;
- dof_blur_far_distance = 10;
- dof_blur_far_transition = 5;
- dof_blur_far_amount = 0.1;
- dof_blur_far_quality = VS::ENV_DOF_BLUR_QUALITY_MEDIUM;
-
- dof_blur_near_enabled = false;
- dof_blur_near_distance = 2;
- dof_blur_near_transition = 1;
- dof_blur_near_amount = 0.1;
- dof_blur_near_quality = VS::ENV_DOF_BLUR_QUALITY_MEDIUM;
-
- adjustments_enabled = false;
- adjustments_brightness = 1.0;
- adjustments_contrast = 1.0;
- adjustments_saturation = 1.0;
-
- fog_enabled = false;
- fog_color = Color(0.5, 0.5, 0.5);
- fog_sun_color = Color(0.8, 0.8, 0.0);
- fog_sun_amount = 0;
-
- fog_depth_enabled = true;
-
- fog_depth_begin = 10;
- fog_depth_end = 0;
- fog_depth_curve = 1;
-
- fog_transmit_enabled = true;
- fog_transmit_curve = 1;
-
- fog_height_enabled = false;
- fog_height_min = 0;
- fog_height_max = 100;
- fog_height_curve = 1;
+ Environment() :
+ bg_mode(VS::ENV_BG_CLEAR_COLOR),
+ sky_custom_fov(0.0),
+ bg_energy(1.0),
+ sky_ambient(0),
+ ambient_energy(1.0),
+ ambient_sky_contribution(0.0),
+ canvas_max_layer(0),
+ ssr_enabled(false),
+ ssr_max_steps(64),
+ ssr_fade_in(0.15),
+ ssr_fade_out(2.0),
+ ssr_depth_tolerance(0.2),
+ ssr_roughness(true),
+ ssao_enabled(false),
+ ssao_intensity(1.0),
+ ssao_radius(1.0),
+ ssao_intensity2(1.0),
+ ssao_radius2(0.0),
+ ssao_bias(0.01),
+ ssao_light_affect(0),
+ ssao_ao_channel_affect(0),
+ ssao_quality(VS::ENV_SSAO_QUALITY_LOW),
+ ssao_bilateral_sharpness(4),
+ ssao_filter(VS::ENV_SSAO_BLUR_3x3),
+ glow_enabled(false),
+ glow_levels((1 << 2) | (1 << 4)),
+ glow_intensity(0.8),
+ glow_strength(1.0),
+ glow_bloom(0.0),
+ glow_blend_mode(VS::GLOW_BLEND_MODE_SOFTLIGHT),
+ glow_hdr_bleed_threshold(1.0),
+ glow_hdr_bleed_scale(2.0),
+ glow_hdr_luminance_cap(12.0),
+ glow_bicubic_upscale(false),
+ tone_mapper(VS::ENV_TONE_MAPPER_LINEAR),
+ tone_mapper_exposure(1.0),
+ tone_mapper_exposure_white(1.0),
+ auto_exposure(false),
+ auto_exposure_speed(0.5),
+ auto_exposure_min(0.05),
+ auto_exposure_max(8),
+ auto_exposure_grey(0.4),
+ dof_blur_far_enabled(false),
+ dof_blur_far_distance(10),
+ dof_blur_far_transition(5),
+ dof_blur_far_amount(0.1),
+ dof_blur_far_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM),
+ dof_blur_near_enabled(false),
+ dof_blur_near_distance(2),
+ dof_blur_near_transition(1),
+ dof_blur_near_amount(0.1),
+ dof_blur_near_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM),
+ adjustments_enabled(false),
+ adjustments_brightness(1.0),
+ adjustments_contrast(1.0),
+ adjustments_saturation(1.0),
+ fog_enabled(false),
+ fog_color(Color(0.5, 0.5, 0.5)),
+ fog_sun_color(Color(0.8, 0.8, 0.0)),
+ fog_sun_amount(0),
+ fog_depth_enabled(true),
+ fog_depth_begin(10),
+ fog_depth_end(0),
+ fog_depth_curve(1),
+ fog_transmit_enabled(true),
+ fog_transmit_curve(1),
+ fog_height_enabled(false),
+ fog_height_min(0),
+ fog_height_max(100),
+ fog_height_curve(1) {
}
};
@@ -643,9 +631,9 @@ public:
Vector3 bounds;
Transform transform_to_data;
- GIProbeInstance() {
- probe = NULL;
- tex_cache = 0;
+ GIProbeInstance() :
+ probe(NULL),
+ tex_cache(0) {
}
};
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 398ffdeb82..958086f6c7 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -285,29 +285,30 @@ public:
VisualServer::TextureDetectCallback detect_normal;
void *detect_normal_ud;
- Texture() {
-
- using_srgb = false;
- stored_cube_sides = 0;
- ignore_mipmaps = false;
- render_target = NULL;
- flags = width = height = 0;
- tex_id = 0;
- data_size = 0;
- format = Image::FORMAT_L8;
- active = false;
- compressed = false;
- total_data_size = 0;
- target = GL_TEXTURE_2D;
- mipmaps = 0;
- detect_3d = NULL;
- detect_3d_ud = NULL;
- detect_srgb = NULL;
- detect_srgb_ud = NULL;
- detect_normal = NULL;
- detect_normal_ud = NULL;
- proxy = NULL;
- redraw_if_visible = false;
+ Texture() :
+ proxy(NULL),
+ flags(0),
+ width(0),
+ height(0),
+ format(Image::FORMAT_L8),
+ target(GL_TEXTURE_2D),
+ data_size(0),
+ compressed(false),
+ total_data_size(0),
+ ignore_mipmaps(false),
+ mipmaps(0),
+ active(false),
+ tex_id(0),
+ using_srgb(false),
+ redraw_if_visible(false),
+ stored_cube_sides(0),
+ render_target(NULL),
+ detect_3d(NULL),
+ detect_3d_ud(NULL),
+ detect_srgb(NULL),
+ detect_srgb_ud(NULL),
+ detect_normal(NULL),
+ detect_normal_ud(NULL) {
}
_ALWAYS_INLINE_ Texture *get_ptr() {
@@ -553,16 +554,16 @@ public:
bool is_animated_cache;
Material() :
+ shader(NULL),
+ ubo_id(0),
+ ubo_size(0),
list(this),
- dirty_list(this) {
- can_cast_shadow_cache = false;
- is_animated_cache = false;
- shader = NULL;
- line_width = 1.0;
- ubo_id = 0;
- ubo_size = 0;
- last_pass = 0;
- render_priority = 0;
+ dirty_list(this),
+ line_width(1.0),
+ render_priority(0),
+ last_pass(0),
+ can_cast_shadow_cache(false),
+ is_animated_cache(false) {
}
};
@@ -661,27 +662,24 @@ public:
int total_data_size;
- Surface() {
-
- array_byte_size = 0;
- index_array_byte_size = 0;
- mesh = NULL;
- format = 0;
- array_id = 0;
- vertex_id = 0;
- index_id = 0;
- array_len = 0;
+ Surface() :
+ mesh(NULL),
+ format(0),
+ array_id(0),
+ vertex_id(0),
+ index_id(0),
+ index_wireframe_id(0),
+ array_wireframe_id(0),
+ instancing_array_wireframe_id(0),
+ index_wireframe_len(0),
+ array_len(0),
+ index_array_len(0),
+ array_byte_size(0),
+ index_array_byte_size(0),
+ primitive(VS::PRIMITIVE_POINTS),
+ active(false),
+ total_data_size(0) {
type = GEOMETRY_SURFACE;
- primitive = VS::PRIMITIVE_POINTS;
- index_array_len = 0;
- active = false;
-
- total_data_size = 0;
-
- index_wireframe_id = 0;
- array_wireframe_id = 0;
- instancing_array_wireframe_id = 0;
- index_wireframe_len = 0;
}
~Surface() {
@@ -708,11 +706,11 @@ public:
}
}
- Mesh() {
- blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED;
- blend_shape_count = 0;
- last_pass = 0;
- active = false;
+ Mesh() :
+ active(false),
+ blend_shape_count(0),
+ blend_shape_mode(VS::BLEND_SHAPE_MODE_NORMALIZED),
+ last_pass(0) {
}
};
@@ -780,19 +778,19 @@ public:
bool dirty_data;
MultiMesh() :
+ size(0),
+ transform_format(VS::MULTIMESH_TRANSFORM_2D),
+ color_format(VS::MULTIMESH_COLOR_NONE),
+ custom_data_format(VS::MULTIMESH_CUSTOM_DATA_NONE),
update_list(this),
- mesh_list(this) {
- dirty_aabb = true;
- dirty_data = true;
- xform_floats = 0;
- color_floats = 0;
- custom_data_floats = 0;
- visible_instances = -1;
- size = 0;
- buffer = 0;
- transform_format = VS::MULTIMESH_TRANSFORM_2D;
- color_format = VS::MULTIMESH_COLOR_NONE;
- custom_data_format = VS::MULTIMESH_CUSTOM_DATA_NONE;
+ mesh_list(this),
+ buffer(0),
+ visible_instances(-1),
+ xform_floats(0),
+ color_floats(0),
+ custom_data_floats(0),
+ dirty_aabb(true),
+ dirty_data(true) {
}
};
@@ -889,11 +887,10 @@ public:
Transform2D base_transform_2d;
Skeleton() :
+ use_2d(false),
+ size(0),
+ texture(0),
update_list(this) {
- size = 0;
-
- use_2d = false;
- texture = 0;
}
};
@@ -1174,37 +1171,31 @@ public:
Transform emission_transform;
Particles() :
- particle_element(this) {
- cycle_number = 0;
- emitting = false;
- one_shot = false;
- amount = 0;
- lifetime = 1.0;
- pre_process_time = 0.0;
- explosiveness = 0.0;
- randomness = 0.0;
- use_local_coords = true;
- fixed_fps = 0;
- fractional_delta = false;
- frame_remainder = 0;
- histories_enabled = false;
- speed_scale = 1.0;
- random_seed = 0;
-
- restart_request = false;
-
- custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
-
- draw_order = VS::PARTICLES_DRAW_ORDER_INDEX;
+ inactive(true),
+ inactive_time(0.0),
+ emitting(false),
+ one_shot(false),
+ amount(0),
+ lifetime(1.0),
+ pre_process_time(0.0),
+ explosiveness(0.0),
+ randomness(0.0),
+ restart_request(false),
+ custom_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))),
+ use_local_coords(true),
+ draw_order(VS::PARTICLES_DRAW_ORDER_INDEX),
+ histories_enabled(false),
+ particle_element(this),
+ prev_ticks(0),
+ random_seed(0),
+ cycle_number(0),
+ speed_scale(1.0),
+ fixed_fps(0),
+ fractional_delta(false),
+ frame_remainder(0),
+ clear(true) {
particle_buffers[0] = 0;
particle_buffers[1] = 0;
-
- prev_ticks = 0;
-
- clear = true;
- inactive = true;
- inactive_time = 0.0;
-
glGenBuffers(2, particle_buffers);
glGenVertexArrays(2, particle_vaos);
}
@@ -1309,9 +1300,9 @@ public:
GLuint color;
int levels;
- MipMaps() {
- color = 0;
- levels = 0;
+ MipMaps() :
+ color(0),
+ levels(0) {
}
};
@@ -1326,10 +1317,10 @@ public:
Vector<GLuint> depth_mipmap_fbos; //fbos for depth mipmapsla ver
- SSAO() {
+ SSAO() :
+ linear_depth(0) {
blur_fbo[0] = 0;
blur_fbo[1] = 0;
- linear_depth = 0;
}
} ssao;
@@ -1341,7 +1332,8 @@ public:
GLuint fbo;
GLuint color;
- Exposure() { fbo = 0; }
+ Exposure() :
+ fbo(0) {}
} exposure;
uint64_t last_exposure_tick;
@@ -1355,26 +1347,22 @@ public:
RID texture;
- RenderTarget() {
-
- msaa = VS::VIEWPORT_MSAA_DISABLED;
- width = 0;
- height = 0;
- depth = 0;
- fbo = 0;
+ RenderTarget() :
+ fbo(0),
+ depth(0),
+ last_exposure_tick(0),
+ width(0),
+ height(0),
+ used_in_frame(false),
+ msaa(VS::VIEWPORT_MSAA_DISABLED) {
exposure.fbo = 0;
buffers.fbo = 0;
- used_in_frame = false;
-
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
flags[i] = false;
}
flags[RENDER_TARGET_HDR] = true;
-
buffers.active = false;
buffers.effects_active = false;
-
- last_exposure_tick = 0;
}
};
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index adb145711d..2a2280e8a4 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -786,7 +786,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
/** CANVAS ITEM SHADER **/
actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy";
- actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
+ actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv";
actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize";
actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix";
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 407e7ec591..ff273e4e9f 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1565,6 +1565,7 @@ void main() {
//lay out everything, whathever is unused is optimized away anyway
highp vec3 vertex = vertex_interp;
+ vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
vec3 transmission = vec3(0.0);
float metallic = 0.0;
@@ -1699,7 +1700,7 @@ FRAGMENT_SHADER_CODE
vec3 ambient_light;
vec3 env_reflection_light = vec3(0.0, 0.0, 0.0);
- vec3 eye_vec = -normalize(vertex_interp);
+ vec3 eye_vec = view;
#ifdef USE_RADIANCE_MAP
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 720824d451..4988557dcb 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -743,35 +743,28 @@ String AudioDriverPulseAudio::capture_get_device() {
return name;
}
-AudioDriverPulseAudio::AudioDriverPulseAudio() {
-
- pa_ml = NULL;
- pa_ctx = NULL;
- pa_str = NULL;
- pa_rec_str = NULL;
-
- mutex = NULL;
- thread = NULL;
-
- device_name = "Default";
- new_device = "Default";
- default_device = "";
-
+AudioDriverPulseAudio::AudioDriverPulseAudio() :
+ thread(NULL),
+ mutex(NULL),
+ pa_ml(NULL),
+ pa_ctx(NULL),
+ pa_str(NULL),
+ pa_rec_str(NULL),
+ device_name("Default"),
+ new_device("Default"),
+ default_device(""),
+ mix_rate(0),
+ buffer_frames(0),
+ pa_buffer_size(0),
+ channels(0),
+ pa_ready(0),
+ pa_status(0),
+ active(false),
+ thread_exited(false),
+ exit_thread(false),
+ latency(0) {
samples_in.clear();
samples_out.clear();
-
- mix_rate = 0;
- buffer_frames = 0;
- pa_buffer_size = 0;
- channels = 0;
- pa_ready = 0;
- pa_status = 0;
-
- active = false;
- thread_exited = false;
- exit_thread = false;
-
- latency = 0;
}
AudioDriverPulseAudio::~AudioDriverPulseAudio() {
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index bc6ceb1e7e..80537315af 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -194,13 +194,12 @@ void AudioDriverRtAudio::finish() {
}
}
-AudioDriverRtAudio::AudioDriverRtAudio() {
-
- active = false;
- mutex = NULL;
- dac = NULL;
- mix_rate = DEFAULT_MIX_RATE;
- speaker_mode = SPEAKER_MODE_STEREO;
+AudioDriverRtAudio::AudioDriverRtAudio() :
+ speaker_mode(SPEAKER_MODE_STEREO),
+ mutex(NULL),
+ dac(NULL),
+ mix_rate(DEFAULT_MIX_RATE),
+ active(false) {
}
#endif
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 3b97b95f7c..10f6be3cbe 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -309,11 +309,10 @@ FileAccess *FileAccessUnix::create_libc() {
CloseNotificationFunc FileAccessUnix::close_notification_func = NULL;
-FileAccessUnix::FileAccessUnix() {
-
- f = NULL;
- flags = 0;
- last_error = OK;
+FileAccessUnix::FileAccessUnix() :
+ f(NULL),
+ flags(0),
+ last_error(OK) {
}
FileAccessUnix::~FileAccessUnix() {
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 833b17f122..740b1edb9c 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -167,10 +167,10 @@ void NetSocketPosix::cleanup() {
#endif
}
-NetSocketPosix::NetSocketPosix() {
- _sock = SOCK_EMPTY;
- _ip_type = IP::TYPE_NONE;
- _is_stream = false;
+NetSocketPosix::NetSocketPosix() :
+ _sock(SOCK_EMPTY),
+ _ip_type(IP::TYPE_NONE),
+ _is_stream(false) {
}
NetSocketPosix::~NetSocketPosix() {
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index 3d94f3ba49..71f56cfb5b 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -58,17 +58,17 @@ class AudioDriverWASAPI : public AudioDriver {
String device_name;
String new_device;
- AudioDeviceWASAPI() {
- audio_client = NULL;
- render_client = NULL;
- capture_client = NULL;
- active = false;
- format_tag = 0;
- bits_per_sample = 0;
- channels = 0;
- frame_size = 0;
- device_name = "Default";
- new_device = "Default";
+ AudioDeviceWASAPI() :
+ audio_client(NULL),
+ render_client(NULL),
+ capture_client(NULL),
+ active(false),
+ format_tag(0),
+ bits_per_sample(0),
+ channels(0),
+ frame_size(0),
+ device_name("Default"),
+ new_device("Default") {
}
};
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 2582478259..a289945aa7 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -307,11 +307,10 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
}
}
-FileAccessWindows::FileAccessWindows() {
-
- f = NULL;
- flags = 0;
- last_error = OK;
+FileAccessWindows::FileAccessWindows() :
+ f(NULL),
+ flags(0),
+ last_error(OK) {
}
FileAccessWindows::~FileAccessWindows() {
diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp
index 52dcfacdf8..dbccad3b5d 100644
--- a/drivers/windows/thread_windows.cpp
+++ b/drivers/windows/thread_windows.cpp
@@ -93,9 +93,8 @@ void ThreadWindows::make_default() {
wait_to_finish_func = wait_to_finish_func_windows;
}
-ThreadWindows::ThreadWindows() {
-
- handle = NULL;
+ThreadWindows::ThreadWindows() :
+ handle(NULL) {
}
ThreadWindows::~ThreadWindows() {
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index 452a1105ca..ce2f0db0fc 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -91,7 +91,7 @@ Error AudioDriverXAudio2::init() {
thread = Thread::create(AudioDriverXAudio2::thread_func, this);
return OK;
-};
+}
void AudioDriverXAudio2::thread_func(void *p_udata) {
@@ -131,10 +131,10 @@ void AudioDriverXAudio2::thread_func(void *p_udata) {
WaitForSingleObject(ad->voice_callback.buffer_end_event, INFINITE);
}
}
- };
+ }
ad->thread_exited = true;
-};
+}
void AudioDriverXAudio2::start() {
@@ -144,17 +144,17 @@ void AudioDriverXAudio2::start() {
ERR_EXPLAIN("XAudio2 start error " + itos(hr));
ERR_FAIL();
}
-};
+}
int AudioDriverXAudio2::get_mix_rate() const {
return mix_rate;
-};
+}
AudioDriver::SpeakerMode AudioDriverXAudio2::get_speaker_mode() const {
return speaker_mode;
-};
+}
float AudioDriverXAudio2::get_latency() {
@@ -172,13 +172,13 @@ void AudioDriverXAudio2::lock() {
if (!thread || !mutex)
return;
mutex->lock();
-};
+}
void AudioDriverXAudio2::unlock() {
if (!thread || !mutex)
return;
mutex->unlock();
-};
+}
void AudioDriverXAudio2::finish() {
@@ -195,12 +195,12 @@ void AudioDriverXAudio2::finish() {
if (samples_in) {
memdelete_arr(samples_in);
- };
+ }
if (samples_out[0]) {
for (int i = 0; i < AUDIO_BUFFERS; i++) {
memdelete_arr(samples_out[i]);
}
- };
+ }
mastering_voice->DestroyVoice();
@@ -208,20 +208,18 @@ void AudioDriverXAudio2::finish() {
if (mutex)
memdelete(mutex);
thread = NULL;
-};
-
-AudioDriverXAudio2::AudioDriverXAudio2() {
+}
- mutex = NULL;
- thread = NULL;
+AudioDriverXAudio2::AudioDriverXAudio2() :
+ thread(NULL),
+ mutex(NULL),
+ current_buffer(0) {
wave_format = { 0 };
for (int i = 0; i < AUDIO_BUFFERS; i++) {
xaudio_buffer[i] = { 0 };
samples_out[i] = 0;
}
- current_buffer = 0;
-};
-
-AudioDriverXAudio2::~AudioDriverXAudio2(){
+}
-};
+AudioDriverXAudio2::~AudioDriverXAudio2() {
+}
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index a0a8e9459d..a7a51cb93d 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -768,6 +768,7 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
text_editor->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size"));
text_editor->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent"));
+ text_editor->set_draw_indent_guides(EditorSettings::get_singleton()->get("text_editor/indent/draw_indent_guides"));
text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_numbers_zero_padded"));
diff --git a/editor/collada/collada.h b/editor/collada/collada.h
index b777fa04c2..2d5819902c 100644
--- a/editor/collada/collada.h
+++ b/editor/collada/collada.h
@@ -110,14 +110,13 @@ public:
float z_near;
float z_far;
- CameraData() {
-
- mode = MODE_PERSPECTIVE;
- perspective.y_fov = 0;
+ CameraData() :
+ mode(MODE_PERSPECTIVE),
+ aspect(1),
+ z_near(0.1),
+ z_far(100) {
perspective.x_fov = 0;
- aspect = 1;
- z_near = 0.1;
- z_far = 100;
+ perspective.y_fov = 0;
}
};
@@ -141,16 +140,14 @@ public:
float spot_angle;
float spot_exp;
- LightData() {
-
- mode = MODE_AMBIENT;
- color = Color(1, 1, 1, 1);
- constant_att = 0;
- linear_att = 0;
- quad_att = 0;
-
- spot_angle = 45;
- spot_exp = 1;
+ LightData() :
+ mode(MODE_AMBIENT),
+ color(Color(1, 1, 1, 1)),
+ constant_att(0),
+ linear_att(0),
+ quad_att(0),
+ spot_angle(45),
+ spot_exp(1) {
}
};
@@ -580,11 +577,11 @@ public:
float animation_length;
- State() {
- unit_scale = 1.0;
- up_axis = Vector3::AXIS_Y;
- import_flags = 0;
- animation_length = 0;
+ State() :
+ import_flags(0),
+ unit_scale(1.0),
+ up_axis(Vector3::AXIS_Y),
+ animation_length(0) {
}
} state;
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 6cd81626c7..b1f5bc4908 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -36,11 +36,35 @@
#include "filesystem_dock.h"
#include "servers/audio_server.h"
+void EditorAudioBus::_update_visible_channels() {
+
+ int i = 0;
+ for (; i < cc; i++) {
+
+ if (!channel[i].vu_l->is_visible()) {
+ channel[i].vu_l->show();
+ }
+ if (!channel[i].vu_r->is_visible()) {
+ channel[i].vu_r->show();
+ }
+ }
+
+ for (; i < CHANNELS_MAX; i++) {
+
+ if (channel[i].vu_l->is_visible()) {
+ channel[i].vu_l->hide();
+ }
+ if (channel[i].vu_r->is_visible()) {
+ channel[i].vu_r->hide();
+ }
+ }
+}
+
void EditorAudioBus::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
- for (int i = 0; i < cc; i++) {
+ for (int i = 0; i < CHANNELS_MAX; i++) {
channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
@@ -72,6 +96,11 @@ void EditorAudioBus::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
+ if (cc != AudioServer::get_singleton()->get_bus_channels(get_index())) {
+ cc = AudioServer::get_singleton()->get_bus_channels(get_index());
+ _update_visible_channels();
+ }
+
for (int i = 0; i < cc; i++) {
float real_peak[2] = { -100, -100 };
bool activity_found = false;
@@ -113,7 +142,7 @@ void EditorAudioBus::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < CHANNELS_MAX; i++) {
channel[i].peak_l = -100;
channel[i].peak_r = -100;
channel[i].prev_active = true;
@@ -124,7 +153,7 @@ void EditorAudioBus::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED) {
- for (int i = 0; i < cc; i++) {
+ for (int i = 0; i < CHANNELS_MAX; i++) {
channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
@@ -709,9 +738,8 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
slider->connect("value_changed", this, "_volume_db_changed");
hb->add_child(slider);
- cc = AudioServer::get_singleton()->get_channel_count();
-
- for (int i = 0; i < cc; i++) {
+ cc = 0;
+ for (int i = 0; i < CHANNELS_MAX; i++) {
channel[i].vu_l = memnew(TextureProgress);
channel[i].vu_l->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
hb->add_child(channel[i].vu_l);
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 4cdcb65d7b..02038fbe18 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -59,6 +59,7 @@ class EditorAudioBus : public PanelContainer {
VSlider *slider;
int cc;
+ static const int CHANNELS_MAX = 4;
struct {
bool prev_active;
@@ -68,7 +69,7 @@ class EditorAudioBus : public PanelContainer {
TextureProgress *vu_l;
TextureProgress *vu_r;
- } channel[4];
+ } channel[CHANNELS_MAX];
TextureRect *scale;
OptionButton *send;
@@ -102,6 +103,7 @@ class EditorAudioBus : public PanelContainer {
void _effect_selected();
void _delete_effect_pressed(int p_option);
void _effect_rmb(const Vector2 &p_pos);
+ void _update_visible_channels();
virtual Variant get_drag_data(const Point2 &p_point);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 9df0f30ca4..71315f1377 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -222,11 +222,10 @@ String EditorExportPreset::get_custom_features() const {
return custom_features;
}
-EditorExportPreset::EditorExportPreset() {
-
- export_path = "";
- export_filter = EXPORT_ALL_RESOURCES;
- runnable = false;
+EditorExportPreset::EditorExportPreset() :
+ export_filter(EXPORT_ALL_RESOURCES),
+ export_path(""),
+ runnable(false) {
}
///////////////////////////////////
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 483af489a3..881e86fb12 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -206,9 +206,9 @@ public:
PropertyInfo option;
Variant default_value;
- ExportOption(const PropertyInfo &p_info, const Variant &p_default) {
- option = p_info;
- default_value = p_default;
+ ExportOption(const PropertyInfo &p_info, const Variant &p_default) :
+ option(p_info),
+ default_value(p_default) {
}
ExportOption() {}
};
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 4e4c5143f2..a9f7be0fff 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -130,7 +130,7 @@ void EditorHelpSearch::_notification(int p_what) {
} break;
case NOTIFICATION_POPUP_HIDE: {
- results_tree->clear();
+ results_tree->call_deferred("clear"); // Wait for the Tree's mouse event propagation.
get_ok()->set_disabled(true);
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", get_rect());
} break;
@@ -579,18 +579,12 @@ bool EditorHelpSearch::Runner::work(uint64_t slot) {
return true;
}
-EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags) {
-
- ui_service = p_icon_service;
- results_tree = p_results_tree;
- term = p_term.strip_edges();
- search_flags = p_search_flags;
-
- if ((search_flags & SEARCH_CASE_SENSITIVE) == 0)
- term = term.to_lower();
-
- empty_icon = ui_service->get_icon("ArrowRight", "EditorIcons");
- disabled_color = ui_service->get_color("disabled_font_color", "Editor");
-
- phase = 0;
+EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags) :
+ phase(0),
+ ui_service(p_icon_service),
+ results_tree(p_results_tree),
+ term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()),
+ search_flags(p_search_flags),
+ empty_icon(ui_service->get_icon("ArrowRight", "EditorIcons")),
+ disabled_color(ui_service->get_color("disabled_font_color", "Editor")) {
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index a3743efb38..d100d7f618 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -5187,14 +5187,9 @@ EditorNode::EditorNode() {
top_region->add_child(left_menu_hb);
menu_hb->add_child(top_region);
- {
- Control *sp = memnew(Control);
- sp->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
- menu_hb->add_child(sp);
- }
-
file_menu = memnew(MenuButton);
file_menu->set_flat(false);
+ file_menu->set_switch_on_hover(true);
file_menu->set_text(TTR("Scene"));
file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(file_menu);
@@ -5286,6 +5281,7 @@ EditorNode::EditorNode() {
project_menu = memnew(MenuButton);
project_menu->set_flat(false);
+ project_menu->set_switch_on_hover(true);
project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
project_menu->set_text(TTR("Project"));
project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
@@ -5327,6 +5323,7 @@ EditorNode::EditorNode() {
debug_menu = memnew(MenuButton);
debug_menu->set_flat(false);
+ debug_menu->set_switch_on_hover(true);
debug_menu->set_text(TTR("Debug"));
debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(debug_menu);
@@ -5357,6 +5354,7 @@ EditorNode::EditorNode() {
settings_menu = memnew(MenuButton);
settings_menu->set_flat(false);
+ settings_menu->set_switch_on_hover(true);
settings_menu->set_text(TTR("Editor"));
settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(settings_menu);
@@ -5393,6 +5391,7 @@ EditorNode::EditorNode() {
// Help Menu
help_menu = memnew(MenuButton);
help_menu->set_flat(false);
+ help_menu->set_switch_on_hover(true);
help_menu->set_text(TTR("Help"));
help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
left_menu_hb->add_child(help_menu);
@@ -5409,12 +5408,8 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_icon_item(gui_base->get_icon("Godot", "EditorIcons"), TTR("About"), HELP_ABOUT);
- play_cc = memnew(CenterContainer);
- play_cc->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- menu_hb->add_child(play_cc);
-
play_button_panel = memnew(PanelContainer);
- play_cc->add_child(play_button_panel);
+ menu_hb->add_child(play_button_panel);
HBoxContainer *play_hb = memnew(HBoxContainer);
play_button_panel->add_child(play_hb);
@@ -5460,11 +5455,6 @@ EditorNode::EditorNode() {
run_native = memnew(EditorRunNative);
play_hb->add_child(run_native);
- native_play_button = memnew(MenuButton);
- native_play_button->set_text("NTV");
- menu_hb->add_child(native_play_button);
- native_play_button->hide();
- native_play_button->get_popup()->connect("id_pressed", this, "_run_in_device");
run_native->connect("native_run", this, "_menu_option", varray(RUN_PLAY_NATIVE));
play_scene_button = memnew(ToolButton);
@@ -5493,6 +5483,9 @@ EditorNode::EditorNode() {
play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5));
#endif
+ HBoxContainer *right_menu_hb = memnew(HBoxContainer);
+ menu_hb->add_child(right_menu_hb);
+
// Toggle for video driver
video_driver = memnew(OptionButton);
video_driver->set_flat(true);
@@ -5500,7 +5493,7 @@ EditorNode::EditorNode() {
video_driver->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
video_driver->connect("item_selected", this, "_video_driver_selected");
video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts"));
- menu_hb->add_child(video_driver);
+ right_menu_hb->add_child(video_driver);
String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string;
String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
@@ -5526,9 +5519,6 @@ EditorNode::EditorNode() {
progress_hb = memnew(BackgroundProgress);
- HBoxContainer *right_menu_hb = memnew(HBoxContainer);
- menu_hb->add_child(right_menu_hb);
-
layout_dialog = memnew(EditorNameDialog);
gui_base->add_child(layout_dialog);
layout_dialog->set_hide_on_ok(false);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 3a4b8d451f..e5670e5e7c 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -243,7 +243,6 @@ private:
Control *vp_base;
PaneDrag *pd;
- CenterContainer *play_cc;
HBoxContainer *menu_hb;
Control *viewport;
MenuButton *file_menu;
@@ -255,7 +254,6 @@ private:
ToolButton *export_button;
ToolButton *prev_scene;
ToolButton *play_button;
- MenuButton *native_play_button;
ToolButton *pause_button;
ToolButton *stop_button;
ToolButton *run_settings_button;
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 86b2db877e..cd024ff870 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -829,11 +829,11 @@ void EditorPlugin::_bind_methods() {
BIND_ENUM_CONSTANT(DOCK_SLOT_MAX);
}
-EditorPlugin::EditorPlugin() {
- undo_redo = NULL;
- input_event_forwarding_always_enabled = false;
- force_draw_over_forwarding_enabled = false;
- last_main_screen_name = "";
+EditorPlugin::EditorPlugin() :
+ undo_redo(NULL),
+ input_event_forwarding_always_enabled(false),
+ force_draw_over_forwarding_enabled(false),
+ last_main_screen_name("") {
}
EditorPlugin::~EditorPlugin() {
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index de948acc71..ff7ab051b5 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1096,6 +1096,8 @@ void EditorPropertyVector2::setup(double p_min, double p_max, double p_step, boo
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1177,6 +1179,8 @@ void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1257,6 +1261,8 @@ void EditorPropertyVector3::setup(double p_min, double p_max, double p_step, boo
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1337,6 +1343,8 @@ void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1419,6 +1427,8 @@ void EditorPropertyQuat::setup(double p_min, double p_max, double p_step, bool p
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1506,6 +1516,8 @@ void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1580,6 +1592,8 @@ void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step,
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1659,6 +1673,8 @@ void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1744,6 +1760,8 @@ void EditorPropertyTransform::setup(double p_min, double p_max, double p_step, b
spin[i]->set_max(p_max);
spin[i]->set_step(p_step);
spin[i]->set_hide_slider(p_no_slider);
+ spin[i]->set_allow_greater(true);
+ spin[i]->set_allow_lesser(true);
}
}
@@ -1938,6 +1956,20 @@ EditorPropertyNodePath::EditorPropertyNodePath() {
void EditorPropertyResource::_file_selected(const String &p_path) {
RES res = ResourceLoader::load(p_path);
+
+ List<PropertyInfo> prop_list;
+ get_edited_object()->get_property_list(&prop_list);
+ String type;
+
+ for (List<PropertyInfo>::Element *E = prop_list.front(); E; E = E->next()) {
+ if (E->get().name == get_edited_property() && (E->get().hint & PROPERTY_HINT_RESOURCE_TYPE)) {
+ type = E->get().hint_string;
+ }
+ }
+
+ if (!type.empty() && !res->is_class(type))
+ EditorNode::get_singleton()->show_warning(vformat(TTR("The selected resource (%s) does not match the type expected for this property (%s)."), res->get_class(), type));
+
emit_signal("property_changed", get_edited_property(), res);
update_property();
}
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 9d3ab59116..a28d071d77 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -298,19 +298,18 @@ EditorInspector *SectionedInspector::get_inspector() {
return inspector;
}
-SectionedInspector::SectionedInspector() {
-
- obj = -1;
-
- search_box = NULL;
-
+SectionedInspector::SectionedInspector() :
+ obj(-1),
+ sections(memnew(Tree)),
+ filter(memnew(SectionedInspectorFilter)),
+ inspector(memnew(EditorInspector)),
+ search_box(NULL) {
add_constant_override("autohide", 1); // Fixes the dragger always showing up
VBoxContainer *left_vb = memnew(VBoxContainer);
left_vb->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
add_child(left_vb);
- sections = memnew(Tree);
sections->set_v_size_flags(SIZE_EXPAND_FILL);
sections->set_hide_root(true);
@@ -321,8 +320,6 @@ SectionedInspector::SectionedInspector() {
right_vb->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(right_vb);
- filter = memnew(SectionedInspectorFilter);
- inspector = memnew(EditorInspector);
inspector->set_v_size_flags(SIZE_EXPAND_FILL);
right_vb->add_child(inspector, true);
inspector->set_use_doc_hints(true);
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index fdfa094ba2..7fa5019cb7 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -256,6 +256,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_THREAD_SAFE_METHOD_
+ /* Languages */
+
{
String lang_hint = "en";
String host_lang = OS::get_singleton()->get_locale();
@@ -291,11 +293,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/editor_language"] = PropertyInfo(Variant::STRING, "interface/editor/editor_language", PROPERTY_HINT_ENUM, lang_hint, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
}
+ /* Interface */
+
+ // Editor
_initial_set("interface/editor/display_scale", 0);
hints["interface/editor/display_scale"] = PropertyInfo(Variant::INT, "interface/editor/display_scale", PROPERTY_HINT_ENUM, "Auto,75%,100%,125%,150%,175%,200%,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/custom_display_scale", 1.0f);
hints["interface/editor/custom_display_scale"] = PropertyInfo(Variant::REAL, "interface/editor/custom_display_scale", PROPERTY_HINT_RANGE, "0.75,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- _initial_set("interface/scene_tabs/show_script_button", false);
_initial_set("interface/editor/main_font_size", 14);
hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font_size", 14);
@@ -317,12 +321,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/dim_amount"] = PropertyInfo(Variant::REAL, "interface/editor/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/dim_transition_time", 0.08f);
hints["interface/editor/dim_transition_time"] = PropertyInfo(Variant::REAL, "interface/editor/dim_transition_time", PROPERTY_HINT_RANGE, "0,1,0.001", PROPERTY_USAGE_DEFAULT);
-
_initial_set("interface/editor/separate_distraction_mode", false);
-
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
_initial_set("interface/editor/quit_confirmation", true);
+ // Theme
_initial_set("interface/theme/preset", "Default");
hints["interface/theme/preset"] = PropertyInfo(Variant::STRING, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Alien,Arc,Godot 2,Grey,Light,Solarized (Dark),Solarized (Light),Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/theme/icon_and_font_color", 0);
@@ -342,43 +345,88 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/theme/custom_theme", "");
hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ // Scene tabs
_initial_set("interface/scene_tabs/show_extension", false);
_initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);
_initial_set("interface/scene_tabs/resize_if_many_tabs", true);
_initial_set("interface/scene_tabs/minimum_width", 50);
hints["interface/scene_tabs/minimum_width"] = PropertyInfo(Variant::INT, "interface/scene_tabs/minimum_width", PROPERTY_HINT_RANGE, "50,500,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/scene_tabs/show_script_button", false);
+
+ /* Filesystem */
+ // Directories
_initial_set("filesystem/directories/autoscan_project_path", "");
hints["filesystem/directories/autoscan_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/autoscan_project_path", PROPERTY_HINT_GLOBAL_DIR);
_initial_set("filesystem/directories/default_project_path", OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS));
hints["filesystem/directories/default_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/default_project_path", PROPERTY_HINT_GLOBAL_DIR);
- _initial_set("filesystem/directories/default_project_export_path", "");
- hints["filesystem/directories/default_project_export_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/default_project_export_path", PROPERTY_HINT_GLOBAL_DIR);
- _initial_set("interface/scene_tabs/show_script_button", false);
+ // On save
+ _initial_set("filesystem/on_save/compress_binary_resources", true);
+ _initial_set("filesystem/on_save/safe_save_on_backup_then_rename", true);
+
+ // File dialog
+ _initial_set("filesystem/file_dialog/show_hidden_files", false);
+ _initial_set("filesystem/file_dialog/display_mode", 0);
+ hints["filesystem/file_dialog/display_mode"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
+ _initial_set("filesystem/file_dialog/thumbnail_size", 64);
+ hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
+
+ // Import
+ _initial_set("filesystem/import/pvrtc_texture_tool", "");
+#ifdef WINDOWS_ENABLED
+ hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "*.exe");
+#else
+ hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "");
+#endif
+ _initial_set("filesystem/import/pvrtc_fast_conversion", false);
+
+ /* Docks */
+
+ // SceneTree
+ _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
+ _initial_set("docks/scene_tree/draw_relationship_lines", true);
+ _initial_set("docks/scene_tree/relationship_line_color", Color::html("464646"));
+
+ // FileSystem
+ _initial_set("docks/filesystem/display_mode", 0);
+ hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Tree only, Split");
+ _initial_set("docks/filesystem/thumbnail_size", 64);
+ hints["docks/filesystem/thumbnail_size"] = PropertyInfo(Variant::INT, "docks/filesystem/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
+ _initial_set("docks/filesystem/files_display_mode", 0);
+ hints["docks/filesystem/files_display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/files_display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
+ _initial_set("docks/filesystem/always_show_folders", true);
+
+ // Property editor
+ _initial_set("docks/property_editor/auto_refresh_interval", 0.3);
+
+ /* Text editor */
+
+ // Theme
_initial_set("text_editor/theme/color_theme", "Adaptive");
hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default,Custom");
-
_initial_set("text_editor/theme/line_spacing", 6);
_initial_set("text_editor/theme/selection_color", Color::html("40808080"));
_load_default_text_editor_theme();
+ // Highlighting
_initial_set("text_editor/highlighting/syntax_highlighting", true);
-
_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
_initial_set("text_editor/highlighting/highlight_current_line", true);
_initial_set("text_editor/highlighting/highlight_type_safe_lines", true);
- _initial_set("text_editor/cursor/scroll_past_end_of_file", false);
+ // Indent
_initial_set("text_editor/indent/type", 0);
hints["text_editor/indent/type"] = PropertyInfo(Variant::INT, "text_editor/indent/type", PROPERTY_HINT_ENUM, "Tabs,Spaces");
_initial_set("text_editor/indent/size", 4);
hints["text_editor/indent/size"] = PropertyInfo(Variant::INT, "text_editor/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes.
_initial_set("text_editor/indent/auto_indent", true);
_initial_set("text_editor/indent/convert_indent_on_save", false);
+ _initial_set("text_editor/indent/draw_indent_guides", true);
_initial_set("text_editor/indent/draw_tabs", true);
+ // Line numbers
_initial_set("text_editor/line_numbers/show_line_numbers", true);
_initial_set("text_editor/line_numbers/line_numbers_zero_padded", false);
_initial_set("text_editor/line_numbers/show_breakpoint_gutter", true);
@@ -388,35 +436,45 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/line_numbers/line_length_guideline_column", 80);
hints["text_editor/line_numbers/line_length_guideline_column"] = PropertyInfo(Variant::INT, "text_editor/line_numbers/line_length_guideline_column", PROPERTY_HINT_RANGE, "20, 160, 1");
+ // Open scripts
_initial_set("text_editor/open_scripts/smooth_scrolling", true);
_initial_set("text_editor/open_scripts/v_scroll_speed", 80);
_initial_set("text_editor/open_scripts/show_members_overview", true);
+ // Files
_initial_set("text_editor/files/trim_trailing_whitespace_on_save", false);
- _initial_set("text_editor/completion/idle_parse_delay", 2);
+ _initial_set("text_editor/files/autosave_interval_secs", 0);
+ _initial_set("text_editor/files/restore_scripts_on_load", true);
+
+ // Tools
_initial_set("text_editor/tools/create_signal_callbacks", true);
_initial_set("text_editor/tools/sort_members_outline_alphabetically", false);
- _initial_set("text_editor/files/autosave_interval_secs", 0);
+ // Cursor
+ _initial_set("text_editor/cursor/scroll_past_end_of_file", false);
_initial_set("text_editor/cursor/block_caret", false);
_initial_set("text_editor/cursor/caret_blink", true);
_initial_set("text_editor/cursor/caret_blink_speed", 0.5);
hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01");
_initial_set("text_editor/cursor/right_click_moves_caret", true);
+ // Completion
+ _initial_set("text_editor/completion/idle_parse_delay", 2);
_initial_set("text_editor/completion/auto_brace_complete", false);
_initial_set("text_editor/completion/put_callhint_tooltip_below_current_line", true);
_initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
- _initial_set("text_editor/files/restore_scripts_on_load", true);
_initial_set("text_editor/completion/complete_file_paths", true);
_initial_set("text_editor/completion/add_type_hints", false);
- _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
- _initial_set("docks/scene_tree/draw_relationship_lines", true);
- _initial_set("docks/scene_tree/relationship_line_color", Color::html("464646"));
+ // Help
+ _initial_set("text_editor/help/show_help_index", true);
+ /* Editors */
+
+ // GridMap
_initial_set("editors/grid_map/pick_distance", 5000.0);
+ // 3D
_initial_set("editors/3d/primary_grid_color", Color::html("909090"));
hints["editors/3d/primary_grid_color"] = PropertyInfo(Variant::COLOR, "editors/3d/primary_grid_color", PROPERTY_HINT_COLOR_NO_ALPHA, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
@@ -433,7 +491,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/3d/default_z_near", 0.05);
_initial_set("editors/3d/default_z_far", 500.0);
- // navigation
+ // 3D: Navigation
_initial_set("editors/3d/navigation/navigation_scheme", 0);
_initial_set("editors/3d/navigation/invert_y_axis", false);
hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo");
@@ -447,14 +505,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["editors/3d/navigation/pan_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/pan_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
_initial_set("editors/3d/navigation/zoom_modifier", 4);
hints["editors/3d/navigation/zoom_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
-
- // _initial_set("editors/3d/navigation/emulate_numpad", false); not used at the moment
_initial_set("editors/3d/navigation/warped_mouse_panning", true);
- // navigation feel
+ // 3D: Navigation feel
_initial_set("editors/3d/navigation_feel/orbit_sensitivity", 0.4);
hints["editors/3d/navigation_feel/orbit_sensitivity"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_sensitivity", PROPERTY_HINT_RANGE, "0.0, 2, 0.01");
-
_initial_set("editors/3d/navigation_feel/orbit_inertia", 0.05);
hints["editors/3d/navigation_feel/orbit_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
_initial_set("editors/3d/navigation_feel/translation_inertia", 0.15);
@@ -466,7 +521,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/3d/navigation_feel/manipulation_translation_inertia", 0.075);
hints["editors/3d/navigation_feel/manipulation_translation_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/manipulation_translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
- // freelook
+ // 3D: Freelook
_initial_set("editors/3d/freelook/freelook_inertia", 0.1);
hints["editors/3d/freelook/freelook_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
_initial_set("editors/3d/freelook/freelook_base_speed", 5.0);
@@ -477,6 +532,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["editors/3d/freelook/freelook_modifier_speed_factor"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_modifier_speed_factor", PROPERTY_HINT_RANGE, "0.0, 10.0, 0.1");
_initial_set("editors/3d/freelook/freelook_speed_zoom_link", false);
+ // 2D
_initial_set("editors/2d/grid_color", Color(1.0, 1.0, 1.0, 0.07));
_initial_set("editors/2d/guides_color", Color(0.6, 0.0, 0.8));
_initial_set("editors/2d/bone_width", 5);
@@ -493,9 +549,19 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/scroll_to_pan", false);
_initial_set("editors/2d/pan_speed", 20);
+ // Polygon editor
_initial_set("editors/poly_editor/point_grab_radius", 8);
_initial_set("editors/poly_editor/show_previous_outline", true);
+ // Animation
+ _initial_set("editors/animation/autorename_animation_tracks", true);
+ _initial_set("editors/animation/confirm_insert_track", true);
+ _initial_set("editors/animation/onion_layers_past_color", Color(1, 0, 0));
+ _initial_set("editors/animation/onion_layers_future_color", Color(0, 1, 0));
+
+ /* Run */
+
+ // Window placement
_initial_set("run/window_placement/rect", 1);
hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen");
String screen_hints = "Same as Editor,Previous Monitor,Next Monitor";
@@ -506,54 +572,15 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("run/window_placement/screen", 0);
hints["run/window_placement/screen"] = PropertyInfo(Variant::INT, "run/window_placement/screen", PROPERTY_HINT_ENUM, screen_hints);
- _initial_set("filesystem/on_save/compress_binary_resources", true);
- _initial_set("filesystem/on_save/save_modified_external_resources", true);
-
- _initial_set("text_editor/tools/create_signal_callbacks", true);
-
- _initial_set("filesystem/file_dialog/show_hidden_files", false);
- _initial_set("filesystem/file_dialog/display_mode", 0);
- hints["filesystem/file_dialog/display_mode"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
-
- _initial_set("filesystem/file_dialog/thumbnail_size", 64);
- hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
-
- _initial_set("docks/filesystem/display_mode", 0);
- hints["docks/filesystem/display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/display_mode", PROPERTY_HINT_ENUM, "Tree only, Split");
- _initial_set("docks/filesystem/thumbnail_size", 64);
- hints["docks/filesystem/thumbnail_size"] = PropertyInfo(Variant::INT, "docks/filesystem/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16");
- _initial_set("docks/filesystem/files_display_mode", 0);
- hints["docks/filesystem/files_display_mode"] = PropertyInfo(Variant::INT, "docks/filesystem/files_display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List");
- _initial_set("docks/filesystem/always_show_folders", true);
-
- _initial_set("editors/animation/autorename_animation_tracks", true);
- _initial_set("editors/animation/confirm_insert_track", true);
- _initial_set("editors/animation/onion_layers_past_color", Color(1, 0, 0));
- _initial_set("editors/animation/onion_layers_future_color", Color(0, 1, 0));
-
- _initial_set("docks/property_editor/texture_preview_width", 48);
- _initial_set("docks/property_editor/auto_refresh_interval", 0.3);
- _initial_set("text_editor/help/show_help_index", true);
-
- _initial_set("filesystem/import/ask_save_before_reimport", false);
-
- _initial_set("filesystem/import/pvrtc_texture_tool", "");
-#ifdef WINDOWS_ENABLED
- hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "*.exe");
-#else
- hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "");
-#endif
- _initial_set("filesystem/import/pvrtc_fast_conversion", false);
-
+ // Auto save
_initial_set("run/auto_save/save_before_running", true);
+
+ // Output
_initial_set("run/output/always_clear_output_on_play", true);
_initial_set("run/output/always_open_output_on_play", true);
_initial_set("run/output/always_close_output_on_stop", false);
- _initial_set("filesystem/resources/save_compressed_resources", true);
- _initial_set("filesystem/resources/auto_reload_modified_images", true);
- _initial_set("filesystem/import/automatic_reimport_on_sources_changed", true);
- _initial_set("filesystem/on_save/safe_save_on_backup_then_rename", true);
+ /* Extra config */
if (p_extra_config.is_valid()) {
@@ -592,8 +619,8 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/engine_type_color", Color::html("83d3ff"));
_initial_set("text_editor/highlighting/comment_color", Color::html("676767"));
_initial_set("text_editor/highlighting/string_color", Color::html("ef6ebe"));
- _initial_set("text_editor/highlighting/background_color", dark_theme ? Color::html("3b000000") : Color::html("#323b4f"));
- _initial_set("text_editor/highlighting/completion_background_color", Color::html("2C2A32"));
+ _initial_set("text_editor/highlighting/background_color", dark_theme ? Color::html("3b000000") : Color::html("323b4f"));
+ _initial_set("text_editor/highlighting/completion_background_color", Color::html("2c2a32"));
_initial_set("text_editor/highlighting/completion_selected_color", Color::html("434244"));
_initial_set("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
_initial_set("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
@@ -603,13 +630,14 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/safe_line_number_color", Color::html("99aac8aa"));
_initial_set("text_editor/highlighting/caret_color", Color::html("aaaaaa"));
_initial_set("text_editor/highlighting/caret_background_color", Color::html("000000"));
+ _initial_set("text_editor/highlighting/indent_guide_color", Color::html("50808080"));
_initial_set("text_editor/highlighting/text_selected_color", Color::html("000000"));
_initial_set("text_editor/highlighting/selection_color", Color::html("6ca9c2"));
_initial_set("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
_initial_set("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
_initial_set("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1));
_initial_set("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
- _initial_set("text_editor/highlighting/number_color", Color::html("EB9532"));
+ _initial_set("text_editor/highlighting/number_color", Color::html("eb9532"));
_initial_set("text_editor/highlighting/function_color", Color::html("66a2ce"));
_initial_set("text_editor/highlighting/member_variable_color", Color::html("e64e59"));
_initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 7b0de9617c..dabe697f10 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -71,23 +71,23 @@ private:
bool hide_from_editor;
bool save;
bool restart_if_changed;
- VariantContainer() {
- variant = Variant();
- initial = Variant();
- order = 0;
- hide_from_editor = false;
- has_default_value = false;
- save = false;
- restart_if_changed = false;
+ VariantContainer() :
+ order(0),
+ variant(Variant()),
+ initial(Variant()),
+ has_default_value(false),
+ hide_from_editor(false),
+ save(false),
+ restart_if_changed(false) {
}
- VariantContainer(const Variant &p_variant, int p_order) {
- variant = p_variant;
- initial = Variant();
- order = p_order;
- hide_from_editor = false;
- has_default_value = false;
- save = false;
- restart_if_changed = false;
+ VariantContainer(const Variant &p_variant, int p_order) :
+ order(p_order),
+ variant(p_variant),
+ initial(Variant()),
+ has_default_value(false),
+ hide_from_editor(false),
+ save(false),
+ restart_if_changed(false) {
}
};
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 36053d7534..3dfc49583c 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1080,6 +1080,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color safe_line_number_color = dim_color * Color(1, 1.2, 1, 1.5);
const Color caret_color = mono_color;
const Color caret_background_color = mono_color.inverted();
+ const Color indent_guide_color = alpha2;
const Color text_selected_color = dark_color_3;
const Color selection_color = alpha2;
const Color brace_mismatch_color = error_color;
@@ -1115,6 +1116,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/highlighting/safe_line_number_color", safe_line_number_color, true);
setting->set_initial_value("text_editor/highlighting/caret_color", caret_color, true);
setting->set_initial_value("text_editor/highlighting/caret_background_color", caret_background_color, true);
+ setting->set_initial_value("text_editor/highlighting/indent_guide_color", indent_guide_color, true);
setting->set_initial_value("text_editor/highlighting/text_selected_color", text_selected_color, true);
setting->set_initial_value("text_editor/highlighting/selection_color", selection_color, true);
setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", brace_mismatch_color, true);
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 8e69090da3..93c462f747 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -771,7 +771,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
int binormal_pos = (binormal_src->stride ? binormal_src->stride : 3) * p.indices[src + binormal_ofs];
ERR_FAIL_INDEX_V(binormal_pos, binormal_src->array.size(), ERR_INVALID_DATA);
- Vector3 binormal = Vector3(-binormal_src->array[binormal_pos + 0], -binormal_src->array[binormal_pos + 1], -binormal_src->array[binormal_pos + 2]); // Due to Godots face order it seems we need to flip our binormal!
+ Vector3 binormal = Vector3(binormal_src->array[binormal_pos + 0], binormal_src->array[binormal_pos + 1], binormal_src->array[binormal_pos + 2]);
int tangent_pos = (tangent_src->stride ? tangent_src->stride : 3) * p.indices[src + tangent_ofs];
ERR_FAIL_INDEX_V(tangent_pos, tangent_src->array.size(), ERR_INVALID_DATA);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 00ca86a43b..b5d646d5d4 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -899,16 +899,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
}
if (a.has("TANGENT")) {
- PoolVector<float> tans = _decode_accessor_as_floats(state, a["TANGENT"], true);
- { // we need our binormals inversed, so flip our w component.
- int ts = tans.size();
- PoolVector<float>::Write w = tans.write();
-
- for (int j = 3; j < ts; j += 4) {
- w[j] *= -1.0;
- }
- }
- array[Mesh::ARRAY_TANGENT] = tans;
+ array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true);
}
if (a.has("TEXCOORD_0")) {
array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true);
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index 8258ec41fd..721db30112 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -114,14 +114,14 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Vector<int> children;
Vector<Node *> godot_nodes;
- GLTFNode() {
- // child_of_skeleton = -1;
- // skeleton_skin = -1;
- mesh = -1;
- camera = -1;
- parent = -1;
- skin = -1;
- scale = Vector3(1, 1, 1);
+ GLTFNode() :
+ parent(-1),
+ mesh(-1),
+ camera(-1),
+ skin(-1),
+ //skeleton_skin(-1),
+ //child_of_skeleton(-1),
+ scale(Vector3(1, 1, 1)) {
}
};
@@ -134,12 +134,12 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
bool indices;
//matrices need to be transformed to this
- GLTFBufferView() {
- buffer = 0;
- byte_offset = 0;
- byte_length = 0;
- byte_stride = 0;
- indices = false;
+ GLTFBufferView() :
+ buffer(0),
+ byte_offset(0),
+ byte_length(0),
+ byte_stride(0),
+ indices(false) {
}
};
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 55f4cc7439..85ea0d343c 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -272,12 +272,18 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
for (int i = 0; i < 10; i++)
file->get_32(); // i wish to know why should i do this... no doc!
- // only read 0x00 (loop forward) and 0x01 (loop ping-pong) and skip anything else because
- // it's not supported (loop backward), reserved for future uses or sampler specific
+ // only read 0x00 (loop forward), 0x01 (loop ping-pong) and 0x02 (loop backward)
+ // Skip anything else because it's not supported, reserved for future uses or sampler specific
// from https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl (loop type values table)
int loop_type = file->get_32();
- if (loop_type == 0x00 || loop_type == 0x01) {
- loop = loop_type ? AudioStreamSample::LOOP_PING_PONG : AudioStreamSample::LOOP_FORWARD;
+ if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) {
+ if (loop_type == 0x00) {
+ loop = AudioStreamSample::LOOP_FORWARD;
+ } else if (loop_type == 0x01) {
+ loop = AudioStreamSample::LOOP_PING_PONG;
+ } else if (loop_type == 0x02) {
+ loop = AudioStreamSample::LOOP_BACKWARD;
+ }
loop_begin = file->get_32();
loop_end = file->get_32();
}
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index a85f4456f7..dfdf56a2ef 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -425,7 +425,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
return true;
} else {
- const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) {
//wip closed
@@ -565,7 +565,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
offset = _get_offset(j);
}
- if (!wip_active && j == edited_point.polygon && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) {
+ if (!wip_active && j == edited_point.polygon && EDITOR_GET("editors/poly_editor/show_previous_outline")) {
const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color();
const int n = pre_move_edit.size();
@@ -695,7 +695,7 @@ AbstractPolygon2DEditor::Vertex AbstractPolygon2DEditor::get_active_point() cons
AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const Vector2 &p_pos) const {
- const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
const int n_polygons = _get_polygon_count();
const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform();
@@ -726,7 +726,7 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const
AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(const Vector2 &p_pos) const {
- const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
const real_t eps = grab_threshold * 2;
const real_t eps2 = eps * eps;
@@ -826,13 +826,11 @@ void AbstractPolygon2DEditorPlugin::make_visible(bool p_visible) {
}
}
-AbstractPolygon2DEditorPlugin::AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class) {
-
- editor = p_node;
- polygon_editor = p_polygon_editor;
- klass = p_class;
+AbstractPolygon2DEditorPlugin::AbstractPolygon2DEditorPlugin(EditorNode *p_node, AbstractPolygon2DEditor *p_polygon_editor, String p_class) :
+ polygon_editor(p_polygon_editor),
+ editor(p_node),
+ klass(p_class) {
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(polygon_editor);
-
polygon_editor->hide();
}
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index e2daefdec6..e7934ea3a0 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -70,9 +70,9 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
String name;
String type;
Ref<Script> script;
- AddOption(const String &p_name = String(), const String &p_type = String()) {
- name = p_name;
- type = p_type;
+ AddOption(const String &p_name = String(), const String &p_type = String()) :
+ name(p_name),
+ type(p_type) {
}
};
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 8d9872236c..c272f8d756 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -456,7 +456,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
if (Object::cast_to<Viewport>(p_node))
return;
- const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ const real_t grab_distance = EDITOR_GET("editors/poly_editor/point_grab_radius");
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp
index e92a91db7c..9b31f2e24d 100644
--- a/editor/plugins/collision_polygon_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -144,7 +144,7 @@ bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Ref<Inpu
Vector<Vector2> poly = node->call("get_polygon");
//first check if a point is to be added (segment split)
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
+ real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
switch (mode) {
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index c67c96798a..3d4816b17b 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -70,8 +70,9 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (!node->get_curve().is_valid())
return false;
- Ref<InputEventMouseButton> mb = p_event;
+ real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius");
+ Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
@@ -79,8 +80,6 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
Vector2 gpoint = mb->get_position();
Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position())));
- real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
-
if (mb->is_pressed() && action == ACTION_NONE) {
Ref<Curve2D> curve = node->get_curve();
@@ -179,6 +178,41 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
+ // Check for segment split.
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mode == MODE_EDIT && on_edge == true) {
+ Vector2 gpoint = mb->get_position();
+ Ref<Curve2D> curve = node->get_curve();
+
+ int insertion_point = -1;
+ float mbLength = curve->get_closest_offset(xform.affine_inverse().xform(gpoint));
+ int len = curve->get_point_count();
+ for (int i = 0; i < len - 1; i++) {
+ float compareLength = curve->get_closest_offset(curve->get_point_position(i + 1));
+ if (mbLength >= curve->get_closest_offset(curve->get_point_position(i)) && mbLength <= compareLength)
+ insertion_point = i;
+ }
+ if (insertion_point == -1)
+ insertion_point = curve->get_point_count() - 2;
+
+ undo_redo->create_action(TTR("Split Curve"));
+ undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint), Vector2(0, 0), Vector2(0, 0), insertion_point + 1);
+ undo_redo->add_undo_method(curve.ptr(), "remove_point", insertion_point + 1);
+ undo_redo->add_do_method(canvas_item_editor, "update_viewport");
+ undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
+ undo_redo->commit_action();
+
+ action = ACTION_MOVING_POINT;
+ action_point = insertion_point + 1;
+ moving_from = curve->get_point_position(action_point);
+ moving_screen_from = gpoint;
+
+ canvas_item_editor->update_viewport();
+
+ on_edge = false;
+
+ return true;
+ }
+
// Check for point movement completion.
if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && action != ACTION_NONE) {
@@ -245,6 +279,49 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
+ if (action == ACTION_NONE && mode == MODE_EDIT) {
+ // Handle Edge Follow
+ bool old_edge = on_edge;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Vector2 gpoint = mm->get_position();
+
+ Ref<Curve2D> curve = node->get_curve();
+ if (curve == NULL) return true;
+ if (curve->get_point_count() < 2) return true;
+
+ // Find edge
+ edge_point = xform.xform(curve->get_closest_point(xform.affine_inverse().xform(mm->get_position())));
+ on_edge = false;
+ if (edge_point.distance_to(gpoint) <= grab_threshold) {
+ on_edge = true;
+ }
+ // However, if near a control point or its in-out handles then not on edge
+ int len = curve->get_point_count();
+ for (int i = 0; i < len; i++) {
+ Vector2 pp = curve->get_point_position(i);
+ Vector2 p = xform.xform(pp);
+ if (p.distance_to(gpoint) <= grab_threshold) {
+ on_edge = false;
+ break;
+ }
+ p = xform.xform(pp + curve->get_point_in(i));
+ if (p.distance_to(gpoint) <= grab_threshold) {
+ on_edge = false;
+ break;
+ }
+ p = xform.xform(pp + curve->get_point_out(i));
+ if (p.distance_to(gpoint) <= grab_threshold) {
+ on_edge = false;
+ break;
+ }
+ }
+ if (on_edge || old_edge != on_edge) {
+ canvas_item_editor->update_viewport();
+ return true;
+ }
+ }
+
if (action != ACTION_NONE) {
// Handle point/control movement.
Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
@@ -309,7 +386,6 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Control *vpc = canvas_item_editor->get_viewport_control();
for (int i = 0; i < len; i++) {
-
Vector2 point = xform.xform(curve->get_point_position(i));
vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false, Color(1, 1, 1, 1));
@@ -325,6 +401,11 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
vpc->draw_texture_rect(handle, Rect2(pointin - handle_size * 0.5, handle_size), false, Color(1, 0.5, 1, 0.3));
}
}
+
+ if (on_edge) {
+ Ref<Texture> add_handle = get_icon("EditorHandleAdd", "EditorIcons");
+ p_overlay->draw_texture(add_handle, edge_point - add_handle->get_size() * 0.5);
+ }
}
void Path2DEditor::_node_visibility_changed() {
@@ -442,6 +523,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
undo_redo = editor->get_undo_redo();
mirror_handle_angle = true;
mirror_handle_length = true;
+ on_edge = false;
mode = MODE_EDIT;
action = ACTION_NONE;
@@ -455,7 +537,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons"));
curve_edit->set_toggle_mode(true);
curve_edit->set_focus_mode(Control::FOCUS_NONE);
- curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point"));
+ curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point"));
curve_edit->connect("pressed", this, "_mode_selected", varray(MODE_EDIT));
base_hb->add_child(curve_edit);
curve_edit_curve = memnew(ToolButton);
@@ -469,7 +551,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) {
curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons"));
curve_create->set_toggle_mode(true);
curve_create->set_focus_mode(Control::FOCUS_NONE);
- curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)"));
+ curve_create->set_tooltip(TTR("Add Point (in empty space)"));
curve_create->connect("pressed", this, "_mode_selected", varray(MODE_CREATE));
base_hb->add_child(curve_create);
curve_del = memnew(ToolButton);
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 3a78657746..34952b473a 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -73,6 +73,7 @@ class Path2DEditor : public HBoxContainer {
bool mirror_handle_angle;
bool mirror_handle_length;
+ bool on_edge;
enum HandleOption {
HANDLE_OPTION_ANGLE,
@@ -93,6 +94,7 @@ class Path2DEditor : public HBoxContainer {
Point2 moving_screen_from;
float orig_in_length;
float orig_out_length;
+ Vector2 edge_point;
void _mode_selected(int p_mode);
void _handle_option_pressed(int p_option);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 75529d6007..44f1625d06 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -897,12 +897,12 @@ void ScriptEditor::_file_dialog_action(String p_file) {
} break;
case THEME_SAVE_AS: {
if (!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) {
- editor->show_warning(TTR("Error while saving theme"), TTR("Error saving"));
+ editor->show_warning(TTR("Error while saving theme."), TTR("Error Saving"));
}
} break;
case THEME_IMPORT: {
if (!EditorSettings::get_singleton()->import_text_editor_theme(p_file)) {
- editor->show_warning(TTR("Error importing theme"), TTR("Error importing"));
+ editor->show_warning(TTR("Error importing theme."), TTR("Error Importing"));
}
} break;
}
@@ -1090,7 +1090,7 @@ void ScriptEditor::_menu_option(int p_option) {
Ref<Script> scr = current->get_edited_resource();
if (scr == NULL || scr.is_null()) {
- EditorNode::get_singleton()->show_warning("Can't obtain the script for running");
+ EditorNode::get_singleton()->show_warning("Can't obtain the script for running.");
break;
}
@@ -1103,13 +1103,13 @@ void ScriptEditor::_menu_option(int p_option) {
}
if (!scr->is_tool()) {
- EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run");
+ EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run.");
return;
}
if (!ClassDB::is_parent_class(scr->get_instance_base_type(), "EditorScript")) {
- EditorNode::get_singleton()->show_warning("To run this script, it must inherit EditorScript and be set to tool mode");
+ EditorNode::get_singleton()->show_warning("To run this script, it must inherit EditorScript and be set to tool mode.");
return;
}
@@ -2977,10 +2977,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
file_menu = memnew(MenuButton);
menu_hb->add_child(file_menu);
file_menu->set_text(TTR("File"));
+ file_menu->set_switch_on_hover(true);
file_menu->get_popup()->set_hide_on_window_lose_focus(true);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script")), FILE_NEW);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New TextFile")), FILE_NEW_TEXTFILE);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script...")), FILE_NEW);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New TextFile...")), FILE_NEW_TEXTFILE);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN);
file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT);
recent_scripts = memnew(PopupMenu);
@@ -3009,10 +3010,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
theme_submenu->set_name("Theme");
file_menu->get_popup()->add_child(theme_submenu);
theme_submenu->connect("id_pressed", this, "_theme_option");
- theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme")), THEME_IMPORT);
+ theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme...")), THEME_IMPORT);
theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/reload_theme", TTR("Reload Theme")), THEME_RELOAD);
+ theme_submenu->add_separator();
theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme", TTR("Save Theme")), THEME_SAVE);
- theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As")), THEME_SAVE_AS);
+ theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As...")), THEME_SAVE_AS);
file_menu->get_popup()->add_separator();
file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS);
@@ -3028,6 +3030,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
script_search_menu = memnew(MenuButton);
menu_hb->add_child(script_search_menu);
script_search_menu->set_text(TTR("Search"));
+ script_search_menu->set_switch_on_hover(true);
script_search_menu->get_popup()->set_hide_on_window_lose_focus(true);
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F), HELP_SEARCH_FIND);
script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT);
@@ -3037,6 +3040,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
debug_menu = memnew(MenuButton);
menu_hb->add_child(debug_menu);
debug_menu->set_text(TTR("Debug"));
+ debug_menu->set_switch_on_hover(true);
debug_menu->get_popup()->set_hide_on_window_lose_focus(true);
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT);
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index e6bb8b24a9..6d4b1d1b9c 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -131,6 +131,7 @@ void ScriptTextEditor::_load_theme_settings() {
Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
+ Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
@@ -163,6 +164,7 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->add_color_override("safe_line_number_color", safe_line_number_color);
text_edit->add_color_override("caret_color", caret_color);
text_edit->add_color_override("caret_background_color", caret_background_color);
+ text_edit->add_color_override("indent_guide_color", indent_guide_color);
text_edit->add_color_override("font_selected_color", text_selected_color);
text_edit->add_color_override("selection_color", selection_color);
text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color);
@@ -1076,7 +1078,7 @@ void ScriptTextEditor::set_syntax_highlighter(SyntaxHighlighter *p_highlighter)
if (p_highlighter != NULL)
highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(p_highlighter->get_name()), true);
else
- highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text("Standard"), true);
+ highlighter_menu->set_item_checked(highlighter_menu->get_item_idx_from_text(TTR("Standard")), true);
}
void ScriptTextEditor::_change_syntax_highlighter(int p_idx) {
@@ -1466,6 +1468,7 @@ ScriptTextEditor::ScriptTextEditor() {
edit_menu = memnew(MenuButton);
edit_menu->set_text(TTR("Edit"));
+ edit_menu->set_switch_on_hover(true);
edit_menu->get_popup()->set_hide_on_window_lose_focus(true);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
@@ -1509,7 +1512,7 @@ ScriptTextEditor::ScriptTextEditor() {
convert_case->add_shortcut(ED_SHORTCUT("script_text_editor/capitalize", TTR("Capitalize"), KEY_MASK_SHIFT | KEY_F6), EDIT_CAPITALIZE);
convert_case->connect("id_pressed", this, "_edit_option");
- highlighters["Standard"] = NULL;
+ highlighters[TTR("Standard")] = NULL;
highlighter_menu = memnew(PopupMenu);
highlighter_menu->set_name("highlighter_menu");
edit_menu->get_popup()->add_child(highlighter_menu);
@@ -1520,6 +1523,7 @@ ScriptTextEditor::ScriptTextEditor() {
search_menu = memnew(MenuButton);
edit_hb->add_child(search_menu);
search_menu->set_text(TTR("Search"));
+ search_menu->set_switch_on_hover(true);
search_menu->get_popup()->set_hide_on_window_lose_focus(true);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 914901b29a..e3389f25cf 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -70,6 +70,7 @@ void ShaderTextEditor::_load_theme_settings() {
Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
+ Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
@@ -98,6 +99,7 @@ void ShaderTextEditor::_load_theme_settings() {
get_text_edit()->add_color_override("line_number_color", line_number_color);
get_text_edit()->add_color_override("caret_color", caret_color);
get_text_edit()->add_color_override("caret_background_color", caret_background_color);
+ get_text_edit()->add_color_override("indent_guide_color", indent_guide_color);
get_text_edit()->add_color_override("font_selected_color", text_selected_color);
get_text_edit()->add_color_override("selection_color", selection_color);
get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color);
@@ -368,6 +370,7 @@ void ShaderEditor::_editor_settings_changed() {
shader_editor->get_text_edit()->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size"));
shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent"));
+ shader_editor->get_text_edit()->set_draw_indent_guides(EditorSettings::get_singleton()->get("text_editor/indent/draw_indent_guides"));
shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
@@ -531,9 +534,8 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
HBoxContainer *hbc = memnew(HBoxContainer);
edit_menu = memnew(MenuButton);
- //edit_menu->set_position(Point2(5, -1));
edit_menu->set_text(TTR("Edit"));
-
+ edit_menu->set_switch_on_hover(true);
edit_menu->get_popup()->set_hide_on_window_lose_focus(true);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
@@ -553,12 +555,11 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
-
edit_menu->get_popup()->connect("id_pressed", this, "_menu_option");
search_menu = memnew(MenuButton);
- //search_menu->set_position(Point2(38, -1));
search_menu->set_text(TTR("Search"));
+ search_menu->set_switch_on_hover(true);
search_menu->get_popup()->set_hide_on_window_lose_focus(true);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index cc5f50a834..4fe278d005 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -5475,6 +5475,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
transform_menu = memnew(MenuButton);
transform_menu->set_text(TTR("Transform"));
+ transform_menu->set_switch_on_hover(true);
hbc_menu->add_child(transform_menu);
p = transform_menu->get_popup();
@@ -5487,6 +5488,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
view_menu = memnew(MenuButton);
view_menu->set_text(TTR("View"));
+ view_menu->set_switch_on_hover(true);
hbc_menu->add_child(view_menu);
p = view_menu->get_popup();
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 4a8eae1ba4..52dd115b3e 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -84,6 +84,7 @@ void TextEditor::_load_theme_settings() {
Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
+ Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color");
Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color");
Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color");
@@ -115,6 +116,7 @@ void TextEditor::_load_theme_settings() {
text_edit->add_color_override("line_number_color", line_number_color);
text_edit->add_color_override("caret_color", caret_color);
text_edit->add_color_override("caret_background_color", caret_background_color);
+ text_edit->add_color_override("indent_guide_color", indent_guide_color);
text_edit->add_color_override("font_selected_color", text_selected_color);
text_edit->add_color_override("selection_color", selection_color);
text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color);
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index fe896e12ff..cab9a4297d 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -185,6 +185,7 @@ void TileSetEditor::_bind_methods() {
ClassDB::bind_method("_on_workspace_input", &TileSetEditor::_on_workspace_input);
ClassDB::bind_method("_on_tool_clicked", &TileSetEditor::_on_tool_clicked);
ClassDB::bind_method("_on_priority_changed", &TileSetEditor::_on_priority_changed);
+ ClassDB::bind_method("_on_z_index_changed", &TileSetEditor::_on_z_index_changed);
ClassDB::bind_method("_on_grid_snap_toggled", &TileSetEditor::_on_grid_snap_toggled);
ClassDB::bind_method("_set_snap_step", &TileSetEditor::_set_snap_step);
ClassDB::bind_method("_set_snap_off", &TileSetEditor::_set_snap_off);
@@ -233,6 +234,7 @@ void TileSetEditor::_notification(int p_what) {
tool_editmode[EDITMODE_BITMASK]->set_icon(get_icon("PackedDataContainer", "EditorIcons"));
tool_editmode[EDITMODE_PRIORITY]->set_icon(get_icon("MaterialPreviewLight1", "EditorIcons"));
tool_editmode[EDITMODE_ICON]->set_icon(get_icon("LargeTexture", "EditorIcons"));
+ tool_editmode[EDITMODE_Z_INDEX]->set_icon(get_icon("Sort", "EditorIcons"));
scroll->add_style_override("bg", get_stylebox("bg", "Tree"));
} break;
@@ -320,7 +322,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
tool_hb = memnew(HBoxContainer);
g = Ref<ButtonGroup>(memnew(ButtonGroup));
- String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" };
+ String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon", "Z Index" };
for (int i = 0; i < (int)EDITMODE_MAX; i++) {
tool_editmode[i] = memnew(Button);
tool_editmode[i]->set_text(label[i]);
@@ -395,6 +397,15 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
spin_priority->hide();
toolbar->add_child(spin_priority);
+ spin_z_index = memnew(SpinBox);
+ spin_z_index->set_min(VS::CANVAS_ITEM_Z_MIN);
+ spin_z_index->set_max(VS::CANVAS_ITEM_Z_MAX);
+ spin_z_index->set_step(1);
+ spin_z_index->set_custom_minimum_size(Size2(100, 0));
+ spin_z_index->connect("value_changed", this, "_on_z_index_changed");
+ spin_z_index->hide();
+ toolbar->add_child(spin_z_index);
+
Control *separator = memnew(Control);
separator->set_h_size_flags(SIZE_EXPAND_FILL);
toolbar->add_child(separator);
@@ -617,6 +628,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
tools[TOOL_SELECT]->set_tooltip(TTR("Drag handles to edit Rect.\nClick on another Tile to edit it."));
tools[SHAPE_DELETE]->set_tooltip(TTR("Delete selected Rect."));
spin_priority->hide();
+ spin_z_index->hide();
} break;
case EDITMODE_COLLISION:
case EDITMODE_NAVIGATION:
@@ -639,6 +651,8 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.\nClick on another Tile to edit it."));
tools[SHAPE_DELETE]->set_tooltip(TTR("Delete polygon."));
spin_priority->hide();
+ spin_z_index->hide();
+
select_coord(edited_shape_coord);
} break;
case EDITMODE_BITMASK: {
@@ -661,6 +675,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
tools[TOOL_SELECT]->set_tooltip(TTR("LMB: Set bit on.\nRMB: Set bit off.\nClick on another Tile to edit it."));
spin_priority->hide();
} break;
+ case EDITMODE_Z_INDEX:
case EDITMODE_PRIORITY:
case EDITMODE_ICON: {
tools[TOOL_SELECT]->show();
@@ -681,9 +696,15 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
if (edit_mode == EDITMODE_ICON) {
tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.\nClick on another Tile to edit it."));
spin_priority->hide();
- } else {
+ spin_z_index->hide();
+ } else if (edit_mode == EDITMODE_PRIORITY) {
tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its priority.\nClick on another Tile to edit it."));
spin_priority->show();
+ spin_z_index->hide();
+ } else {
+ tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its z index.\nClick on another Tile to edit it."));
+ spin_priority->hide();
+ spin_z_index->show();
}
} break;
default: {}
@@ -811,6 +832,10 @@ void TileSetEditor::_on_workspace_draw() {
spin_priority->set_suffix(" / " + String::num(total, 0));
draw_highlight_subtile(edited_shape_coord, queue_others);
} break;
+ case EDITMODE_Z_INDEX: {
+ spin_z_index->set_value(tileset->autotile_get_z_index(get_current_tile(), edited_shape_coord));
+ draw_highlight_subtile(edited_shape_coord);
+ } break;
default: {}
}
}
@@ -1205,7 +1230,8 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
case EDITMODE_COLLISION:
case EDITMODE_OCCLUSION:
case EDITMODE_NAVIGATION:
- case EDITMODE_PRIORITY: {
+ case EDITMODE_PRIORITY:
+ case EDITMODE_Z_INDEX: {
Vector2 shape_anchor = Vector2(0, 0);
if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) {
shape_anchor = edited_shape_coord;
@@ -1481,6 +1507,11 @@ void TileSetEditor::_on_priority_changed(float val) {
workspace->update();
}
+void TileSetEditor::_on_z_index_changed(float val) {
+ tileset->autotile_set_z_index(get_current_tile(), edited_shape_coord, (int)val);
+ workspace->update();
+}
+
void TileSetEditor::_on_grid_snap_toggled(bool p_val) {
helper->set_snap_options_visible(p_val);
workspace->update();
@@ -2219,7 +2250,7 @@ void TileSetEditor::update_workspace_tile_mode() {
separator_editmode->show();
if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
- if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) {
+ if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed() || tool_editmode[EDITMODE_Z_INDEX]->is_pressed()) {
tool_editmode[EDITMODE_COLLISION]->set_pressed(true);
edit_mode = EDITMODE_COLLISION;
}
@@ -2228,6 +2259,7 @@ void TileSetEditor::update_workspace_tile_mode() {
tool_editmode[EDITMODE_ICON]->hide();
tool_editmode[EDITMODE_BITMASK]->hide();
tool_editmode[EDITMODE_PRIORITY]->hide();
+ tool_editmode[EDITMODE_Z_INDEX]->hide();
} else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) {
if (edit_mode == EDITMODE_ICON)
select_coord(tileset->autotile_get_icon_coordinate(get_current_tile()));
diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h
index e713818c70..276e23f9ee 100644
--- a/editor/plugins/tile_set_editor_plugin.h
+++ b/editor/plugins/tile_set_editor_plugin.h
@@ -71,6 +71,7 @@ class TileSetEditor : public HSplitContainer {
EDITMODE_BITMASK,
EDITMODE_PRIORITY,
EDITMODE_ICON,
+ EDITMODE_Z_INDEX,
EDITMODE_MAX
};
@@ -138,6 +139,7 @@ class TileSetEditor : public HSplitContainer {
VSeparator *separator_delete;
VSeparator *separator_grid;
SpinBox *spin_priority;
+ SpinBox *spin_z_index;
WorkspaceMode workspace_mode;
EditMode edit_mode;
int current_tile;
@@ -178,6 +180,7 @@ private:
void _on_workspace_input(const Ref<InputEvent> &p_ie);
void _on_tool_clicked(int p_tool);
void _on_priority_changed(float val);
+ void _on_z_index_changed(float val);
void _on_grid_snap_toggled(bool p_val);
void _set_snap_step(Vector2 p_val);
void _set_snap_off(Vector2 p_val);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index b084fe1915..d3295c0f51 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -633,18 +633,23 @@ void VisualShaderEditor::_duplicate_nodes() {
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
List<int> nodes;
+ Set<int> excluded;
for (int i = 0; i < graph->get_child_count(); i++) {
- if (Object::cast_to<GraphNode>(graph->get_child(i))) {
- int id = String(graph->get_child(i)->get_name()).to_int();
+ GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
+ if (gn) {
+ int id = String(gn->get_name()).to_int();
Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
Ref<VisualShaderNodeOutput> output = node;
- if (output.is_valid()) //can't duplicate output
+ if (output.is_valid()) { // can't duplicate output
+ excluded.insert(id);
continue;
- if (node.is_valid()) {
+ }
+ if (node.is_valid() && gn->is_selected()) {
nodes.push_back(id);
}
+ excluded.insert(id);
}
}
@@ -683,15 +688,16 @@ void VisualShaderEditor::_duplicate_nodes() {
undo_redo->add_undo_method(this, "_update_graph");
undo_redo->commit_action();
- //reselect
+ // reselect duplicated nodes by excluding the other ones
for (int i = 0; i < graph->get_child_count(); i++) {
- if (Object::cast_to<GraphNode>(graph->get_child(i))) {
- int id = String(graph->get_child(i)->get_name()).to_int();
- if (nodes.find(id)) {
- Object::cast_to<GraphNode>(graph->get_child(i))->set_selected(true);
+ GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
+ if (gn) {
+ int id = String(gn->get_name()).to_int();
+ if (!excluded.has(id)) {
+ gn->set_selected(true);
} else {
- Object::cast_to<GraphNode>(graph->get_child(i))->set_selected(false);
+ gn->set_selected(false);
}
}
}
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 557aac021d..f82133e0d3 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -298,6 +298,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
custom_features->set_text(current->get_custom_features());
_update_feature_list();
_update_export_all();
+ minimum_size_changed();
updating = false;
}
@@ -1173,6 +1174,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_pck_zip->connect("file_selected", this, "_export_pck_zip_selected");
export_error = memnew(Label);
+ export_error->set_autowrap(true);
main_vb->add_child(export_error);
export_error->hide();
export_error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
diff --git a/main/main.cpp b/main/main.cpp
index 6a786e9cb5..7383294167 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1705,6 +1705,9 @@ bool Main::start() {
OS::get_singleton()->set_context(OS::CONTEXT_EDITOR);
}
#endif
+ if (!editor) {
+ OS::get_singleton()->set_context(OS::CONTEXT_ENGINE);
+ }
}
if (!project_manager && !editor) { // game
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 8bb621a863..2027d8e1eb 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -461,7 +461,47 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
int l_width = d["width"];
int l_depth = d["depth"];
- PoolVector<real_t> l_heights = d["heights"];
+
+ // TODO This code will need adjustments if real_t is set to `double`,
+ // because that precision is unnecessary for a heightmap and Bullet doesn't support it...
+
+ PoolVector<real_t> l_heights;
+ Variant l_heights_v = d["heights"];
+
+ if (l_heights_v.get_type() == Variant::POOL_REAL_ARRAY) {
+ // Ready-to-use heights can be passed
+
+ l_heights = l_heights_v;
+
+ } else if (l_heights_v.get_type() == Variant::OBJECT) {
+ // If an image is passed, we have to convert it to a format Bullet supports.
+ // this would be expensive to do with a script, so it's nice to have it here.
+
+ Ref<Image> l_image = l_heights_v;
+ ERR_FAIL_COND(l_image.is_null());
+
+ // Float is the only common format between Godot and Bullet that can be used for decent collision.
+ // (Int16 would be nice too but we still don't have it)
+ // We could convert here automatically but it's better to not be intrusive and let the caller do it if necessary.
+ ERR_FAIL_COND(l_image->get_format() != Image::FORMAT_RF);
+
+ PoolByteArray im_data = l_image->get_data();
+
+ l_heights.resize(l_image->get_width() * l_image->get_width());
+
+ PoolRealArray::Write w = l_heights.write();
+ PoolByteArray::Read r = im_data.read();
+ float *rp = (float *)r.ptr();
+ // At this point, `rp` could be used directly for Bullet, but I don't know how safe it would be.
+
+ for (int i = 0; i < l_heights.size(); ++i) {
+ w[i] = rp[i];
+ }
+
+ } else {
+ ERR_EXPLAIN("Expected PoolRealArray or float Image.");
+ ERR_FAIL();
+ }
ERR_FAIL_COND(l_width <= 0);
ERR_FAIL_COND(l_depth <= 0);
@@ -497,19 +537,8 @@ PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const {
void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
// TODO cell size must be tweaked using localScaling, which is a shared property for all Bullet shapes
- { // Copy
-
- // TODO If Godot supported 16-bit integer image format, we could share the same memory block for heightfields
- // without having to copy anything, optimizing memory and loading performance (Bullet only reads and doesn't take ownership of the data).
-
- const int heights_size = p_heights.size();
- heights.resize(heights_size);
- PoolVector<real_t>::Read p_heights_r = p_heights.read();
- PoolVector<real_t>::Write heights_w = heights.write();
- for (int i = heights_size - 1; 0 <= i; --i) {
- heights_w[i] = p_heights_r[i];
- }
- }
+ // If this array is resized outside of here, it should be preserved due to CoW
+ heights = p_heights;
width = p_width;
depth = p_depth;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 4e35014459..f4b061f494 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -197,17 +197,6 @@ void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexc
fvTexcOut[1] = t.y;
}
-void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) {
- ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
-
- int i = (iFace * 3 + iVert) * 4;
-
- surface.tansw[i++] = fvTangent[0];
- surface.tansw[i++] = fvTangent[1];
- surface.tansw[i++] = fvTangent[2];
- surface.tansw[i++] = fSign;
-}
-
void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
@@ -216,7 +205,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f
int i = iFace * 3 + iVert;
Vector3 normal = surface.normalsw[i];
Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
- Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+ Vector3 bitangent = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot
float d = bitangent.dot(normal.cross(tangent));
i *= 4;
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 0a4bb5f665..7326f3d36a 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -97,7 +97,6 @@ private:
static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert);
static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
- static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
const tbool bIsOrientationPreserving, const int iFace, const int iVert);
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 0926c1a1ab..6ea0dbcb19 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -5746,18 +5746,23 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
if (p_container.kind == DataType::BUILTIN && p_expression.kind == DataType::BUILTIN) {
bool valid = p_container.builtin_type == p_expression.builtin_type;
if (p_allow_implicit_conversion) {
- valid = valid || (p_container.builtin_type == Variant::INT && p_expression.builtin_type == Variant::REAL);
- valid = valid || (p_container.builtin_type == Variant::REAL && p_expression.builtin_type == Variant::INT);
- valid = valid || (p_container.builtin_type == Variant::STRING && p_expression.builtin_type == Variant::NODE_PATH);
- valid = valid || (p_container.builtin_type == Variant::NODE_PATH && p_expression.builtin_type == Variant::STRING);
- valid = valid || (p_container.builtin_type == Variant::BOOL && p_expression.builtin_type == Variant::REAL);
- valid = valid || (p_container.builtin_type == Variant::BOOL && p_expression.builtin_type == Variant::INT);
- valid = valid || (p_container.builtin_type == Variant::INT && p_expression.builtin_type == Variant::BOOL);
- valid = valid || (p_container.builtin_type == Variant::REAL && p_expression.builtin_type == Variant::BOOL);
+ valid = valid || Variant::can_convert_strict(p_expression.builtin_type, p_container.builtin_type);
}
return valid;
}
+ if (p_container.kind == DataType::BUILTIN && p_container.builtin_type == Variant::OBJECT) {
+ // Object built-in is a special case, it's compatible with any object and with null
+ if (p_expression.kind == DataType::BUILTIN && p_expression.builtin_type == Variant::NIL) {
+ return true;
+ }
+ if (p_expression.kind == DataType::BUILTIN) {
+ return false;
+ }
+ // If it's not a built-in, must be an object
+ return true;
+ }
+
if (p_container.kind == DataType::BUILTIN || (p_expression.kind == DataType::BUILTIN && p_expression.builtin_type != Variant::NIL)) {
// Can't mix built-ins with objects
return false;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 3c818898e6..943d95bfc9 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2474,6 +2474,18 @@ void CSharpScript::set_source_code(const String &p_code) {
#endif
}
+void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const {
+
+ if (!script_class)
+ return;
+
+ // TODO: Filter out things unsuitable for explicit calls, like constructors.
+ const Vector<GDMonoMethod *> &methods = script_class->get_all_methods();
+ for (int i = 0; i < methods.size(); ++i) {
+ p_list->push_back(methods[i]->get_method_info());
+ }
+}
+
bool CSharpScript::has_method(const StringName &p_method) const {
if (!script_class)
@@ -2482,6 +2494,25 @@ bool CSharpScript::has_method(const StringName &p_method) const {
return script_class->has_fetched_method_unknown_params(p_method);
}
+MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
+
+ if (!script_class)
+ return MethodInfo();
+
+ GDMonoClass *top = script_class;
+
+ while (top && top != native) {
+ GDMonoMethod *params = top->get_fetched_method_unknown_params(p_method);
+ if (params) {
+ return params->get_method_info();
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return MethodInfo();
+}
+
Error CSharpScript::reload(bool p_keep_state) {
bool has_instances;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 501e0d9d6d..08466bae58 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -174,9 +174,9 @@ public:
virtual Ref<Script> get_base_script() const;
virtual ScriptLanguage *get_language() const;
- /* TODO */ virtual void get_script_method_list(List<MethodInfo> *p_list) const {}
+ virtual void get_script_method_list(List<MethodInfo> *p_list) const;
bool has_method(const StringName &p_method) const;
- /* TODO */ MethodInfo get_method_info(const StringName &p_method) const { return MethodInfo(); }
+ MethodInfo get_method_info(const StringName &p_method) const;
virtual int get_member_line(const StringName &p_member) const;
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index 4e515cde28..c55f9160bd 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -151,6 +151,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
StringName name = mono_method_get_name(raw_method);
+ // get_method implicitly fetches methods and adds them to this->methods
GDMonoMethod *method = get_method(raw_method, name);
ERR_CONTINUE(!method);
@@ -449,6 +450,21 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() {
return delegates_list;
}
+const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() {
+
+ if (!method_list_fetched) {
+ void *iter = NULL;
+ MonoMethod *raw_method = NULL;
+ while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
+ method_list.push_back(memnew(GDMonoMethod(mono_method_get_name(raw_method), raw_method)));
+ }
+
+ method_list_fetched = true;
+ }
+
+ return method_list;
+}
+
GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) {
namespace_name = p_namespace;
@@ -460,6 +476,7 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name
attributes = NULL;
methods_fetched = false;
+ method_list_fetched = false;
fields_fetched = false;
properties_fetched = false;
delegates_fetched = false;
@@ -512,4 +529,8 @@ GDMonoClass::~GDMonoClass() {
methods.clear();
}
+
+ for (int i = 0; i < method_list.size(); ++i) {
+ memdelete(method_list[i]);
+ }
}
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index 477305d503..689001f494 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -79,9 +79,14 @@ class GDMonoClass {
bool attrs_fetched;
MonoCustomAttrInfo *attributes;
+ // This contains both the original method names and remapped method names from the native Godot identifiers to the C# functions.
+ // Most method-related functions refer to this and it's possible this is unintuitive for outside users; this may be a prime location for refactoring or renaming.
bool methods_fetched;
HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods;
+ bool method_list_fetched;
+ Vector<GDMonoMethod *> method_list;
+
bool fields_fetched;
Map<StringName, GDMonoField *> fields;
Vector<GDMonoField *> fields_list;
@@ -143,6 +148,8 @@ public:
const Vector<GDMonoClass *> &get_all_delegates();
+ const Vector<GDMonoMethod *> &get_all_methods();
+
~GDMonoClass();
};
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index 630bda8b4e..6ef6e97f5a 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -68,6 +68,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
param_types.push_back(param_type);
}
+
+ // clear the cache
+ method_info_fetched = false;
+ method_info = MethodInfo();
}
bool GDMonoMethod::is_static() {
@@ -246,11 +250,34 @@ void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const {
}
}
+const MethodInfo &GDMonoMethod::get_method_info() {
+
+ if (!method_info_fetched) {
+ method_info.name = name;
+ method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type), "");
+
+ Vector<StringName> names;
+ get_parameter_names(names);
+
+ for (int i = 0; i < params_count; ++i) {
+ method_info.arguments.push_back(PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i]), names[i]));
+ }
+
+ // TODO: default arguments
+
+ method_info_fetched = true;
+ }
+
+ return method_info;
+}
+
GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) {
name = p_name;
mono_method = p_method;
+ method_info_fetched = false;
+
attrs_fetched = false;
attributes = NULL;
diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h
index 444ec2a67d..6c3ae5fce0 100644
--- a/modules/mono/mono_gd/gd_mono_method.h
+++ b/modules/mono/mono_gd/gd_mono_method.h
@@ -43,6 +43,9 @@ class GDMonoMethod : public GDMonoClassMember {
ManagedType return_type;
Vector<ManagedType> param_types;
+ bool method_info_fetched;
+ MethodInfo method_info;
+
bool attrs_fetched;
MonoCustomAttrInfo *attributes;
@@ -83,6 +86,8 @@ public:
void get_parameter_names(Vector<StringName> &names) const;
void get_parameter_types(Vector<ManagedType> &types) const;
+ const MethodInfo &get_method_info();
+
GDMonoMethod(StringName p_name, MonoMethod *p_method);
~GDMonoMethod();
};
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index afaa6a9b95..080d0643a2 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -3491,6 +3491,7 @@ VisualScriptEditor::VisualScriptEditor() {
edit_menu = memnew(MenuButton);
edit_menu->set_text(TTR("Edit"));
+ edit_menu->set_switch_on_hover(true);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/delete_selected"), EDIT_DELETE_NODES);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/toggle_breakpoint"), EDIT_TOGGLE_BREAKPOINT);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("visual_script_editor/find_node_type"), EDIT_FIND_NODE_TYPE);
diff --git a/modules/webp/SCsub b/modules/webp/SCsub
index 8a4307fbe1..d215f19cef 100644
--- a/modules/webp/SCsub
+++ b/modules/webp/SCsub
@@ -42,7 +42,6 @@ if env['builtin_libwebp']:
"dsp/dec_neon.c",
"dsp/dec_sse2.c",
"dsp/dec_sse41.c",
- "dsp/enc_avx2.c",
"dsp/enc.c",
"dsp/enc_mips32.c",
"dsp/enc_mips_dsp_r2.c",
@@ -90,7 +89,6 @@ if env['builtin_libwebp']:
"enc/backward_references_enc.c",
"enc/config_enc.c",
"enc/cost_enc.c",
- "enc/delta_palettization_enc.c",
"enc/filter_enc.c",
"enc/frame_enc.c",
"enc/histogram_enc.c",
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index c9f37931b0..4608770c09 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -105,13 +105,13 @@ def configure(env):
detect_darwin_sdk_path('iphonesimulator', env)
env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
- env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
+ env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=10.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
elif (env["arch"] == "arm"):
detect_darwin_sdk_path('iphone', env)
- env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split())
+ env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=10.0 -MMD -MT dependencies'.split())
elif (env["arch"] == "arm64"):
detect_darwin_sdk_path('iphone', env)
- env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=9.0 -isysroot $IPHONESDK'.split())
+ env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=10.0 -isysroot $IPHONESDK'.split())
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
@@ -124,7 +124,7 @@ def configure(env):
if (env["arch"] == "x86" or env["arch"] == "x86_64"):
arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
- env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=9.0',
+ env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=10.0',
'-isysroot', '$IPHONESDK',
'-Xlinker',
'-objc_abi_version',
@@ -132,9 +132,9 @@ def configure(env):
'-F$IPHONESDK',
])
elif (env["arch"] == "arm"):
- env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=9.0'])
+ env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
if (env["arch"] == "arm64"):
- env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=9.0'])
+ env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
env.Append(LINKFLAGS=['-isysroot', '$IPHONESDK',
'-framework', 'AudioToolbox',
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 546c88e74a..ae2eb6288c 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -124,8 +124,8 @@ public:
Point2 im_position;
bool im_active;
- ImeCallback im_callback;
- void *im_target;
+ String im_text;
+ Point2 im_selection;
power_osx *power_manager;
@@ -245,7 +245,8 @@ public:
virtual void set_ime_active(const bool p_active);
virtual void set_ime_position(const Point2 &p_pos);
- virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp);
+ virtual Point2 get_ime_selection() const;
+ virtual String get_ime_text() const;
virtual String get_unique_id() const;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index e7b3e35381..f8dec3ec7a 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -427,11 +427,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
} else {
[markedText initWithString:aString];
}
- if (OS_OSX::singleton->im_callback) {
+ if (OS_OSX::singleton->im_active) {
imeMode = true;
- String ret;
- ret.parse_utf8([[markedText mutableString] UTF8String]);
- OS_OSX::singleton->im_callback(OS_OSX::singleton->im_target, ret, Point2(selectedRange.location, selectedRange.length));
+ OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
+ OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
+
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
}
}
@@ -443,8 +445,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)unmarkText {
imeMode = false;
[[markedText mutableString] setString:@""];
- if (OS_OSX::singleton->im_callback)
- OS_OSX::singleton->im_callback(OS_OSX::singleton->im_target, "", Point2());
+ if (OS_OSX::singleton->im_active) {
+ OS_OSX::singleton->im_text = String();
+ OS_OSX::singleton->im_selection = Point2();
+
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
+ }
}
- (NSArray *)validAttributesForMarkedText {
@@ -1136,12 +1143,14 @@ inline void sendPanEvent(double dx, double dy, int modifierFlags) {
@end
-void OS_OSX::set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp) {
- im_callback = p_callback;
- im_target = p_inp;
- if (!im_callback) {
- [window_view cancelComposition];
- }
+Point2 OS_OSX::get_ime_selection() const {
+
+ return im_selection;
+}
+
+String OS_OSX::get_ime_text() const {
+
+ return im_text;
}
String OS_OSX::get_unique_id() const {
@@ -1169,10 +1178,14 @@ String OS_OSX::get_unique_id() const {
}
void OS_OSX::set_ime_active(const bool p_active) {
+
im_active = p_active;
+ if (!im_active)
+ [window_view cancelComposition];
}
void OS_OSX::set_ime_position(const Point2 &p_pos) {
+
im_position = p_pos;
}
@@ -2637,8 +2650,6 @@ OS_OSX::OS_OSX() {
singleton = this;
im_active = false;
im_position = Point2();
- im_callback = NULL;
- im_target = NULL;
layered_window = false;
autoreleasePool = [[NSAutoreleasePool alloc] init];
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 04854e93b6..0c02e47b5e 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2853,11 +2853,19 @@ void OS_X11::set_context(int p_context) {
XClassHint *classHint = XAllocClassHint();
if (classHint) {
+ char *wm_class = (char *)"Godot";
if (p_context == CONTEXT_EDITOR)
classHint->res_name = (char *)"Godot_Editor";
if (p_context == CONTEXT_PROJECTMAN)
classHint->res_name = (char *)"Godot_ProjectList";
- classHint->res_class = (char *)"Godot";
+
+ if (p_context == CONTEXT_ENGINE) {
+ classHint->res_name = (char *)"Godot_Engine";
+ wm_class = (char *)((String)GLOBAL_GET("application/config/name")).utf8().ptrw();
+ }
+
+ classHint->res_class = wm_class;
+
XSetClassHint(x11_display, x11_window, classHint);
XFree(classHint);
}
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index d847fa2471..2534f676ca 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -42,7 +42,7 @@
#include "servers/visual_server.h"
Mutex *CanvasItemMaterial::material_mutex = NULL;
-SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials;
+SelfList<CanvasItemMaterial>::List *CanvasItemMaterial::dirty_materials = NULL;
Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map;
CanvasItemMaterial::ShaderNames *CanvasItemMaterial::shader_names = NULL;
@@ -52,6 +52,8 @@ void CanvasItemMaterial::init_shaders() {
material_mutex = Mutex::create();
#endif
+ dirty_materials = memnew(SelfList<CanvasItemMaterial>::List);
+
shader_names = memnew(ShaderNames);
shader_names->particles_anim_h_frames = "particles_anim_h_frames";
@@ -61,6 +63,9 @@ void CanvasItemMaterial::init_shaders() {
void CanvasItemMaterial::finish_shaders() {
+ memdelete(dirty_materials);
+ dirty_materials = NULL;
+
#ifndef NO_THREADS
memdelete(material_mutex);
#endif
@@ -68,7 +73,7 @@ void CanvasItemMaterial::finish_shaders() {
void CanvasItemMaterial::_update_shader() {
- dirty_materials.remove(&element);
+ dirty_materials->remove(&element);
MaterialKey mk = _compute_key();
if (mk.key == current_key.key)
@@ -157,9 +162,9 @@ void CanvasItemMaterial::flush_changes() {
if (material_mutex)
material_mutex->lock();
- while (dirty_materials.first()) {
+ while (dirty_materials->first()) {
- dirty_materials.first()->self()->_update_shader();
+ dirty_materials->first()->self()->_update_shader();
}
if (material_mutex)
@@ -172,7 +177,7 @@ void CanvasItemMaterial::_queue_shader_change() {
material_mutex->lock();
if (!element.in_list()) {
- dirty_materials.add(&element);
+ dirty_materials->add(&element);
}
if (material_mutex)
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 9fe7cb1e00..1a6016e6e1 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -109,7 +109,7 @@ private:
}
static Mutex *material_mutex;
- static SelfList<CanvasItemMaterial>::List dirty_materials;
+ static SelfList<CanvasItemMaterial>::List *dirty_materials;
SelfList<CanvasItemMaterial> element;
void _update_shader();
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 8fe65f53a9..641cb161ca 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -327,6 +327,10 @@ void TileMap::update_dirty_quadrants() {
Ref<ShaderMaterial> mat = tile_set->tile_get_material(c.id);
int z_index = tile_set->tile_get_z_index(c.id);
+ if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE) {
+ z_index += tile_set->autotile_get_z_index(c.id, Vector2(c.autotile_coord_x, c.autotile_coord_y));
+ }
+
RID canvas_item;
RID debug_canvas_item;
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 5bde224ce3..7b4c7de029 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -463,9 +463,9 @@ void Sprite3D::_draw() {
Plane tangent;
if (axis == Vector3::AXIS_X) {
- tangent = Plane(0, 0, -1, -1);
+ tangent = Plane(0, 0, -1, 1);
} else {
- tangent = Plane(1, 0, 0, -1);
+ tangent = Plane(1, 0, 0, 1);
}
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 7f9953ab43..cfc3b2f4ce 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1427,6 +1427,8 @@ StringName AnimationPlayer::find_animation(const Ref<Animation> &p_animation) co
}
void AnimationPlayer::set_autoplay(const String &p_name) {
+ if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint())
+ WARN_PRINT("Setting autoplay after the node has been added to the scene has no effect.");
autoplay = p_name;
}
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 524784df53..6adfb94695 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -401,6 +401,9 @@ void AnimationTreePlayer::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
+ ERR_EXPLAIN("AnimationTreePlayer has been deprecated. Use AnimationTree instead.");
+ WARN_DEPRECATED
+
if (!processing) {
//make sure that a previous process state was not saved
//only process if "processing" is set
@@ -409,12 +412,14 @@ void AnimationTreePlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_READY: {
+
dirty_caches = true;
if (master != NodePath()) {
_update_sources();
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
+
if (animation_process_mode == ANIMATION_PROCESS_PHYSICS)
break;
@@ -1715,6 +1720,11 @@ Error AnimationTreePlayer::node_rename(const StringName &p_node, const StringNam
return OK;
}
+String AnimationTreePlayer::get_configuration_warning() const {
+
+ return TTR("This node has been deprecated. Use AnimationTree instead.");
+}
+
void AnimationTreePlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_node", "type", "id"), &AnimationTreePlayer::add_node);
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index d2d7b1c9ec..4e4c876e87 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -343,6 +343,8 @@ public:
int node_get_input_count(const StringName &p_node) const;
StringName node_get_input_source(const StringName &p_node, int p_input) const;
+ String get_configuration_warning() const;
+
/* ANIMATION NODE */
void animation_node_set_animation(const StringName &p_node, const Ref<Animation> &p_animation);
Ref<Animation> animation_node_get_animation(const StringName &p_node) const;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index c5d3def4c1..19c6cde111 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -253,6 +253,24 @@ void ColorPicker::add_preset(const Color &p_color) {
bt_add_preset->hide();
}
+void ColorPicker::erase_preset(const Color &p_color) {
+
+ if (presets.find(p_color)) {
+ presets.erase(presets.find(p_color));
+ preset->update();
+ }
+}
+
+PoolColorArray ColorPicker::get_presets() const {
+
+ PoolColorArray arr;
+ arr.resize(presets.size());
+ for (int i = 0; i < presets.size(); i++) {
+ arr.set(i, presets[i]);
+ }
+ return arr;
+}
+
void ColorPicker::set_raw_mode(bool p_enabled) {
if (raw_mode_enabled == p_enabled)
@@ -446,7 +464,9 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
set_pick_color(presets[index]);
} else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) {
int index = bev->get_position().x / (preset->get_size().x / presets.size());
- presets.erase(presets[index]);
+ Color clicked_preset = presets[index];
+ presets.erase(clicked_preset);
+ emit_signal("preset_removed", clicked_preset);
preset->update();
bt_add_preset->show();
}
@@ -501,6 +521,7 @@ void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
void ColorPicker::_add_preset_pressed() {
add_preset(color);
+ emit_signal("preset_added", color);
}
void ColorPicker::_screen_pick_pressed() {
@@ -553,6 +574,8 @@ void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha);
ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset);
+ ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset);
+ ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets);
ClassDB::bind_method(D_METHOD("_value_changed"), &ColorPicker::_value_changed);
ClassDB::bind_method(D_METHOD("_html_entered"), &ColorPicker::_html_entered);
ClassDB::bind_method(D_METHOD("_text_type_toggled"), &ColorPicker::_text_type_toggled);
@@ -575,6 +598,8 @@ void ColorPicker::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
+ ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color")));
+ ADD_SIGNAL(MethodInfo("preset_removed", PropertyInfo(Variant::COLOR, "color")));
}
ColorPicker::ColorPicker() :
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 0166da7118..e32c830434 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -105,6 +105,9 @@ public:
Color get_pick_color() const;
void add_preset(const Color &p_color);
+ void erase_preset(const Color &p_color);
+ PoolColorArray get_presets() const;
+
void set_raw_mode(bool p_enabled);
bool is_raw_mode() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 79e1d35b94..a580d89439 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -451,6 +451,11 @@ void Control::_update_canvas_item_transform() {
Transform2D xform = _get_internal_transform();
xform[2] += get_position();
+ // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot()
+ if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) {
+ xform[2] = xform[2].round();
+ }
+
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
}
@@ -1336,11 +1341,6 @@ void Control::_size_changed() {
new_size_cache.height = minimum_size.height;
}
- // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot()
- if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) {
- new_size_cache = new_size_cache.round();
- new_pos_cache = new_pos_cache.round();
- }
bool pos_changed = new_pos_cache != data.pos_cache;
bool size_changed = new_size_cache != data.size_cache;
@@ -1740,10 +1740,10 @@ Rect2 Control::_compute_child_rect(const float p_anchors[4], const float p_margi
void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
- r_margins[0] = Math::floor(p_rect.position.x - (p_anchors[0] * parent_rect_size.x));
- r_margins[1] = Math::floor(p_rect.position.y - (p_anchors[1] * parent_rect_size.y));
- r_margins[2] = Math::floor(p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x));
- r_margins[3] = Math::floor(p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y));
+ r_margins[0] = p_rect.position.x - (p_anchors[0] * parent_rect_size.x);
+ r_margins[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y);
+ r_margins[2] = p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
+ r_margins[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
}
void Control::set_position(const Size2 &p_point) {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 299c304c5f..42d7f1b080 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -831,7 +831,6 @@ void LineEdit::_notification(int p_what) {
OS::get_singleton()->set_ime_active(true);
OS::get_singleton()->set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height));
- OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -843,7 +842,6 @@ void LineEdit::_notification(int p_what) {
OS::get_singleton()->set_ime_active(true);
Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
- OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->show_virtual_keyboard(text, get_global_rect());
@@ -852,7 +850,6 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
OS::get_singleton()->set_ime_position(Point2());
- OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL);
OS::get_singleton()->set_ime_active(false);
ime_text = "";
ime_selection = Point2();
@@ -861,6 +858,12 @@ void LineEdit::_notification(int p_what) {
OS::get_singleton()->hide_virtual_keyboard();
} break;
+ case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
+
+ ime_text = OS::get_singleton()->get_ime_text();
+ ime_selection = OS::get_singleton()->get_ime_selection();
+ update();
+ } break;
}
}
@@ -1461,13 +1464,6 @@ void LineEdit::set_right_icon(const Ref<Texture> &p_icon) {
update();
}
-void LineEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) {
- LineEdit *self = (LineEdit *)p_self;
- self->ime_text = p_text;
- self->ime_selection = p_selection;
- self->update();
-}
-
void LineEdit::_text_changed() {
if (expand_to_text_length)
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 5294d99da0..ddcdeda8c0 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -122,7 +122,6 @@ private:
Timer *caret_blink_timer;
- static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
void _text_changed();
void _emit_text_change();
bool expand_to_text_length;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 95ec618c3b..b4cb297900 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -71,13 +71,24 @@ PopupMenu *MenuButton::get_popup() const {
return popup;
}
+void MenuButton::_set_items(const Array &p_items) {
+
+ popup->set("items", p_items);
+}
+
Array MenuButton::_get_items() const {
return popup->get("items");
}
-void MenuButton::_set_items(const Array &p_items) {
- popup->set("items", p_items);
+void MenuButton::set_switch_on_hover(bool p_enabled) {
+
+ switch_on_hover = p_enabled;
+}
+
+bool MenuButton::is_switch_on_hover() {
+
+ return switch_on_hover;
}
void MenuButton::_bind_methods() {
@@ -86,9 +97,12 @@ void MenuButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items);
ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items);
+ ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover);
+ ClassDB::bind_method(D_METHOD("is_switch_on_hover"), &MenuButton::is_switch_on_hover);
ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &MenuButton::set_disable_shortcuts);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover");
ADD_SIGNAL(MethodInfo("about_to_show"));
}
@@ -100,6 +114,7 @@ void MenuButton::set_disable_shortcuts(bool p_disabled) {
MenuButton::MenuButton() {
+ switch_on_hover = false;
set_flat(true);
set_disable_shortcuts(false);
set_enabled_focus_mode(FOCUS_NONE);
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 0636accfee..abc49f4988 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -41,6 +41,7 @@ class MenuButton : public Button {
GDCLASS(MenuButton, Button);
bool clicked;
+ bool switch_on_hover;
bool disable_shortcuts;
PopupMenu *popup;
@@ -57,6 +58,8 @@ public:
virtual void pressed();
PopupMenu *get_popup() const;
+ void set_switch_on_hover(bool p_enabled);
+ bool is_switch_on_hover();
void set_disable_shortcuts(bool p_disabled);
MenuButton();
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index ace22dddff..4f43bb0581 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -110,6 +110,9 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
range_click_timer->start();
line_edit->grab_focus();
+
+ drag.allowed = true;
+ drag.capture_pos = mb->get_position();
} break;
case BUTTON_RIGHT: {
@@ -133,14 +136,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == 1) {
-
- //set_default_cursor_shape(CURSOR_VSIZE);
- Vector2 cpos = Vector2(mb->get_position().x, mb->get_position().y);
- drag.mouse_pos = cpos;
- }
-
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == 1) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
//set_default_cursor_shape(CURSOR_ARROW);
range_click_timer->stop();
@@ -150,32 +146,24 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
warp_mouse(drag.capture_pos);
}
+ drag.allowed = false;
}
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & 1) {
-
- Vector2 cpos = mm->get_position();
+ if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
if (drag.enabled) {
- float diff_y = drag.mouse_pos.y - cpos.y;
- diff_y = Math::pow(ABS(diff_y), 1.8f) * SGN(diff_y);
- diff_y *= 0.1;
-
- drag.mouse_pos = cpos;
- drag.base_val = CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max());
-
- set_value(drag.base_val);
-
- } else if (drag.mouse_pos.distance_to(cpos) > 2) {
+ drag.diff_y += mm->get_relative().y;
+ float diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8f) * SGN(drag.diff_y);
+ set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()));
+ } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
drag.enabled = true;
drag.base_val = get_value();
- drag.mouse_pos = cpos;
- drag.capture_pos = cpos;
+ drag.diff_y = 0;
}
}
}
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index f1ee26d9f3..6425af7158 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -54,10 +54,10 @@ class SpinBox : public Range {
struct Drag {
float base_val;
+ bool allowed;
bool enabled;
- Vector2 from;
- Vector2 mouse_pos;
Vector2 capture_pos;
+ float diff_y;
} drag;
void _line_edit_focus_exit();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index c339cf6374..1504ad7bf1 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -39,6 +39,7 @@
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
+#include "editor_settings.h"
#endif
#define TAB_PIXELS
@@ -918,6 +919,26 @@ void TextEdit::_notification(int p_what) {
}
}
+ int indent_level = get_indent_level(i);
+ if (draw_indent_guides && indent_level > 0) {
+#ifdef TOOLS_ENABLED
+ int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size");
+ float line_width = Math::round(EDSCALE);
+#else
+ int indent_size = 4;
+ float line_width = 1.0;
+#endif
+ int guides = 1 + (indent_level - 1) / indent_size;
+
+ for (int guide = 0; guide < guides; guide++) {
+ draw_line(
+ Point2(guide * indent_size * cache.font->get_char_size(' ').width + char_margin, ofs_y),
+ Point2(guide * indent_size * cache.font->get_char_size(' ').width + char_margin, ofs_y + get_row_height()),
+ cache.indent_guide_color,
+ line_width);
+ }
+ }
+
if (line_wrap_index == 0) {
// only do these if we are on the first wrapped part of a line
@@ -1179,9 +1200,14 @@ void TextEdit::_notification(int p_what) {
draw_rect(Rect2(char_ofs + char_margin + ofs_x, yofs + ascent + 2, w, line_width), in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
- } else if (draw_tabs && str[j] == '\t') {
+ } else if (draw_tabs && (j > get_indent_level(i) || !draw_indent_guides) && str[j] == '\t') {
+ // If indent guides are enabled, only draw trailing or alignment tabs
+ // Otherwise, draw all tabs (including those used for indentation)
int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2;
- cache.tab_icon->draw(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color);
+ cache.tab_icon->draw(
+ ci,
+ Point2(char_ofs + char_margin + ofs_x, ofs_y + yofs),
+ in_selection && override_selected_font_color ? cache.font_selected_color : color);
}
char_ofs += char_w;
@@ -1412,7 +1438,6 @@ void TextEdit::_notification(int p_what) {
if (has_focus()) {
OS::get_singleton()->set_ime_active(true);
OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
- OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
}
} break;
@@ -1425,7 +1450,6 @@ void TextEdit::_notification(int p_what) {
OS::get_singleton()->set_ime_active(true);
Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height();
OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
- OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
@@ -1433,7 +1457,6 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
OS::get_singleton()->set_ime_position(Point2());
- OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL);
OS::get_singleton()->set_ime_active(false);
ime_text = "";
ime_selection = Point2();
@@ -1441,14 +1464,13 @@ void TextEdit::_notification(int p_what) {
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->hide_virtual_keyboard();
} break;
- }
-}
+ case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
-void TextEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) {
- TextEdit *self = (TextEdit *)p_self;
- self->ime_text = p_text;
- self->ime_selection = p_selection;
- self->update();
+ ime_text = OS::get_singleton()->get_ime_text();
+ ime_selection = OS::get_singleton()->get_ime_selection();
+ update();
+ } break;
+ }
}
void TextEdit::_consume_pair_symbol(CharType ch) {
@@ -4333,6 +4355,7 @@ void TextEdit::_update_caches() {
cache.font = get_font("font");
cache.caret_color = get_color("caret_color");
cache.caret_background_color = get_color("caret_background_color");
+ cache.indent_guide_color = get_color("indent_guide_color");
cache.line_number_color = get_color("line_number_color");
cache.safe_line_number_color = get_color("safe_line_number_color");
cache.font_color = get_color("font_color");
@@ -5446,6 +5469,16 @@ int TextEdit::get_indent_size() {
return indent_size;
}
+void TextEdit::set_draw_indent_guides(bool p_draw) {
+
+ draw_indent_guides = p_draw;
+}
+
+bool TextEdit::is_drawing_indent_guides() const {
+
+ return draw_indent_guides;
+}
+
void TextEdit::set_draw_tabs(bool p_draw) {
draw_tabs = p_draw;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index b1a0b60442..7ecb2be6e7 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -167,6 +167,7 @@ private:
Color completion_font_color;
Color caret_color;
Color caret_background_color;
+ Color indent_guide_color;
Color line_number_color;
Color safe_line_number_color;
Color font_color;
@@ -276,6 +277,7 @@ private:
int wrap_right_offset;
bool setting_row;
+ bool draw_indent_guides;
bool draw_tabs;
bool override_selected_font_color;
bool cursor_changed_dirty;
@@ -380,8 +382,6 @@ private:
void _scroll_lines_up();
void _scroll_lines_down();
- static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
-
//void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask);
Size2 get_minimum_size() const;
@@ -590,6 +590,8 @@ public:
bool is_indent_using_spaces() const;
void set_indent_size(const int p_size);
int get_indent_size();
+ void set_draw_indent_guides(bool p_draw);
+ bool is_drawing_indent_guides() const;
void set_draw_tabs(bool p_draw);
bool is_drawing_tabs() const;
void set_override_selected_font_color(bool p_override_selected_font_color);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 3f664bab10..be4878588e 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -639,6 +639,7 @@ void SceneTree::_notification(int p_notification) {
}
} break;
case NOTIFICATION_OS_MEMORY_WARNING:
+ case NOTIFICATION_OS_IME_UPDATE:
case NOTIFICATION_WM_MOUSE_ENTER:
case NOTIFICATION_WM_MOUSE_EXIT:
case NOTIFICATION_WM_FOCUS_IN:
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 3e27c86c67..5b1c2d8020 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1955,10 +1955,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
// If the mouse is over a menu button, this menu will open automatically
// if there is already a pop-up menu open at the same hierarchical level.
- if (popup_menu_parent && menu_button &&
- popup_menu_parent->get_icon().is_null() &&
- menu_button->get_icon().is_null() &&
- (popup_menu->get_parent()->get_parent()->is_a_parent_of(menu_button) ||
+ if (popup_menu_parent && menu_button && popup_menu_parent->is_switch_on_hover() &&
+ !menu_button->is_disabled() && menu_button->is_switch_on_hover() &&
+ (popup_menu_parent->get_parent()->is_a_parent_of(menu_button) ||
menu_button->get_parent()->is_a_parent_of(popup_menu))) {
popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE);
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 9ee85b64b6..35132c1195 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -249,6 +249,10 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in
int32_t todo = p_frames;
+ if (base->loop_mode == AudioStreamSample::LOOP_BACKWARD) {
+ sign = -1;
+ }
+
float base_rate = AudioServer::get_singleton()->get_mix_rate();
float srate = base->mix_rate;
srate *= p_rate_scale;
@@ -621,7 +625,7 @@ void AudioStreamSample::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong"), "set_loop_mode", "get_loop_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong,Backward"), "set_loop_mode", "get_loop_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_end"), "set_loop_end", "get_loop_end");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate"), "set_mix_rate", "get_mix_rate");
@@ -634,6 +638,7 @@ void AudioStreamSample::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_DISABLED);
BIND_ENUM_CONSTANT(LOOP_FORWARD);
BIND_ENUM_CONSTANT(LOOP_PING_PONG);
+ BIND_ENUM_CONSTANT(LOOP_BACKWARD);
}
AudioStreamSample::AudioStreamSample() {
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index a27acc92b7..2c39e0a11e 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -94,7 +94,8 @@ public:
enum LoopMode {
LOOP_DISABLED,
LOOP_FORWARD,
- LOOP_PING_PONG
+ LOOP_PING_PONG,
+ LOOP_BACKWARD
};
private:
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index fff136cdc3..b0c1dcde9a 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -307,10 +307,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("hseparation", "MenuButton", 3 * scale);
- // ButtonGroup
-
- theme->set_stylebox("panel", "ButtonGroup", memnew(StyleBoxEmpty));
-
// CheckBox
Ref<StyleBox> cbx_empty = memnew(StyleBoxEmpty);
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 5327ed318f..f6dc60900f 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -258,7 +258,7 @@ ShaderMaterial::~ShaderMaterial() {
/////////////////////////////////
Mutex *SpatialMaterial::material_mutex = NULL;
-SelfList<SpatialMaterial>::List SpatialMaterial::dirty_materials;
+SelfList<SpatialMaterial>::List *SpatialMaterial::dirty_materials = NULL;
Map<SpatialMaterial::MaterialKey, SpatialMaterial::ShaderData> SpatialMaterial::shader_map;
SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = NULL;
@@ -268,6 +268,8 @@ void SpatialMaterial::init_shaders() {
material_mutex = Mutex::create();
#endif
+ dirty_materials = memnew(SelfList<SpatialMaterial>::List);
+
shader_names = memnew(ShaderNames);
shader_names->albedo = "albedo";
@@ -348,12 +350,15 @@ void SpatialMaterial::finish_shaders() {
memdelete(material_mutex);
#endif
+ memdelete(dirty_materials);
+ dirty_materials = NULL;
+
memdelete(shader_names);
}
void SpatialMaterial::_update_shader() {
- dirty_materials.remove(&element);
+ dirty_materials->remove(&element);
MaterialKey mk = _compute_key();
if (mk.key == current_key.key)
@@ -699,7 +704,7 @@ void SpatialMaterial::_update_shader() {
if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
code += "\t{\n";
- code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace
+ code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,-BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-)
if (deep_parallax) {
code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
@@ -1002,9 +1007,9 @@ void SpatialMaterial::flush_changes() {
if (material_mutex)
material_mutex->lock();
- while (dirty_materials.first()) {
+ while (dirty_materials->first()) {
- dirty_materials.first()->self()->_update_shader();
+ dirty_materials->first()->self()->_update_shader();
}
if (material_mutex)
@@ -1017,7 +1022,7 @@ void SpatialMaterial::_queue_shader_change() {
material_mutex->lock();
if (!element.in_list()) {
- dirty_materials.add(&element);
+ dirty_materials->add(&element);
}
if (material_mutex)
@@ -1315,7 +1320,7 @@ void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) {
return;
flags[p_flag] = p_enabled;
- if (p_flag == FLAG_USE_ALPHA_SCISSOR) {
+ if (p_flag == FLAG_USE_ALPHA_SCISSOR || p_flag == FLAG_UNSHADED) {
_change_notify();
}
_queue_shader_change();
@@ -1421,6 +1426,48 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
if ((property.name == "depth_min_layers" || property.name == "depth_max_layers") && !deep_parallax) {
property.usage = 0;
}
+
+ if (flags[FLAG_UNSHADED]) {
+ if (property.name.begins_with("anisotropy")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("ao")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("clearcoat")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("emission")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("metallic")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("normal")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("rim")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("roughness")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("subsurf_scatter")) {
+ property.usage = 0;
+ }
+
+ if (property.name.begins_with("transmission")) {
+ property.usage = 0;
+ }
+ }
}
void SpatialMaterial::set_line_width(float p_line_width) {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 54fceaddc1..921f3baeaa 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -360,7 +360,7 @@ private:
};
static Mutex *material_mutex;
- static SelfList<SpatialMaterial>::List dirty_materials;
+ static SelfList<SpatialMaterial>::List *dirty_materials;
static ShaderNames *shader_names;
SelfList<SpatialMaterial> element;
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index dae01e8d96..92c185712a 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -31,7 +31,7 @@
#include "particles_material.h"
Mutex *ParticlesMaterial::material_mutex = NULL;
-SelfList<ParticlesMaterial>::List ParticlesMaterial::dirty_materials;
+SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = NULL;
Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map;
ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL;
@@ -41,6 +41,8 @@ void ParticlesMaterial::init_shaders() {
material_mutex = Mutex::create();
#endif
+ dirty_materials = memnew(SelfList<ParticlesMaterial>::List);
+
shader_names = memnew(ShaderNames);
shader_names->spread = "spread";
@@ -106,12 +108,15 @@ void ParticlesMaterial::finish_shaders() {
memdelete(material_mutex);
#endif
+ memdelete(dirty_materials);
+ dirty_materials = NULL;
+
memdelete(shader_names);
}
void ParticlesMaterial::_update_shader() {
- dirty_materials.remove(&element);
+ dirty_materials->remove(&element);
MaterialKey mk = _compute_key();
if (mk.key == current_key.key)
@@ -584,9 +589,9 @@ void ParticlesMaterial::flush_changes() {
if (material_mutex)
material_mutex->lock();
- while (dirty_materials.first()) {
+ while (dirty_materials->first()) {
- dirty_materials.first()->self()->_update_shader();
+ dirty_materials->first()->self()->_update_shader();
}
if (material_mutex)
@@ -599,7 +604,7 @@ void ParticlesMaterial::_queue_shader_change() {
material_mutex->lock();
if (!element.in_list()) {
- dirty_materials.add(&element);
+ dirty_materials->add(&element);
}
if (material_mutex)
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index 06ebb3c4dc..20b505532e 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -126,7 +126,7 @@ private:
}
static Mutex *material_mutex;
- static SelfList<ParticlesMaterial>::List dirty_materials;
+ static SelfList<ParticlesMaterial>::List *dirty_materials;
struct ShaderNames {
StringName spread;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index dafdddd990..6dedb74fad 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -306,7 +306,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(-y, x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, 1.0)
uvs.push_back(Vector2(u, v * onethird));
point++;
@@ -345,7 +345,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y * radius, z);
points.push_back(p);
normals.push_back(Vector3(x, y, 0.0));
- ADD_TANGENT(-y, x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, 1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
point++;
@@ -385,7 +385,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(-y, x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, 1.0)
uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
point++;
@@ -514,14 +514,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// front
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(u, v));
point++;
// back
points.push_back(Vector3(-x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, v));
point++;
@@ -568,14 +568,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// right
points.push_back(Vector3(-start_pos.x, -y, -z));
normals.push_back(Vector3(1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
// left
points.push_back(Vector3(start_pos.x, -y, z));
normals.push_back(Vector3(-1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -622,14 +622,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// top
points.push_back(Vector3(-x, -start_pos.y, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(onethird + u, 0.5 + v));
point++;
// bottom
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -773,7 +773,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y, z * radius);
points.push_back(p);
normals.push_back(Vector3(x, 0.0, z));
- ADD_TANGENT(z, 0.0, -x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v * 0.5));
point++;
@@ -799,7 +799,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.25, 0.75));
point++;
@@ -816,7 +816,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * top_radius, y, z * top_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -835,7 +835,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.75, 0.75));
point++;
@@ -852,7 +852,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -982,7 +982,7 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(Vector3(-x, 0.0, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
point++;
@@ -1108,14 +1108,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* front */
points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(offset_front + u, v));
point++;
/* back */
points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + offset_back + u, v));
point++;
@@ -1187,14 +1187,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* right */
points.push_back(Vector3(right, -y, -z));
normals.push_back(normal_right);
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
/* left */
points.push_back(Vector3(left, -y, z));
normals.push_back(normal_left);
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -1241,7 +1241,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* bottom */
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -1382,7 +1382,7 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
tangents.set(i * 4 + 0, 1.0);
tangents.set(i * 4 + 1, 0.0);
tangents.set(i * 4 + 2, 0.0);
- tangents.set(i * 4 + 3, -1.0);
+ tangents.set(i * 4 + 3, 1.0);
static const Vector2 quad_uv[4] = {
Vector2(0, 1),
@@ -1468,7 +1468,7 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(p);
normals.push_back(p.normalized());
};
- ADD_TANGENT(z, 0.0, -x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, 1.0)
uvs.push_back(Vector2(u, v));
point++;
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 9907636e91..842252d5d9 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -853,7 +853,7 @@ void SurfaceTool::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, cons
if (vtx != NULL) {
vtx->tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
- vtx->binormal = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+ vtx->binormal = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot
}
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index f852ecd7eb..c2c2c0ff32 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -129,6 +129,22 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
}
p.pop_front();
}
+ } else if (what == "z_index_map") {
+ tile_map[id].autotile_data.z_index_map.clear();
+ Array p = p_value;
+ Vector3 val;
+ Vector2 v;
+ int z_index;
+ while (p.size() > 0) {
+ val = p[0];
+ if (val.z != 0) {
+ v.x = val.x;
+ v.y = val.y;
+ z_index = (int)val.z;
+ tile_map[id].autotile_data.z_index_map[v] = z_index;
+ }
+ p.pop_front();
+ }
}
} else if (what == "shape")
tile_set_shape(id, 0, p_value);
@@ -228,6 +244,19 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
}
}
r_ret = p;
+ } else if (what == "z_index_map") {
+ Array p;
+ Vector3 v;
+ for (Map<Vector2, int>::Element *E = tile_map[id].autotile_data.z_index_map.front(); E; E = E->next()) {
+ if (E->value() != 0) {
+ //Don't save default value
+ v.x = E->key().x;
+ v.y = E->key().y;
+ v.z = E->value();
+ p.push_back(v);
+ }
+ }
+ r_ret = p;
}
} else if (what == "shape")
r_ret = tile_get_shape(id, 0);
@@ -278,6 +307,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/occluder_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/navpoly_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
} else if (tile_get_tile_mode(id) == ATLAS_TILE) {
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
@@ -476,6 +506,23 @@ int TileSet::autotile_get_subtile_priority(int p_id, const Vector2 &p_coord) {
return 1;
}
+void TileSet::autotile_set_z_index(int p_id, const Vector2 &p_coord, int p_z_index) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].autotile_data.z_index_map[p_coord] = p_z_index;
+ emit_changed();
+}
+
+int TileSet::autotile_get_z_index(int p_id, const Vector2 &p_coord) {
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id), 1);
+ if (tile_map[p_id].autotile_data.z_index_map.has(p_coord)) {
+ return tile_map[p_id].autotile_data.z_index_map[p_coord];
+ }
+ //When not custom z index set return the default value
+ return 0;
+}
+
const Map<Vector2, int> &TileSet::autotile_get_priority_map(int p_id) const {
static Map<Vector2, int> dummy;
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 1802bf12b6..2ab771b1b0 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -87,6 +87,7 @@ public:
Map<Vector2, Ref<OccluderPolygon2D> > occluder_map;
Map<Vector2, Ref<NavigationPolygon> > navpoly_map;
Map<Vector2, int> priority_map;
+ Map<Vector2, int> z_index_map;
// Default size to prevent invalid value
explicit AutotileData() :
@@ -172,6 +173,9 @@ public:
int autotile_get_subtile_priority(int p_id, const Vector2 &p_coord);
const Map<Vector2, int> &autotile_get_priority_map(int p_id) const;
+ void autotile_set_z_index(int p_id, const Vector2 &p_coord, int p_z_index);
+ int autotile_get_z_index(int p_id, const Vector2 &p_coord);
+
void autotile_set_bitmask(int p_id, Vector2 p_coord, uint16_t p_flag);
uint16_t autotile_get_bitmask(int p_id, Vector2 p_coord);
const Map<Vector2, uint16_t> &autotile_get_bitmask_map(int p_id);
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 6fd996c3d3..530976f084 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -737,6 +737,12 @@ float AudioServer::get_bus_volume_db(int p_bus) const {
return buses[p_bus]->volume_db;
}
+int AudioServer::get_bus_channels(int p_bus) const {
+
+ ERR_FAIL_INDEX_V(p_bus, buses.size(), 0);
+ return buses[p_bus]->channels.size();
+}
+
void AudioServer::set_bus_send(int p_bus, const StringName &p_send) {
ERR_FAIL_INDEX(p_bus, buses.size());
@@ -1267,6 +1273,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_name", "bus_idx"), &AudioServer::get_bus_name);
ClassDB::bind_method(D_METHOD("get_bus_index", "bus_name"), &AudioServer::get_bus_index);
+ ClassDB::bind_method(D_METHOD("get_bus_channels", "bus_idx"), &AudioServer::get_bus_channels);
+
ClassDB::bind_method(D_METHOD("set_bus_volume_db", "bus_idx", "volume_db"), &AudioServer::set_bus_volume_db);
ClassDB::bind_method(D_METHOD("get_bus_volume_db", "bus_idx"), &AudioServer::get_bus_volume_db);
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 52fa84e3e6..642af9b252 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -299,6 +299,8 @@ public:
String get_bus_name(int p_bus) const;
int get_bus_index(const StringName &p_bus_name) const;
+ int get_bus_channels(int p_bus) const;
+
void set_bus_volume_db(int p_bus, float p_volume_db);
float get_bus_volume_db(int p_bus) const;
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index baafe2f8d0..b5e03b4826 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -86,6 +86,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
@@ -118,6 +119,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
@@ -126,6 +128,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
@@ -229,7 +232,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 55b693af96..e63e1fc109 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -233,7 +233,7 @@ Godot-made change marked with `// -- GODOT --` comments.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 1.0.0
+- Version: 1.0.1
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -503,7 +503,7 @@ changes are marked with `// -- GODOT --` comments.
## tinyexr
- Upstream: https://github.com/syoyo/tinyexr
-- Version: git (2d5375f, 2018)
+- Version: git (5ae30aa, 2018)
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/libwebp/src/dec/alphai_dec.h b/thirdparty/libwebp/src/dec/alphai_dec.h
index e0fa281a55..a64104abeb 100644
--- a/thirdparty/libwebp/src/dec/alphai_dec.h
+++ b/thirdparty/libwebp/src/dec/alphai_dec.h
@@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_ALPHAI_DEC_H_ */
+#endif // WEBP_DEC_ALPHAI_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/buffer_dec.c b/thirdparty/libwebp/src/dec/buffer_dec.c
index 75eb3c40b4..3cd94eb4d9 100644
--- a/thirdparty/libwebp/src/dec/buffer_dec.c
+++ b/thirdparty/libwebp/src/dec/buffer_dec.c
@@ -74,7 +74,8 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
} else { // RGB checks
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
const int stride = abs(buf->stride);
- const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
+ const uint64_t size =
+ MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
ok &= (size <= buf->size);
ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL);
diff --git a/thirdparty/libwebp/src/dec/common_dec.h b/thirdparty/libwebp/src/dec/common_dec.h
index 9995f1a51a..b158550a80 100644
--- a/thirdparty/libwebp/src/dec/common_dec.h
+++ b/thirdparty/libwebp/src/dec/common_dec.h
@@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11
};
-#endif // WEBP_DEC_COMMON_DEC_H_
+#endif // WEBP_DEC_COMMON_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index a9d5430d00..bda9e1a6f6 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
VP8QuantMatrix* const dqm = &dec->dqm_[s];
if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
- // TODO(skal): should we specially dither more for uv_quant_ < 0?
const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
}
@@ -669,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
(void)height;
assert(headers == NULL || !headers->is_lossless);
#if defined(WEBP_USE_THREAD)
- if (width < MIN_WIDTH_FOR_THREADS) return 0;
- // TODO(skal): tune the heuristic further
-#if 0
- if (height < 2 * width) return 2;
+ if (width >= MIN_WIDTH_FOR_THREADS) return 2;
#endif
- return 2;
-#else // !WEBP_USE_THREAD
return 0;
-#endif
}
#undef MT_CACHE_LINES
diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c
index a371ed7500..9bc9166808 100644
--- a/thirdparty/libwebp/src/dec/idec_dec.c
+++ b/thirdparty/libwebp/src/dec/idec_dec.c
@@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (NeedCompressedAlpha(idec)) {
ALPHDecoder* const alph_dec = dec->alph_dec_;
dec->alpha_data_ += offset;
- if (alph_dec != NULL) {
+ if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) {
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
- assert(alph_vp8l_dec != NULL);
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
dec->alpha_data_ + ALPHA_HEADER_LEN,
@@ -283,10 +282,8 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
if (idec->state_ == STATE_VP8_DATA) {
- VP8Io* const io = &idec->io_;
- if (io->teardown != NULL) {
- io->teardown(io);
- }
+ // Synchronize the thread, clean-up and check for errors.
+ VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
}
idec->state_ = STATE_ERROR;
return error;
@@ -451,7 +448,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
VP8Io* const io = &idec->io_;
- assert(dec->ready_);
+ // Make sure partition #0 has been read before, to set dec to ready_.
+ if (!dec->ready_) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
if (idec->last_mb_y_ != dec->mb_y_) {
if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
@@ -473,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
+ // Synchronize the threads.
+ if (dec->mt_method_ > 0) {
+ if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ }
RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED;
}
@@ -491,6 +497,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
}
// Synchronize the thread and check for errors.
if (!VP8ExitCritical(dec, io)) {
+ idec->state_ = STATE_ERROR; // prevent re-entry in IDecError
return IDecError(idec, VP8_STATUS_USER_ABORT);
}
dec->ready_ = 0;
@@ -571,6 +578,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
status = DecodePartition0(idec);
}
if (idec->state_ == STATE_VP8_DATA) {
+ const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ if (dec == NULL) {
+ return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
+ }
status = DecodeRemaining(idec);
}
if (idec->state_ == STATE_VP8L_HEADER) {
diff --git a/thirdparty/libwebp/src/dec/vp8_dec.h b/thirdparty/libwebp/src/dec/vp8_dec.h
index ca85b340cf..a05405df72 100644
--- a/thirdparty/libwebp/src/dec/vp8_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8_dec.h
@@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo(
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8_DEC_H_ */
+#endif // WEBP_DEC_VP8_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index c929933e1c..e5e89df57d 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 0
+#define DEC_REV_VERSION 1
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
@@ -316,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8I_DEC_H_ */
+#endif // WEBP_DEC_VP8I_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index 0570f53a77..333bb3e80d 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -362,12 +362,19 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
+ // When reading htrees, some might be unused, as the format allows it.
+ // We will still read them but put them in this htree_group_bogus.
+ HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
+ HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
int num_htree_groups = 1;
+ int num_htree_groups_max = 1;
int max_alphabet_size = 0;
int* code_lengths = NULL;
const int table_size = kTableSize[color_cache_bits];
+ int* mapping = NULL;
+ int ok = 0;
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
@@ -384,9 +391,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
// The huffman data is stored in red and green bytes.
const int group = (huffman_image[i] >> 8) & 0xffff;
huffman_image[i] = group;
- if (group >= num_htree_groups) {
- num_htree_groups = group + 1;
+ if (group >= num_htree_groups_max) {
+ num_htree_groups_max = group + 1;
+ }
+ }
+ // Check the validity of num_htree_groups_max. If it seems too big, use a
+ // smaller value for later. This will prevent big memory allocations to end
+ // up with a bad bitstream anyway.
+ // The value of 1000 is totally arbitrary. We know that num_htree_groups_max
+ // is smaller than (1 << 16) and should be smaller than the number of pixels
+ // (though the format allows it to be bigger).
+ if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
+ // Create a mapping from the used indices to the minimal set of used
+ // values [0, num_htree_groups)
+ mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
+ if (mapping == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
+ // -1 means a value is unmapped, and therefore unused in the Huffman
+ // image.
+ memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
+ for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
+ // Get the current mapping for the group and remap the Huffman image.
+ int* const mapped_group = &mapping[huffman_image[i]];
+ if (*mapped_group == -1) *mapped_group = num_htree_groups++;
+ huffman_image[i] = *mapped_group;
+ }
+ huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
+ table_size, sizeof(*huffman_tables_bogus));
+ if (huffman_tables_bogus == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
}
+ } else {
+ num_htree_groups = num_htree_groups_max;
}
}
@@ -403,11 +442,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
}
+ code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
+ sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
- code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
- sizeof(*code_lengths));
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
@@ -415,28 +454,35 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
next = huffman_tables;
- for (i = 0; i < num_htree_groups; ++i) {
- HTreeGroup* const htree_group = &htree_groups[i];
+ for (i = 0; i < num_htree_groups_max; ++i) {
+ // If the index "i" is unused in the Huffman image, read the coefficients
+ // but store them to a bogus htree_group.
+ const int is_bogus = (mapping != NULL && mapping[i] == -1);
+ HTreeGroup* const htree_group =
+ is_bogus ? &htree_group_bogus :
+ &htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
+ HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
- htrees[j] = next;
+ htrees[j] = huffman_tables_i;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
+ size =
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (next->bits == 0);
+ is_trivial_literal = (huffman_tables_i->bits == 0);
}
- total_size += next->bits;
- next += size;
+ total_size += huffman_tables_i->bits;
+ huffman_tables_i += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@@ -448,38 +494,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
max_bits += local_max_bits;
}
}
+ if (!is_bogus) next = huffman_tables_i;
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
- htree_group->literal_arb =
- ((uint32_t)alpha << 24) | (red << 16) | blue;
+ htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
- htree_group->use_packed_table = !htree_group->is_trivial_code &&
- (max_bits < HUFFMAN_PACKED_BITS);
+ htree_group->use_packed_table =
+ !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
- WebPSafeFree(code_lengths);
+ ok = 1;
- // All OK. Finalize pointers and return.
+ // All OK. Finalize pointers.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
- return 1;
Error:
WebPSafeFree(code_lengths);
- WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(htree_groups);
- return 0;
+ WebPSafeFree(huffman_tables_bogus);
+ WebPSafeFree(mapping);
+ if (!ok) {
+ WebPSafeFree(huffman_image);
+ WebPSafeFree(huffman_tables);
+ VP8LHtreeGroupsFree(htree_groups);
+ }
+ return ok;
}
//------------------------------------------------------------------------------
@@ -884,7 +933,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
#endif
break;
case 2:
+#if !defined(WORDS_BIGENDIAN)
memcpy(&pattern, src, sizeof(uint16_t));
+#else
+ pattern = ((uint32_t)src[0] << 8) | src[1];
+#endif
#if defined(__arm__) || defined(_M_ARM)
pattern |= pattern << 16;
#elif defined(WEBP_USE_MIPS_DSP_R2)
@@ -1523,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (dec == NULL) return 0;
assert(alph_dec != NULL);
- alph_dec->vp8l_dec_ = dec;
dec->width_ = alph_dec->width_;
dec->height_ = alph_dec->height_;
@@ -1555,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (!ok) goto Err;
+ // Only set here, once we are sure it is valid (to avoid thread races).
+ alph_dec->vp8l_dec_ = dec;
return 1;
Err:
- VP8LDelete(alph_dec->vp8l_dec_);
- alph_dec->vp8l_dec_ = NULL;
+ VP8LDelete(dec);
return 0;
}
diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h
index 8e500cf9ff..0a4d613f99 100644
--- a/thirdparty/libwebp/src/dec/vp8li_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8li_dec.h
@@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8LI_DEC_H_ */
+#endif // WEBP_DEC_VP8LI_DEC_H_
diff --git a/thirdparty/libwebp/src/dec/webpi_dec.h b/thirdparty/libwebp/src/dec/webpi_dec.h
index c378ba6fc3..24baff5d27 100644
--- a/thirdparty/libwebp/src/dec/webpi_dec.h
+++ b/thirdparty/libwebp/src/dec/webpi_dec.h
@@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
} // extern "C"
#endif
-#endif /* WEBP_DEC_WEBPI_DEC_H_ */
+#endif // WEBP_DEC_WEBPI_DEC_H_
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index 684215e3de..a69c65b7cf 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 0
+#define DMUX_REV_VERSION 1
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index 4ab77a5130..fafc2d05d3 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -76,10 +76,6 @@ extern "C" {
#define WEBP_USE_SSE41
#endif
-#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
-#define WEBP_USE_AVX2
-#endif
-
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if (defined(__ARM_NEON__) || \
@@ -679,4 +675,4 @@ void VP8FiltersInit(void);
} // extern "C"
#endif
-#endif /* WEBP_DSP_DSP_H_ */
+#endif // WEBP_DSP_DSP_H_
diff --git a/thirdparty/libwebp/src/dsp/enc.c b/thirdparty/libwebp/src/dsp/enc.c
index fa23b40a30..2fddbc4c52 100644
--- a/thirdparty/libwebp/src/dsp/enc.c
+++ b/thirdparty/libwebp/src/dsp/enc.c
@@ -734,7 +734,6 @@ VP8BlockCopy VP8Copy16x8;
extern void VP8EncDspInitSSE2(void);
extern void VP8EncDspInitSSE41(void);
-extern void VP8EncDspInitAVX2(void);
extern void VP8EncDspInitNEON(void);
extern void VP8EncDspInitMIPS32(void);
extern void VP8EncDspInitMIPSdspR2(void);
@@ -784,11 +783,6 @@ WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
#endif
}
#endif
-#if defined(WEBP_USE_AVX2)
- if (VP8GetCPUInfo(kAVX2)) {
- VP8EncDspInitAVX2();
- }
-#endif
#if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) {
VP8EncDspInitMIPS32();
diff --git a/thirdparty/libwebp/src/dsp/enc_avx2.c b/thirdparty/libwebp/src/dsp/enc_avx2.c
deleted file mode 100644
index 8bc5798fee..0000000000
--- a/thirdparty/libwebp/src/dsp/enc_avx2.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// AVX2 version of speed-critical encoding functions.
-
-#include "src/dsp/dsp.h"
-
-#if defined(WEBP_USE_AVX2)
-
-#endif // WEBP_USE_AVX2
-
-//------------------------------------------------------------------------------
-// Entry point
-
-WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2)
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index f9b3c182d3..d21aa6a0a0 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -23,8 +23,6 @@
#include "src/dsp/lossless.h"
#include "src/dsp/lossless_common.h"
-#define MAX_DIFF_COST (1e30f)
-
//------------------------------------------------------------------------------
// Image transforms.
diff --git a/thirdparty/libwebp/src/dsp/lossless.h b/thirdparty/libwebp/src/dsp/lossless.h
index b2bbdfc93c..f709cc86b2 100644
--- a/thirdparty/libwebp/src/dsp/lossless.h
+++ b/thirdparty/libwebp/src/dsp/lossless.h
@@ -163,7 +163,7 @@ extern VP8LCostCombinedFunc VP8LExtraCostCombined;
extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
typedef struct { // small struct to hold counters
- int counts[2]; // index: 0=zero steak, 1=non-zero streak
+ int counts[2]; // index: 0=zero streak, 1=non-zero streak
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks;
@@ -194,10 +194,14 @@ extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
VP8LBitEntropy* const entropy);
-typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out);
-extern VP8LHistogramAddFunc VP8LHistogramAdd;
+typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b,
+ uint32_t* out, int size);
+extern VP8LAddVectorFunc VP8LAddVector;
+typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size);
+extern VP8LAddVectorEqFunc VP8LAddVectorEq;
+void VP8LHistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out);
// -----------------------------------------------------------------------------
// PrefixEncode()
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc.c b/thirdparty/libwebp/src/dsp/lossless_enc.c
index d608326fef..1408fbf580 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc.c
@@ -632,38 +632,67 @@ static double ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y,
//------------------------------------------------------------------------------
-static void HistogramAdd_C(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
+static void AddVector_C(const uint32_t* a, const uint32_t* b, uint32_t* out,
+ int size) {
+ int i;
+ for (i = 0; i < size; ++i) out[i] = a[i] + b[i];
+}
+
+static void AddVectorEq_C(const uint32_t* a, uint32_t* out, int size) {
+ int i;
+ for (i = 0; i < size; ++i) out[i] += a[i];
+}
+
+#define ADD(X, ARG, LEN) do { \
+ if (a->is_used_[X]) { \
+ if (b->is_used_[X]) { \
+ VP8LAddVector(a->ARG, b->ARG, out->ARG, (LEN)); \
+ } else { \
+ memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } \
+ } else if (b->is_used_[X]) { \
+ memcpy(&out->ARG[0], &b->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } else { \
+ memset(&out->ARG[0], 0, (LEN) * sizeof(out->ARG[0])); \
+ } \
+} while (0)
+
+#define ADD_EQ(X, ARG, LEN) do { \
+ if (a->is_used_[X]) { \
+ if (out->is_used_[X]) { \
+ VP8LAddVectorEq(a->ARG, out->ARG, (LEN)); \
+ } else { \
+ memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
+ } \
+ } \
+} while (0)
+
+void VP8LHistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b, VP8LHistogram* const out) {
int i;
const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
assert(a->palette_code_bits_ == b->palette_code_bits_);
+
if (b != out) {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] = a->red_[i] + b->red_[i];
- out->blue_[i] = a->blue_[i] + b->blue_[i];
- out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
+ ADD(0, literal_, literal_size);
+ ADD(1, red_, NUM_LITERAL_CODES);
+ ADD(2, blue_, NUM_LITERAL_CODES);
+ ADD(3, alpha_, NUM_LITERAL_CODES);
+ ADD(4, distance_, NUM_DISTANCE_CODES);
+ for (i = 0; i < 5; ++i) {
+ out->is_used_[i] = (a->is_used_[i] | b->is_used_[i]);
}
} else {
- for (i = 0; i < literal_size; ++i) {
- out->literal_[i] += a->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] += a->distance_[i];
- }
- for (i = 0; i < NUM_LITERAL_CODES; ++i) {
- out->red_[i] += a->red_[i];
- out->blue_[i] += a->blue_[i];
- out->alpha_[i] += a->alpha_[i];
- }
+ ADD_EQ(0, literal_, literal_size);
+ ADD_EQ(1, red_, NUM_LITERAL_CODES);
+ ADD_EQ(2, blue_, NUM_LITERAL_CODES);
+ ADD_EQ(3, alpha_, NUM_LITERAL_CODES);
+ ADD_EQ(4, distance_, NUM_DISTANCE_CODES);
+ for (i = 0; i < 5; ++i) out->is_used_[i] |= a->is_used_[i];
}
}
+#undef ADD
+#undef ADD_EQ
//------------------------------------------------------------------------------
// Image transforms.
@@ -848,7 +877,8 @@ VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;
-VP8LHistogramAddFunc VP8LHistogramAdd;
+VP8LAddVectorFunc VP8LAddVector;
+VP8LAddVectorEqFunc VP8LAddVectorEq;
VP8LVectorMismatchFunc VP8LVectorMismatch;
VP8LBundleColorMapFunc VP8LBundleColorMap;
@@ -885,7 +915,8 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
VP8LGetEntropyUnrefined = GetEntropyUnrefined_C;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C;
- VP8LHistogramAdd = HistogramAdd_C;
+ VP8LAddVector = AddVector_C;
+ VP8LAddVectorEq = AddVectorEq_C;
VP8LVectorMismatch = VectorMismatch_C;
VP8LBundleColorMap = VP8LBundleColorMap_C;
@@ -971,7 +1002,8 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
assert(VP8LCombinedShannonEntropy != NULL);
assert(VP8LGetEntropyUnrefined != NULL);
assert(VP8LGetCombinedEntropyUnrefined != NULL);
- assert(VP8LHistogramAdd != NULL);
+ assert(VP8LAddVector != NULL);
+ assert(VP8LAddVectorEq != NULL);
assert(VP8LVectorMismatch != NULL);
assert(VP8LBundleColorMap != NULL);
assert(VP8LPredictorsSub[0] != NULL);
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c b/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
index e7b58f4e8c..0412a093cf 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_mips32.c
@@ -344,65 +344,29 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
ASM_END_COMMON_0 \
ASM_END_COMMON_1
-#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- const uint32_t* pb = (const uint32_t*)(B); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
- ASM_END_0 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
- } \
-} while (0)
-
-#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
- const uint32_t* pa = (const uint32_t*)(A); \
- uint32_t* pout = (uint32_t*)(OUT); \
- const uint32_t* const LoopEnd = pa + (SIZE); \
- assert((SIZE) % 4 == 0); \
- ASM_START \
- ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
- ASM_END_1 \
- if ((EXTRA_SIZE) > 0) { \
- const int last = (EXTRA_SIZE); \
- int i; \
- for (i = 0; i < last; ++i) pout[i] += pa[i]; \
- } \
-} while (0)
-
-static void HistogramAdd_MIPS32(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
+static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
+ uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
- - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
-
- if (b != out) {
- ADD_VECTOR(a->literal_, b->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR(a->distance_, b->distance_, out->distance_,
- NUM_DISTANCE_CODES, 0);
- ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- } else {
- ADD_VECTOR_EQ(a->literal_, out->literal_,
- NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
- ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
- ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
- ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
- }
+ const uint32_t end = ((size) / 4) * 4;
+ const uint32_t* const LoopEnd = pa + end;
+ int i;
+ ASM_START
+ ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
+ ASM_END_0
+ for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
+}
+
+static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
+ uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
+ const uint32_t end = ((size) / 4) * 4;
+ const uint32_t* const LoopEnd = pa + end;
+ int i;
+ ASM_START
+ ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
+ ASM_END_1
+ for (i = end; i < size; ++i) pout[i] += pa[i];
}
-#undef ADD_VECTOR_EQ
-#undef ADD_VECTOR
#undef ASM_END_1
#undef ASM_END_0
#undef ASM_END_COMMON_1
@@ -422,7 +386,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
VP8LExtraCostCombined = ExtraCostCombined_MIPS32;
VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32;
- VP8LHistogramAdd = HistogramAdd_MIPS32;
+ VP8LAddVector = AddVector_MIPS32;
+ VP8LAddVectorEq = AddVectorEq_MIPS32;
}
#else // !WEBP_USE_MIPS32
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index f84a9909e1..36478c4912 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -170,12 +170,13 @@ static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
//------------------------------------------------------------------------------
+// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
+// that's ok since the histogram values are less than 1<<28 (max picture size).
#define LINE_SIZE 16 // 8 or 16
static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
int size) {
int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
+ for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -195,12 +196,14 @@ static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
+ for (; i < size; ++i) {
+ out[i] = a[i] + b[i];
+ }
}
static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
int i;
- assert(size % LINE_SIZE == 0);
- for (i = 0; i < size; i += LINE_SIZE) {
+ for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -220,35 +223,11 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
-}
-#undef LINE_SIZE
-
-// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
-// that's ok since the histogram values are less than 1<<28 (max picture size).
-static void HistogramAdd_SSE2(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out) {
- int i;
- const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
- assert(a->palette_code_bits_ == b->palette_code_bits_);
- if (b != out) {
- AddVector_SSE2(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVector_SSE2(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
- } else {
- AddVectorEq_SSE2(a->literal_, out->literal_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->red_, out->red_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->blue_, out->blue_, NUM_LITERAL_CODES);
- AddVectorEq_SSE2(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
- }
- for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
- out->literal_[i] = a->literal_[i] + b->literal_[i];
- }
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- out->distance_[i] = a->distance_[i] + b->distance_[i];
+ for (; i < size; ++i) {
+ out[i] += a[i];
}
}
+#undef LINE_SIZE
//------------------------------------------------------------------------------
// Entropy
@@ -675,7 +654,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LTransformColor = TransformColor_SSE2;
VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2;
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2;
- VP8LHistogramAdd = HistogramAdd_SSE2;
+ VP8LAddVector = AddVector_SSE2;
+ VP8LAddVectorEq = AddVectorEq_SSE2;
VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2;
VP8LVectorMismatch = VectorMismatch_SSE2;
VP8LBundleColorMap = BundleColorMap_SSE2;
diff --git a/thirdparty/libwebp/src/dsp/msa_macro.h b/thirdparty/libwebp/src/dsp/msa_macro.h
index dfacda6ccd..de026a1d9e 100644
--- a/thirdparty/libwebp/src/dsp/msa_macro.h
+++ b/thirdparty/libwebp/src/dsp/msa_macro.h
@@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
-#endif /* WEBP_DSP_MSA_MACRO_H_ */
+#endif // WEBP_DSP_MSA_MACRO_H_
diff --git a/thirdparty/libwebp/src/dsp/rescaler.c b/thirdparty/libwebp/src/dsp/rescaler.c
index f307d35056..753f84fcf4 100644
--- a/thirdparty/libwebp/src/dsp/rescaler.c
+++ b/thirdparty/libwebp/src/dsp/rescaler.c
@@ -21,6 +21,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------
// Row import
@@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/thirdparty/libwebp/src/dsp/rescaler_mips32.c b/thirdparty/libwebp/src/dsp/rescaler_mips32.c
index 542f7e5970..61f63c616c 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_mips32.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_mips32.c
@@ -209,6 +209,7 @@ static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) {
}
}
+#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
const int x_out_max = wrk->dst_width * wrk->num_channels;
uint8_t* dst = wrk->dst;
@@ -273,6 +274,7 @@ static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
);
}
}
+#endif // 0
//------------------------------------------------------------------------------
// Entry point
@@ -283,7 +285,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
WebPRescalerImportRowExpand = ImportRowExpand_MIPS32;
WebPRescalerImportRowShrink = ImportRowShrink_MIPS32;
WebPRescalerExportRowExpand = ExportRowExpand_MIPS32;
- WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
}
#else // !WEBP_USE_MIPS32
diff --git a/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c b/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
index b78aac15e6..ce9e64862e 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c
@@ -20,10 +20,12 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------
// Row export
+#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
int i;
const int x_out_max = wrk->dst_width * wrk->num_channels;
@@ -106,7 +108,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
- const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = frac; // new fractional start
@@ -154,13 +156,14 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
);
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
- const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = 0;
}
}
}
+#endif // 0
static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
int i;
@@ -294,6 +297,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
@@ -304,7 +308,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2;
- WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
+// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
}
#else // !WEBP_USE_MIPS_DSP_R2
diff --git a/thirdparty/libwebp/src/dsp/rescaler_msa.c b/thirdparty/libwebp/src/dsp/rescaler_msa.c
index f3bc99f1cd..c559254836 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_msa.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_msa.c
@@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
v4u32 tmp0, tmp1, tmp2, tmp3; \
@@ -262,6 +263,7 @@ static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}
+#if 0 // disabled for now. TODO(skal): make match the C-code
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
uint8_t* dst, int length,
const uint32_t yscale,
@@ -341,7 +343,7 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
}
for (x_out = 0; x_out < length; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac;
@@ -426,6 +428,7 @@ static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
ExportRowShrink_1(irow, dst, x_out_max, wrk);
}
}
+#endif // 0
//------------------------------------------------------------------------------
// Entry point
@@ -434,7 +437,7 @@ extern void WebPRescalerDspInitMSA(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
- WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
+// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
}
#else // !WEBP_USE_MSA
diff --git a/thirdparty/libwebp/src/dsp/rescaler_neon.c b/thirdparty/libwebp/src/dsp/rescaler_neon.c
index 3eff9fbaf4..a553f06f79 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_neon.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_neon.c
@@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
#define LOAD_32x8(SRC, DST0, DST1) \
@@ -35,8 +36,11 @@
#if (WEBP_RESCALER_RFIX == 32)
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
-#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
+// note: B is actualy scale>>1. See MAKE_HALF_CST
+#define MULT_FIX(A, B) \
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
+#define MULT_FIX_FLOOR(A, B) \
+ vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#else
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
#endif
@@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1);
- const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
- const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
+ const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
+ const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
@@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
- const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR_C
+#undef MULT_FIX_C
+#undef MULT_FIX_FLOOR
+#undef MULT_FIX
+#undef ROUNDER
+
//------------------------------------------------------------------------------
extern void WebPRescalerDspInitNEON(void);
diff --git a/thirdparty/libwebp/src/dsp/rescaler_sse2.c b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
index 64c50deab5..f7461a452c 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_sse2.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
@@ -25,6 +25,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
@@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G);
}
+static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
+ const __m128i* const A1,
+ const __m128i* const A2,
+ const __m128i* const A3,
+ const __m128i* const mult,
+ uint8_t* const dst) {
+ const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
+ const __m128i B0 = _mm_mul_epu32(*A0, *mult);
+ const __m128i B1 = _mm_mul_epu32(*A1, *mult);
+ const __m128i B2 = _mm_mul_epu32(*A2, *mult);
+ const __m128i B3 = _mm_mul_epu32(*A3, *mult);
+ const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
+ const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
+#if (WEBP_RESCALER_RFIX < 32)
+ const __m128i D2 =
+ _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
+ const __m128i D3 =
+ _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
+#else
+ const __m128i D2 = _mm_and_si128(B2, mask);
+ const __m128i D3 = _mm_and_si128(B3, mask);
+#endif
+ const __m128i E0 = _mm_or_si128(D0, D2);
+ const __m128i E1 = _mm_or_si128(D1, D3);
+ const __m128i F = _mm_packs_epi32(E0, E1);
+ const __m128i G = _mm_packus_epi16(F, F);
+ _mm_storel_epi64((__m128i*)dst, G);
+}
+
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out;
uint8_t* const dst = wrk->dst;
@@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
- ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
+ ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
}
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/thirdparty/libwebp/src/dsp/yuv.h b/thirdparty/libwebp/src/dsp/yuv.h
index eb787270d2..c12be1d094 100644
--- a/thirdparty/libwebp/src/dsp/yuv.h
+++ b/thirdparty/libwebp/src/dsp/yuv.h
@@ -207,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
} // extern "C"
#endif
-#endif /* WEBP_DSP_YUV_H_ */
+#endif // WEBP_DSP_YUV_H_
diff --git a/thirdparty/libwebp/src/enc/analysis_enc.c b/thirdparty/libwebp/src/enc/analysis_enc.c
index a47ff7d4e8..687757ae03 100644
--- a/thirdparty/libwebp/src/enc/analysis_enc.c
+++ b/thirdparty/libwebp/src/enc/analysis_enc.c
@@ -458,7 +458,7 @@ static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
dst->uv_alpha += src->uv_alpha;
}
-// initialize the job struct with some TODOs
+// initialize the job struct with some tasks to perform
static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
int start_row, int end_row) {
WebPGetWorkerInterface()->Init(&job->worker);
diff --git a/thirdparty/libwebp/src/enc/backward_references_cost_enc.c b/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
index 7175496c7f..516abd73eb 100644
--- a/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
+++ b/thirdparty/libwebp/src/enc/backward_references_cost_enc.c
@@ -67,7 +67,7 @@ static int CostModelBuild(CostModel* const m, int xsize, int cache_bits,
// The following code is similar to VP8LHistogramCreate but converts the
// distance to plane code.
- VP8LHistogramInit(histo, cache_bits);
+ VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1);
while (VP8LRefsCursorOk(&c)) {
VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode,
xsize);
diff --git a/thirdparty/libwebp/src/enc/backward_references_enc.c b/thirdparty/libwebp/src/enc/backward_references_enc.c
index 39230188b9..3ab7b0ac7d 100644
--- a/thirdparty/libwebp/src/enc/backward_references_enc.c
+++ b/thirdparty/libwebp/src/enc/backward_references_enc.c
@@ -715,6 +715,7 @@ static int CalculateBestCacheSize(const uint32_t* argb, int quality,
for (i = 0; i <= cache_bits_max; ++i) {
histos[i] = VP8LAllocateHistogram(i);
if (histos[i] == NULL) goto Error;
+ VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1);
if (i == 0) continue;
cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
if (!cc_init[i]) goto Error;
diff --git a/thirdparty/libwebp/src/enc/cost_enc.h b/thirdparty/libwebp/src/enc/cost_enc.h
index bdce1e6a3b..a4b177b342 100644
--- a/thirdparty/libwebp/src/enc/cost_enc.h
+++ b/thirdparty/libwebp/src/enc/cost_enc.h
@@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
} // extern "C"
#endif
-#endif /* WEBP_ENC_COST_ENC_H_ */
+#endif // WEBP_ENC_COST_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/delta_palettization_enc.c b/thirdparty/libwebp/src/enc/delta_palettization_enc.c
deleted file mode 100644
index a61c8e6c93..0000000000
--- a/thirdparty/libwebp/src/enc/delta_palettization_enc.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#include "src/enc/delta_palettization_enc.h"
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "src/webp/types.h"
-#include "src/dsp/lossless.h"
-
-#define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b))
-
-// Format allows palette up to 256 entries, but more palette entries produce
-// bigger entropy. In the future it will probably be useful to add more entries
-// that are far from the origin of the palette or choose remaining entries
-// dynamically.
-#define DELTA_PALETTE_SIZE 226
-
-// Palette used for delta_palettization. Entries are roughly sorted by distance
-// of their signed equivalents from the origin.
-static const uint32_t kDeltaPalette[DELTA_PALETTE_SIZE] = {
- MK_COL(0u, 0u, 0u),
- MK_COL(255u, 255u, 255u),
- MK_COL(1u, 1u, 1u),
- MK_COL(254u, 254u, 254u),
- MK_COL(2u, 2u, 2u),
- MK_COL(4u, 4u, 4u),
- MK_COL(252u, 252u, 252u),
- MK_COL(250u, 0u, 0u),
- MK_COL(0u, 250u, 0u),
- MK_COL(0u, 0u, 250u),
- MK_COL(6u, 0u, 0u),
- MK_COL(0u, 6u, 0u),
- MK_COL(0u, 0u, 6u),
- MK_COL(0u, 0u, 248u),
- MK_COL(0u, 0u, 8u),
- MK_COL(0u, 248u, 0u),
- MK_COL(0u, 248u, 248u),
- MK_COL(0u, 248u, 8u),
- MK_COL(0u, 8u, 0u),
- MK_COL(0u, 8u, 248u),
- MK_COL(0u, 8u, 8u),
- MK_COL(8u, 8u, 8u),
- MK_COL(248u, 0u, 0u),
- MK_COL(248u, 0u, 248u),
- MK_COL(248u, 0u, 8u),
- MK_COL(248u, 248u, 0u),
- MK_COL(248u, 8u, 0u),
- MK_COL(8u, 0u, 0u),
- MK_COL(8u, 0u, 248u),
- MK_COL(8u, 0u, 8u),
- MK_COL(8u, 248u, 0u),
- MK_COL(8u, 8u, 0u),
- MK_COL(23u, 23u, 23u),
- MK_COL(13u, 13u, 13u),
- MK_COL(232u, 232u, 232u),
- MK_COL(244u, 244u, 244u),
- MK_COL(245u, 245u, 250u),
- MK_COL(50u, 50u, 50u),
- MK_COL(204u, 204u, 204u),
- MK_COL(236u, 236u, 236u),
- MK_COL(16u, 16u, 16u),
- MK_COL(240u, 16u, 16u),
- MK_COL(16u, 240u, 16u),
- MK_COL(240u, 240u, 16u),
- MK_COL(16u, 16u, 240u),
- MK_COL(240u, 16u, 240u),
- MK_COL(16u, 240u, 240u),
- MK_COL(240u, 240u, 240u),
- MK_COL(0u, 0u, 232u),
- MK_COL(0u, 232u, 0u),
- MK_COL(232u, 0u, 0u),
- MK_COL(0u, 0u, 24u),
- MK_COL(0u, 24u, 0u),
- MK_COL(24u, 0u, 0u),
- MK_COL(32u, 32u, 32u),
- MK_COL(224u, 32u, 32u),
- MK_COL(32u, 224u, 32u),
- MK_COL(224u, 224u, 32u),
- MK_COL(32u, 32u, 224u),
- MK_COL(224u, 32u, 224u),
- MK_COL(32u, 224u, 224u),
- MK_COL(224u, 224u, 224u),
- MK_COL(0u, 0u, 176u),
- MK_COL(0u, 0u, 80u),
- MK_COL(0u, 176u, 0u),
- MK_COL(0u, 176u, 176u),
- MK_COL(0u, 176u, 80u),
- MK_COL(0u, 80u, 0u),
- MK_COL(0u, 80u, 176u),
- MK_COL(0u, 80u, 80u),
- MK_COL(176u, 0u, 0u),
- MK_COL(176u, 0u, 176u),
- MK_COL(176u, 0u, 80u),
- MK_COL(176u, 176u, 0u),
- MK_COL(176u, 80u, 0u),
- MK_COL(80u, 0u, 0u),
- MK_COL(80u, 0u, 176u),
- MK_COL(80u, 0u, 80u),
- MK_COL(80u, 176u, 0u),
- MK_COL(80u, 80u, 0u),
- MK_COL(0u, 0u, 152u),
- MK_COL(0u, 0u, 104u),
- MK_COL(0u, 152u, 0u),
- MK_COL(0u, 152u, 152u),
- MK_COL(0u, 152u, 104u),
- MK_COL(0u, 104u, 0u),
- MK_COL(0u, 104u, 152u),
- MK_COL(0u, 104u, 104u),
- MK_COL(152u, 0u, 0u),
- MK_COL(152u, 0u, 152u),
- MK_COL(152u, 0u, 104u),
- MK_COL(152u, 152u, 0u),
- MK_COL(152u, 104u, 0u),
- MK_COL(104u, 0u, 0u),
- MK_COL(104u, 0u, 152u),
- MK_COL(104u, 0u, 104u),
- MK_COL(104u, 152u, 0u),
- MK_COL(104u, 104u, 0u),
- MK_COL(216u, 216u, 216u),
- MK_COL(216u, 216u, 40u),
- MK_COL(216u, 216u, 176u),
- MK_COL(216u, 216u, 80u),
- MK_COL(216u, 40u, 216u),
- MK_COL(216u, 40u, 40u),
- MK_COL(216u, 40u, 176u),
- MK_COL(216u, 40u, 80u),
- MK_COL(216u, 176u, 216u),
- MK_COL(216u, 176u, 40u),
- MK_COL(216u, 176u, 176u),
- MK_COL(216u, 176u, 80u),
- MK_COL(216u, 80u, 216u),
- MK_COL(216u, 80u, 40u),
- MK_COL(216u, 80u, 176u),
- MK_COL(216u, 80u, 80u),
- MK_COL(40u, 216u, 216u),
- MK_COL(40u, 216u, 40u),
- MK_COL(40u, 216u, 176u),
- MK_COL(40u, 216u, 80u),
- MK_COL(40u, 40u, 216u),
- MK_COL(40u, 40u, 40u),
- MK_COL(40u, 40u, 176u),
- MK_COL(40u, 40u, 80u),
- MK_COL(40u, 176u, 216u),
- MK_COL(40u, 176u, 40u),
- MK_COL(40u, 176u, 176u),
- MK_COL(40u, 176u, 80u),
- MK_COL(40u, 80u, 216u),
- MK_COL(40u, 80u, 40u),
- MK_COL(40u, 80u, 176u),
- MK_COL(40u, 80u, 80u),
- MK_COL(80u, 216u, 216u),
- MK_COL(80u, 216u, 40u),
- MK_COL(80u, 216u, 176u),
- MK_COL(80u, 216u, 80u),
- MK_COL(80u, 40u, 216u),
- MK_COL(80u, 40u, 40u),
- MK_COL(80u, 40u, 176u),
- MK_COL(80u, 40u, 80u),
- MK_COL(80u, 176u, 216u),
- MK_COL(80u, 176u, 40u),
- MK_COL(80u, 176u, 176u),
- MK_COL(80u, 176u, 80u),
- MK_COL(80u, 80u, 216u),
- MK_COL(80u, 80u, 40u),
- MK_COL(80u, 80u, 176u),
- MK_COL(80u, 80u, 80u),
- MK_COL(0u, 0u, 192u),
- MK_COL(0u, 0u, 64u),
- MK_COL(0u, 0u, 128u),
- MK_COL(0u, 192u, 0u),
- MK_COL(0u, 192u, 192u),
- MK_COL(0u, 192u, 64u),
- MK_COL(0u, 192u, 128u),
- MK_COL(0u, 64u, 0u),
- MK_COL(0u, 64u, 192u),
- MK_COL(0u, 64u, 64u),
- MK_COL(0u, 64u, 128u),
- MK_COL(0u, 128u, 0u),
- MK_COL(0u, 128u, 192u),
- MK_COL(0u, 128u, 64u),
- MK_COL(0u, 128u, 128u),
- MK_COL(176u, 216u, 216u),
- MK_COL(176u, 216u, 40u),
- MK_COL(176u, 216u, 176u),
- MK_COL(176u, 216u, 80u),
- MK_COL(176u, 40u, 216u),
- MK_COL(176u, 40u, 40u),
- MK_COL(176u, 40u, 176u),
- MK_COL(176u, 40u, 80u),
- MK_COL(176u, 176u, 216u),
- MK_COL(176u, 176u, 40u),
- MK_COL(176u, 176u, 176u),
- MK_COL(176u, 176u, 80u),
- MK_COL(176u, 80u, 216u),
- MK_COL(176u, 80u, 40u),
- MK_COL(176u, 80u, 176u),
- MK_COL(176u, 80u, 80u),
- MK_COL(192u, 0u, 0u),
- MK_COL(192u, 0u, 192u),
- MK_COL(192u, 0u, 64u),
- MK_COL(192u, 0u, 128u),
- MK_COL(192u, 192u, 0u),
- MK_COL(192u, 192u, 192u),
- MK_COL(192u, 192u, 64u),
- MK_COL(192u, 192u, 128u),
- MK_COL(192u, 64u, 0u),
- MK_COL(192u, 64u, 192u),
- MK_COL(192u, 64u, 64u),
- MK_COL(192u, 64u, 128u),
- MK_COL(192u, 128u, 0u),
- MK_COL(192u, 128u, 192u),
- MK_COL(192u, 128u, 64u),
- MK_COL(192u, 128u, 128u),
- MK_COL(64u, 0u, 0u),
- MK_COL(64u, 0u, 192u),
- MK_COL(64u, 0u, 64u),
- MK_COL(64u, 0u, 128u),
- MK_COL(64u, 192u, 0u),
- MK_COL(64u, 192u, 192u),
- MK_COL(64u, 192u, 64u),
- MK_COL(64u, 192u, 128u),
- MK_COL(64u, 64u, 0u),
- MK_COL(64u, 64u, 192u),
- MK_COL(64u, 64u, 64u),
- MK_COL(64u, 64u, 128u),
- MK_COL(64u, 128u, 0u),
- MK_COL(64u, 128u, 192u),
- MK_COL(64u, 128u, 64u),
- MK_COL(64u, 128u, 128u),
- MK_COL(128u, 0u, 0u),
- MK_COL(128u, 0u, 192u),
- MK_COL(128u, 0u, 64u),
- MK_COL(128u, 0u, 128u),
- MK_COL(128u, 192u, 0u),
- MK_COL(128u, 192u, 192u),
- MK_COL(128u, 192u, 64u),
- MK_COL(128u, 192u, 128u),
- MK_COL(128u, 64u, 0u),
- MK_COL(128u, 64u, 192u),
- MK_COL(128u, 64u, 64u),
- MK_COL(128u, 64u, 128u),
- MK_COL(128u, 128u, 0u),
- MK_COL(128u, 128u, 192u),
- MK_COL(128u, 128u, 64u),
- MK_COL(128u, 128u, 128u),
-};
-
-#undef MK_COL
-
-//------------------------------------------------------------------------------
-// TODO(skal): move the functions to dsp/lossless.c when the correct
-// granularity is found. For now, we'll just copy-paste some useful bits
-// here instead.
-
-// In-place sum of each component with mod 256.
-static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
- const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
- const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
- *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-static WEBP_INLINE uint32_t Clip255(uint32_t a) {
- if (a < 256) {
- return a;
- }
- // return 0, when a is a negative integer.
- // return 255, when a is positive.
- return ~a >> 24;
-}
-
-// Delta palettization functions.
-static WEBP_INLINE int Square(int x) {
- return x * x;
-}
-
-static WEBP_INLINE uint32_t Intensity(uint32_t a) {
- return
- 30 * ((a >> 16) & 0xff) +
- 59 * ((a >> 8) & 0xff) +
- 11 * ((a >> 0) & 0xff);
-}
-
-static uint32_t CalcDist(uint32_t predicted_value, uint32_t actual_value,
- uint32_t palette_entry) {
- int i;
- uint32_t distance = 0;
- AddPixelsEq(&predicted_value, palette_entry);
- for (i = 0; i < 32; i += 8) {
- const int32_t av = (actual_value >> i) & 0xff;
- const int32_t pv = (predicted_value >> i) & 0xff;
- distance += Square(pv - av);
- }
- // We sum square of intensity difference with factor 10, but because Intensity
- // returns 100 times real intensity we need to multiply differences of colors
- // by 1000.
- distance *= 1000u;
- distance += Square(Intensity(predicted_value)
- - Intensity(actual_value));
- return distance;
-}
-
-static uint32_t Predict(int x, int y, uint32_t* image) {
- const uint32_t t = (y == 0) ? ARGB_BLACK : image[x];
- const uint32_t l = (x == 0) ? ARGB_BLACK : image[x - 1];
- const uint32_t p =
- (((((t >> 24) & 0xff) + ((l >> 24) & 0xff)) / 2) << 24) +
- (((((t >> 16) & 0xff) + ((l >> 16) & 0xff)) / 2) << 16) +
- (((((t >> 8) & 0xff) + ((l >> 8) & 0xff)) / 2) << 8) +
- (((((t >> 0) & 0xff) + ((l >> 0) & 0xff)) / 2) << 0);
- if (x == 0 && y == 0) return ARGB_BLACK;
- if (x == 0) return t;
- if (y == 0) return l;
- return p;
-}
-
-static WEBP_INLINE int AddSubtractComponentFullWithCoefficient(
- int a, int b, int c) {
- return Clip255(a + ((b - c) >> 2));
-}
-
-static WEBP_INLINE uint32_t ClampedAddSubtractFullWithCoefficient(
- uint32_t c0, uint32_t c1, uint32_t c2) {
- const int a = AddSubtractComponentFullWithCoefficient(
- c0 >> 24, c1 >> 24, c2 >> 24);
- const int r = AddSubtractComponentFullWithCoefficient((c0 >> 16) & 0xff,
- (c1 >> 16) & 0xff,
- (c2 >> 16) & 0xff);
- const int g = AddSubtractComponentFullWithCoefficient((c0 >> 8) & 0xff,
- (c1 >> 8) & 0xff,
- (c2 >> 8) & 0xff);
- const int b = AddSubtractComponentFullWithCoefficient(
- c0 & 0xff, c1 & 0xff, c2 & 0xff);
- return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
-}
-
-//------------------------------------------------------------------------------
-
-// Find palette entry with minimum error from difference of actual pixel value
-// and predicted pixel value. Propagate error of pixel to its top and left pixel
-// in src array. Write predicted_value + palette_entry to new_image. Return
-// index of best palette entry.
-static int FindBestPaletteEntry(uint32_t src, uint32_t predicted_value,
- const uint32_t palette[], int palette_size) {
- int i;
- int idx = 0;
- uint32_t best_distance = CalcDist(predicted_value, src, palette[0]);
- for (i = 1; i < palette_size; ++i) {
- const uint32_t distance = CalcDist(predicted_value, src, palette[i]);
- if (distance < best_distance) {
- best_distance = distance;
- idx = i;
- }
- }
- return idx;
-}
-
-static void ApplyBestPaletteEntry(int x, int y,
- uint32_t new_value, uint32_t palette_value,
- uint32_t* src, int src_stride,
- uint32_t* new_image) {
- AddPixelsEq(&new_value, palette_value);
- if (x > 0) {
- src[x - 1] = ClampedAddSubtractFullWithCoefficient(src[x - 1],
- new_value, src[x]);
- }
- if (y > 0) {
- src[x - src_stride] =
- ClampedAddSubtractFullWithCoefficient(src[x - src_stride],
- new_value, src[x]);
- }
- new_image[x] = new_value;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point
-
-static WebPEncodingError ApplyDeltaPalette(uint32_t* src, uint32_t* dst,
- uint32_t src_stride,
- uint32_t dst_stride,
- const uint32_t* palette,
- int palette_size,
- int width, int height,
- int num_passes) {
- int x, y;
- WebPEncodingError err = VP8_ENC_OK;
- uint32_t* new_image = (uint32_t*)WebPSafeMalloc(width, sizeof(*new_image));
- uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
- if (new_image == NULL || tmp_row == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- while (num_passes--) {
- uint32_t* cur_src = src;
- uint32_t* cur_dst = dst;
- for (y = 0; y < height; ++y) {
- for (x = 0; x < width; ++x) {
- const uint32_t predicted_value = Predict(x, y, new_image);
- tmp_row[x] = FindBestPaletteEntry(cur_src[x], predicted_value,
- palette, palette_size);
- ApplyBestPaletteEntry(x, y, predicted_value, palette[tmp_row[x]],
- cur_src, src_stride, new_image);
- }
- for (x = 0; x < width; ++x) {
- cur_dst[x] = palette[tmp_row[x]];
- }
- cur_src += src_stride;
- cur_dst += dst_stride;
- }
- }
- Error:
- WebPSafeFree(new_image);
- WebPSafeFree(tmp_row);
- return err;
-}
-
-// replaces enc->argb_ by a palettizable approximation of it,
-// and generates optimal enc->palette_[]
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- const WebPPicture* const pic = enc->pic_;
- uint32_t* src = pic->argb;
- uint32_t* dst = enc->argb_;
- const int width = pic->width;
- const int height = pic->height;
-
- WebPEncodingError err = VP8_ENC_OK;
- memcpy(enc->palette_, kDeltaPalette, sizeof(kDeltaPalette));
- enc->palette_[DELTA_PALETTE_SIZE - 1] = src[0] - 0xff000000u;
- enc->palette_size_ = DELTA_PALETTE_SIZE;
- err = ApplyDeltaPalette(src, dst, pic->argb_stride, enc->current_width_,
- enc->palette_, enc->palette_size_,
- width, height, 2);
- if (err != VP8_ENC_OK) goto Error;
-
- Error:
- return err;
-}
-
-#else // !WEBP_EXPERIMENTAL_FEATURES
-
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc) {
- (void)enc;
- return VP8_ENC_ERROR_INVALID_CONFIGURATION;
-}
-
-#endif // WEBP_EXPERIMENTAL_FEATURES
diff --git a/thirdparty/libwebp/src/enc/delta_palettization_enc.h b/thirdparty/libwebp/src/enc/delta_palettization_enc.h
deleted file mode 100644
index b15e2cd487..0000000000
--- a/thirdparty/libwebp/src/enc/delta_palettization_enc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
-// -----------------------------------------------------------------------------
-//
-// Author: Mislav Bradac (mislavm@google.com)
-//
-
-#ifndef WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
-#define WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
-
-#include "src/webp/encode.h"
-#include "src/enc/vp8li_enc.h"
-
-// Replaces enc->argb_[] input by a palettizable approximation of it,
-// and generates optimal enc->palette_[].
-// This function can revert enc->use_palette_ / enc->use_predict_ flag
-// if delta-palettization is not producing expected saving.
-WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc);
-
-#endif // WEBP_ENC_DELTA_PALETTIZATION_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index 9fdbc627a1..4e49e0a201 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -51,10 +51,12 @@ static void HistogramCopy(const VP8LHistogram* const src,
VP8LHistogram* const dst) {
uint32_t* const dst_literal = dst->literal_;
const int dst_cache_bits = dst->palette_code_bits_;
+ const int literal_size = VP8LHistogramNumCodes(dst_cache_bits);
const int histo_size = VP8LGetHistogramSize(dst_cache_bits);
assert(src->palette_code_bits_ == dst_cache_bits);
memcpy(dst, src, histo_size);
dst->literal_ = dst_literal;
+ memcpy(dst->literal_, src->literal_, literal_size * sizeof(*dst->literal_));
}
int VP8LGetHistogramSize(int cache_bits) {
@@ -91,9 +93,19 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
VP8LHistogramStoreRefs(refs, p);
}
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits) {
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
+ int init_arrays) {
p->palette_code_bits_ = palette_code_bits;
- HistogramClear(p);
+ if (init_arrays) {
+ HistogramClear(p);
+ } else {
+ p->trivial_symbol_ = 0;
+ p->bit_cost_ = 0.;
+ p->literal_cost_ = 0.;
+ p->red_cost_ = 0.;
+ p->blue_cost_ = 0.;
+ memset(p->is_used_, 0, sizeof(p->is_used_));
+ }
}
VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
@@ -104,37 +116,70 @@ VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
histo = (VP8LHistogram*)memory;
// literal_ won't necessary be aligned.
histo->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(histo, cache_bits);
+ VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0);
return histo;
}
+// Resets the pointers of the histograms to point to the bit buffer in the set.
+static void HistogramSetResetPointers(VP8LHistogramSet* const set,
+ int cache_bits) {
+ int i;
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ uint8_t* memory = (uint8_t*) (set->histograms);
+ memory += set->max_size * sizeof(*set->histograms);
+ for (i = 0; i < set->max_size; ++i) {
+ memory = (uint8_t*) WEBP_ALIGN(memory);
+ set->histograms[i] = (VP8LHistogram*) memory;
+ // literal_ won't necessary be aligned.
+ set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
+ memory += histo_size;
+ }
+}
+
+// Returns the total size of the VP8LHistogramSet.
+static size_t HistogramSetTotalSize(int size, int cache_bits) {
+ const int histo_size = VP8LGetHistogramSize(cache_bits);
+ return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) +
+ histo_size + WEBP_ALIGN_CST));
+}
+
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
int i;
VP8LHistogramSet* set;
- const int histo_size = VP8LGetHistogramSize(cache_bits);
- const size_t total_size =
- sizeof(*set) + size * (sizeof(*set->histograms) +
- histo_size + WEBP_ALIGN_CST);
+ const size_t total_size = HistogramSetTotalSize(size, cache_bits);
uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
if (memory == NULL) return NULL;
set = (VP8LHistogramSet*)memory;
memory += sizeof(*set);
set->histograms = (VP8LHistogram**)memory;
- memory += size * sizeof(*set->histograms);
set->max_size = size;
set->size = size;
+ HistogramSetResetPointers(set, cache_bits);
for (i = 0; i < size; ++i) {
- memory = (uint8_t*)WEBP_ALIGN(memory);
- set->histograms[i] = (VP8LHistogram*)memory;
- // literal_ won't necessary be aligned.
- set->histograms[i]->literal_ = (uint32_t*)(memory + sizeof(VP8LHistogram));
- VP8LHistogramInit(set->histograms[i], cache_bits);
- memory += histo_size;
+ VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0);
}
return set;
}
+void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
+ int i;
+ const int cache_bits = set->histograms[0]->palette_code_bits_;
+ const int size = set->size;
+ const size_t total_size = HistogramSetTotalSize(size, cache_bits);
+ uint8_t* memory = (uint8_t*)set;
+
+ memset(memory, 0, total_size);
+ memory += sizeof(*set);
+ set->histograms = (VP8LHistogram**)memory;
+ set->max_size = size;
+ set->size = size;
+ HistogramSetResetPointers(set, cache_bits);
+ for (i = 0; i < size; ++i) {
+ set->histograms[i]->palette_code_bits_ = cache_bits;
+ }
+}
+
// -----------------------------------------------------------------------------
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
@@ -237,7 +282,8 @@ static double FinalHuffmanCost(const VP8LStreaks* const stats) {
// Get the symbol entropy for the distribution 'population'.
// Set 'trivial_sym', if there's only one symbol present in the distribution.
static double PopulationCost(const uint32_t* const population, int length,
- uint32_t* const trivial_sym) {
+ uint32_t* const trivial_sym,
+ uint8_t* const is_used) {
VP8LBitEntropy bit_entropy;
VP8LStreaks stats;
VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
@@ -245,6 +291,8 @@ static double PopulationCost(const uint32_t* const population, int length,
*trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
: VP8L_NON_TRIVIAL_SYM;
}
+ // The histogram is used if there is at least one non-zero streak.
+ *is_used = (stats.streaks[1][0] != 0 || stats.streaks[1][1] != 0);
return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
}
@@ -253,7 +301,9 @@ static double PopulationCost(const uint32_t* const population, int length,
// non-zero: both the zero-th one, or both the last one.
static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
const uint32_t* const Y,
- int length, int trivial_at_end) {
+ int length, int is_X_used,
+ int is_Y_used,
+ int trivial_at_end) {
VP8LStreaks stats;
if (trivial_at_end) {
// This configuration is due to palettization that transforms an indexed
@@ -262,28 +312,43 @@ static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
// Only FinalHuffmanCost needs to be evaluated.
memset(&stats, 0, sizeof(stats));
// Deal with the non-zero value at index 0 or length-1.
- stats.streaks[1][0] += 1;
+ stats.streaks[1][0] = 1;
// Deal with the following/previous zero streak.
- stats.counts[0] += 1;
- stats.streaks[0][1] += length - 1;
+ stats.counts[0] = 1;
+ stats.streaks[0][1] = length - 1;
return FinalHuffmanCost(&stats);
} else {
VP8LBitEntropy bit_entropy;
- VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
+ if (is_X_used) {
+ if (is_Y_used) {
+ VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
+ } else {
+ VP8LGetEntropyUnrefined(X, length, &bit_entropy, &stats);
+ }
+ } else {
+ if (is_Y_used) {
+ VP8LGetEntropyUnrefined(Y, length, &bit_entropy, &stats);
+ } else {
+ memset(&stats, 0, sizeof(stats));
+ stats.counts[0] = 1;
+ stats.streaks[0][length > 3] = length;
+ VP8LBitEntropyInit(&bit_entropy);
+ }
+ }
return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
}
}
// Estimates the Entropy + Huffman + other block overhead size cost.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
+double VP8LHistogramEstimateBits(VP8LHistogram* const p) {
return
- PopulationCost(
- p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
- + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
+ PopulationCost(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_),
+ NULL, &p->is_used_[0])
+ + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1])
+ + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2])
+ + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3])
+ + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, &p->is_used_[4])
+ VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
+ VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
}
@@ -299,7 +364,8 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
int trivial_at_end = 0;
assert(a->palette_code_bits_ == b->palette_code_bits_);
*cost += GetCombinedEntropy(a->literal_, b->literal_,
- VP8LHistogramNumCodes(palette_code_bits), 0);
+ VP8LHistogramNumCodes(palette_code_bits),
+ a->is_used_[0], b->is_used_[0], 0);
*cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES,
b->literal_ + NUM_LITERAL_CODES,
NUM_LENGTH_CODES);
@@ -319,19 +385,23 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a,
}
*cost +=
- GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, trivial_at_end);
+ GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, a->is_used_[1],
+ b->is_used_[1], trivial_at_end);
if (*cost > cost_threshold) return 0;
*cost +=
- GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, trivial_at_end);
+ GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, a->is_used_[2],
+ b->is_used_[2], trivial_at_end);
if (*cost > cost_threshold) return 0;
- *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES,
- trivial_at_end);
+ *cost +=
+ GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES,
+ a->is_used_[3], b->is_used_[3], trivial_at_end);
if (*cost > cost_threshold) return 0;
*cost +=
- GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, 0);
+ GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES,
+ a->is_used_[4], b->is_used_[4], 0);
*cost +=
VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES);
if (*cost > cost_threshold) return 0;
@@ -419,16 +489,19 @@ static void UpdateDominantCostRange(
static void UpdateHistogramCost(VP8LHistogram* const h) {
uint32_t alpha_sym, red_sym, blue_sym;
const double alpha_cost =
- PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym);
+ PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym,
+ &h->is_used_[3]);
const double distance_cost =
- PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
+ PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL, &h->is_used_[4]) +
VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
- h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) +
- VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
- NUM_LENGTH_CODES);
- h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
- h->blue_cost_ = PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym);
+ h->literal_cost_ =
+ PopulationCost(h->literal_, num_codes, NULL, &h->is_used_[0]) +
+ VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES);
+ h->red_cost_ =
+ PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym, &h->is_used_[1]);
+ h->blue_cost_ =
+ PopulationCost(h->blue_, NUM_LITERAL_CODES, &blue_sym, &h->is_used_[2]);
h->bit_cost_ = h->literal_cost_ + h->red_cost_ + h->blue_cost_ +
alpha_cost + distance_cost;
if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) {
@@ -473,6 +546,7 @@ static void HistogramBuild(
VP8LHistogram** const histograms = image_histo->histograms;
VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
assert(histo_bits > 0);
+ VP8LHistogramSetClear(image_histo);
while (VP8LRefsCursorOk(&c)) {
const PixOrCopy* const v = c.cur_pos;
const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
@@ -493,11 +567,19 @@ static void HistogramCopyAndAnalyze(
const int histo_size = orig_histo->size;
VP8LHistogram** const orig_histograms = orig_histo->histograms;
VP8LHistogram** const histograms = image_histo->histograms;
+ image_histo->size = 0;
for (i = 0; i < histo_size; ++i) {
VP8LHistogram* const histo = orig_histograms[i];
UpdateHistogramCost(histo);
+
+ // Skip the histogram if it is completely empty, which can happen for tiles
+ // with no information (when they are skipped because of LZ77).
+ if (!histo->is_used_[0] && !histo->is_used_[1] && !histo->is_used_[2]
+ && !histo->is_used_[3] && !histo->is_used_[4]) {
+ continue;
+ }
// Copy histograms from orig_histo[] to image_histo[].
- HistogramCopy(histo, histograms[i]);
+ HistogramCopy(histo, histograms[image_histo->size++]);
}
}
@@ -674,6 +756,18 @@ static void HistoQueueUpdateHead(HistoQueue* const histo_queue,
}
}
+// Update the cost diff and combo of a pair of histograms. This needs to be
+// called when the the histograms have been merged with a third one.
+static void HistoQueueUpdatePair(const VP8LHistogram* const h1,
+ const VP8LHistogram* const h2,
+ double threshold,
+ HistogramPair* const pair) {
+ const double sum_cost = h1->bit_cost_ + h2->bit_cost_;
+ pair->cost_combo = 0.;
+ GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair->cost_combo);
+ pair->cost_diff = pair->cost_combo - sum_cost;
+}
+
// Create a pair from indices "idx1" and "idx2" provided its cost
// is inferior to "threshold", a negative entropy.
// It returns the cost of the pair, or 0. if it superior to threshold.
@@ -683,7 +777,6 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
const VP8LHistogram* h1;
const VP8LHistogram* h2;
HistogramPair pair;
- double sum_cost;
assert(threshold <= 0.);
if (idx1 > idx2) {
@@ -695,10 +788,8 @@ static double HistoQueuePush(HistoQueue* const histo_queue,
pair.idx2 = idx2;
h1 = histograms[idx1];
h2 = histograms[idx2];
- sum_cost = h1->bit_cost_ + h2->bit_cost_;
- pair.cost_combo = 0.;
- GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair.cost_combo);
- pair.cost_diff = pair.cost_combo - sum_cost;
+
+ HistoQueueUpdatePair(h1, h2, threshold, &pair);
// Do not even consider the pair if it does not improve the entropy.
if (pair.cost_diff >= threshold) return 0.;
@@ -891,8 +982,7 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
}
if (do_eval) {
// Re-evaluate the cost of an updated pair.
- GetCombinedHistogramEntropy(histograms[p->idx1], histograms[p->idx2], 0,
- &p->cost_diff);
+ HistoQueueUpdatePair(histograms[p->idx1], histograms[p->idx2], 0., p);
if (p->cost_diff >= 0.) {
HistoQueuePopPair(&histo_queue, p);
continue;
@@ -987,8 +1077,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
// histograms of small sizes (as bin_map will be very sparse) and
// maximum quality q==100 (to preserve the compression gains at that level).
const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
- const int entropy_combine =
- (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
+ int entropy_combine;
if (orig_histo == NULL) goto Error;
@@ -996,15 +1085,16 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
HistogramBuild(xsize, histo_bits, refs, orig_histo);
// Copies the histograms and computes its bit_cost.
HistogramCopyAndAnalyze(orig_histo, image_histo);
-
+ entropy_combine =
+ (image_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
if (entropy_combine) {
- const int bin_map_size = orig_histo->size;
+ const int bin_map_size = image_histo->size;
// Reuse histogram_symbols storage. By definition, it's guaranteed to be ok.
uint16_t* const bin_map = histogram_symbols;
const double combine_cost_factor =
GetCombineCostFactor(image_histo_raw_size, quality);
- HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort);
+ HistogramAnalyzeEntropyBin(image_histo, bin_map, low_effort);
// Collapse histograms with similar entropy.
HistogramCombineEntropyBin(image_histo, tmp_histo, bin_map, bin_map_size,
entropy_combine_num_bins, combine_cost_factor,
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.h b/thirdparty/libwebp/src/enc/histogram_enc.h
index e8c4c83f6f..54c2d21783 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.h
+++ b/thirdparty/libwebp/src/enc/histogram_enc.h
@@ -44,6 +44,7 @@ typedef struct {
double literal_cost_; // Cached values of dominant entropy costs:
double red_cost_; // literal, red & blue.
double blue_cost_;
+ uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance
} VP8LHistogram;
// Collection of histograms with fixed capacity, allocated as one
@@ -67,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
int VP8LGetHistogramSize(int palette_code_bits);
// Set the palette_code_bits and reset the stats.
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
+// If init_arrays is true, the arrays are also filled with 0's.
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
+ int init_arrays);
// Collect all the references into a histogram (without reset)
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
@@ -83,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
// using 'cache_bits'. Return NULL in case of memory error.
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
+// Set the histograms in set to 0.
+void VP8LHistogramSetClear(VP8LHistogramSet* const set);
+
// Allocate and initialize histogram object with specified 'cache_bits'.
// Returns NULL in case of memory error.
// Special case of VP8LAllocateHistogramSet, with size equals 1.
@@ -113,7 +119,7 @@ double VP8LBitsEntropy(const uint32_t* const array, int n);
// Estimate how many bits the combined entropy of literals and distance
// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+double VP8LHistogramEstimateBits(VP8LHistogram* const p);
#ifdef __cplusplus
}
diff --git a/thirdparty/libwebp/src/enc/iterator_enc.c b/thirdparty/libwebp/src/enc/iterator_enc.c
index 7c47d51272..29f91d8315 100644
--- a/thirdparty/libwebp/src/enc/iterator_enc.c
+++ b/thirdparty/libwebp/src/enc/iterator_enc.c
@@ -128,7 +128,7 @@ static void ImportLine(const uint8_t* src, int src_stride,
for (; i < total_len; ++i) dst[i] = dst[len - 1];
}
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32) {
const VP8Encoder* const enc = it->enc_;
const int x = it->x_, y = it->y_;
const WebPPicture* const pic = enc->pic_;
diff --git a/thirdparty/libwebp/src/enc/picture_tools_enc.c b/thirdparty/libwebp/src/enc/picture_tools_enc.c
index be292d4391..d0e8a495da 100644
--- a/thirdparty/libwebp/src/enc/picture_tools_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_tools_enc.c
@@ -16,10 +16,6 @@
#include "src/enc/vp8i_enc.h"
#include "src/dsp/yuv.h"
-static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
- return (0xff000000u | (r << 16) | (g << 8) | b);
-}
-
//------------------------------------------------------------------------------
// Helper: clean up fully transparent area to help compressibility.
@@ -195,6 +191,10 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
#define BLEND_10BIT(V0, V1, ALPHA) \
((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18)
+static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
+ return (0xff000000u | (r << 16) | (g << 8) | b);
+}
+
void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int red = (background_rgb >> 16) & 0xff;
const int green = (background_rgb >> 8) & 0xff;
@@ -208,39 +208,44 @@ void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT;
- if (!has_alpha || pic->a == NULL) return; // nothing to do
+ uint8_t* y_ptr = pic->y;
+ uint8_t* u_ptr = pic->u;
+ uint8_t* v_ptr = pic->v;
+ uint8_t* a_ptr = pic->a;
+ if (!has_alpha || a_ptr == NULL) return; // nothing to do
for (y = 0; y < pic->height; ++y) {
// Luma blending
- uint8_t* const y_ptr = pic->y + y * pic->y_stride;
- uint8_t* const a_ptr = pic->a + y * pic->a_stride;
for (x = 0; x < pic->width; ++x) {
- const int alpha = a_ptr[x];
+ const uint8_t alpha = a_ptr[x];
if (alpha < 0xff) {
- y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]);
+ y_ptr[x] = BLEND(Y0, y_ptr[x], alpha);
}
}
// Chroma blending every even line
if ((y & 1) == 0) {
- uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride;
- uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride;
uint8_t* const a_ptr2 =
(y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride;
for (x = 0; x < uv_width; ++x) {
// Average four alpha values into a single blending weight.
// TODO(skal): might lead to visible contouring. Can we do better?
- const int alpha =
+ const uint32_t alpha =
a_ptr[2 * x + 0] + a_ptr[2 * x + 1] +
a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1];
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
+ u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
+ v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
if (pic->width & 1) { // rightmost pixel
- const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
- u[x] = BLEND_10BIT(U0, u[x], alpha);
- v[x] = BLEND_10BIT(V0, v[x], alpha);
+ const uint32_t alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
+ u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
+ v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
+ } else {
+ u_ptr += pic->uv_stride;
+ v_ptr += pic->uv_stride;
}
- memset(a_ptr, 0xff, pic->width);
+ memset(a_ptr, 0xff, pic->width); // reset alpha value to opaque
+ a_ptr += pic->a_stride;
+ y_ptr += pic->y_stride;
}
} else {
uint32_t* argb = pic->argb;
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 624e8f8e66..92439febb8 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 0
+#define ENC_REV_VERSION 1
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -278,7 +278,7 @@ int VP8IteratorIsDone(const VP8EncIterator* const it);
// Import uncompressed samples from source.
// If tmp_32 is not NULL, import boundary samples too.
// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32);
// export decimated samples
void VP8IteratorExport(const VP8EncIterator* const it);
// go to next macroblock. Returns false if not finished.
@@ -515,4 +515,4 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8I_ENC_H_ */
+#endif // WEBP_ENC_VP8I_ENC_H_
diff --git a/thirdparty/libwebp/src/enc/vp8l_enc.c b/thirdparty/libwebp/src/enc/vp8l_enc.c
index a89184eb08..2713edcd95 100644
--- a/thirdparty/libwebp/src/enc/vp8l_enc.c
+++ b/thirdparty/libwebp/src/enc/vp8l_enc.c
@@ -809,6 +809,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
+ VP8LHistogramSetClear(histogram_image);
// Build histogram image and symbols from backward references.
VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
@@ -1248,14 +1249,20 @@ static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) {
const WebPPicture* const picture = enc->pic_;
const int width = picture->width;
const int height = picture->height;
- int y;
+
err = AllocateTransformBuffer(enc, width, height);
if (err != VP8_ENC_OK) return err;
if (enc->argb_content_ == kEncoderARGB) return VP8_ENC_OK;
- for (y = 0; y < height; ++y) {
- memcpy(enc->argb_ + y * width,
- picture->argb + y * picture->argb_stride,
- width * sizeof(*enc->argb_));
+
+ {
+ uint32_t* dst = enc->argb_;
+ const uint32_t* src = picture->argb;
+ int y;
+ for (y = 0; y < height; ++y) {
+ memcpy(dst, src, width * sizeof(*dst));
+ dst += width;
+ src += picture->argb_stride;
+ }
}
enc->argb_content_ = kEncoderARGB;
assert(enc->current_width_ == width);
diff --git a/thirdparty/libwebp/src/enc/vp8li_enc.h b/thirdparty/libwebp/src/enc/vp8li_enc.h
index 298a4a0014..d2d0fc509c 100644
--- a/thirdparty/libwebp/src/enc/vp8li_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8li_enc.h
@@ -115,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8LI_ENC_H_ */
+#endif // WEBP_ENC_VP8LI_ENC_H_
diff --git a/thirdparty/libwebp/src/mux/animi.h b/thirdparty/libwebp/src/mux/animi.h
index 88899532aa..34c45ba4da 100644
--- a/thirdparty/libwebp/src/mux/animi.h
+++ b/thirdparty/libwebp/src/mux/animi.h
@@ -40,4 +40,4 @@ int WebPAnimEncoderRefineRect(
} // extern "C"
#endif
-#endif /* WEBP_MUX_ANIMI_H_ */
+#endif // WEBP_MUX_ANIMI_H_
diff --git a/thirdparty/libwebp/src/mux/muxedit.c b/thirdparty/libwebp/src/mux/muxedit.c
index 7a027b3cb4..ccf14b2a0c 100644
--- a/thirdparty/libwebp/src/mux/muxedit.c
+++ b/thirdparty/libwebp/src/mux/muxedit.c
@@ -69,12 +69,12 @@ void WebPMuxDelete(WebPMux* mux) {
if (idx == (INDEX)) { \
err = ChunkAssignData(&chunk, data, copy_data, tag); \
if (err == WEBP_MUX_OK) { \
- err = ChunkSetNth(&chunk, (LIST), nth); \
+ err = ChunkSetHead(&chunk, (LIST)); \
} \
return err; \
}
-static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
+static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag,
const WebPData* const data, int copy_data) {
WebPChunk chunk;
WebPMuxError err = WEBP_MUX_NOT_FOUND;
@@ -190,7 +190,7 @@ WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
// Add the given chunk.
- return MuxSet(mux, tag, 1, chunk_data, copy_data);
+ return MuxSet(mux, tag, chunk_data, copy_data);
}
// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
@@ -202,7 +202,7 @@ static WebPMuxError AddDataToChunkList(
ChunkInit(&chunk);
err = ChunkAssignData(&chunk, data, copy_data, tag);
if (err != WEBP_MUX_OK) goto Err;
- err = ChunkSetNth(&chunk, chunk_list, 1);
+ err = ChunkSetHead(&chunk, chunk_list);
if (err != WEBP_MUX_OK) goto Err;
return WEBP_MUX_OK;
Err:
@@ -266,14 +266,14 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
- const WebPData* const bitstream = &info->bitstream;
// Sanity checks.
if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT;
if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;
- if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
+ if (info->bitstream.bytes == NULL ||
+ info->bitstream.size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
@@ -287,7 +287,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
}
MuxImageInit(&wpi);
- err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
+ err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
if (err != WEBP_MUX_OK) goto Err;
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
@@ -342,7 +342,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
// Set the animation parameters.
PutLE32(data, params->bgcolor);
PutLE16(data + 4, params->loop_count);
- return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
+ return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1);
}
WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
@@ -540,7 +540,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
PutLE24(data + 4, width - 1); // canvas width.
PutLE24(data + 7, height - 1); // canvas height.
- return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
+ return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1);
}
// Cleans up 'mux' by removing any unnecessary chunks.
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index 6b57eea30f..df9f74c63c 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -14,6 +14,7 @@
#ifndef WEBP_MUX_MUXI_H_
#define WEBP_MUX_MUXI_H_
+#include <assert.h>
#include <stdlib.h>
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
@@ -28,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
-#define MUX_REV_VERSION 0
+#define MUX_REV_VERSION 1
// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -126,11 +127,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
int copy_data, uint32_t tag);
-// Sets 'chunk' at nth position in the 'chunk_list'.
-// nth = 0 has the special meaning "last of the list".
+// Sets 'chunk' as the only element in 'chunk_list' if it is empty.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth);
+WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list);
+// Sets 'chunk' at last position in the 'chunk_list'.
+// On success ownership is transferred from 'chunk' to the 'chunk_list'.
+// *chunk_list also points towards the last valid element of the initial
+// *chunk_list.
+WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);
// Releases chunk and returns chunk->next_.
WebPChunk* ChunkRelease(WebPChunk* const chunk);
@@ -143,13 +147,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);
// Returns size of the chunk including chunk header and padding byte (if any).
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
+ assert(chunk_size <= MAX_CHUNK_PAYLOAD);
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
}
// Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
const size_t data_size = chunk->data_.size;
- assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size);
}
@@ -227,4 +231,4 @@ WebPMuxError MuxValidate(const WebPMux* const mux);
} // extern "C"
#endif
-#endif /* WEBP_MUX_MUXI_H_ */
+#endif // WEBP_MUX_MUXI_H_
diff --git a/thirdparty/libwebp/src/mux/muxinternal.c b/thirdparty/libwebp/src/mux/muxinternal.c
index 1473f100e5..b9ee6717d3 100644
--- a/thirdparty/libwebp/src/mux/muxinternal.c
+++ b/thirdparty/libwebp/src/mux/muxinternal.c
@@ -111,27 +111,6 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
return ((nth > 0) && (iter > 0)) ? NULL : first;
}
-// Outputs a pointer to 'prev_chunk->next_',
-// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
-// Returns true if nth chunk was found.
-static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
- WebPChunk*** const location) {
- uint32_t count = 0;
- assert(chunk_list != NULL);
- *location = chunk_list;
-
- while (*chunk_list != NULL) {
- WebPChunk* const cur_chunk = *chunk_list;
- ++count;
- if (count == nth) return 1; // Found.
- chunk_list = &cur_chunk->next_;
- *location = chunk_list;
- }
-
- // *chunk_list is ok to be NULL if adding at last location.
- return (nth == 0 || (count == nth - 1)) ? 1 : 0;
-}
-
//------------------------------------------------------------------------------
// Chunk writer methods.
@@ -156,11 +135,12 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
return WEBP_MUX_OK;
}
-WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
- uint32_t nth) {
+WebPMuxError ChunkSetHead(WebPChunk* const chunk,
+ WebPChunk** const chunk_list) {
WebPChunk* new_chunk;
- if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
+ assert(chunk_list != NULL);
+ if (*chunk_list != NULL) {
return WEBP_MUX_NOT_FOUND;
}
@@ -168,11 +148,26 @@ WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
chunk->owner_ = 0;
- new_chunk->next_ = *chunk_list;
+ new_chunk->next_ = NULL;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
}
+WebPMuxError ChunkAppend(WebPChunk* const chunk,
+ WebPChunk*** const chunk_list) {
+ assert(chunk_list != NULL && *chunk_list != NULL);
+
+ if (**chunk_list == NULL) {
+ ChunkSetHead(chunk, *chunk_list);
+ } else {
+ WebPChunk* last_chunk = **chunk_list;
+ while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_;
+ ChunkSetHead(chunk, &last_chunk->next_);
+ *chunk_list = &last_chunk->next_;
+ }
+ return WEBP_MUX_OK;
+}
+
//------------------------------------------------------------------------------
// Chunk deletion method(s).
@@ -232,9 +227,11 @@ void MuxImageInit(WebPMuxImage* const wpi) {
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
WebPMuxImage* next;
if (wpi == NULL) return NULL;
- ChunkDelete(wpi->header_);
- ChunkDelete(wpi->alpha_);
- ChunkDelete(wpi->img_);
+ // There should be at most one chunk of header_, alpha_, img_ but we call
+ // ChunkListDelete to be safe
+ ChunkListDelete(&wpi->header_);
+ ChunkListDelete(&wpi->alpha_);
+ ChunkListDelete(&wpi->img_);
ChunkListDelete(&wpi->unknown_);
next = wpi->next_;
diff --git a/thirdparty/libwebp/src/mux/muxread.c b/thirdparty/libwebp/src/mux/muxread.c
index 0b55286862..268f6acb53 100644
--- a/thirdparty/libwebp/src/mux/muxread.c
+++ b/thirdparty/libwebp/src/mux/muxread.c
@@ -59,6 +59,7 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
// Sanity checks.
if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE);
+ if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA;
{
const size_t chunk_disk_size = SizeWithPadding(chunk_size);
@@ -102,6 +103,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
const uint8_t* const last = bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
+ WebPChunk** unknown_chunk_list = &wpi->unknown_;
ChunkInit(&subchunk);
assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
@@ -116,7 +118,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
- ChunkSetNth(&subchunk, &wpi->header_, 1);
+ ChunkSetHead(&subchunk, &wpi->header_);
wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
// Rest of the chunks.
@@ -133,18 +135,23 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
switch (ChunkGetIdFromTag(subchunk.tag_)) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
- if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
+ if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
+ if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
+ if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail;
if (!MuxImageFinalize(wpi)) goto Fail;
wpi->is_partial_ = 0; // wpi is completely filled.
break;
case WEBP_CHUNK_UNKNOWN:
- if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
- // before some image chunks.
- if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
+ if (wpi->is_partial_) {
+ goto Fail; // Encountered an unknown chunk
+ // before some image chunks.
+ }
+ if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) {
+ goto Fail;
+ }
break;
default:
goto Fail;
@@ -175,6 +182,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
const uint8_t* data;
size_t size;
WebPChunk chunk;
+ // Stores the end of the chunk lists so that it is faster to append data to
+ // their ends.
+ WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL };
ChunkInit(&chunk);
// Sanity checks.
@@ -187,7 +197,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
size = bitstream->size;
if (data == NULL) return NULL;
- if (size < RIFF_HEADER_SIZE) return NULL;
+ if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL;
if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
return NULL;
@@ -196,8 +206,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
mux = WebPMuxNew();
if (mux == NULL) return NULL;
- if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;
-
tag = GetLE32(data + RIFF_HEADER_SIZE);
if (tag != kChunks[IDX_VP8].tag &&
tag != kChunks[IDX_VP8L].tag &&
@@ -205,13 +213,17 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
goto Err; // First chunk should be VP8, VP8L or VP8X.
}
- riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
- if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
- goto Err;
- } else {
- if (riff_size < size) { // Redundant data after last chunk.
- size = riff_size; // To make sure we don't read any data beyond mux_size.
- }
+ riff_size = GetLE32(data + TAG_SIZE);
+ if (riff_size > MAX_CHUNK_PAYLOAD) goto Err;
+
+ // Note this padding is historical and differs from demux.c which does not
+ // pad the file size.
+ riff_size = SizeWithPadding(riff_size);
+ if (riff_size < CHUNK_HEADER_SIZE) goto Err;
+ if (riff_size > size) goto Err;
+ // There's no point in reading past the end of the RIFF chunk.
+ if (size > riff_size + CHUNK_HEADER_SIZE) {
+ size = riff_size + CHUNK_HEADER_SIZE;
}
end = data + size;
@@ -226,7 +238,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
while (data != end) {
size_t data_size;
WebPChunkId id;
- WebPChunk** chunk_list;
if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
copy_data) != WEBP_MUX_OK) {
goto Err;
@@ -236,11 +247,11 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
switch (id) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
- if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
+ if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
- if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
+ if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err;
if (!MuxImageFinalize(wpi)) goto Err;
wpi->is_partial_ = 0; // wpi is completely filled.
PushImage:
@@ -257,9 +268,13 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
default: // A non-image chunk.
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
// getting all chunks of an image.
- chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
- if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
+ if (chunk_list_ends[id] == NULL) {
+ chunk_list_ends[id] =
+ MuxGetChunkListFromId(mux, id); // List to add this chunk.
+ }
+ if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
if (id == WEBP_CHUNK_VP8X) { // grab global specs
+ if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
mux->canvas_width_ = GetLE24(data + 12) + 1;
mux->canvas_height_ = GetLE24(data + 15) + 1;
}
@@ -385,6 +400,10 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
+ // There should be at most one alpha_ chunk and exactly one img_ chunk.
+ assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL);
+ assert(wpi->img_ != NULL && wpi->img_->next_ == NULL);
+
// Main RIFF header.
dst = MuxEmitRiffHeader(data, size);
diff --git a/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h b/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
index 2ccc6ed326..7e607f370a 100644
--- a/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_reader_inl_utils.h
@@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
} // extern "C"
#endif
-#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
+#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/bit_reader_utils.h b/thirdparty/libwebp/src/utils/bit_reader_utils.h
index 04f9804409..de810d402a 100644
--- a/thirdparty/libwebp/src/utils/bit_reader_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_reader_utils.h
@@ -182,4 +182,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_READER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/bit_writer_utils.h b/thirdparty/libwebp/src/utils/bit_writer_utils.h
index 2cf5976fe3..b9d5102a5a 100644
--- a/thirdparty/libwebp/src/utils/bit_writer_utils.h
+++ b/thirdparty/libwebp/src/utils/bit_writer_utils.h
@@ -151,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/filters_utils.h b/thirdparty/libwebp/src/utils/filters_utils.h
index 410f2fcdf2..61da66e212 100644
--- a/thirdparty/libwebp/src/utils/filters_utils.h
+++ b/thirdparty/libwebp/src/utils/filters_utils.h
@@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */
+#endif // WEBP_UTILS_FILTERS_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
index 3818a78b93..f65b6cdbb6 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
+++ b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.c
@@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) {
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength) {
- const int radius = 4 * strength / 100;
+ int radius = 4 * strength / 100;
+
if (strength < 0 || strength > 100) return 0;
if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
+
+ // limit the filter size to not exceed the image dimensions
+ if (2 * radius + 1 > width) radius = (width - 1) >> 1;
+ if (2 * radius + 1 > height) radius = (height - 1) >> 1;
+
if (radius > 0) {
SmoothParams p;
memset(&p, 0, sizeof(p));
diff --git a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
index f822107a72..327f19f336 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
+++ b/thirdparty/libwebp/src/utils/quant_levels_dec_utils.h
@@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/quant_levels_utils.h b/thirdparty/libwebp/src/utils/quant_levels_utils.h
index 75df2ba6a4..9ee3ea0075 100644
--- a/thirdparty/libwebp/src/utils/quant_levels_utils.h
+++ b/thirdparty/libwebp/src/utils/quant_levels_utils.h
@@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/random_utils.h b/thirdparty/libwebp/src/utils/random_utils.h
index 6d36c667e7..a5006f84f7 100644
--- a/thirdparty/libwebp/src/utils/random_utils.h
+++ b/thirdparty/libwebp/src/utils/random_utils.h
@@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */
+#endif // WEBP_UTILS_RANDOM_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/rescaler_utils.h b/thirdparty/libwebp/src/utils/rescaler_utils.h
index 8890e6fa13..ca41e42c4a 100644
--- a/thirdparty/libwebp/src/utils/rescaler_utils.h
+++ b/thirdparty/libwebp/src/utils/rescaler_utils.h
@@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */
+#endif // WEBP_UTILS_RESCALER_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/thread_utils.h b/thirdparty/libwebp/src/utils/thread_utils.h
index c8ae6c9033..29ad49f74b 100644
--- a/thirdparty/libwebp/src/utils/thread_utils.h
+++ b/thirdparty/libwebp/src/utils/thread_utils.h
@@ -87,4 +87,4 @@ WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void);
} // extern "C"
#endif
-#endif /* WEBP_UTILS_THREAD_UTILS_H_ */
+#endif // WEBP_UTILS_THREAD_UTILS_H_
diff --git a/thirdparty/libwebp/src/utils/utils.h b/thirdparty/libwebp/src/utils/utils.h
index 52921bf24e..da97b5d38f 100644
--- a/thirdparty/libwebp/src/utils/utils.h
+++ b/thirdparty/libwebp/src/utils/utils.h
@@ -175,4 +175,4 @@ WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_UTILS_H_ */
+#endif // WEBP_UTILS_UTILS_H_
diff --git a/thirdparty/libwebp/src/webp/decode.h b/thirdparty/libwebp/src/webp/decode.h
index 2165e96c95..95d31e7619 100644
--- a/thirdparty/libwebp/src/webp/decode.h
+++ b/thirdparty/libwebp/src/webp/decode.h
@@ -491,4 +491,4 @@ WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DECODE_H_ */
+#endif // WEBP_WEBP_DECODE_H_
diff --git a/thirdparty/libwebp/src/webp/demux.h b/thirdparty/libwebp/src/webp/demux.h
index 555d641338..846eeb15a9 100644
--- a/thirdparty/libwebp/src/webp/demux.h
+++ b/thirdparty/libwebp/src/webp/demux.h
@@ -360,4 +360,4 @@ WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DEMUX_H_ */
+#endif // WEBP_WEBP_DEMUX_H_
diff --git a/thirdparty/libwebp/src/webp/encode.h b/thirdparty/libwebp/src/webp/encode.h
index 7ec3543dc2..549cf07730 100644
--- a/thirdparty/libwebp/src/webp/encode.h
+++ b/thirdparty/libwebp/src/webp/encode.h
@@ -542,4 +542,4 @@ WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_ENCODE_H_ */
+#endif // WEBP_WEBP_ENCODE_H_
diff --git a/thirdparty/libwebp/src/webp/format_constants.h b/thirdparty/libwebp/src/webp/format_constants.h
index 329fc8a3b0..eca6981a47 100644
--- a/thirdparty/libwebp/src/webp/format_constants.h
+++ b/thirdparty/libwebp/src/webp/format_constants.h
@@ -84,4 +84,4 @@ typedef enum {
// overflow a uint32_t.
#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
-#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
+#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_
diff --git a/thirdparty/libwebp/src/webp/mux.h b/thirdparty/libwebp/src/webp/mux.h
index 28bb4a41c9..66096a92e0 100644
--- a/thirdparty/libwebp/src/webp/mux.h
+++ b/thirdparty/libwebp/src/webp/mux.h
@@ -527,4 +527,4 @@ WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_H_ */
+#endif // WEBP_WEBP_MUX_H_
diff --git a/thirdparty/libwebp/src/webp/mux_types.h b/thirdparty/libwebp/src/webp/mux_types.h
index b37e2c67aa..ceea77dfc6 100644
--- a/thirdparty/libwebp/src/webp/mux_types.h
+++ b/thirdparty/libwebp/src/webp/mux_types.h
@@ -95,4 +95,4 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_TYPES_H_ */
+#endif // WEBP_WEBP_MUX_TYPES_H_
diff --git a/thirdparty/libwebp/src/webp/types.h b/thirdparty/libwebp/src/webp/types.h
index 989a763f0d..0ce2622e41 100644
--- a/thirdparty/libwebp/src/webp/types.h
+++ b/thirdparty/libwebp/src/webp/types.h
@@ -49,4 +49,4 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
-#endif /* WEBP_WEBP_TYPES_H_ */
+#endif // WEBP_WEBP_TYPES_H_
diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h
index 990c8ee142..b3a7ee00c2 100644
--- a/thirdparty/tinyexr/tinyexr.h
+++ b/thirdparty/tinyexr/tinyexr.h
@@ -116,6 +116,8 @@ extern "C" {
#define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-7)
#define TINYEXR_ERROR_INVALID_HEADER (-8)
#define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-9)
+#define TINYEXR_ERROR_CANT_WRITE_FILE (-10)
+#define TINYEXR_ERROR_SERIALZATION_FAILED (-11)
// @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf }
@@ -279,9 +281,12 @@ extern int LoadEXR(float **out_rgba, int *width, int *height,
// Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
// value.
// Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
+// Use ZIP compression by default.
+// Returns negative value and may set error string in `err` when there's an
+// error
extern int SaveEXR(const float *data, const int width, const int height,
const int components, const int save_as_fp16,
- const char *filename);
+ const char *filename, const char **err);
// Initialize EXRHeader struct
extern void InitEXRHeader(EXRHeader *exr_header);
@@ -400,9 +405,9 @@ extern int SaveEXRImageToFile(const EXRImage *image,
// Saves multi-channel, single-frame OpenEXR image to a memory.
// Image is compressed using EXRImage.compression value.
-// Return the number of bytes if succes.
-// Returns negative value and may set error string in `err` when there's an
-// error
+// Return the number of bytes if success.
+// Return zero and will set error string in `err` when there's an
+// error.
// When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern size_t SaveEXRImageToMemory(const EXRImage *image,
@@ -524,15 +529,23 @@ namespace miniz {
#if __has_warning("-Wcomma")
#pragma clang diagnostic ignored "-Wcomma"
#endif
+
#if __has_warning("-Wmacro-redefined")
#pragma clang diagnostic ignored "-Wmacro-redefined"
#endif
+
#if __has_warning("-Wcast-qual")
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
+
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
+
+#if __has_warning("-Wtautological-constant-compare")
+#pragma clang diagnostic ignored "-Wtautological-constant-compare"
+#endif
+
#endif
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
@@ -2518,10 +2531,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
tinfl_status status = TINFL_STATUS_FAILED;
mz_uint32 num_bits, dist, counter, num_extra;
tinfl_bit_buf_t bit_buf;
- const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
- pIn_buf_next + *pIn_buf_size;
- mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
- pOut_buf_next + *pOut_buf_size;
+ const mz_uint8 *pIn_buf_cur = pIn_buf_next,
+ *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
+ mz_uint8 *pOut_buf_cur = pOut_buf_next,
+ *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
size_t out_buf_size_mask =
(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
? (size_t)-1
@@ -2938,9 +2951,8 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
tinfl_status status = tinfl_decompress(
&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
(mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
- &dst_buf_size,
- (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
+ &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
MZ_FREE(pBuf);
*pOut_len = 0;
@@ -2993,8 +3005,9 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
tinfl_status status =
tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
&in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
- (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
+ (flags &
+ ~(TINFL_FLAG_HAS_MORE_INPUT |
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
in_buf_ofs += in_buf_size;
if ((dst_buf_size) &&
(!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
@@ -3119,9 +3132,7 @@ static const mz_uint8 s_tdefl_large_dist_extra[128] = {
// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
// values.
-typedef struct {
- mz_uint16 m_key, m_sym_index;
-} tdefl_sym_freq;
+typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
tdefl_sym_freq *pSyms0,
tdefl_sym_freq *pSyms1) {
@@ -5265,10 +5276,9 @@ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
pStat->m_comment_size = n;
- memcpy(pStat->m_comment,
- p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
- MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
- MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
+ memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
+ MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
+ MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
n);
pStat->m_comment[n] = '\0';
@@ -10087,9 +10097,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
unsigned short *outLine =
reinterpret_cast<unsigned short *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
for (int u = 0; u < width; u++) {
@@ -10105,9 +10116,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
} else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
float *outLine = reinterpret_cast<float *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
@@ -10140,9 +10152,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
float *outLine = reinterpret_cast<float *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
@@ -10167,9 +10180,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
unsigned int *outLine =
reinterpret_cast<unsigned int *>(out_images[c]);
if (line_order == 0) {
- outLine += (y + v) * x_stride;
+ outLine += (size_t(y) + v) * size_t(x_stride);
} else {
- outLine += (height - 1 - (y + v)) * x_stride;
+ outLine +=
+ (size_t(height) - 1 - (size_t(y) + v)) * size_t(x_stride);
}
for (int u = 0; u < width; u++) {
@@ -11133,21 +11147,53 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
}
}
- if ((idxA == 0) && (idxR == -1) && (idxG == -1) && (idxB == -1)) {
- // Alpha channel only.
+ if (exr_header.num_channels == 1) {
+ // Grayscale channel only.
- if (exr_header.tiled) {
- // todo.implement this
- }
(*out_rgba) = reinterpret_cast<float *>(
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
- for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
- (*out_rgba)[4 * i + 0] = val;
- (*out_rgba)[4 * i + 1] = val;
- (*out_rgba)[4 * i + 2] = val;
- (*out_rgba)[4 * i + 3] = val;
+
+ if (exr_header.tiled) {
+ // todo.implement this
+
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++) {
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
+
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ (*out_rgba)[4 * idx + 3] =
+ reinterpret_cast<float **>(src)[0][srcIdx];
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
+ (*out_rgba)[4 * i + 0] = val;
+ (*out_rgba)[4 * i + 1] = val;
+ (*out_rgba)[4 * i + 2] = val;
+ (*out_rgba)[4 * i + 3] = val;
+ }
}
} else {
// Assume RGB(A)
@@ -11179,7 +11225,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
static_cast<size_t>(exr_image.height)));
if (exr_header.tiled) {
for (int it = 0; it < exr_image.num_tiles; it++) {
- for (int j = 0; j < exr_header.tile_size_y; j++)
+ for (int j = 0; j < exr_header.tile_size_y; j++) {
for (int i = 0; i < exr_header.tile_size_x; i++) {
const int ii =
exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
@@ -11209,6 +11255,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
(*out_rgba)[4 * idx + 3] = 1.0;
}
}
+ }
}
} else {
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
@@ -11356,18 +11403,53 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
static_cast<size_t>(exr_image.height)));
- for (int i = 0; i < exr_image.width * exr_image.height; i++) {
- (*out_rgba)[4 * i + 0] =
- reinterpret_cast<float **>(exr_image.images)[idxR][i];
- (*out_rgba)[4 * i + 1] =
- reinterpret_cast<float **>(exr_image.images)[idxG][i];
- (*out_rgba)[4 * i + 2] =
- reinterpret_cast<float **>(exr_image.images)[idxB][i];
- if (idxA != -1) {
- (*out_rgba)[4 * i + 3] =
- reinterpret_cast<float **>(exr_image.images)[idxA][i];
- } else {
- (*out_rgba)[4 * i + 3] = 1.0;
+ if (exr_header.tiled) {
+ for (int it = 0; it < exr_image.num_tiles; it++) {
+ for (int j = 0; j < exr_header.tile_size_y; j++)
+ for (int i = 0; i < exr_header.tile_size_x; i++) {
+ const int ii =
+ exr_image.tiles[it].offset_x * exr_header.tile_size_x + i;
+ const int jj =
+ exr_image.tiles[it].offset_y * exr_header.tile_size_y + j;
+ const int idx = ii + jj * exr_image.width;
+
+ // out of region check.
+ if (ii >= exr_image.width) {
+ continue;
+ }
+ if (jj >= exr_image.height) {
+ continue;
+ }
+ const int srcIdx = i + j * exr_header.tile_size_x;
+ unsigned char **src = exr_image.tiles[it].images;
+ (*out_rgba)[4 * idx + 0] =
+ reinterpret_cast<float **>(src)[idxR][srcIdx];
+ (*out_rgba)[4 * idx + 1] =
+ reinterpret_cast<float **>(src)[idxG][srcIdx];
+ (*out_rgba)[4 * idx + 2] =
+ reinterpret_cast<float **>(src)[idxB][srcIdx];
+ if (idxA != -1) {
+ (*out_rgba)[4 * idx + 3] =
+ reinterpret_cast<float **>(src)[idxA][srcIdx];
+ } else {
+ (*out_rgba)[4 * idx + 3] = 1.0;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < exr_image.width * exr_image.height; i++) {
+ (*out_rgba)[4 * i + 0] =
+ reinterpret_cast<float **>(exr_image.images)[idxR][i];
+ (*out_rgba)[4 * i + 1] =
+ reinterpret_cast<float **>(exr_image.images)[idxG][i];
+ (*out_rgba)[4 * i + 2] =
+ reinterpret_cast<float **>(exr_image.images)[idxB][i];
+ if (idxA != -1) {
+ (*out_rgba)[4 * i + 3] =
+ reinterpret_cast<float **>(exr_image.images)[idxA][i];
+ } else {
+ (*out_rgba)[4 * i + 3] = 1.0;
+ }
}
}
@@ -11452,7 +11534,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
if (exr_image == NULL || memory_out == NULL ||
exr_header->compression_type < 0) {
tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToMemory", err);
- return 0; // @fixme
+ return 0;
}
#if !TINYEXR_USE_PIZ
@@ -11623,8 +11705,6 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
sizeof(
tinyexr::tinyexr_int64); // sizeof(header) + sizeof(offsetTable)
- std::vector<unsigned char> data;
-
std::vector<std::vector<unsigned char> > data_list(
static_cast<size_t>(num_blocks));
std::vector<size_t> channel_offset_list(
@@ -11863,9 +11943,9 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
} else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
#if TINYEXR_USE_PIZ
unsigned int bufLen =
- 1024 + static_cast<unsigned int>(
- 1.2 * static_cast<unsigned int>(
- buf.size())); // @fixme { compute good bound. }
+ 8192 + static_cast<unsigned int>(
+ 2 * static_cast<unsigned int>(
+ buf.size())); // @fixme { compute good bound. }
std::vector<unsigned char> block(bufLen);
unsigned int outSize = static_cast<unsigned int>(block.size());
@@ -11924,13 +12004,12 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
} // omp parallel
for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
- data.insert(data.end(), data_list[i].begin(), data_list[i].end());
-
offsets[i] = offset;
tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64 *>(&offsets[i]));
offset += data_list[i].size();
}
+ size_t totalSize = static_cast<size_t>(offset);
{
memory.insert(
memory.end(), reinterpret_cast<unsigned char *>(&offsets.at(0)),
@@ -11938,14 +12017,21 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
sizeof(tinyexr::tinyexr_uint64) * static_cast<size_t>(num_blocks));
}
- { memory.insert(memory.end(), data.begin(), data.end()); }
-
- assert(memory.size() > 0);
+ if ( memory.size() == 0 ) {
+ tinyexr::SetErrorMessage("Output memory size is zero", err);
+ return 0;
+ }
- (*memory_out) = static_cast<unsigned char *>(malloc(memory.size()));
+ (*memory_out) = static_cast<unsigned char *>(malloc(totalSize));
memcpy((*memory_out), &memory.at(0), memory.size());
+ unsigned char *memory_ptr = *memory_out + memory.size();
- return memory.size(); // OK
+ for (size_t i = 0; i < static_cast<size_t>(num_blocks); i++) {
+ memcpy(memory_ptr, &data_list[i].at(0), data_list[i].size());
+ memory_ptr += data_list[i].size();
+ }
+
+ return totalSize; // OK
}
int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
@@ -11960,7 +12046,7 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
err);
- return 0;
+ return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
}
#endif
@@ -11968,7 +12054,7 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
err);
- return 0;
+ return TINYEXR_ERROR_UNSUPPORTED_FEATURE;
}
#endif
@@ -11980,19 +12066,28 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
#endif
if (!fp) {
tinyexr::SetErrorMessage("Cannot write a file", err);
- return TINYEXR_ERROR_CANT_OPEN_FILE;
+ return TINYEXR_ERROR_CANT_WRITE_FILE;
}
unsigned char *mem = NULL;
size_t mem_size = SaveEXRImageToMemory(exr_image, exr_header, &mem, err);
+ if (mem_size == 0) {
+ return TINYEXR_ERROR_SERIALZATION_FAILED;
+ }
+ size_t written_size = 0;
if ((mem_size > 0) && mem) {
- fwrite(mem, 1, mem_size, fp);
+ written_size = fwrite(mem, 1, mem_size, fp);
}
free(mem);
fclose(fp);
+ if (written_size != mem_size) {
+ tinyexr::SetErrorMessage("Cannot write a file", err);
+ return TINYEXR_ERROR_CANT_WRITE_FILE;
+ }
+
return TINYEXR_SUCCESS;
}
@@ -12861,20 +12956,27 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
}
int SaveEXR(const float *data, int width, int height, int components,
- const int save_as_fp16, const char *outfilename) {
+ const int save_as_fp16, const char *outfilename, const char **err) {
if ((components == 1) || components == 3 || components == 4) {
// OK
} else {
+ std::stringstream ss;
+ ss << "Unsupported component value : " << components << std::endl;
+
+ tinyexr::SetErrorMessage(ss.str(), err);
return TINYEXR_ERROR_INVALID_ARGUMENT;
}
- // Assume at least 16x16 pixels.
- if (width < 16) return TINYEXR_ERROR_INVALID_ARGUMENT;
- if (height < 16) return TINYEXR_ERROR_INVALID_ARGUMENT;
-
EXRHeader header;
InitEXRHeader(&header);
+ if ((width < 16) && (height < 16)) {
+ // No compression for small image.
+ header.compression_type = TINYEXR_COMPRESSIONTYPE_NONE;
+ } else {
+ header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
+ }
+
EXRImage image;
InitEXRImage(&image);
@@ -12980,8 +13082,7 @@ int SaveEXR(const float *data, int width, int height, int components,
}
}
- const char *err;
- int ret = SaveEXRImageToFile(&image, &header, outfilename, &err);
+ int ret = SaveEXRImageToFile(&image, &header, outfilename, err);
if (ret != TINYEXR_SUCCESS) {
return ret;
}