summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/json.cpp32
-rw-r--r--core/io/json.h23
-rw-r--r--core/math/expression.cpp713
-rw-r--r--core/math/expression.h82
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/string/ustring.h20
-rw-r--r--core/variant/array.cpp5
-rw-r--r--core/variant/array.h1
-rw-r--r--core/variant/variant.cpp26
-rw-r--r--core/variant/variant.h29
-rw-r--r--core/variant/variant_builtin_funcs.cpp1392
-rw-r--r--core/variant/variant_call.cpp21
-rw-r--r--core/variant/variant_construct.cpp20
-rw-r--r--doc/classes/AABB.xml30
-rw-r--r--doc/classes/Array.xml102
-rw-r--r--doc/classes/Basis.xml52
-rw-r--r--doc/classes/Callable.xml22
-rw-r--r--doc/classes/Color.xml102
-rw-r--r--doc/classes/Dictionary.xml28
-rw-r--r--doc/classes/EditorPlugin.xml54
-rw-r--r--doc/classes/NodePath.xml22
-rw-r--r--doc/classes/PackedByteArray.xml38
-rw-r--r--doc/classes/PackedColorArray.xml38
-rw-r--r--doc/classes/PackedFloat32Array.xml30
-rw-r--r--doc/classes/PackedFloat64Array.xml38
-rw-r--r--doc/classes/PackedInt32Array.xml38
-rw-r--r--doc/classes/PackedInt64Array.xml38
-rw-r--r--doc/classes/PackedStringArray.xml38
-rw-r--r--doc/classes/PackedVector2Array.xml46
-rw-r--r--doc/classes/PackedVector3Array.xml46
-rw-r--r--doc/classes/Plane.xml40
-rw-r--r--doc/classes/Quat.xml106
-rw-r--r--doc/classes/RID.xml52
-rw-r--r--doc/classes/Rect2.xml34
-rw-r--r--doc/classes/Rect2i.xml26
-rw-r--r--doc/classes/Signal.xml22
-rw-r--r--doc/classes/String.xml88
-rw-r--r--doc/classes/StringName.xml38
-rw-r--r--doc/classes/Transform.xml56
-rw-r--r--doc/classes/Transform2D.xml64
-rw-r--r--doc/classes/Vector2.xml148
-rw-r--r--doc/classes/Vector2i.xml156
-rw-r--r--doc/classes/Vector3.xml164
-rw-r--r--doc/classes/Vector3i.xml156
-rw-r--r--doc/classes/bool.xml40
-rw-r--r--doc/classes/float.xml228
-rw-r--r--doc/classes/int.xml282
-rwxr-xr-xdoc/tools/doc_merge.py237
-rwxr-xr-xdoc/tools/makerst.py2
-rw-r--r--editor/doc_data.cpp65
-rw-r--r--editor/editor_plugin.cpp2
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj79
-rw-r--r--modules/SCsub9
-rw-r--r--modules/arkit/arkit.gdip18
-rw-r--r--modules/arkit/arkit_module.cpp (renamed from modules/arkit/register_types.cpp)4
-rw-r--r--modules/arkit/arkit_module.h (renamed from modules/arkit/register_types.h)2
-rw-r--r--modules/camera/SCsub12
-rw-r--r--modules/camera/config.py2
-rw-r--r--modules/camera/register_types.cpp6
-rw-r--r--modules/camera_iphone/SCsub15
-rw-r--r--modules/camera_iphone/camera.gdip18
-rw-r--r--modules/camera_iphone/camera_ios.h (renamed from modules/camera/camera_ios.h)0
-rw-r--r--modules/camera_iphone/camera_ios.mm (renamed from modules/camera/camera_ios.mm)0
-rw-r--r--modules/camera_iphone/camera_module.cpp40
-rw-r--r--modules/camera_iphone/camera_module.h32
-rw-r--r--modules/camera_iphone/config.py6
-rw-r--r--modules/gamecenter/SCsub15
-rw-r--r--modules/gamecenter/config.py6
-rw-r--r--modules/gamecenter/game_center.h (renamed from platform/iphone/game_center.h)4
-rw-r--r--modules/gamecenter/game_center.mm (renamed from platform/iphone/game_center.mm)37
-rw-r--r--modules/gamecenter/game_center_delegate.h35
-rw-r--r--modules/gamecenter/game_center_delegate.mm45
-rw-r--r--modules/gamecenter/game_center_module.cpp48
-rw-r--r--modules/gamecenter/game_center_module.h32
-rw-r--r--modules/gamecenter/gamecenter.gdip17
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml9
-rw-r--r--modules/gdscript/gdscript_editor.cpp5
-rw-r--r--modules/gdscript/gdscript_parser.cpp40
-rw-r--r--modules/icloud/SCsub15
-rw-r--r--modules/icloud/config.py6
-rw-r--r--modules/icloud/icloud.gdip17
-rw-r--r--modules/icloud/icloud.h (renamed from platform/iphone/icloud.h)4
-rw-r--r--modules/icloud/icloud.mm (renamed from platform/iphone/icloud.mm)14
-rw-r--r--modules/icloud/icloud_module.cpp48
-rw-r--r--modules/icloud/icloud_module.h32
-rw-r--r--modules/inappstore/SCsub15
-rw-r--r--modules/inappstore/config.py6
-rw-r--r--modules/inappstore/in_app_store.h (renamed from platform/iphone/in_app_store.h)4
-rw-r--r--modules/inappstore/in_app_store.mm (renamed from platform/iphone/in_app_store.mm)4
-rw-r--r--modules/inappstore/in_app_store_module.cpp48
-rw-r--r--modules/inappstore/in_app_store_module.h32
-rw-r--r--modules/inappstore/inappstore.gdip17
-rw-r--r--modules/mono/glue/gd_glue.cpp3
-rw-r--r--platform/iphone/SCsub3
-rw-r--r--platform/iphone/app_delegate.mm1
-rw-r--r--platform/iphone/detect.py15
-rw-r--r--platform/iphone/export/export.cpp660
-rw-r--r--platform/iphone/os_iphone.h15
-rw-r--r--platform/iphone/os_iphone.mm35
-rw-r--r--platform/iphone/plugin/godot_plugin_config.h265
-rw-r--r--platform/iphone/view_controller.h3
-rw-r--r--platform/iphone/view_controller.mm11
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp2
-rw-r--r--thirdparty/jpeg-compressor/jpgd.cpp8
104 files changed, 5310 insertions, 1643 deletions
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 58bce1cf63..d61c2b8236 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -455,3 +455,35 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &
return err;
}
+
+Error JSONParser::parse_string(const String &p_json_string) {
+ return JSON::parse(p_json_string, data, err_text, err_line);
+}
+String JSONParser::get_error_text() const {
+ return err_text;
+}
+int JSONParser::get_error_line() const {
+ return err_line;
+}
+Variant JSONParser::get_data() const {
+ return data;
+}
+
+Error JSONParser::decode_data(const Variant &p_data, const String &p_indent, bool p_sort_keys) {
+ string = JSON::print(p_data, p_indent, p_sort_keys);
+ data = p_data;
+ return OK;
+}
+
+String JSONParser::get_string() const {
+ return string;
+}
+
+void JSONParser::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("parse_string", "json_string"), &JSONParser::parse_string);
+ ClassDB::bind_method(D_METHOD("get_error_text"), &JSONParser::get_error_text);
+ ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParser::get_error_line);
+ ClassDB::bind_method(D_METHOD("get_data"), &JSONParser::get_data);
+ ClassDB::bind_method(D_METHOD("decode_data", "data", "indent", "sort_keys"), &JSONParser::decode_data, DEFVAL(""), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_string"), &JSONParser::get_string);
+}
diff --git a/core/io/json.h b/core/io/json.h
index 9fc6655fb4..2854d956ec 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,8 +31,8 @@
#ifndef JSON_H
#define JSON_H
+#include "core/object/reference.h"
#include "core/variant/variant.h"
-
class JSON {
enum TokenType {
TK_CURLY_BRACKET_OPEN,
@@ -75,4 +75,25 @@ public:
static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
};
+class JSONParser : public Reference {
+ GDCLASS(JSONParser, Reference);
+
+ Variant data;
+ String string;
+ String err_text;
+ int err_line = 0;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Error parse_string(const String &p_json_string);
+ String get_error_text() const;
+ int get_error_line() const;
+ Variant get_data() const;
+
+ Error decode_data(const Variant &p_data, const String &p_indent = "", bool p_sort_keys = true);
+ String get_string() const;
+};
+
#endif // JSON_H
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 48ad73bd32..13c8904f7e 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -37,688 +37,6 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
-const char *Expression::func_name[Expression::FUNC_MAX] = {
- "sin",
- "cos",
- "tan",
- "sinh",
- "cosh",
- "tanh",
- "asin",
- "acos",
- "atan",
- "atan2",
- "sqrt",
- "fmod",
- "fposmod",
- "posmod",
- "floor",
- "ceil",
- "round",
- "abs",
- "sign",
- "pow",
- "log",
- "exp",
- "is_nan",
- "is_inf",
- "ease",
- "step_decimals",
- "stepify",
- "lerp",
- "lerp_angle",
- "inverse_lerp",
- "range_lerp",
- "smoothstep",
- "move_toward",
- "dectime",
- "randomize",
- "randi",
- "randf",
- "randf_range",
- "randi_range",
- "seed",
- "rand_seed",
- "deg2rad",
- "rad2deg",
- "linear2db",
- "db2linear",
- "polar2cartesian",
- "cartesian2polar",
- "wrapi",
- "wrapf",
- "max",
- "min",
- "clamp",
- "nearest_po2",
- "weakref",
- "convert",
- "typeof",
- "type_exists",
- "char",
- "ord",
- "str",
- "print",
- "printerr",
- "printraw",
- "var2str",
- "str2var",
- "var2bytes",
- "bytes2var",
- "color_named",
-};
-
-Expression::BuiltinFunc Expression::find_function(const String &p_string) {
- for (int i = 0; i < FUNC_MAX; i++) {
- if (p_string == func_name[i]) {
- return BuiltinFunc(i);
- }
- }
-
- return FUNC_MAX;
-}
-
-String Expression::get_func_name(BuiltinFunc p_func) {
- ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String());
- return func_name[p_func];
-}
-
-int Expression::get_func_argument_count(BuiltinFunc p_func) {
- switch (p_func) {
- case MATH_RANDOMIZE:
- case MATH_RANDI:
- case MATH_RANDF:
- return 0;
- case MATH_SIN:
- case MATH_COS:
- case MATH_TAN:
- case MATH_SINH:
- case MATH_COSH:
- case MATH_TANH:
- case MATH_ASIN:
- case MATH_ACOS:
- case MATH_ATAN:
- case MATH_SQRT:
- case MATH_FLOOR:
- case MATH_CEIL:
- case MATH_ROUND:
- case MATH_ABS:
- case MATH_SIGN:
- case MATH_LOG:
- case MATH_EXP:
- case MATH_ISNAN:
- case MATH_ISINF:
- case MATH_STEP_DECIMALS:
- case MATH_SEED:
- case MATH_RANDSEED:
- case MATH_DEG2RAD:
- case MATH_RAD2DEG:
- case MATH_LINEAR2DB:
- case MATH_DB2LINEAR:
- case LOGIC_NEAREST_PO2:
- case OBJ_WEAKREF:
- case TYPE_OF:
- case TEXT_CHAR:
- case TEXT_ORD:
- case TEXT_STR:
- case TEXT_PRINT:
- case TEXT_PRINTERR:
- case TEXT_PRINTRAW:
- case VAR_TO_STR:
- case STR_TO_VAR:
- case TYPE_EXISTS:
- return 1;
- case VAR_TO_BYTES:
- case BYTES_TO_VAR:
- case MATH_ATAN2:
- case MATH_FMOD:
- case MATH_FPOSMOD:
- case MATH_POSMOD:
- case MATH_POW:
- case MATH_EASE:
- case MATH_STEPIFY:
- case MATH_RANDF_RANGE:
- case MATH_RANDI_RANGE:
- case MATH_POLAR2CARTESIAN:
- case MATH_CARTESIAN2POLAR:
- case LOGIC_MAX:
- case LOGIC_MIN:
- case TYPE_CONVERT:
- case COLORN:
- return 2;
- case MATH_LERP:
- case MATH_LERP_ANGLE:
- case MATH_INVERSE_LERP:
- case MATH_SMOOTHSTEP:
- case MATH_MOVE_TOWARD:
- case MATH_DECTIME:
- case MATH_WRAP:
- case MATH_WRAPF:
- case LOGIC_CLAMP:
- return 3;
- case MATH_RANGE_LERP:
- return 5;
- case FUNC_MAX: {
- }
- }
- return 0;
-}
-
-#define VALIDATE_ARG_NUM(m_arg) \
- if (!p_inputs[m_arg]->is_num()) { \
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \
- r_error.argument = m_arg; \
- r_error.expected = Variant::FLOAT; \
- return; \
- }
-
-void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str) {
- r_error.error = Callable::CallError::CALL_OK;
- switch (p_func) {
- case MATH_SIN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sin((double)*p_inputs[0]);
- } break;
- case MATH_COS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::cos((double)*p_inputs[0]);
- } break;
- case MATH_TAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::tan((double)*p_inputs[0]);
- } break;
- case MATH_SINH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sinh((double)*p_inputs[0]);
- } break;
- case MATH_COSH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::cosh((double)*p_inputs[0]);
- } break;
- case MATH_TANH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::tanh((double)*p_inputs[0]);
- } break;
- case MATH_ASIN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::asin((double)*p_inputs[0]);
- } break;
- case MATH_ACOS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::acos((double)*p_inputs[0]);
- } break;
- case MATH_ATAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::atan((double)*p_inputs[0]);
- } break;
- case MATH_ATAN2: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_SQRT: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sqrt((double)*p_inputs[0]);
- } break;
- case MATH_FMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_FPOSMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_POSMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]);
- } break;
- case MATH_FLOOR: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::floor((double)*p_inputs[0]);
- } break;
- case MATH_CEIL: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::ceil((double)*p_inputs[0]);
- } break;
- case MATH_ROUND: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::round((double)*p_inputs[0]);
- } break;
- case MATH_ABS: {
- if (p_inputs[0]->get_type() == Variant::INT) {
- int64_t i = *p_inputs[0];
- *r_return = ABS(i);
- } else if (p_inputs[0]->get_type() == Variant::FLOAT) {
- real_t r = *p_inputs[0];
- *r_return = Math::abs(r);
- } else {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::FLOAT;
- }
- } break;
- case MATH_SIGN: {
- if (p_inputs[0]->get_type() == Variant::INT) {
- int64_t i = *p_inputs[0];
- *r_return = i < 0 ? -1 : (i > 0 ? +1 : 0);
- } else if (p_inputs[0]->get_type() == Variant::FLOAT) {
- real_t r = *p_inputs[0];
- *r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0);
- } else {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::FLOAT;
- }
- } break;
- case MATH_POW: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_LOG: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::log((double)*p_inputs[0]);
- } break;
- case MATH_EXP: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::exp((double)*p_inputs[0]);
- } break;
- case MATH_ISNAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::is_nan((double)*p_inputs[0]);
- } break;
- case MATH_ISINF: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::is_inf((double)*p_inputs[0]);
- } break;
- case MATH_EASE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_STEP_DECIMALS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::step_decimals((double)*p_inputs[0]);
- } break;
- case MATH_STEPIFY: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_LERP_ANGLE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_INVERSE_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_RANGE_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- VALIDATE_ARG_NUM(3);
- VALIDATE_ARG_NUM(4);
- *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]);
- } break;
- case MATH_SMOOTHSTEP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_MOVE_TOWARD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_DECTIME: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::dectime((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_RANDOMIZE: {
- Math::randomize();
-
- } break;
- case MATH_RANDI: {
- *r_return = Math::rand();
- } break;
- case MATH_RANDF: {
- *r_return = Math::randf();
- } break;
- case MATH_RANDF_RANGE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_RANDI_RANGE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::random((int)*p_inputs[0], (int)*p_inputs[1]);
- } break;
- case MATH_SEED: {
- VALIDATE_ARG_NUM(0);
- uint64_t seed = *p_inputs[0];
- Math::seed(seed);
-
- } break;
- case MATH_RANDSEED: {
- VALIDATE_ARG_NUM(0);
- uint64_t seed = *p_inputs[0];
- int ret = Math::rand_from_seed(&seed);
- Array reta;
- reta.push_back(ret);
- reta.push_back(seed);
- *r_return = reta;
-
- } break;
- case MATH_DEG2RAD: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::deg2rad((double)*p_inputs[0]);
- } break;
- case MATH_RAD2DEG: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::rad2deg((double)*p_inputs[0]);
- } break;
- case MATH_LINEAR2DB: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::linear2db((double)*p_inputs[0]);
- } break;
- case MATH_DB2LINEAR: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::db2linear((double)*p_inputs[0]);
- } break;
- case MATH_POLAR2CARTESIAN: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- double r = *p_inputs[0];
- double th = *p_inputs[1];
- *r_return = Vector2(r * Math::cos(th), r * Math::sin(th));
- } break;
- case MATH_CARTESIAN2POLAR: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- double x = *p_inputs[0];
- double y = *p_inputs[1];
- *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
- } break;
- case MATH_WRAP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]);
- } break;
- case MATH_WRAPF: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case LOGIC_MAX: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- *r_return = MAX(a, b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
-
- *r_return = MAX(a, b);
- }
-
- } break;
- case LOGIC_MIN: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- *r_return = MIN(a, b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
-
- *r_return = MIN(a, b);
- }
- } break;
- case LOGIC_CLAMP: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- int64_t c = *p_inputs[2];
- *r_return = CLAMP(a, b, c);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
- real_t c = *p_inputs[2];
-
- *r_return = CLAMP(a, b, c);
- }
- } break;
- case LOGIC_NEAREST_PO2: {
- VALIDATE_ARG_NUM(0);
- int64_t num = *p_inputs[0];
- *r_return = next_power_of_2(num);
- } break;
- case OBJ_WEAKREF: {
- if (p_inputs[0]->get_type() != Variant::OBJECT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::OBJECT;
-
- return;
- }
-
- if (p_inputs[0]->is_ref()) {
- REF r = *p_inputs[0];
- if (!r.is_valid()) {
- return;
- }
-
- Ref<WeakRef> wref = memnew(WeakRef);
- wref->set_ref(r);
- *r_return = wref;
- } else {
- Object *obj = *p_inputs[0];
- if (!obj) {
- return;
- }
- Ref<WeakRef> wref = memnew(WeakRef);
- wref->set_obj(obj);
- *r_return = wref;
- }
-
- } break;
- case TYPE_CONVERT: {
- VALIDATE_ARG_NUM(1);
- int type = *p_inputs[1];
- if (type < 0 || type >= Variant::VARIANT_MAX) {
- r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants.");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::INT;
- return;
-
- } else {
- Variant::construct(Variant::Type(type), *r_return, p_inputs, 1, r_error);
- }
- } break;
- case TYPE_OF: {
- *r_return = p_inputs[0]->get_type();
-
- } break;
- case TYPE_EXISTS: {
- *r_return = ClassDB::class_exists(*p_inputs[0]);
-
- } break;
- case TEXT_CHAR: {
- char32_t result[2] = { *p_inputs[0], 0 };
-
- *r_return = String(result);
-
- } break;
- case TEXT_ORD: {
- if (p_inputs[0]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- String str = *p_inputs[0];
-
- if (str.length() != 1) {
- r_error_str = RTR("Expected a string of length 1 (a character).");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- *r_return = str.get(0);
-
- } break;
- case TEXT_STR: {
- String str = *p_inputs[0];
-
- *r_return = str;
-
- } break;
- case TEXT_PRINT: {
- String str = *p_inputs[0];
- print_line(str);
-
- } break;
-
- case TEXT_PRINTERR: {
- String str = *p_inputs[0];
- print_error(str);
-
- } break;
- case TEXT_PRINTRAW: {
- String str = *p_inputs[0];
- OS::get_singleton()->print("%s", str.utf8().get_data());
-
- } break;
- case VAR_TO_STR: {
- String vars;
- VariantWriter::write_to_string(*p_inputs[0], vars);
- *r_return = vars;
- } break;
- case STR_TO_VAR: {
- if (p_inputs[0]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- VariantParser::StreamString ss;
- ss.s = *p_inputs[0];
-
- String errs;
- int line;
- Error err = VariantParser::parse(&ss, *r_return, errs, line);
-
- if (err != OK) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
- *r_return = "Parse error at line " + itos(line) + ": " + errs;
- return;
- }
-
- } break;
- case VAR_TO_BYTES: {
- PackedByteArray barr;
- bool full_objects = *p_inputs[1];
- int len;
- Error err = encode_variant(*p_inputs[0], nullptr, len, full_objects);
- if (err) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::NIL;
- r_error_str = "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).";
- return;
- }
-
- barr.resize(len);
- {
- uint8_t *w = barr.ptrw();
- encode_variant(*p_inputs[0], w, len, full_objects);
- }
- *r_return = barr;
- } break;
- case BYTES_TO_VAR: {
- if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::PACKED_BYTE_ARRAY;
-
- return;
- }
-
- PackedByteArray varr = *p_inputs[0];
- bool allow_objects = *p_inputs[1];
- Variant ret;
- {
- const uint8_t *r = varr.ptr();
- Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects);
- if (err != OK) {
- r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format.");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::PACKED_BYTE_ARRAY;
- return;
- }
- }
-
- *r_return = ret;
-
- } break;
- case COLORN: {
- VALIDATE_ARG_NUM(1);
-
- Color color = Color::named(*p_inputs[0]);
- color.a = *p_inputs[1];
-
- *r_return = String(color);
-
- } break;
- default: {
- }
- }
-}
-
-////////
-
static bool _is_number(char32_t c) {
return (c >= '0' && c <= '9');
}
@@ -1092,18 +410,9 @@ Error Expression::_get_token(Token &r_token) {
} else if (id == "self") {
r_token.type = TK_SELF;
} else {
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (id == Variant::get_type_name(Variant::Type(i))) {
- r_token.type = TK_BASIC_TYPE;
- r_token.value = i;
- return OK;
- }
- }
-
- BuiltinFunc bifunc = find_function(id);
- if (bifunc != FUNC_MAX) {
+ if (Variant::has_builtin_func(id)) {
r_token.type = TK_BUILTIN_FUNC;
- r_token.value = bifunc;
+ r_token.value = id;
return OK;
}
@@ -1401,6 +710,8 @@ Expression::ENode *Expression::_parse_expression() {
case TK_BUILTIN_FUNC: {
//builtin function
+ StringName func = tk.value;
+
_get_token(tk);
if (tk.type != TK_PARENTHESIS_OPEN) {
_set_error("Expected '('");
@@ -1408,7 +719,7 @@ Expression::ENode *Expression::_parse_expression() {
}
BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>();
- bifunc->func = BuiltinFunc(int(tk.value));
+ bifunc->func = func;
while (true) {
int cofs = str_ofs;
@@ -1436,9 +747,11 @@ Expression::ENode *Expression::_parse_expression() {
}
}
- int expected_args = get_func_argument_count(bifunc->func);
- if (bifunc->arguments.size() != expected_args) {
- _set_error("Builtin func '" + get_func_name(bifunc->func) + "' expects " + itos(expected_args) + " arguments.");
+ if (!Variant::is_builtin_func_vararg(bifunc->func)) {
+ int expected_args = Variant::get_builtin_func_argument_count(bifunc->func);
+ if (expected_args != bifunc->arguments.size()) {
+ _set_error("Builtin func '" + String(bifunc->func) + "' expects " + itos(expected_args) + " arguments.");
+ }
}
expr = bifunc;
@@ -2047,11 +1360,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
argp.write[i] = &arr[i];
}
+ r_ret = Variant(); //may not return anything
Callable::CallError ce;
- exec_func(bifunc->func, (const Variant **)argp.ptr(), &r_ret, ce, r_error_str);
-
+ Variant::call_builtin_func(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
- r_error_str = "Builtin Call Failed. " + r_error_str;
+ r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
return true;
}
diff --git a/core/math/expression.h b/core/math/expression.h
index 991554f4fd..d9cedb8c2c 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -36,87 +36,7 @@
class Expression : public Reference {
GDCLASS(Expression, Reference);
-public:
- enum BuiltinFunc {
- MATH_SIN,
- MATH_COS,
- MATH_TAN,
- MATH_SINH,
- MATH_COSH,
- MATH_TANH,
- MATH_ASIN,
- MATH_ACOS,
- MATH_ATAN,
- MATH_ATAN2,
- MATH_SQRT,
- MATH_FMOD,
- MATH_FPOSMOD,
- MATH_POSMOD,
- MATH_FLOOR,
- MATH_CEIL,
- MATH_ROUND,
- MATH_ABS,
- MATH_SIGN,
- MATH_POW,
- MATH_LOG,
- MATH_EXP,
- MATH_ISNAN,
- MATH_ISINF,
- MATH_EASE,
- MATH_STEP_DECIMALS,
- MATH_STEPIFY,
- MATH_LERP,
- MATH_LERP_ANGLE,
- MATH_INVERSE_LERP,
- MATH_RANGE_LERP,
- MATH_SMOOTHSTEP,
- MATH_MOVE_TOWARD,
- MATH_DECTIME,
- MATH_RANDOMIZE,
- MATH_RANDI,
- MATH_RANDF,
- MATH_RANDF_RANGE,
- MATH_RANDI_RANGE,
- MATH_SEED,
- MATH_RANDSEED,
- MATH_DEG2RAD,
- MATH_RAD2DEG,
- MATH_LINEAR2DB,
- MATH_DB2LINEAR,
- MATH_POLAR2CARTESIAN,
- MATH_CARTESIAN2POLAR,
- MATH_WRAP,
- MATH_WRAPF,
- LOGIC_MAX,
- LOGIC_MIN,
- LOGIC_CLAMP,
- LOGIC_NEAREST_PO2,
- OBJ_WEAKREF,
- TYPE_CONVERT,
- TYPE_OF,
- TYPE_EXISTS,
- TEXT_CHAR,
- TEXT_ORD,
- TEXT_STR,
- TEXT_PRINT,
- TEXT_PRINTERR,
- TEXT_PRINTRAW,
- VAR_TO_STR,
- STR_TO_VAR,
- VAR_TO_BYTES,
- BYTES_TO_VAR,
- COLORN,
- FUNC_MAX
- };
-
- static int get_func_argument_count(BuiltinFunc p_func);
- static String get_func_name(BuiltinFunc p_func);
- static void exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str);
- static BuiltinFunc find_function(const String &p_string);
-
private:
- static const char *func_name[FUNC_MAX];
-
struct Input {
Variant::Type type = Variant::NIL;
String name;
@@ -315,7 +235,7 @@ private:
};
struct BuiltinFuncNode : public ENode {
- BuiltinFunc func;
+ StringName func;
Vector<ENode *> arguments;
BuiltinFuncNode() {
type = TYPE_BUILTIN_FUNC;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 6bbdad11f8..7e32f215e7 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -43,6 +43,7 @@
#include "core/io/dtls_server.h"
#include "core/io/http_client.h"
#include "core/io/image_loader.h"
+#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/io/multiplayer_api.h"
#include "core/io/networked_multiplayer_peer.h"
@@ -197,6 +198,7 @@ void register_core_types() {
ClassDB::register_class<_Semaphore>();
ClassDB::register_class<XMLParser>();
+ ClassDB::register_class<JSONParser>();
ClassDB::register_class<ConfigFile>();
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 201b439b12..b46733ab66 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -536,4 +536,24 @@ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const St
bool is_symbol(char32_t c);
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
+}
+
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
+ arr.push_back(p_str);
+}
+
+template <class... P>
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
+ arr.push_back(p_str);
+ sarray_add_str(arr, p_args...);
+}
+
+template <class... P>
+_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
+ Vector<String> arr;
+ sarray_add_str(arr, p_args...);
+ return arr;
+}
+
#endif // USTRING_H
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 04ee47efff..79bc01b89c 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -192,6 +192,11 @@ void Array::push_back(const Variant &p_value) {
_p->array.push_back(p_value);
}
+void Array::append_array(const Array &p_array) {
+ ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array"));
+ _p->array.append_array(p_array._p->array);
+}
+
Error Array::resize(int p_new_size) {
return _p->array.resize(p_new_size);
}
diff --git a/core/variant/array.h b/core/variant/array.h
index b37d600abd..e01ac13168 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -68,6 +68,7 @@ public:
void push_back(const Variant &p_value);
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
+ void append_array(const Array &p_array);
Error resize(int p_new_size);
void insert(int p_pos, const Variant &p_value);
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 3114a358f7..055f61cf92 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3435,6 +3435,30 @@ String Variant::get_construct_string() const {
return vars;
}
+String Variant::get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
+ String err_text;
+
+ if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ int errorarg = ce.argument;
+ if (p_argptrs) {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ } else {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ }
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
+ err_text = "Method not found.";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ err_text = "Instance is null";
+ } else if (ce.error == Callable::CallError::CALL_OK) {
+ return "Call OK";
+ }
+ return "'" + String(p_method) + "': " + err_text;
+}
+
String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
String err_text;
@@ -3525,10 +3549,12 @@ void Variant::register_types() {
_register_variant_methods();
_register_variant_setters_getters();
_register_variant_constructors();
+ _register_variant_builtin_funcs();
}
void Variant::unregister_types() {
_unregister_variant_operators();
_unregister_variant_methods();
_unregister_variant_setters_getters();
_unregister_variant_constructors();
+ _unregister_variant_builtin_funcs();
}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index ee08373b27..d3e2f84357 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -267,6 +267,8 @@ private:
static void _unregister_variant_setters_getters();
static void _register_variant_constructors();
static void _unregister_variant_constructors();
+ static void _register_variant_builtin_funcs();
+ static void _unregister_variant_builtin_funcs();
public:
_FORCE_INLINE_ Type get_type() const {
@@ -523,6 +525,7 @@ public:
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
+ static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
@@ -619,6 +622,32 @@ public:
void get_property_list(List<PropertyInfo> *p_list) const;
+ static void call_builtin_func(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ static bool has_builtin_func(const StringName &p_name);
+
+ typedef void (*BuiltinFunctionValidatedCall)(Variant *r_ret, const Variant **p_args, int p_argcount);
+ typedef void (*BuiltinFunctionPTRCall)(void *r_ret, const void **p_args, int p_argcount);
+
+ static BuiltinFunctionValidatedCall get_builtin_validated_caller(const StringName &p_name);
+ static BuiltinFunctionPTRCall get_builtin_ptr_caller(const StringName &p_name);
+
+ enum BuiltInFunctionType {
+ BUILTIN_FUNC_TYPE_MATH,
+ BUILTIN_FUNC_TYPE_RANDOM,
+ BUILTIN_FUNC_TYPE_UTILITY,
+ };
+
+ static BuiltInFunctionType get_builtin_func_type(const StringName &p_name);
+
+ static int get_builtin_func_argument_count(const StringName &p_name);
+ static Variant::Type get_builtin_func_argument_type(const StringName &p_name, int p_arg);
+ static String get_builtin_func_argument_name(const StringName &p_name, int p_arg);
+ static bool has_builtin_func_return_value(const StringName &p_name);
+ static Variant::Type get_builtin_func_return_type(const StringName &p_name);
+ static bool is_builtin_func_vararg(const StringName &p_name);
+
+ static void get_builtin_function_list(List<StringName> *r_functions);
+
//argsVariant call()
bool operator==(const Variant &p_variant) const;
diff --git a/core/variant/variant_builtin_funcs.cpp b/core/variant/variant_builtin_funcs.cpp
new file mode 100644
index 0000000000..e89b83e6dd
--- /dev/null
+++ b/core/variant/variant_builtin_funcs.cpp
@@ -0,0 +1,1392 @@
+/*************************************************************************/
+/* variant_builtin_funcs.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/io/marshalls.h"
+#include "core/object/reference.h"
+#include "core/os/os.h"
+#include "core/templates/oa_hash_map.h"
+#include "core/variant/binder_common.h"
+#include "core/variant/variant_parser.h"
+
+struct VariantBuiltinFunctions {
+ // Math
+ static inline double sin(double arg) {
+ return Math::sin(arg);
+ }
+ static inline double cos(double arg) {
+ return Math::cos(arg);
+ }
+ static inline double tan(double arg) {
+ return Math::tan(arg);
+ }
+
+ static inline double sinh(double arg) {
+ return Math::sinh(arg);
+ }
+ static inline double cosh(double arg) {
+ return Math::cosh(arg);
+ }
+ static inline double tanh(double arg) {
+ return Math::tanh(arg);
+ }
+
+ static inline double asin(double arg) {
+ return Math::asin(arg);
+ }
+ static inline double acos(double arg) {
+ return Math::acos(arg);
+ }
+ static inline double atan(double arg) {
+ return Math::atan(arg);
+ }
+
+ static inline double atan2(double y, double x) {
+ return Math::atan2(y, x);
+ }
+
+ static inline double sqrt(double x) {
+ return Math::sqrt(x);
+ }
+
+ static inline double fmod(double b, double r) {
+ return Math::fmod(b, r);
+ }
+
+ static inline double fposmod(double b, double r) {
+ return Math::fposmod(b, r);
+ }
+
+ static inline double floor(double x) {
+ return Math::floor(x);
+ }
+
+ static inline double ceil(double x) {
+ return Math::ceil(x);
+ }
+
+ static inline double round(double x) {
+ return Math::round(x);
+ }
+
+ static inline Variant abs(const Variant &x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return ABS(VariantInternalAccessor<int64_t>::get(&x));
+ } break;
+ case Variant::FLOAT: {
+ return Math::absd(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).abs();
+ } break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x).abs();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).abs();
+ } break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x).abs();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double absf(double x) {
+ return Math::absd(x);
+ }
+
+ static inline int64_t absi(int64_t x) {
+ return ABS(x);
+ }
+
+ static inline Variant sign(const Variant &x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return SGN(VariantInternalAccessor<int64_t>::get(&x));
+ } break;
+ case Variant::FLOAT: {
+ return SGN(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).sign();
+ } break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x).sign();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).sign();
+ } break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x).sign();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double signf(double x) {
+ return SGN(x);
+ }
+
+ static inline int64_t signi(int64_t x) {
+ return SGN(x);
+ }
+
+ static inline double pow(double x, double y) {
+ return Math::pow(x, y);
+ }
+ static inline double log(double x) {
+ return Math::log(x);
+ }
+
+ static inline double exp(double x) {
+ return Math::exp(x);
+ }
+
+ static inline double is_nan(double x) {
+ return Math::is_nan(x);
+ }
+
+ static inline double is_inf(double x) {
+ return Math::is_inf(x);
+ }
+
+ static inline double is_equal_approx(double x, double y) {
+ return Math::is_equal_approx(x, y);
+ }
+
+ static inline double is_zero_approx(double x) {
+ return Math::is_zero_approx(x);
+ }
+
+ static inline double ease(float x, float c) {
+ return Math::ease(x, c);
+ }
+
+ static inline int step_decimals(float step) {
+ return Math::step_decimals(step);
+ }
+
+ static inline int range_step_decimals(float step) {
+ return Math::range_step_decimals(step);
+ }
+
+ static inline double stepify(double value, double step) {
+ return Math::stepify(value, step);
+ }
+
+ static inline double lerp(double from, double to, double weight) {
+ return Math::lerp(from, to, weight);
+ }
+
+ static inline double lerp_angle(double from, double to, double weight) {
+ return Math::lerp_angle(from, to, weight);
+ }
+
+ static inline double inverse_lerp(double from, double to, double weight) {
+ return Math::inverse_lerp(from, to, weight);
+ }
+
+ static inline double range_lerp(double value, double istart, double istop, double ostart, double ostop) {
+ return Math::range_lerp(value, istart, istop, ostart, ostop);
+ }
+
+ static inline double smoothstep(double from, double to, double val) {
+ return Math::smoothstep(from, to, val);
+ }
+
+ static inline double move_toward(double from, double to, double delta) {
+ return Math::move_toward(from, to, delta);
+ }
+
+ static inline double dectime(double value, double amount, double step) {
+ return Math::dectime(value, amount, step);
+ }
+
+ static inline double deg2rad(double angle_deg) {
+ return Math::deg2rad(angle_deg);
+ }
+
+ static inline double rad2deg(double angle_rad) {
+ return Math::rad2deg(angle_rad);
+ }
+
+ static inline double linear2db(double linear) {
+ return Math::linear2db(linear);
+ }
+
+ static inline double db2linear(double db) {
+ return Math::db2linear(db);
+ }
+
+ static inline Vector2 polar2cartesian(double r, double th) {
+ return Vector2(r * Math::cos(th), r * Math::sin(th));
+ }
+
+ static inline Vector2 cartesian2polar(double x, double y) {
+ return Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ }
+
+ static inline int64_t wrapi(int64_t value, int64_t min, int64_t max) {
+ return Math::wrapi(value, min, max);
+ }
+ static inline double wrapf(double value, double min, double max) {
+ return Math::wrapf(value, min, max);
+ }
+
+ static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 2) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.expected = 2;
+ return Variant();
+ }
+ Variant base = *p_args[0];
+ Variant ret;
+ for (int i = 1; i < p_argcount; i++) {
+ bool valid;
+ Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = base.get_type();
+ r_error.argument = i;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ base = *p_args[i];
+ }
+ }
+ r_error.error = Callable::CallError::CALL_OK;
+ return base;
+ }
+
+ static inline double maxf(double x, double y) {
+ return MAX(x, y);
+ }
+
+ static inline int64_t maxi(int64_t x, int64_t y) {
+ return MAX(x, y);
+ }
+
+ static inline Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 2) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.expected = 2;
+ return Variant();
+ }
+ Variant base = *p_args[0];
+ Variant ret;
+ for (int i = 1; i < p_argcount; i++) {
+ bool valid;
+ Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = base.get_type();
+ r_error.argument = i;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ base = *p_args[i];
+ }
+ }
+ r_error.error = Callable::CallError::CALL_OK;
+ return base;
+ }
+
+ static inline double minf(double x, double y) {
+ return MIN(x, y);
+ }
+
+ static inline int64_t mini(int64_t x, int64_t y) {
+ return MIN(x, y);
+ }
+
+ static inline Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error) {
+ Variant value = x;
+
+ Variant ret;
+
+ bool valid;
+ Variant::evaluate(Variant::OP_LESS, value, min, ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = value.get_type();
+ r_error.argument = 1;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ value = min;
+ }
+ Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = value.get_type();
+ r_error.argument = 2;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ value = max;
+ }
+
+ r_error.error = Callable::CallError::CALL_OK;
+
+ return value;
+ }
+
+ static inline double clampf(double x, double min, double max) {
+ return CLAMP(x, min, max);
+ }
+
+ static inline int64_t clampi(int64_t x, int64_t min, int64_t max) {
+ return CLAMP(x, min, max);
+ }
+
+ static inline int64_t nearest_po2(int64_t x) {
+ return nearest_power_of_2_templated(uint64_t(x));
+ }
+
+ // Random
+
+ static inline void randomize() {
+ Math::randomize();
+ }
+
+ static inline int64_t randi() {
+ return Math::rand();
+ }
+
+ static inline double randf() {
+ return Math::randf();
+ }
+
+ static inline int64_t randi_range(int64_t from, int64_t to) {
+ return Math::random((int32_t)from, (int32_t)to);
+ }
+
+ static inline double randf_range(double from, double to) {
+ return Math::random(from, to);
+ }
+
+ static inline void seed(int64_t s) {
+ return Math::seed(s);
+ }
+
+ static inline PackedInt64Array rand_from_seed(int64_t seed) {
+ uint64_t s = seed;
+ PackedInt64Array arr;
+ arr.resize(2);
+ arr.write[0] = Math::rand_from_seed(&s);
+ arr.write[1] = s;
+ return arr;
+ }
+
+ // Utility
+
+ static inline Variant weakref(const Variant &obj, Callable::CallError &r_error) {
+ if (obj.get_type() == Variant::OBJECT) {
+ r_error.error = Callable::CallError::CALL_OK;
+ if (obj.is_ref()) {
+ Ref<WeakRef> wref = memnew(WeakRef);
+ REF r = obj;
+ if (r.is_valid()) {
+ wref->set_ref(r);
+ }
+ return wref;
+ } else {
+ Ref<WeakRef> wref = memnew(WeakRef);
+ Object *o = obj.get_validated_object();
+ if (o) {
+ wref->set_obj(o);
+ }
+ return wref;
+ }
+ } else if (obj.get_type() == Variant::NIL) {
+ r_error.error = Callable::CallError::CALL_OK;
+ Ref<WeakRef> wref = memnew(WeakRef);
+ return wref;
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::OBJECT;
+ return Variant();
+ }
+ }
+
+ static inline int64_t _typeof(const Variant &obj) {
+ return obj.get_type();
+ }
+
+ static inline String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ return String();
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ r_error.error = Callable::CallError::CALL_OK;
+
+ return str;
+ }
+
+ static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ print_line(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ if (i) {
+ str += "\t";
+ }
+ str += p_args[i]->operator String();
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ if (i) {
+ str += " ";
+ }
+ str += p_args[i]->operator String();
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ OS::get_singleton()->print("%s", str.utf8().get_data());
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ ERR_PRINT(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ WARN_PRINT(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline String var2str(const Variant &p_var) {
+ String vars;
+ VariantWriter::write_to_string(p_var, vars);
+ return vars;
+ }
+
+ static inline Variant str2var(const String &p_var) {
+ VariantParser::StreamString ss;
+ ss.s = p_var;
+
+ String errs;
+ int line;
+ Variant ret;
+ (void)VariantParser::parse(&ss, ret, errs, line);
+
+ return ret;
+ }
+
+ static inline PackedByteArray var2bytes(const Variant &p_var) {
+ int len;
+ Error err = encode_variant(p_var, nullptr, len, false);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+
+ PackedByteArray barr;
+ barr.resize(len);
+ {
+ uint8_t *w = barr.ptrw();
+ err = encode_variant(p_var, w, len, false);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+ }
+
+ return barr;
+ }
+
+ static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) {
+ int len;
+ Error err = encode_variant(p_var, nullptr, len, true);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+
+ PackedByteArray barr;
+ barr.resize(len);
+ {
+ uint8_t *w = barr.ptrw();
+ err = encode_variant(p_var, w, len, true);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+ }
+
+ return barr;
+ }
+
+ static inline Variant bytes2var(const PackedByteArray &p_arr) {
+ Variant ret;
+ {
+ const uint8_t *r = p_arr.ptr();
+ Error err = decode_variant(ret, r, p_arr.size(), nullptr, false);
+ if (err != OK) {
+ return Variant();
+ }
+ }
+ return ret;
+ }
+
+ static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) {
+ Variant ret;
+ {
+ const uint8_t *r = p_arr.ptr();
+ Error err = decode_variant(ret, r, p_arr.size(), nullptr, true);
+ if (err != OK) {
+ return Variant();
+ }
+ }
+ return ret;
+ }
+
+ static inline int64_t hash(const Variant &p_arr) {
+ return p_arr.hash();
+ }
+
+ static inline Variant instance_from_id(int64_t p_id) {
+ ObjectID id = ObjectID((uint64_t)p_id);
+ Variant ret = ObjectDB::get_instance(id);
+ return ret;
+ }
+
+ static inline bool is_instance_id_valid(int64_t p_id) {
+ return ObjectDB::get_instance(ObjectID((uint64_t)p_id)) != nullptr;
+ }
+
+ static inline bool is_instance_valid(const Variant &p_instance) {
+ if (p_instance.get_type() != Variant::OBJECT) {
+ return false;
+ }
+ return p_instance.get_validated_object() != nullptr;
+ }
+};
+
+#ifdef DEBUG_METHODS_ENABLED
+#define VCALLR *ret = p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
+#define VCALL p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
+#else
+#define VCALLR *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...)
+#define VCALL p_func(VariantCaster<P>::cast(*p_args[Is])...)
+#endif
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+ VCALLR;
+ (void)p_args;
+ (void)r_error;
+}
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence<Is...>) {
+ *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...);
+ (void)p_args;
+}
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence<Is...>) {
+ PtrToArg<R>::encode(p_func(PtrToArg<P>::convert(p_args[Is])...), ret);
+ (void)p_args;
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) {
+ call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args) {
+ validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) {
+ ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) {
+ return sizeof...(P);
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+}
+
+// WITHOUT RET
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+ VCALL;
+ (void)p_args;
+ (void)r_error;
+}
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence<Is...>) {
+ p_func(VariantCaster<P>::cast(*p_args[Is])...);
+ (void)p_args;
+}
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence<Is...>) {
+ p_func(PtrToArg<P>::convert(p_args[Is])...);
+ (void)p_args;
+}
+
+template <class... P>
+static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error) {
+ call_helperp(p_func, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) {
+ validated_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) {
+ ptr_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) {
+ return sizeof...(P);
+}
+
+template <class... P>
+static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
+template <class... P>
+static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
+ return Variant::NIL;
+}
+
+#define FUNCBINDR(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ call_helperr(VariantBuiltinFunctions::m_func, r_ret, p_args, r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ validated_call_helperr(VariantBuiltinFunctions::m_func, r_ret, p_args); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ ptr_call_helperr(VariantBuiltinFunctions::m_func, ret, p_args); \
+ } \
+ \
+ static int get_argument_count() { \
+ return get_arg_count_helperr(VariantBuiltinFunctions::m_func); \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return get_arg_type_helperr(VariantBuiltinFunctions::m_func, p_arg); \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return get_ret_type_helperr(VariantBuiltinFunctions::m_func); \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::BuiltInFunctionType get_type() { return m_category; } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVR(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantBuiltinFunctions::m_func(*p_args[0], r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ *r_ret = VariantBuiltinFunctions::m_func(*p_args[0], ce); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ PtrToArg<Variant>::encode(VariantBuiltinFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), ce), ret); \
+ } \
+ \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::BuiltInFunctionType get_type() { return m_category; } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVR3(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantBuiltinFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ *r_ret = VariantBuiltinFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], ce); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ Variant r; \
+ r = VariantBuiltinFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), PtrToArg<Variant>::convert(p_args[2]), ce); \
+ PtrToArg<Variant>::encode(r, ret); \
+ } \
+ \
+ static int get_argument_count() { \
+ return 3; \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::BuiltInFunctionType get_type() { return m_category; } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARG(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantBuiltinFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ *r_ret = VariantBuiltinFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ PtrToArg<Variant>::encode(r, ret); \
+ } \
+ \
+ static int get_argument_count() { \
+ return 2; \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::BuiltInFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARGS(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantBuiltinFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ *r_ret = VariantBuiltinFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ PtrToArg<String>::encode(r.operator String(), ret); \
+ } \
+ \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return Variant::STRING; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::BuiltInFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARGV(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ VariantBuiltinFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ VariantBuiltinFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ } \
+ \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return false; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::BuiltInFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBIND(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ call_helper(VariantBuiltinFunctions::m_func, p_args, r_error); \
+ } \
+ \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ validated_call_helper(VariantBuiltinFunctions::m_func, p_args); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ ptr_call_helper(VariantBuiltinFunctions::m_func, p_args); \
+ } \
+ \
+ static int get_argument_count() { \
+ return get_arg_count_helper(VariantBuiltinFunctions::m_func); \
+ } \
+ \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return get_arg_type_helper(VariantBuiltinFunctions::m_func, p_arg); \
+ } \
+ \
+ static Variant::Type get_return_type() { \
+ return get_ret_type_helper(VariantBuiltinFunctions::m_func); \
+ } \
+ static bool has_return_type() { \
+ return false; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::BuiltInFunctionType get_type() { return m_category; } \
+ }; \
+ register_builtin_function<Func_##m_func>(#m_func, m_args)
+
+struct VariantBuiltinFunctionInfo {
+ void (*call_builtin)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Variant::BuiltinFunctionValidatedCall validated_call_builtin;
+ Variant::BuiltinFunctionPTRCall ptr_call_builtin;
+ Vector<String> argnames;
+ bool is_vararg;
+ bool returns_value;
+ int argcount;
+ Variant::Type (*get_arg_type)(int);
+ Variant::Type return_type;
+ Variant::BuiltInFunctionType type;
+};
+
+static OAHashMap<StringName, VariantBuiltinFunctionInfo> builtin_function_table;
+static List<StringName> builtin_function_name_table;
+
+template <class T>
+static void register_builtin_function(const String &p_name, const Vector<String> &argnames) {
+ String name = p_name;
+ if (name.begins_with("_")) {
+ name = name.substr(1, name.length() - 1);
+ }
+ StringName sname = name;
+ ERR_FAIL_COND(builtin_function_table.has(sname));
+
+ VariantBuiltinFunctionInfo bfi;
+ bfi.call_builtin = T::call;
+ bfi.validated_call_builtin = T::validated_call;
+ bfi.ptr_call_builtin = T::ptrcall;
+ bfi.is_vararg = T::is_vararg();
+ bfi.argnames = argnames;
+ bfi.argcount = T::get_argument_count();
+ if (!bfi.is_vararg) {
+ ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding builtin function: " + name);
+ }
+ bfi.get_arg_type = T::get_argument_type;
+ bfi.return_type = T::get_return_type();
+ bfi.type = T::get_type();
+ bfi.returns_value = T::has_return_type();
+
+ builtin_function_table.insert(sname, bfi);
+ builtin_function_name_table.push_back(sname);
+}
+
+void Variant::_register_variant_builtin_funcs() {
+ // Math
+
+ FUNCBINDR(sin, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(cos, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(tan, sarray("angle_rad"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(sinh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(cosh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(tanh, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(asin, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(acos, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(atan, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(atan2, sarray("y", "x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(sqrt, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(fmod, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(fposmod, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(floor, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(ceil, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(round, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(abs, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(absf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(absi, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(sign, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(signf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(signi, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(pow, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(log, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(exp, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(is_nan, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(is_inf, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(is_zero_approx, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(ease, sarray("x", "c"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(step_decimals, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(range_step_decimals, sarray("x"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(stepify, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(lerp, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(lerp_angle, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(inverse_lerp, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(range_lerp, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(smoothstep, sarray("from", "to", "c"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(dectime, sarray("value", "amount", "step"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(deg2rad, sarray("deg"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(rad2deg, sarray("rad"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(linear2db, sarray("lin"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(db2linear, sarray("db"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(polar2cartesian, sarray("r", "th"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(cartesian2polar, sarray("x", "y"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDVARARG(max, sarray(), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(maxi, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(maxf, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDVARARG(min, sarray(), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(mini, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(minf, sarray("a", "b"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDVR3(clamp, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(clampi, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH);
+ FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ FUNCBINDR(nearest_po2, sarray("value"), Variant::BUILTIN_FUNC_TYPE_MATH);
+
+ //Random
+
+ FUNCBIND(randomize, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randi, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randf, sarray(), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randi_range, sarray("from", "to"), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randf_range, sarray("from", "to"), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBIND(seed, sarray("base"), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+ FUNCBINDR(rand_from_seed, sarray("seed"), Variant::BUILTIN_FUNC_TYPE_RANDOM);
+
+ // Utility
+ FUNCBINDVR(weakref, sarray("from"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(_typeof, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGS(str, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(print, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(printerr, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(printt, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(prints, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(printraw, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(push_error, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDVARARGV(push_warning, sarray(), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+
+ FUNCBINDR(var2str, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(str2var, sarray("string"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+
+ FUNCBINDR(var2bytes, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(bytes2var, sarray("bytes"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+
+ FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+
+ FUNCBINDR(hash, sarray("variable"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+
+ FUNCBINDR(instance_from_id, sarray("id"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(is_instance_id_valid, sarray("id"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+ FUNCBINDR(is_instance_valid, sarray("instance"), Variant::BUILTIN_FUNC_TYPE_UTILITY);
+}
+void Variant::_unregister_variant_builtin_funcs() {
+ builtin_function_table.clear();
+ builtin_function_name_table.clear();
+}
+
+void Variant::call_builtin_func(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.argument = 0;
+ r_error.expected = 0;
+ return;
+ }
+
+ if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 0;
+ r_error.expected = bfi->argcount;
+ return;
+ }
+
+ if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 0;
+ r_error.expected = bfi->argcount;
+ return;
+ }
+
+ bfi->call_builtin(r_ret, p_args, p_argcount, r_error);
+}
+
+bool Variant::has_builtin_func(const StringName &p_name) {
+ return builtin_function_table.has(p_name);
+}
+
+Variant::BuiltinFunctionValidatedCall Variant::get_builtin_validated_caller(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return nullptr;
+ }
+
+ return bfi->validated_call_builtin;
+}
+Variant::BuiltinFunctionPTRCall Variant::get_builtin_ptr_caller(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return nullptr;
+ }
+
+ return bfi->ptr_call_builtin;
+}
+
+Variant::BuiltInFunctionType Variant::get_builtin_func_type(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::BUILTIN_FUNC_TYPE_MATH;
+ }
+
+ return bfi->type;
+}
+
+int Variant::get_builtin_func_argument_count(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return 0;
+ }
+
+ return bfi->argcount;
+}
+Variant::Type Variant::get_builtin_func_argument_type(const StringName &p_name, int p_arg) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::NIL;
+ }
+
+ return bfi->get_arg_type(p_arg);
+}
+String Variant::get_builtin_func_argument_name(const StringName &p_name, int p_arg) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return String();
+ }
+ ERR_FAIL_COND_V(bfi->is_vararg, String());
+ ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String());
+ return bfi->argnames[p_arg];
+}
+bool Variant::has_builtin_func_return_value(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return false;
+ }
+ return bfi->returns_value;
+}
+Variant::Type Variant::get_builtin_func_return_type(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::NIL;
+ }
+
+ return bfi->return_type;
+}
+bool Variant::is_builtin_func_vararg(const StringName &p_name) {
+ const VariantBuiltinFunctionInfo *bfi = builtin_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return false;
+ }
+
+ return bfi->is_vararg;
+}
+
+void Variant::get_builtin_function_list(List<StringName> *r_functions) {
+ for (List<StringName>::Element *E = builtin_function_name_table.front(); E; E = E->next()) {
+ r_functions->push_back(E->get());
+ }
+}
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 929a8e2cc8..39290f2b04 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -38,26 +38,6 @@
#include "core/os/os.h"
#include "core/templates/oa_hash_map.h"
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
-}
-
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
- arr.push_back(p_str);
-}
-
-template <class... P>
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
- arr.push_back(p_str);
- sarray_add_str(arr, p_args...);
-}
-
-template <class... P>
-_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
- Vector<String> arr;
- sarray_add_str(arr, p_args...);
- return arr;
-}
-
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
@@ -1356,6 +1336,7 @@ void Variant::_register_variant_methods() {
bind_method(Array, push_back, sarray("value"), varray());
bind_method(Array, push_front, sarray("value"), varray());
bind_method(Array, append, sarray("value"), varray());
+ bind_method(Array, append_array, sarray("array"), varray());
bind_method(Array, resize, sarray("size"), varray());
bind_method(Array, insert, sarray("position", "value"), varray());
bind_method(Array, remove, sarray("position"), varray());
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index b777323e82..01f5b7df59 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -39,26 +39,6 @@
#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
-}
-
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
- arr.push_back(p_str);
-}
-
-template <class... P>
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
- arr.push_back(p_str);
- sarray_add_str(arr, p_args...);
-}
-
-template <class... P>
-_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
- Vector<String> arr;
- sarray_add_str(arr, p_args...);
- return arr;
-}
-
template <class T, class... P>
class VariantConstructor {
template <size_t... Is>
diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml
index a4972612d9..baea84df65 100644
--- a/doc/classes/AABB.xml
+++ b/doc/classes/AABB.xml
@@ -14,14 +14,14 @@
<link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link>
</tutorials>
<methods>
- <method name="AABB">
+ <method name="AABB" qualifiers="constructor">
<return type="AABB">
</return>
<description>
Constructs a default-initialized [AABB] with default (zero) values of [member position] and [member size].
</description>
</method>
- <method name="AABB">
+ <method name="AABB" qualifiers="constructor">
<return type="AABB">
</return>
<argument index="0" name="from" type="AABB">
@@ -30,7 +30,7 @@
Constructs an [AABB] as a copy of the given [AABB].
</description>
</method>
- <method name="AABB">
+ <method name="AABB" qualifiers="constructor">
<return type="AABB">
</return>
<argument index="0" name="position" type="Vector3">
@@ -231,6 +231,30 @@
Returns a larger [AABB] that contains both this [AABB] and [code]with[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="AABB">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="end" type="Vector3" setter="" getter="" default="Vector3( 0, 0, 0 )">
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 86ef5bef4c..0ad5960d4a 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -38,19 +38,20 @@
GD.Print(array1 + array2); // Prints [One, 2, 3, Four]
[/csharp]
[/codeblocks]
+ Note that concatenating with [code]+=[/code] operator will create a new array. If you want to append another array to an existing array, [method append_array] is more efficient.
[b]Note:[/b] Arrays are always passed by reference. To get a copy of an array which can be modified independently of the original array, use [method duplicate].
</description>
<tutorials>
</tutorials>
<methods>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<description>
Constructs an empty [Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="Array">
@@ -59,7 +60,7 @@
Constructs an [Array] as a copy of the given [Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedByteArray">
@@ -68,7 +69,7 @@
Constructs an array from a [PackedByteArray].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedColorArray">
@@ -77,7 +78,7 @@
Constructs an array from a [PackedColorArray].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedFloat32Array">
@@ -86,7 +87,7 @@
Constructs an array from a [PackedFloat32Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedFloat64Array">
@@ -95,7 +96,7 @@
Constructs an array from a [PackedFloat64Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedInt32Array">
@@ -104,7 +105,7 @@
Constructs an array from a [PackedInt32Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedInt64Array">
@@ -113,7 +114,7 @@
Constructs an array from a [PackedInt64Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedStringArray">
@@ -122,7 +123,7 @@
Constructs an array from a [PackedStringArray].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedVector2Array">
@@ -131,7 +132,7 @@
Constructs an array from a [PackedVector2Array].
</description>
</method>
- <method name="Array">
+ <method name="Array" qualifiers="constructor">
<return type="Array">
</return>
<argument index="0" name="from" type="PackedVector3Array">
@@ -149,6 +150,21 @@
Appends an element at the end of the array (alias of [method push_back]).
</description>
</method>
+ <method name="append_array">
+ <return type="void">
+ </return>
+ <argument index="0" name="array" type="Array">
+ </argument>
+ <description>
+ Appends another array at the end of this array.
+ [codeblock]
+ var array1 = [1, 2, 3]
+ var array2 = [4, 5, 6]
+ array1.append_array(array2)
+ print(array1) # Prints [1, 2, 3, 4, 5, 6].
+ [/codeblock]
+ </description>
+ </method>
<method name="back">
<return type="Variant">
</return>
@@ -336,6 +352,70 @@
Returns the minimum value contained in the array if all elements are of comparable types. If the elements can't be compared, [code]null[/code] is returned.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Array">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="void">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="pop_back">
<return type="Variant">
</return>
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index 908f316e4e..877d3ca85a 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -19,14 +19,14 @@
<link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link>
</tutorials>
<methods>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<description>
Constructs a default-initialized [Basis] set to [constant IDENTITY].
</description>
</method>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<argument index="0" name="from" type="Basis">
@@ -35,7 +35,7 @@
Constructs a [Basis] as a copy of the given [Basis].
</description>
</method>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<argument index="0" name="axis" type="Vector3">
@@ -46,7 +46,7 @@
Constructs a pure rotation basis matrix, rotated around the given [code]axis[/code] by [code]phi[/code], in radians. The axis must be a normalized vector.
</description>
</method>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<argument index="0" name="euler" type="Vector3">
@@ -56,7 +56,7 @@
Consider using the [Quat] constructor instead, which uses a quaternion instead of Euler angles.
</description>
</method>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<argument index="0" name="from" type="Quat">
@@ -65,7 +65,7 @@
Constructs a pure rotation basis matrix from the given quaternion.
</description>
</method>
- <method name="Basis">
+ <method name="Basis" qualifiers="constructor">
<return type="Basis">
</return>
<argument index="0" name="x_axis" type="Vector3">
@@ -131,6 +131,46 @@
Returns [code]true[/code] if this basis and [code]b[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Basis">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Basis">
+ </return>
+ <argument index="0" name="right" type="Basis">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Basis">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="orthonormalized">
<return type="Basis">
</return>
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index c31efc2581..f137ede90f 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -36,14 +36,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="Callable">
+ <method name="Callable" qualifiers="constructor">
<return type="Callable">
</return>
<description>
Constructs a null [Callable] with no object nor method bound.
</description>
</method>
- <method name="Callable">
+ <method name="Callable" qualifiers="constructor">
<return type="Callable">
</return>
<argument index="0" name="from" type="Callable">
@@ -52,7 +52,7 @@
Constructs a [Callable] as a copy of the given [Callable].
</description>
</method>
- <method name="Callable">
+ <method name="Callable" qualifiers="constructor">
<return type="Callable">
</return>
<argument index="0" name="object" type="Object">
@@ -128,6 +128,22 @@
<description>
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Callable">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Callable">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="unbind">
<return type="Callable">
</return>
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 721fea8a19..ae8703c837 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -16,14 +16,14 @@
<link title="GUI Drag And Drop Demo">https://godotengine.org/asset-library/asset/133</link>
</tutorials>
<methods>
- <method name="Color">
+ <method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<description>
Constructs a default-initialized [Color] with all components set to [code]0[/code].
</description>
</method>
- <method name="Color">
+ <method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="from" type="Color">
@@ -32,7 +32,7 @@
Constructs a [Color] as a copy of the given [Color].
</description>
</method>
- <method name="Color">
+ <method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="from" type="Color">
@@ -51,7 +51,7 @@
[/codeblocks]
</description>
</method>
- <method name="Color">
+ <method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="r" type="float">
@@ -74,7 +74,7 @@
[/codeblocks]
</description>
</method>
- <method name="Color">
+ <method name="Color" qualifiers="constructor">
<return type="Color">
</return>
<argument index="0" name="r" type="float">
@@ -203,6 +203,98 @@
[/codeblocks]
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="to_abgr32">
<return type="int">
</return>
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index a7a3632fef..dc38fdf0e8 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -171,14 +171,14 @@
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
<methods>
- <method name="Dictionary">
+ <method name="Dictionary" qualifiers="constructor">
<return type="Dictionary">
</return>
<description>
Constructs an empty [Dictionary].
</description>
</method>
- <method name="Dictionary">
+ <method name="Dictionary" qualifiers="constructor">
<return type="Dictionary">
</return>
<argument index="0" name="from" type="Dictionary">
@@ -294,6 +294,30 @@
Returns the list of keys in the [Dictionary].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Dictionary">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Dictionary">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="key" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="size">
<return type="int">
</return>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index a069bdd836..ca011abb36 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -292,6 +292,56 @@
[/codeblocks]
</description>
</method>
+ <method name="forward_spatial_draw_over_viewport" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="overlay" type="Control">
+ </argument>
+ <description>
+ Called by the engine when the 3D editor's viewport is updated. Use the [code]overlay[/code] [Control] for drawing. You can update the viewport manually by calling [method update_overlays].
+ [codeblocks]
+ [gdscript]
+ func forward_spatial_draw_over_viewport(overlay):
+ # Draw a circle at cursor position.
+ overlay.draw_circle(overlay.get_local_mouse_position(), 64)
+
+ func forward_spatial_gui_input(camera, event):
+ if event is InputEventMouseMotion:
+ # Redraw viewport when cursor is moved.
+ update_overlays()
+ return true
+ return false
+ [/gdscript]
+ [csharp]
+ public override void ForwardSpatialDrawOverViewport(Godot.Control overlay)
+ {
+ // Draw a circle at cursor position.
+ overlay.DrawCircle(overlay.GetLocalMousePosition(), 64, Colors.White);
+ }
+
+ public override bool ForwardSpatialGuiInput(Godot.Camera3D camera, InputEvent @event)
+ {
+ if (@event is InputEventMouseMotion)
+ {
+ // Redraw viewport when cursor is moved.
+ UpdateOverlays();
+ return true;
+ }
+ return false;
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="forward_spatial_force_draw_over_viewport" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="overlay" type="Control">
+ </argument>
+ <description>
+ This method is the same as [method forward_spatial_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
+ You need to enable calling of this method by using [method set_force_draw_over_forwarding_enabled].
+ </description>
+ </method>
<method name="forward_spatial_gui_input" qualifiers="virtual">
<return type="bool">
</return>
@@ -584,7 +634,7 @@
<return type="void">
</return>
<description>
- Enables calling of [method forward_canvas_force_draw_over_viewport] when the 2D editor's viewport is updated. You need to call this method only once and it will work permanently for this plugin.
+ Enables calling of [method forward_canvas_force_draw_over_viewport] for the 2D editor and [method forward_spatial_force_draw_over_viewport] for the 3D editor when their viewports are updated. You need to call this method only once and it will work permanently for this plugin.
</description>
</method>
<method name="set_input_event_forwarding_always_enabled">
@@ -616,7 +666,7 @@
<return type="int">
</return>
<description>
- Updates the overlays of the 2D and 3D editor viewport. Causes [method forward_canvas_draw_over_viewport] and [method forward_canvas_force_draw_over_viewport] to be called.
+ Updates the overlays of the 2D and 3D editor viewport. Causes methods [method forward_canvas_draw_over_viewport], [method forward_canvas_force_draw_over_viewport], [method forward_spatial_draw_over_viewport] and [method forward_spatial_force_draw_over_viewport] to be called.
</description>
</method>
</methods>
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 980bea0d9f..93ede047fd 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -25,14 +25,14 @@
<link title="2D Role Playing Game Demo">https://godotengine.org/asset-library/asset/520</link>
</tutorials>
<methods>
- <method name="NodePath">
+ <method name="NodePath" qualifiers="constructor">
<return type="NodePath">
</return>
<description>
Constructs an empty [NodePath].
</description>
</method>
- <method name="NodePath">
+ <method name="NodePath" qualifiers="constructor">
<return type="NodePath">
</return>
<argument index="0" name="from" type="NodePath">
@@ -41,7 +41,7 @@
Constructs a [NodePath] as a copy of the given [NodePath].
</description>
</method>
- <method name="NodePath">
+ <method name="NodePath" qualifiers="constructor">
<return type="NodePath">
</return>
<argument index="0" name="from" type="String">
@@ -150,6 +150,22 @@
Returns [code]true[/code] if the node path is empty.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="NodePath">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="NodePath">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 5ac5f15fb2..4a6893879d 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -10,14 +10,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedByteArray">
+ <method name="PackedByteArray" qualifiers="constructor">
<return type="PackedByteArray">
</return>
<description>
Constructs an empty [PackedByteArray].
</description>
</method>
- <method name="PackedByteArray">
+ <method name="PackedByteArray" qualifiers="constructor">
<return type="PackedByteArray">
</return>
<argument index="0" name="from" type="PackedByteArray">
@@ -26,7 +26,7 @@
Constructs a [PackedByteArray] as a copy of the given [PackedByteArray].
</description>
</method>
- <method name="PackedByteArray">
+ <method name="PackedByteArray" qualifiers="constructor">
<return type="PackedByteArray">
</return>
<argument index="0" name="from" type="Array">
@@ -159,6 +159,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="right" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml
index e4b9e02be7..3065d16945 100644
--- a/doc/classes/PackedColorArray.xml
+++ b/doc/classes/PackedColorArray.xml
@@ -10,14 +10,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedColorArray">
+ <method name="PackedColorArray" qualifiers="constructor">
<return type="PackedColorArray">
</return>
<description>
Constructs an empty [PackedColorArray].
</description>
</method>
- <method name="PackedColorArray">
+ <method name="PackedColorArray" qualifiers="constructor">
<return type="PackedColorArray">
</return>
<argument index="0" name="from" type="PackedColorArray">
@@ -26,7 +26,7 @@
Constructs a [PackedColorArray] as a copy of the given [PackedColorArray].
</description>
</method>
- <method name="PackedColorArray">
+ <method name="PackedColorArray" qualifiers="constructor">
<return type="PackedColorArray">
</return>
<argument index="0" name="from" type="Array">
@@ -87,6 +87,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedColorArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedColorArray">
+ </return>
+ <argument index="0" name="right" type="PackedColorArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedColorArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index 1b2091f72b..ab9594d2e3 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -11,14 +11,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedFloat32Array">
+ <method name="PackedFloat32Array" qualifiers="constructor">
<return type="PackedFloat32Array">
</return>
<description>
Constructs an empty [PackedFloat32Array].
</description>
</method>
- <method name="PackedFloat32Array">
+ <method name="PackedFloat32Array" qualifiers="constructor">
<return type="PackedFloat32Array">
</return>
<argument index="0" name="from" type="PackedFloat32Array">
@@ -27,7 +27,7 @@
Constructs a [PackedFloat32Array] as a copy of the given [PackedFloat32Array].
</description>
</method>
- <method name="PackedFloat32Array">
+ <method name="PackedFloat32Array" qualifiers="constructor">
<return type="PackedFloat32Array">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,30 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedFloat32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedFloat32Array">
+ </return>
+ <argument index="0" name="right" type="PackedFloat32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedFloat32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index a55ac6bacc..3088aee483 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -11,14 +11,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedFloat64Array">
+ <method name="PackedFloat64Array" qualifiers="constructor">
<return type="PackedFloat64Array">
</return>
<description>
Constructs an empty [PackedFloat64Array].
</description>
</method>
- <method name="PackedFloat64Array">
+ <method name="PackedFloat64Array" qualifiers="constructor">
<return type="PackedFloat64Array">
</return>
<argument index="0" name="from" type="PackedFloat64Array">
@@ -27,7 +27,7 @@
Constructs a [PackedFloat64Array] as a copy of the given [PackedFloat64Array].
</description>
</method>
- <method name="PackedFloat64Array">
+ <method name="PackedFloat64Array" qualifiers="constructor">
<return type="PackedFloat64Array">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedFloat64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedFloat64Array">
+ </return>
+ <argument index="0" name="right" type="PackedFloat64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedFloat64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index ecf8abd1eb..eded545de8 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -11,14 +11,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedInt32Array">
+ <method name="PackedInt32Array" qualifiers="constructor">
<return type="PackedInt32Array">
</return>
<description>
Constructs an empty [PackedInt32Array].
</description>
</method>
- <method name="PackedInt32Array">
+ <method name="PackedInt32Array" qualifiers="constructor">
<return type="PackedInt32Array">
</return>
<argument index="0" name="from" type="PackedInt32Array">
@@ -27,7 +27,7 @@
Constructs a [PackedInt32Array] as a copy of the given [PackedInt32Array].
</description>
</method>
- <method name="PackedInt32Array">
+ <method name="PackedInt32Array" qualifiers="constructor">
<return type="PackedInt32Array">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="right" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedInt32Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index a254a6ff5f..83731b1023 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -11,14 +11,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedInt64Array">
+ <method name="PackedInt64Array" qualifiers="constructor">
<return type="PackedInt64Array">
</return>
<description>
Constructs an empty [PackedInt64Array].
</description>
</method>
- <method name="PackedInt64Array">
+ <method name="PackedInt64Array" qualifiers="constructor">
<return type="PackedInt64Array">
</return>
<argument index="0" name="from" type="PackedInt64Array">
@@ -27,7 +27,7 @@
Constructs a [PackedInt64Array] as a copy of the given [PackedInt64Array].
</description>
</method>
- <method name="PackedInt64Array">
+ <method name="PackedInt64Array" qualifiers="constructor">
<return type="PackedInt64Array">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedInt64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedInt64Array">
+ </return>
+ <argument index="0" name="right" type="PackedInt64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedInt64Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml
index c50ec38a93..c71f5ffa7e 100644
--- a/doc/classes/PackedStringArray.xml
+++ b/doc/classes/PackedStringArray.xml
@@ -11,14 +11,14 @@
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
<methods>
- <method name="PackedStringArray">
+ <method name="PackedStringArray" qualifiers="constructor">
<return type="PackedStringArray">
</return>
<description>
Constructs an empty [PackedStringArray].
</description>
</method>
- <method name="PackedStringArray">
+ <method name="PackedStringArray" qualifiers="constructor">
<return type="PackedStringArray">
</return>
<argument index="0" name="from" type="PackedStringArray">
@@ -27,7 +27,7 @@
Constructs a [PackedStringArray] as a copy of the given [PackedStringArray].
</description>
</method>
- <method name="PackedStringArray">
+ <method name="PackedStringArray" qualifiers="constructor">
<return type="PackedStringArray">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,38 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedStringArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedStringArray">
+ </return>
+ <argument index="0" name="right" type="PackedStringArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedStringArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="String">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index 0bd658c488..5f68d9256d 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -11,14 +11,14 @@
<link title="2D Navigation Astar Demo">https://godotengine.org/asset-library/asset/519</link>
</tutorials>
<methods>
- <method name="PackedVector2Array">
+ <method name="PackedVector2Array" qualifiers="constructor">
<return type="PackedVector2Array">
</return>
<description>
Constructs an empty [PackedVector2Array].
</description>
</method>
- <method name="PackedVector2Array">
+ <method name="PackedVector2Array" qualifiers="constructor">
<return type="PackedVector2Array">
</return>
<argument index="0" name="from" type="PackedVector2Array">
@@ -27,7 +27,7 @@
Constructs a [PackedVector2Array] as a copy of the given [PackedVector2Array].
</description>
</method>
- <method name="PackedVector2Array">
+ <method name="PackedVector2Array" qualifiers="constructor">
<return type="PackedVector2Array">
</return>
<argument index="0" name="from" type="Array">
@@ -88,6 +88,46 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedVector2Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="PackedVector2Array">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedVector2Array">
+ </return>
+ <argument index="0" name="right" type="PackedVector2Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedVector2Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml
index 5b835f2fbf..e681e1deb7 100644
--- a/doc/classes/PackedVector3Array.xml
+++ b/doc/classes/PackedVector3Array.xml
@@ -10,14 +10,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="PackedVector3Array">
+ <method name="PackedVector3Array" qualifiers="constructor">
<return type="PackedVector3Array">
</return>
<description>
Constructs an empty [PackedVector3Array].
</description>
</method>
- <method name="PackedVector3Array">
+ <method name="PackedVector3Array" qualifiers="constructor">
<return type="PackedVector3Array">
</return>
<argument index="0" name="from" type="PackedVector3Array">
@@ -26,7 +26,7 @@
Constructs a [PackedVector3Array] as a copy of the given [PackedVector3Array].
</description>
</method>
- <method name="PackedVector3Array">
+ <method name="PackedVector3Array" qualifiers="constructor">
<return type="PackedVector3Array">
</return>
<argument index="0" name="from" type="Array">
@@ -87,6 +87,46 @@
Reverses the order of the elements in the array.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedVector3Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="PackedVector3Array">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="PackedVector3Array">
+ </return>
+ <argument index="0" name="right" type="PackedVector3Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="PackedVector3Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="push_back">
<return type="bool">
</return>
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index bb0b25a552..e3242512c4 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -10,14 +10,14 @@
<link title="Math tutorial index">https://docs.godotengine.org/en/latest/tutorials/math/index.html</link>
</tutorials>
<methods>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<description>
Constructs a default-initialized [Plane] with all components set to [code]0[/code].
</description>
</method>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<argument index="0" name="from" type="Plane">
@@ -26,7 +26,7 @@
Constructs a [Plane] as a copy of the given [Plane].
</description>
</method>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<argument index="0" name="a" type="float">
@@ -41,7 +41,7 @@
Creates a plane from the four parameters. The three components of the resulting plane's [member normal] are [code]a[/code], [code]b[/code] and [code]c[/code], and the plane has a distance of [code]d[/code] from the origin.
</description>
</method>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<argument index="0" name="normal" type="Vector3">
@@ -52,7 +52,7 @@
Creates a plane from the normal and the plane's distance to the origin.
</description>
</method>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<argument index="0" name="point" type="Vector3">
@@ -63,7 +63,7 @@
Creates a plane from the given position and a plane normal.
</description>
</method>
- <method name="Plane">
+ <method name="Plane" qualifiers="constructor">
<return type="Plane">
</return>
<argument index="0" name="point1" type="Vector3">
@@ -161,6 +161,34 @@
Returns a copy of the plane, normalized.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Plane">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Plane">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Plane">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Plane">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="project">
<return type="Vector3">
</return>
diff --git a/doc/classes/Quat.xml b/doc/classes/Quat.xml
index edfe99a8b8..5932a624f2 100644
--- a/doc/classes/Quat.xml
+++ b/doc/classes/Quat.xml
@@ -13,14 +13,14 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<description>
Constructs a default-initialized quaternion with all components set to [code]0[/code].
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="from" type="Quat">
@@ -29,7 +29,7 @@
Constructs a [Quat] as a copy of the given [Quat].
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="arc_from" type="Vector3">
@@ -39,7 +39,7 @@
<description>
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="axis" type="Vector3">
@@ -50,7 +50,7 @@
Constructs a quaternion that will rotate around the given axis by the specified angle. The axis must be a normalized vector.
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="euler" type="Vector3">
@@ -59,7 +59,7 @@
Constructs a quaternion that will perform a rotation specified by Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle).
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="from" type="Basis">
@@ -68,7 +68,7 @@
Constructs a quaternion from the given [Basis].
</description>
</method>
- <method name="Quat">
+ <method name="Quat" qualifiers="constructor">
<return type="Quat">
</return>
<argument index="0" name="x" type="float">
@@ -158,6 +158,98 @@
Returns a copy of the quaternion, normalized to unit length.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="slerp">
<return type="Quat">
</return>
diff --git a/doc/classes/RID.xml b/doc/classes/RID.xml
index d944f7a86a..0ee34d4194 100644
--- a/doc/classes/RID.xml
+++ b/doc/classes/RID.xml
@@ -9,14 +9,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="RID">
+ <method name="RID" qualifiers="constructor">
<return type="RID">
</return>
<description>
Constructs an empty [RID] with the invalid ID [code]0[/code].
</description>
</method>
- <method name="RID">
+ <method name="RID" qualifiers="constructor">
<return type="RID">
</return>
<argument index="0" name="from" type="RID">
@@ -32,6 +32,54 @@
Returns the ID of the referenced resource.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="RID">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index b970d0188c..02a77a0e24 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -14,14 +14,14 @@
<link title="Advanced vector math">https://docs.godotengine.org/en/latest/tutorials/math/vectors_advanced.html</link>
</tutorials>
<methods>
- <method name="Rect2">
+ <method name="Rect2" qualifiers="constructor">
<return type="Rect2">
</return>
<description>
Constructs a default-initialized [Rect2] with default (zero) values of [member position] and [member size].
</description>
</method>
- <method name="Rect2">
+ <method name="Rect2" qualifiers="constructor">
<return type="Rect2">
</return>
<argument index="0" name="from" type="Rect2">
@@ -30,7 +30,7 @@
Constructs a [Rect2] as a copy of the given [Rect2].
</description>
</method>
- <method name="Rect2">
+ <method name="Rect2" qualifiers="constructor">
<return type="Rect2">
</return>
<argument index="0" name="from" type="Rect2i">
@@ -39,7 +39,7 @@
Constructs a [Rect2] from a [Rect2i].
</description>
</method>
- <method name="Rect2">
+ <method name="Rect2" qualifiers="constructor">
<return type="Rect2">
</return>
<argument index="0" name="position" type="Vector2">
@@ -50,7 +50,7 @@
Constructs a [Rect2] by position and size.
</description>
</method>
- <method name="Rect2">
+ <method name="Rect2" qualifiers="constructor">
<return type="Rect2">
</return>
<argument index="0" name="x" type="float">
@@ -187,6 +187,30 @@
Returns a larger [Rect2] that contains this [Rect2] and [code]b[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Rect2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Rect2">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Rect2">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="end" type="Vector2" setter="" getter="" default="Vector2( 0, 0 )">
diff --git a/doc/classes/Rect2i.xml b/doc/classes/Rect2i.xml
index 5c9162baf4..e8b75a6ac6 100644
--- a/doc/classes/Rect2i.xml
+++ b/doc/classes/Rect2i.xml
@@ -12,14 +12,14 @@
<link title="Vector math">https://docs.godotengine.org/en/latest/tutorials/math/vector_math.html</link>
</tutorials>
<methods>
- <method name="Rect2i">
+ <method name="Rect2i" qualifiers="constructor">
<return type="Rect2i">
</return>
<description>
Constructs a default-initialized [Rect2i] with default (zero) values of [member position] and [member size].
</description>
</method>
- <method name="Rect2i">
+ <method name="Rect2i" qualifiers="constructor">
<return type="Rect2i">
</return>
<argument index="0" name="from" type="Rect2i">
@@ -28,7 +28,7 @@
Constructs a [Rect2i] as a copy of the given [Rect2i].
</description>
</method>
- <method name="Rect2i">
+ <method name="Rect2i" qualifiers="constructor">
<return type="Rect2i">
</return>
<argument index="0" name="from" type="Rect2">
@@ -37,7 +37,7 @@
Constructs a new [Rect2i] from [Rect2]. The floating point coordinates will be truncated.
</description>
</method>
- <method name="Rect2i">
+ <method name="Rect2i" qualifiers="constructor">
<return type="Rect2i">
</return>
<argument index="0" name="position" type="Vector2i">
@@ -48,7 +48,7 @@
Constructs a [Rect2i] by position and size.
</description>
</method>
- <method name="Rect2i">
+ <method name="Rect2i" qualifiers="constructor">
<return type="Rect2i">
</return>
<argument index="0" name="x" type="int">
@@ -174,6 +174,22 @@
Returns a larger [Rect2i] that contains this [Rect2i] and [code]b[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Rect2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Rect2i">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="end" type="Vector2i" setter="" getter="" default="Vector2i( 0, 0 )">
diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml
index bd091899ac..b7a2258fc1 100644
--- a/doc/classes/Signal.xml
+++ b/doc/classes/Signal.xml
@@ -8,14 +8,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="Signal">
+ <method name="Signal" qualifiers="constructor">
<return type="Signal">
</return>
<description>
Constructs a null [Signal] with no object nor signal name bound.
</description>
</method>
- <method name="Signal">
+ <method name="Signal" qualifiers="constructor">
<return type="Signal">
</return>
<argument index="0" name="from" type="Signal">
@@ -24,7 +24,7 @@
Constructs a [Signal] as a copy of the given [Signal].
</description>
</method>
- <method name="Signal">
+ <method name="Signal" qualifiers="constructor">
<return type="Signal">
</return>
<argument index="0" name="object" type="Object">
@@ -107,6 +107,22 @@
<description>
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Signal">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Signal">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index a600a575aa..4ee9dbf1f9 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -10,14 +10,14 @@
<link title="GDScript format strings">https://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/gdscript_format_string.html</link>
</tutorials>
<methods>
- <method name="String">
+ <method name="String" qualifiers="constructor">
<return type="String">
</return>
<description>
Constructs an empty [String] ([code]""[/code]).
</description>
</method>
- <method name="String">
+ <method name="String" qualifiers="constructor">
<return type="String">
</return>
<argument index="0" name="from" type="String">
@@ -26,7 +26,7 @@
Constructs a [String] as a copy of the given [String].
</description>
</method>
- <method name="String">
+ <method name="String" qualifiers="constructor">
<return type="String">
</return>
<argument index="0" name="from" type="NodePath">
@@ -35,7 +35,7 @@
Constructs a new String from the given [NodePath].
</description>
</method>
- <method name="String">
+ <method name="String" qualifiers="constructor">
<return type="String">
</return>
<argument index="0" name="from" type="StringName">
@@ -466,6 +466,86 @@
To get a boolean result from a string comparison, use the [code]==[/code] operator instead. See also [method casecmp_to] and [method naturalnocasecmp_to].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="StringName">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="String">
+ </return>
+ <argument index="0" name="right" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="String">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="StringName">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="ord_at">
<return type="int">
</return>
diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml
index a847d44120..af0074f080 100644
--- a/doc/classes/StringName.xml
+++ b/doc/classes/StringName.xml
@@ -9,14 +9,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="StringName">
+ <method name="StringName" qualifiers="constructor">
<return type="StringName">
</return>
<description>
Constructs an empty [StringName].
</description>
</method>
- <method name="StringName">
+ <method name="StringName" qualifiers="constructor">
<return type="StringName">
</return>
<argument index="0" name="from" type="StringName">
@@ -25,7 +25,7 @@
Constructs a [StringName] as a copy of the given [StringName].
</description>
</method>
- <method name="StringName">
+ <method name="StringName" qualifiers="constructor">
<return type="StringName">
</return>
<argument index="0" name="from" type="String">
@@ -34,6 +34,38 @@
Creates a new [StringName] from the given [String].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="StringName">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="StringName">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
index 920a6c704e..cda69f6a64 100644
--- a/doc/classes/Transform.xml
+++ b/doc/classes/Transform.xml
@@ -16,14 +16,14 @@
<link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link>
</tutorials>
<methods>
- <method name="Transform">
+ <method name="Transform" qualifiers="constructor">
<return type="Transform">
</return>
<description>
Constructs a default-initialized [Transform] set to [constant IDENTITY].
</description>
</method>
- <method name="Transform">
+ <method name="Transform" qualifiers="constructor">
<return type="Transform">
</return>
<argument index="0" name="from" type="Transform">
@@ -32,7 +32,7 @@
Constructs a [Transform] as a copy of the given [Transform].
</description>
</method>
- <method name="Transform">
+ <method name="Transform" qualifiers="constructor">
<return type="Transform">
</return>
<argument index="0" name="basis" type="Basis">
@@ -43,7 +43,7 @@
Constructs a Transform from a [Basis] and [Vector3].
</description>
</method>
- <method name="Transform">
+ <method name="Transform" qualifiers="constructor">
<return type="Transform">
</return>
<argument index="0" name="x_axis" type="Vector3">
@@ -105,6 +105,54 @@
Operations take place in global space.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="PackedVector3Array">
+ </return>
+ <argument index="0" name="right" type="PackedVector3Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Transform">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="AABB">
+ </return>
+ <argument index="0" name="right" type="AABB">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="orthonormalized">
<return type="Transform">
</return>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index af67ad2bd4..ff291663fa 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -14,14 +14,14 @@
<link title="2.5D Demo">https://godotengine.org/asset-library/asset/583</link>
</tutorials>
<methods>
- <method name="Transform2D">
+ <method name="Transform2D" qualifiers="constructor">
<return type="Transform2D">
</return>
<description>
Constructs a default-initialized [Transform] set to [constant IDENTITY].
</description>
</method>
- <method name="Transform2D">
+ <method name="Transform2D" qualifiers="constructor">
<return type="Transform2D">
</return>
<argument index="0" name="from" type="Transform2D">
@@ -30,7 +30,7 @@
Constructs a [Transform2D] as a copy of the given [Transform2D].
</description>
</method>
- <method name="Transform2D">
+ <method name="Transform2D" qualifiers="constructor">
<return type="Transform2D">
</return>
<argument index="0" name="rotation" type="float">
@@ -41,7 +41,7 @@
Constructs the transform from a given angle (in radians) and position.
</description>
</method>
- <method name="Transform2D">
+ <method name="Transform2D" qualifiers="constructor">
<return type="Transform2D">
</return>
<argument index="0" name="x_axis" type="Vector2">
@@ -129,6 +129,62 @@
Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Rect2">
+ </return>
+ <argument index="0" name="right" type="Rect2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Transform2D">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="PackedVector2Array">
+ </return>
+ <argument index="0" name="right" type="PackedVector2Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="orthonormalized">
<return type="Transform2D">
</return>
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index da1526df52..f99231de39 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -17,14 +17,14 @@
<link title="All 2D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/2d</link>
</tutorials>
<methods>
- <method name="Vector2">
+ <method name="Vector2" qualifiers="constructor">
<return type="Vector2">
</return>
<description>
Constructs a default-initialized [Vector2] with all components set to [code]0[/code].
</description>
</method>
- <method name="Vector2">
+ <method name="Vector2" qualifiers="constructor">
<return type="Vector2">
</return>
<argument index="0" name="from" type="Vector2">
@@ -33,7 +33,7 @@
Constructs a [Vector2] as a copy of the given [Vector2].
</description>
</method>
- <method name="Vector2">
+ <method name="Vector2" qualifiers="constructor">
<return type="Vector2">
</return>
<argument index="0" name="from" type="Vector2i">
@@ -42,7 +42,7 @@
Constructs a new [Vector2] from [Vector2i].
</description>
</method>
- <method name="Vector2">
+ <method name="Vector2" qualifiers="constructor">
<return type="Vector2">
</return>
<argument index="0" name="x" type="float">
@@ -250,6 +250,146 @@
Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Transform2D">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="posmod">
<return type="Vector2">
</return>
diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml
index e5b85dff9e..a4ea5c2742 100644
--- a/doc/classes/Vector2i.xml
+++ b/doc/classes/Vector2i.xml
@@ -14,14 +14,14 @@
<link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link>
</tutorials>
<methods>
- <method name="Vector2i">
+ <method name="Vector2i" qualifiers="constructor">
<return type="Vector2i">
</return>
<description>
Constructs a default-initialized [Vector2i] with all components set to [code]0[/code].
</description>
</method>
- <method name="Vector2i">
+ <method name="Vector2i" qualifiers="constructor">
<return type="Vector2i">
</return>
<argument index="0" name="from" type="Vector2i">
@@ -30,7 +30,7 @@
Constructs a [Vector2i] as a copy of the given [Vector2i].
</description>
</method>
- <method name="Vector2i">
+ <method name="Vector2i" qualifiers="constructor">
<return type="Vector2i">
</return>
<argument index="0" name="from" type="Vector2">
@@ -39,7 +39,7 @@
Constructs a new [Vector2i] from [Vector2]. The floating point coordinates will be truncated.
</description>
</method>
- <method name="Vector2i">
+ <method name="Vector2i" qualifiers="constructor">
<return type="Vector2i">
</return>
<argument index="0" name="x" type="int">
@@ -64,6 +64,154 @@
Returns the ratio of [member x] to [member y].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="sign">
<return type="Vector2i">
</return>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 356c9501e1..6ba0d6ab8d 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -17,14 +17,14 @@
<link title="All 3D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/3d</link>
</tutorials>
<methods>
- <method name="Vector3">
+ <method name="Vector3" qualifiers="constructor">
<return type="Vector3">
</return>
<description>
Constructs a default-initialized [Vector3] with all components set to [code]0[/code].
</description>
</method>
- <method name="Vector3">
+ <method name="Vector3" qualifiers="constructor">
<return type="Vector3">
</return>
<argument index="0" name="from" type="Vector3">
@@ -33,7 +33,7 @@
Constructs a [Vector3] as a copy of the given [Vector3].
</description>
</method>
- <method name="Vector3">
+ <method name="Vector3" qualifiers="constructor">
<return type="Vector3">
</return>
<argument index="0" name="from" type="Vector3i">
@@ -42,7 +42,7 @@
Constructs a new [Vector3] from [Vector3i].
</description>
</method>
- <method name="Vector3">
+ <method name="Vector3" qualifiers="constructor">
<return type="Vector3">
</return>
<argument index="0" name="x" type="float">
@@ -239,6 +239,162 @@
Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Basis">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Transform">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="outer">
<return type="Basis">
</return>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index 761bddaeef..a1ae2aceab 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -14,14 +14,14 @@
<link title="3Blue1Brown Essence of Linear Algebra">https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab</link>
</tutorials>
<methods>
- <method name="Vector3i">
+ <method name="Vector3i" qualifiers="constructor">
<return type="Vector3i">
</return>
<description>
Constructs a default-initialized [Vector3i] with all components set to [code]0[/code].
</description>
</method>
- <method name="Vector3i">
+ <method name="Vector3i" qualifiers="constructor">
<return type="Vector3i">
</return>
<argument index="0" name="from" type="Vector3i">
@@ -30,7 +30,7 @@
Constructs a [Vector3i] as a copy of the given [Vector3i].
</description>
</method>
- <method name="Vector3i">
+ <method name="Vector3i" qualifiers="constructor">
<return type="Vector3i">
</return>
<argument index="0" name="from" type="Vector3">
@@ -39,7 +39,7 @@
Constructs a new [Vector3i] from [Vector3]. The floating point coordinates will be truncated.
</description>
</method>
- <method name="Vector3i">
+ <method name="Vector3i" qualifiers="constructor">
<return type="Vector3i">
</return>
<argument index="0" name="x" type="int">
@@ -72,6 +72,154 @@
Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants. If all components are equal, this method returns [constant AXIS_Z].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator []" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="sign">
<return type="Vector3i">
</return>
diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml
index e9f4c2ecf4..03e8bee7d5 100644
--- a/doc/classes/bool.xml
+++ b/doc/classes/bool.xml
@@ -91,14 +91,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="bool">
+ <method name="bool" qualifiers="constructor">
<return type="bool">
</return>
<description>
Constructs a default-initialized [bool] set to [code]false[/code].
</description>
</method>
- <method name="bool">
+ <method name="bool" qualifiers="constructor">
<return type="bool">
</return>
<argument index="0" name="from" type="bool">
@@ -107,7 +107,7 @@
Constructs a [bool] as a copy of the given [bool].
</description>
</method>
- <method name="bool">
+ <method name="bool" qualifiers="constructor">
<return type="bool">
</return>
<argument index="0" name="from" type="float">
@@ -116,7 +116,7 @@
Cast a [float] value to a boolean value, this method will return [code]false[/code] if [code]0.0[/code] is passed in, and [code]true[/code] for all other floats.
</description>
</method>
- <method name="bool">
+ <method name="bool" qualifiers="constructor">
<return type="bool">
</return>
<argument index="0" name="from" type="int">
@@ -125,6 +125,38 @@
Cast an [int] value to a boolean value, this method will return [code]false[/code] if [code]0[/code] is passed in, and [code]true[/code] for all other ints.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/float.xml b/doc/classes/float.xml
index 8153d62bc9..85fe31eec8 100644
--- a/doc/classes/float.xml
+++ b/doc/classes/float.xml
@@ -9,14 +9,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="float">
+ <method name="float" qualifiers="constructor">
<return type="float">
</return>
<description>
Constructs a default-initialized [float] set to [code]0.0[/code].
</description>
</method>
- <method name="float">
+ <method name="float" qualifiers="constructor">
<return type="float">
</return>
<argument index="0" name="from" type="float">
@@ -25,7 +25,7 @@
Constructs a [float] as a copy of the given [float].
</description>
</method>
- <method name="float">
+ <method name="float" qualifiers="constructor">
<return type="float">
</return>
<argument index="0" name="from" type="bool">
@@ -34,7 +34,7 @@
Cast a [bool] value to a floating-point value, [code]float(true)[/code] will be equal to 1.0 and [code]float(false)[/code] will be equal to 0.0.
</description>
</method>
- <method name="float">
+ <method name="float" qualifiers="constructor">
<return type="float">
</return>
<argument index="0" name="from" type="int">
@@ -43,6 +43,226 @@
Cast an [int] value to a floating-point value, [code]float(1)[/code] will be equal to [code]1.0[/code].
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/int.xml b/doc/classes/int.xml
index 27d873831b..5ac9f8405a 100644
--- a/doc/classes/int.xml
+++ b/doc/classes/int.xml
@@ -23,14 +23,14 @@
<tutorials>
</tutorials>
<methods>
- <method name="int">
+ <method name="int" qualifiers="constructor">
<return type="int">
</return>
<description>
Constructs a default-initialized [int] set to [code]0[/code].
</description>
</method>
- <method name="int">
+ <method name="int" qualifiers="constructor">
<return type="int">
</return>
<argument index="0" name="from" type="int">
@@ -39,7 +39,7 @@
Constructs an [int] as a copy of the given [int].
</description>
</method>
- <method name="int">
+ <method name="int" qualifiers="constructor">
<return type="int">
</return>
<argument index="0" name="from" type="bool">
@@ -48,7 +48,7 @@
Cast a [bool] value to an integer value, [code]int(true)[/code] will be equals to 1 and [code]int(false)[/code] will be equals to 0.
</description>
</method>
- <method name="int">
+ <method name="int" qualifiers="constructor">
<return type="int">
</return>
<argument index="0" name="from" type="float">
@@ -57,6 +57,280 @@
Cast a float value to an integer value, this method simply removes the number fractions, so for example [code]int(2.7)[/code] will be equals to 2, [code]int(.1)[/code] will be equals to 0 and [code]int(-2.7)[/code] will be equals to -2.
</description>
</method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator !=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator %" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &amp;" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="right" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector2i">
+ </return>
+ <argument index="0" name="right" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="right" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Vector3i">
+ </return>
+ <argument index="0" name="right" type="Vector3i">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Quat">
+ </return>
+ <argument index="0" name="right" type="Quat">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator *" qualifiers="operator">
+ <return type="Color">
+ </return>
+ <argument index="0" name="right" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator +" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator -" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="float">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator /" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;&lt;" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &lt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ==" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;=" qualifiers="operator">
+ <return type="bool">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator &gt;&gt;" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ^" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator |" qualifiers="operator">
+ <return type="int">
+ </return>
+ <argument index="0" name="right" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="operator ~" qualifiers="operator">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/tools/doc_merge.py b/doc/tools/doc_merge.py
deleted file mode 100755
index f6f52f5d66..0000000000
--- a/doc/tools/doc_merge.py
+++ /dev/null
@@ -1,237 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import sys
-import xml.etree.ElementTree as ET
-
-
-tree = ET.parse(sys.argv[1])
-old_doc = tree.getroot()
-
-tree = ET.parse(sys.argv[2])
-new_doc = tree.getroot()
-
-f = file(sys.argv[3], "wb")
-tab = 0
-
-old_classes = {}
-
-
-def write_string(_f, text, newline=True):
- for t in range(tab):
- _f.write("\t")
- _f.write(text)
- if newline:
- _f.write("\n")
-
-
-def escape(ret):
- ret = ret.replace("&", "&amp;")
- ret = ret.replace("<", "&gt;")
- ret = ret.replace(">", "&lt;")
- ret = ret.replace("'", "&apos;")
- ret = ret.replace('"', "&quot;")
- return ret
-
-
-def inc_tab():
- global tab
- tab += 1
-
-
-def dec_tab():
- global tab
- tab -= 1
-
-
-write_string(f, '<?xml version="1.0" encoding="UTF-8" ?>')
-write_string(f, '<doc version="' + new_doc.attrib["version"] + '">')
-
-
-def get_tag(node, name):
- tag = ""
- if name in node.attrib:
- tag = " " + name + '="' + escape(node.attrib[name]) + '" '
- return tag
-
-
-def find_method_descr(old_class, name):
-
- methods = old_class.find("methods")
- if methods != None and len(list(methods)) > 0:
- for m in list(methods):
- if m.attrib["name"] == name:
- description = m.find("description")
- if description != None and description.text.strip() != "":
- return description.text
-
- return None
-
-
-def find_signal_descr(old_class, name):
-
- signals = old_class.find("signals")
- if signals != None and len(list(signals)) > 0:
- for m in list(signals):
- if m.attrib["name"] == name:
- description = m.find("description")
- if description != None and description.text.strip() != "":
- return description.text
-
- return None
-
-
-def find_constant_descr(old_class, name):
-
- if old_class is None:
- return None
- constants = old_class.find("constants")
- if constants != None and len(list(constants)) > 0:
- for m in list(constants):
- if m.attrib["name"] == name:
- if m.text.strip() != "":
- return m.text
- return None
-
-
-def write_class(c):
- class_name = c.attrib["name"]
- print("Parsing Class: " + class_name)
- if class_name in old_classes:
- old_class = old_classes[class_name]
- else:
- old_class = None
-
- category = get_tag(c, "category")
- inherits = get_tag(c, "inherits")
- write_string(f, '<class name="' + class_name + '" ' + category + inherits + ">")
- inc_tab()
-
- write_string(f, "<brief_description>")
-
- if old_class != None:
- old_brief_descr = old_class.find("brief_description")
- if old_brief_descr != None:
- write_string(f, escape(old_brief_descr.text.strip()))
-
- write_string(f, "</brief_description>")
-
- write_string(f, "<description>")
- if old_class != None:
- old_descr = old_class.find("description")
- if old_descr != None:
- write_string(f, escape(old_descr.text.strip()))
-
- write_string(f, "</description>")
-
- methods = c.find("methods")
- if methods != None and len(list(methods)) > 0:
-
- write_string(f, "<methods>")
- inc_tab()
-
- for m in list(methods):
- qualifiers = get_tag(m, "qualifiers")
-
- write_string(f, '<method name="' + escape(m.attrib["name"]) + '" ' + qualifiers + ">")
- inc_tab()
-
- for a in list(m):
- if a.tag == "return":
- typ = get_tag(a, "type")
- write_string(f, "<return" + typ + ">")
- write_string(f, "</return>")
- elif a.tag == "argument":
-
- default = get_tag(a, "default")
-
- write_string(
- f,
- '<argument index="'
- + a.attrib["index"]
- + '" name="'
- + escape(a.attrib["name"])
- + '" type="'
- + a.attrib["type"]
- + '"'
- + default
- + ">",
- )
- write_string(f, "</argument>")
-
- write_string(f, "<description>")
- if old_class != None:
- old_method_descr = find_method_descr(old_class, m.attrib["name"])
- if old_method_descr:
- write_string(f, escape(escape(old_method_descr.strip())))
-
- write_string(f, "</description>")
- dec_tab()
- write_string(f, "</method>")
- dec_tab()
- write_string(f, "</methods>")
-
- signals = c.find("signals")
- if signals != None and len(list(signals)) > 0:
-
- write_string(f, "<signals>")
- inc_tab()
-
- for m in list(signals):
-
- write_string(f, '<signal name="' + escape(m.attrib["name"]) + '">')
- inc_tab()
-
- for a in list(m):
- if a.tag == "argument":
-
- write_string(
- f,
- '<argument index="'
- + a.attrib["index"]
- + '" name="'
- + escape(a.attrib["name"])
- + '" type="'
- + a.attrib["type"]
- + '">',
- )
- write_string(f, "</argument>")
-
- write_string(f, "<description>")
- if old_class != None:
- old_signal_descr = find_signal_descr(old_class, m.attrib["name"])
- if old_signal_descr:
- write_string(f, escape(old_signal_descr.strip()))
- write_string(f, "</description>")
- dec_tab()
- write_string(f, "</signal>")
- dec_tab()
- write_string(f, "</signals>")
-
- constants = c.find("constants")
- if constants != None and len(list(constants)) > 0:
-
- write_string(f, "<constants>")
- inc_tab()
-
- for m in list(constants):
-
- write_string(f, '<constant name="' + escape(m.attrib["name"]) + '" value="' + m.attrib["value"] + '">')
- old_constant_descr = find_constant_descr(old_class, m.attrib["name"])
- if old_constant_descr:
- write_string(f, escape(old_constant_descr.strip()))
- write_string(f, "</constant>")
-
- dec_tab()
- write_string(f, "</constants>")
-
- dec_tab()
- write_string(f, "</class>")
-
-
-for c in list(old_doc):
- old_classes[c.attrib["name"]] = c
-
-for c in list(new_doc):
- write_class(c)
-write_string(f, "</doc>\n")
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index ed147f31cd..5335116c8a 100755
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -1042,6 +1042,8 @@ def make_footer(): # type: () -> str
".. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`\n"
".. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`\n"
".. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)`\n"
+ ".. |constructor| replace:: :abbr:`constructor (This method is used to construct a type.)`\n"
+ ".. |operator| replace:: :abbr:`operator (This method describes a valid operator to use with this type as left-hand operand.)`\n"
)
# fmt: on
diff --git a/editor/doc_data.cpp b/editor/doc_data.cpp
index 6767159721..78c601d4bc 100644
--- a/editor/doc_data.cpp
+++ b/editor/doc_data.cpp
@@ -569,12 +569,15 @@ void DocData::generate(bool p_basic_types) {
method_list.sort();
Variant::get_constructor_list(Variant::Type(i), &method_list);
- for (int j = 0; j < Variant::OP_AND; j++) { //showing above 'and' is pretty confusing and there are a lot of variations
-
+ for (int j = 0; j < Variant::OP_AND; j++) { // Showing above 'and' is pretty confusing and there are a lot of variations.
for (int k = 0; k < Variant::VARIANT_MAX; k++) {
Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(j), Variant::Type(i), Variant::Type(k));
- if (rt != Variant::NIL) {
- //has operator
+ if (rt != Variant::NIL) { // Has operator.
+ // Skip String % operator as it's registered separately for each Variant arg type,
+ // we'll add it manually below.
+ if (i == Variant::STRING && Variant::Operator(j) == Variant::OP_MODULE) {
+ continue;
+ }
MethodInfo mi;
mi.name = "operator " + Variant::get_operator_name(Variant::Operator(j));
mi.return_val.type = rt;
@@ -589,6 +592,21 @@ void DocData::generate(bool p_basic_types) {
}
}
+ if (i == Variant::STRING) {
+ // We skipped % operator above, and we register it manually once for Variant arg type here.
+ MethodInfo mi;
+ mi.name = "operator %";
+ mi.return_val.type = Variant::STRING;
+
+ PropertyInfo arg;
+ arg.name = "right";
+ arg.type = Variant::NIL;
+ arg.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
+ mi.arguments.push_back(arg);
+
+ method_list.push_back(mi);
+ }
+
if (Variant::is_keyed(Variant::Type(i))) {
MethodInfo mi;
mi.name = "operator []";
@@ -718,6 +736,43 @@ void DocData::generate(bool p_basic_types) {
}
c.properties.push_back(pd);
}
+
+ List<StringName> builtin_funcs;
+ Variant::get_builtin_function_list(&builtin_funcs);
+ builtin_funcs.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E = builtin_funcs.front(); E; E = E->next()) {
+ MethodDoc md;
+ md.name = E->get();
+ //return
+ if (Variant::has_builtin_func_return_value(E->get())) {
+ PropertyInfo pi;
+ pi.type = Variant::get_builtin_func_return_type(E->get());
+ if (pi.type == Variant::NIL) {
+ pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ DocData::ArgumentDoc ad;
+ argument_doc_from_arginfo(ad, pi);
+ md.return_type = ad.type;
+ }
+
+ if (Variant::is_builtin_func_vararg(E->get())) {
+ md.qualifiers = "vararg";
+ } else {
+ for (int i = 0; i < Variant::get_builtin_func_argument_count(E->get()); i++) {
+ PropertyInfo pi;
+ pi.type = Variant::get_builtin_func_argument_type(E->get(), i);
+ pi.name = Variant::get_builtin_func_argument_name(E->get(), i);
+ if (pi.type == Variant::NIL) {
+ pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ DocData::ArgumentDoc ad;
+ argument_doc_from_arginfo(ad, pi);
+ md.arguments.push_back(ad);
+ }
+ }
+
+ c.methods.push_back(md);
+ }
}
// Built-in script reference.
@@ -1147,7 +1202,7 @@ Error DocData::save_classes(const String &p_default_path, const Map<String, Stri
qualifiers += " qualifiers=\"" + m.qualifiers.xml_escape() + "\"";
}
- _write_string(f, 2, "<method name=\"" + m.name + "\"" + qualifiers + ">");
+ _write_string(f, 2, "<method name=\"" + m.name.xml_escape() + "\"" + qualifiers + ">");
if (m.return_type != "") {
String enum_text;
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index e330713cfb..49d8e58955 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -866,6 +866,8 @@ void EditorPlugin::_bind_methods() {
ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_canvas_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "forward_spatial_gui_input", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_spatial_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ ClassDB::add_virtual_method(get_class_static(), MethodInfo("forward_spatial_force_draw_over_viewport", PropertyInfo(Variant::OBJECT, "overlay", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_plugin_name"));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "get_plugin_icon"));
ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "has_main_screen"));
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index d8da520ed7..bd21883259 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -153,81 +153,6 @@
DevelopmentTeam = $team_id;
ProvisioningStyle = Automatic;
SystemCapabilities = {
- com.apple.AccessWiFi = {
- enabled = $access_wifi;
- };
- com.apple.ApplePay = {
- enabled = 0;
- };
- com.apple.ApplicationGroups.iOS = {
- enabled = 0;
- };
- com.apple.AutoFillCredentialProvider = {
- enabled = 0;
- };
- com.apple.BackgroundModes = {
- enabled = 0;
- };
- com.apple.ClassKit = {
- enabled = 0;
- };
- com.apple.DataProtection = {
- enabled = 0;
- };
- com.apple.GameCenter.iOS = {
- enabled = $game_center;
- };
- com.apple.HealthKit = {
- enabled = 0;
- };
- com.apple.HomeKit = {
- enabled = 0;
- };
- com.apple.HotspotConfiguration = {
- enabled = 0;
- };
- com.apple.InAppPurchase = {
- enabled = $in_app_purchases;
- };
- com.apple.InterAppAudio = {
- enabled = 0;
- };
- com.apple.Keychain = {
- enabled = 0;
- };
- com.apple.Maps.iOS = {
- enabled = 0;
- };
- com.apple.Multipath = {
- enabled = 0;
- };
- com.apple.NearFieldCommunicationTagReading = {
- enabled = 0;
- };
- com.apple.NetworkExtensions.iOS = {
- enabled = 0;
- };
- com.apple.Push = {
- enabled = $push_notifications;
- };
- com.apple.SafariKeychain = {
- enabled = 0;
- };
- com.apple.Siri = {
- enabled = 0;
- };
- com.apple.VPNLite = {
- enabled = 0;
- };
- com.apple.WAC = {
- enabled = 0;
- };
- com.apple.Wallet = {
- enabled = 0;
- };
- com.apple.iCloud = {
- enabled = 0;
- };
};
};
};
@@ -393,7 +318,7 @@
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)",
+ "$(PROJECT_DIR)/**",
);
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -423,7 +348,7 @@
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "$(PROJECT_DIR)",
+ "$(PROJECT_DIR)/**",
);
PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/modules/SCsub b/modules/SCsub
index edfc4ed9c6..24598f4b28 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -47,7 +47,14 @@ for name, path in env.module_list.items():
# Some modules are not linked automatically but can be enabled optionally
# on iOS, so we handle those specially.
- if env["platform"] == "iphone" and name in ["arkit", "camera"]:
+ if env["platform"] == "iphone" and name in [
+ "arkit",
+ "camera",
+ "camera_iphone",
+ "gamecenter",
+ "inappstore",
+ "icloud",
+ ]:
continue
lib = env_modules.add_library("module_%s" % name, env.modules_sources)
diff --git a/modules/arkit/arkit.gdip b/modules/arkit/arkit.gdip
new file mode 100644
index 0000000000..22c0a07e26
--- /dev/null
+++ b/modules/arkit/arkit.gdip
@@ -0,0 +1,18 @@
+[config]
+name="ARKit"
+binary="arkit_lib.a"
+
+initialization="register_arkit_types"
+deinitialization="unregister_arkit_types"
+
+[dependencies]
+linked=[]
+embedded=[]
+system=["AVFoundation.framework", "ARKit.framework"]
+
+capabilities=["arkit"]
+
+files=[]
+
+[plist]
+NSCameraUsageDescription="Device camera is used for some functionality"
diff --git a/modules/arkit/register_types.cpp b/modules/arkit/arkit_module.cpp
index 91069ab364..87ee3b87a5 100644
--- a/modules/arkit/register_types.cpp
+++ b/modules/arkit/arkit_module.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* register_types.cpp */
+/* arkit_module.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "register_types.h"
+#include "arkit_module.h"
#include "arkit_interface.h"
diff --git a/modules/arkit/register_types.h b/modules/arkit/arkit_module.h
index f8939a1e3f..8aa8175ed5 100644
--- a/modules/arkit/register_types.h
+++ b/modules/arkit/arkit_module.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* register_types.h */
+/* arkit_module.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/modules/camera/SCsub b/modules/camera/SCsub
index 631a65bde2..de97724d09 100644
--- a/modules/camera/SCsub
+++ b/modules/camera/SCsub
@@ -5,17 +5,7 @@ Import("env_modules")
env_camera = env_modules.Clone()
-if env["platform"] == "iphone":
- # (iOS) Enable module support
- env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
-
- # (iOS) Build as separate static library
- modules_sources = []
- env_camera.add_source_files(modules_sources, "register_types.cpp")
- env_camera.add_source_files(modules_sources, "camera_ios.mm")
- mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources)
-
-elif env["platform"] == "windows":
+if env["platform"] == "windows":
env_camera.add_source_files(env.modules_sources, "register_types.cpp")
env_camera.add_source_files(env.modules_sources, "camera_win.cpp")
diff --git a/modules/camera/config.py b/modules/camera/config.py
index 87d7542741..8a22751aa7 100644
--- a/modules/camera/config.py
+++ b/modules/camera/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return platform == "iphone" or platform == "osx" or platform == "windows"
+ return platform == "osx" or platform == "windows"
def configure(env):
diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp
index 3b6c916914..9479310a13 100644
--- a/modules/camera/register_types.cpp
+++ b/modules/camera/register_types.cpp
@@ -33,9 +33,6 @@
#if defined(WINDOWS_ENABLED)
#include "camera_win.h"
#endif
-#if defined(IPHONE_ENABLED)
-#include "camera_ios.h"
-#endif
#if defined(OSX_ENABLED)
#include "camera_osx.h"
#endif
@@ -44,9 +41,6 @@ void register_camera_types() {
#if defined(WINDOWS_ENABLED)
CameraServer::make_default<CameraWindows>();
#endif
-#if defined(IPHONE_ENABLED)
- CameraServer::make_default<CameraIOS>();
-#endif
#if defined(OSX_ENABLED)
CameraServer::make_default<CameraOSX>();
#endif
diff --git a/modules/camera_iphone/SCsub b/modules/camera_iphone/SCsub
new file mode 100644
index 0000000000..0a37d9a6f5
--- /dev/null
+++ b/modules/camera_iphone/SCsub
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_camera = env_modules.Clone()
+
+# (iOS) Enable module support
+env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
+
+# (iOS) Build as separate static library
+modules_sources = []
+env_camera.add_source_files(modules_sources, "*.cpp")
+env_camera.add_source_files(modules_sources, "*.mm")
+mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources)
diff --git a/modules/camera_iphone/camera.gdip b/modules/camera_iphone/camera.gdip
new file mode 100644
index 0000000000..09017b8d27
--- /dev/null
+++ b/modules/camera_iphone/camera.gdip
@@ -0,0 +1,18 @@
+[config]
+name="Camera"
+binary="camera_lib.a"
+
+initialization="register_camera_types"
+deinitialization="unregister_camera_types"
+
+[dependencies]
+linked=[]
+embedded=[]
+system=["AVFoundation.framework"]
+
+capabilities=[]
+
+files=[]
+
+[plist]
+NSCameraUsageDescription="Device camera is used for some functionality"
diff --git a/modules/camera/camera_ios.h b/modules/camera_iphone/camera_ios.h
index 7da43e4851..7da43e4851 100644
--- a/modules/camera/camera_ios.h
+++ b/modules/camera_iphone/camera_ios.h
diff --git a/modules/camera/camera_ios.mm b/modules/camera_iphone/camera_ios.mm
index e4cb928805..e4cb928805 100644
--- a/modules/camera/camera_ios.mm
+++ b/modules/camera_iphone/camera_ios.mm
diff --git a/modules/camera_iphone/camera_module.cpp b/modules/camera_iphone/camera_module.cpp
new file mode 100644
index 0000000000..f3d00be204
--- /dev/null
+++ b/modules/camera_iphone/camera_module.cpp
@@ -0,0 +1,40 @@
+/*************************************************************************/
+/* camera_module.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "camera_module.h"
+
+#include "camera_ios.h"
+
+void register_camera_types() {
+ CameraServer::make_default<CameraIOS>();
+}
+
+void unregister_camera_types() {
+}
diff --git a/modules/camera_iphone/camera_module.h b/modules/camera_iphone/camera_module.h
new file mode 100644
index 0000000000..d123071a70
--- /dev/null
+++ b/modules/camera_iphone/camera_module.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* camera_module.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+void register_camera_types();
+void unregister_camera_types();
diff --git a/modules/camera_iphone/config.py b/modules/camera_iphone/config.py
new file mode 100644
index 0000000000..e68603fc93
--- /dev/null
+++ b/modules/camera_iphone/config.py
@@ -0,0 +1,6 @@
+def can_build(env, platform):
+ return platform == "iphone"
+
+
+def configure(env):
+ pass
diff --git a/modules/gamecenter/SCsub b/modules/gamecenter/SCsub
new file mode 100644
index 0000000000..72fbf7ab0e
--- /dev/null
+++ b/modules/gamecenter/SCsub
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_gamecenter = env_modules.Clone()
+
+# (iOS) Enable module support
+env_gamecenter.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
+
+# (iOS) Build as separate static library
+modules_sources = []
+env_gamecenter.add_source_files(modules_sources, "*.cpp")
+env_gamecenter.add_source_files(modules_sources, "*.mm")
+mod_lib = env_modules.add_library("#bin/libgodot_gamecenter_module" + env["LIBSUFFIX"], modules_sources)
diff --git a/modules/gamecenter/config.py b/modules/gamecenter/config.py
new file mode 100644
index 0000000000..e68603fc93
--- /dev/null
+++ b/modules/gamecenter/config.py
@@ -0,0 +1,6 @@
+def can_build(env, platform):
+ return platform == "iphone"
+
+
+def configure(env):
+ pass
diff --git a/platform/iphone/game_center.h b/modules/gamecenter/game_center.h
index cbfd616e56..76fd295460 100644
--- a/platform/iphone/game_center.h
+++ b/modules/gamecenter/game_center.h
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef GAME_CENTER_ENABLED
-
#ifndef GAME_CENTER_H
#define GAME_CENTER_H
@@ -71,5 +69,3 @@ public:
};
#endif
-
-#endif
diff --git a/platform/iphone/game_center.mm b/modules/gamecenter/game_center.mm
index 0f8c0100c3..114f639a32 100644
--- a/platform/iphone/game_center.mm
+++ b/modules/gamecenter/game_center.mm
@@ -28,28 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef GAME_CENTER_ENABLED
-
#include "game_center.h"
+#import "platform/iphone/app_delegate.h"
-#ifdef __IPHONE_9_0
-
-#import <GameKit/GameKit.h>
-extern "C" {
-
-#else
-
-extern "C" {
+#import "game_center_delegate.h"
+#import "platform/iphone/view_controller.h"
#import <GameKit/GameKit.h>
-#endif
-
-#import "app_delegate.h"
-};
-
-#import "view_controller.h"
-
GameCenter *GameCenter::instance = NULL;
+GodotGameCenterDelegate *gameCenterDelegate = nil;
void GameCenter::_bind_methods() {
ClassDB::bind_method(D_METHOD("authenticate"), &GameCenter::authenticate);
@@ -76,7 +63,7 @@ Error GameCenter::authenticate() {
GKLocalPlayer *player = [GKLocalPlayer localPlayer];
ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE);
- ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController;
+ UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController;
ERR_FAIL_COND_V(!root_controller, FAILED);
// This handler is called several times. First when the view needs to be shown, then again
@@ -305,10 +292,10 @@ Error GameCenter::show_game_center(Dictionary p_params) {
GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init];
ERR_FAIL_COND_V(!controller, FAILED);
- ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController;
+ UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController;
ERR_FAIL_COND_V(!root_controller, FAILED);
- controller.gameCenterDelegate = root_controller;
+ controller.gameCenterDelegate = gameCenterDelegate;
controller.viewState = view_state;
if (view_state == GKGameCenterViewControllerStateLeaderboards) {
controller.leaderboardIdentifier = nil;
@@ -382,8 +369,12 @@ GameCenter::GameCenter() {
ERR_FAIL_COND(instance != NULL);
instance = this;
authenticated = false;
-};
-GameCenter::~GameCenter() {}
+ gameCenterDelegate = [[GodotGameCenterDelegate alloc] init];
+};
-#endif
+GameCenter::~GameCenter() {
+ if (gameCenterDelegate) {
+ gameCenterDelegate = nil;
+ }
+}
diff --git a/modules/gamecenter/game_center_delegate.h b/modules/gamecenter/game_center_delegate.h
new file mode 100644
index 0000000000..1b7025f915
--- /dev/null
+++ b/modules/gamecenter/game_center_delegate.h
@@ -0,0 +1,35 @@
+/*************************************************************************/
+/* game_center_delegate.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#import <GameKit/GameKit.h>
+
+@interface GodotGameCenterDelegate : NSObject <GKGameCenterControllerDelegate>
+
+@end
diff --git a/modules/gamecenter/game_center_delegate.mm b/modules/gamecenter/game_center_delegate.mm
new file mode 100644
index 0000000000..9a10c439c6
--- /dev/null
+++ b/modules/gamecenter/game_center_delegate.mm
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* game_center_delegate.mm */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#import "game_center_delegate.h"
+
+#include "game_center.h"
+
+@implementation GodotGameCenterDelegate
+
+- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController {
+ //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone
+ if (GameCenter::get_singleton()) {
+ GameCenter::get_singleton()->game_center_closed();
+ }
+ [gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
+}
+
+@end
diff --git a/modules/gamecenter/game_center_module.cpp b/modules/gamecenter/game_center_module.cpp
new file mode 100644
index 0000000000..6c5157345f
--- /dev/null
+++ b/modules/gamecenter/game_center_module.cpp
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* game_center_module.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "game_center_module.h"
+
+#include "core/config/engine.h"
+
+#include "game_center.h"
+
+GameCenter *game_center;
+
+void register_gamecenter_types() {
+ game_center = memnew(GameCenter);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center));
+}
+
+void unregister_gamecenter_types() {
+ if (game_center) {
+ memdelete(game_center);
+ }
+}
diff --git a/modules/gamecenter/game_center_module.h b/modules/gamecenter/game_center_module.h
new file mode 100644
index 0000000000..8da3ae02ee
--- /dev/null
+++ b/modules/gamecenter/game_center_module.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* game_center_module.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+void register_gamecenter_types();
+void unregister_gamecenter_types();
diff --git a/modules/gamecenter/gamecenter.gdip b/modules/gamecenter/gamecenter.gdip
new file mode 100644
index 0000000000..eb44effbdd
--- /dev/null
+++ b/modules/gamecenter/gamecenter.gdip
@@ -0,0 +1,17 @@
+[config]
+name="GameCenter"
+binary="gamecenter_lib.a"
+
+initialization="register_gamecenter_types"
+deinitialization="unregister_gamecenter_types"
+
+[dependencies]
+linked=[]
+embedded=[]
+system=["GameKit.framework"]
+
+capabilities=["gamekit"]
+
+files=[]
+
+[plist]
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 60051499a5..d90b3e52d0 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -94,14 +94,15 @@
<argument index="1" name="message" type="String" default="&quot;&quot;">
</argument>
<description>
- Asserts that the [code]condition[/code] is [code]true[/code]. If the [code]condition[/code] is [code]false[/code], an error is generated and the program is halted until you resume it. Only executes in debug builds, or when running the game from the editor. Use it for debugging purposes, to make sure a statement is [code]true[/code] during development.
+ Asserts that the [code]condition[/code] is [code]true[/code]. If the [code]condition[/code] is [code]false[/code], an error is generated. When running from the editor, the running project will also be paused until you resume it. This can be used as a stronger form of [method push_error] for reporting errors to project developers or add-on users.
+ [b]Note:[/b] For performance reasons, the code inside [method assert] is only executed in debug builds or when running the project from the editor. Don't include code that has side effects in an [method assert] call. Otherwise, the project will behave differently when exported in release mode.
The optional [code]message[/code] argument, if given, is shown in addition to the generic "Assertion failed" message. You can use this to provide additional details about why the assertion failed.
[codeblock]
- # Imagine we always want speed to be between 0 and 20
- speed = -10
+ # Imagine we always want speed to be between 0 and 20.
+ var speed = -10
assert(speed &lt; 20) # True, the program will continue
assert(speed &gt;= 0) # False, the program will stop
- assert(speed &gt;= 0 &amp;&amp; speed &lt; 20) # You can also combine the two conditional statements in one check
+ assert(speed &gt;= 0 and speed &lt; 20) # You can also combine the two conditional statements in one check
assert(speed &lt; 20, "speed = %f, but the speed limit is 20" % speed) # Show a message with clarifying details
[/codeblock]
</description>
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index d0acc14a04..a426046797 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2315,11 +2315,6 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (GDScriptParser::get_builtin_function(call->function_name) < GDScriptFunctions::FUNC_MAX) {
MethodInfo info = GDScriptFunctions::get_info(GDScriptParser::get_builtin_function(call->function_name));
-
- if ((info.name == "load" || info.name == "preload") && bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) {
- _get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), r_result);
- }
-
r_arghint = _make_arguments_hint(info, p_argidx);
return;
} else if (GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 1eb3846319..fde3662d66 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2486,26 +2486,28 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
}
}
- if (!check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
- // Arguments.
- push_completion_call(call);
- make_completion_context(COMPLETION_CALL_ARGUMENTS, call, 0, true);
- int argument_index = 0;
- do {
- make_completion_context(COMPLETION_CALL_ARGUMENTS, call, argument_index++, true);
- if (check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
- // Allow for trailing comma.
- break;
- }
- ExpressionNode *argument = parse_expression(false);
- if (argument == nullptr) {
- push_error(R"(Expected expression as the function argument.)");
- } else {
- call->arguments.push_back(argument);
- }
- } while (match(GDScriptTokenizer::Token::COMMA));
- pop_completion_call();
+ // Arguments.
+ CompletionType ct = COMPLETION_CALL_ARGUMENTS;
+ if (get_builtin_function(call->function_name) == GDScriptFunctions::RESOURCE_LOAD) {
+ ct = COMPLETION_RESOURCE_PATH;
}
+ push_completion_call(call);
+ int argument_index = 0;
+ do {
+ make_completion_context(ct, call, argument_index++, true);
+ if (check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
+ // Allow for trailing comma.
+ break;
+ }
+ ExpressionNode *argument = parse_expression(false);
+ if (argument == nullptr) {
+ push_error(R"(Expected expression as the function argument.)");
+ } else {
+ call->arguments.push_back(argument);
+ }
+ ct = COMPLETION_CALL_ARGUMENTS;
+ } while (match(GDScriptTokenizer::Token::COMMA));
+ pop_completion_call();
pop_multiline();
consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after call arguments.)*");
diff --git a/modules/icloud/SCsub b/modules/icloud/SCsub
new file mode 100644
index 0000000000..805a484600
--- /dev/null
+++ b/modules/icloud/SCsub
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_icloud = env_modules.Clone()
+
+# (iOS) Enable module support
+env_icloud.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
+
+# (iOS) Build as separate static library
+modules_sources = []
+env_icloud.add_source_files(modules_sources, "*.cpp")
+env_icloud.add_source_files(modules_sources, "*.mm")
+mod_lib = env_modules.add_library("#bin/libgodot_icloud_module" + env["LIBSUFFIX"], modules_sources)
diff --git a/modules/icloud/config.py b/modules/icloud/config.py
new file mode 100644
index 0000000000..e68603fc93
--- /dev/null
+++ b/modules/icloud/config.py
@@ -0,0 +1,6 @@
+def can_build(env, platform):
+ return platform == "iphone"
+
+
+def configure(env):
+ pass
diff --git a/modules/icloud/icloud.gdip b/modules/icloud/icloud.gdip
new file mode 100644
index 0000000000..9f81be8a34
--- /dev/null
+++ b/modules/icloud/icloud.gdip
@@ -0,0 +1,17 @@
+[config]
+name="iCloud"
+binary="icloud_lib.a"
+
+initialization="register_icloud_types"
+deinitialization="unregister_icloud_types"
+
+[dependencies]
+linked=[]
+embedded=[]
+system=[]
+
+capabilities=[]
+
+files=[]
+
+[plist]
diff --git a/platform/iphone/icloud.h b/modules/icloud/icloud.h
index 5f59abdfc0..35eede0bf9 100644
--- a/platform/iphone/icloud.h
+++ b/modules/icloud/icloud.h
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef ICLOUD_ENABLED
-
#ifndef ICLOUD_H
#define ICLOUD_H
@@ -60,5 +58,3 @@ public:
};
#endif
-
-#endif
diff --git a/platform/iphone/icloud.mm b/modules/icloud/icloud.mm
index 3d81349883..8a8ddbefe9 100644
--- a/platform/iphone/icloud.mm
+++ b/modules/icloud/icloud.mm
@@ -28,22 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef ICLOUD_ENABLED
-
#include "icloud.h"
-#ifndef __IPHONE_9_0
-extern "C" {
-#endif
-
-#import "app_delegate.h"
+#import "platform/iphone/app_delegate.h"
#import <Foundation/Foundation.h>
-#ifndef __IPHONE_9_0
-};
-#endif
-
ICloud *ICloud::instance = NULL;
void ICloud::_bind_methods() {
@@ -353,5 +343,3 @@ ICloud::ICloud() {
}
ICloud::~ICloud() {}
-
-#endif
diff --git a/modules/icloud/icloud_module.cpp b/modules/icloud/icloud_module.cpp
new file mode 100644
index 0000000000..43fdc7d45e
--- /dev/null
+++ b/modules/icloud/icloud_module.cpp
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* icloud_module.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "icloud_module.h"
+
+#include "core/config/engine.h"
+
+#include "icloud.h"
+
+ICloud *icloud;
+
+void register_icloud_types() {
+ icloud = memnew(ICloud);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud));
+}
+
+void unregister_icloud_types() {
+ if (icloud) {
+ memdelete(icloud);
+ }
+}
diff --git a/modules/icloud/icloud_module.h b/modules/icloud/icloud_module.h
new file mode 100644
index 0000000000..7fd057525e
--- /dev/null
+++ b/modules/icloud/icloud_module.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* icloud_module.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+void register_icloud_types();
+void unregister_icloud_types();
diff --git a/modules/inappstore/SCsub b/modules/inappstore/SCsub
new file mode 100644
index 0000000000..cee6a256d5
--- /dev/null
+++ b/modules/inappstore/SCsub
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+Import("env")
+Import("env_modules")
+
+env_inappstore = env_modules.Clone()
+
+# (iOS) Enable module support
+env_inappstore.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
+
+# (iOS) Build as separate static library
+modules_sources = []
+env_inappstore.add_source_files(modules_sources, "*.cpp")
+env_inappstore.add_source_files(modules_sources, "*.mm")
+mod_lib = env_modules.add_library("#bin/libgodot_inappstore_module" + env["LIBSUFFIX"], modules_sources)
diff --git a/modules/inappstore/config.py b/modules/inappstore/config.py
new file mode 100644
index 0000000000..e68603fc93
--- /dev/null
+++ b/modules/inappstore/config.py
@@ -0,0 +1,6 @@
+def can_build(env, platform):
+ return platform == "iphone"
+
+
+def configure(env):
+ pass
diff --git a/platform/iphone/in_app_store.h b/modules/inappstore/in_app_store.h
index 85075e4e20..c8e5d17cec 100644
--- a/platform/iphone/in_app_store.h
+++ b/modules/inappstore/in_app_store.h
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef STOREKIT_ENABLED
-
#ifndef IN_APP_STORE_H
#define IN_APP_STORE_H
@@ -77,5 +75,3 @@ public:
};
#endif
-
-#endif
diff --git a/platform/iphone/in_app_store.mm b/modules/inappstore/in_app_store.mm
index 3eec9dae69..62977318c1 100644
--- a/platform/iphone/in_app_store.mm
+++ b/modules/inappstore/in_app_store.mm
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef STOREKIT_ENABLED
-
#include "in_app_store.h"
#import <Foundation/Foundation.h>
@@ -411,5 +409,3 @@ InAppStore::~InAppStore() {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:transactions_observer];
transactions_observer = nil;
}
-
-#endif
diff --git a/modules/inappstore/in_app_store_module.cpp b/modules/inappstore/in_app_store_module.cpp
new file mode 100644
index 0000000000..039bdd4f83
--- /dev/null
+++ b/modules/inappstore/in_app_store_module.cpp
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* in_app_store_module.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "in_app_store_module.h"
+
+#include "core/config/engine.h"
+
+#include "in_app_store.h"
+
+InAppStore *store_kit;
+
+void register_inappstore_types() {
+ store_kit = memnew(InAppStore);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit));
+}
+
+void unregister_inappstore_types() {
+ if (store_kit) {
+ memdelete(store_kit);
+ }
+}
diff --git a/modules/inappstore/in_app_store_module.h b/modules/inappstore/in_app_store_module.h
new file mode 100644
index 0000000000..44673e58bc
--- /dev/null
+++ b/modules/inappstore/in_app_store_module.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* in_app_store_module.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+void register_inappstore_types();
+void unregister_inappstore_types();
diff --git a/modules/inappstore/inappstore.gdip b/modules/inappstore/inappstore.gdip
new file mode 100644
index 0000000000..7a5efb8ad3
--- /dev/null
+++ b/modules/inappstore/inappstore.gdip
@@ -0,0 +1,17 @@
+[config]
+name="InAppStore"
+binary="inappstore_lib.a"
+
+initialization="register_inappstore_types"
+deinitialization="unregister_inappstore_types"
+
+[dependencies]
+linked=[]
+embedded=[]
+system=["StoreKit.framework"]
+
+capabilities=[]
+
+files=[]
+
+[plist]
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
index 4c1df529fc..58d8dceb25 100644
--- a/modules/mono/glue/gd_glue.cpp
+++ b/modules/mono/glue/gd_glue.cpp
@@ -55,7 +55,8 @@ MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) {
Variant what = GDMonoMarshal::mono_object_to_variant(p_what);
const Variant *args[1] = { &what };
Callable::CallError ce;
- Variant ret = Variant::construct(Variant::Type(p_type), args, 1, ce);
+ Variant ret;
+ Variant::construct(Variant::Type(p_type), ret, args, 1, ce);
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
return GDMonoMarshal::variant_to_mono_object(ret);
}
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 1dd37dabe5..0a558f8e3d 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -8,9 +8,6 @@ iphone_lib = [
"main.m",
"app_delegate.mm",
"view_controller.mm",
- "game_center.mm",
- "in_app_store.mm",
- "icloud.mm",
"ios.mm",
"vulkan_context_iphone.mm",
"display_server_iphone.mm",
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index c9891309fe..c1942e77dd 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -36,6 +36,7 @@
#include "os_iphone.h"
#import "view_controller.h"
+#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioServices.h>
#define kRenderingFrequency 60
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index ab453c353f..0456458326 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -35,9 +35,6 @@ def get_opts():
" validation layers)",
False,
),
- BoolVariable("game_center", "Support for game center", True),
- BoolVariable("store_kit", "Support for in-app store", True),
- BoolVariable("icloud", "Support for iCloud", True),
BoolVariable("ios_exceptions", "Enable exceptions", False),
("ios_triple", "Triple for ios toolchain", ""),
]
@@ -222,18 +219,6 @@ def configure(env):
]
)
- # Feature options
- if env["game_center"]:
- env.Append(CPPDEFINES=["GAME_CENTER_ENABLED"])
- env.Append(LINKFLAGS=["-framework", "GameKit"])
-
- if env["store_kit"]:
- env.Append(CPPDEFINES=["STOREKIT_ENABLED"])
- env.Append(LINKFLAGS=["-framework", "StoreKit"])
-
- if env["icloud"]:
- env.Append(CPPDEFINES=["ICLOUD_ENABLED"])
-
env.Prepend(
CPPPATH=[
"$IPHONESDK/usr/include",
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index cf46883b92..cbef136247 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -43,6 +43,7 @@
#include "editor/editor_settings.h"
#include "main/splash.gen.h"
#include "platform/iphone/logo.gen.h"
+#include "platform/iphone/plugin/godot_plugin_config.h"
#include "string.h"
#include <sys/stat.h>
@@ -54,6 +55,13 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Ref<ImageTexture> logo;
+ // Plugins
+ volatile bool plugins_changed;
+ Thread *check_for_changes_thread;
+ volatile bool quit_request;
+ Mutex plugins_lock;
+ Vector<PluginConfig> plugins;
+
typedef Error (*FileHandler)(String p_file, void *p_userdata);
static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
static Error _codesign(String p_file, void *p_userdata);
@@ -70,6 +78,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
String modules_fileref;
String modules_buildphase;
String modules_buildgrp;
+ Vector<String> capabilities;
};
struct ExportArchitecture {
String name;
@@ -102,7 +111,9 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
void _add_assets_to_project(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_project_data, const Vector<IOSExportAsset> &p_additional_assets);
Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets);
+ Error _copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets);
Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
+ Error _export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug);
bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const {
String pname = p_package;
@@ -127,6 +138,40 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
return true;
}
+ static void _check_for_changes_poll_thread(void *ud) {
+ EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud;
+
+ while (!ea->quit_request) {
+ // Nothing to do if we already know the plugins have changed.
+ if (!ea->plugins_changed) {
+ MutexLock lock(ea->plugins_lock);
+
+ Vector<PluginConfig> loaded_plugins = get_plugins();
+
+ if (ea->plugins.size() != loaded_plugins.size()) {
+ ea->plugins_changed = true;
+ } else {
+ for (int i = 0; i < ea->plugins.size(); i++) {
+ if (ea->plugins[i].name != loaded_plugins[i].name || ea->plugins[i].last_updated != loaded_plugins[i].last_updated) {
+ ea->plugins_changed = true;
+ break;
+ }
+ }
+ }
+ }
+
+ uint64_t wait = 3000000;
+ uint64_t time = OS::get_singleton()->get_ticks_usec();
+ while (OS::get_singleton()->get_ticks_usec() - time < wait) {
+ OS::get_singleton()->delay_usec(300000);
+
+ if (ea->quit_request) {
+ break;
+ }
+ }
+ }
+ }
+
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
virtual void get_export_options(List<ExportOption> *r_options) override;
@@ -136,13 +181,21 @@ public:
virtual String get_os_name() const override { return "iOS"; }
virtual Ref<Texture2D> get_logo() const override { return logo; }
+ virtual bool should_update_export_options() override {
+ bool export_options_changed = plugins_changed;
+ if (export_options_changed) {
+ // don't clear unless we're reporting true, to avoid race
+ plugins_changed = false;
+ }
+ return export_options_changed;
+ }
+
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override {
List<String> list;
list.push_back("ipa");
return list;
}
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
- virtual void add_module_code(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid);
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
@@ -156,6 +209,85 @@ public:
EditorExportPlatformIOS();
~EditorExportPlatformIOS();
+
+ /// List the gdip files in the directory specified by the p_path parameter.
+ static Vector<String> list_plugin_config_files(const String &p_path, bool p_check_directories) {
+ Vector<String> dir_files;
+ DirAccessRef da = DirAccess::open(p_path);
+ if (da) {
+ da->list_dir_begin();
+ while (true) {
+ String file = da->get_next();
+ if (file.empty()) {
+ break;
+ }
+
+ if (file == "." || file == "..") {
+ continue;
+ }
+
+ if (da->current_is_hidden()) {
+ continue;
+ }
+
+ if (da->current_is_dir()) {
+ if (p_check_directories) {
+ Vector<String> directory_files = list_plugin_config_files(p_path.plus_file(file), false);
+ for (int i = 0; i < directory_files.size(); ++i) {
+ dir_files.push_back(file.plus_file(directory_files[i]));
+ }
+ }
+
+ continue;
+ }
+
+ if (file.ends_with(PLUGIN_CONFIG_EXT)) {
+ dir_files.push_back(file);
+ }
+ }
+ da->list_dir_end();
+ }
+
+ return dir_files;
+ }
+
+ static Vector<PluginConfig> get_plugins() {
+ Vector<PluginConfig> loaded_plugins;
+
+ String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins");
+
+ if (DirAccess::exists(plugins_dir)) {
+ Vector<String> plugins_filenames = list_plugin_config_files(plugins_dir, true);
+
+ if (!plugins_filenames.empty()) {
+ Ref<ConfigFile> config_file = memnew(ConfigFile);
+ for (int i = 0; i < plugins_filenames.size(); i++) {
+ PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
+ if (config.valid_config) {
+ loaded_plugins.push_back(config);
+ } else {
+ print_error("Invalid plugin config file " + plugins_filenames[i]);
+ }
+ }
+ }
+ }
+
+ return loaded_plugins;
+ }
+
+ static Vector<PluginConfig> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
+ Vector<PluginConfig> enabled_plugins;
+ Vector<PluginConfig> all_plugins = get_plugins();
+ for (int i = 0; i < all_plugins.size(); i++) {
+ PluginConfig plugin = all_plugins[i];
+ bool enabled = p_presets->get("plugins/" + plugin.name);
+ if (enabled) {
+ enabled_plugins.push_back(plugin);
+ }
+ }
+
+ return enabled_plugins;
+ }
};
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
@@ -224,12 +356,16 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/camera"), false));
+ Vector<PluginConfig> found_plugins = get_plugins();
+
+ for (int i = 0; i < found_plugins.size(); i++) {
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false));
+ }
+
+ plugins_changed = false;
+ plugins = found_plugins;
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false));
@@ -345,18 +481,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "<true/>" : "<false/>") + "\n";
} else if (lines[i].find("$docs_sharing") != -1) {
strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "<true/>" : "<false/>") + "\n";
- } else if (lines[i].find("$access_wifi") != -1) {
- bool is_on = p_preset->get("capabilities/access_wifi");
- strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n";
- } else if (lines[i].find("$game_center") != -1) {
- bool is_on = p_preset->get("capabilities/game_center");
- strnew += lines[i].replace("$game_center", is_on ? "1" : "0") + "\n";
- } else if (lines[i].find("$in_app_purchases") != -1) {
- bool is_on = p_preset->get("capabilities/in_app_purchases");
- strnew += lines[i].replace("$in_app_purchases", is_on ? "1" : "0") + "\n";
- } else if (lines[i].find("$push_notifications") != -1) {
- bool is_on = p_preset->get("capabilities/push_notifications");
- strnew += lines[i].replace("$push_notifications", is_on ? "1" : "0") + "\n";
} else if (lines[i].find("$entitlements_push_notifications") != -1) {
bool is_on = p_preset->get("capabilities/push_notifications");
strnew += lines[i].replace("$entitlements_push_notifications", is_on ? "<key>aps-environment</key><string>development</string>" : "") + "\n";
@@ -366,15 +490,14 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
// I've removed armv7 as we can run on 64bit only devices
// Note that capabilities listed here are requirements for the app to be installed.
// They don't enable anything.
+ Vector<String> capabilities_list = p_config.capabilities;
- if ((bool)p_preset->get("capabilities/arkit")) {
- capabilities += "<string>arkit</string>\n";
- }
- if ((bool)p_preset->get("capabilities/game_center")) {
- capabilities += "<string>gamekit</string>\n";
+ if ((bool)p_preset->get("capabilities/access_wifi") && !capabilities_list.has("wifi")) {
+ capabilities_list.push_back("wifi");
}
- if ((bool)p_preset->get("capabilities/access_wifi")) {
- capabilities += "<string>wifi</string>\n";
+
+ for (int idx = 0; idx < capabilities_list.size(); idx++) {
+ capabilities += "<string>" + capabilities_list[idx] + "</string>\n";
}
strnew += lines[i].replace("$required_device_capabilities", capabilities);
@@ -984,28 +1107,6 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
// Note, frameworks like gamekit are always included in our project.pbxprof file
// even if turned off in capabilities.
- // We do need our ARKit framework
- if ((bool)p_preset->get("capabilities/arkit")) {
- String build_id = (++current_id).str();
- String ref_id = (++current_id).str();
-
- if (pbx_frameworks_build.length() > 0) {
- pbx_frameworks_build += ",\n";
- pbx_frameworks_refs += ",\n";
- }
-
- pbx_frameworks_build += build_id;
- pbx_frameworks_refs += ref_id;
-
- Dictionary format_dict;
- format_dict["build_id"] = build_id;
- format_dict["ref_id"] = ref_id;
- format_dict["name"] = "ARKit.framework";
- format_dict["file_path"] = "System/Library/Frameworks/ARKit.framework";
- format_dict["file_type"] = "wrapper.framework";
- pbx_files += file_info_format.format(format_dict, "$_");
- }
-
String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size());
str = str.replace("$additional_pbx_files", pbx_files);
str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build);
@@ -1021,142 +1122,179 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
}
}
-Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
+Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
+
String binary_name = p_out_dir.get_file().get_basename();
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
- for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) {
- String asset = p_assets[f_idx];
- if (!asset.begins_with("res://")) {
- // either SDK-builtin or already a part of the export template
- IOSExportAsset exported_asset = { asset, p_is_framework, p_should_embed };
- r_exported_assets.push_back(exported_asset);
+ DirAccess *da = DirAccess::create_for_path(p_asset);
+ if (!da) {
+ memdelete(filesystem_da);
+ ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + ".");
+ }
+ bool file_exists = da->file_exists(p_asset);
+ bool dir_exists = da->dir_exists(p_asset);
+ if (!file_exists && !dir_exists) {
+ memdelete(da);
+ memdelete(filesystem_da);
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ String base_dir = p_asset.get_base_dir().replace("res://", "");
+ String destination_dir;
+ String destination;
+ String asset_path;
+
+ bool create_framework = false;
+
+ if (p_is_framework && p_asset.ends_with(".dylib")) {
+ // For iOS we need to turn .dylib into .framework
+ // to be able to send application to AppStore
+ asset_path = String("dylibs").plus_file(base_dir);
+
+ String file_name;
+
+ if (!p_custom_file_name) {
+ file_name = p_asset.get_basename().get_file();
} else {
- DirAccess *da = DirAccess::create_for_path(asset);
- if (!da) {
- memdelete(filesystem_da);
- ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + asset + ".");
- }
- bool file_exists = da->file_exists(asset);
- bool dir_exists = da->dir_exists(asset);
- if (!file_exists && !dir_exists) {
- memdelete(da);
- memdelete(filesystem_da);
- return ERR_FILE_NOT_FOUND;
- }
+ file_name = *p_custom_file_name;
+ }
- String base_dir = asset.get_base_dir().replace("res://", "");
- String destination_dir;
- String destination;
- String asset_path;
+ String framework_name = file_name + ".framework";
- bool create_framework = false;
+ asset_path = asset_path.plus_file(framework_name);
+ destination_dir = p_out_dir.plus_file(asset_path);
+ destination = destination_dir.plus_file(file_name);
+ create_framework = true;
+ } else if (p_is_framework && (p_asset.ends_with(".framework") || p_asset.ends_with(".xcframework"))) {
+ asset_path = String("dylibs").plus_file(base_dir);
- if (p_is_framework && asset.ends_with(".dylib")) {
- // For iOS we need to turn .dylib into .framework
- // to be able to send application to AppStore
- asset_path = String("dylibs").plus_file(base_dir);
+ String file_name;
- String file_name = asset.get_basename().get_file();
- String framework_name = file_name + ".framework";
+ if (!p_custom_file_name) {
+ file_name = p_asset.get_file();
+ } else {
+ file_name = *p_custom_file_name;
+ }
- asset_path = asset_path.plus_file(framework_name);
- destination_dir = p_out_dir.plus_file(asset_path);
- destination = destination_dir.plus_file(file_name);
- create_framework = true;
- } else if (p_is_framework && (asset.ends_with(".framework") || asset.ends_with(".xcframework"))) {
- asset_path = String("dylibs").plus_file(base_dir);
+ asset_path = asset_path.plus_file(file_name);
+ destination_dir = p_out_dir.plus_file(asset_path);
+ destination = destination_dir;
+ } else {
+ asset_path = base_dir;
- String file_name = asset.get_file();
- asset_path = asset_path.plus_file(file_name);
- destination_dir = p_out_dir.plus_file(asset_path);
- destination = destination_dir;
- } else {
- asset_path = base_dir;
+ String file_name;
- String file_name = asset.get_file();
- destination_dir = p_out_dir.plus_file(asset_path);
- asset_path = asset_path.plus_file(file_name);
- destination = p_out_dir.plus_file(asset_path);
- }
+ if (!p_custom_file_name) {
+ file_name = p_asset.get_file();
+ } else {
+ file_name = *p_custom_file_name;
+ }
- if (!filesystem_da->dir_exists(destination_dir)) {
- Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
- if (make_dir_err) {
- memdelete(da);
- memdelete(filesystem_da);
- return make_dir_err;
- }
- }
+ destination_dir = p_out_dir.plus_file(asset_path);
+ asset_path = asset_path.plus_file(file_name);
+ destination = p_out_dir.plus_file(asset_path);
+ }
- Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination);
+ if (!filesystem_da->dir_exists(destination_dir)) {
+ Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
+ if (make_dir_err) {
memdelete(da);
- if (err) {
- memdelete(filesystem_da);
- return err;
- }
- IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
- r_exported_assets.push_back(exported_asset);
+ memdelete(filesystem_da);
+ return make_dir_err;
+ }
+ }
- if (create_framework) {
- String file_name = asset.get_basename().get_file();
- String framework_name = file_name + ".framework";
+ Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination);
+ memdelete(da);
+ if (err) {
+ memdelete(filesystem_da);
+ return err;
+ }
+ IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
+ r_exported_assets.push_back(exported_asset);
- // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib
- {
- List<String> install_name_args;
- install_name_args.push_back("-id");
- install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name));
- install_name_args.push_back(destination);
+ if (create_framework) {
+ String file_name;
- OS::get_singleton()->execute("install_name_tool", install_name_args, true);
- }
+ if (!p_custom_file_name) {
+ file_name = p_asset.get_basename().get_file();
+ } else {
+ file_name = *p_custom_file_name;
+ }
- // Creating Info.plist
- {
- String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- "<plist version=\"1.0\">\n"
- "<dict>\n"
- "<key>CFBundleShortVersionString</key>\n"
- "<string>1.0</string>\n"
- "<key>CFBundleIdentifier</key>\n"
- "<string>com.gdnative.framework.$name</string>\n"
- "<key>CFBundleName</key>\n"
- "<string>$name</string>\n"
- "<key>CFBundleExecutable</key>\n"
- "<string>$name</string>\n"
- "<key>DTPlatformName</key>\n"
- "<string>iphoneos</string>\n"
- "<key>CFBundleInfoDictionaryVersion</key>\n"
- "<string>6.0</string>\n"
- "<key>CFBundleVersion</key>\n"
- "<string>1</string>\n"
- "<key>CFBundlePackageType</key>\n"
- "<string>FMWK</string>\n"
- "<key>MinimumOSVersion</key>\n"
- "<string>10.0</string>\n"
- "</dict>\n"
- "</plist>";
-
- String info_plist = info_plist_format.replace("$name", file_name);
-
- FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
- if (f) {
- f->store_string(info_plist);
- f->close();
- memdelete(f);
- }
- }
+ String framework_name = file_name + ".framework";
+
+ // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib
+ {
+ List<String> install_name_args;
+ install_name_args.push_back("-id");
+ install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name));
+ install_name_args.push_back(destination);
+
+ OS::get_singleton()->execute("install_name_tool", install_name_args, true);
+ }
+
+ // Creating Info.plist
+ {
+ String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ "<plist version=\"1.0\">\n"
+ "<dict>\n"
+ "<key>CFBundleShortVersionString</key>\n"
+ "<string>1.0</string>\n"
+ "<key>CFBundleIdentifier</key>\n"
+ "<string>com.gdnative.framework.$name</string>\n"
+ "<key>CFBundleName</key>\n"
+ "<string>$name</string>\n"
+ "<key>CFBundleExecutable</key>\n"
+ "<string>$name</string>\n"
+ "<key>DTPlatformName</key>\n"
+ "<string>iphoneos</string>\n"
+ "<key>CFBundleInfoDictionaryVersion</key>\n"
+ "<string>6.0</string>\n"
+ "<key>CFBundleVersion</key>\n"
+ "<string>1</string>\n"
+ "<key>CFBundlePackageType</key>\n"
+ "<string>FMWK</string>\n"
+ "<key>MinimumOSVersion</key>\n"
+ "<string>10.0</string>\n"
+ "</dict>\n"
+ "</plist>";
+
+ String info_plist = info_plist_format.replace("$name", file_name);
+
+ FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
+ if (f) {
+ f->store_string(info_plist);
+ f->close();
+ memdelete(f);
}
}
}
+
memdelete(filesystem_da);
return OK;
}
+Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
+ for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) {
+ String asset = p_assets[f_idx];
+ if (!asset.begins_with("res://")) {
+ // either SDK-builtin or already a part of the export template
+ IOSExportAsset exported_asset = { asset, p_is_framework, p_should_embed };
+ r_exported_assets.push_back(exported_asset);
+ } else {
+ Error err = _copy_asset(p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ }
+ }
+
+ return OK;
+}
+
Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets) {
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
@@ -1202,20 +1340,173 @@ Vector<String> EditorExportPlatformIOS::_get_preset_architectures(const Ref<Edit
return enabled_archs;
}
-void EditorExportPlatformIOS::add_module_code(const Ref<EditorExportPreset> &p_preset, EditorExportPlatformIOS::IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid) {
- if ((bool)p_preset->get("capabilities/" + p_name)) {
- //add module static library
- print_line("ADDING MODULE: " + p_name);
+Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset> &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector<IOSExportAsset> &r_exported_assets, bool p_debug) {
+ String plugin_definition_cpp_code;
+ String plugin_initialization_cpp_code;
+ String plugin_deinitialization_cpp_code;
- p_config_data.modules_buildfile += p_gid + " /* libgodot_" + p_name + "_module.a in Frameworks */ = {isa = PBXBuildFile; fileRef = " + p_fid + " /* libgodot_" + p_name + "_module.a */; };\n\t\t";
- p_config_data.modules_fileref += p_fid + " /* libgodot_" + p_name + "_module.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot_" + p_name + "_module ; path = \"libgodot_" + p_name + "_module.a\"; sourceTree = \"<group>\"; };\n\t\t";
- p_config_data.modules_buildphase += p_gid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t";
- p_config_data.modules_buildgrp += p_fid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t";
- } else {
- //add stub function for disabled module
- p_config_data.cpp_code += "void register_" + p_name + "_types() { /*stub*/ };\n";
- p_config_data.cpp_code += "void unregister_" + p_name + "_types() { /*stub*/ };\n";
+ Vector<String> plugin_linked_dependencies;
+ Vector<String> plugin_embedded_dependencies;
+ Vector<String> plugin_files;
+
+ Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
+
+ Vector<String> added_linked_dependenciy_names;
+ Vector<String> added_embedded_dependenciy_names;
+ HashMap<String, String> plist_values;
+
+ Error err;
+
+ for (int i = 0; i < enabled_plugins.size(); i++) {
+ PluginConfig plugin = enabled_plugins[i];
+
+ // Export plugin binary.
+ if (!plugin.supports_targets) {
+ err = _copy_asset(dest_dir, plugin.binary, nullptr, true, true, r_exported_assets);
+ } else {
+ String plugin_binary_dir = plugin.binary.get_base_dir();
+ String plugin_name_prefix = plugin.binary.get_basename().get_file();
+ String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + ".a";
+ String result_file_name = plugin.binary.get_file();
+
+ err = _copy_asset(dest_dir, plugin_binary_dir.plus_file(plugin_file), &result_file_name, true, true, r_exported_assets);
+ }
+
+ ERR_FAIL_COND_V(err, err);
+
+ // Adding dependencies.
+ // Use separate container for names to check for duplicates.
+ for (int j = 0; j < plugin.linked_dependencies.size(); j++) {
+ String dependency = plugin.linked_dependencies[j];
+ String name = dependency.get_file();
+
+ if (added_linked_dependenciy_names.has(name)) {
+ continue;
+ }
+
+ added_linked_dependenciy_names.push_back(name);
+ plugin_linked_dependencies.push_back(dependency);
+ }
+
+ for (int j = 0; j < plugin.system_dependencies.size(); j++) {
+ String dependency = plugin.system_dependencies[j];
+ String name = dependency.get_file();
+
+ if (added_linked_dependenciy_names.has(name)) {
+ continue;
+ }
+
+ added_linked_dependenciy_names.push_back(name);
+ plugin_linked_dependencies.push_back(dependency);
+ }
+
+ for (int j = 0; j < plugin.embedded_dependencies.size(); j++) {
+ String dependency = plugin.embedded_dependencies[j];
+ String name = dependency.get_file();
+
+ if (added_embedded_dependenciy_names.has(name)) {
+ continue;
+ }
+
+ added_embedded_dependenciy_names.push_back(name);
+ plugin_embedded_dependencies.push_back(dependency);
+ }
+
+ plugin_files.append_array(plugin.files_to_copy);
+
+ // Capabilities
+ // Also checking for duplicates.
+ for (int j = 0; j < plugin.capabilities.size(); j++) {
+ String capability = plugin.capabilities[j];
+
+ if (p_config_data.capabilities.has(capability)) {
+ continue;
+ }
+
+ p_config_data.capabilities.push_back(capability);
+ }
+
+ // Plist
+ // Using hash map container to remove duplicates
+ const String *K = nullptr;
+
+ while ((K = plugin.plist.next(K))) {
+ String key = *K;
+ String value = plugin.plist[key];
+
+ if (key.empty() || value.empty()) {
+ continue;
+ }
+
+ plist_values[key] = value;
+ }
+
+ // CPP Code
+ String definition_comment = "// Plugin: " + plugin.name + "\n";
+ String initialization_method = plugin.initialization_method + "();\n";
+ String deinitialization_method = plugin.deinitialization_method + "();\n";
+
+ plugin_definition_cpp_code += definition_comment +
+ "extern void " + initialization_method +
+ "extern void " + deinitialization_method + "\n";
+
+ plugin_initialization_cpp_code += "\t" + initialization_method;
+ plugin_deinitialization_cpp_code += "\t" + deinitialization_method;
+ }
+
+ // Updating `Info.plist`
+ {
+ const String *K = nullptr;
+ while ((K = plist_values.next(K))) {
+ String key = *K;
+ String value = plist_values[key];
+
+ if (key.empty() || value.empty()) {
+ continue;
+ }
+
+ p_config_data.plist_content += "<key>" + key + "</key><string>" + value + "</string>\n";
+ }
}
+
+ // Export files
+ {
+ // Export linked plugin dependency
+ err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+
+ // Export embedded plugin dependency
+ err = _export_additional_assets(dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+
+ // Export plugin files
+ err = _export_additional_assets(dest_dir, plugin_files, false, false, r_exported_assets);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ // Update CPP
+ {
+ Dictionary plugin_format;
+ plugin_format["definition"] = plugin_definition_cpp_code;
+ plugin_format["initialization"] = plugin_initialization_cpp_code;
+ plugin_format["deinitialization"] = plugin_deinitialization_cpp_code;
+
+ String plugin_cpp_code = "\n// Godot Plugins\n"
+ "void godot_ios_plugins_initialize();\n"
+ "void godot_ios_plugins_deinitialize();\n"
+ "// Exported Plugins\n\n"
+ "$definition"
+ "// Use Plugins\n"
+ "void godot_ios_plugins_initialize() {\n"
+ "$initialization"
+ "}\n\n"
+ "void godot_ios_plugins_deinitialize() {\n"
+ "$deinitialization"
+ "}\n";
+
+ p_config_data.cpp_code += plugin_cpp_code.format(plugin_format, "$_");
+ }
+ return OK;
}
Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
@@ -1324,9 +1615,12 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
"",
"",
"",
- ""
+ "",
+ Vector<String>()
};
+ Vector<IOSExportAsset> assets;
+
DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
@@ -1339,8 +1633,8 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_CANT_OPEN;
}
- add_module_code(p_preset, config_data, "arkit", "F9B95E6E2391205500AF0000", "F9C95E812391205C00BF0000");
- add_module_code(p_preset, config_data, "camera", "F9B95E6E2391205500AF0001", "F9C95E812391205C00BF0001");
+ err = _export_ios_plugins(p_preset, config_data, dest_dir + binary_name, assets, p_debug);
+ ERR_FAIL_COND_V(err, err);
//export rest of the files
int ret = unzGoToFirstFile(src_pkg_zip);
@@ -1382,21 +1676,8 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
is_execute = true;
#endif
file = "godot_ios.a";
- } else if (file.begins_with("libgodot_arkit")) {
- if ((bool)p_preset->get("capabilities/arkit") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) {
- file = "libgodot_arkit_module.a";
- } else {
- ret = unzGoToNextFile(src_pkg_zip);
- continue; //ignore!
- }
- } else if (file.begins_with("libgodot_camera")) {
- if ((bool)p_preset->get("capabilities/camera") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) {
- file = "libgodot_camera_module.a";
- } else {
- ret = unzGoToNextFile(src_pkg_zip);
- continue; //ignore!
- }
}
+
if (file == project_file) {
project_file_data = data;
}
@@ -1530,7 +1811,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
print_line("Exporting additional assets");
- Vector<IOSExportAsset> assets;
_export_additional_assets(dest_dir + binary_name, libraries, assets);
_add_assets_to_project(p_preset, project_file_data, assets);
String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
@@ -1665,9 +1945,17 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() {
Ref<Image> img = memnew(Image(_iphone_logo));
logo.instance();
logo->create_from_image(img);
+
+ plugins_changed = true;
+ quit_request = false;
+
+ check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
}
EditorExportPlatformIOS::~EditorExportPlatformIOS() {
+ quit_request = true;
+ Thread::wait_to_finish(check_for_changes_thread);
+ memdelete(check_for_changes_thread);
}
void register_iphone_exporter() {
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index c6f95869ee..04a0a478d5 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -35,9 +35,6 @@
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
-#include "game_center.h"
-#include "icloud.h"
-#include "in_app_store.h"
#include "ios.h"
#include "joypad_iphone.h"
#include "servers/audio_server.h"
@@ -48,6 +45,9 @@
#include "platform/iphone/vulkan_context_iphone.h"
#endif
+extern void godot_ios_plugins_initialize();
+extern void godot_ios_plugins_deinitialize();
+
class OSIPhone : public OS_Unix {
private:
static HashMap<String, void *> dynamic_symbol_lookup_table;
@@ -55,15 +55,6 @@ private:
AudioDriverCoreAudio audio_driver;
-#ifdef GAME_CENTER_ENABLED
- GameCenter *game_center;
-#endif
-#ifdef STOREKIT_ENABLED
- InAppStore *store_kit;
-#endif
-#ifdef ICLOUD_ENABLED
- ICloud *icloud;
-#endif
iOS *ios;
JoypadIPhone *joypad_iphone;
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 32e9dda92b..b87e6f37a0 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -125,21 +125,6 @@ void OSIPhone::initialize() {
}
void OSIPhone::initialize_modules() {
-#ifdef GAME_CENTER_ENABLED
- game_center = memnew(GameCenter);
- Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center));
-#endif
-
-#ifdef STOREKIT_ENABLED
- store_kit = memnew(InAppStore);
- Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit));
-#endif
-
-#ifdef ICLOUD_ENABLED
- icloud = memnew(ICloud);
- Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud));
-#endif
-
ios = memnew(iOS);
Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios));
@@ -155,26 +140,12 @@ void OSIPhone::deinitialize_modules() {
memdelete(ios);
}
-#ifdef GAME_CENTER_ENABLED
- if (game_center) {
- memdelete(game_center);
- }
-#endif
-
-#ifdef STOREKIT_ENABLED
- if (store_kit) {
- memdelete(store_kit);
- }
-#endif
-
-#ifdef ICLOUD_ENABLED
- if (icloud) {
- memdelete(icloud);
- }
-#endif
+ godot_ios_plugins_deinitialize();
}
void OSIPhone::set_main_loop(MainLoop *p_main_loop) {
+ godot_ios_plugins_initialize();
+
main_loop = p_main_loop;
if (main_loop) {
diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h
new file mode 100644
index 0000000000..5323f94989
--- /dev/null
+++ b/platform/iphone/plugin/godot_plugin_config.h
@@ -0,0 +1,265 @@
+/*************************************************************************/
+/* godot_plugin_config.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_PLUGIN_CONFIG_H
+#define GODOT_PLUGIN_CONFIG_H
+
+#include "core/error/error_list.h"
+#include "core/io/config_file.h"
+#include "core/string/ustring.h"
+
+static const char *PLUGIN_CONFIG_EXT = ".gdip";
+
+static const char *CONFIG_SECTION = "config";
+static const char *CONFIG_NAME_KEY = "name";
+static const char *CONFIG_BINARY_KEY = "binary";
+static const char *CONFIG_INITIALIZE_KEY = "initialization";
+static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization";
+
+static const char *DEPENDENCIES_SECTION = "dependencies";
+static const char *DEPENDENCIES_LINKED_KEY = "linked";
+static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded";
+static const char *DEPENDENCIES_SYSTEM_KEY = "system";
+static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities";
+static const char *DEPENDENCIES_FILES_KEY = "files";
+
+static const char *PLIST_SECTION = "plist";
+
+/*
+ The `config` section and fields are required and defined as follow:
+- **name**: name of the plugin
+- **binary**: path to static `.a` library
+
+The `dependencies` and fields are optional.
+- **linked**: dependencies that should only be linked.
+- **embedded**: dependencies that should be linked and embedded into application.
+- **system**: system dependencies that should be linked.
+- **capabilities**: capabilities that would be used for `UIRequiredDeviceCapabilities` options in Info.plist file.
+- **files**: files that would be copied into application
+
+The `plist` section are optional.
+- **key**: key and value that would be added in Info.plist file.
+ */
+
+struct PluginConfig {
+ // Set to true when the config file is properly loaded.
+ bool valid_config = false;
+ bool supports_targets = false;
+ // Unix timestamp of last change to this plugin.
+ uint64_t last_updated = 0;
+
+ // Required config section
+ String name;
+ String binary;
+ String initialization_method;
+ String deinitialization_method;
+
+ // Optional dependencies section
+ Vector<String> linked_dependencies;
+ Vector<String> embedded_dependencies;
+ Vector<String> system_dependencies;
+
+ Vector<String> files_to_copy;
+ Vector<String> capabilities;
+
+ // Optional plist section
+ // Supports only string types for now
+ HashMap<String, String> plist;
+};
+
+static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) {
+ String absolute_path;
+
+ if (dependency_path.empty()) {
+ return absolute_path;
+ }
+
+ if (dependency_path.is_abs_path()) {
+ return dependency_path;
+ }
+
+ String res_path = ProjectSettings::get_singleton()->globalize_path("res://");
+ absolute_path = plugin_config_dir.plus_file(dependency_path);
+
+ return absolute_path.replace(res_path, "res://");
+}
+
+static inline String resolve_system_dependency_path(String dependency_path) {
+ String absolute_path;
+
+ if (dependency_path.empty()) {
+ return absolute_path;
+ }
+
+ if (dependency_path.is_abs_path()) {
+ return dependency_path;
+ }
+
+ String system_path = "/System/Library/Frameworks";
+
+ return system_path.plus_file(dependency_path);
+}
+
+static inline Vector<String> resolve_local_dependencies(String plugin_config_dir, Vector<String> p_paths) {
+ Vector<String> paths;
+
+ for (int i = 0; i < p_paths.size(); i++) {
+ String path = resolve_local_dependency_path(plugin_config_dir, p_paths[i]);
+
+ if (path.empty()) {
+ continue;
+ }
+
+ paths.push_back(path);
+ }
+
+ return paths;
+}
+
+static inline Vector<String> resolve_system_dependencies(Vector<String> p_paths) {
+ Vector<String> paths;
+
+ for (int i = 0; i < p_paths.size(); i++) {
+ String path = resolve_system_dependency_path(p_paths[i]);
+
+ if (path.empty()) {
+ continue;
+ }
+
+ paths.push_back(path);
+ }
+
+ return paths;
+}
+
+static inline bool validate_plugin(PluginConfig &plugin_config) {
+ bool valid_name = !plugin_config.name.empty();
+ bool valid_binary_name = !plugin_config.binary.empty();
+ bool valid_initialize = !plugin_config.initialization_method.empty();
+ bool valid_deinitialize = !plugin_config.deinitialization_method.empty();
+
+ bool fields_value = valid_name && valid_binary_name && valid_initialize && valid_deinitialize;
+
+ if (fields_value && FileAccess::exists(plugin_config.binary)) {
+ plugin_config.valid_config = true;
+ plugin_config.supports_targets = false;
+ } else if (fields_value) {
+ String file_path = plugin_config.binary.get_base_dir();
+ String file_name = plugin_config.binary.get_basename().get_file();
+ String release_file_name = file_path.plus_file(file_name + ".release.a");
+ String debug_file_name = file_path.plus_file(file_name + ".debug.a");
+
+ if (FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) {
+ plugin_config.valid_config = true;
+ plugin_config.supports_targets = true;
+ }
+ }
+
+ return plugin_config.valid_config;
+}
+
+static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) {
+ uint64_t last_updated = FileAccess::get_modified_time(config_path);
+
+ if (!plugin_config.supports_targets) {
+ last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary));
+ } else {
+ String file_path = plugin_config.binary.get_base_dir();
+ String file_name = plugin_config.binary.get_basename().get_file();
+ String release_file_name = file_path.plus_file(file_name + ".release.a");
+ String debug_file_name = file_path.plus_file(file_name + ".debug.a");
+
+ last_updated = MAX(last_updated, FileAccess::get_modified_time(release_file_name));
+ last_updated = MAX(last_updated, FileAccess::get_modified_time(debug_file_name));
+ }
+
+ return last_updated;
+}
+
+static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
+ PluginConfig plugin_config = {};
+
+ if (!config_file.is_valid()) {
+ return plugin_config;
+ }
+
+ Error err = config_file->load(path);
+
+ if (err != OK) {
+ return plugin_config;
+ }
+
+ String config_base_dir = path.get_base_dir();
+
+ plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String());
+ plugin_config.initialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_INITIALIZE_KEY, String());
+ plugin_config.deinitialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_DEINITIALIZE_KEY, String());
+
+ String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String());
+ plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path);
+
+ if (config_file->has_section(DEPENDENCIES_SECTION)) {
+ Vector<String> linked_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LINKED_KEY, Vector<String>());
+ Vector<String> embedded_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_EMBEDDED_KEY, Vector<String>());
+ Vector<String> system_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_SYSTEM_KEY, Vector<String>());
+ Vector<String> files = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_FILES_KEY, Vector<String>());
+
+ plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies);
+ plugin_config.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies);
+ plugin_config.system_dependencies = resolve_system_dependencies(system_dependencies);
+
+ plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files);
+
+ plugin_config.capabilities = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CAPABILITIES_KEY, Vector<String>());
+ }
+
+ if (config_file->has_section(PLIST_SECTION)) {
+ List<String> keys;
+ config_file->get_section_keys(PLIST_SECTION, &keys);
+
+ for (int i = 0; i < keys.size(); i++) {
+ String value = config_file->get_value(PLIST_SECTION, keys[i], String());
+
+ if (value.empty()) {
+ continue;
+ }
+
+ plugin_config.plist[keys[i]] = value;
+ }
+ }
+
+ if (validate_plugin(plugin_config)) {
+ plugin_config.last_updated = get_plugin_modification_time(plugin_config, path);
+ }
+
+ return plugin_config;
+}
+
+#endif // GODOT_PLUGIN_CONFIG_H
diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h
index b0b31ae377..2cc4e4c388 100644
--- a/platform/iphone/view_controller.h
+++ b/platform/iphone/view_controller.h
@@ -28,13 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#import <GameKit/GameKit.h>
#import <UIKit/UIKit.h>
@class GodotView;
@class GodotNativeVideoView;
-@interface ViewController : UIViewController <GKGameCenterControllerDelegate>
+@interface ViewController : UIViewController
@property(nonatomic, readonly, strong) GodotView *godotView;
@property(nonatomic, readonly, strong) GodotNativeVideoView *videoView;
diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm
index e11eff423b..5d18a72be1 100644
--- a/platform/iphone/view_controller.mm
+++ b/platform/iphone/view_controller.mm
@@ -36,6 +36,7 @@
#import "native_video_view.h"
#include "os_iphone.h"
+#import <AVFoundation/AVFoundation.h>
#import <GameController/GameController.h>
@interface ViewController ()
@@ -214,14 +215,4 @@
}
}
-// MARK: Delegates
-
-#ifdef GAME_CENTER_ENABLED
-- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController {
- //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone
- GameCenter::get_singleton()->game_center_closed();
- [gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
-}
-#endif
-
@end
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 01ed7b8d6a..5d9e68f2b4 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -2567,6 +2567,4 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
storage->free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
-
- RD::get_singleton()->free(state.default_transforms_uniform_set);
}
diff --git a/thirdparty/jpeg-compressor/jpgd.cpp b/thirdparty/jpeg-compressor/jpgd.cpp
index baf6ea0484..d6b5d96aac 100644
--- a/thirdparty/jpeg-compressor/jpgd.cpp
+++ b/thirdparty/jpeg-compressor/jpgd.cpp
@@ -1669,7 +1669,7 @@ namespace jpgd {
int row = m_max_mcu_y_size - m_mcu_lines_left;
uint8* d0 = m_pScan_line_0;
- const int half_image_x_size = (m_image_x_size >> 1) - 1;
+ const int half_image_x_size = (m_image_x_size == 1) ? 0 : (m_image_x_size >> 1) - 1;
const int row_x8 = row * 8;
for (int x = 0; x < m_image_x_size; x++)
@@ -1762,7 +1762,7 @@ namespace jpgd {
int y = m_image_y_size - m_total_lines_left;
int row = y & 15;
- const int half_image_y_size = (m_image_y_size >> 1) - 1;
+ const int half_image_y_size = (m_image_y_size == 1) ? 0 : (m_image_y_size >> 1) - 1;
uint8* d0 = m_pScan_line_0;
@@ -1891,7 +1891,7 @@ namespace jpgd {
int y = m_image_y_size - m_total_lines_left;
int row = y & 15;
- const int half_image_y_size = (m_image_y_size >> 1) - 1;
+ const int half_image_y_size = (m_image_y_size == 1) ? 0 : (m_image_y_size >> 1) - 1;
uint8* d0 = m_pScan_line_0;
@@ -1915,7 +1915,7 @@ namespace jpgd {
const int y0_base = (c_y0 & 7) * 8 + 256;
const int y1_base = (c_y1 & 7) * 8 + 256;
- const int half_image_x_size = (m_image_x_size >> 1) - 1;
+ const int half_image_x_size = (m_image_x_size == 1) ? 0 : (m_image_x_size >> 1) - 1;
static const uint8_t s_muls[2][2][4] =
{