summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub21
-rw-r--r--core/bind/core_bind.cpp6
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/command_queue_mt.h44
-rw-r--r--core/dvector.h8
-rw-r--r--core/global_config.cpp8
-rw-r--r--core/image.cpp184
-rw-r--r--core/image.h24
-rw-r--r--core/io/compression.cpp20
-rw-r--r--core/io/compression.h9
-rw-r--r--core/io/file_access_compressed.cpp2
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/http_client.cpp14
-rw-r--r--core/math/a_star.cpp2
-rw-r--r--core/math/math_funcs.h17
-rw-r--r--core/script_language.h2
-rw-r--r--core/translation.h2
17 files changed, 321 insertions, 46 deletions
diff --git a/core/SCsub b/core/SCsub
index fd3f57dd7c..da2403f1d3 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -83,6 +83,25 @@ thirdparty_minizip_sources = [
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
+thirdparty_zstd_dir = "#thirdparty/zstd/"
+thirdparty_zstd_sources = [
+ "common/entropy_common.c",
+ "common/error_private.c",
+ "common/fse_decompress.c",
+ "common/pool.c",
+ "common/threading.c",
+ "common/xxhash.c",
+ "common/zstd_common.c",
+ "compress/fse_compress.c",
+ "compress/huf_compress.c",
+ "compress/zstd_compress.c",
+ "compress/zstdmt_compress.c",
+ "decompress/huf_decompress.c",
+ "decompress/zstd_decompress.c",
+]
+thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
+env.add_source_files(env.core_sources, thirdparty_zstd_sources)
+
# Godot's own sources
env.add_source_files(env.core_sources, "*.cpp")
@@ -104,5 +123,5 @@ SConscript('helper/SCsub')
# Build it all as a library
lib = env.Library("core", env.core_sources)
env.Prepend(LIBS=[lib])
-
+env.Append(CPPPATH=["#thirdparty/zstd", "#thirdparty/zstd/common"])
Export('env')
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 2752391901..d81ccf0265 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -2532,6 +2532,10 @@ Dictionary _Engine::get_version_info() const {
return Engine::get_singleton()->get_version_info();
}
+bool _Engine::is_in_fixed_frame() const {
+ return Engine::get_singleton()->is_in_fixed_frame();
+}
+
void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_iterations_per_second", "iterations_per_second"), &_Engine::set_iterations_per_second);
@@ -2550,6 +2554,8 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_main_loop:MainLoop"), &_Engine::get_main_loop);
ClassDB::bind_method(D_METHOD("get_version_info"), &_Engine::get_version_info);
+
+ ClassDB::bind_method(D_METHOD("is_in_fixed_frame"), &_Engine::is_in_fixed_frame);
}
_Engine *_Engine::singleton = NULL;
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index e48b5c85ad..a2fb6c966c 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -634,6 +634,8 @@ public:
Dictionary get_version_info() const;
+ bool is_in_fixed_frame() const;
+
_Engine();
};
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index 83c90a925c..2e0c478108 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -207,6 +207,26 @@ class CommandQueueMT {
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
};
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>
+ struct Command11 : public CommandBase {
+
+ T *instance;
+ M method;
+ typename GetSimpleTypeT<P1>::type_t p1;
+ typename GetSimpleTypeT<P2>::type_t p2;
+ typename GetSimpleTypeT<P3>::type_t p3;
+ typename GetSimpleTypeT<P4>::type_t p4;
+ typename GetSimpleTypeT<P5>::type_t p5;
+ typename GetSimpleTypeT<P6>::type_t p6;
+ typename GetSimpleTypeT<P7>::type_t p7;
+ typename GetSimpleTypeT<P8>::type_t p8;
+ typename GetSimpleTypeT<P9>::type_t p9;
+ typename GetSimpleTypeT<P10>::type_t p10;
+ typename GetSimpleTypeT<P11>::type_t p11;
+
+ virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
+ };
+
/* comands that return */
template <class T, class M, class R>
@@ -862,6 +882,30 @@ public:
if (sync) sync->post();
}
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>
+ void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {
+
+ Command11<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> *cmd = allocate_and_lock<Command11<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> >();
+
+ cmd->instance = p_instance;
+ cmd->method = p_method;
+ cmd->p1 = p1;
+ cmd->p2 = p2;
+ cmd->p3 = p3;
+ cmd->p4 = p4;
+ cmd->p5 = p5;
+ cmd->p6 = p6;
+ cmd->p7 = p7;
+ cmd->p8 = p8;
+ cmd->p9 = p9;
+ cmd->p10 = p10;
+ cmd->p11 = p11;
+
+ unlock();
+
+ if (sync) sync->post();
+ }
+
/*** PUSH AND RET COMMANDS ***/
template <class T, class M, class R>
diff --git a/core/dvector.h b/core/dvector.h
index 2e951b9661..4584a300f9 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -92,6 +92,7 @@ class PoolVector {
// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all
+ // Refcount should not be zero, otherwise it's a misuse of COW
if (alloc->refcount.get() == 1)
return; //nothing to do
@@ -216,7 +217,12 @@ class PoolVector {
{
int cur_elements = alloc->size / sizeof(T);
- Write w = write();
+
+ // Don't use write() here because it could otherwise provoke COW,
+ // which is not desirable here because we are destroying the last reference anyways
+ Write w;
+ // Reference to still prevent other threads from touching the alloc
+ w._ref(alloc);
for (int i = 0; i < cur_elements; i++) {
diff --git a/core/global_config.cpp b/core/global_config.cpp
index 896384d9c8..ba0a7f3e31 100644
--- a/core/global_config.cpp
+++ b/core/global_config.cpp
@@ -39,6 +39,8 @@
#include "os/os.h"
#include "variant_parser.h"
+#include <zlib.h>
+
#define FORMAT_VERSION 3
GlobalConfig *GlobalConfig::singleton = NULL;
@@ -967,6 +969,12 @@ GlobalConfig::GlobalConfig() {
custom_prop_info["physics/2d/thread_model"] = PropertyInfo(Variant::INT, "physics/2d/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
GLOBAL_DEF("debug/profiler/max_functions", 16384);
+
+ GLOBAL_DEF("compression/zstd/compression_level", 3);
+ custom_prop_info["compression/zstd/compression_level"] = PropertyInfo(Variant::INT, "compression/zstd/compression_level", PROPERTY_HINT_RANGE, "1,22,1");
+ GLOBAL_DEF("compression/zlib/compression_level", Z_DEFAULT_COMPRESSION);
+ custom_prop_info["compression/zlib/compression_level"] = PropertyInfo(Variant::INT, "compression/zlib/compression_level", PROPERTY_HINT_RANGE, "-1,9,1");
+
using_datapack = false;
}
diff --git a/core/image.cpp b/core/image.cpp
index 686735c906..ec21260b19 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1483,23 +1483,23 @@ Error Image::decompress() {
_image_decompress_bc(this);
else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc)
_image_decompress_pvrtc(this);
- else if (format == FORMAT_ETC && _image_decompress_etc)
- _image_decompress_etc(this);
- else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc)
+ else if (format == FORMAT_ETC && _image_decompress_etc1)
+ _image_decompress_etc1(this);
+ else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RGB8A1 && _image_decompress_etc1)
_image_decompress_etc2(this);
else
return ERR_UNAVAILABLE;
return OK;
}
-Error Image::compress(CompressMode p_mode, bool p_for_srgb) {
+Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) {
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
- _image_compress_bc_func(this, p_for_srgb);
+ _image_compress_bc_func(this, p_source);
} break;
case COMPRESS_PVRTC2: {
@@ -1513,13 +1513,13 @@ Error Image::compress(CompressMode p_mode, bool p_for_srgb) {
} break;
case COMPRESS_ETC: {
- ERR_FAIL_COND_V(!_image_compress_etc_func, ERR_UNAVAILABLE);
- _image_compress_etc_func(this);
+ ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE);
+ _image_compress_etc1_func(this, p_lossy_quality);
} break;
case COMPRESS_ETC2: {
- ERR_FAIL_COND_V(!_image_compress_etc_func, ERR_UNAVAILABLE);
- _image_compress_etc_func(this);
+ ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
+ _image_compress_etc2_func(this, p_lossy_quality, p_source);
} break;
}
@@ -1612,11 +1612,11 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(format != p_src->format);
- Rect2i local_src_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest + p_src_rect.position, p_src_rect.size));
-
- if (local_src_rect.size.x <= 0 || local_src_rect.size.y <= 0)
+ Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return;
- Rect2i src_rect(p_src_rect.position + (local_src_rect.position - p_dest), local_src_rect.size);
+
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
PoolVector<uint8_t>::Write wp = data.write();
uint8_t *dst_data_ptr = wp.ptr();
@@ -1626,15 +1626,15 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
int pixel_size = get_format_pixel_size(format);
- for (int i = 0; i < src_rect.size.y; i++) {
+ for (int i = 0; i < dest_rect.size.y; i++) {
- for (int j = 0; j < src_rect.size.x; j++) {
+ for (int j = 0; j < dest_rect.size.x; j++) {
- int src_x = src_rect.position.x + j;
- int src_y = src_rect.position.y + i;
+ int src_x = clipped_src_rect.position.x + j;
+ int src_y = clipped_src_rect.position.y + i;
- int dst_x = local_src_rect.position.x + j;
- int dst_y = local_src_rect.position.y + i;
+ int dst_x = dest_rect.position.x + j;
+ int dst_y = dest_rect.position.y + i;
const uint8_t *src = &src_data_ptr[(src_y * p_src->width + src_x) * pixel_size];
uint8_t *dst = &dst_data_ptr[(dst_y * width + dst_x) * pixel_size];
@@ -1646,17 +1646,144 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
}
}
+void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
+
+ ERR_FAIL_COND(p_src.is_null());
+ int dsize = data.size();
+ int srcdsize = p_src->data.size();
+ ERR_FAIL_COND(dsize == 0);
+ ERR_FAIL_COND(srcdsize == 0);
+ ERR_FAIL_COND(format != p_src->format);
+
+ Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ return;
+
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+
+ lock();
+ Ref<Image> img = p_src;
+ img->lock();
+
+ for (int i = 0; i < dest_rect.size.y; i++) {
+
+ for (int j = 0; j < dest_rect.size.x; j++) {
+
+ int src_x = clipped_src_rect.position.x + j;
+ int src_y = clipped_src_rect.position.y + i;
+
+ int dst_x = dest_rect.position.x + j;
+ int dst_y = dest_rect.position.y + i;
+
+ Color sc = img->get_pixel(src_x, src_y);
+ Color dc = get_pixel(dst_x, dst_y);
+ dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
+ dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
+ dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
+ dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
+ put_pixel(dst_x, dst_y, dc);
+ }
+ }
+
+ img->unlock();
+ unlock();
+}
+
+void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) {
+
+ ERR_FAIL_COND(p_src.is_null());
+ ERR_FAIL_COND(p_mask.is_null());
+ int dsize = data.size();
+ int srcdsize = p_src->data.size();
+ int maskdsize = p_mask->data.size();
+ ERR_FAIL_COND(dsize == 0);
+ ERR_FAIL_COND(srcdsize == 0);
+ ERR_FAIL_COND(maskdsize == 0);
+ ERR_FAIL_COND(p_src->width != p_mask->width);
+ ERR_FAIL_COND(p_src->height != p_mask->height);
+ ERR_FAIL_COND(format != p_src->format);
+
+ Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect);
+ if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
+ return;
+
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+
+ lock();
+ Ref<Image> img = p_src;
+ Ref<Image> msk = p_mask;
+ img->lock();
+ msk->lock();
+
+ for (int i = 0; i < dest_rect.size.y; i++) {
+
+ for (int j = 0; j < dest_rect.size.x; j++) {
+
+ int src_x = clipped_src_rect.position.x + j;
+ int src_y = clipped_src_rect.position.y + i;
+
+ // If the mask's pixel is transparent then we skip it
+ //Color c = msk->get_pixel(src_x, src_y);
+ //if (c.a == 0) continue;
+ if (msk->get_pixel(src_x, src_y).a != 0) {
+
+ int dst_x = dest_rect.position.x + j;
+ int dst_y = dest_rect.position.y + i;
+
+ Color sc = img->get_pixel(src_x, src_y);
+ Color dc = get_pixel(dst_x, dst_y);
+ dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r);
+ dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g);
+ dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b);
+ dc.a = (double)(sc.a + dc.a * (1.0 - sc.a));
+ put_pixel(dst_x, dst_y, dc);
+ }
+ }
+ }
+
+ msk->unlock();
+ img->unlock();
+ unlock();
+}
+
+void Image::fill(const Color &c) {
+
+ lock();
+
+ PoolVector<uint8_t>::Write wp = data.write();
+ uint8_t *dst_data_ptr = wp.ptr();
+
+ int pixel_size = get_format_pixel_size(format);
+
+ // put first pixel with the format-aware API
+ put_pixel(0, 0, c);
+
+ for (int y = 0; y < height; y++) {
+
+ for (int x = 0; x < width; x++) {
+
+ uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size];
+
+ for (int k = 0; k < pixel_size; k++) {
+ dst[k] = dst_data_ptr[k];
+ }
+ }
+ }
+
+ unlock();
+}
+
Ref<Image> (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL;
Ref<Image> (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL;
-void (*Image::_image_compress_bc_func)(Image *, bool) = NULL;
+void (*Image::_image_compress_bc_func)(Image *, Image::CompressSource) = NULL;
void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
void (*Image::_image_compress_pvrtc4_func)(Image *) = NULL;
-void (*Image::_image_compress_etc_func)(Image *) = NULL;
-void (*Image::_image_compress_etc2_func)(Image *) = NULL;
+void (*Image::_image_compress_etc1_func)(Image *, float) = NULL;
+void (*Image::_image_compress_etc2_func)(Image *, float, Image::CompressSource) = NULL;
void (*Image::_image_decompress_pvrtc)(Image *) = NULL;
void (*Image::_image_decompress_bc)(Image *) = NULL;
-void (*Image::_image_decompress_etc)(Image *) = NULL;
+void (*Image::_image_decompress_etc1)(Image *) = NULL;
void (*Image::_image_decompress_etc2)(Image *) = NULL;
PoolVector<uint8_t> (*Image::lossy_packer)(const Ref<Image> &, float) = NULL;
@@ -1712,7 +1839,7 @@ void Image::unlock() {
write_lock = PoolVector<uint8_t>::Write();
}
-Color Image::get_pixel(int p_x, int p_y) {
+Color Image::get_pixel(int p_x, int p_y) const {
uint8_t *ptr = write_lock.ptr();
#ifdef DEBUG_ENABLED
@@ -2072,6 +2199,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("normalmap_to_xy"), &Image::normalmap_to_xy);
ClassDB::bind_method(D_METHOD("blit_rect", "src:Image", "src_rect", "dst"), &Image::blit_rect);
+ ClassDB::bind_method(D_METHOD("blend_rect", "src:Image", "src_rect", "dst"), &Image::blend_rect);
+ ClassDB::bind_method(D_METHOD("blend_rect_mask", "src:Image", "mask:Image", "src_rect", "dst"), &Image::blend_rect_mask);
+ ClassDB::bind_method(D_METHOD("fill", "color"), &Image::fill);
ClassDB::bind_method(D_METHOD("get_used_rect"), &Image::get_used_rect);
ClassDB::bind_method(D_METHOD("get_rect:Image", "rect"), &Image::get_rect);
@@ -2140,9 +2270,13 @@ void Image::_bind_methods() {
BIND_CONSTANT(COMPRESS_PVRTC4);
BIND_CONSTANT(COMPRESS_ETC);
BIND_CONSTANT(COMPRESS_ETC2);
+
+ BIND_CONSTANT(COMPRESS_SOURCE_GENERIC);
+ BIND_CONSTANT(COMPRESS_SOURCE_SRGB);
+ BIND_CONSTANT(COMPRESS_SOURCE_NORMAL);
}
-void Image::set_compress_bc_func(void (*p_compress_func)(Image *, bool)) {
+void Image::set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource)) {
_image_compress_bc_func = p_compress_func;
}
diff --git a/core/image.h b/core/image.h
index e3174a2899..3323afdc4b 100644
--- a/core/image.h
+++ b/core/image.h
@@ -109,20 +109,26 @@ public:
/* INTERPOLATE GAUSS */
};
+ enum CompressSource {
+ COMPRESS_SOURCE_GENERIC,
+ COMPRESS_SOURCE_SRGB,
+ COMPRESS_SOURCE_NORMAL
+ };
+
//some functions provided by something else
static Ref<Image> (*_png_mem_loader_func)(const uint8_t *p_png, int p_size);
static Ref<Image> (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size);
- static void (*_image_compress_bc_func)(Image *, bool p_srgb);
+ static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
- static void (*_image_compress_etc_func)(Image *);
- static void (*_image_compress_etc2_func)(Image *);
+ static void (*_image_compress_etc1_func)(Image *, float);
+ static void (*_image_compress_etc2_func)(Image *, float, CompressSource p_source);
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
- static void (*_image_decompress_etc)(Image *);
+ static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
static PoolVector<uint8_t> (*lossy_packer)(const Ref<Image> &p_image, float p_quality);
@@ -267,7 +273,7 @@ public:
COMPRESS_ETC2,
};
- Error compress(CompressMode p_mode = COMPRESS_S3TC, bool p_for_srgb = false);
+ Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
Error decompress();
bool is_compressed() const;
@@ -277,11 +283,14 @@ public:
void normalmap_to_xy();
void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
+ void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
+ void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);
+ void fill(const Color &c);
Rect2 get_used_rect() const;
Ref<Image> get_rect(const Rect2 &p_area) const;
- static void set_compress_bc_func(void (*p_compress_func)(Image *, bool));
+ static void set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource));
static String get_format_name(Format p_format);
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
@@ -304,7 +313,7 @@ public:
DetectChannels get_detected_channels();
- Color get_pixel(int p_x, int p_y);
+ Color get_pixel(int p_x, int p_y) const;
void put_pixel(int p_x, int p_y, const Color &p_color);
void copy_internals_from(const Ref<Image> &p_image) {
@@ -322,6 +331,7 @@ public:
VARIANT_ENUM_CAST(Image::Format)
VARIANT_ENUM_CAST(Image::Interpolation)
VARIANT_ENUM_CAST(Image::CompressMode)
+VARIANT_ENUM_CAST(Image::CompressSource)
VARIANT_ENUM_CAST(Image::AlphaMode)
#endif
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 662411a62e..f806c4da6d 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -28,11 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "compression.h"
-
+#include "global_config.h"
#include "os/copymem.h"
#include "zip_io.h"
#include "thirdparty/misc/fastlz.h"
+#include "thirdparty/zstd/zstd.h"
#include <zlib.h>
@@ -57,7 +58,8 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,
strm.zalloc = zipio_alloc;
strm.zfree = zipio_free;
strm.opaque = Z_NULL;
- int err = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
+ int level = GLOBAL_GET("compression/zlib/compression_level");
+ int err = deflateInit(&strm, level);
if (err != Z_OK)
return -1;
@@ -76,6 +78,12 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,
return aout;
} break;
+ case MODE_ZSTD: {
+
+ int max_dst_size = get_max_compressed_buffer_size(p_src_size, MODE_ZSTD);
+ int level = GLOBAL_GET("compression/zstd/compression_level");
+ return ZSTD_compress(p_dst, max_dst_size, p_src, p_src_size, level);
+ } break;
}
ERR_FAIL_V(-1);
@@ -105,6 +113,10 @@ int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) {
deflateEnd(&strm);
return aout;
} break;
+ case MODE_ZSTD: {
+
+ return ZSTD_compressBound(p_src_size);
+ } break;
}
ERR_FAIL_V(-1);
@@ -148,6 +160,10 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
ERR_FAIL_COND_V(err != Z_STREAM_END, -1);
return total;
} break;
+ case MODE_ZSTD: {
+
+ return ZSTD_decompress(p_dst, p_dst_max_size, p_src, p_src_size);
+ } break;
}
ERR_FAIL_V(-1);
diff --git a/core/io/compression.h b/core/io/compression.h
index a982a074b1..742f0f4d68 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -36,12 +36,13 @@ class Compression {
public:
enum Mode {
MODE_FASTLZ,
- MODE_DEFLATE
+ MODE_DEFLATE,
+ MODE_ZSTD
};
- static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_FASTLZ);
- static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_FASTLZ);
- static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_FASTLZ);
+ static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
+ static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD);
+ static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
Compression();
};
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 4c6e8f5507..4e802579c6 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -369,7 +369,7 @@ FileAccessCompressed::FileAccessCompressed() {
f = NULL;
magic = "GCMP";
block_size = 16384;
- cmode = Compression::MODE_DEFLATE;
+ cmode = Compression::MODE_ZSTD;
writing = false;
write_ptr = 0;
write_buffer_size = 0;
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 6af9d9b6ca..340c298a0f 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -64,7 +64,7 @@ class FileAccessCompressed : public FileAccess {
FileAccess *f;
public:
- void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_FASTLZ, int p_block_size = 4096);
+ void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096);
Error open_after_magic(FileAccess *p_base);
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 899f3b3b2d..0c84a5213f 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -96,7 +96,12 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
};
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
+ // don't append the standard ports
+ request += "Host: " + conn_host + "\r\n";
+ } else {
+ request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ }
bool add_clen = p_body.size() > 0;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
@@ -151,7 +156,12 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
};
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) {
+ // don't append the standard ports
+ request += "Host: " + conn_host + "\r\n";
+ } else {
+ request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ }
bool add_clen = p_body.length() > 0;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 320990cc50..838fec22f0 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -401,7 +401,7 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar::get_point_weight_scale);
ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point);
- ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id"), &AStar::connect_points, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points);
ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id"), &AStar::are_points_connected);
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index ca960aabad..45509a0808 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -110,6 +110,15 @@ public:
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
#ifdef _MSC_VER
return !_finite(p_val);
+// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint64_t u;
+ double f;
+ } ieee754;
+ ieee754.f = p_val;
+ return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
+ ((unsigned)ieee754.u == 0);
#else
return isinf(p_val);
#endif
@@ -118,6 +127,14 @@ public:
static _ALWAYS_INLINE_ bool is_inf(float p_val) {
#ifdef _MSC_VER
return !_finite(p_val);
+// use an inline implementation of isinf as a workaround for problematic libstdc++ versions from gcc 5.x era
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint32_t u;
+ float f;
+ } ieee754;
+ ieee754.f = p_val;
+ return (ieee754.u & 0x7fffffff) == 0x7f800000;
#else
return isinf(p_val);
#endif
diff --git a/core/script_language.h b/core/script_language.h
index 115ab59dca..6e39593a89 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -196,6 +196,8 @@ public:
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const = 0;
+ virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {}
+ virtual bool is_using_templates() { return false; }
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
diff --git a/core/translation.h b/core/translation.h
index 577282b45f..8630b8a478 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -36,7 +36,7 @@ class Translation : public Resource {
GDCLASS(Translation, Resource);
OBJ_SAVE_TYPE(Translation);
- RES_BASE_EXTENSION("xl");
+ RES_BASE_EXTENSION("translation");
String locale;
Map<StringName, StringName> translation_map;