summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/enet/SCsub2
-rw-r--r--modules/etc/config.py4
-rw-r--r--modules/freetype/SCsub4
-rw-r--r--modules/gdnative/SCsub2
-rw-r--r--modules/gdnative/gdnative.cpp7
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h5
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h4
-rw-r--r--modules/gdnative/nativescript/SCsub3
-rw-r--r--modules/gdscript/gd_editor.cpp3
-rw-r--r--modules/gdscript/gd_function.cpp305
-rw-r--r--modules/mobile_vr/SCsub13
-rw-r--r--modules/mobile_vr/config.py6
-rw-r--r--modules/mobile_vr/mobile_interface.cpp511
-rw-r--r--modules/mobile_vr/mobile_interface.h155
-rw-r--r--modules/mobile_vr/register_types.cpp43
-rw-r--r--modules/mobile_vr/register_types.h31
-rw-r--r--modules/mobile_vr/shaders/SCsub7
-rw-r--r--modules/mobile_vr/shaders/lens_distorted.glsl59
-rw-r--r--modules/ogg/SCsub2
-rw-r--r--modules/openssl/SCsub2
-rw-r--r--modules/opus/SCsub4
-rw-r--r--modules/recast/SCsub6
-rw-r--r--modules/regex/SCsub2
-rw-r--r--modules/squish/SCsub2
-rw-r--r--modules/squish/config.py4
-rw-r--r--modules/svg/image_loader_svg.cpp2
-rw-r--r--modules/theora/SCsub6
-rw-r--r--modules/tinyexr/config.py4
-rw-r--r--modules/visual_script/visual_script.cpp4
-rw-r--r--modules/visual_script/visual_script_editor.cpp3
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp14
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp8
-rw-r--r--modules/visual_script/visual_script_yield_nodes.h2
-rw-r--r--modules/vorbis/SCsub4
-rw-r--r--modules/webm/SCsub8
-rw-r--r--modules/webm/libvpx/SCsub2
-rw-r--r--modules/webp/SCsub2
37 files changed, 1081 insertions, 164 deletions
diff --git a/modules/enet/SCsub b/modules/enet/SCsub
index 42a933a66d..4790c5099f 100644
--- a/modules/enet/SCsub
+++ b/modules/enet/SCsub
@@ -7,7 +7,7 @@ Import('env_modules')
env_enet = env_modules.Clone()
-if (env['builtin_enet'] != 'no'):
+if env['builtin_enet']:
thirdparty_dir = "#thirdparty/enet/"
thirdparty_sources = [
"godot.cpp",
diff --git a/modules/etc/config.py b/modules/etc/config.py
index 4b0b01b78e..7dc2cb59c1 100644
--- a/modules/etc/config.py
+++ b/modules/etc/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_etc_enabled"] = "no"
+ if not env['tools']:
+ env['module_etc_enabled'] = False
env.disabled_modules.append("etc")
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index f22df4407c..19e384af73 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -6,7 +6,7 @@ from compat import isbasestring
# Not building in a separate env as scene needs it
# Thirdparty source files
-if (env['builtin_freetype'] != 'no'):
+if env['builtin_freetype']:
thirdparty_dir = "#thirdparty/freetype/"
thirdparty_sources = [
"src/autofit/autofit.c",
@@ -65,7 +65,7 @@ if (env['builtin_freetype'] != 'no'):
env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
# also requires libpng headers
- if (env['builtin_libpng'] != 'no'):
+ if env['builtin_libpng']:
env.Append(CPPPATH=["#thirdparty/libpng"])
lib = env.Library("freetype_builtin", thirdparty_sources)
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index f386f2b542..39f5ec5378 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -11,7 +11,7 @@ gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
gdn_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
-if "platform" in env and env["platform"] == "x11": # there has to be a better solution?
+if "platform" in env and env["platform"] in ["x11", "iphone"]:
env.Append(LINKFLAGS=["-rdynamic"])
env.use_ptrcall = True
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 93a9bac11c..f0c09a3370 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -110,6 +110,7 @@ GDNativeLibrary::~GDNativeLibrary() {
void GDNativeLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path);
ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);
+ ClassDB::bind_method(D_METHOD("get_active_library_path"), &GDNativeLibrary::get_active_library_path);
ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative);
ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative);
@@ -234,8 +235,11 @@ bool GDNative::initialize() {
ERR_PRINT("No library set for this platform");
return false;
}
-
+#ifdef IPHONE_ENABLED
+ String path = lib_path.replace("res://", "dylibs/");
+#else
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
+#endif
Error err = OS::get_singleton()->open_dynamic_library(path, native_handle);
if (err != OK) {
return false;
@@ -265,6 +269,7 @@ bool GDNative::initialize() {
options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE);
options.gd_native_library = (godot_object *)(get_library().ptr());
+ options.active_library_path = (godot_string *)&path;
library_init_fpointer(&options);
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 18d51daeb3..9134f1c581 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -49,8 +49,8 @@ extern "C" {
#elif defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
-#define GDCALLINGCONV
-#define GDAPI
+#define GDCALLINGCONV __attribute__((visibility("default")))
+#define GDAPI GDCALLINGCONV
#elif TARGET_OS_MAC
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDAPI GDCALLINGCONV
@@ -243,6 +243,7 @@ typedef struct {
uint64_t no_api_hash;
godot_object *gd_native_library; // pointer to GDNativeLibrary that is being initialized
const struct godot_gdnative_api_struct *api_struct;
+ const godot_string *active_library_path;
} godot_gdnative_init_options;
typedef struct {
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 96f213ead7..5095b7a83e 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -51,8 +51,8 @@ extern "C" {
#elif defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
-#define GDCALLINGCONV
-#define GDAPI
+#define GDCALLINGCONV __attribute__((visibility("default")))
+#define GDAPI GDCALLINGCONV
#elif TARGET_OS_MAC
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDAPI GDCALLINGCONV
diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub
index e980e40e8e..178afec64a 100644
--- a/modules/gdnative/nativescript/SCsub
+++ b/modules/gdnative/nativescript/SCsub
@@ -7,4 +7,7 @@ mod_env.add_source_files(env.modules_sources, "*.cpp")
mod_env.Append(CPPPATH='#modules/gdnative')
mod_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
+if "platform" in env and env["platform"] in ["x11", "iphone"]:
+ env.Append(LINKFLAGS=["-rdynamic"])
+
Export('mod_env')
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index aa39ad92c4..b0408917a4 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -1952,7 +1952,6 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
//make sure identifier exists...
const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1]);
-
if (op->arguments[0]->type == GDParser::Node::TYPE_SELF) {
//self, look up
@@ -2021,7 +2020,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
base = script->get_native();
} else if (nc.is_valid()) {
- if (context.function && !context.function->_static) {
+ if (!(context.function && context.function->_static)) {
GDCompletionIdentifier ci;
ci.type = Variant::OBJECT;
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index 70340f0823..9df2823c35 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -41,11 +41,12 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) {
case ADDR_TYPE_SELF: {
-
+#ifdef DEBUG_ENABLED
if (unlikely(!p_instance)) {
r_error = "Cannot access self without instance.";
return NULL;
}
+#endif
return &self;
} break;
case ADDR_TYPE_CLASS: {
@@ -53,18 +54,22 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
return &p_script->_static_ref;
} break;
case ADDR_TYPE_MEMBER: {
- //member indexing is O(1)
+#ifdef DEBUG_ENABLED
if (unlikely(!p_instance)) {
r_error = "Cannot access member without instance.";
return NULL;
}
+#endif
+ //member indexing is O(1)
return &p_instance->members[address];
} break;
case ADDR_TYPE_CLASS_CONSTANT: {
//todo change to index!
GDScript *o = p_script;
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _global_names_count, NULL);
+#endif
const StringName *sn = &_global_names_ptr[address];
while (o) {
@@ -84,18 +89,22 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
ERR_FAIL_V(NULL);
} break;
case ADDR_TYPE_LOCAL_CONSTANT: {
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _constant_count, NULL);
+#endif
return &_constants_ptr[address];
} break;
case ADDR_TYPE_STACK:
case ADDR_TYPE_STACK_VARIABLE: {
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _stack_size, NULL);
+#endif
return &p_stack[address];
} break;
case ADDR_TYPE_GLOBAL: {
-
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), NULL);
-
+#endif
return &GDScriptLanguage::get_singleton()->get_global_array()[address];
} break;
case ADDR_TYPE_NIL: {
@@ -161,8 +170,71 @@ static String _get_var_type(const Variant *p_type) {
return basestr;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#define OPCODES_TABLE \
+ static const void *switch_table_ops[] = { \
+ &&OPCODE_OPERATOR, \
+ &&OPCODE_EXTENDS_TEST, \
+ &&OPCODE_SET, \
+ &&OPCODE_GET, \
+ &&OPCODE_SET_NAMED, \
+ &&OPCODE_GET_NAMED, \
+ &&OPCODE_SET_MEMBER, \
+ &&OPCODE_GET_MEMBER, \
+ &&OPCODE_ASSIGN, \
+ &&OPCODE_ASSIGN_TRUE, \
+ &&OPCODE_ASSIGN_FALSE, \
+ &&OPCODE_CONSTRUCT, \
+ &&OPCODE_CONSTRUCT_ARRAY, \
+ &&OPCODE_CONSTRUCT_DICTIONARY, \
+ &&OPCODE_CALL, \
+ &&OPCODE_CALL_RETURN, \
+ &&OPCODE_CALL_BUILT_IN, \
+ &&OPCODE_CALL_SELF, \
+ &&OPCODE_CALL_SELF_BASE, \
+ &&OPCODE_YIELD, \
+ &&OPCODE_YIELD_SIGNAL, \
+ &&OPCODE_YIELD_RESUME, \
+ &&OPCODE_JUMP, \
+ &&OPCODE_JUMP_IF, \
+ &&OPCODE_JUMP_IF_NOT, \
+ &&OPCODE_JUMP_TO_DEF_ARGUMENT, \
+ &&OPCODE_RETURN, \
+ &&OPCODE_ITERATE_BEGIN, \
+ &&OPCODE_ITERATE, \
+ &&OPCODE_ASSERT, \
+ &&OPCODE_BREAKPOINT, \
+ &&OPCODE_LINE, \
+ &&OPCODE_END \
+ };
+
+#define OPCODE(m_op) \
+ m_op:
+#define OPCODE_WHILE(m_test)
+#define OPCODES_END \
+ OPSEXIT:
+#define OPCODES_OUT \
+ OPSOUT:
+#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]]
+#define OPCODE_SWITCH(m_test) DISPATCH_OPCODE;
+#define OPCODE_BREAK goto OPSEXIT
+#define OPCODE_OUT goto OPSOUT
+#else
+#define OPCODES_TABLE
+#define OPCODE(m_op) case m_op:
+#define OPCODE_WHILE(m_test) while (m_test)
+#define OPCODES_END
+#define OPCODES_OUT
+#define DISPATCH_OPCODE continue
+#define OPCODE_SWITCH(m_test) switch (m_test)
+#define OPCODE_BREAK break
+#define OPCODE_OUT break
+#endif
+
Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) {
+ OPCODES_TABLE;
+
if (!_code_ptr) {
return Variant();
@@ -271,16 +343,23 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (ScriptDebugger::get_singleton())
GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line);
-#define GD_ERR_BREAK(m_cond) ERR_BREAK(m_cond)
+#define GD_ERR_BREAK(m_cond) \
+ { \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
+ OPCODE_BREAK; \
+ } else \
+ _err_error_exists = false; \
+ }
#define CHECK_SPACE(m_space) \
- ERR_BREAK((ip + m_space) > _code_size)
+ GD_ERR_BREAK((ip + m_space) > _code_size)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
if (unlikely(!m_v)) \
- break;
+ OPCODE_BREAK;
#else
#define GD_ERR_BREAK(m_cond)
@@ -306,15 +385,15 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
bool exit_ok = false;
#ifdef DEBUG_ENABLED
- while (ip < _code_size) {
+ OPCODE_WHILE(ip < _code_size) {
int last_opcode = _code_ptr[ip];
#else
- while (true) {
+ OPCODE_WHILE(true) {
#endif
- switch (_code_ptr[ip]) {
+ OPCODE_SWITCH(_code_ptr[ip]) {
- case OPCODE_OPERATOR: {
+ OPCODE(OPCODE_OPERATOR) {
CHECK_SPACE(5);
@@ -343,14 +422,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
}
- break;
+ OPCODE_BREAK;
}
*dst = ret;
#endif
ip += 5;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_EXTENDS_TEST: {
+ OPCODE(OPCODE_EXTENDS_TEST) {
CHECK_SPACE(4);
@@ -362,12 +441,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
err_text = "Left operand of 'is' is not an instance of anything.";
- break;
+ OPCODE_BREAK;
}
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
err_text = "Right operand of 'is' is not a class.";
- break;
+ OPCODE_BREAK;
}
#endif
Object *obj_A = *a;
@@ -405,7 +484,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!nc) {
err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
- break;
+ OPCODE_BREAK;
}
#endif
extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
@@ -413,9 +492,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = extends_ok;
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET: {
+ OPCODE(OPCODE_SET) {
CHECK_SPACE(3);
@@ -435,13 +514,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
v = "of type '" + _get_var_type(index) + "'";
}
err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "').";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET: {
+ OPCODE(OPCODE_GET) {
CHECK_SPACE(3);
@@ -466,14 +545,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
v = "of type '" + _get_var_type(index) + "'";
}
err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
- break;
+ OPCODE_BREAK;
}
*dst = ret;
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET_NAMED: {
+ OPCODE(OPCODE_SET_NAMED) {
CHECK_SPACE(3);
@@ -492,13 +571,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!valid) {
String err_type;
err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "').";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET_NAMED: {
+ OPCODE(OPCODE_GET_NAMED) {
CHECK_SPACE(4);
@@ -525,14 +604,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
}
- break;
+ OPCODE_BREAK;
}
*dst = ret;
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET_MEMBER: {
+ OPCODE(OPCODE_SET_MEMBER) {
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
@@ -545,16 +624,16 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!ok) {
err_text = "Internal error setting property: " + String(*index);
- break;
+ OPCODE_BREAK;
} else if (!valid) {
err_text = "Error setting property '" + String(*index) + "' with value of type " + Variant::get_type_name(src->get_type()) + ".";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET_MEMBER: {
+ OPCODE(OPCODE_GET_MEMBER) {
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
@@ -566,13 +645,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!ok) {
err_text = "Internal error getting property: " + String(*index);
- break;
+ OPCODE_BREAK;
}
#endif
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN: {
+ OPCODE(OPCODE_ASSIGN) {
CHECK_SPACE(3);
GET_VARIANT_PTR(dst, 1);
@@ -581,9 +660,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = *src;
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN_TRUE: {
+ OPCODE(OPCODE_ASSIGN_TRUE) {
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -591,9 +670,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = true;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN_FALSE: {
+ OPCODE(OPCODE_ASSIGN_FALSE) {
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -601,9 +680,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = false;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT: {
+ OPCODE(OPCODE_CONSTRUCT) {
CHECK_SPACE(2);
Variant::Type t = Variant::Type(_code_ptr[ip + 1]);
@@ -623,15 +702,15 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (err.error != Variant::CallError::CALL_OK) {
err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
#endif
ip += 4 + argc;
//construct a basic type
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT_ARRAY: {
+ OPCODE(OPCODE_CONSTRUCT_ARRAY) {
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
@@ -649,9 +728,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = array;
ip += 3 + argc;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT_DICTIONARY: {
+ OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
@@ -671,10 +750,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = dict;
ip += 3 + argc * 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_RETURN:
- case OPCODE_CALL: {
+ OPCODE(OPCODE_CALL_RETURN)
+ OPCODE(OPCODE_CALL) {
CHECK_SPACE(4);
bool call_ret = _code_ptr[ip] == OPCODE_CALL_RETURN;
@@ -736,24 +815,24 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (base->is_ref()) {
err_text = "Attempted to free a reference.";
- break;
+ OPCODE_BREAK;
} else if (base->get_type() == Variant::OBJECT) {
err_text = "Attempted to free a locked object (calling or emitting).";
- break;
+ OPCODE_BREAK;
}
}
}
err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
#endif
//_call_func(NULL,base,*methodname,ip,argc,p_instance,stack);
ip += argc + 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_BUILT_IN: {
+ OPCODE(OPCODE_CALL_BUILT_IN) {
CHECK_SPACE(4);
@@ -786,17 +865,17 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
err_text = _get_call_error(err, "built-in function '" + methodstr + "'", (const Variant **)argptrs);
}
- break;
+ OPCODE_BREAK;
}
#endif
ip += argc + 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_SELF: {
+ OPCODE(OPCODE_CALL_SELF) {
- break;
+ OPCODE_BREAK;
}
- case OPCODE_CALL_SELF_BASE: {
+ OPCODE(OPCODE_CALL_SELF_BASE) {
CHECK_SPACE(2);
int self_fun = _code_ptr[ip + 1];
@@ -805,7 +884,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (self_fun < 0 || self_fun >= _global_names_count) {
err_text = "compiler bug, function name not found";
- break;
+ OPCODE_BREAK;
}
#endif
const StringName *methodname = &_global_names_ptr[self_fun];
@@ -865,14 +944,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
String methodstr = *methodname;
err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
ip += 4 + argc;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_YIELD:
- case OPCODE_YIELD_SIGNAL: {
+ OPCODE(OPCODE_YIELD)
+ OPCODE(OPCODE_YIELD_SIGNAL) {
int ipofs = 1;
if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) {
@@ -913,11 +992,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (argobj->get_type() != Variant::OBJECT) {
err_text = "First argument of yield() not of type object.";
- break;
+ OPCODE_BREAK;
}
if (argname->get_type() != Variant::STRING) {
err_text = "Second argument of yield() not a string (for signal name).";
- break;
+ OPCODE_BREAK;
}
#endif
Object *obj = argobj->operator Object *();
@@ -926,18 +1005,18 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!obj) {
err_text = "First argument of yield() is null.";
- break;
+ OPCODE_BREAK;
}
if (ScriptDebugger::get_singleton()) {
if (!ObjectDB::instance_validate(obj)) {
err_text = "First argument of yield() is a previously freed instance.";
- break;
+ OPCODE_BREAK;
}
}
if (signal.length() == 0) {
err_text = "Second argument of yield() is an empty string (for signal name).";
- break;
+ OPCODE_BREAK;
}
#endif
@@ -945,38 +1024,38 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (err != OK) {
err_text = "Error connecting to signal: " + signal + " during yield().";
- break;
+ OPCODE_BREAK;
}
#endif
}
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
- case OPCODE_YIELD_RESUME: {
+ OPCODE(OPCODE_YIELD_RESUME) {
CHECK_SPACE(2);
#ifdef DEBUG_ENABLED
if (!p_state) {
err_text = ("Invalid Resume (bug?)");
- break;
+ OPCODE_BREAK;
}
#endif
GET_VARIANT_PTR(result, 1);
*result = p_state->result;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP: {
+ OPCODE(OPCODE_JUMP) {
CHECK_SPACE(2);
int to = _code_ptr[ip + 1];
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_IF: {
+ OPCODE(OPCODE_JUMP_IF) {
CHECK_SPACE(3);
@@ -988,12 +1067,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int to = _code_ptr[ip + 2];
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_IF_NOT: {
+ OPCODE(OPCODE_JUMP_IF_NOT) {
CHECK_SPACE(3);
@@ -1005,26 +1084,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int to = _code_ptr[ip + 2];
GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_TO_DEF_ARGUMENT: {
+ OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
CHECK_SPACE(2);
ip = _default_arg_ptr[defarg];
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_RETURN: {
+ OPCODE(OPCODE_RETURN) {
CHECK_SPACE(2);
GET_VARIANT_PTR(r, 1);
retvalue = *r;
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
- case OPCODE_ITERATE_BEGIN: {
+ OPCODE(OPCODE_ITERATE_BEGIN) {
CHECK_SPACE(8); //space for this a regular iterate
@@ -1036,13 +1115,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "'.";
- break;
+ OPCODE_BREAK;
}
#endif
int jumpto = _code_ptr[ip + 3];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- continue;
+ DISPATCH_OPCODE;
}
GET_VARIANT_PTR(iterator, 4);
@@ -1050,13 +1129,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'.";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 5; //skip regular iterate which is always next
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ITERATE: {
+ OPCODE(OPCODE_ITERATE) {
CHECK_SPACE(4);
@@ -1068,13 +1147,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?).";
- break;
+ OPCODE_BREAK;
}
#endif
int jumpto = _code_ptr[ip + 3];
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- continue;
+ DISPATCH_OPCODE;
}
GET_VARIANT_PTR(iterator, 4);
@@ -1082,13 +1161,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 5; //loop again
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSERT: {
+ OPCODE(OPCODE_ASSERT) {
CHECK_SPACE(2);
GET_VARIANT_PTR(test, 1);
@@ -1098,23 +1177,23 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!result) {
err_text = "Assertion failed.";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_BREAKPOINT: {
+ OPCODE(OPCODE_BREAKPOINT) {
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton()) {
GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement", true);
}
#endif
ip += 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_LINE: {
+ OPCODE(OPCODE_LINE) {
CHECK_SPACE(2);
line = _code_ptr[ip + 1];
@@ -1141,23 +1220,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
ScriptDebugger::get_singleton()->line_poll();
}
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_END: {
+ OPCODE(OPCODE_END) {
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
+#if 0
default: {
err_text = "Illegal opcode " + itos(_code_ptr[ip]) + " at address " + itos(ip);
- break;
+ OPCODE_BREAK;
}
+#endif
}
+ OPCODES_END
#ifdef DEBUG_ENABLED
if (exit_ok)
- break;
+ OPCODE_OUT;
//error
// function, file, line, error, explanation
String err_file;
@@ -1182,9 +1264,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
}
#endif
- break;
+ OPCODE_OUT;
}
+ OPCODES_OUT
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->profiling) {
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time;
diff --git a/modules/mobile_vr/SCsub b/modules/mobile_vr/SCsub
new file mode 100644
index 0000000000..b4e2edcca1
--- /dev/null
+++ b/modules/mobile_vr/SCsub
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+import os
+import methods
+
+Import('env')
+Import('env_modules')
+
+env_mobile_vr = env_modules.Clone()
+
+env_mobile_vr.add_source_files(env.modules_sources, '*.cpp')
+
+SConscript("shaders/SCsub")
diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py
new file mode 100644
index 0000000000..d0156b1b77
--- /dev/null
+++ b/modules/mobile_vr/config.py
@@ -0,0 +1,6 @@
+def can_build(platform):
+ # should probably change this to only be true on iOS and Android
+ return True
+
+def configure(env):
+ pass \ No newline at end of file
diff --git a/modules/mobile_vr/mobile_interface.cpp b/modules/mobile_vr/mobile_interface.cpp
new file mode 100644
index 0000000000..f5c9bccaba
--- /dev/null
+++ b/modules/mobile_vr/mobile_interface.cpp
@@ -0,0 +1,511 @@
+/*************************************************************************/
+/* mobile_interface.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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 "mobile_interface.h"
+#include "core/os/input.h"
+#include "core/os/os.h"
+#include "servers/visual/visual_server_global.h"
+
+StringName MobileVRInterface::get_name() const {
+ return "Native mobile";
+};
+
+Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) {
+ // Our magnetometer doesn't give us nice clean data.
+ // Well it may on Mac OS X because we're getting a calibrated value in the current implementation but Android we're getting raw data.
+ // This is a fairly simple adjustment we can do to correct for the magnetometer data being elliptical
+
+ Vector3 mag_raw = p_magnetometer;
+ Vector3 mag_scaled = p_magnetometer;
+
+ // update our variables every x frames
+ if (mag_count > 20) {
+ mag_current_min = mag_next_min;
+ mag_current_max = mag_next_max;
+ mag_count = 0;
+ } else {
+ mag_count++;
+ };
+
+ // adjust our min and max
+ if (mag_raw.x > mag_next_max.x) mag_next_max.x = mag_raw.x;
+ if (mag_raw.y > mag_next_max.y) mag_next_max.y = mag_raw.y;
+ if (mag_raw.z > mag_next_max.z) mag_next_max.z = mag_raw.z;
+
+ if (mag_raw.x < mag_next_min.x) mag_next_min.x = mag_raw.x;
+ if (mag_raw.y < mag_next_min.y) mag_next_min.y = mag_raw.y;
+ if (mag_raw.z < mag_next_min.z) mag_next_min.z = mag_raw.z;
+
+ // scale our x, y and z
+ if (!(mag_current_max.x - mag_current_min.x)) {
+ mag_raw.x -= (mag_current_min.x + mag_current_max.x) / 2.0;
+ mag_scaled.x = (mag_raw.x - mag_current_min.x) / ((mag_current_max.x - mag_current_min.x) * 2.0 - 1.0);
+ };
+
+ if (!(mag_current_max.y - mag_current_min.y)) {
+ mag_raw.y -= (mag_current_min.y + mag_current_max.y) / 2.0;
+ mag_scaled.y = (mag_raw.y - mag_current_min.y) / ((mag_current_max.y - mag_current_min.y) * 2.0 - 1.0);
+ };
+
+ if (!(mag_current_max.z - mag_current_min.z)) {
+ mag_raw.z -= (mag_current_min.z + mag_current_max.z) / 2.0;
+ mag_scaled.z = (mag_raw.z - mag_current_min.z) / ((mag_current_max.z - mag_current_min.z) * 2.0 - 1.0);
+ };
+
+ return mag_scaled;
+};
+
+Basis MobileVRInterface::combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto) {
+ // yup, stock standard cross product solution...
+ Vector3 up = -p_grav.normalized();
+
+ Vector3 magneto_east = up.cross(p_magneto.normalized()); // or is this west?, but should be horizon aligned now
+ magneto_east.normalize();
+
+ Vector3 magneto = up.cross(magneto_east); // and now we have a horizon aligned north
+ magneto.normalize();
+
+ // We use our gravity and magnetometer vectors to construct our matrix
+ Basis acc_mag_m3;
+ acc_mag_m3.elements[0] = -magneto_east;
+ acc_mag_m3.elements[1] = up;
+ acc_mag_m3.elements[2] = magneto;
+
+ return acc_mag_m3;
+};
+
+void MobileVRInterface::set_position_from_sensors() {
+ _THREAD_SAFE_METHOD_
+
+ // this is a helper function that attempts to adjust our transform using our 9dof sensors
+ // 9dof is a misleading marketing term coming from 3 accelerometer axis + 3 gyro axis + 3 magnetometer axis = 9 axis
+ // but in reality this only offers 3 dof (yaw, pitch, roll) orientation
+
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec();
+ uint64_t ticks_elapsed = ticks - last_ticks;
+ float delta_time = (double)ticks_elapsed / 1000000.0;
+
+ // few things we need
+ Input *input = Input::get_singleton();
+ Vector3 down(0.0, -1.0, 0.0); // Down is Y negative
+ Vector3 north(0.0, 0.0, 1.0); // North is Z positive
+
+ // make copies of our inputs
+ Vector3 acc = input->get_accelerometer();
+ Vector3 gyro = input->get_gyroscope();
+ Vector3 grav = input->get_gravity();
+ Vector3 magneto = scale_magneto(input->get_magnetometer()); // this may be overkill on iOS because we're already getting a calibrated magnetometer reading
+
+ if (sensor_first) {
+ sensor_first = false;
+ } else {
+ acc = scrub(acc, last_accerometer_data, 2, 0.2);
+ magneto = scrub(magneto, last_magnetometer_data, 3, 0.3);
+ };
+
+ last_accerometer_data = acc;
+ last_magnetometer_data = magneto;
+
+ if (grav.length() < 0.1) {
+ // not ideal but use our accelerometer, this will contain shakey shakey user behaviour
+ // maybe look into some math but I'm guessing that if this isn't available, its because we lack the gyro sensor to actually work out
+ // what a stable gravity vector is
+ grav = acc;
+ if (grav.length() > 0.1) {
+ has_gyro = true;
+ };
+ } else {
+ has_gyro = true;
+ };
+
+ bool has_magneto = magneto.length() > 0.1;
+ bool has_grav = grav.length() > 0.1;
+
+#ifdef ANDROID_ENABLED
+ ///@TODO needs testing, i don't have a gyro, potentially can be removed depending on what comes out of issue #8101
+ // On Android x and z axis seem inverted
+ gyro.x = -gyro.x;
+ gyro.z = -gyro.z;
+ grav.x = -grav.x;
+ grav.z = -grav.z;
+ magneto.x = -magneto.x;
+ magneto.z = -magneto.z;
+#endif
+
+ if (has_gyro) {
+ // start with applying our gyro (do NOT smooth our gyro!)
+ Basis rotate;
+ rotate.rotate(orientation.get_axis(0), gyro.x * delta_time);
+ rotate.rotate(orientation.get_axis(1), gyro.y * delta_time);
+ rotate.rotate(orientation.get_axis(2), gyro.z * delta_time);
+ orientation = rotate * orientation;
+ };
+
+ ///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part)
+ // if you have a gyro + accelerometer that combo tends to be better then combining all three but without a gyro you need the magnetometer..
+ if (has_magneto && has_grav && !has_gyro) {
+ // convert to quaternions, easier to smooth those out
+ Quat transform_quat(orientation);
+ Quat acc_mag_quat(combine_acc_mag(grav, magneto));
+ transform_quat = transform_quat.slerp(acc_mag_quat, 0.1);
+ orientation = Basis(transform_quat);
+ } else if (has_grav) {
+ // use gravity vector to make sure down is down...
+ // transform gravity into our world space
+ grav.normalize();
+ Vector3 grav_adj = orientation.xform(grav);
+ float dot = grav_adj.dot(down);
+ if ((dot > -1.0) && (dot < 1.0)) {
+ // axis around which we have this rotation
+ Vector3 axis = grav_adj.cross(down);
+ axis.normalize();
+
+ Basis drift_compensation(axis, acos(dot) * delta_time * 10);
+ orientation = drift_compensation * orientation;
+ };
+ };
+
+ // JIC
+ orientation.orthonormalize();
+
+ last_ticks = ticks;
+};
+
+void MobileVRInterface::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_iod", "iod"), &MobileVRInterface::set_iod);
+ ClassDB::bind_method(D_METHOD("get_iod"), &MobileVRInterface::get_iod);
+
+ ClassDB::bind_method(D_METHOD("set_display_width", "display_width"), &MobileVRInterface::set_display_width);
+ ClassDB::bind_method(D_METHOD("get_display_width"), &MobileVRInterface::get_display_width);
+
+ ClassDB::bind_method(D_METHOD("set_display_to_lens", "display_to_lens"), &MobileVRInterface::set_display_to_lens);
+ ClassDB::bind_method(D_METHOD("get_display_to_lens"), &MobileVRInterface::get_display_to_lens);
+
+ ClassDB::bind_method(D_METHOD("set_oversample", "oversample"), &MobileVRInterface::set_oversample);
+ ClassDB::bind_method(D_METHOD("get_oversample"), &MobileVRInterface::get_oversample);
+
+ ClassDB::bind_method(D_METHOD("set_k1", "k"), &MobileVRInterface::set_k1);
+ ClassDB::bind_method(D_METHOD("get_k1"), &MobileVRInterface::get_k1);
+
+ ClassDB::bind_method(D_METHOD("set_k2", "k"), &MobileVRInterface::set_k2);
+ ClassDB::bind_method(D_METHOD("get_k2"), &MobileVRInterface::get_k2);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "iod", PROPERTY_HINT_RANGE, "4.0,10.0,0.1"), "set_iod", "get_iod");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_width", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_width", "get_display_width");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_to_lens", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_to_lens", "get_display_to_lens");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "oversample", PROPERTY_HINT_RANGE, "1.0,2.0,0.1"), "set_oversample", "get_oversample");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "k1", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k1", "get_k1");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "k2", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k2", "get_k2");
+}
+
+void MobileVRInterface::set_iod(const real_t p_iod) {
+ intraocular_dist = p_iod;
+};
+
+real_t MobileVRInterface::get_iod() const {
+ return intraocular_dist;
+};
+
+void MobileVRInterface::set_display_width(const real_t p_display_width) {
+ display_width = p_display_width;
+};
+
+real_t MobileVRInterface::get_display_width() const {
+ return display_width;
+};
+
+void MobileVRInterface::set_display_to_lens(const real_t p_display_to_lens) {
+ display_to_lens = p_display_to_lens;
+};
+
+real_t MobileVRInterface::get_display_to_lens() const {
+ return display_to_lens;
+};
+
+void MobileVRInterface::set_oversample(const real_t p_oversample) {
+ oversample = p_oversample;
+};
+
+real_t MobileVRInterface::get_oversample() const {
+ return oversample;
+};
+
+void MobileVRInterface::set_k1(const real_t p_k1) {
+ k1 = p_k1;
+};
+
+real_t MobileVRInterface::get_k1() const {
+ return k1;
+};
+
+void MobileVRInterface::set_k2(const real_t p_k2) {
+ k2 = p_k2;
+};
+
+real_t MobileVRInterface::get_k2() const {
+ return k2;
+};
+
+bool MobileVRInterface::is_installed() {
+ // we don't have any middle ware here, if we have our interface, we can use it
+ return true;
+};
+
+bool MobileVRInterface::hmd_is_present() {
+ // our device is our HMD
+ return true;
+};
+
+bool MobileVRInterface::supports_hmd() {
+ // our device is our HMD
+ return true;
+};
+
+bool MobileVRInterface::is_stereo() {
+ // needs stereo...
+ return true;
+};
+
+bool MobileVRInterface::is_initialized() {
+ return (initialized);
+};
+
+bool MobileVRInterface::initialize() {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, false);
+
+ if (!initialized) {
+ // reset our sensor data and orientation
+ mag_count = 0;
+ has_gyro = false;
+ sensor_first = true;
+ mag_next_min = Vector3(10000, 10000, 10000);
+ mag_next_max = Vector3(-10000, -10000, -10000);
+ mag_current_min = Vector3(0, 0, 0);
+ mag_current_max = Vector3(0, 0, 0);
+
+ // reset our orientation
+ orientation = Basis();
+
+ // make this our primary interface
+ arvr_server->set_primary_interface(this);
+
+ last_ticks = OS::get_singleton()->get_ticks_usec();
+ ;
+ initialized = true;
+ };
+
+ return true;
+};
+
+void MobileVRInterface::uninitialize() {
+ if (initialized) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ if (arvr_server != NULL) {
+ // no longer our primary interface
+ arvr_server->clear_primary_interface_if(this);
+ }
+
+ initialized = false;
+ };
+};
+
+Size2 MobileVRInterface::get_recommended_render_targetsize() {
+ _THREAD_SAFE_METHOD_
+
+ // we use half our window size
+ Size2 target_size = OS::get_singleton()->get_window_size();
+ target_size.x *= 0.5 * oversample;
+ target_size.y *= oversample;
+
+ return target_size;
+};
+
+Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+ _THREAD_SAFE_METHOD_
+
+ Transform transform_for_eye;
+
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, transform_for_eye);
+
+ if (initialized) {
+ float world_scale = arvr_server->get_world_scale();
+
+ // we don't need to check for the existance of our HMD, doesn't effect our values...
+ // note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction...
+ if (p_eye == ARVRInterface::EYE_LEFT) {
+ transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale);
+ } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ transform_for_eye.origin.x = intraocular_dist * 0.01 * 0.5 * world_scale;
+ } else {
+ // for mono we don't reposition, we want our center position.
+ };
+
+ // just scale our origin point of our transform
+ Transform hmd_transform;
+ hmd_transform.basis = orientation;
+ hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0);
+
+ transform_for_eye = p_cam_transform * (arvr_server->get_reference_frame()) * hmd_transform * transform_for_eye;
+ } else {
+ // huh? well just return what we got....
+ transform_for_eye = p_cam_transform;
+ };
+
+ return transform_for_eye;
+};
+
+CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+ _THREAD_SAFE_METHOD_
+
+ CameraMatrix eye;
+
+ if (p_eye == ARVRInterface::EYE_MONO) {
+ ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties
+ // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example.
+ // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface
+ // to position a stock standard Godot camera and have control over this.
+ // This will make more sense when we implement ARkit on iOS (probably a separate interface).
+ eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false);
+ } else {
+ eye.set_for_hmd(p_eye == ARVRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
+ };
+
+ return eye;
+};
+
+void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+ _THREAD_SAFE_METHOD_
+
+ // We must have a valid render target
+ ERR_FAIL_COND(!p_render_target.is_valid());
+
+ // Because we are rendering to our device we must use our main viewport!
+ ERR_FAIL_COND(p_screen_rect == Rect2());
+
+ float offset_x = 0.0;
+ float aspect_ratio = 0.5 * p_screen_rect.size.x / p_screen_rect.size.y;
+ Vector2 eye_center;
+
+ if (p_eye == ARVRInterface::EYE_LEFT) {
+ offset_x = -1.0;
+ eye_center.x = ((-intraocular_dist / 2.0) + (display_width / 4.0)) / (display_width / 2.0);
+ } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ eye_center.x = ((intraocular_dist / 2.0) - (display_width / 4.0)) / (display_width / 2.0);
+ }
+
+ // unset our render target so we are outputting to our main screen by making RasterizerStorageGLES3::system_fbo our current FBO
+ VSG::rasterizer->set_current_render_target(RID());
+
+ // now output to screen
+ // VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0);
+
+ // get our render target
+ RID eye_texture = VSG::storage->render_target_get_texture(p_render_target);
+ uint32_t texid = VS::get_singleton()->texture_get_texid(eye_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ lens_shader.bind();
+ lens_shader.set_uniform(LensDistortedShaderGLES3::OFFSET_X, offset_x);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::K1, k1);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::K2, k2);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::EYE_CENTER, eye_center);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::UPSCALE, oversample);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::ASPECT_RATIO, aspect_ratio);
+
+ glBindVertexArray(half_screen_array);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindVertexArray(0);
+};
+
+void MobileVRInterface::process() {
+ _THREAD_SAFE_METHOD_
+
+ if (initialized) {
+ set_position_from_sensors();
+ };
+};
+
+MobileVRInterface::MobileVRInterface() {
+ initialized = false;
+
+ // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes
+ eye_height = 1.85;
+ intraocular_dist = 6.0;
+ display_width = 13.0;
+ display_to_lens = 4.0;
+ oversample = 1.5;
+ k1 = 0.22;
+ k2 = 0.23;
+ last_ticks = 0;
+
+ // create our shader stuff
+ lens_shader.init();
+
+ {
+ glGenBuffers(1, &half_screen_quad);
+ glBindBuffer(GL_ARRAY_BUFFER, half_screen_quad);
+ {
+ const float qv[16] = {
+ 0, -1,
+ -1, -1,
+ 0, 1,
+ -1, 1,
+ 1, 1,
+ 1, 1,
+ 1, -1,
+ 1, -1,
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+
+ glGenVertexArrays(1, &half_screen_array);
+ glBindVertexArray(half_screen_array);
+ glBindBuffer(GL_ARRAY_BUFFER, half_screen_quad);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, ((uint8_t *)NULL) + 8);
+ glEnableVertexAttribArray(4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ }
+};
+
+MobileVRInterface::~MobileVRInterface() {
+ // and make sure we cleanup if we haven't already
+ if (is_initialized()) {
+ uninitialize();
+ };
+};
diff --git a/modules/mobile_vr/mobile_interface.h b/modules/mobile_vr/mobile_interface.h
new file mode 100644
index 0000000000..dfe3cd200e
--- /dev/null
+++ b/modules/mobile_vr/mobile_interface.h
@@ -0,0 +1,155 @@
+/*************************************************************************/
+/* mobile_interface.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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 MOBILE_VR_INTERFACE_H
+#define MOBILE_VR_INTERFACE_H
+
+#include "servers/arvr/arvr_interface.h"
+#include "servers/arvr/arvr_positional_tracker.h"
+
+#include "shaders/lens_distorted.glsl.gen.h"
+
+/**
+ @author Bastiaan Olij <mux213@gmail.com>
+
+ The mobile interface is a native VR interface that can be used on Android and iOS phones.
+ It contains a basic implementation supporting 3DOF tracking if a gyroscope and accelerometer are
+ present and sets up the proper projection matrices based on the values provided.
+
+ We're planning to eventually do separate interfaces towards mobile SDKs that have far more capabilities and
+ do not rely on the user providing most of these settings (though enhancing this with auto detection features
+ based on the device we're running on would be cool). I'm mostly adding this as an example or base plate for
+ more advanced interfaces.
+*/
+
+class MobileVRInterface : public ARVRInterface {
+ GDCLASS(MobileVRInterface, ARVRInterface);
+
+private:
+ bool initialized;
+ Basis orientation;
+ float eye_height;
+ uint64_t last_ticks;
+
+ LensDistortedShaderGLES3 lens_shader;
+ GLuint half_screen_quad;
+ GLuint half_screen_array;
+
+ real_t intraocular_dist;
+ real_t display_width;
+ real_t display_to_lens;
+ real_t oversample;
+
+ //@TODO not yet used, these are needed in our distortion shader...
+ real_t k1;
+ real_t k2;
+
+ /*
+ logic for processing our sensor data, this was originally in our positional tracker logic but I think
+ that doesn't make sense in hindsight. It only makes marginally more sense to park it here for now,
+ this probably deserves an object of its own
+ */
+ Vector3 scale_magneto(const Vector3 &p_magnetometer);
+ Basis combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto);
+
+ int mag_count;
+ bool has_gyro;
+ bool sensor_first;
+ Vector3 last_accerometer_data;
+ Vector3 last_magnetometer_data;
+ Vector3 mag_current_min;
+ Vector3 mag_current_max;
+ Vector3 mag_next_min;
+ Vector3 mag_next_max;
+
+ ///@TODO a few support functions for trackers, most are math related and should likely be moved elsewhere
+ float floor_decimals(float p_value, float p_decimals) {
+ float power_of_10 = pow(10.0, p_decimals);
+ return floor(p_value * power_of_10) / power_of_10;
+ };
+
+ Vector3 floor_decimals(const Vector3 &p_vector, float p_decimals) {
+ return Vector3(floor_decimals(p_vector.x, p_decimals), floor_decimals(p_vector.y, p_decimals), floor_decimals(p_vector.z, p_decimals));
+ };
+
+ Vector3 low_pass(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_factor) {
+ return p_vector + (p_factor * (p_last_vector - p_vector));
+ };
+
+ Vector3 scrub(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_decimals, float p_factor) {
+ return low_pass(floor_decimals(p_vector, p_decimals), p_last_vector, p_factor);
+ };
+
+ void set_position_from_sensors();
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_iod(const real_t p_iod);
+ real_t get_iod() const;
+
+ void set_display_width(const real_t p_display_width);
+ real_t get_display_width() const;
+
+ void set_display_to_lens(const real_t p_display_to_lens);
+ real_t get_display_to_lens() const;
+
+ void set_oversample(const real_t p_oversample);
+ real_t get_oversample() const;
+
+ void set_k1(const real_t p_k1);
+ real_t get_k1() const;
+
+ void set_k2(const real_t p_k2);
+ real_t get_k2() const;
+
+ virtual StringName get_name() const;
+
+ virtual bool is_installed();
+ virtual bool hmd_is_present();
+ virtual bool supports_hmd();
+
+ virtual bool is_initialized();
+ virtual bool initialize();
+ virtual void uninitialize();
+
+ virtual Size2 get_recommended_render_targetsize();
+ virtual bool is_stereo();
+ virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
+ virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+
+ virtual void process();
+
+ MobileVRInterface();
+ ~MobileVRInterface();
+};
+
+#endif // MOBILE_VR_INTERFACE_H
diff --git a/modules/mobile_vr/register_types.cpp b/modules/mobile_vr/register_types.cpp
new file mode 100644
index 0000000000..f742ecbf00
--- /dev/null
+++ b/modules/mobile_vr/register_types.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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 "register_types.h"
+
+#include "mobile_interface.h"
+
+void register_mobile_vr_types() {
+ ClassDB::register_class<MobileVRInterface>();
+
+ Ref<MobileVRInterface> mobile_vr;
+ mobile_vr.instance();
+ ARVRServer::get_singleton()->add_interface(mobile_vr);
+}
+
+void unregister_mobile_vr_types() {
+}
diff --git a/modules/mobile_vr/register_types.h b/modules/mobile_vr/register_types.h
new file mode 100644
index 0000000000..a492fff397
--- /dev/null
+++ b/modules/mobile_vr/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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_mobile_vr_types();
+void unregister_mobile_vr_types();
diff --git a/modules/mobile_vr/shaders/SCsub b/modules/mobile_vr/shaders/SCsub
new file mode 100644
index 0000000000..cf53c9ebe0
--- /dev/null
+++ b/modules/mobile_vr/shaders/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import('env')
+
+if 'GLES3_GLSL' in env['BUILDERS']:
+ env.GLES3_GLSL('lens_distorted.glsl');
+
diff --git a/modules/mobile_vr/shaders/lens_distorted.glsl b/modules/mobile_vr/shaders/lens_distorted.glsl
new file mode 100644
index 0000000000..5a2975d737
--- /dev/null
+++ b/modules/mobile_vr/shaders/lens_distorted.glsl
@@ -0,0 +1,59 @@
+[vertex]
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+uniform float offset_x;
+
+out vec2 uv_interp;
+
+void main() {
+
+ uv_interp = uv_in;
+ gl_Position = vec4(vertex_attrib.x + offset_x, vertex_attrib.y, 0.0, 1.0);
+}
+
+[fragment]
+
+uniform sampler2D source; //texunit:0
+
+uniform vec2 eye_center;
+uniform float k1;
+uniform float k2;
+uniform float upscale;
+uniform float aspect_ratio;
+
+in vec2 uv_interp;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ vec2 coords = uv_interp;
+ vec2 offset = coords - eye_center;
+
+ // take aspect ratio into account
+ offset.y /= aspect_ratio;
+
+ // distort
+ vec2 offset_sq = offset * offset;
+ float radius_sq = offset_sq.x + offset_sq.y;
+ float radius_s4 = radius_sq * radius_sq;
+ float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4);
+ offset *= distortion_scale;
+
+ // reapply aspect ratio
+ offset.y *= aspect_ratio;
+
+ // add our eye center back in
+ coords = offset + eye_center;
+ coords /= upscale;
+
+ // and check our color
+ if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) {
+ frag_color = vec4(0.0, 0.0, 0.0, 1.0);
+ } else {
+ coords = (coords + vec2(1.0)) / vec2(2.0);
+ frag_color = textureLod(source, coords, 0.0);
+ }
+}
+
diff --git a/modules/ogg/SCsub b/modules/ogg/SCsub
index 5eabaf6f2b..5e559bd4db 100644
--- a/modules/ogg/SCsub
+++ b/modules/ogg/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_ogg = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libogg'] != 'no'):
+if env['builtin_libogg']:
thirdparty_dir = "#thirdparty/libogg/"
thirdparty_sources = [
"bitwise.c",
diff --git a/modules/openssl/SCsub b/modules/openssl/SCsub
index eb3c0e64d8..84c5e68439 100644
--- a/modules/openssl/SCsub
+++ b/modules/openssl/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_openssl = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_openssl'] != 'no'):
+if env['builtin_openssl']:
thirdparty_dir = "#thirdparty/openssl/"
thirdparty_sources = [
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index 4d3053c7ec..fee06bd267 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_opus = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_opus'] != 'no'):
+if env['builtin_opus']:
thirdparty_dir = "#thirdparty/opus/"
thirdparty_sources = [
@@ -209,7 +209,7 @@ if (env['builtin_opus'] != 'no'):
env_opus.Append(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths])
# also requires libogg
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_opus.Append(CPPPATH=["#thirdparty/libogg"])
# Module files
diff --git a/modules/recast/SCsub b/modules/recast/SCsub
index 349bd22efb..500c0ec055 100644
--- a/modules/recast/SCsub
+++ b/modules/recast/SCsub
@@ -5,7 +5,7 @@ Import('env')
# Not building in a separate env as core needs it
# Thirdparty source files
-if (env['builtin_recast'] != 'no'):
+if env['builtin_recast']:
thirdparty_dir = "#thirdparty/recastnavigation/Recast/"
thirdparty_sources = [
"Source/Recast.cpp",
@@ -24,10 +24,6 @@ if (env['builtin_recast'] != 'no'):
env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/Include"])
- # also requires recast headers
- if (env['builtin_recast'] != 'no'):
- env.Append(CPPPATH=["#thirdparty/recastnavigation/Recast"])
-
lib = env.Library("recast_builtin", thirdparty_sources)
env.Append(LIBS=[lib])
diff --git a/modules/regex/SCsub b/modules/regex/SCsub
index 2dfc2739e9..2bab144a28 100644
--- a/modules/regex/SCsub
+++ b/modules/regex/SCsub
@@ -7,7 +7,7 @@ env_regex = env_modules.Clone()
env_regex.Append(CPPFLAGS=["-DPCRE2_CODE_UNIT_WIDTH=0"])
env_regex.add_source_files(env.modules_sources, "*.cpp")
-if (env['builtin_pcre2'] != 'no'):
+if env['builtin_pcre2']:
jit_blacklist = ['javascript']
thirdparty_dir = '#thirdparty/pcre2/src/'
thirdparty_flags = ['-DPCRE2_STATIC', '-DHAVE_CONFIG_H']
diff --git a/modules/squish/SCsub b/modules/squish/SCsub
index cca7c038f1..127f22d798 100644
--- a/modules/squish/SCsub
+++ b/modules/squish/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_squish = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_squish'] != 'no'):
+if env['builtin_squish']:
thirdparty_dir = "#thirdparty/squish/"
thirdparty_sources = [
"alpha.cpp",
diff --git a/modules/squish/config.py b/modules/squish/config.py
index cc8f098010..9b7729bda4 100644
--- a/modules/squish/config.py
+++ b/modules/squish/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_squish_enabled"] = "no"
+ if not env['tools']:
+ env['module_squish_enabled'] = False
env.disabled_modules.append("squish")
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index e27452354b..9c198ea98e 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -51,7 +51,7 @@ inline void change_nsvg_paint_color(NSVGpaint *p_paint, const uint32_t p_old, co
if (p_paint->type == NSVG_PAINT_COLOR) {
if (p_paint->color << 8 == p_old << 8) {
- p_paint->color = p_new;
+ p_paint->color = (p_paint->color & 0xFF000000) | (p_new & 0x00FFFFFF);
}
}
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 2de4d29640..9015c2c354 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_theora = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libtheora'] != 'no'):
+if env['builtin_libtheora']:
thirdparty_dir = "#thirdparty/libtheora/"
thirdparty_sources = [
#"analyze.c",
@@ -74,9 +74,9 @@ if (env['builtin_libtheora'] != 'no'):
env_theora.Append(CPPPATH=[thirdparty_dir])
# also requires libogg and libvorbis
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_theora.Append(CPPPATH=["#thirdparty/libogg"])
- if (env['builtin_libvorbis'] != 'no'):
+ if env['builtin_libvorbis']:
env_theora.Append(CPPPATH=["#thirdparty/libvorbis"])
# Godot source files
diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py
index 2e4b96a6b0..3e16fd725e 100644
--- a/modules/tinyexr/config.py
+++ b/modules/tinyexr/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_tinyexr_enabled"] = "no"
+ if not env['tools']:
+ env['module_tinyexr_enabled'] = False
env.disabled_modules.append("tinyexr")
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index c665fa12cf..2a556b5a52 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -2008,8 +2008,8 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
Node *node = Object::cast_to<Node>(p_owner);
if (p_script->functions.has("_process"))
node->set_process(true);
- if (p_script->functions.has("_fixed_process"))
- node->set_fixed_process(true);
+ if (p_script->functions.has("_physics_process"))
+ node->set_physics_process(true);
if (p_script->functions.has("_input"))
node->set_process_input(true);
if (p_script->functions.has("_unhandled_input"))
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index d0ab29f184..985f8a8d0e 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -3267,8 +3267,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph = memnew(GraphEdit);
add_child(graph);
- graph->set_area_as_parent_rect();
- graph->set_h_size_flags(SIZE_EXPAND_FILL);
+ graph->set_anchors_and_margins_preset(Control::PRESET_WIDE);
graph->connect("node_selected", this, "_node_selected");
graph->connect("_begin_node_move", this, "_begin_node_move");
graph->connect("_end_node_move", this, "_end_node_move");
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index f02e797fe6..8d73de9889 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -42,7 +42,7 @@
int VisualScriptFunctionCall::get_output_sequence_port_count() const {
- if (method_cache.flags & METHOD_FLAG_CONST || call_mode == CALL_MODE_BASIC_TYPE)
+ if (method_cache.flags & METHOD_FLAG_CONST || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)))
return 0;
else
return 1;
@@ -50,7 +50,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const {
bool VisualScriptFunctionCall::has_input_sequence_port() const {
- if (method_cache.flags & METHOD_FLAG_CONST || call_mode == CALL_MODE_BASIC_TYPE)
+ if (method_cache.flags & METHOD_FLAG_CONST || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)))
return false;
else
return true;
@@ -763,7 +763,7 @@ public:
NodePath node_path;
int input_args;
bool validate;
- bool returns;
+ int returns;
VisualScriptFunctionCall::RPCCallMode rpc_mode;
StringName function;
StringName singleton;
@@ -856,7 +856,13 @@ public:
}
} else if (returns) {
if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
- *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
+ if (returns >= 2) {
+ *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
+ } else {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
+ return 0;
+ }
} else {
*p_outputs[0] = v.call(function, p_inputs + 1, input_args, r_error);
}
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index b6d4021ca3..bc033418ba 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -82,7 +82,7 @@ String VisualScriptYield::get_text() const {
switch (yield_mode) {
case YIELD_RETURN: return ""; break;
case YIELD_FRAME: return "Next Frame"; break;
- case YIELD_FIXED_FRAME: return "Next Fixed Frame"; break;
+ case YIELD_PHYSICS_FRAME: return "Next Fixed Frame"; break;
case YIELD_WAIT: return rtos(wait_time) + " sec(s)"; break;
}
@@ -122,7 +122,7 @@ public:
ret = STEP_EXIT_FUNCTION_BIT;
break; //return the yield
case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree, "idle_frame", Array()); break;
- case VisualScriptYield::YIELD_FIXED_FRAME: state->connect_to_signal(tree, "fixed_frame", Array()); break;
+ case VisualScriptYield::YIELD_PHYSICS_FRAME: state->connect_to_signal(tree, "physics_frame", Array()); break;
case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); break;
}
@@ -190,7 +190,7 @@ void VisualScriptYield::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time"), "set_wait_time", "get_wait_time");
BIND_ENUM_CONSTANT(YIELD_FRAME);
- BIND_ENUM_CONSTANT(YIELD_FIXED_FRAME);
+ BIND_ENUM_CONSTANT(YIELD_PHYSICS_FRAME);
BIND_ENUM_CONSTANT(YIELD_WAIT);
}
@@ -597,7 +597,7 @@ static Ref<VisualScriptNode> create_yield_signal_node(const String &p_name) {
void register_visual_script_yield_nodes() {
VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_frame", create_yield_node<VisualScriptYield::YIELD_FRAME>);
- VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_fixed_frame", create_yield_node<VisualScriptYield::YIELD_FIXED_FRAME>);
+ VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_physics_frame", create_yield_node<VisualScriptYield::YIELD_PHYSICS_FRAME>);
VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time", create_yield_node<VisualScriptYield::YIELD_WAIT>);
VisualScriptLanguage::singleton->add_register_func("functions/yield", create_yield_node<VisualScriptYield::YIELD_RETURN>);
diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h
index d074962471..4a595a875a 100644
--- a/modules/visual_script/visual_script_yield_nodes.h
+++ b/modules/visual_script/visual_script_yield_nodes.h
@@ -39,7 +39,7 @@ public:
enum YieldMode {
YIELD_RETURN,
YIELD_FRAME,
- YIELD_FIXED_FRAME,
+ YIELD_PHYSICS_FRAME,
YIELD_WAIT
};
diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub
index d3e4f7e15a..9d2d0feb92 100644
--- a/modules/vorbis/SCsub
+++ b/modules/vorbis/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_vorbis = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libvorbis'] != 'no'):
+if env['builtin_libvorbis']:
thirdparty_dir = "#thirdparty/libvorbis/"
thirdparty_sources = [
#"analysis.c",
@@ -42,7 +42,7 @@ if (env['builtin_libvorbis'] != 'no'):
env_vorbis.Append(CPPPATH=[thirdparty_dir])
# also requires libogg
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_vorbis.Append(CPPPATH=["#thirdparty/libogg"])
# Godot source files
diff --git a/modules/webm/SCsub b/modules/webm/SCsub
index 889f5e83aa..2f1a28a54c 100644
--- a/modules/webm/SCsub
+++ b/modules/webm/SCsub
@@ -19,14 +19,14 @@ env_webm.add_source_files(env.modules_sources, thirdparty_libsimplewebm_sources)
env_webm.Append(CPPPATH=[thirdparty_libsimplewebm_dir, thirdparty_libsimplewebm_dir + "libwebm/"])
# also requires libogg, libvorbis and libopus
-if (env['builtin_libogg'] != 'no'):
+if env['builtin_libogg']:
env_webm.Append(CPPPATH=["#thirdparty/libogg"])
-if (env['builtin_libvorbis'] != 'no'):
+if env['builtin_libvorbis']:
env_webm.Append(CPPPATH=["#thirdparty/libvorbis"])
-if (env['builtin_opus'] != 'no'):
+if env['builtin_opus']:
env_webm.Append(CPPPATH=["#thirdparty/opus"])
-if (env['builtin_libvpx'] != 'no'):
+if env['builtin_libvpx']:
Export('env_webm')
SConscript("libvpx/SCsub")
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index 0ee2ed45b8..fd8d762a5e 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -265,7 +265,7 @@ if env["platform"] == 'uwp':
else:
import platform
is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and platform.machine().startswith('arm'))
- is_ios_x86 = (env["platform"] == 'iphone' and env["ios_sim"] == "yes")
+ is_ios_x86 = (env["platform"] == 'iphone' and env["ios_sim"])
is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86')
if is_android_x86:
cpu_bits = '32'
diff --git a/modules/webp/SCsub b/modules/webp/SCsub
index aa3486a2c5..f9295fed47 100644
--- a/modules/webp/SCsub
+++ b/modules/webp/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_webp = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libwebp'] != 'no'):
+if env['builtin_libwebp']:
thirdparty_dir = "#thirdparty/libwebp/"
thirdparty_sources = [
"dec/alpha_dec.c",