summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/class_db.h4
-rw-r--r--core/color.cpp18
-rw-r--r--core/color.h1
-rw-r--r--core/global_constants.cpp1
-rw-r--r--core/image.cpp364
-rw-r--r--core/image.h13
-rw-r--r--core/input_map.cpp2
-rw-r--r--core/io/resource_import.cpp2
-rw-r--r--core/math/quick_hull.cpp11
-rw-r--r--core/object.cpp33
-rw-r--r--core/object.h8
-rw-r--r--core/os/os.h2
-rw-r--r--core/reference.h7
-rw-r--r--core/resource.cpp6
-rw-r--r--core/variant_call.cpp18
15 files changed, 378 insertions, 112 deletions
diff --git a/core/class_db.h b/core/class_db.h
index f1d1879236..66a67f6c9f 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -39,6 +39,10 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+/** To bind more then 6 parameters include this:
+ * #include "method_bind_ext.gen.inc"
+ */
+
#define DEFVAL(m_defval) (m_defval)
//#define SIMPLE_METHODDEF
diff --git a/core/color.cpp b/core/color.cpp
index fcfcf20355..17c9e2daeb 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -253,6 +253,21 @@ Color Color::hex64(uint64_t p_hex) {
return Color(r, g, b, a);
}
+Color Color::from_rgbe9995(uint32_t p_rgbe) {
+
+ float r = p_rgbe & 0x1ff;
+ float g = (p_rgbe >> 9) & 0x1ff;
+ float b = (p_rgbe >> 18) & 0x1ff;
+ float e = (p_rgbe >> 27);
+ float m = Math::pow(2, e - 15.0 - 9.0);
+
+ float rd = r * m;
+ float gd = g * m;
+ float bd = b * m;
+
+ return Color(rd, gd, bd, 1.0f);
+}
+
static float _parse_col(const String &p_str, int p_ofs) {
int ig = 0;
@@ -506,8 +521,11 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) {
return Color(m + r, m + g, m + b, p_a);
}
+// FIXME: Remove once Godot 3.1 has been released
float Color::gray() const {
+ ERR_EXPLAIN("Color.gray() is deprecated and will be removed in a future version. Use Color.get_v() for a better grayscale approximation.");
+ WARN_DEPRECATED
return (r + g + b) / 3.0;
}
diff --git a/core/color.h b/core/color.h
index c0516e55fe..00f4c9e9e8 100644
--- a/core/color.h
+++ b/core/color.h
@@ -195,6 +195,7 @@ struct Color {
static Color named(const String &p_name);
String to_html(bool p_alpha = true) const;
Color from_hsv(float p_h, float p_s, float p_v, float p_a);
+ static Color from_rgbe9995(uint32_t p_color);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 187813f9d0..962881e720 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -532,6 +532,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_DIR);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RESOURCE_TYPE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_MULTILINE_TEXT);
+ BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS);
diff --git a/core/image.cpp b/core/image.cpp
index c94f2c3534..b1f0125b43 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -37,6 +37,7 @@
#include "print_string.h"
#include "io/resource_loader.h"
+#include "math_funcs.h"
#include "thirdparty/misc/hq2x.h"
#include <stdio.h>
@@ -525,7 +526,7 @@ static double _bicubic_interp_kernel(double x) {
return bc;
}
-template <int CC>
+template <int CC, class T = uint8_t>
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
// get source image size
@@ -556,7 +557,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
// initial pixel value
- uint8_t *__restrict dst = p_dst + (y * p_dst_width + x) * CC;
+ T *__restrict dst = ((T *)p_dst) + (y * p_dst_width + x) * CC;
double color[CC];
for (int i = 0; i < CC; i++) {
@@ -584,23 +585,32 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
ox2 = xmax;
// get pixel of original image
- const uint8_t *__restrict p = p_src + (oy2 * p_src_width + ox2) * CC;
+ const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
for (int i = 0; i < CC; i++) {
-
- color[i] += p[i] * k2;
+ if (sizeof(T) == 2) { //half float
+ color[i] = Math::half_to_float(p[i]);
+ } else {
+ color[i] += p[i] * k2;
+ }
}
}
}
for (int i = 0; i < CC; i++) {
- dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
+ if (sizeof(T) == 1) { //byte
+ dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
+ } else if (sizeof(T) == 2) { //half float
+ dst[i] = Math::make_half_float(color[i]);
+ } else {
+ dst[i] = color[i];
+ }
}
}
}
}
-template <int CC>
+template <int CC, class T = uint8_t>
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
enum {
@@ -640,22 +650,58 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
for (uint32_t l = 0; l < CC; l++) {
- uint32_t p00 = p_src[y_ofs_up + src_xofs_left + l] << FRAC_BITS;
- uint32_t p10 = p_src[y_ofs_up + src_xofs_right + l] << FRAC_BITS;
- uint32_t p01 = p_src[y_ofs_down + src_xofs_left + l] << FRAC_BITS;
- uint32_t p11 = p_src[y_ofs_down + src_xofs_right + l] << FRAC_BITS;
-
- uint32_t interp_up = p00 + (((p10 - p00) * src_xofs_frac) >> FRAC_BITS);
- uint32_t interp_down = p01 + (((p11 - p01) * src_xofs_frac) >> FRAC_BITS);
- uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
- interp >>= FRAC_BITS;
- p_dst[i * p_dst_width * CC + j * CC + l] = interp;
+ if (sizeof(T) == 1) { //uint8
+ uint32_t p00 = p_src[y_ofs_up + src_xofs_left + l] << FRAC_BITS;
+ uint32_t p10 = p_src[y_ofs_up + src_xofs_right + l] << FRAC_BITS;
+ uint32_t p01 = p_src[y_ofs_down + src_xofs_left + l] << FRAC_BITS;
+ uint32_t p11 = p_src[y_ofs_down + src_xofs_right + l] << FRAC_BITS;
+
+ uint32_t interp_up = p00 + (((p10 - p00) * src_xofs_frac) >> FRAC_BITS);
+ uint32_t interp_down = p01 + (((p11 - p01) * src_xofs_frac) >> FRAC_BITS);
+ uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
+ interp >>= FRAC_BITS;
+ p_dst[i * p_dst_width * CC + j * CC + l] = interp;
+ } else if (sizeof(T) == 2) { //half float
+
+ float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
+ float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
+ const T *src = ((const T *)p_src);
+ T *dst = ((T *)p_dst);
+
+ float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
+ float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
+ float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
+ float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
+
+ float interp_up = p00 + (p10 - p00) * xofs_frac;
+ float interp_down = p01 + (p11 - p01) * xofs_frac;
+ float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
+
+ dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
+ } else if (sizeof(T) == 4) { //float
+
+ float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
+ float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
+ const T *src = ((const T *)p_src);
+ T *dst = ((T *)p_dst);
+
+ float p00 = src[y_ofs_up + src_xofs_left + l];
+ float p10 = src[y_ofs_up + src_xofs_right + l];
+ float p01 = src[y_ofs_down + src_xofs_left + l];
+ float p11 = src[y_ofs_down + src_xofs_right + l];
+
+ float interp_up = p00 + (p10 - p00) * xofs_frac;
+ float interp_down = p01 + (p11 - p01) * xofs_frac;
+ float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
+
+ dst[i * p_dst_width * CC + j * CC + l] = interp;
+ }
}
}
}
}
-template <int CC>
+template <int CC, class T = uint8_t>
static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
for (uint32_t i = 0; i < p_dst_height; i++) {
@@ -670,8 +716,11 @@ static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict
for (uint32_t l = 0; l < CC; l++) {
- uint32_t p = p_src[y_ofs + src_xofs + l];
- p_dst[i * p_dst_width * CC + j * CC + l] = p;
+ const T *src = ((const T *)p_src);
+ T *dst = ((T *)p_dst);
+
+ T p = src[y_ofs + src_xofs + l];
+ dst[i * p_dst_width * CC + j * CC + l] = p;
}
}
}
@@ -766,12 +815,30 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
case INTERPOLATE_NEAREST: {
- switch (get_format_pixel_size(format)) {
- case 1: _scale_nearest<1>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_nearest<2>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_nearest<3>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_nearest<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
+ switch (get_format_pixel_size(format)) {
+ case 1: _scale_nearest<1>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2: _scale_nearest<2>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 3: _scale_nearest<3>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_nearest<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
+ switch (get_format_pixel_size(format)) {
+ case 4: _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 12: _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 16: _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+
+ } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
+ switch (get_format_pixel_size(format)) {
+ case 2: _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 6: _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
}
+
} break;
case INTERPOLATE_BILINEAR:
case INTERPOLATE_TRILINEAR: {
@@ -812,11 +879,27 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
}
}
- switch (get_format_pixel_size(format)) {
- case 1: _scale_bilinear<1>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 2: _scale_bilinear<2>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 3: _scale_bilinear<3>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
- case 4: _scale_bilinear<4>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
+ switch (get_format_pixel_size(format)) {
+ case 1: _scale_bilinear<1>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 2: _scale_bilinear<2>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 3: _scale_bilinear<3>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 4: _scale_bilinear<4>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
+ switch (get_format_pixel_size(format)) {
+ case 4: _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 8: _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 12: _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 16: _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
+ switch (get_format_pixel_size(format)) {
+ case 2: _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 4: _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 6: _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 8: _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ }
}
}
@@ -829,13 +912,28 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
} break;
case INTERPOLATE_CUBIC: {
- switch (get_format_pixel_size(format)) {
- case 1: _scale_cubic<1>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_cubic<2>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_cubic<3>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_cubic<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
+ switch (get_format_pixel_size(format)) {
+ case 1: _scale_cubic<1>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 2: _scale_cubic<2>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 3: _scale_cubic<3>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_cubic<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
+ switch (get_format_pixel_size(format)) {
+ case 4: _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 12: _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 16: _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
+ } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
+ switch (get_format_pixel_size(format)) {
+ case 2: _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 4: _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 6: _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ case 8: _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ }
}
-
} break;
}
@@ -1029,8 +1127,10 @@ bool Image::_can_modify(Format p_format) const {
return p_format <= FORMAT_RGBE9995;
}
-template <int CC, bool renormalize>
-static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_width, uint32_t p_height) {
+template <class Component, int CC, bool renormalize,
+ void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
+ void (*renormalize_func)(Component *)>
+static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) {
//fast power of 2 mipmap generation
uint32_t dst_w = p_width >> 1;
@@ -1038,34 +1138,19 @@ static void _generate_po2_mipmap(const uint8_t *p_src, uint8_t *p_dst, uint32_t
for (uint32_t i = 0; i < dst_h; i++) {
- const uint8_t *rup_ptr = &p_src[i * 2 * p_width * CC];
- const uint8_t *rdown_ptr = rup_ptr + p_width * CC;
- uint8_t *dst_ptr = &p_dst[i * dst_w * CC];
+ const Component *rup_ptr = &p_src[i * 2 * p_width * CC];
+ const Component *rdown_ptr = rup_ptr + p_width * CC;
+ Component *dst_ptr = &p_dst[i * dst_w * CC];
uint32_t count = dst_w;
while (count--) {
for (int j = 0; j < CC; j++) {
-
- uint16_t val = 0;
- val += rup_ptr[j];
- val += rup_ptr[j + CC];
- val += rdown_ptr[j];
- val += rdown_ptr[j + CC];
- dst_ptr[j] = val >> 2;
+ average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + CC], rdown_ptr[j], rdown_ptr[j + CC]);
}
if (renormalize) {
- Vector3 n(dst_ptr[0] / 255.0, dst_ptr[1] / 255.0, dst_ptr[2] / 255.0);
- n *= 2.0;
- n -= Vector3(1, 1, 1);
- n.normalize();
- n += Vector3(1, 1, 1);
- n *= 0.5;
- n *= 255;
- dst_ptr[0] = CLAMP(int(n.x), 0, 255);
- dst_ptr[1] = CLAMP(int(n.y), 0, 255);
- dst_ptr[2] = CLAMP(int(n.z), 0, 255);
+ renormalize_func(dst_ptr);
}
dst_ptr += CC;
@@ -1150,11 +1235,23 @@ void Image::shrink_x2() {
switch (format) {
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<1, false>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_LA8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RG8: _generate_po2_mipmap<2, false>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RGB8: _generate_po2_mipmap<3, false>(r.ptr(), w.ptr(), width, height); break;
- case FORMAT_RGBA8: _generate_po2_mipmap<4, false>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
+ case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r.ptr(), w.ptr(), width, height); break;
+
+ case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
+ case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
+ case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
+ case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r.ptr()), reinterpret_cast<float *>(w.ptr()), width, height); break;
+
+ case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
+ case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
+ case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
+ case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r.ptr()), reinterpret_cast<uint16_t *>(w.ptr()), width, height); break;
+
+ case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r.ptr()), reinterpret_cast<uint32_t *>(w.ptr()), width, height); break;
default: {}
}
}
@@ -1224,21 +1321,68 @@ Error Image::generate_mipmaps(bool p_renormalize) {
switch (format) {
case FORMAT_L8:
- case FORMAT_R8: _generate_po2_mipmap<1, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
case FORMAT_LA8:
- case FORMAT_RG8: _generate_po2_mipmap<2, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
+ case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break;
case FORMAT_RGB8:
if (p_renormalize)
- _generate_po2_mipmap<3, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ _generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
else
- _generate_po2_mipmap<3, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
break;
case FORMAT_RGBA8:
if (p_renormalize)
- _generate_po2_mipmap<4, true>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ _generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ else
+ _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ break;
+ case FORMAT_RF:
+ _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ break;
+ case FORMAT_RGF:
+ _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ break;
+ case FORMAT_RGBF:
+ if (p_renormalize)
+ _generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ else
+ _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+
+ break;
+ case FORMAT_RGBAF:
+ if (p_renormalize)
+ _generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+ else
+ _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h);
+
+ break;
+ case FORMAT_RH:
+ _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+ break;
+ case FORMAT_RGH:
+ _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+ break;
+ case FORMAT_RGBH:
+ if (p_renormalize)
+ _generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
else
- _generate_po2_mipmap<4, false>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h);
+ _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+
+ break;
+ case FORMAT_RGBAH:
+ if (p_renormalize)
+ _generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+ else
+ _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h);
+
+ break;
+ case FORMAT_RGBE9995:
+ if (p_renormalize)
+ _generate_po2_mipmap<uint32_t, 1, true, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
+ else
+ _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h);
+
break;
default: {}
}
@@ -1617,8 +1761,10 @@ bool Image::is_compressed() const {
Error Image::decompress() {
- if (format >= FORMAT_DXT1 && format <= FORMAT_BPTC_RGBFU && _image_decompress_bc)
+ if (format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG && _image_decompress_bc)
_image_decompress_bc(this);
+ else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc)
+ _image_decompress_bptc(this);
else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc)
_image_decompress_pvrtc(this);
else if (format == FORMAT_ETC && _image_decompress_etc1)
@@ -1659,6 +1805,11 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_loss
ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE);
_image_compress_etc2_func(this, p_lossy_quality, p_source);
} break;
+ case COMPRESS_BPTC: {
+
+ ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE);
+ _image_compress_bptc_func(this, p_lossy_quality, p_source);
+ } break;
}
return OK;
@@ -1996,12 +2147,14 @@ ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL;
ImageMemLoadFunc Image::_webp_mem_loader_func = NULL;
void (*Image::_image_compress_bc_func)(Image *, Image::CompressSource) = NULL;
+void (*Image::_image_compress_bptc_func)(Image *, float, Image::CompressSource) = NULL;
void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
void (*Image::_image_compress_pvrtc4_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_bptc)(Image *) = NULL;
void (*Image::_image_decompress_etc1)(Image *) = NULL;
void (*Image::_image_decompress_etc2)(Image *) = NULL;
@@ -2185,18 +2338,7 @@ Color Image::get_pixel(int p_x, int p_y) const {
return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), Math::half_to_float(a));
} break;
case FORMAT_RGBE9995: {
- uint32_t rgbe = ((uint32_t *)ptr)[ofs];
- float r = rgbe & 0x1ff;
- float g = (rgbe >> 9) & 0x1ff;
- float b = (rgbe >> 18) & 0x1ff;
- float e = (rgbe >> 27);
- float m = Math::pow(2, e - 15.0 - 9.0);
- ;
- float rd = r * m;
- float gd = g * m;
- float bd = b * m;
-
- return Color(rd, gd, bd, 1.0);
+ return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
} break;
default: {
@@ -2230,10 +2372,10 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) {
switch (format) {
case FORMAT_L8: {
- ptr[ofs] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255));
+ ptr[ofs] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255));
} break;
case FORMAT_LA8: {
- ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.gray() * 255.0, 0, 255));
+ ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.get_v() * 255.0, 0, 255));
ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
} break;
case FORMAT_R8: {
@@ -2530,6 +2672,11 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource
_image_compress_bc_func = p_compress_func;
}
+void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource)) {
+
+ _image_compress_bptc_func = p_compress_func;
+}
+
void Image::normalmap_to_xy() {
convert(Image::FORMAT_RGBA8);
@@ -2783,6 +2930,55 @@ Error Image::_load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadF
return OK;
}
+void Image::average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d) {
+ p_out = static_cast<uint8_t>((p_a + p_b + p_c + p_d + 2) >> 2);
+}
+
+void Image::average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d) {
+ p_out = (p_a + p_b + p_c + p_d) * 0.25f;
+}
+
+void Image::average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
+ p_out = Math::make_half_float((Math::half_to_float(p_a) + Math::half_to_float(p_b) + Math::half_to_float(p_c) + Math::half_to_float(p_d)) * 0.25f);
+}
+
+void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d) {
+ p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
+}
+
+void Image::renormalize_uint8(uint8_t *p_rgb) {
+ Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
+ n *= 2.0;
+ n -= Vector3(1, 1, 1);
+ n.normalize();
+ n += Vector3(1, 1, 1);
+ n *= 0.5;
+ n *= 255;
+ p_rgb[0] = CLAMP(int(n.x), 0, 255);
+ p_rgb[1] = CLAMP(int(n.y), 0, 255);
+ p_rgb[2] = CLAMP(int(n.z), 0, 255);
+}
+
+void Image::renormalize_float(float *p_rgb) {
+ Vector3 n(p_rgb[0], p_rgb[1], p_rgb[2]);
+ n.normalize();
+ p_rgb[0] = n.x;
+ p_rgb[1] = n.y;
+ p_rgb[2] = n.z;
+}
+
+void Image::renormalize_half(uint16_t *p_rgb) {
+ Vector3 n(Math::half_to_float(p_rgb[0]), Math::half_to_float(p_rgb[1]), Math::half_to_float(p_rgb[2]));
+ n.normalize();
+ p_rgb[0] = Math::make_half_float(n.x);
+ p_rgb[1] = Math::make_half_float(n.y);
+ p_rgb[2] = Math::make_half_float(n.z);
+}
+
+void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
+ // Never used
+}
+
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
width = 0;
diff --git a/core/image.h b/core/image.h
index c450e88290..854096b773 100644
--- a/core/image.h
+++ b/core/image.h
@@ -127,6 +127,7 @@ public:
static ImageMemLoadFunc _webp_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
+ static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, CompressSource p_source);
static void (*_image_compress_pvrtc2_func)(Image *);
static void (*_image_compress_pvrtc4_func)(Image *);
static void (*_image_compress_etc1_func)(Image *, float);
@@ -134,6 +135,7 @@ public:
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
+ static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
static void (*_image_decompress_etc2)(Image *);
@@ -182,6 +184,15 @@ private:
Error _load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader);
+ static void average_4_uint8(uint8_t &p_out, const uint8_t &p_a, const uint8_t &p_b, const uint8_t &p_c, const uint8_t &p_d);
+ static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
+ static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
+ static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
+ static void renormalize_uint8(uint8_t *p_rgb);
+ static void renormalize_float(float *p_rgb);
+ static void renormalize_half(uint16_t *p_rgb);
+ static void renormalize_rgbe9995(uint32_t *p_rgb);
+
public:
int get_width() const; ///< Get image width
int get_height() const; ///< Get image height
@@ -282,6 +293,7 @@ public:
COMPRESS_PVRTC4,
COMPRESS_ETC,
COMPRESS_ETC2,
+ COMPRESS_BPTC
};
Error compress(CompressMode p_mode = COMPRESS_S3TC, CompressSource p_source = COMPRESS_SOURCE_GENERIC, float p_lossy_quality = 0.7);
@@ -305,6 +317,7 @@ public:
Ref<Image> get_rect(const Rect2 &p_area) const;
static void set_compress_bc_func(void (*p_compress_func)(Image *, CompressSource));
+ static void set_compress_bptc_func(void (*p_compress_func)(Image *, float, CompressSource));
static String get_format_name(Format p_format);
Error load_png_from_buffer(const PoolVector<uint8_t> &p_array);
diff --git a/core/input_map.cpp b/core/input_map.cpp
index d33f40cbcf..ffc8a39da5 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -44,7 +44,7 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.5f));
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
- ClassDB::bind_method(D_METHOD("action_set_deadzone", "deadzone"), &InputMap::action_set_deadzone);
+ ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone);
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp
index cfe6655504..83e8a40da9 100644
--- a/core/io/resource_import.cpp
+++ b/core/io/resource_import.cpp
@@ -78,7 +78,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
if (assign != String()) {
if (!path_found && assign.begins_with("path.") && r_path_and_type.path == String()) {
String feature = assign.get_slicec('.', 1);
- if (OS::get_singleton()->has_feature(feature)) {
+ if (feature == "fallback" || OS::get_singleton()->has_feature(feature)) {
r_path_and_type.path = value;
path_found = true; //first match must have priority
}
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index cb923d264e..45c106102e 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -397,7 +397,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e);
ERR_CONTINUE(!F);
-
List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left;
ERR_CONTINUE(O == E);
ERR_CONTINUE(O == NULL);
@@ -426,7 +425,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
Edge e2(idx, idxn);
Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2);
-
ERR_CONTINUE(!F2);
//change faceconnect, point to this face instead
if (F2->get().left == O)
@@ -439,6 +437,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
}
}
+ // remove all edge connections to this face
+ for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) {
+ if (E->get().left == O)
+ E->get().left = NULL;
+
+ if (E->get().right == O)
+ E->get().right = NULL;
+ }
+
ret_edges.erase(F); //remove the edge
ret_faces.erase(O); //remove the face
}
diff --git a/core/object.cpp b/core/object.cpp
index ba8b710a84..76226d113a 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1476,8 +1476,13 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
if (s->slot_map.has(target)) {
- ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
- ERR_FAIL_COND_V(s->slot_map.has(target), ERR_INVALID_PARAMETER);
+ if (p_flags & CONNECT_REFERENCE_COUNTED) {
+ s->slot_map[target].reference_count++;
+ return OK;
+ } else {
+ ERR_EXPLAIN("Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
+ ERR_FAIL_COND_V(s->slot_map.has(target), ERR_INVALID_PARAMETER);
+ }
}
Signal::Slot slot;
@@ -1491,6 +1496,10 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
conn.binds = p_binds;
slot.conn = conn;
slot.cE = p_to_object->connections.push_back(conn);
+ if (p_flags & CONNECT_REFERENCE_COUNTED) {
+ slot.reference_count = 1;
+ }
+
s->slot_map[target] = slot;
return OK;
@@ -1521,6 +1530,10 @@ bool Object::is_connected(const StringName &p_signal, Object *p_to_object, const
void Object::disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) {
+ _disconnect(p_signal, p_to_object, p_to_method);
+}
+void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force) {
+
ERR_FAIL_NULL(p_to_object);
Signal *s = signal_map.getptr(p_signal);
if (!s) {
@@ -1539,7 +1552,16 @@ void Object::disconnect(const StringName &p_signal, Object *p_to_object, const S
ERR_FAIL();
}
- p_to_object->connections.erase(s->slot_map[target].cE);
+ Signal::Slot *slot = &s->slot_map[target];
+
+ if (!p_force) {
+ slot->reference_count--; // by default is zero, if it was not referenced it will go below it
+ if (slot->reference_count >= 0) {
+ return;
+ }
+ }
+
+ p_to_object->connections.erase(slot->cE);
s->slot_map.erase(target);
if (s->slot_map.empty() && ClassDB::has_signal(get_class_name(), p_signal)) {
@@ -1761,6 +1783,7 @@ void Object::_bind_methods() {
BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
BIND_ENUM_CONSTANT(CONNECT_ONESHOT);
+ BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
}
void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
@@ -1948,13 +1971,13 @@ Object::~Object() {
Connection &c = E->get();
ERR_CONTINUE(c.source != this); //bug?
- this->disconnect(c.signal, c.target, c.method);
+ this->_disconnect(c.signal, c.target, c.method, true);
}
while (connections.size()) {
Connection c = connections.front()->get();
- c.source->disconnect(c.signal, c.target, c.method);
+ c.source->_disconnect(c.signal, c.target, c.method, true);
}
ObjectDB::remove_instance(this);
diff --git a/core/object.h b/core/object.h
index 8dc3426d1d..d741371306 100644
--- a/core/object.h
+++ b/core/object.h
@@ -71,6 +71,7 @@ enum PropertyHint {
PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
+ PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
@@ -391,7 +392,8 @@ public:
CONNECT_DEFERRED = 1,
CONNECT_PERSIST = 2, // hint for scene to save this connection
- CONNECT_ONESHOT = 4
+ CONNECT_ONESHOT = 4,
+ CONNECT_REFERENCE_COUNTED = 8,
};
struct Connection {
@@ -442,8 +444,10 @@ private:
struct Slot {
+ int reference_count;
Connection conn;
List<Connection>::Element *cE;
+ Slot() { reference_count = 0; }
};
MethodInfo user;
@@ -547,6 +551,8 @@ protected:
friend class ClassDB;
virtual void _validate_property(PropertyInfo &property) const;
+ void _disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force = false);
+
public: //should be protected, but bug in clang++
static void initialize_class();
_FORCE_INLINE_ static void register_custom_data_to_otdb(){};
diff --git a/core/os/os.h b/core/os/os.h
index dd783408e8..12c0222ad4 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -254,7 +254,7 @@ public:
virtual String get_executable_path() const;
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
- virtual Error kill(const ProcessID &p_pid) = 0;
+ virtual Error kill(const ProcessID &p_pid, const int p_max_wait_msec = -1) = 0;
virtual int get_process_id() const;
virtual Error shell_open(String p_uri);
diff --git a/core/reference.h b/core/reference.h
index 0d6b1ced6e..25e02180fa 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -87,6 +87,13 @@ class Ref {
//virtual Reference * get_reference() const { return reference; }
public:
+ _FORCE_INLINE_ bool operator==(const T *p_ptr) const {
+ return reference == p_ptr;
+ }
+ _FORCE_INLINE_ bool operator!=(const T *p_ptr) const {
+ return reference != p_ptr;
+ }
+
_FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const {
return reference < p_r.reference;
diff --git a/core/resource.cpp b/core/resource.cpp
index 87ff4d3c2a..3078eb135a 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -151,7 +151,7 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
List<PropertyInfo> plist;
get_property_list(&plist);
- Resource *r = (Resource *)ClassDB::instance(get_class());
+ Resource *r = Object::cast_to<Resource>(ClassDB::instance(get_class()));
ERR_FAIL_COND_V(!r, Ref<Resource>());
r->local_scene = p_for_scene;
@@ -182,7 +182,9 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
r->set(E->get().name, p);
}
- return Ref<Resource>(r);
+ RES res = Ref<Resource>(r);
+
+ return res;
}
void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource> > &remap_cache) {
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index ea51419233..1c50df75f5 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1920,23 +1920,11 @@ void register_variant_methods() {
transform_x.set(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
_VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", transform_z);
- _VariantCall::add_variant_constant(Variant::PLANE, "X", Plane(Vector3(1, 0, 0), 0));
- _VariantCall::add_variant_constant(Variant::PLANE, "Y", Plane(Vector3(0, 1, 0), 0));
- _VariantCall::add_variant_constant(Variant::PLANE, "Z", Plane(Vector3(0, 0, 1), 0));
+ _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_YZ", Plane(Vector3(1, 0, 0), 0));
+ _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XZ", Plane(Vector3(0, 1, 0), 0));
+ _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0));
_VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1));
-
- CharType black_circle[2] = { 0x25CF, 0 };
- _VariantCall::add_variant_constant(Variant::STRING, "BLACK_CIRCLE", String(black_circle));
- CharType white_circle[2] = { 0x25CB, 0 };
- _VariantCall::add_variant_constant(Variant::STRING, "WHITE_CIRCLE", String(white_circle));
- CharType black_diamond[2] = { 0x25C6, 0 };
- _VariantCall::add_variant_constant(Variant::STRING, "BLACK_DIAMOND", String(black_diamond));
- CharType white_diamond[2] = { 0x25C7, 0 };
- _VariantCall::add_variant_constant(Variant::STRING, "WHITE_DIAMOND", String(white_diamond));
-
- _VariantCall::add_variant_constant(Variant::NODE_PATH, "CURRENT", String("."));
- _VariantCall::add_variant_constant(Variant::NODE_PATH, "PARENT", String(".."));
}
void unregister_variant_methods() {