summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bmp/config.py4
-rw-r--r--modules/bullet/config.py2
-rw-r--r--modules/csg/config.py2
-rw-r--r--modules/csg/register_types.cpp4
-rw-r--r--modules/dds/config.py2
-rw-r--r--modules/enet/config.py2
-rw-r--r--modules/etc/config.py10
-rw-r--r--modules/freetype/config.py2
-rw-r--r--modules/gdnative/arvr/arvr_interface_gdnative.cpp4
-rw-r--r--modules/gdnative/config.py2
-rw-r--r--modules/gdnative/gdnative_api.json2
-rw-r--r--modules/gdnative/include/arvr/godot_arvr.h8
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h3
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp38
-rw-r--r--modules/gdnative/nativescript/nativescript.h4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.cpp4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp24
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.h8
-rw-r--r--modules/gdscript/config.py2
-rw-r--r--modules/gdscript/gdscript.cpp13
-rw-r--r--modules/gdscript/gdscript.h6
-rw-r--r--modules/gdscript/gdscript_function.cpp2
-rw-r--r--modules/gdscript/gdscript_function.h12
-rw-r--r--modules/gdscript/gdscript_parser.cpp49
-rw-r--r--modules/gdscript/gdscript_parser.h8
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp9
-rw-r--r--modules/gdscript/gdscript_tokenizer.h3
-rw-r--r--modules/gridmap/config.py2
-rw-r--r--modules/hdr/config.py2
-rw-r--r--modules/jpg/config.py2
-rwxr-xr-xmodules/mbedtls/config.py2
-rw-r--r--modules/mobile_vr/config.py2
-rw-r--r--modules/mono/config.py2
-rw-r--r--modules/mono/csharp_script.cpp32
-rw-r--r--modules/mono/csharp_script.h6
-rw-r--r--modules/mono/glue/cs_files/RPCAttributes.cs9
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h3
-rw-r--r--modules/ogg/config.py2
-rw-r--r--modules/opus/config.py2
-rw-r--r--modules/pvr/config.py2
-rw-r--r--modules/recast/SCsub12
-rw-r--r--modules/recast/config.py4
-rw-r--r--modules/recast/navigation_mesh_editor_plugin.cpp163
-rw-r--r--modules/recast/navigation_mesh_editor_plugin.h84
-rw-r--r--modules/recast/navigation_mesh_generator.cpp304
-rw-r--r--modules/recast/navigation_mesh_generator.h59
-rw-r--r--modules/recast/register_types.cpp7
-rw-r--r--modules/regex/config.py2
-rw-r--r--modules/squish/config.py10
-rw-r--r--modules/stb_vorbis/config.py2
-rw-r--r--modules/svg/SCsub19
-rw-r--r--modules/svg/config.py2
-rw-r--r--modules/tga/config.py2
-rw-r--r--modules/thekla_unwrap/config.py8
-rw-r--r--modules/theora/config.py2
-rw-r--r--modules/tinyexr/config.py10
-rw-r--r--modules/visual_script/config.py2
-rw-r--r--modules/visual_script/visual_script.cpp10
-rw-r--r--modules/visual_script/visual_script.h4
-rw-r--r--modules/visual_script/visual_script_nodes.cpp8
-rw-r--r--modules/visual_script/visual_script_nodes.h6
-rw-r--r--modules/vorbis/config.py2
-rw-r--r--modules/webm/config.py4
-rw-r--r--modules/webp/config.py2
-rw-r--r--modules/websocket/config.py4
67 files changed, 849 insertions, 190 deletions
diff --git a/modules/bmp/config.py b/modules/bmp/config.py
index fb920482f5..1c8cd12a2d 100644
--- a/modules/bmp/config.py
+++ b/modules/bmp/config.py
@@ -1,7 +1,5 @@
-
-def can_build(platform):
+def can_build(env, platform):
return True
-
def configure(env):
pass
diff --git a/modules/bullet/config.py b/modules/bullet/config.py
index 0a31c2e503..92dbcf5cb0 100644
--- a/modules/bullet/config.py
+++ b/modules/bullet/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/csg/config.py b/modules/csg/config.py
index 5e1d916790..38ccc66d91 100644
--- a/modules/csg/config.py
+++ b/modules/csg/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp
index 020724ee59..0dea09808a 100644
--- a/modules/csg/register_types.cpp
+++ b/modules/csg/register_types.cpp
@@ -30,8 +30,8 @@
#include "register_types.h"
-#include "csg_shape.h"
#include "csg_gizmos.h"
+#include "csg_shape.h"
void register_csg_types() {
@@ -51,9 +51,7 @@ void register_csg_types() {
EditorPlugins::add_by_type<EditorPluginCSG>();
#endif
#endif
-
}
void unregister_csg_types() {
-
}
diff --git a/modules/dds/config.py b/modules/dds/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/dds/config.py
+++ b/modules/dds/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/enet/config.py b/modules/enet/config.py
index 8031fbb4b6..3e30bbe778 100644
--- a/modules/enet/config.py
+++ b/modules/enet/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/etc/config.py b/modules/etc/config.py
index 395fc1bb02..098f1eafa9 100644
--- a/modules/etc/config.py
+++ b/modules/etc/config.py
@@ -1,9 +1,5 @@
-def can_build(platform):
- return True
+def can_build(env, platform):
+ return env['tools']
def configure(env):
- # Tools only, disabled for non-tools
- # TODO: Find a cleaner way to achieve that
- if not env['tools']:
- env['module_etc_enabled'] = False
- env.disabled_modules.append("etc")
+ pass
diff --git a/modules/freetype/config.py b/modules/freetype/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/freetype/config.py
+++ b/modules/freetype/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
index 49e0a19d9e..385c020a78 100644
--- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp
+++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
@@ -217,6 +217,10 @@ void ARVRInterfaceGDNative::process() {
extern "C" {
void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) {
+ // If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin
+ ERR_EXPLAINC("GDNative ARVR interfaces build for Godot 3.0 are not supported");
+ ERR_FAIL_COND((p_interface->version.major == 0) || (p_interface->version.major > 10));
+
Ref<ARVRInterfaceGDNative> new_interface;
new_interface.instance();
new_interface->set_interface((godot_arvr_interface_gdnative *const)p_interface);
diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py
index 68148c4d87..626e9239f8 100644
--- a/modules/gdnative/config.py
+++ b/modules/gdnative/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 9fcf61af8a..c16f2d3b40 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -5966,7 +5966,7 @@
"type": "ARVR",
"version": {
"major": 1,
- "minor": 0
+ "minor": 1
},
"next": null,
"api": [
diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h
index b9aedc0bef..63de62b507 100644
--- a/modules/gdnative/include/arvr/godot_arvr.h
+++ b/modules/gdnative/include/arvr/godot_arvr.h
@@ -37,7 +37,15 @@
extern "C" {
#endif
+// For future versions of the API we should only add new functions at the end of the structure and use the
+// version info to detect whether a call is available
+
+// Use these to populate version in your plugin
+#define GODOTVR_API_MAJOR 1
+#define GODOTVR_API_MINOR 0
+
typedef struct {
+ godot_gdnative_api_version version; /* version of our API */
void *(*constructor)(godot_object *);
void (*destructor)(void *);
godot_string (*get_name)(const void *);
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index cfbe16fa7d..f28ba352ab 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -43,6 +43,9 @@ typedef enum {
GODOT_METHOD_RPC_MODE_SYNC,
GODOT_METHOD_RPC_MODE_MASTER,
GODOT_METHOD_RPC_MODE_SLAVE,
+ GODOT_METHOD_RPC_MODE_REMOTESYNC,
+ GODOT_METHOD_RPC_MODE_MASTERSYNC,
+ GODOT_METHOD_RPC_MODE_SLAVESYNC,
} godot_method_rpc_mode;
typedef enum {
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index cf8977f3ea..d6abbc1bcf 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -747,7 +747,7 @@ Ref<Script> NativeScriptInstance::get_script() const {
return script;
}
-NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
+MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
@@ -757,27 +757,33 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringNam
if (E) {
switch (E->get().rpc_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
- return RPC_MODE_REMOTE;
+ return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_SYNC:
- return RPC_MODE_SYNC;
+ return MultiplayerAPI::RPC_MODE_SYNC;
case GODOT_METHOD_RPC_MODE_MASTER:
- return RPC_MODE_MASTER;
+ return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_SLAVE:
- return RPC_MODE_SLAVE;
+ return MultiplayerAPI::RPC_MODE_SLAVE;
+ case GODOT_METHOD_RPC_MODE_REMOTESYNC:
+ return MultiplayerAPI::RPC_MODE_REMOTESYNC;
+ case GODOT_METHOD_RPC_MODE_MASTERSYNC:
+ return MultiplayerAPI::RPC_MODE_MASTERSYNC;
+ case GODOT_METHOD_RPC_MODE_SLAVESYNC:
+ return MultiplayerAPI::RPC_MODE_SLAVESYNC;
default:
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
script_data = script_data->base_data;
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
-NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
+MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
NativeScriptDesc *script_data = GET_SCRIPT_DESC();
@@ -787,24 +793,24 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringNa
if (E) {
switch (E.get().rset_mode) {
case GODOT_METHOD_RPC_MODE_DISABLED:
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
case GODOT_METHOD_RPC_MODE_REMOTE:
- return RPC_MODE_REMOTE;
+ return MultiplayerAPI::RPC_MODE_REMOTE;
case GODOT_METHOD_RPC_MODE_SYNC:
- return RPC_MODE_SYNC;
+ return MultiplayerAPI::RPC_MODE_SYNC;
case GODOT_METHOD_RPC_MODE_MASTER:
- return RPC_MODE_MASTER;
+ return MultiplayerAPI::RPC_MODE_MASTER;
case GODOT_METHOD_RPC_MODE_SLAVE:
- return RPC_MODE_SLAVE;
+ return MultiplayerAPI::RPC_MODE_SLAVE;
default:
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
script_data = script_data->base_data;
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
ScriptLanguage *NativeScriptInstance::get_language() {
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index 68a8126a32..b47962dc37 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -196,8 +196,8 @@ public:
virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
virtual void notification(int p_notification);
virtual Ref<Script> get_script() const;
- virtual RPCMode get_rpc_mode(const StringName &p_method) const;
- virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
virtual ScriptLanguage *get_language();
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.cpp b/modules/gdnative/pluginscript/pluginscript_instance.cpp
index 931ab0bfe4..13026e8e7a 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_instance.cpp
@@ -138,11 +138,11 @@ void PluginScriptInstance::notification(int p_notification) {
_desc->notification(_data, p_notification);
}
-ScriptInstance::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
+MultiplayerAPI::RPCMode PluginScriptInstance::get_rpc_mode(const StringName &p_method) const {
return _script->get_rpc_mode(p_method);
}
-ScriptInstance::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
+MultiplayerAPI::RPCMode PluginScriptInstance::get_rset_mode(const StringName &p_variable) const {
return _script->get_rset_mode(p_variable);
}
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
index 3c7b360ad9..8be6a4ccaa 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.h
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -76,8 +76,8 @@ public:
void set_path(const String &p_path);
- virtual RPCMode get_rpc_mode(const StringName &p_method) const;
- virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
virtual void refcount_incremented();
virtual bool refcount_decremented();
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index 5ae7926f1b..eb2e7903e5 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -245,9 +245,9 @@ Error PluginScript::reload(bool p_keep_state) {
// rpc_mode is passed as an optional field and is not part of MethodInfo
Variant var = v["rpc_mode"];
if (var == Variant()) {
- _methods_rpc_mode[mi.name] = ScriptInstance::RPC_MODE_DISABLED;
+ _methods_rpc_mode[mi.name] = MultiplayerAPI::RPC_MODE_DISABLED;
} else {
- _methods_rpc_mode[mi.name] = ScriptInstance::RPCMode(int(var));
+ _methods_rpc_mode[mi.name] = MultiplayerAPI::RPCMode(int(var));
}
}
Array *signals = (Array *)&manifest.signals;
@@ -265,9 +265,9 @@ Error PluginScript::reload(bool p_keep_state) {
// rset_mode is passed as an optional field and is not part of PropertyInfo
Variant var = v["rset_mode"];
if (var == Variant()) {
- _methods_rpc_mode[pi.name] = ScriptInstance::RPC_MODE_DISABLED;
+ _methods_rpc_mode[pi.name] = MultiplayerAPI::RPC_MODE_DISABLED;
} else {
- _methods_rpc_mode[pi.name] = ScriptInstance::RPCMode(int(var));
+ _methods_rpc_mode[pi.name] = MultiplayerAPI::RPCMode(int(var));
}
}
// Manifest's attributes must be explicitly freed
@@ -402,23 +402,23 @@ int PluginScript::get_member_line(const StringName &p_member) const {
return -1;
}
-ScriptInstance::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
- ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED);
- const Map<StringName, ScriptInstance::RPCMode>::Element *e = _methods_rpc_mode.find(p_method);
+MultiplayerAPI::RPCMode PluginScript::get_rpc_mode(const StringName &p_method) const {
+ ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
+ const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _methods_rpc_mode.find(p_method);
if (e != NULL) {
return e->get();
} else {
- return ScriptInstance::RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
-ScriptInstance::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
- ASSERT_SCRIPT_VALID_V(ScriptInstance::RPC_MODE_DISABLED);
- const Map<StringName, ScriptInstance::RPCMode>::Element *e = _variables_rset_mode.find(p_variable);
+MultiplayerAPI::RPCMode PluginScript::get_rset_mode(const StringName &p_variable) const {
+ ASSERT_SCRIPT_VALID_V(MultiplayerAPI::RPC_MODE_DISABLED);
+ const Map<StringName, MultiplayerAPI::RPCMode>::Element *e = _variables_rset_mode.find(p_variable);
if (e != NULL) {
return e->get();
} else {
- return ScriptInstance::RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h
index 1be9e907c2..31c6c4d67f 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.h
+++ b/modules/gdnative/pluginscript/pluginscript_script.h
@@ -62,8 +62,8 @@ private:
Map<StringName, PropertyInfo> _properties_info;
Map<StringName, MethodInfo> _signals_info;
Map<StringName, MethodInfo> _methods_info;
- Map<StringName, ScriptInstance::RPCMode> _variables_rset_mode;
- Map<StringName, ScriptInstance::RPCMode> _methods_rpc_mode;
+ Map<StringName, MultiplayerAPI::RPCMode> _variables_rset_mode;
+ Map<StringName, MultiplayerAPI::RPCMode> _methods_rpc_mode;
Set<Object *> _instances;
//exported members
@@ -116,8 +116,8 @@ public:
virtual int get_member_line(const StringName &p_member) const;
- ScriptInstance::RPCMode get_rpc_mode(const StringName &p_method) const;
- ScriptInstance::RPCMode get_rset_mode(const StringName &p_variable) const;
+ MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
PluginScript();
void init(PluginScriptLanguage *language);
diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py
index 6496b59d75..95b40d90af 100644
--- a/modules/gdscript/config.py
+++ b/modules/gdscript/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 14bdce50ec..f23e7854a5 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1220,7 +1220,7 @@ ScriptLanguage *GDScriptInstance::get_language() {
return GDScriptLanguage::get_singleton();
}
-GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
+MultiplayerAPI::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_method) const {
const GDScript *cscript = script.ptr();
@@ -1228,17 +1228,17 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rpc_mode(const StringName &p_met
const Map<StringName, GDScriptFunction *>::Element *E = cscript->member_functions.find(p_method);
if (E) {
- if (E->get()->get_rpc_mode() != RPC_MODE_DISABLED) {
+ if (E->get()->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
return E->get()->get_rpc_mode();
}
}
cscript = cscript->_base;
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
-GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
+MultiplayerAPI::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_variable) const {
const GDScript *cscript = script.ptr();
@@ -1253,7 +1253,7 @@ GDScriptInstance::RPCMode GDScriptInstance::get_rset_mode(const StringName &p_va
cscript = cscript->_base;
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
void GDScriptInstance::reload_members() {
@@ -1769,6 +1769,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"sync",
"master",
"slave",
+ "remotesync",
+ "mastersync",
+ "slavesync",
0
};
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 6885fbb7fe..a35b0a10d5 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -63,7 +63,7 @@ class GDScript : public Script {
int index;
StringName setter;
StringName getter;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
};
friend class GDScriptInstance;
@@ -248,8 +248,8 @@ public:
void reload_members();
- virtual RPCMode get_rpc_mode(const StringName &p_method) const;
- virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
GDScriptInstance();
~GDScriptInstance();
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index dac7da3a28..61130cb58f 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1455,7 +1455,7 @@ GDScriptFunction::GDScriptFunction() :
_stack_size = 0;
_call_size = 0;
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
name = "<anonymous>";
#ifdef DEBUG_ENABLED
_func_cname = NULL;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index ea009dcd96..836325f0fe 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -96,14 +96,6 @@ public:
ADDR_TYPE_NIL = 9
};
- enum RPCMode {
- RPC_DISABLED,
- RPC_ENABLED,
- RPC_SYNC,
- RPC_SYNC_MASTER,
- RPC_SYNC_SLAVE
- };
-
struct StackDebug {
int line;
@@ -135,7 +127,7 @@ private:
int _call_size;
int _initial_line;
bool _static;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
GDScript *_script;
@@ -230,7 +222,7 @@ public:
Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL);
- _FORCE_INLINE_ ScriptInstance::RPCMode get_rpc_mode() const { return rpc_mode; }
+ _FORCE_INLINE_ MultiplayerAPI::RPCMode get_rpc_mode() const { return rpc_mode; }
GDScriptFunction();
~GDScriptFunction();
};
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 5e93b377d2..fdb92a68a9 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3373,7 +3373,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
function->line = fnline;
function->rpc_mode = rpc_mode;
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
if (_static)
p_class->static_functions.push_back(function);
@@ -3931,10 +3931,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
- if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVESYNC) {
current_export = PropertyInfo();
- _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave' or 'sync'.");
+ _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave', 'sync', 'remotesync', 'mastersync', 'slavesync'.");
return;
}
@@ -3967,7 +3967,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
}
- rpc_mode = ScriptInstance::RPC_MODE_REMOTE;
+ rpc_mode = MultiplayerAPI::RPC_MODE_REMOTE;
continue;
} break;
@@ -3988,7 +3988,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
- rpc_mode = ScriptInstance::RPC_MODE_MASTER;
+ rpc_mode = MultiplayerAPI::RPC_MODE_MASTER;
continue;
} break;
case GDScriptTokenizer::TK_PR_SLAVE: {
@@ -4008,9 +4008,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
- rpc_mode = ScriptInstance::RPC_MODE_SLAVE;
+ rpc_mode = MultiplayerAPI::RPC_MODE_SLAVE;
continue;
} break;
+ case GDScriptTokenizer::TK_PR_REMOTESYNC:
case GDScriptTokenizer::TK_PR_SYNC: {
//may be fallthrough from export, ignore if so
@@ -4023,7 +4024,37 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- rpc_mode = ScriptInstance::RPC_MODE_SYNC;
+ rpc_mode = MultiplayerAPI::RPC_MODE_SYNC;
+ continue;
+ } break;
+ case GDScriptTokenizer::TK_PR_MASTERSYNC: {
+
+ //may be fallthrough from export, ignore if so
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
+ if (current_export.type)
+ _set_error("Expected 'var'.");
+ else
+ _set_error("Expected 'var' or 'func'.");
+ return;
+ }
+
+ rpc_mode = MultiplayerAPI::RPC_MODE_MASTERSYNC;
+ continue;
+ } break;
+ case GDScriptTokenizer::TK_PR_SLAVESYNC: {
+
+ //may be fallthrough from export, ignore if so
+ tokenizer->advance();
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
+ if (current_export.type)
+ _set_error("Expected 'var'.");
+ else
+ _set_error("Expected 'var' or 'func'.");
+ return;
+ }
+
+ rpc_mode = MultiplayerAPI::RPC_MODE_SLAVESYNC;
continue;
} break;
case GDScriptTokenizer::TK_PR_VAR: {
@@ -4053,7 +4084,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
@@ -4478,7 +4509,7 @@ void GDScriptParser::clear() {
current_class = NULL;
completion_found = false;
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
current_function = NULL;
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 485ba1263d..b88a59537c 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -89,7 +89,7 @@ public:
StringName getter;
int line;
Node *expression;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
};
struct Constant {
StringName identifier;
@@ -125,7 +125,7 @@ public:
struct FunctionNode : public Node {
bool _static;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
StringName name;
Vector<StringName> arguments;
Vector<Node *> default_values;
@@ -134,7 +134,7 @@ public:
FunctionNode() {
type = TYPE_FUNCTION;
_static = false;
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
};
@@ -493,7 +493,7 @@ private:
PropertyInfo current_export;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
void _set_error(const String &p_error, int p_line = -1, int p_column = -1);
bool _recover_from_completion();
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 6a844cd651..3c8e1ddbe4 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -110,6 +110,9 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"sync",
"master",
"slave",
+ "remotesync",
+ "mastersync",
+ "slavesync",
"'['",
"']'",
"'{'",
@@ -201,6 +204,9 @@ static const _kws _keyword_list[] = {
{ GDScriptTokenizer::TK_PR_MASTER, "master" },
{ GDScriptTokenizer::TK_PR_SLAVE, "slave" },
{ GDScriptTokenizer::TK_PR_SYNC, "sync" },
+ { GDScriptTokenizer::TK_PR_REMOTESYNC, "remotesync" },
+ { GDScriptTokenizer::TK_PR_MASTERSYNC, "mastersync" },
+ { GDScriptTokenizer::TK_PR_SLAVESYNC, "slavesync" },
{ GDScriptTokenizer::TK_PR_CONST, "const" },
{ GDScriptTokenizer::TK_PR_ENUM, "enum" },
//controlflow
@@ -247,6 +253,9 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const
case TK_PR_MASTER:
case TK_PR_SLAVE:
case TK_PR_SYNC:
+ case TK_PR_REMOTESYNC:
+ case TK_PR_MASTERSYNC:
+ case TK_PR_SLAVESYNC:
return true;
// Literal for non-variables only:
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index b020c85199..c4f1f9fd94 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -115,6 +115,9 @@ public:
TK_PR_SYNC,
TK_PR_MASTER,
TK_PR_SLAVE,
+ TK_PR_REMOTESYNC,
+ TK_PR_MASTERSYNC,
+ TK_PR_SLAVESYNC,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_CURLY_BRACKET_OPEN,
diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py
index a93f4edb81..5022116c9b 100644
--- a/modules/gridmap/config.py
+++ b/modules/gridmap/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/hdr/config.py b/modules/hdr/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/hdr/config.py
+++ b/modules/hdr/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/jpg/config.py b/modules/jpg/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/jpg/config.py
+++ b/modules/jpg/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/mbedtls/config.py b/modules/mbedtls/config.py
index 5f133eba90..1c8cd12a2d 100755
--- a/modules/mbedtls/config.py
+++ b/modules/mbedtls/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py
index aa8ef111d3..4912457e2b 100644
--- a/modules/mobile_vr/config.py
+++ b/modules/mobile_vr/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
# should probably change this to only be true on iOS and Android
return False
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 18d9c67795..3afb8a8892 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -19,7 +19,7 @@ def find_file_in_dir(directory, files, prefix='', extension=''):
return ''
-def can_build(platform):
+def can_build(env, platform):
if platform in ["javascript"]:
return False # Not yet supported
return True
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 24292b77ed..3cfc376317 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1310,21 +1310,27 @@ bool CSharpInstance::refcount_decremented() {
return ref_dying;
}
-ScriptInstance::RPCMode CSharpInstance::_member_get_rpc_mode(GDMonoClassMember *p_member) const {
+MultiplayerAPI::RPCMode CSharpInstance::_member_get_rpc_mode(GDMonoClassMember *p_member) const {
if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute)))
- return RPC_MODE_REMOTE;
+ return MultiplayerAPI::RPC_MODE_REMOTE;
if (p_member->has_attribute(CACHED_CLASS(SyncAttribute)))
- return RPC_MODE_SYNC;
+ return MultiplayerAPI::RPC_MODE_SYNC;
if (p_member->has_attribute(CACHED_CLASS(MasterAttribute)))
- return RPC_MODE_MASTER;
+ return MultiplayerAPI::RPC_MODE_MASTER;
if (p_member->has_attribute(CACHED_CLASS(SlaveAttribute)))
- return RPC_MODE_SLAVE;
+ return MultiplayerAPI::RPC_MODE_SLAVE;
+ if (p_member->has_attribute(CACHED_CLASS(RemoteSyncAttribute)))
+ return MultiplayerAPI::RPC_MODE_REMOTESYNC;
+ if (p_member->has_attribute(CACHED_CLASS(MasterSyncAttribute)))
+ return MultiplayerAPI::RPC_MODE_MASTERSYNC;
+ if (p_member->has_attribute(CACHED_CLASS(SlaveSyncAttribute)))
+ return MultiplayerAPI::RPC_MODE_SLAVESYNC;
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
-ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
+MultiplayerAPI::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
GDMonoClass *top = script->script_class;
@@ -1337,10 +1343,10 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method)
top = top->get_parent_class();
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
-ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
+MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
GDMonoClass *top = script->script_class;
@@ -1358,7 +1364,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab
top = top->get_parent_class();
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
void CSharpInstance::notification(int p_notification) {
@@ -1967,15 +1973,15 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) {
return NULL;
#endif
}
-
+
if (!script_class) {
if (GDMono::get_singleton()->get_project_assembly() == NULL) {
// The project assembly is not loaded
ERR_EXPLAIN("Cannot instance script because the project assembly is not loaded. Script: " + get_path());
ERR_FAIL_V(NULL);
}
-
- // The project assembly is loaded, but the class could not found
+
+ // The project assembly is loaded, but the class could not found
ERR_EXPLAIN("Cannot instance script because the class '" + name + "' could not be found. Script: " + get_path());
ERR_FAIL_V(NULL);
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 8666149111..cae2bbf40a 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -192,7 +192,7 @@ class CSharpInstance : public ScriptInstance {
void _call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount);
- RPCMode _member_get_rpc_mode(GDMonoClassMember *p_member) const;
+ MultiplayerAPI::RPCMode _member_get_rpc_mode(GDMonoClassMember *p_member) const;
public:
MonoObject *get_mono_object() const;
@@ -213,8 +213,8 @@ public:
virtual void refcount_incremented();
virtual bool refcount_decremented();
- virtual RPCMode get_rpc_mode(const StringName &p_method) const;
- virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
virtual void notification(int p_notification);
void call_notification_no_check(MonoObject *p_mono_object, int p_notification);
diff --git a/modules/mono/glue/cs_files/RPCAttributes.cs b/modules/mono/glue/cs_files/RPCAttributes.cs
index 08841ffd76..6bf9560bfa 100644
--- a/modules/mono/glue/cs_files/RPCAttributes.cs
+++ b/modules/mono/glue/cs_files/RPCAttributes.cs
@@ -13,4 +13,13 @@ namespace Godot
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
public class SlaveAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class RemoteSyncAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class MasterSyncAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class SlaveSyncAttribute : Attribute {}
}
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index db136a1313..fbdbeaa3f7 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -120,6 +120,9 @@ void MonoCache::clear_members() {
class_SyncAttribute = NULL;
class_MasterAttribute = NULL;
class_SlaveAttribute = NULL;
+ class_RemoteSyncAttribute = NULL;
+ class_MasterSyncAttribute = NULL;
+ class_SlaveSyncAttribute = NULL;
class_GodotMethodAttribute = NULL;
field_GodotMethodAttribute_methodName = NULL;
@@ -208,6 +211,9 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute));
+ CACHE_CLASS_AND_CHECK(RemoteSyncAttribute, GODOT_API_CLASS(RemoteSyncAttribute));
+ CACHE_CLASS_AND_CHECK(MasterSyncAttribute, GODOT_API_CLASS(MasterSyncAttribute));
+ CACHE_CLASS_AND_CHECK(SlaveSyncAttribute, GODOT_API_CLASS(SlaveSyncAttribute));
CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 1a34180d15..fc13a00e85 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -112,6 +112,9 @@ struct MonoCache {
GDMonoClass *class_ToolAttribute;
GDMonoClass *class_RemoteAttribute;
GDMonoClass *class_SyncAttribute;
+ GDMonoClass *class_RemoteSyncAttribute;
+ GDMonoClass *class_MasterSyncAttribute;
+ GDMonoClass *class_SlaveSyncAttribute;
GDMonoClass *class_MasterAttribute;
GDMonoClass *class_SlaveAttribute;
GDMonoClass *class_GodotMethodAttribute;
diff --git a/modules/ogg/config.py b/modules/ogg/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/ogg/config.py
+++ b/modules/ogg/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/opus/config.py b/modules/opus/config.py
index 60f8d838d6..a1cde10ea0 100644
--- a/modules/opus/config.py
+++ b/modules/opus/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/pvr/config.py b/modules/pvr/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/pvr/config.py
+++ b/modules/pvr/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/recast/SCsub b/modules/recast/SCsub
index 530df9a37c..f56be72b24 100644
--- a/modules/recast/SCsub
+++ b/modules/recast/SCsub
@@ -1,8 +1,9 @@
#!/usr/bin/env python
Import('env')
+Import('env_modules')
-# Not building in a separate env as core needs it
+env_recast = env_modules.Clone()
# Thirdparty source files
if env['builtin_recast']:
@@ -22,13 +23,10 @@ if env['builtin_recast']:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/Include"])
-
- lib = env.add_library("recast_builtin", thirdparty_sources)
- env.Append(LIBS=[lib])
+ env_recast.add_source_files(env.modules_sources, thirdparty_sources)
+ env_recast.Append(CPPPATH=[thirdparty_dir + "/Include"])
# Godot source files
-env.add_source_files(env.modules_sources, "*.cpp")
-env.Append(CCFLAGS=['-DRECAST_ENABLED'])
+env_recast.add_source_files(env.modules_sources, "*.cpp")
Export('env')
diff --git a/modules/recast/config.py b/modules/recast/config.py
index fc074cf661..098f1eafa9 100644
--- a/modules/recast/config.py
+++ b/modules/recast/config.py
@@ -1,5 +1,5 @@
-def can_build(platform):
- return platform != "android"
+def can_build(env, platform):
+ return env['tools']
def configure(env):
pass
diff --git a/modules/recast/navigation_mesh_editor_plugin.cpp b/modules/recast/navigation_mesh_editor_plugin.cpp
new file mode 100644
index 0000000000..8556b7aa0a
--- /dev/null
+++ b/modules/recast/navigation_mesh_editor_plugin.cpp
@@ -0,0 +1,163 @@
+/*************************************************************************/
+/* navigation_mesh_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 "navigation_mesh_editor_plugin.h"
+
+#include "io/marshalls.h"
+#include "io/resource_saver.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/gui/box_container.h"
+
+void NavigationMeshEditor::_node_removed(Node *p_node) {
+
+ if (p_node == node) {
+ node = NULL;
+
+ hide();
+ }
+}
+
+void NavigationMeshEditor::_notification(int p_option) {
+
+ if (p_option == NOTIFICATION_ENTER_TREE) {
+
+ button_bake->set_icon(get_icon("Bake", "EditorIcons"));
+ button_reset->set_icon(get_icon("Reload", "EditorIcons"));
+ }
+}
+
+void NavigationMeshEditor::_bake_pressed() {
+
+ ERR_FAIL_COND(!node);
+ const String conf_warning = node->get_configuration_warning();
+ if (!conf_warning.empty()) {
+ err_dialog->set_text(conf_warning);
+ err_dialog->popup_centered_minsize();
+ button_bake->set_pressed(false);
+ return;
+ }
+
+ NavigationMeshGenerator::clear(node->get_navigation_mesh());
+ NavigationMeshGenerator::bake(node->get_navigation_mesh(), node);
+
+ if (node) {
+ node->update_gizmo();
+ }
+}
+
+void NavigationMeshEditor::_clear_pressed() {
+
+ if (node)
+ NavigationMeshGenerator::clear(node->get_navigation_mesh());
+
+ button_bake->set_pressed(false);
+ bake_info->set_text("");
+
+ if (node) {
+ node->update_gizmo();
+ }
+}
+
+void NavigationMeshEditor::edit(NavigationMeshInstance *p_nav_mesh_instance) {
+
+ if (p_nav_mesh_instance == NULL || node == p_nav_mesh_instance) {
+ return;
+ }
+
+ node = p_nav_mesh_instance;
+}
+
+void NavigationMeshEditor::_bind_methods() {
+
+ ClassDB::bind_method("_bake_pressed", &NavigationMeshEditor::_bake_pressed);
+ ClassDB::bind_method("_clear_pressed", &NavigationMeshEditor::_clear_pressed);
+}
+
+NavigationMeshEditor::NavigationMeshEditor() {
+
+ bake_hbox = memnew(HBoxContainer);
+ button_bake = memnew(ToolButton);
+ button_bake->set_text(TTR("Bake!"));
+ button_bake->set_toggle_mode(true);
+ button_reset = memnew(Button);
+ button_bake->set_tooltip(TTR("Bake the navigation mesh.") + "\n");
+
+ bake_info = memnew(Label);
+ bake_hbox->add_child(button_bake);
+ bake_hbox->add_child(button_reset);
+ bake_hbox->add_child(bake_info);
+
+ err_dialog = memnew(AcceptDialog);
+ add_child(err_dialog);
+ node = NULL;
+
+ button_bake->connect("pressed", this, "_bake_pressed");
+ button_reset->connect("pressed", this, "_clear_pressed");
+ button_reset->set_tooltip(TTR("Clear the navigation mesh."));
+}
+
+NavigationMeshEditor::~NavigationMeshEditor() {
+}
+
+void NavigationMeshEditorPlugin::edit(Object *p_object) {
+
+ navigation_mesh_editor->edit(Object::cast_to<NavigationMeshInstance>(p_object));
+}
+
+bool NavigationMeshEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("NavigationMeshInstance");
+}
+
+void NavigationMeshEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ navigation_mesh_editor->show();
+ navigation_mesh_editor->bake_hbox->show();
+ } else {
+
+ navigation_mesh_editor->hide();
+ navigation_mesh_editor->bake_hbox->hide();
+ navigation_mesh_editor->edit(NULL);
+ }
+}
+
+NavigationMeshEditorPlugin::NavigationMeshEditorPlugin(EditorNode *p_node) {
+
+ editor = p_node;
+ navigation_mesh_editor = memnew(NavigationMeshEditor);
+ editor->get_viewport()->add_child(navigation_mesh_editor);
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, navigation_mesh_editor->bake_hbox);
+ navigation_mesh_editor->hide();
+ navigation_mesh_editor->bake_hbox->hide();
+}
+
+NavigationMeshEditorPlugin::~NavigationMeshEditorPlugin() {
+}
diff --git a/modules/recast/navigation_mesh_editor_plugin.h b/modules/recast/navigation_mesh_editor_plugin.h
new file mode 100644
index 0000000000..4f3e222002
--- /dev/null
+++ b/modules/recast/navigation_mesh_editor_plugin.h
@@ -0,0 +1,84 @@
+/*************************************************************************/
+/* navigation_mesh_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 NAVIGATION_MESH_GENERATOR_PLUGIN_H
+#define NAVIGATION_MESH_GENERATOR_PLUGIN_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "navigation_mesh_generator.h"
+
+class NavigationMeshEditor : public Control {
+ friend class NavigationMeshEditorPlugin;
+
+ GDCLASS(NavigationMeshEditor, Control);
+
+ AcceptDialog *err_dialog;
+
+ HBoxContainer *bake_hbox;
+ Button *button_bake;
+ Button *button_reset;
+ Label *bake_info;
+
+ NavigationMeshInstance *node;
+
+ void _bake_pressed();
+ void _clear_pressed();
+
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+ void _notification(int p_option);
+
+public:
+ void edit(NavigationMeshInstance *p_nav_mesh_instance);
+ NavigationMeshEditor();
+ ~NavigationMeshEditor();
+};
+
+class NavigationMeshEditorPlugin : public EditorPlugin {
+
+ GDCLASS(NavigationMeshEditorPlugin, EditorPlugin);
+
+ NavigationMeshEditor *navigation_mesh_editor;
+ EditorNode *editor;
+
+public:
+ virtual String get_name() const { return "NavigationMesh"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual void make_visible(bool p_visible);
+
+ NavigationMeshEditorPlugin(EditorNode *p_node);
+ ~NavigationMeshEditorPlugin();
+};
+
+#endif // NAVIGATION_MESH_GENERATOR_PLUGIN_H
diff --git a/modules/recast/navigation_mesh_generator.cpp b/modules/recast/navigation_mesh_generator.cpp
new file mode 100644
index 0000000000..64c4b85269
--- /dev/null
+++ b/modules/recast/navigation_mesh_generator.cpp
@@ -0,0 +1,304 @@
+/*************************************************************************/
+/* navigation_mesh_generator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 "navigation_mesh_generator.h"
+
+void NavigationMeshGenerator::_add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies) {
+ p_verticies.push_back(p_vec3.x);
+ p_verticies.push_back(p_vec3.y);
+ p_verticies.push_back(p_vec3.z);
+}
+
+void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
+ int current_vertex_count = 0;
+
+ for (int i = 0; i < p_mesh->get_surface_count(); i++) {
+ current_vertex_count = p_verticies.size() / 3;
+
+ if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+
+ int index_count = 0;
+ if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) {
+ index_count = p_mesh->surface_get_array_index_len(i);
+ } else {
+ index_count = p_mesh->surface_get_array_len(i);
+ }
+
+ ERR_CONTINUE((index_count == 0 || (index_count % 3) != 0));
+
+ int face_count = index_count / 3;
+
+ Array a = p_mesh->surface_get_arrays(i);
+
+ PoolVector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX];
+ PoolVector<Vector3>::Read vr = mesh_vertices.read();
+
+ if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) {
+
+ PoolVector<int> mesh_indices = a[Mesh::ARRAY_INDEX];
+ PoolVector<int>::Read ir = mesh_indices.read();
+
+ for (int i = 0; i < mesh_vertices.size(); i++) {
+ _add_vertex(p_xform.xform(vr[i]), p_verticies);
+ }
+
+ for (int i = 0; i < face_count; i++) {
+ // CCW
+ p_indices.push_back(current_vertex_count + (ir[i * 3 + 0]));
+ p_indices.push_back(current_vertex_count + (ir[i * 3 + 2]));
+ p_indices.push_back(current_vertex_count + (ir[i * 3 + 1]));
+ }
+ } else {
+ face_count = mesh_vertices.size() / 3;
+ for (int i = 0; i < face_count; i++) {
+ _add_vertex(p_xform.xform(vr[i * 3 + 0]), p_verticies);
+ _add_vertex(p_xform.xform(vr[i * 3 + 2]), p_verticies);
+ _add_vertex(p_xform.xform(vr[i * 3 + 1]), p_verticies);
+
+ p_indices.push_back(current_vertex_count + (i * 3 + 0));
+ p_indices.push_back(current_vertex_count + (i * 3 + 1));
+ p_indices.push_back(current_vertex_count + (i * 3 + 2));
+ }
+ }
+ }
+}
+
+void NavigationMeshGenerator::_parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices) {
+
+ if (Object::cast_to<MeshInstance>(p_node)) {
+
+ MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(p_node);
+ Ref<Mesh> mesh = mesh_instance->get_mesh();
+ if (mesh.is_valid()) {
+ _add_mesh(mesh, p_base_inverse * mesh_instance->get_global_transform(), p_verticies, p_indices);
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _parse_geometry(p_base_inverse, p_node->get_child(i), p_verticies, p_indices);
+ }
+}
+
+void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) {
+
+ PoolVector<Vector3> nav_vertices;
+
+ for (int i = 0; i < p_detail_mesh->nverts; i++) {
+ const float *v = &p_detail_mesh->verts[i * 3];
+ nav_vertices.append(Vector3(v[0], v[1], v[2]));
+ }
+ p_nav_mesh->set_vertices(nav_vertices);
+
+ for (int i = 0; i < p_detail_mesh->nmeshes; i++) {
+ const unsigned int *m = &p_detail_mesh->meshes[i * 4];
+ const unsigned int bverts = m[0];
+ const unsigned int btris = m[2];
+ const unsigned int ntris = m[3];
+ const unsigned char *tris = &p_detail_mesh->tris[btris * 4];
+ for (unsigned int j = 0; j < ntris; j++) {
+ Vector<int> nav_indices;
+ nav_indices.resize(3);
+ nav_indices[0] = ((int)(bverts + tris[j * 4 + 0]));
+ nav_indices[1] = ((int)(bverts + tris[j * 4 + 1]));
+ nav_indices[2] = ((int)(bverts + tris[j * 4 + 2]));
+ p_nav_mesh->add_polygon(nav_indices);
+ }
+ }
+}
+
+void NavigationMeshGenerator::_build_recast_navigation_mesh(Ref<NavigationMesh> p_nav_mesh, EditorProgress *ep,
+ rcHeightfield *hf, rcCompactHeightfield *chf, rcContourSet *cset, rcPolyMesh *poly_mesh, rcPolyMeshDetail *detail_mesh,
+ Vector<float> &vertices, Vector<int> &indices) {
+ rcContext ctx;
+ ep->step(TTR("Setting up Configuration..."), 1);
+
+ const float *verts = vertices.ptr();
+ const int nverts = vertices.size() / 3;
+ const int *tris = indices.ptr();
+ const int ntris = indices.size() / 3;
+
+ float bmin[3], bmax[3];
+ rcCalcBounds(verts, nverts, bmin, bmax);
+
+ rcConfig cfg;
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.cs = p_nav_mesh->get_cell_size();
+ cfg.ch = p_nav_mesh->get_cell_height();
+ cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope();
+ cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch);
+ cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch);
+ cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs);
+ cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size());
+ cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error();
+ cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
+ cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
+ cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
+ cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance();
+ cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
+
+ cfg.bmin[0] = bmin[0];
+ cfg.bmin[1] = bmin[1];
+ cfg.bmin[2] = bmin[2];
+ cfg.bmax[0] = bmax[0];
+ cfg.bmax[1] = bmax[1];
+ cfg.bmax[2] = bmax[2];
+
+ ep->step(TTR("Calculating grid size..."), 2);
+ rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
+
+ ep->step(TTR("Creating heightfield..."), 3);
+ hf = rcAllocHeightfield();
+
+ ERR_FAIL_COND(!hf);
+ ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch));
+
+ ep->step(TTR("Marking walkable triangles..."), 4);
+ {
+ Vector<unsigned char> tri_areas;
+ tri_areas.resize(ntris);
+
+ ERR_FAIL_COND(tri_areas.size() == 0);
+
+ memset(tri_areas.ptrw(), 0, ntris * sizeof(unsigned char));
+ rcMarkWalkableTriangles(&ctx, cfg.walkableSlopeAngle, verts, nverts, tris, ntris, tri_areas.ptrw());
+
+ ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb));
+ }
+
+ if (p_nav_mesh->get_filter_low_hanging_obstacles())
+ rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf);
+ if (p_nav_mesh->get_filter_ledge_spans())
+ rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf);
+ if (p_nav_mesh->get_filter_walkable_low_height_spans())
+ rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
+
+ ep->step(TTR("Constructing compact heightfield..."), 5);
+
+ chf = rcAllocCompactHeightfield();
+
+ ERR_FAIL_COND(!chf);
+ ERR_FAIL_COND(!rcBuildCompactHeightfield(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf, *chf));
+
+ rcFreeHeightField(hf);
+ hf = 0;
+
+ ep->step(TTR("Eroding walkable area..."), 6);
+ ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf));
+
+ ep->step(TTR("Partitioning..."), 7);
+ if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
+ ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
+ ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
+ } else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
+ ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
+ } else {
+ ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea));
+ }
+
+ ep->step(TTR("Creating contours..."), 8);
+
+ cset = rcAllocContourSet();
+
+ ERR_FAIL_COND(!cset);
+ ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset));
+
+ ep->step(TTR("Creating polymesh..."), 9);
+
+ poly_mesh = rcAllocPolyMesh();
+ ERR_FAIL_COND(!poly_mesh);
+ ERR_FAIL_COND(!rcBuildPolyMesh(&ctx, *cset, cfg.maxVertsPerPoly, *poly_mesh));
+
+ detail_mesh = rcAllocPolyMeshDetail();
+ ERR_FAIL_COND(!detail_mesh);
+ ERR_FAIL_COND(!rcBuildPolyMeshDetail(&ctx, *poly_mesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *detail_mesh));
+
+ rcFreeCompactHeightfield(chf);
+ chf = 0;
+ rcFreeContourSet(cset);
+ cset = 0;
+
+ ep->step(TTR("Converting to native navigation mesh..."), 10);
+
+ _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh);
+
+ rcFreePolyMesh(poly_mesh);
+ poly_mesh = 0;
+ rcFreePolyMeshDetail(detail_mesh);
+ detail_mesh = 0;
+}
+
+void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) {
+
+ ERR_FAIL_COND(!p_nav_mesh.is_valid());
+
+ EditorProgress ep("bake", TTR("Navigation Mesh Generator Setup:"), 11);
+ ep.step(TTR("Parsing Geometry..."), 0);
+
+ Vector<float> vertices;
+ Vector<int> indices;
+
+ _parse_geometry(Object::cast_to<Spatial>(p_node)->get_global_transform().affine_inverse(), p_node, vertices, indices);
+
+ if (vertices.size() > 0 && indices.size() > 0) {
+
+ rcHeightfield *hf = NULL;
+ rcCompactHeightfield *chf = NULL;
+ rcContourSet *cset = NULL;
+ rcPolyMesh *poly_mesh = NULL;
+ rcPolyMeshDetail *detail_mesh = NULL;
+
+ _build_recast_navigation_mesh(p_nav_mesh, &ep, hf, chf, cset, poly_mesh, detail_mesh, vertices, indices);
+
+ rcFreeHeightField(hf);
+ hf = 0;
+
+ rcFreeCompactHeightfield(chf);
+ chf = 0;
+
+ rcFreeContourSet(cset);
+ cset = 0;
+
+ rcFreePolyMesh(poly_mesh);
+ poly_mesh = 0;
+
+ rcFreePolyMeshDetail(detail_mesh);
+ detail_mesh = 0;
+ }
+ ep.step(TTR("Done!"), 11);
+}
+
+void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) {
+ if (p_nav_mesh.is_valid()) {
+ p_nav_mesh->clear_polygons();
+ p_nav_mesh->set_vertices(PoolVector<Vector3>());
+ }
+}
diff --git a/modules/recast/navigation_mesh_generator.h b/modules/recast/navigation_mesh_generator.h
new file mode 100644
index 0000000000..3588539ef1
--- /dev/null
+++ b/modules/recast/navigation_mesh_generator.h
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* navigation_mesh_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 NAVIGATION_MESH_GENERATOR_H
+#define NAVIGATION_MESH_GENERATOR_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "os/thread.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/navigation_mesh.h"
+#include "scene/resources/shape.h"
+
+#include <Recast.h>
+
+class NavigationMeshGenerator {
+protected:
+ static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies);
+ static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
+ static void _parse_geometry(const Transform &p_base_inverse, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices);
+
+ static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
+ static void _build_recast_navigation_mesh(Ref<NavigationMesh> p_nav_mesh, EditorProgress *ep,
+ rcHeightfield *hf, rcCompactHeightfield *chf, rcContourSet *cset, rcPolyMesh *poly_mesh,
+ rcPolyMeshDetail *detail_mesh, Vector<float> &vertices, Vector<int> &indices);
+
+public:
+ static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node);
+ static void clear(Ref<NavigationMesh> p_nav_mesh);
+};
+
+#endif // NAVIGATION_MESH_GENERATOR_H
diff --git a/modules/recast/register_types.cpp b/modules/recast/register_types.cpp
index 913857c591..f2f18fc86f 100644
--- a/modules/recast/register_types.cpp
+++ b/modules/recast/register_types.cpp
@@ -30,5 +30,10 @@
#include "register_types.h"
-void register_recast_types() {}
+#include "navigation_mesh_editor_plugin.h"
+
+void register_recast_types() {
+ EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
+}
+
void unregister_recast_types() {}
diff --git a/modules/regex/config.py b/modules/regex/config.py
index cb2da26738..42cfe3b43c 100644
--- a/modules/regex/config.py
+++ b/modules/regex/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/squish/config.py b/modules/squish/config.py
index 97c95999c8..098f1eafa9 100644
--- a/modules/squish/config.py
+++ b/modules/squish/config.py
@@ -1,9 +1,5 @@
-def can_build(platform):
- return True
+def can_build(env, platform):
+ return env['tools']
def configure(env):
- # Tools only, disabled for non-tools
- # TODO: Find a cleaner way to achieve that
- if not env['tools']:
- env['module_squish_enabled'] = False
- env.disabled_modules.append("squish")
+ pass
diff --git a/modules/stb_vorbis/config.py b/modules/stb_vorbis/config.py
index defe8d0c94..d75e41797a 100644
--- a/modules/stb_vorbis/config.py
+++ b/modules/stb_vorbis/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/svg/SCsub b/modules/svg/SCsub
index e12abac8c1..a41e0703bd 100644
--- a/modules/svg/SCsub
+++ b/modules/svg/SCsub
@@ -1,7 +1,6 @@
#!/usr/bin/env python
Import('env')
-from compat import isbasestring
# Thirdparty source files
thirdparty_dir = "#thirdparty/nanosvg/"
@@ -10,23 +9,7 @@ thirdparty_sources = [
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-# env.add_source_files(env.modules_sources, thirdparty_sources)
-
-lib = env.add_library("svg_builtin", thirdparty_sources)
-
-# Needs to be appended to arrive after libscene in the linker call,
-# but we don't want it to arrive *after* system libs, so manual hack
-# LIBS contains first SCons Library objects ("SCons.Node.FS.File object")
-# and then plain strings for system library. We insert between the two.
-inserted = False
-for idx, linklib in enumerate(env["LIBS"]):
- if isbasestring(linklib): # first system lib such as "X11", otherwise SCons lib object
- env["LIBS"].insert(idx, lib)
- inserted = True
- break
-if not inserted:
- env.Append(LIBS=[lib])
-
+env.add_source_files(env.modules_sources, thirdparty_sources)
env.Append(CPPPATH=[thirdparty_dir])
env.Append(CCFLAGS=["-DSVG_ENABLED"])
diff --git a/modules/svg/config.py b/modules/svg/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/svg/config.py
+++ b/modules/svg/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/tga/config.py b/modules/tga/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/tga/config.py
+++ b/modules/tga/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/thekla_unwrap/config.py b/modules/thekla_unwrap/config.py
index b1ce7d4b91..bd092bdc16 100644
--- a/modules/thekla_unwrap/config.py
+++ b/modules/thekla_unwrap/config.py
@@ -1,7 +1,5 @@
-def can_build(platform):
- return platform != "android" and platform != "ios"
+def can_build(env, platform):
+ return (env['tools'] and platform not in ["android", "ios"])
def configure(env):
- if not env['tools']:
- env['builtin_thekla_atlas'] = False
- env.disabled_modules.append("thekla_unwrap")
+ pass
diff --git a/modules/theora/config.py b/modules/theora/config.py
index 34d34f8be2..7504166237 100644
--- a/modules/theora/config.py
+++ b/modules/theora/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py
index e12bb398ce..098f1eafa9 100644
--- a/modules/tinyexr/config.py
+++ b/modules/tinyexr/config.py
@@ -1,9 +1,5 @@
-def can_build(platform):
- return True
+def can_build(env, platform):
+ return env['tools']
def configure(env):
- # Tools only, disabled for non-tools
- # TODO: Find a cleaner way to achieve that
- if not env['tools']:
- env['module_tinyexr_enabled'] = False
- env.disabled_modules.append("tinyexr")
+ pass
diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py
index 6b1ce41014..07a0450734 100644
--- a/modules/visual_script/config.py
+++ b/modules/visual_script/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 318fb7fb9c..9331092171 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -1971,11 +1971,11 @@ Ref<Script> VisualScriptInstance::get_script() const {
return script;
}
-ScriptInstance::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
+MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method);
if (!E) {
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) {
@@ -1987,12 +1987,12 @@ ScriptInstance::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_m
}
}
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
-ScriptInstance::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const {
+MultiplayerAPI::RPCMode VisualScriptInstance::get_rset_mode(const StringName &p_variable) const {
- return RPC_MODE_DISABLED;
+ return MultiplayerAPI::RPC_MODE_DISABLED;
}
void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_owner) {
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index a15360ad39..aaa6dfea11 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -433,8 +433,8 @@ public:
virtual ScriptLanguage *get_language();
- virtual RPCMode get_rpc_mode(const StringName &p_method) const;
- virtual RPCMode get_rset_mode(const StringName &p_variable) const;
+ virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const;
+ virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const;
VisualScriptInstance();
~VisualScriptInstance();
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 4803f29519..8b7b809ec0 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -93,7 +93,7 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value
}
if (p_name == "rpc/mode") {
- rpc_mode = ScriptInstance::RPCMode(int(p_value));
+ rpc_mode = MultiplayerAPI::RPCMode(int(p_value));
return true;
}
@@ -267,11 +267,11 @@ int VisualScriptFunction::get_argument_count() const {
return arguments.size();
}
-void VisualScriptFunction::set_rpc_mode(ScriptInstance::RPCMode p_mode) {
+void VisualScriptFunction::set_rpc_mode(MultiplayerAPI::RPCMode p_mode) {
rpc_mode = p_mode;
}
-ScriptInstance::RPCMode VisualScriptFunction::get_rpc_mode() const {
+MultiplayerAPI::RPCMode VisualScriptFunction::get_rpc_mode() const {
return rpc_mode;
}
@@ -319,7 +319,7 @@ VisualScriptFunction::VisualScriptFunction() {
stack_size = 256;
stack_less = false;
sequenced = true;
- rpc_mode = ScriptInstance::RPC_MODE_DISABLED;
+ rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
}
void VisualScriptFunction::set_stack_less(bool p_enable) {
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index a0bc35dd92..9bfbd46e47 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -46,7 +46,7 @@ class VisualScriptFunction : public VisualScriptNode {
bool stack_less;
int stack_size;
- ScriptInstance::RPCMode rpc_mode;
+ MultiplayerAPI::RPCMode rpc_mode;
bool sequenced;
protected:
@@ -93,8 +93,8 @@ public:
void set_return_type(Variant::Type p_type);
Variant::Type get_return_type() const;
- void set_rpc_mode(ScriptInstance::RPCMode p_mode);
- ScriptInstance::RPCMode get_rpc_mode() const;
+ void set_rpc_mode(MultiplayerAPI::RPCMode p_mode);
+ MultiplayerAPI::RPCMode get_rpc_mode() const;
virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance);
diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/vorbis/config.py
+++ b/modules/vorbis/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/webm/config.py b/modules/webm/config.py
index dcae4447d5..72a4073423 100644
--- a/modules/webm/config.py
+++ b/modules/webm/config.py
@@ -1,5 +1,5 @@
-def can_build(platform):
- return platform != 'iphone'
+def can_build(env, platform):
+ return platform not in ['iphone']
def configure(env):
pass
diff --git a/modules/webp/config.py b/modules/webp/config.py
index 5f133eba90..1c8cd12a2d 100644
--- a/modules/webp/config.py
+++ b/modules/webp/config.py
@@ -1,4 +1,4 @@
-def can_build(platform):
+def can_build(env, platform):
return True
def configure(env):
diff --git a/modules/websocket/config.py b/modules/websocket/config.py
index 399ca88fc1..f59ef432b4 100644
--- a/modules/websocket/config.py
+++ b/modules/websocket/config.py
@@ -1,8 +1,6 @@
-
-def can_build(platform):
+def can_build(env, platform):
return True
-
def configure(env):
pass