summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp4
-rw-r--r--modules/csg/csg_shape.cpp8
-rw-r--r--modules/csg/doc_classes/CSGShape.xml2
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp4
-rw-r--r--modules/dds/texture_loader_dds.cpp5
-rw-r--r--modules/etc/texture_loader_pkm.cpp2
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp4
-rw-r--r--modules/gdscript/gdscript_parser.cpp3
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp4
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h2
-rw-r--r--modules/jpg/image_loader_jpegd.cpp4
-rw-r--r--modules/mono/build_scripts/godot_tools_build.py6
-rw-r--r--modules/mono/build_scripts/solution_builder.py18
-rw-r--r--modules/mono/class_db_api_json.cpp242
-rw-r--r--modules/mono/class_db_api_json.h39
-rw-r--r--modules/mono/csharp_script.cpp99
-rw-r--r--modules/mono/csharp_script.h5
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs107
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.sln35
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs18
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs23
-rw-r--r--modules/mono/editor/bindings_generator.cpp26
-rw-r--r--modules/mono/glue/base_object_glue.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp8
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp25
-rw-r--r--modules/mono/utils/path_utils.cpp127
-rw-r--r--modules/mono/utils/path_utils.h32
-rw-r--r--modules/mono/utils/string_utils.cpp2
-rw-r--r--modules/opus/audio_stream_opus.cpp2
-rw-r--r--modules/pvr/texture_loader_pvr.cpp6
-rw-r--r--modules/recast/register_types.cpp7
-rw-r--r--modules/squish/image_compress_squish.cpp4
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/svg/image_loader_svg.cpp2
-rw-r--r--modules/tga/image_loader_tga.cpp2
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp2
-rw-r--r--modules/visual_script/visual_script.cpp4
-rw-r--r--modules/visual_script/visual_script_editor.cpp148
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp7
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp1
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/webp/image_loader_webp.cpp8
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h2
-rw-r--r--modules/websocket/wsl_client.cpp1
-rw-r--r--modules/websocket/wsl_server.cpp33
-rw-r--r--modules/websocket/wsl_server.h6
50 files changed, 841 insertions, 273 deletions
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index 093e2f3006..f23c66dbcf 100644
--- a/modules/assimp/editor_scene_importer_assimp.cpp
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -854,7 +854,7 @@ Ref<Material> EditorSceneImporterAssimp::_generate_material_from_index(ImportSta
if (found) {
Ref<Texture> texture = _load_texture(state, path);
- if (texture != NULL) {
+ if (texture.is_valid()) {
_set_texture_mapping_mode(map_mode, texture);
mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 085cce9733..8d21b25b20 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -728,12 +728,12 @@ bool RigidBodyBullet::is_axis_locked(PhysicsServer::BodyAxis p_axis) const {
void RigidBodyBullet::reload_axis_lock() {
- btBody->setLinearFactor(btVector3(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_X), !is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Y), !is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Z)));
+ btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Z))));
if (PhysicsServer::BODY_MODE_CHARACTER == mode) {
/// When character angular is always locked
btBody->setAngularFactor(btVector3(0., 0., 0.));
} else {
- btBody->setAngularFactor(btVector3(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_X), !is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Y), !is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Z)));
+ btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Z))));
}
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 0a714dcc6c..23725c4960 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -436,10 +436,10 @@ void CSGShape::_update_shape() {
}
// unset write access
- surfaces.write[i].verticesw = PoolVector<Vector3>::Write();
- surfaces.write[i].normalsw = PoolVector<Vector3>::Write();
- surfaces.write[i].uvsw = PoolVector<Vector2>::Write();
- surfaces.write[i].tansw = PoolVector<float>::Write();
+ surfaces.write[i].verticesw.release();
+ surfaces.write[i].normalsw.release();
+ surfaces.write[i].uvsw.release();
+ surfaces.write[i].tansw.release();
if (surfaces[i].last_added == 0)
continue;
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index 91f54f8246..755d8df67e 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -92,7 +92,7 @@
Only intersecting geometry remains, the rest is removed.
</constant>
<constant name="OPERATION_SUBTRACTION" value="2" enum="Operation">
- The second shape is susbtracted from the first, leaving a dent with it's shape.
+ The second shape is subtracted from the first, leaving a dent with its shape.
</constant>
</constants>
</class>
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index 024e9ffc3b..17b0038780 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -388,8 +388,8 @@ void image_decompress_cvtt(Image *p_image) {
h >>= 1;
}
- rb = PoolVector<uint8_t>::Read();
- wb = PoolVector<uint8_t>::Write();
+ rb.release();
+ wb.release();
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 197b41b30c..4628bd9a5b 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -251,7 +251,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
src_data.resize(size);
PoolVector<uint8_t>::Write wb = src_data.write();
f->get_buffer(wb.ptr(), size);
- wb = PoolVector<uint8_t>::Write();
} else if (info.palette) {
@@ -296,8 +295,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
if (colsize == 4)
wb[dst_ofs + 3] = palette[src_ofs + 3];
}
-
- wb = PoolVector<uint8_t>::Write();
} else {
//uncompressed generic...
@@ -444,8 +441,6 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
default: {
}
}
-
- wb = PoolVector<uint8_t>::Write();
}
Ref<Image> img = memnew(Image(width, height, mipmaps - 1, info.format, src_data));
diff --git a/modules/etc/texture_loader_pkm.cpp b/modules/etc/texture_loader_pkm.cpp
index f302834222..ff925480b8 100644
--- a/modules/etc/texture_loader_pkm.cpp
+++ b/modules/etc/texture_loader_pkm.cpp
@@ -80,7 +80,7 @@ RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path,
src_data.resize(size);
PoolVector<uint8_t>::Write wb = src_data.write();
f->get_buffer(wb.ptr(), size);
- wb = PoolVector<uint8_t>::Write();
+ wb.release();
int mipmaps = h.format;
int width = h.origWidth;
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 62b65fe96b..963b40529d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -370,8 +370,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
bool default_theme = text_editor_color_theme == "Default";
bool dark_theme = settings->is_dark_theme();
- function_definition_color = Color::html(default_theme ? "#01e1ff" : dark_theme ? "#01e1ff" : "#00a5ba");
- node_path_color = Color::html(default_theme ? "#64c15a" : dark_theme ? "64c15a" : "#518b4b");
+ function_definition_color = default_theme ? Color(0.0, 0.88, 1.0) : dark_theme ? Color(0.0, 0.88, 1.0) : Color(0.0, 0.65, 0.73);
+ node_path_color = default_theme ? Color(0.39, 0.76, 0.35) : dark_theme ? Color(0.39, 0.76, 0.35) : Color(0.32, 0.55, 0.29);
EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index c5c86fda0a..80da606967 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -5077,6 +5077,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
+ } else if (tokenizer->is_token_literal(0, true)) {
+ _set_error("Unexpected identifier");
+ return;
}
if (enum_name != "") {
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 20e454c218..5a21833ffa 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -345,7 +345,7 @@ void GridMapEditor::_validate_selection() {
_update_selection_transform();
}
-void GridMapEditor::_set_selection(bool p_active, const Vector3 p_begin, const Vector3 p_end) {
+void GridMapEditor::_set_selection(bool p_active, const Vector3 &p_begin, const Vector3 &p_end) {
selection.active = p_active;
selection.begin = p_begin;
@@ -578,7 +578,7 @@ void GridMapEditor::_update_paste_indicator() {
return;
}
- Vector3 center = 0.5 * Vector3(node->get_center_x(), node->get_center_y(), node->get_center_z());
+ Vector3 center = 0.5 * Vector3(float(node->get_center_x()), float(node->get_center_y()), float(node->get_center_z()));
Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size();
Transform xf;
xf.scale(scale);
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index da36165d4e..b9be925ff7 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -222,7 +222,7 @@ class GridMapEditor : public VBoxContainer {
void _do_paste();
void _update_selection_transform();
void _validate_selection();
- void _set_selection(bool p_active, const Vector3 p_begin = Vector3(), const Vector3 p_end = Vector3());
+ void _set_selection(bool p_active, const Vector3 &p_begin = Vector3(), const Vector3 &p_end = Vector3());
void _floor_changed(float p_value);
void _floor_mouse_exited();
diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp
index 5493223cb0..dcd8b8aebd 100644
--- a/modules/jpg/image_loader_jpegd.cpp
+++ b/modules/jpg/image_loader_jpegd.cpp
@@ -96,7 +96,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
else
fmt = Image::FORMAT_RGB8;
- dw = PoolVector<uint8_t>::Write();
+ dw.release();
p_image->create(image_width, image_height, 0, fmt, data);
return OK;
@@ -117,8 +117,6 @@ Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
Error err = jpeg_load_image_from_buffer(p_image.ptr(), w.ptr(), src_image_len);
- w = PoolVector<uint8_t>::Write();
-
return err;
}
diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py
index f66ffdb573..c47cfc8a38 100644
--- a/modules/mono/build_scripts/godot_tools_build.py
+++ b/modules/mono/build_scripts/godot_tools_build.py
@@ -87,7 +87,7 @@ def build(env_mono):
target_filenames = ['GodotTools.dll', 'GodotTools.BuildLogger.dll', 'GodotTools.ProjectEditor.dll', 'DotNet.Glob.dll', 'GodotTools.Core.dll']
if env_mono['target'] == 'debug':
- target_filenames += ['GodotTools.pdb', 'GodotTools.BuildLogger.dll', 'GodotTools.ProjectEditor.dll', 'GodotTools.Core.dll']
+ target_filenames += ['GodotTools.pdb', 'GodotTools.BuildLogger.pdb', 'GodotTools.ProjectEditor.pdb', 'GodotTools.Core.pdb']
targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames]
@@ -102,6 +102,10 @@ def build_project_editor_only(env_mono):
editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools')
target_filenames = ['GodotTools.ProjectEditor.dll', 'DotNet.Glob.dll', 'GodotTools.Core.dll']
+
+ if env_mono['target'] == 'debug':
+ target_filenames += ['GodotTools.ProjectEditor.pdb', 'GodotTools.Core.pdb']
+
targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames]
cmd = env_mono.CommandNoCache(targets, [], build_godot_tools_project_editor, module_dir=os.getcwd())
diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py
index 9f549a10ed..d1529a64d2 100644
--- a/modules/mono/build_scripts/solution_builder.py
+++ b/modules/mono/build_scripts/solution_builder.py
@@ -108,10 +108,14 @@ def find_msbuild_windows(env):
if not mono_root:
raise RuntimeError('Cannot find mono root directory')
- framework_path = os.path.join(mono_root, 'lib', 'mono', '4.5')
mono_bin_dir = os.path.join(mono_root, 'bin')
msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat')
+ msbuild_tools_path = find_msbuild_tools_path_reg()
+
+ if msbuild_tools_path:
+ return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), {})
+
if os.path.isfile(msbuild_mono):
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
# building with Mono's MSBuild. They must point to the batch files
@@ -121,12 +125,7 @@ def find_msbuild_windows(env):
'VbcToolExe': os.path.join(mono_bin_dir, 'vbc.bat'),
'FscToolExe': os.path.join(mono_bin_dir, 'fsharpc.bat')
}
- return (msbuild_mono, framework_path, mono_msbuild_env)
-
- msbuild_tools_path = find_msbuild_tools_path_reg()
-
- if msbuild_tools_path:
- return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
+ return (msbuild_mono, mono_msbuild_env)
return None
@@ -172,7 +171,6 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
global verbose
verbose = env['verbose']
- framework_path = ''
msbuild_env = os.environ.copy()
# Needed when running from Developer Command Prompt for VS
@@ -185,8 +183,7 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
if msbuild_info is None:
raise RuntimeError('Cannot find MSBuild executable')
msbuild_path = msbuild_info[0]
- framework_path = msbuild_info[1]
- msbuild_env.update(msbuild_info[2])
+ msbuild_env.update(msbuild_info[1])
else:
msbuild_path = find_msbuild_unix('msbuild')
if msbuild_path is None:
@@ -212,7 +209,6 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
# Build solution
msbuild_args = [solution_path, '/p:Configuration=' + build_config]
- msbuild_args += ['/p:FrameworkPathOverride=' + framework_path] if framework_path else []
msbuild_args += extra_msbuild_args
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name='msbuild')
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
new file mode 100644
index 0000000000..71ccdb7aab
--- /dev/null
+++ b/modules/mono/class_db_api_json.cpp
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* class_db_api_json.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 "class_db_api_json.h"
+
+#include "core/io/json.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
+#include "core/version.h"
+
+void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
+ Dictionary classes_dict;
+
+ List<StringName> names;
+
+ const StringName *k = NULL;
+
+ while ((k = ClassDB::classes.next(k))) {
+
+ names.push_back(*k);
+ }
+ //must be alphabetically sorted for hash to compute
+ names.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+
+ ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get());
+ ERR_FAIL_COND(!t);
+ if (t->api != p_api || !t->exposed)
+ continue;
+
+ Dictionary class_dict;
+ classes_dict[t->name] = class_dict;
+
+ class_dict["inherits"] = t->inherits;
+
+ { //methods
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->method_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array methods;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary method_dict;
+ methods.push_back(method_dict);
+
+ MethodBind *mb = t->method_map[F->get()];
+ method_dict["name"] = mb->get_name();
+ method_dict["argument_count"] = mb->get_argument_count();
+ method_dict["return_type"] = mb->get_argument_type(-1);
+
+ Array arguments;
+ method_dict["arguments"] = arguments;
+
+ for (int i = 0; i < mb->get_argument_count(); i++) {
+ Dictionary argument_dict;
+ arguments.push_back(argument_dict);
+ const PropertyInfo info = mb->get_argument_info(i);
+ argument_dict["type"] = info.type;
+ argument_dict["name"] = info.name;
+ argument_dict["hint"] = info.hint;
+ argument_dict["hint_string"] = info.hint_string;
+ }
+
+ method_dict["default_argument_count"] = mb->get_default_argument_count();
+
+ Array default_arguments;
+ method_dict["default_arguments"] = default_arguments;
+
+ for (int i = 0; i < mb->get_default_argument_count(); i++) {
+ Dictionary default_argument_dict;
+ default_arguments.push_back(default_argument_dict);
+ //hash should not change, i hope for tis
+ Variant da = mb->get_default_argument(i);
+ default_argument_dict["value"] = da;
+ }
+
+ method_dict["hint_flags"] = mb->get_hint_flags();
+ }
+
+ if (!methods.empty()) {
+ class_dict["methods"] = methods;
+ }
+ }
+
+ { //constants
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->constant_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array constants;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary constant_dict;
+ constants.push_back(constant_dict);
+
+ constant_dict["name"] = F->get();
+ constant_dict["value"] = t->constant_map[F->get()];
+ }
+
+ if (!constants.empty()) {
+ class_dict["constants"] = constants;
+ }
+ }
+
+ { //signals
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->signal_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array signals;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary signal_dict;
+ signals.push_back(signal_dict);
+
+ MethodInfo &mi = t->signal_map[F->get()];
+ signal_dict["name"] = F->get();
+
+ Array arguments;
+ signal_dict["arguments"] = arguments;
+ for (int i = 0; i < mi.arguments.size(); i++) {
+ Dictionary argument_dict;
+ arguments.push_back(argument_dict);
+ argument_dict["type"] = mi.arguments[i].type;
+ }
+ }
+
+ if (!signals.empty()) {
+ class_dict["signals"] = signals;
+ }
+ }
+
+ { //properties
+
+ List<StringName> snames;
+
+ k = NULL;
+
+ while ((k = t->property_setget.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ Array properties;
+
+ for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ Dictionary property_dict;
+ properties.push_back(property_dict);
+
+ ClassDB::PropertySetGet *psg = t->property_setget.getptr(F->get());
+
+ property_dict["name"] = F->get();
+ property_dict["setter"] = psg->setter;
+ property_dict["getter"] = psg->getter;
+ }
+
+ if (!properties.empty()) {
+ class_dict["property_setget"] = properties;
+ }
+ }
+
+ Array property_list;
+
+ //property list
+ for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
+ Dictionary property_dict;
+ property_list.push_back(property_dict);
+
+ property_dict["name"] = F->get().name;
+ property_dict["type"] = F->get().type;
+ property_dict["hint"] = F->get().hint;
+ property_dict["hint_string"] = F->get().hint_string;
+ property_dict["usage"] = F->get().usage;
+ }
+
+ if (!property_list.empty()) {
+ class_dict["property_list"] = property_list;
+ }
+ }
+
+ FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE);
+ ERR_FAIL_COND(!f);
+ f->store_string(JSON::print(classes_dict, /*indent: */ "\t"));
+ f->close();
+
+ print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file));
+}
diff --git a/modules/mono/class_db_api_json.h b/modules/mono/class_db_api_json.h
new file mode 100644
index 0000000000..0aa9c20930
--- /dev/null
+++ b/modules/mono/class_db_api_json.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* class_db_api_json.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 CLASS_DB_API_JSON_H
+#define CLASS_DB_API_JSON_H
+
+#include "core/class_db.h"
+#include "core/ustring.h"
+
+void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api);
+
+#endif // CLASS_DB_API_JSON_H
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index b5c91a8585..1add697997 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -44,6 +44,10 @@
#include "editor/editor_node.h"
#endif
+#ifdef DEBUG_METHODS_ENABLED
+#include "class_db_api_json.h"
+#endif
+
#include "editor/editor_internal_calls.h"
#include "godotsharp_dirs.h"
#include "mono_gd/gd_mono_class.h"
@@ -98,6 +102,15 @@ Error CSharpLanguage::execute_file(const String &p_path) {
void CSharpLanguage::init() {
+#ifdef DEBUG_METHODS_ENABLED
+ if (OS::get_singleton()->get_cmdline_args().find("--class_db_to_json")) {
+ class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE);
+#ifdef TOOLS_ENABLED
+ class_db_api_to_json("user://class_db_api_editor.json", ClassDB::API_EDITOR);
+#endif
+ }
+#endif
+
gdmono = memnew(GDMono);
gdmono->initialize();
@@ -867,17 +880,26 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
script->reload(p_soft_reload);
script->update_exports();
+
+ if (!script->valid) {
+ script->pending_reload_instances.clear();
+ continue;
+ }
} else {
const StringName &class_namespace = script->tied_class_namespace_for_reload;
const StringName &class_name = script->tied_class_name_for_reload;
GDMonoAssembly *project_assembly = gdmono->get_project_assembly();
- GDMonoAssembly *tools_assembly = gdmono->get_tools_assembly();
// Search in project and tools assemblies first as those are the most likely to have the class
GDMonoClass *script_class = (project_assembly ? project_assembly->get_class(class_namespace, class_name) : NULL);
+
+#ifdef TOOLS_ENABLED
if (!script_class) {
+ GDMonoAssembly *tools_assembly = gdmono->get_tools_assembly();
script_class = (tools_assembly ? tools_assembly->get_class(class_namespace, class_name) : NULL);
}
+#endif
+
if (!script_class) {
script_class = gdmono->get_class(class_namespace, class_name);
}
@@ -897,12 +919,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
GDMonoClass *native = GDMonoUtils::get_class_native_base(script_class);
- Ref<CSharpScript> new_script = CSharpScript::create_for_managed_type(script_class, native);
- CRASH_COND(new_script.is_null());
-
- new_script->pending_reload_instances = script->pending_reload_instances;
- new_script->pending_reload_state = script->pending_reload_state;
- script = new_script;
+ CSharpScript::initialize_for_managed_type(script, script_class, native);
}
String native_name = NATIVE_GDMONOCLASS_NAME(script->native);
@@ -953,7 +970,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
CRASH_COND(si != NULL);
#endif
// Re-create script instance
-
obj->set_script(script.get_ref_ptr()); // will create the script instance as well
}
}
@@ -1203,7 +1219,9 @@ CSharpLanguage::CSharpLanguage() {
scripts_metadata_invalidated = true;
+#ifdef TOOLS_ENABLED
godotsharp_editor = NULL;
+#endif
}
CSharpLanguage::~CSharpLanguage() {
@@ -2144,7 +2162,6 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
propnames.push_back(E->get());
}
}
-#endif
void CSharpScript::_update_member_info_no_exports() {
@@ -2191,6 +2208,7 @@ void CSharpScript::_update_member_info_no_exports() {
}
}
}
+#endif
bool CSharpScript::_update_exports() {
@@ -2673,35 +2691,46 @@ void CSharpScript::_bind_methods() {
Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) {
- // This method should not fail
+ // This method should not fail, only assertions allowed
CRASH_COND(p_class == NULL);
// TODO OPTIMIZE: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time
Ref<CSharpScript> script = memnew(CSharpScript);
- script->name = p_class->get_name();
- script->script_class = p_class;
- script->native = p_native;
+ initialize_for_managed_type(script, p_class, p_native);
- CRASH_COND(script->native == NULL);
+ return script;
+}
+
+void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native) {
+
+ // This method should not fail, only assertions allowed
+
+ CRASH_COND(p_class == NULL);
- GDMonoClass *base = script->script_class->get_parent_class();
+ p_script->name = p_class->get_name();
+ p_script->script_class = p_class;
+ p_script->native = p_native;
- if (base != script->native)
- script->base = base;
+ CRASH_COND(p_script->native == NULL);
- script->valid = true;
- script->tool = script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
+ GDMonoClass *base = p_script->script_class->get_parent_class();
- if (!script->tool) {
- GDMonoClass *nesting_class = script->script_class->get_nesting_class();
- script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
+ if (base != p_script->native)
+ p_script->base = base;
+
+ p_script->valid = true;
+ p_script->tool = p_script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
+
+ if (!p_script->tool) {
+ GDMonoClass *nesting_class = p_script->script_class->get_nesting_class();
+ p_script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
}
#if TOOLS_ENABLED
- if (!script->tool) {
- script->tool = script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
+ if (!p_script->tool) {
+ p_script->tool = p_script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
}
#endif
@@ -2710,10 +2739,10 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
// Native base methods must be fetched before the current class.
// Not needed if the script class itself is a native class.
- if (script->script_class != script->native) {
- GDMonoClass *native_top = script->native;
+ if (p_script->script_class != p_script->native) {
+ GDMonoClass *native_top = p_script->native;
while (native_top) {
- native_top->fetch_methods_with_godot_api_checks(script->native);
+ native_top->fetch_methods_with_godot_api_checks(p_script->native);
if (native_top == CACHED_CLASS(GodotObject))
break;
@@ -2723,19 +2752,19 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
}
#endif
- script->script_class->fetch_methods_with_godot_api_checks(script->native);
+ p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
// Need to fetch method from base classes as well
- GDMonoClass *top = script->script_class;
- while (top && top != script->native) {
- top->fetch_methods_with_godot_api_checks(script->native);
+ GDMonoClass *top = p_script->script_class;
+ while (top && top != p_script->native) {
+ top->fetch_methods_with_godot_api_checks(p_script->native);
top = top->get_parent_class();
}
- script->load_script_signals(script->script_class, script->native);
- script->_update_member_info_no_exports();
-
- return script;
+ p_script->load_script_signals(p_script->script_class, p_script->native);
+#ifdef TOOLS_ENABLED
+ p_script->_update_member_info_no_exports();
+#endif
}
bool CSharpScript::can_instance() const {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index d31a1c35d2..eb168f344d 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -121,6 +121,7 @@ class CSharpScript : public Script {
bool placeholder_fallback_enabled;
bool exports_invalidated;
void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
+ void _update_member_info_no_exports();
virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
#endif
@@ -131,7 +132,6 @@ class CSharpScript : public Script {
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
bool _get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> &params);
- void _update_member_info_no_exports();
bool _update_exports();
#ifdef TOOLS_ENABLED
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
@@ -144,6 +144,7 @@ class CSharpScript : public Script {
// Do not use unless you know what you are doing
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
+ static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
protected:
static void _bind_methods();
@@ -354,7 +355,9 @@ public:
_FORCE_INLINE_ static CSharpLanguage *get_singleton() { return singleton; }
+#ifdef TOOLS_ENABLED
_FORCE_INLINE_ EditorPlugin *get_godotsharp_editor() const { return godotsharp_editor; }
+#endif
static void release_script_gchandle(Ref<MonoGCHandle> &p_gchandle);
static void release_script_gchandle(MonoObject *p_expected_obj, Ref<MonoGCHandle> &p_gchandle);
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
index 7cf58b6755..4f21871f1a 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
@@ -91,13 +91,11 @@ namespace GodotTools.ProjectEditor
var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", CoreApiProjectName + ".dll"));
- coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProjectName + ".dll"));
coreApiRef.AddMetadata("Private", "False");
var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", EditorApiProjectName + ".dll"));
- editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProjectName + ".dll"));
editorApiRef.AddMetadata("Private", "False");
GenAssemblyInfoFile(root, dir, name);
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 22cf89695d..1edc426e00 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -1,6 +1,8 @@
using GodotTools.Core;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
+using System.Linq;
using DotNet.Globbing;
using Microsoft.Build.Construction;
@@ -12,6 +14,8 @@ namespace GodotTools.ProjectEditor
{
var dir = Directory.GetParent(projectPath).FullName;
var root = ProjectRootElement.Open(projectPath);
+ Debug.Assert(root != null);
+
var normalizedInclude = include.RelativeToPath(dir).Replace("/", "\\");
if (root.AddItemChecked(itemType, normalizedInclude))
@@ -23,7 +27,8 @@ namespace GodotTools.ProjectEditor
string[] files = Directory.GetFiles(rootDirectory, mask, SearchOption.AllDirectories);
// We want relative paths
- for (int i = 0; i < files.Length; i++) {
+ for (int i = 0; i < files.Length; i++)
+ {
files[i] = files[i].RelativeToPath(rootDirectory);
}
@@ -35,7 +40,7 @@ namespace GodotTools.ProjectEditor
var result = new List<string>();
var existingFiles = GetAllFilesRecursive(Path.GetDirectoryName(projectPath), "*.cs");
- GlobOptions globOptions = new GlobOptions();
+ var globOptions = new GlobOptions();
globOptions.Evaluation.CaseInsensitive = false;
var root = ProjectRootElement.Open(projectPath);
@@ -68,5 +73,103 @@ namespace GodotTools.ProjectEditor
return result.ToArray();
}
+
+ /// Simple function to make sure the Api assembly references are configured correctly
+ public static void FixApiHintPath(string projectPath)
+ {
+ var root = ProjectRootElement.Open(projectPath);
+ Debug.Assert(root != null);
+
+ bool dirty = false;
+
+ void AddPropertyIfNotPresent(string name, string condition, string value)
+ {
+ if (root.PropertyGroups
+ .Any(g => g.Condition == string.Empty || g.Condition == condition &&
+ g.Properties
+ .Any(p => p.Name == name &&
+ p.Value == value &&
+ (p.Condition == condition || g.Condition == condition))))
+ {
+ return;
+ }
+
+ root.AddProperty(name, value).Condition = condition;
+ dirty = true;
+ }
+
+ AddPropertyIfNotPresent(name: "ApiConfiguration",
+ condition: " '$(Configuration)' != 'Release' ",
+ value: "Debug");
+ AddPropertyIfNotPresent(name: "ApiConfiguration",
+ condition: " '$(Configuration)' == 'Release' ",
+ value: "Release");
+
+ void SetReferenceHintPath(string referenceName, string condition, string hintPath)
+ {
+ foreach (var itemGroup in root.ItemGroups.Where(g =>
+ g.Condition == string.Empty || g.Condition == condition))
+ {
+ var references = itemGroup.Items.Where(item =>
+ item.ItemType == "Reference" &&
+ item.Include == referenceName &&
+ (item.Condition == condition || itemGroup.Condition == condition));
+
+ var referencesWithHintPath = references.Where(reference =>
+ reference.Metadata.Any(m => m.Name == "HintPath"));
+
+ if (referencesWithHintPath.Any(reference => reference.Metadata
+ .Any(m => m.Name == "HintPath" && m.Value == hintPath)))
+ {
+ // Found a Reference item with the right HintPath
+ return;
+ }
+
+ var referenceWithHintPath = referencesWithHintPath.FirstOrDefault();
+ if (referenceWithHintPath != null)
+ {
+ // Found a Reference item with a wrong HintPath
+ foreach (var metadata in referenceWithHintPath.Metadata.ToList()
+ .Where(m => m.Name == "HintPath"))
+ {
+ // Safe to remove as we duplicate with ToList() to loop
+ referenceWithHintPath.RemoveChild(metadata);
+ }
+
+ referenceWithHintPath.AddMetadata("HintPath", hintPath);
+ dirty = true;
+ return;
+ }
+
+ var referenceWithoutHintPath = references.FirstOrDefault();
+ if (referenceWithoutHintPath != null)
+ {
+ // Found a Reference item without a HintPath
+ referenceWithoutHintPath.AddMetadata("HintPath", hintPath);
+ dirty = true;
+ return;
+ }
+ }
+
+ // Found no Reference item at all. Add it.
+ root.AddItem("Reference", referenceName).Condition = condition;
+ dirty = true;
+ }
+
+ const string coreProjectName = "GodotSharp";
+ const string editorProjectName = "GodotSharpEditor";
+
+ const string coreCondition = "";
+ const string editorCondition = " '$(Configuration)' == 'Tools' ";
+
+ var coreHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{coreProjectName}.dll";
+ var editorHintPath = $"$(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/{editorProjectName}.dll";
+
+ SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath);
+ SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath);
+
+ if (dirty)
+ root.Save();
+ }
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln
new file mode 100644
index 0000000000..6f7d44bec2
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.sln
@@ -0,0 +1,35 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools", "GodotTools\GodotTools.csproj", "{27B00618-A6F2-4828-B922-05CAEB08C286}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.Core", "GodotTools.Core\GodotTools.Core.csproj", "{639E48BD-44E5-4091-8EDD-22D36DC0768D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.BuildLogger", "GodotTools.BuildLogger\GodotTools.BuildLogger.csproj", "{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.Build.0 = Release|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {27B00618-A6F2-4828-B922-05CAEB08C286}.Release|Any CPU.Build.0 = Release|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {639E48BD-44E5-4091-8EDD-22D36DC0768D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6CE9A984-37B1-4F8A-8FE9-609F05F071B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
index a0d14c43c9..f0068385f4 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
@@ -172,7 +172,7 @@ namespace GodotTools.Build
if (outputArray.Count == 0)
return string.Empty;
- var lines = outputArray[1].Split('\n');
+ var lines = outputArray[0].Split('\n');
foreach (string line in lines)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs b/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
index 0426f0ac5a..e216d30462 100644
--- a/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
@@ -11,11 +11,11 @@ namespace GodotTools
{
public static class CSharpProject
{
- public static string GenerateGameProject(string dir, string name, IEnumerable<string> files = null)
+ public static string GenerateGameProject(string dir, string name)
{
try
{
- return ProjectGenerator.GenGameProject(dir, name, files);
+ return ProjectGenerator.GenGameProject(dir, name, compileItems: new string[] { });
}
catch (Exception e)
{
@@ -32,6 +32,18 @@ namespace GodotTools
ProjectUtils.AddItemToProjectChecked(projectPath, itemType, include);
}
+ public static void FixApiHintPath(string projectPath)
+ {
+ try
+ {
+ ProjectUtils.FixApiHintPath(projectPath);
+ }
+ catch (Exception e)
+ {
+ GD.PushError(e.ToString());
+ }
+ }
+
private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static ulong ConvertToTimestamp(this DateTime value)
@@ -58,7 +70,7 @@ namespace GodotTools
{
var oldFileDict = (Dictionary) oldFileVar;
- if (ulong.TryParse((string) oldFileDict["modified_time"], out ulong storedModifiedTime))
+ if (ulong.TryParse(oldFileDict["modified_time"] as string, out ulong storedModifiedTime))
{
if (storedModifiedTime == modifiedTime)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 955574d5fe..da439b8d6f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -26,6 +26,8 @@ namespace GodotTools
private MonoDevelopInstance monoDevelopInstance;
private MonoDevelopInstance visualStudioForMacInstance;
+ private WeakReference<GodotSharpExport> exportPluginWeak;
+
public MonoBottomPanel MonoBottomPanel { get; private set; }
private bool CreateProjectSolution()
@@ -464,6 +466,9 @@ namespace GodotTools
{
// Defer this task because EditorProgress calls Main::iterarion() and the main loop is not yet initialized.
CallDeferred(nameof(_MakeApiSolutionsIfNeeded));
+
+ // Make sure the existing project has Api assembly references configured correctly
+ CSharpProject.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
}
else
{
@@ -513,11 +518,27 @@ namespace GodotTools
});
// Export plugin
- AddExportPlugin(new GodotSharpExport());
+ var exportPlugin = new GodotSharpExport();
+ AddExportPlugin(exportPlugin);
+ exportPluginWeak = new WeakReference<GodotSharpExport>(exportPlugin);
GodotSharpBuilds.Initialize();
}
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (exportPluginWeak.TryGetTarget(out var exportPlugin))
+ {
+ // We need to dispose our export plugin before the editor destroys EditorSettings.
+ // Otherwise, if the GC disposes it at a later time, EditorExportPlatformAndroid
+ // will be freed after EditorSettings already was, and its device polling thread
+ // will try to access the EditorSettings singleton, resulting in null dereferencing.
+ exportPlugin.Dispose();
+ }
+ }
+
public void OnBeforeSerialize()
{
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 1a440e5ced..45037bf637 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -875,14 +875,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
da->make_dir("Core");
da->make_dir("ObjectType");
- String core_dir = path_join(p_proj_dir, "Core");
- String obj_type_dir = path_join(p_proj_dir, "ObjectType");
+ String core_dir = path::join(p_proj_dir, "Core");
+ String obj_type_dir = path::join(p_proj_dir, "ObjectType");
// Generate source file for global scope constants and enums
{
StringBuilder constants_source;
_generate_global_constants(constants_source);
- String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
+ String output_file = path::join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
Error save_err = _save_file(output_file, constants_source);
if (save_err != OK)
return save_err;
@@ -896,7 +896,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
if (itype.api_type == ClassDB::API_EDITOR)
continue;
- String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs");
+ String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP)
@@ -917,7 +917,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
const String &file_name = E->key();
const GodotCsCompressedFile &file_data = E->value();
- String output_file = path_join(core_dir, file_name);
+ String output_file = path::join(core_dir, file_name);
Vector<uint8_t> data;
data.resize(file_data.uncompressed_size);
@@ -971,7 +971,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
- String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs");
+ String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content);
if (err != OK)
@@ -996,8 +996,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
da->make_dir("Core");
da->make_dir("ObjectType");
- String core_dir = path_join(p_proj_dir, "Core");
- String obj_type_dir = path_join(p_proj_dir, "ObjectType");
+ String core_dir = path::join(p_proj_dir, "Core");
+ String obj_type_dir = path::join(p_proj_dir, "ObjectType");
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
const TypeInterface &itype = E.get();
@@ -1005,7 +1005,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
if (itype.api_type != ClassDB::API_EDITOR)
continue;
- String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs");
+ String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP)
@@ -1051,7 +1051,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
- String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs");
+ String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content);
if (err != OK)
@@ -1064,7 +1064,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
Error BindingsGenerator::generate_cs_api(const String &p_output_dir) {
- String output_dir = DirAccess::get_full_path(p_output_dir, DirAccess::ACCESS_FILESYSTEM);
+ String output_dir = path::abspath(path::realpath(p_output_dir));
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
@@ -1862,7 +1862,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.append("\n#endif // MONO_GLUE_ENABLED\n");
- Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output);
+ Error save_err = _save_file(path::join(p_output_dir, "mono_glue.gen.cpp"), output);
if (save_err != OK)
return save_err;
@@ -2192,7 +2192,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
itype.base_name = ClassDB::get_parent_class(type_cname);
itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
- itype.is_instantiable = ClassDB::can_instance(type_cname) && !itype.is_singleton;
+ itype.is_instantiable = class_info->creation_func && !itype.is_singleton;
itype.is_reference = ClassDB::is_parent_class(type_cname, name_cache.type_Reference);
itype.memory_own = itype.is_reference;
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 75b2dfce9a..6d85f55b97 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -219,7 +219,18 @@ MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *
}
MonoString *godot_icall_Object_ToString(Object *p_ptr) {
- return GDMonoMarshal::mono_string_from_godot(Variant(p_ptr).operator String());
+#ifdef DEBUG_ENABLED
+ // Cannot happen in C#; would get an ObjectDisposedException instead.
+ CRASH_COND(p_ptr == NULL);
+
+ if (ScriptDebugger::get_singleton() && !Object::cast_to<Reference>(p_ptr)) { // Only if debugging!
+ // Cannot happen either in C#; the handle is nullified when the object is destroyed
+ CRASH_COND(!ObjectDB::instance_validate(p_ptr));
+ }
+#endif
+
+ String result = "[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]";
+ return GDMonoMarshal::mono_string_from_godot(result);
}
void godot_register_object_icalls() {
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 7ae991eeaa..06fbae019c 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -241,9 +241,9 @@ void GDMono::initialize() {
locations.push_back("/usr/local/var/homebrew/linked/mono/");
for (int i = 0; i < locations.size(); i++) {
- String hint_assembly_rootdir = path_join(locations[i], "lib");
- String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
- String hint_config_dir = path_join(locations[i], "etc");
+ String hint_assembly_rootdir = path::join(locations[i], "lib");
+ String hint_mscorlib_path = path::join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
+ String hint_config_dir = path::join(locations[i], "etc");
if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
assembly_rootdir = hint_assembly_rootdir;
@@ -564,6 +564,7 @@ bool GDMono::_load_corlib_assembly() {
return success;
}
+#ifdef TOOLS_ENABLED
static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) {
// Create destination directory if needed
@@ -607,6 +608,7 @@ static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir,
return true;
}
+#endif
bool GDMono::_load_core_api_assembly() {
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 8e63ef3563..761c7f6fcb 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -46,20 +46,6 @@ bool GDMonoAssembly::in_preload = false;
Vector<String> GDMonoAssembly::search_dirs;
-static String _get_expected_api_build_config() {
-#ifdef TOOLS_ENABLED
- return "Debug";
-#else
-
-#ifdef DEBUG_ENABLED
- return "Debug";
-#else
- return "Release";
-#endif
-
-#endif
-}
-
void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config, const String &p_custom_bcl_dir) {
String framework_dir;
@@ -81,11 +67,14 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin
r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
}
- String api_config = p_custom_config.empty() ? _get_expected_api_build_config() :
- (p_custom_config == "Release" ? "Release" : "Debug");
- r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir().plus_file(api_config));
+ if (p_custom_config.empty()) {
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ } else {
+ String api_config = p_custom_config == "Release" ? "Release" : "Debug";
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir().plus_file(api_config));
+ }
- r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_base_dir());
r_search_dirs.push_back(OS::get_singleton()->get_resource_dir());
r_search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 6e431f51e7..20863b1afe 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -36,16 +36,21 @@
#include "core/project_settings.h"
#ifdef WINDOWS_ENABLED
+#include <windows.h>
+
#define ENV_PATH_SEP ";"
#else
-#define ENV_PATH_SEP ":"
#include <limits.h>
+#include <unistd.h>
+
+#define ENV_PATH_SEP ":"
#endif
#include <stdlib.h>
-String path_which(const String &p_name) {
+namespace path {
+String find_executable(const String &p_name) {
#ifdef WINDOWS_ENABLED
Vector<String> exts = OS::get_singleton()->get_environment("PATHEXT").split(ENV_PATH_SEP, false);
#endif
@@ -55,7 +60,7 @@ String path_which(const String &p_name) {
return String();
for (int i = 0; i < env_path.size(); i++) {
- String p = path_join(env_path[i], p_name);
+ String p = path::join(env_path[i], p_name);
#ifdef WINDOWS_ENABLED
for (int j = 0; j < exts.size(); j++) {
@@ -73,42 +78,96 @@ String path_which(const String &p_name) {
return String();
}
-void fix_path(const String &p_path, String &r_out) {
- r_out = p_path.replace("\\", "/");
+String cwd() {
+#ifdef WINDOWS_ENABLED
+ const DWORD expected_size = ::GetCurrentDirectoryW(0, NULL);
+
+ String buffer;
+ buffer.resize((int)expected_size);
+ if (::GetCurrentDirectoryW(expected_size, buffer.ptrw()) == 0)
+ return ".";
+
+ return buffer.simplify_path();
+#else
+ char buffer[PATH_MAX];
+ if (::getcwd(buffer, sizeof(buffer)) == NULL)
+ return ".";
+
+ String result;
+ if (result.parse_utf8(buffer))
+ return ".";
- while (true) { // in case of using 2 or more slash
- String compare = r_out.replace("//", "/");
- if (r_out == compare)
- break;
- else
- r_out = compare;
+ return result.simplify_path();
+#endif
+}
+
+String abspath(const String &p_path) {
+ if (p_path.is_abs_path()) {
+ return p_path.simplify_path();
+ } else {
+ return path::join(path::cwd(), p_path).simplify_path();
}
}
-bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
+String realpath(const String &p_path) {
#ifdef WINDOWS_ENABLED
- CharType ret[_MAX_PATH];
- if (::_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
- String abspath = String(ret).replace("\\", "/");
- int pos = abspath.find(":/");
- if (pos != -1) {
- r_abs_path = abspath.substr(pos - 1, abspath.length());
- } else {
- r_abs_path = abspath;
- }
- return true;
- }
-#else
- char *resolved_path = ::realpath(p_existing_path.utf8().get_data(), NULL);
- if (resolved_path) {
- String retstr;
- bool success = !retstr.parse_utf8(resolved_path);
- ::free(resolved_path);
- if (success) {
- r_abs_path = retstr;
- return true;
- }
+ // Open file without read/write access
+ HANDLE hFile = ::CreateFileW(p_path.c_str(), 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return p_path;
+
+ const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, NULL, 0, FILE_NAME_NORMALIZED);
+
+ if (expected_size == 0) {
+ ::CloseHandle(hFile);
+ return p_path;
}
+
+ String buffer;
+ buffer.resize((int)expected_size);
+ ::GetFinalPathNameByHandleW(hFile, buffer.ptrw(), expected_size, FILE_NAME_NORMALIZED);
+
+ ::CloseHandle(hFile);
+ return buffer.simplify_path();
+#elif UNIX_ENABLED
+ char *resolved_path = ::realpath(p_path.utf8().get_data(), NULL);
+
+ if (!resolved_path)
+ return p_path;
+
+ String result;
+ bool parse_ok = result.parse_utf8(resolved_path);
+ ::free(resolved_path);
+
+ if (parse_ok)
+ return p_path;
+
+ return result.simplify_path();
#endif
- return false;
}
+
+String join(const String &p_a, const String &p_b) {
+ if (p_a.empty())
+ return p_b;
+
+ const CharType a_last = p_a[p_a.length() - 1];
+ if ((a_last == '/' || a_last == '\\') ||
+ (p_b.size() > 0 && (p_b[0] == '/' || p_b[0] == '\\'))) {
+ return p_a + p_b;
+ }
+
+ return p_a + "/" + p_b;
+}
+
+String join(const String &p_a, const String &p_b, const String &p_c) {
+ return path::join(path::join(p_a, p_b), p_c);
+}
+
+String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d) {
+ return path::join(path::join(path::join(p_a, p_b), p_c), p_d);
+}
+
+} // namespace path
diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h
index 69edf4deb7..ca25bc09f7 100644
--- a/modules/mono/utils/path_utils.h
+++ b/modules/mono/utils/path_utils.h
@@ -31,24 +31,32 @@
#ifndef PATH_UTILS_H
#define PATH_UTILS_H
+#include "core/string_builder.h"
#include "core/ustring.h"
-_FORCE_INLINE_ String path_join(const String &e1, const String &e2) {
- return e1.plus_file(e2);
-}
+namespace path {
-_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3) {
- return e1.plus_file(e2).plus_file(e3);
-}
+String join(const String &p_a, const String &p_b);
+String join(const String &p_a, const String &p_b, const String &p_c);
+String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d);
-_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3, const String &e4) {
- return e1.plus_file(e2).plus_file(e3).plus_file(e4);
-}
+String find_executable(const String &p_name);
-String path_which(const String &p_name);
+/// Returns a normalized absolute path to the current working directory
+String cwd();
-void fix_path(const String &p_path, String &r_out);
+/**
+ * Obtains a normalized absolute path to p_path. Symbolic links are
+ * not resolved. The path p_path might not exist in the file system.
+ */
+String abspath(const String &p_path);
-bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path);
+/**
+ * Obtains a normalized path to p_path with symbolic links resolved.
+ * The resulting path might be either a relative or an absolute path.
+ */
+String realpath(const String &p_path);
+
+} // namespace path
#endif // PATH_UTILS_H
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 877122985d..2b014c2a45 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -44,7 +44,7 @@ int sfind(const String &p_text, int p_from) {
int src_len = 2;
int len = p_text.length();
- if (src_len == 0 || len == 0)
+ if (len == 0)
return -1;
const CharType *src = p_text.c_str();
diff --git a/modules/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp
index 70d0f770d8..615081d818 100644
--- a/modules/opus/audio_stream_opus.cpp
+++ b/modules/opus/audio_stream_opus.cpp
@@ -280,7 +280,7 @@ int AudioStreamPlaybackOpus::mix(int16_t *p_buffer, int p_frames) {
int todo = p_frames;
- if (todo == 0 || todo < MIN_MIX) {
+ if (todo < MIN_MIX) {
break;
}
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 8f6ffcc83f..8b1f21d95d 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -153,7 +153,7 @@ RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path,
ERR_FAIL_V(RES());
}
- w = PoolVector<uint8_t>::Write();
+ w.release();
int tex_flags = Texture::FLAG_FILTER | Texture::FLAG_REPEAT;
@@ -655,8 +655,8 @@ static void _pvrtc_decompress(Image *p_img) {
decompress_pvrtc((PVRTCBlock *)r.ptr(), _2bit, p_img->get_width(), p_img->get_height(), 0, (unsigned char *)w.ptr());
- w = PoolVector<uint8_t>::Write();
- r = PoolVector<uint8_t>::Read();
+ w.release();
+ r.release();
bool make_mipmaps = p_img->has_mipmaps();
p_img->create(p_img->get_width(), p_img->get_height(), false, Image::FORMAT_RGBA8, newdata);
diff --git a/modules/recast/register_types.cpp b/modules/recast/register_types.cpp
index 247d7f6144..44129fbb61 100644
--- a/modules/recast/register_types.cpp
+++ b/modules/recast/register_types.cpp
@@ -40,7 +40,14 @@ void register_recast_types() {
#ifdef TOOLS_ENABLED
EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
_nav_mesh_generator = memnew(EditorNavigationMeshGenerator);
+
+ ClassDB::APIType prev_api = ClassDB::get_current_api();
+ ClassDB::set_current_api(ClassDB::API_EDITOR);
+
ClassDB::register_class<EditorNavigationMeshGenerator>();
+
+ ClassDB::set_current_api(prev_api);
+
Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationMeshGenerator", EditorNavigationMeshGenerator::get_singleton()));
#endif
}
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index 4f38357aa1..64f4c169cb 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -198,8 +198,8 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres
h = MAX(h / 2, 1);
}
- rb = PoolVector<uint8_t>::Read();
- wb = PoolVector<uint8_t>::Write();
+ rb.release();
+ wb.release();
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
}
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index b5f4718c72..0922471500 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -188,7 +188,7 @@ void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t> &p_data) {
ogg_stream = stb_vorbis_open_memory((const unsigned char *)src_datar.ptr(), src_data_len, &error, &ogg_alloc);
if (!ogg_stream && error == VORBIS_outofmem) {
- w = PoolVector<char>::Write();
+ w.release();
alloc_try *= 2;
} else {
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index e36844a1bc..b0cd648734 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -123,7 +123,7 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
rasterizer.rasterize(svg_image, 0, 0, p_scale * upscale, (unsigned char *)dw.ptr(), w, h, w * 4);
- dw = PoolVector<uint8_t>::Write();
+ dw.release();
p_image->create(w, h, false, Image::FORMAT_RGBA8, dst_image);
if (upsample)
p_image->shrink_x2();
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index a3c0f5ded7..6ee408d472 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -199,7 +199,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
}
}
- image_data_w = PoolVector<uint8_t>::Write();
+ image_data_w.release();
p_image->create(width, height, 0, Image::FORMAT_RGBA8, image_data);
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index a9340b1498..74a584821a 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -235,7 +235,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
p_image->create(exr_image.width, exr_image.height, false, format, imgdata);
- w = PoolVector<uint8_t>::Write();
+ w.release();
FreeEXRHeader(&exr_header);
FreeEXRImage(&exr_image);
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index df5bb9ca2e..b816e37936 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -1487,7 +1487,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p
Variant **output_args = (Variant **)(input_args + max_input_args);
int flow_max = f->flow_stack_size;
int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL;
- int *pass_stack = flow_stack + flow_max;
+ int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL;
String error_str;
@@ -1905,7 +1905,7 @@ Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p
Variant **output_args = (Variant **)(input_args + max_input_args);
int flow_max = f->flow_stack_size;
int *flow_stack = flow_max ? (int *)(output_args + max_output_args) : (int *)NULL;
- int *pass_stack = flow_stack + flow_max;
+ int *pass_stack = flow_stack ? (int *)(flow_stack + flow_max) : (int *)NULL;
for (int i = 0; i < f->node_count; i++) {
sequence_bits[i] = false; //all starts as false
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 4579644d49..31d5e4665a 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -341,74 +341,74 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
Color color;
if (dark_theme)
switch (p_type) {
- case Variant::NIL: color = Color::html("#69ecbd"); break;
-
- case Variant::BOOL: color = Color::html("#8da6f0"); break;
- case Variant::INT: color = Color::html("#7dc6ef"); break;
- case Variant::REAL: color = Color::html("#61daf4"); break;
- case Variant::STRING: color = Color::html("#6ba7ec"); break;
-
- case Variant::VECTOR2: color = Color::html("#bd91f1"); break;
- case Variant::RECT2: color = Color::html("#f191a5"); break;
- case Variant::VECTOR3: color = Color::html("#d67dee"); break;
- case Variant::TRANSFORM2D: color = Color::html("#c4ec69"); break;
- case Variant::PLANE: color = Color::html("#f77070"); break;
- case Variant::QUAT: color = Color::html("#ec69a3"); break;
- case Variant::AABB: color = Color::html("#ee7991"); break;
- case Variant::BASIS: color = Color::html("#e3ec69"); break;
- case Variant::TRANSFORM: color = Color::html("#f6a86e"); break;
-
- case Variant::COLOR: color = Color::html("#9dff70"); break;
- case Variant::NODE_PATH: color = Color::html("#6993ec"); break;
- case Variant::_RID: color = Color::html("#69ec9a"); break;
- case Variant::OBJECT: color = Color::html("#79f3e8"); break;
- case Variant::DICTIONARY: color = Color::html("#77edb1"); break;
-
- case Variant::ARRAY: color = Color::html("#e0e0e0"); break;
- case Variant::POOL_BYTE_ARRAY: color = Color::html("#aaf4c8"); break;
- case Variant::POOL_INT_ARRAY: color = Color::html("#afdcf5"); break;
- case Variant::POOL_REAL_ARRAY: color = Color::html("#97e7f8"); break;
- case Variant::POOL_STRING_ARRAY: color = Color::html("#9dc4f2"); break;
- case Variant::POOL_VECTOR2_ARRAY: color = Color::html("#d1b3f5"); break;
- case Variant::POOL_VECTOR3_ARRAY: color = Color::html("#df9bf2"); break;
- case Variant::POOL_COLOR_ARRAY: color = Color::html("#e9ff97"); break;
+ case Variant::NIL: color = Color(0.41, 0.93, 0.74); break;
+
+ case Variant::BOOL: color = Color(0.55, 0.65, 0.94); break;
+ case Variant::INT: color = Color(0.49, 0.78, 0.94); break;
+ case Variant::REAL: color = Color(0.38, 0.85, 0.96); break;
+ case Variant::STRING: color = Color(0.42, 0.65, 0.93); break;
+
+ case Variant::VECTOR2: color = Color(0.74, 0.57, 0.95); break;
+ case Variant::RECT2: color = Color(0.95, 0.57, 0.65); break;
+ case Variant::VECTOR3: color = Color(0.84, 0.49, 0.93); break;
+ case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break;
+ case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break;
+ case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break;
+ case Variant::AABB: color = Color(0.93, 0.47, 0.57); break;
+ case Variant::BASIS: color = Color(0.89, 0.93, 0.41); break;
+ case Variant::TRANSFORM: color = Color(0.96, 0.66, 0.43); break;
+
+ case Variant::COLOR: color = Color(0.62, 1.0, 0.44); break;
+ case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break;
+ case Variant::_RID: color = Color(0.41, 0.93, 0.6); break;
+ case Variant::OBJECT: color = Color(0.47, 0.95, 0.91); break;
+ case Variant::DICTIONARY: color = Color(0.47, 0.93, 0.69); break;
+
+ case Variant::ARRAY: color = Color(0.88, 0.88, 0.88); break;
+ case Variant::POOL_BYTE_ARRAY: color = Color(0.67, 0.96, 0.78); break;
+ case Variant::POOL_INT_ARRAY: color = Color(0.69, 0.86, 0.96); break;
+ case Variant::POOL_REAL_ARRAY: color = Color(0.59, 0.91, 0.97); break;
+ case Variant::POOL_STRING_ARRAY: color = Color(0.62, 0.77, 0.95); break;
+ case Variant::POOL_VECTOR2_ARRAY: color = Color(0.82, 0.7, 0.96); break;
+ case Variant::POOL_VECTOR3_ARRAY: color = Color(0.87, 0.61, 0.95); break;
+ case Variant::POOL_COLOR_ARRAY: color = Color(0.91, 1.0, 0.59); break;
default:
color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.7, 0.7);
}
else
switch (p_type) {
- case Variant::NIL: color = Color::html("#25e3a0"); break;
-
- case Variant::BOOL: color = Color::html("#6d8eeb"); break;
- case Variant::INT: color = Color::html("#4fb2e9"); break;
- case Variant::REAL: color = Color::html("#27ccf0"); break;
- case Variant::STRING: color = Color::html("#4690e7"); break;
-
- case Variant::VECTOR2: color = Color::html("#ad76ee"); break;
- case Variant::RECT2: color = Color::html("#ee758e"); break;
- case Variant::VECTOR3: color = Color::html("#dc6aed"); break;
- case Variant::TRANSFORM2D: color = Color::html("#96ce1a"); break;
- case Variant::PLANE: color = Color::html("#f77070"); break;
- case Variant::QUAT: color = Color::html("#ec69a3"); break;
- case Variant::AABB: color = Color::html("#ee7991"); break;
- case Variant::BASIS: color = Color::html("#b2bb19"); break;
- case Variant::TRANSFORM: color = Color::html("#f49047"); break;
-
- case Variant::COLOR: color = Color::html("#3cbf00"); break;
- case Variant::NODE_PATH: color = Color::html("#6993ec"); break;
- case Variant::_RID: color = Color::html("#2ce573"); break;
- case Variant::OBJECT: color = Color::html("#12d5c3"); break;
- case Variant::DICTIONARY: color = Color::html("#57e99f"); break;
-
- case Variant::ARRAY: color = Color::html("#737373"); break;
- case Variant::POOL_BYTE_ARRAY: color = Color::html("#61ea98"); break;
- case Variant::POOL_INT_ARRAY: color = Color::html("#61baeb"); break;
- case Variant::POOL_REAL_ARRAY: color = Color::html("#40d3f2"); break;
- case Variant::POOL_STRING_ARRAY: color = Color::html("#609fea"); break;
- case Variant::POOL_VECTOR2_ARRAY: color = Color::html("#9d5dea"); break;
- case Variant::POOL_VECTOR3_ARRAY: color = Color::html("#ca5aea"); break;
- case Variant::POOL_COLOR_ARRAY: color = Color::html("#92ba00"); break;
+ case Variant::NIL: color = Color(0.15, 0.89, 0.63); break;
+
+ case Variant::BOOL: color = Color(0.43, 0.56, 0.92); break;
+ case Variant::INT: color = Color(0.31, 0.7, 0.91); break;
+ case Variant::REAL: color = Color(0.15, 0.8, 0.94); break;
+ case Variant::STRING: color = Color(0.27, 0.56, 0.91); break;
+
+ case Variant::VECTOR2: color = Color(0.68, 0.46, 0.93); break;
+ case Variant::RECT2: color = Color(0.93, 0.46, 0.56); break;
+ case Variant::VECTOR3: color = Color(0.86, 0.42, 0.93); break;
+ case Variant::TRANSFORM2D: color = Color(0.59, 0.81, 0.1); break;
+ case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break;
+ case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break;
+ case Variant::AABB: color = Color(0.93, 0.47, 0.57); break;
+ case Variant::BASIS: color = Color(0.7, 0.73, 0.1); break;
+ case Variant::TRANSFORM: color = Color(0.96, 0.56, 0.28); break;
+
+ case Variant::COLOR: color = Color(0.24, 0.75, 0.0); break;
+ case Variant::NODE_PATH: color = Color(0.41, 0.58, 0.93); break;
+ case Variant::_RID: color = Color(0.17, 0.9, 0.45); break;
+ case Variant::OBJECT: color = Color(0.07, 0.84, 0.76); break;
+ case Variant::DICTIONARY: color = Color(0.34, 0.91, 0.62); break;
+
+ case Variant::ARRAY: color = Color(0.45, 0.45, 0.45); break;
+ case Variant::POOL_BYTE_ARRAY: color = Color(0.38, 0.92, 0.6); break;
+ case Variant::POOL_INT_ARRAY: color = Color(0.38, 0.73, 0.92); break;
+ case Variant::POOL_REAL_ARRAY: color = Color(0.25, 0.83, 0.95); break;
+ case Variant::POOL_STRING_ARRAY: color = Color(0.38, 0.62, 0.92); break;
+ case Variant::POOL_VECTOR2_ARRAY: color = Color(0.62, 0.36, 0.92); break;
+ case Variant::POOL_VECTOR3_ARRAY: color = Color(0.79, 0.35, 0.92); break;
+ case Variant::POOL_COLOR_ARRAY: color = Color(0.57, 0.73, 0.0); break;
default:
color.set_hsv(p_type / float(Variant::VARIANT_MAX), 0.3, 0.3);
@@ -3054,19 +3054,19 @@ void VisualScriptEditor::_notification(int p_what) {
List<Pair<String, Color> > colors;
if (dark_theme) {
- colors.push_back(Pair<String, Color>("flow_control", Color::html("#f4f4f4")));
- colors.push_back(Pair<String, Color>("functions", Color::html("#f58581")));
- colors.push_back(Pair<String, Color>("data", Color::html("#80f6cf")));
- colors.push_back(Pair<String, Color>("operators", Color::html("#ab97df")));
- colors.push_back(Pair<String, Color>("custom", Color::html("#80bbf6")));
- colors.push_back(Pair<String, Color>("constants", Color::html("#f680b0")));
+ colors.push_back(Pair<String, Color>("flow_control", Color(0.96, 0.96, 0.96)));
+ colors.push_back(Pair<String, Color>("functions", Color(0.96, 0.52, 0.51)));
+ colors.push_back(Pair<String, Color>("data", Color(0.5, 0.96, 0.81)));
+ colors.push_back(Pair<String, Color>("operators", Color(0.67, 0.59, 0.87)));
+ colors.push_back(Pair<String, Color>("custom", Color(0.5, 0.73, 0.96)));
+ colors.push_back(Pair<String, Color>("constants", Color(0.96, 0.5, 0.69)));
} else {
- colors.push_back(Pair<String, Color>("flow_control", Color::html("#424242")));
- colors.push_back(Pair<String, Color>("functions", Color::html("#f26661")));
- colors.push_back(Pair<String, Color>("data", Color::html("#13bb83")));
- colors.push_back(Pair<String, Color>("operators", Color::html("#8265d0")));
- colors.push_back(Pair<String, Color>("custom", Color::html("#4ea0f2")));
- colors.push_back(Pair<String, Color>("constants", Color::html("#f02f7d")));
+ colors.push_back(Pair<String, Color>("flow_control", Color(0.26, 0.26, 0.26)));
+ colors.push_back(Pair<String, Color>("functions", Color(0.95, 0.4, 0.38)));
+ colors.push_back(Pair<String, Color>("data", Color(0.07, 0.73, 0.51)));
+ colors.push_back(Pair<String, Color>("operators", Color(0.51, 0.4, 0.82)));
+ colors.push_back(Pair<String, Color>("custom", Color(0.31, 0.63, 0.95)));
+ colors.push_back(Pair<String, Color>("constants", Color(0.94, 0.18, 0.49)));
}
for (List<Pair<String, Color> >::Element *E = colors.front(); E; E = E->next()) {
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index f8cb6cfa3c..0413bbf303 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -570,7 +570,6 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
Node *bnode = _get_base_node();
if (bnode) {
property.hint_string = bnode->get_path(); //convert to loong string
- } else {
}
}
}
@@ -1035,8 +1034,6 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
_adjust_input_index(pi);
return pi;
- } else {
- p_idx--;
}
}
@@ -1352,7 +1349,6 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
Node *bnode = _get_base_node();
if (bnode) {
property.hint_string = bnode->get_path(); //convert to loong string
- } else {
}
}
}
@@ -1794,8 +1790,6 @@ PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const
pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type);
pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
return pi;
- } else {
- p_idx--;
}
}
return PropertyInfo();
@@ -2073,7 +2067,6 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
Node *bnode = _get_base_node();
if (bnode) {
property.hint_string = bnode->get_path(); //convert to loong string
- } else {
}
}
}
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index 962560cc96..ebd0f0b3cb 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -431,7 +431,6 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const {
Node *bnode = _get_base_node();
if (bnode) {
property.hint_string = bnode->get_path(); //convert to loong string
- } else {
}
}
}
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index e652abbe6a..2f4a45f108 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -103,7 +103,7 @@ int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_buffer, int p_frames) {
int todo = p_frames;
- if (todo == 0 || todo < MIN_MIX) {
+ if (todo < MIN_MIX) {
break;
}
diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp
index 928a0dcbd3..630c15f140 100644
--- a/modules/webp/image_loader_webp.cpp
+++ b/modules/webp/image_loader_webp.cpp
@@ -71,7 +71,7 @@ static PoolVector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_q
w[3] = 'P';
copymem(&w[4], dst_buff, dst_size);
free(dst_buff);
- w = PoolVector<uint8_t>::Write();
+ w.release();
return dst;
}
@@ -110,7 +110,7 @@ static Ref<Image> _webp_lossy_unpack(const PoolVector<uint8_t> &p_buffer) {
//ERR_EXPLAIN("Error decoding webp! - "+p_file);
ERR_FAIL_COND_V(errdec, Ref<Image>());
- dst_w = PoolVector<uint8_t>::Write();
+ dst_w.release();
Ref<Image> img = memnew(Image(features.width, features.height, 0, features.has_alpha ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8, dst_image));
return img;
@@ -137,7 +137,7 @@ Error webp_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
} else {
errdec = WebPDecodeRGBInto(p_buffer, p_buffer_len, dst_w.ptr(), datasize, 3 * features.width) == NULL;
}
- dst_w = PoolVector<uint8_t>::Write();
+ dst_w.release();
//ERR_EXPLAIN("Error decoding webp!");
ERR_FAIL_COND_V(errdec, ERR_FILE_CORRUPT);
@@ -171,8 +171,6 @@ Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_forc
Error err = webp_load_image_from_buffer(p_image.ptr(), w.ptr(), src_image_len);
- w = PoolVector<uint8_t>::Write();
-
return err;
}
diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp
index 23cbf916eb..e24cb850ec 100644
--- a/modules/websocket/websocket_multiplayer_peer.cpp
+++ b/modules/websocket/websocket_multiplayer_peer.cpp
@@ -191,7 +191,7 @@ void WebSocketMultiplayerPeer::_send_sys(Ref<WebSocketPeer> p_peer, uint8_t p_ty
p_peer->put_packet(&(message.read()[0]), message.size());
}
-PoolVector<uint8_t> WebSocketMultiplayerPeer::_make_pkt(uint32_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size) {
+PoolVector<uint8_t> WebSocketMultiplayerPeer::_make_pkt(uint8_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size) {
PoolVector<uint8_t> out;
out.resize(PROTO_SIZE + p_data_size);
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index 7fd97a6595..e3ab0784ab 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -41,7 +41,7 @@ class WebSocketMultiplayerPeer : public NetworkedMultiplayerPeer {
GDCLASS(WebSocketMultiplayerPeer, NetworkedMultiplayerPeer);
private:
- PoolVector<uint8_t> _make_pkt(uint32_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size);
+ PoolVector<uint8_t> _make_pkt(uint8_t p_type, int32_t p_from, int32_t p_to, const uint8_t *p_data, uint32_t p_data_size);
void _store_pkt(int32_t p_source, int32_t p_dest, const uint8_t *p_data, uint32_t p_data_size);
Error _server_relay(int32_t p_from, int32_t p_to, const uint8_t *p_buffer, uint32_t p_buffer_size);
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index b2d865a58f..86374e8f80 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -92,6 +92,7 @@ void WSLClient::_do_handshake() {
data->id = 1;
_peer->make_context(data, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
_on_connect(protocol);
+ break;
}
_resp_pos += 1;
}
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 1e140a716f..0d09a4d74e 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -42,7 +42,7 @@ WSLServer::PendingPeer::PendingPeer() {
memset(req_buf, 0, sizeof(req_buf));
}
-bool WSLServer::PendingPeer::_parse_request(String &r_key) {
+bool WSLServer::PendingPeer::_parse_request(const PoolStringArray p_protocols) {
Vector<String> psa = String((char *)req_buf).split("\r\n");
int len = psa.size();
if (len < 4) {
@@ -87,11 +87,29 @@ bool WSLServer::PendingPeer::_parse_request(String &r_key) {
_WLS_CHECK_EX("connection");
#undef _WLS_CHECK_EX
#undef _WLS_CHECK
- r_key = headers["sec-websocket-key"];
+ key = headers["sec-websocket-key"];
+ if (headers.has("sec-websocket-protocol")) {
+ Vector<String> protos = headers["sec-websocket-protocol"].split(",");
+ for (int i = 0; i < protos.size(); i++) {
+ // Check if we have the given protocol
+ for (int j = 0; j < p_protocols.size(); j++) {
+ if (protos[i] != p_protocols[j])
+ continue;
+ protocol = protos[i];
+ break;
+ }
+ // Found a protocol
+ if (protocol != "")
+ break;
+ }
+ if (protocol == "") // Invalid protocol(s) requested
+ return false;
+ } else if (p_protocols.size() > 0) // No protocol requested, but we need one
+ return false;
return true;
}
-Error WSLServer::PendingPeer::do_handshake() {
+Error WSLServer::PendingPeer::do_handshake(PoolStringArray p_protocols) {
if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT)
return ERR_TIMEOUT;
if (!has_request) {
@@ -111,13 +129,15 @@ Error WSLServer::PendingPeer::do_handshake() {
int l = req_pos;
if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
r[l - 3] = '\0';
- if (!_parse_request(key)) {
+ if (!_parse_request(p_protocols)) {
return FAILED;
}
String s = "HTTP/1.1 101 Switching Protocols\r\n";
s += "Upgrade: websocket\r\n";
s += "Connection: Upgrade\r\n";
s += "Sec-WebSocket-Accept: " + WSLPeer::compute_key_response(key) + "\r\n";
+ if (protocol != "")
+ s += "Sec-WebSocket-Protocol: " + protocol + "\r\n";
s += "\r\n";
response = s.utf8();
has_request = true;
@@ -143,6 +163,7 @@ Error WSLServer::listen(int p_port, PoolVector<String> p_protocols, bool gd_mp_a
ERR_FAIL_COND_V(is_listening(), ERR_ALREADY_IN_USE);
_is_multiplayer = gd_mp_api;
+ _protocols = p_protocols;
_server->listen(p_port);
return OK;
@@ -167,7 +188,7 @@ void WSLServer::poll() {
List<Ref<PendingPeer> > remove_peers;
for (List<Ref<PendingPeer> >::Element *E = _pending.front(); E; E = E->next()) {
Ref<PendingPeer> ppeer = E->get();
- Error err = ppeer->do_handshake();
+ Error err = ppeer->do_handshake(_protocols);
if (err == ERR_BUSY) {
continue;
} else if (err != OK) {
@@ -188,7 +209,7 @@ void WSLServer::poll() {
_peer_map[id] = ws_peer;
remove_peers.push_back(ppeer);
- _on_connect(id, "");
+ _on_connect(id, ppeer->protocol);
}
for (List<Ref<PendingPeer> >::Element *E = remove_peers.front(); E; E = E->next()) {
_pending.erase(E->get());
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index b0520bd731..2ceb941073 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -49,7 +49,7 @@ private:
class PendingPeer : public Reference {
private:
- bool _parse_request(String &r_key);
+ bool _parse_request(const PoolStringArray p_protocols);
public:
Ref<StreamPeer> connection;
@@ -58,13 +58,14 @@ private:
uint8_t req_buf[WSL_MAX_HEADER_SIZE];
int req_pos;
String key;
+ String protocol;
bool has_request;
CharString response;
int response_sent;
PendingPeer();
- Error do_handshake();
+ Error do_handshake(const PoolStringArray p_protocols);
};
int _in_buf_size;
@@ -74,6 +75,7 @@ private:
List<Ref<PendingPeer> > _pending;
Ref<TCP_Server> _server;
+ PoolStringArray _protocols;
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets);