summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub48
-rw-r--r--core/core_builders.py236
-rw-r--r--core/io/image_loader.cpp80
-rw-r--r--core/io/image_loader.h13
-rw-r--r--core/io/marshalls.cpp177
-rw-r--r--core/make_binders.py10
-rw-r--r--core/object.cpp10
-rw-r--r--core/os/input_event.cpp8
-rw-r--r--core/os/input_event.h1
-rw-r--r--core/os/os.cpp7
-rw-r--r--core/register_core_types.cpp9
11 files changed, 470 insertions, 129 deletions
diff --git a/core/SCsub b/core/SCsub
index c508ecc37e..c8e2e10b9f 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -2,7 +2,9 @@
Import('env')
-import methods
+import core_builders
+import make_binders
+from platform_methods import run_in_subprocess
env.core_sources = []
@@ -21,7 +23,7 @@ gd_cpp += gd_inc
gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n"
with open("global_defaults.gen.cpp", "w") as f:
- f.write(gd_cpp)
+ f.write(gd_cpp)
# Generate AES256 script encryption key
@@ -48,26 +50,27 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
print("Invalid AES256 encryption key, not 64 bits hex: " + e)
+# NOTE: It is safe to generate this file here, since this is still executed serially
with open("script_encryption_key.gen.cpp", "w") as f:
- f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
+ f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
# Add required thirdparty code. Header paths are hardcoded, we don't need to append
# to the include path (saves a few chars on the compiler invocation for touchy MSVC...)
thirdparty_dir = "#thirdparty/misc/"
thirdparty_sources = [
- # C sources
- "base64.c",
- "fastlz.c",
- "sha256.c",
- "smaz.c",
-
- # C++ sources
- "aes256.cpp",
- "hq2x.cpp",
- "md5.cpp",
- "pcg.cpp",
- "triangulator.cpp",
+ # C sources
+ "base64.c",
+ "fastlz.c",
+ "sha256.c",
+ "smaz.c",
+
+ # C++ sources
+ "aes256.cpp",
+ "hq2x.cpp",
+ "md5.cpp",
+ "pcg.cpp",
+ "triangulator.cpp",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env.add_source_files(env.core_sources, thirdparty_sources)
@@ -76,9 +79,9 @@ env.add_source_files(env.core_sources, thirdparty_sources)
# However, our version has some custom modifications, so it won't compile with the system one
thirdparty_minizip_dir = "#thirdparty/minizip/"
thirdparty_minizip_sources = [
- "ioapi.c",
- "unzip.c",
- "zip.c",
+ "ioapi.c",
+ "unzip.c",
+ "zip.c",
]
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
@@ -92,20 +95,19 @@ env.add_source_files(env.core_sources, "*.cpp")
# Make binders
-import make_binders
-env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', make_binders.run)
+env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', run_in_subprocess(make_binders.run))
# Authors
env.Depends('#core/authors.gen.h', "../AUTHORS.md")
-env.CommandNoCache('#core/authors.gen.h', "../AUTHORS.md", methods.make_authors_header)
+env.CommandNoCache('#core/authors.gen.h', "../AUTHORS.md", run_in_subprocess(core_builders.make_authors_header))
# Donors
env.Depends('#core/donors.gen.h', "../DONORS.md")
-env.CommandNoCache('#core/donors.gen.h', "../DONORS.md", methods.make_donors_header)
+env.CommandNoCache('#core/donors.gen.h', "../DONORS.md", run_in_subprocess(core_builders.make_donors_header))
# License
env.Depends('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"])
-env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], methods.make_license_header)
+env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], run_in_subprocess(core_builders.make_license_header))
# Chain load SCsubs
SConscript('os/SCsub')
diff --git a/core/core_builders.py b/core/core_builders.py
new file mode 100644
index 0000000000..90e505aab9
--- /dev/null
+++ b/core/core_builders.py
@@ -0,0 +1,236 @@
+"""Functions used to generate source files during build time
+
+All such functions are invoked in a subprocess on Windows to prevent build flakiness.
+
+"""
+from platform_methods import subprocess_main
+from compat import iteritems, itervalues, open_utf8, escape_string
+
+
+def make_authors_header(target, source, env):
+ sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"]
+ sections_id = ["AUTHORS_FOUNDERS", "AUTHORS_LEAD_DEVELOPERS", "AUTHORS_PROJECT_MANAGERS", "AUTHORS_DEVELOPERS"]
+
+ src = source[0]
+ dst = target[0]
+ f = open_utf8(src, "r")
+ g = open_utf8(dst, "w")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_AUTHORS_H\n")
+ g.write("#define _EDITOR_AUTHORS_H\n")
+
+ reading = False
+
+ def close_section():
+ g.write("\t0\n")
+ g.write("};\n")
+
+ for line in f:
+ if reading:
+ if line.startswith(" "):
+ g.write("\t\"" + escape_string(line.strip()) + "\",\n")
+ continue
+ if line.startswith("## "):
+ if reading:
+ close_section()
+ reading = False
+ for section, section_id in zip(sections, sections_id):
+ if line.strip().endswith(section):
+ current_section = escape_string(section_id)
+ reading = True
+ g.write("const char *const " + current_section + "[] = {\n")
+ break
+
+ if reading:
+ close_section()
+
+ g.write("#endif\n")
+
+ g.close()
+ f.close()
+
+
+def make_donors_header(target, source, env):
+ sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors",
+ "Gold donors", "Silver donors", "Bronze donors"]
+ sections_id = ["DONORS_SPONSOR_PLAT", "DONORS_SPONSOR_GOLD", "DONORS_SPONSOR_MINI",
+ "DONORS_GOLD", "DONORS_SILVER", "DONORS_BRONZE"]
+
+ src = source[0]
+ dst = target[0]
+ f = open_utf8(src, "r")
+ g = open_utf8(dst, "w")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_DONORS_H\n")
+ g.write("#define _EDITOR_DONORS_H\n")
+
+ reading = False
+
+ def close_section():
+ g.write("\t0\n")
+ g.write("};\n")
+
+ for line in f:
+ if reading >= 0:
+ if line.startswith(" "):
+ g.write("\t\"" + escape_string(line.strip()) + "\",\n")
+ continue
+ if line.startswith("## "):
+ if reading:
+ close_section()
+ reading = False
+ for section, section_id in zip(sections, sections_id):
+ if line.strip().endswith(section):
+ current_section = escape_string(section_id)
+ reading = True
+ g.write("const char *const " + current_section + "[] = {\n")
+ break
+
+ if reading:
+ close_section()
+
+ g.write("#endif\n")
+
+ g.close()
+ f.close()
+
+
+def make_license_header(target, source, env):
+ src_copyright = source[0]
+ src_license = source[1]
+ dst = target[0]
+
+ class LicenseReader:
+ def __init__(self, license_file):
+ self._license_file = license_file
+ self.line_num = 0
+ self.current = self.next_line()
+
+ def next_line(self):
+ line = self._license_file.readline()
+ self.line_num += 1
+ while line.startswith("#"):
+ line = self._license_file.readline()
+ self.line_num += 1
+ self.current = line
+ return line
+
+ def next_tag(self):
+ if not ':' in self.current:
+ return ('', [])
+ tag, line = self.current.split(":", 1)
+ lines = [line.strip()]
+ while self.next_line() and self.current.startswith(" "):
+ lines.append(self.current.strip())
+ return (tag, lines)
+
+ from collections import OrderedDict
+ projects = OrderedDict()
+ license_list = []
+
+ with open_utf8(src_copyright, "r") as copyright_file:
+ reader = LicenseReader(copyright_file)
+ part = {}
+ while reader.current:
+ tag, content = reader.next_tag()
+ if tag in ("Files", "Copyright", "License"):
+ part[tag] = content[:]
+ elif tag == "Comment":
+ # attach part to named project
+ projects[content[0]] = projects.get(content[0], []) + [part]
+
+ if not tag or not reader.current:
+ # end of a paragraph start a new part
+ if "License" in part and not "Files" in part:
+ # no Files tag in this one, so assume standalone license
+ license_list.append(part["License"])
+ part = {}
+ reader.next_line()
+
+ data_list = []
+ for project in itervalues(projects):
+ for part in project:
+ part["file_index"] = len(data_list)
+ data_list += part["Files"]
+ part["copyright_index"] = len(data_list)
+ data_list += part["Copyright"]
+
+ with open_utf8(dst, "w") as f:
+
+ f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ f.write("#ifndef _EDITOR_LICENSE_H\n")
+ f.write("#define _EDITOR_LICENSE_H\n")
+ f.write("const char *const GODOT_LICENSE_TEXT =")
+
+ with open_utf8(src_license, "r") as license_file:
+ for line in license_file:
+ escaped_string = escape_string(line.strip())
+ f.write("\n\t\t\"" + escaped_string + "\\n\"")
+ f.write(";\n\n")
+
+ f.write("struct ComponentCopyrightPart {\n"
+ "\tconst char *license;\n"
+ "\tconst char *const *files;\n"
+ "\tconst char *const *copyright_statements;\n"
+ "\tint file_count;\n"
+ "\tint copyright_count;\n"
+ "};\n\n")
+
+ f.write("struct ComponentCopyright {\n"
+ "\tconst char *name;\n"
+ "\tconst ComponentCopyrightPart *parts;\n"
+ "\tint part_count;\n"
+ "};\n\n")
+
+ f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n")
+ for line in data_list:
+ f.write("\t\"" + escape_string(line) + "\",\n")
+ f.write("};\n\n")
+
+ f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
+ part_index = 0
+ part_indexes = {}
+ for project_name, project in iteritems(projects):
+ part_indexes[project_name] = part_index
+ for part in project:
+ f.write("\t{ \"" + escape_string(part["License"][0]) + "\", "
+ + "&COPYRIGHT_INFO_DATA[" + str(part["file_index"]) + "], "
+ + "&COPYRIGHT_INFO_DATA[" + str(part["copyright_index"]) + "], "
+ + str(len(part["Files"])) + ", "
+ + str(len(part["Copyright"])) + " },\n")
+ part_index += 1
+ f.write("};\n\n")
+
+ f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n")
+
+ f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n")
+ for project_name, project in iteritems(projects):
+ f.write("\t{ \"" + escape_string(project_name) + "\", "
+ + "&COPYRIGHT_PROJECT_PARTS[" + str(part_indexes[project_name]) + "], "
+ + str(len(project)) + " },\n")
+ f.write("};\n\n")
+
+ f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n")
+
+ f.write("const char *const LICENSE_NAMES[] = {\n")
+ for l in license_list:
+ f.write("\t\"" + escape_string(l[0]) + "\",\n")
+ f.write("};\n\n")
+
+ f.write("const char *const LICENSE_BODIES[] = {\n\n")
+ for l in license_list:
+ for line in l[1:]:
+ if line == ".":
+ f.write("\t\"\\n\"\n")
+ else:
+ f.write("\t\"" + escape_string(line) + "\\n\"\n")
+ f.write("\t\"\",\n\n")
+ f.write("};\n\n")
+
+ f.write("#endif\n")
+
+
+if __name__ == '__main__':
+ subprocess_main(globals())
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 8ebd9d6cd9..614fbb771f 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -107,3 +107,83 @@ void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
ERR_FAIL_COND(loader_count >= MAX_LOADERS);
loader[loader_count++] = p_loader;
}
+
+/////////////////
+
+RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error) {
+
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
+ if (!f) {
+ if (r_error) {
+ *r_error = ERR_CANT_OPEN;
+ }
+ memdelete(f);
+ return RES();
+ }
+
+ uint8_t header[4] = { 0, 0, 0, 0 };
+ f->get_buffer(header, 4);
+
+ bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M';
+ if (unrecognized) {
+ memdelete(f);
+ if (r_error) {
+ *r_error = ERR_FILE_UNRECOGNIZED;
+ }
+ ERR_FAIL_V(RES());
+ }
+
+ String extension = f->get_pascal_string();
+
+ int idx = -1;
+
+ for (int i = 0; i < ImageLoader::loader_count; i++) {
+ if (ImageLoader::loader[i]->recognize(extension)) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx == -1) {
+ memdelete(f);
+ if (r_error) {
+ *r_error = ERR_FILE_UNRECOGNIZED;
+ }
+ ERR_FAIL_V(RES());
+ }
+
+ Ref<Image> image;
+ image.instance();
+
+ Error err = ImageLoader::loader[idx]->load_image(image, f, false, 1.0);
+
+ memdelete(f);
+
+ if (err != OK) {
+ if (r_error) {
+ *r_error = err;
+ }
+ return RES();
+ }
+
+ if (r_error) {
+ *r_error = OK;
+ }
+
+ return image;
+}
+
+void ResourceFormatLoaderImage::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("image");
+}
+
+bool ResourceFormatLoaderImage::handles_type(const String &p_type) const {
+
+ return p_type == "Image";
+}
+
+String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const {
+
+ return "Image";
+}
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 052a8b8a40..fbb654c326 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -32,9 +32,11 @@
#define IMAGE_LOADER_H
#include "image.h"
+#include "io/resource_loader.h"
#include "list.h"
#include "os/file_access.h"
#include "ustring.h"
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -55,6 +57,7 @@ class ImageLoader;
class ImageFormatLoader {
friend class ImageLoader;
+ friend class ResourceFormatLoaderImage;
protected:
virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) = 0;
@@ -70,7 +73,7 @@ class ImageLoader {
enum {
MAX_LOADERS = 8
};
-
+ friend class ResourceFormatLoaderImage;
static ImageFormatLoader *loader[MAX_LOADERS];
static int loader_count;
@@ -83,4 +86,12 @@ public:
static void add_image_format_loader(ImageFormatLoader *p_loader);
};
+class ResourceFormatLoaderImage : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
#endif
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 0a3a6c1ba1..e97df0c261 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -32,8 +32,13 @@
#include "os/keyboard.h"
#include "print_string.h"
#include "reference.h"
+#include <limits.h>
#include <stdio.h>
+#define _S(a) ((int32_t)a)
+#define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err)
+#define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err)
+
void EncodedObjectAsID::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_object_id", "id"), &EncodedObjectAsID::set_object_id);
ClassDB::bind_method(D_METHOD("get_object_id"), &EncodedObjectAsID::get_object_id);
@@ -60,23 +65,31 @@ EncodedObjectAsID::EncodedObjectAsID() {
static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r_string) {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t strlen = decode_uint32(buf);
+ int32_t strlen = decode_uint32(buf);
+ int32_t pad = 0;
+
+ // Handle padding
+ if (strlen % 4) {
+ pad = 4 - strlen % 4;
+ }
+
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)strlen > len, ERR_FILE_EOF);
+
+ // Ensure buffer is big enough
+ ERR_FAIL_ADD_OF(strlen, pad, ERR_FILE_EOF);
+ ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
String str;
- str.parse_utf8((const char *)buf, strlen);
+ ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen), ERR_INVALID_DATA);
r_string = str;
- //handle padding
- if (strlen % 4) {
- strlen += 4 - strlen % 4;
- }
+ // Add padding
+ strlen += pad;
+ // Update buffer pos, left data count, and return size
buf += strlen;
len -= strlen;
-
if (r_len) {
(*r_len) += 4 + strlen;
}
@@ -119,14 +132,15 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::INT: {
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
if (type & ENCODE_FLAG_64) {
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
int64_t val = decode_uint64(buf);
r_variant = val;
if (r_len)
(*r_len) += 8;
} else {
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
int32_t val = decode_uint32(buf);
r_variant = val;
if (r_len)
@@ -136,14 +150,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::REAL: {
- ERR_FAIL_COND_V(len < (int)4, ERR_INVALID_DATA);
-
if (type & ENCODE_FLAG_64) {
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
double val = decode_double(buf);
r_variant = val;
if (r_len)
(*r_len) += 8;
} else {
+ ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
float val = decode_float(buf);
r_variant = val;
if (r_len)
@@ -164,7 +178,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
// math types
case Variant::VECTOR2: {
- ERR_FAIL_COND_V(len < (int)4 * 2, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA);
Vector2 val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@@ -176,7 +190,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break; // 5
case Variant::RECT2: {
- ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
Rect2 val;
val.position.x = decode_float(&buf[0]);
val.position.y = decode_float(&buf[4]);
@@ -190,7 +204,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::VECTOR3: {
- ERR_FAIL_COND_V(len < (int)4 * 3, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA);
Vector3 val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@@ -203,7 +217,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::TRANSFORM2D: {
- ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA);
Transform2D val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
@@ -220,7 +234,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::PLANE: {
- ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
Plane val;
val.normal.x = decode_float(&buf[0]);
val.normal.y = decode_float(&buf[4]);
@@ -234,7 +248,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::QUAT: {
- ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
Quat val;
val.x = decode_float(&buf[0]);
val.y = decode_float(&buf[4]);
@@ -248,7 +262,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::AABB: {
- ERR_FAIL_COND_V(len < (int)4 * 6, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA);
AABB val;
val.position.x = decode_float(&buf[0]);
val.position.y = decode_float(&buf[4]);
@@ -264,7 +278,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::BASIS: {
- ERR_FAIL_COND_V(len < (int)4 * 9, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 9, ERR_INVALID_DATA);
Basis val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@@ -281,7 +295,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} break;
case Variant::TRANSFORM: {
- ERR_FAIL_COND_V(len < (int)4 * 12, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 12, ERR_INVALID_DATA);
Transform val;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@@ -303,7 +317,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
// misc types
case Variant::COLOR: {
- ERR_FAIL_COND_V(len < (int)4 * 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA);
Color val;
val.r = decode_float(&buf[0]);
val.g = decode_float(&buf[4]);
@@ -318,7 +332,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::NODE_PATH: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t strlen = decode_uint32(buf);
+ int32_t strlen = decode_uint32(buf);
if (strlen & 0x80000000) {
//new format
@@ -343,31 +357,15 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
for (uint32_t i = 0; i < total; i++) {
- ERR_FAIL_COND_V((int)len < 4, ERR_INVALID_DATA);
- strlen = decode_uint32(buf);
-
- int pad = 0;
-
- if (strlen % 4)
- pad += 4 - strlen % 4;
-
- buf += 4;
- len -= 4;
- ERR_FAIL_COND_V((int)strlen + pad > len, ERR_INVALID_DATA);
-
String str;
- str.parse_utf8((const char *)buf, strlen);
+ Error err = _decode_string(buf, len, r_len, str);
+ if (err)
+ return err;
if (i < namecount)
names.push_back(str);
else
subnames.push_back(str);
-
- buf += strlen + pad;
- len -= strlen + pad;
-
- if (r_len)
- (*r_len) += 4 + strlen + pad;
}
r_variant = NodePath(names, subnames, flags & 1);
@@ -375,17 +373,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
} else {
//old format, just a string
- buf += 4;
- len -= 4;
- ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);
-
- String str;
- str.parse_utf8((const char *)buf, strlen);
-
- r_variant = NodePath(str);
-
- if (r_len)
- (*r_len) += 4 + strlen;
+ ERR_FAIL_V(ERR_INVALID_DATA);
}
} break;
@@ -402,6 +390,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (type & ENCODE_FLAG_OBJECT_AS_ID) {
//this _is_ allowed
+ ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
ObjectID val = decode_uint64(buf);
if (r_len)
(*r_len) += 8;
@@ -475,7 +464,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::DICTIONARY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
// bool shared = count&0x80000000;
count &= 0x7FFFFFFF;
@@ -488,7 +477,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Dictionary d;
- for (uint32_t i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
Variant key, value;
@@ -520,7 +509,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
// bool shared = count&0x80000000;
count &= 0x7FFFFFFF;
@@ -533,7 +522,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Array varr;
- for (uint32_t i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
int used = 0;
Variant v;
@@ -555,17 +544,17 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_BYTE_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count > len, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count > len, ERR_INVALID_DATA);
PoolVector<uint8_t> data;
if (count) {
data.resize(count);
PoolVector<uint8_t>::Write w = data.write();
- for (uint32_t i = 0; i < count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i] = buf[i];
}
@@ -585,10 +574,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_INT_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);
+ ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
PoolVector<int> data;
@@ -596,7 +586,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const int*rbuf=(const int*)buf;
data.resize(count);
PoolVector<int>::Write w = data.write();
- for (uint32_t i = 0; i < count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i] = decode_uint32(&buf[i * 4]);
}
@@ -612,10 +602,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_REAL_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count * 4 > len, ERR_INVALID_DATA);
+ ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA);
PoolVector<float> data;
@@ -623,7 +614,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const float*rbuf=(const float*)buf;
data.resize(count);
PoolVector<float>::Write w = data.write();
- for (uint32_t i = 0; i < count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i] = decode_float(&buf[i * 4]);
}
@@ -640,7 +631,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_STRING_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
PoolVector<String> strings;
buf += 4;
@@ -650,35 +641,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4;
//printf("string count: %i\n",count);
- for (int i = 0; i < (int)count; i++) {
+ for (int32_t i = 0; i < count; i++) {
- ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t strlen = decode_uint32(buf);
-
- buf += 4;
- len -= 4;
- ERR_FAIL_COND_V((int)strlen > len, ERR_INVALID_DATA);
-
- //printf("loaded string: %s\n",(const char*)buf);
String str;
- str.parse_utf8((const char *)buf, strlen);
+ Error err = _decode_string(buf, len, r_len, str);
+ if (err)
+ return err;
strings.push_back(str);
-
- buf += strlen;
- len -= strlen;
-
- if (r_len)
- (*r_len) += 4 + strlen;
-
- if (strlen % 4) {
- int pad = 4 - (strlen % 4);
- buf += pad;
- len -= pad;
- if (r_len) {
- (*r_len) += pad;
- }
- }
}
r_variant = strings;
@@ -687,11 +657,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_VECTOR2_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count * 4 * 2 > len, ERR_INVALID_DATA);
+ ERR_FAIL_MUL_OF(count, 4 * 2, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count * 4 * 2 > len, ERR_INVALID_DATA);
PoolVector<Vector2> varray;
if (r_len) {
@@ -702,7 +673,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
varray.resize(count);
PoolVector<Vector2>::Write w = varray.write();
- for (int i = 0; i < (int)count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i].x = decode_float(buf + i * 4 * 2 + 4 * 0);
w[i].y = decode_float(buf + i * 4 * 2 + 4 * 1);
@@ -722,11 +693,13 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_VECTOR3_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count * 4 * 3 > len, ERR_INVALID_DATA);
+ ERR_FAIL_MUL_OF(count, 4 * 3, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count * 4 * 3 > len, ERR_INVALID_DATA);
+
PoolVector<Vector3> varray;
if (r_len) {
@@ -737,7 +710,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
varray.resize(count);
PoolVector<Vector3>::Write w = varray.write();
- for (int i = 0; i < (int)count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i].x = decode_float(buf + i * 4 * 3 + 4 * 0);
w[i].y = decode_float(buf + i * 4 * 3 + 4 * 1);
@@ -758,11 +731,13 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
case Variant::POOL_COLOR_ARRAY: {
ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA);
- uint32_t count = decode_uint32(buf);
+ int32_t count = decode_uint32(buf);
buf += 4;
len -= 4;
- ERR_FAIL_COND_V((int)count * 4 * 4 > len, ERR_INVALID_DATA);
+ ERR_FAIL_MUL_OF(count, 4 * 4, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(count < 0 || count * 4 * 4 > len, ERR_INVALID_DATA);
+
PoolVector<Color> carray;
if (r_len) {
@@ -773,7 +748,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
carray.resize(count);
PoolVector<Color>::Write w = carray.write();
- for (int i = 0; i < (int)count; i++) {
+ for (int32_t i = 0; i < count; i++) {
w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0);
w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1);
@@ -1323,7 +1298,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
while (r_len % 4) {
r_len++; //pad
if (buf)
- buf++;
+ *(buf++) = 0;
}
}
diff --git a/core/make_binders.py b/core/make_binders.py
index 6a7602cd5d..4c61b90d99 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -1,6 +1,5 @@
# -*- coding: ibm850 -*-
-
template_typed = """
#ifdef TYPED_METHOD_BIND
template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
@@ -265,8 +264,13 @@ def run(target, source, env):
else:
text += t
- with open(target[0].path, "w") as f:
+ with open(target[0], "w") as f:
f.write(text)
- with open(target[1].path, "w") as f:
+ with open(target[1], "w") as f:
f.write(text_ext)
+
+
+if __name__ == '__main__':
+ from platform_methods import subprocess_main
+ subprocess_main(globals())
diff --git a/core/object.cpp b/core/object.cpp
index 8c9d3557f8..a0c64feb09 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1209,7 +1209,15 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
}
}
- if (c.flags & CONNECT_ONESHOT) {
+ bool disconnect = c.flags & CONNECT_ONESHOT;
+#ifdef TOOLS_ENABLED
+ if (disconnect && (c.flags & CONNECT_PERSIST) && Engine::get_singleton()->is_editor_hint()) {
+ //this signal was connected from the editor, and is being edited. just dont disconnect for now
+ disconnect = false;
+ }
+#endif
+ if (disconnect) {
+
_ObjectSignalDisconnectData dd;
dd.signal = p_name;
dd.target = target;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index e94ccb4f48..12c6ef7d3b 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -949,6 +949,14 @@ bool InputEventAction::is_pressed() const {
return pressed;
}
+bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event) const {
+ Ref<InputEventKey> event = p_event;
+ if (event.is_null())
+ return false;
+
+ return event->is_action(action);
+}
+
bool InputEventAction::is_action(const StringName &p_action) const {
return action == p_action;
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 04126fee77..07df81488b 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -480,6 +480,7 @@ public:
virtual bool is_action(const StringName &p_action) const;
+ virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
virtual bool is_action_type() const { return true; }
virtual String as_text() const;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 8dcf0990fc..97dae05919 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -577,6 +577,13 @@ bool OS::has_feature(const String &p_feature) {
if (p_feature == "release")
return true;
#endif
+#ifdef TOOLS_ENABLED
+ if (p_feature == "editor")
+ return true;
+#else
+ if (p_feature == "standalone")
+ return true;
+#endif
if (sizeof(void *) == 8 && p_feature == "64") {
return true;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 9bcc2d4530..0e7e63dbd8 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -41,6 +41,7 @@
#include "input_map.h"
#include "io/config_file.h"
#include "io/http_client.h"
+#include "io/image_loader.h"
#include "io/marshalls.h"
#include "io/multiplayer_api.h"
#include "io/networked_multiplayer_peer.h"
@@ -60,11 +61,14 @@
#include "path_remap.h"
#include "project_settings.h"
#include "translation.h"
+
#include "undo_redo.h"
static ResourceFormatSaverBinary *resource_saver_binary = NULL;
static ResourceFormatLoaderBinary *resource_loader_binary = NULL;
static ResourceFormatImporter *resource_format_importer = NULL;
+static ResourceFormatLoaderImage *resource_format_image = NULL;
+
static _ResourceLoader *_resource_loader = NULL;
static _ResourceSaver *_resource_saver = NULL;
static _OS *_os = NULL;
@@ -111,6 +115,9 @@ void register_core_types() {
resource_format_importer = memnew(ResourceFormatImporter);
ResourceLoader::add_resource_format_loader(resource_format_importer);
+ resource_format_image = memnew(ResourceFormatLoaderImage);
+ ResourceLoader::add_resource_format_loader(resource_format_image);
+
ClassDB::register_class<Object>();
ClassDB::register_virtual_class<Script>();
@@ -237,6 +244,8 @@ void unregister_core_types() {
memdelete(_geometry);
+ if (resource_format_image)
+ memdelete(resource_format_image);
if (resource_saver_binary)
memdelete(resource_saver_binary);
if (resource_loader_binary)