summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct3
-rw-r--r--core/variant_call.cpp49
-rw-r--r--drivers/SCsub10
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp4
-rw-r--r--drivers/gles2/shaders/canvas.glsl4
-rw-r--r--drivers/gles2/shaders/scene.glsl3
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp4
-rw-r--r--drivers/gles3/shaders/canvas.glsl2
-rw-r--r--drivers/gles3/shaders/scene.glsl4
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp4
-rw-r--r--methods.py26
-rw-r--r--modules/SCsub2
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml5
-rw-r--r--modules/gdscript/gdscript.cpp3
-rw-r--r--modules/gdscript/gdscript_functions.cpp20
-rw-r--r--modules/mono/build_scripts/godot_tools_build.py3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs20
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj17
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/.editorconfig6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs416
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs117
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/User32Dll.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/packages.config5
-rw-r--r--platform/windows/detect.py9
-rw-r--r--scene/resources/dynamic_font.cpp1
-rw-r--r--scene/resources/texture.cpp1
-rw-r--r--scene/resources/theme.cpp15
-rw-r--r--scene/resources/visual_shader.cpp12
-rw-r--r--thirdparty/vhacd/0003-fix-musl-build.patch15
-rw-r--r--thirdparty/vhacd/inc/vhacdMutex.h4
34 files changed, 723 insertions, 81 deletions
diff --git a/SConstruct b/SConstruct
index 0e282a1f12..ce13c8bd2e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -68,8 +68,6 @@ env_base.AppendENVPath('PATH', os.getenv('PATH'))
env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
env_base.disabled_modules = []
env_base.use_ptrcall = False
-env_base.split_drivers = False
-env_base.split_modules = False
env_base.module_version_string = ""
env_base.msvc = False
@@ -129,6 +127,7 @@ opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=extra werro
opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
opts.Add(BoolVariable('vsproj', "Generate a Visual Studio solution", False))
opts.Add(EnumVariable('macports_clang', "Build using Clang from MacPorts", 'no', ('no', '5.0', 'devel')))
+opts.Add(BoolVariable('split_libmodules', "Split intermediate libmodules.a in smaller chunks to prevent exceeding linker command line size (forced to True when using MinGW)", False))
opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable('disable_advanced_gui', "Disable advanced GUI nodes and behaviors", False))
opts.Add(BoolVariable('no_editor_splash', "Don't use the custom splash screen for the editor", False))
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 6e593a308d..f6ecc506a4 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1187,31 +1187,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
default: return Variant();
}
- } else if (p_argcount > 1) {
-
- _VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type];
-
- for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) {
- const _VariantCall::ConstructData &cd = E->get();
-
- if (cd.arg_count != p_argcount)
- continue;
-
- //validate parameters
- for (int i = 0; i < cd.arg_count; i++) {
- if (!Variant::can_convert(p_args[i]->type, cd.arg_types[i])) {
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; //no such constructor
- r_error.argument = i;
- r_error.expected = cd.arg_types[i];
- return Variant();
- }
- }
-
- Variant v;
- cd.func(v, p_args);
- return v;
- }
-
} else if (p_argcount == 1 && p_args[0]->type == p_type) {
return *p_args[0]; //copy construct
} else if (p_argcount == 1 && (!p_strict || Variant::can_convert(p_args[0]->type, p_type))) {
@@ -1268,6 +1243,30 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
case POOL_COLOR_ARRAY: return (PoolColorArray(*p_args[0]));
default: return Variant();
}
+ } else if (p_argcount >= 1) {
+
+ _VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type];
+
+ for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) {
+ const _VariantCall::ConstructData &cd = E->get();
+
+ if (cd.arg_count != p_argcount)
+ continue;
+
+ //validate parameters
+ for (int i = 0; i < cd.arg_count; i++) {
+ if (!Variant::can_convert(p_args[i]->type, cd.arg_types[i])) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT; //no such constructor
+ r_error.argument = i;
+ r_error.expected = cd.arg_types[i];
+ return Variant();
+ }
+ }
+
+ Variant v;
+ cd.func(v, p_args);
+ return v;
+ }
}
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; //no such constructor
return Variant();
diff --git a/drivers/SCsub b/drivers/SCsub
index 583973c025..d7003a07ce 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -46,9 +46,7 @@ if env['vsproj']:
env.AddToVSProject(env.drivers_sources)
os.chdir(path)
-if env.split_drivers:
- env.split_lib("drivers")
-else:
- env.add_source_files(env.drivers_sources, "*.cpp")
- lib = env.add_library("drivers", env.drivers_sources)
- env.Prepend(LIBS=[lib])
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+lib = env.add_library("drivers", env.drivers_sources)
+env.Prepend(LIBS=[lib])
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 7e9b6fdb82..94cb286b0e 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -911,7 +911,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy";
actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv";
- actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize";
+ actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size";
actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix";
actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix";
@@ -986,7 +986,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp";
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
- actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
+ actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size";
// gl_InstanceID is not available in OpenGL ES 2.0
actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0";
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index 08548ded17..afce403a9f 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -149,6 +149,8 @@ void main() {
uv = uv_attrib;
#endif
+ float point_size = 1.0;
+
{
vec2 src_vtx = outvec.xy;
/* clang-format off */
@@ -158,6 +160,8 @@ VERTEX_SHADER_CODE
/* clang-format on */
}
+ gl_PointSize = point_size;
+
#if !defined(SKIP_TRANSFORM_USED)
outvec = extra_matrix_instance * outvec;
outvec = modelview_matrix * outvec;
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 930d3cd9d4..63eee4eb87 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -423,6 +423,8 @@ void main() {
#define projection_matrix local_projection_matrix
#define world_transform world_matrix
+ float point_size = 1.0;
+
{
/* clang-format off */
@@ -431,6 +433,7 @@ VERTEX_SHADER_CODE
/* clang-format on */
}
+ gl_PointSize = point_size;
vec4 outvec = vertex;
// use local coordinates
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 7499962da3..e78ecbae34 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -913,7 +913,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy";
actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv";
- actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize";
+ actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size";
actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix";
actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix";
@@ -970,7 +970,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp";
actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp";
actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp";
- actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize";
+ actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size";
actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID";
//builtins
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 7255b0425c..53f84abf51 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -150,6 +150,7 @@ void main() {
#define extra_matrix extra_matrix_instance
+ float point_size = 1.0;
//for compatibility with the fragment shader we need to use uv here
vec2 uv = uv_interp;
{
@@ -160,6 +161,7 @@ VERTEX_SHADER_CODE
/* clang-format on */
}
+ gl_PointSize = point_size;
uv_interp = uv;
#ifdef USE_NINEPATCH
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index b4ceb7dcfd..549a36817e 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -432,6 +432,8 @@ void main() {
}
#endif
+ float point_size = 1.0;
+
highp mat4 modelview = camera_inverse_matrix * world_matrix;
{
/* clang-format off */
@@ -441,6 +443,8 @@ VERTEX_SHADER_CODE
/* clang-format on */
}
+ gl_PointSize = point_size;
+
// using local coordinates (default)
#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 980d82d6df..05f029f3c4 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -630,7 +630,7 @@ void EditorNode::_editor_select_next() {
} else {
editor++;
}
- } while (main_editor_buttons[editor]->is_visible());
+ } while (!main_editor_buttons[editor]->is_visible());
_editor_select(editor);
}
@@ -645,7 +645,7 @@ void EditorNode::_editor_select_prev() {
} else {
editor--;
}
- } while (main_editor_buttons[editor]->is_visible());
+ } while (!main_editor_buttons[editor]->is_visible());
_editor_select(editor);
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index d5dc74c134..544e0b69f1 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4938,8 +4938,8 @@ void CanvasItemEditor::_focus_selection(int p_op) {
center = rect.position + rect.size / 2;
Vector2 offset = viewport->get_size() / 2 - editor->get_scene_root()->get_global_canvas_transform().xform(center);
- view_offset.x -= offset.x / zoom;
- view_offset.y -= offset.y / zoom;
+ view_offset.x -= Math::round(offset.x / zoom);
+ view_offset.y -= Math::round(offset.y / zoom);
update_viewport();
} else { // VIEW_FRAME_TO_SELECTION
diff --git a/methods.py b/methods.py
index 86ab7cd9af..84074db0eb 100644
--- a/methods.py
+++ b/methods.py
@@ -307,7 +307,7 @@ def split_lib(self, libname, src_list = None, env_lib = None):
else:
fname = env.File(f)[0].path
fname = fname.replace("\\", "/")
- base = string.join(fname.split("/")[:2], "/")
+ base = "/".join(fname.split("/")[:2])
if base != cur_base and len(list) > max_src:
if num > 0:
lib = env_lib.add_library(libname + str(num), list)
@@ -320,12 +320,6 @@ def split_lib(self, libname, src_list = None, env_lib = None):
lib = env_lib.add_library(libname + str(num), list)
lib_list.append(lib)
- if len(lib_list) > 0:
- if os.name == 'posix' and sys.platform == 'msys':
- env.Replace(ARFLAGS=['rcsT'])
- lib = env_lib.add_library(libname + "_collated", lib_list)
- lib_list = [lib]
-
lib_base = []
env_lib.add_source_files(lib_base, "*.cpp")
lib = env_lib.add_library(libname, lib_base)
@@ -333,6 +327,24 @@ def split_lib(self, libname, src_list = None, env_lib = None):
env.Prepend(LIBS=lib_list)
+ # When we split modules into arbitrary chunks, we end up with linking issues
+ # due to symbol dependencies split over several libs, which may not be linked
+ # in the required order. We use --start-group and --end-group to tell the
+ # linker that those archives should be searched repeatedly to resolve all
+ # undefined references.
+ # As SCons doesn't give us much control over how inserting libs in LIBS
+ # impacts the linker call, we need to hack our way into the linking commands
+ # LINKCOM and SHLINKCOM to set those flags.
+
+ if '-Wl,--start-group' in env['LINKCOM'] and '-Wl,--start-group' in env['SHLINKCOM']:
+ # Already added by a previous call, skip.
+ return
+
+ env['LINKCOM'] = str(env['LINKCOM']).replace('$_LIBFLAGS',
+ '-Wl,--start-group $_LIBFLAGS -Wl,--end-group')
+ env['SHLINKCOM'] = str(env['LINKCOM']).replace('$_LIBFLAGS',
+ '-Wl,--start-group $_LIBFLAGS -Wl,--end-group')
+
def save_active_platforms(apnames, ap):
diff --git a/modules/SCsub b/modules/SCsub
index 42d89d6ce2..dc0420616c 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -16,7 +16,7 @@ for x in env.module_list:
env_modules.Append(CPPDEFINES=["MODULE_" + x.upper() + "_ENABLED"])
SConscript(x + "/SCsub")
-if env.split_modules:
+if env['split_libmodules']:
env.split_lib("modules", env_lib = env_modules)
else:
lib = env_modules.add_library("modules", env.modules_sources)
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index d1f52d2422..502a68cd61 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -616,9 +616,10 @@
Loads a resource from the filesystem located at [code]path[/code].
[b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing [b]Copy Path[/b].
[codeblock]
- # Load a scene called main located in the root of the project directory
+ # Load a scene called main located in the root of the project directory.
var main = load("res://main.tscn")
[/codeblock]
+ [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code].
</description>
</method>
<method name="log">
@@ -786,7 +787,7 @@
Returns a resource from the filesystem that is loaded during script parsing.
[b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path".
[codeblock]
- # Load a scene called main located in the root of the project directory
+ # Load a scene called main located in the root of the project directory.
var main = preload("res://main.tscn")
[/codeblock]
</description>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 563f7e2471..2f620df8fb 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2143,7 +2143,8 @@ GDScriptLanguage::GDScriptLanguage() {
GLOBAL_DEF("debug/gdscript/completion/autocomplete_setters_and_getters", false);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
- GLOBAL_DEF("debug/gdscript/warnings/" + warning, !warning.begins_with("unsafe_"));
+ bool default_enabled = !warning.begins_with("unsafe_") && i != GDScriptWarning::UNUSED_CLASS_VARIABLE;
+ GLOBAL_DEF("debug/gdscript/warnings/" + warning, default_enabled);
}
#endif // DEBUG_ENABLED
}
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index bbafef68ed..9e05c7b574 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -1128,25 +1128,11 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
d["@subpath"] = cp;
d["@path"] = p->get_path();
- p = base.ptr();
-
- while (p) {
-
- for (Set<StringName>::Element *E = p->members.front(); E; E = E->next()) {
-
- Variant value;
- if (ins->get(E->get(), value)) {
-
- String k = E->get();
- if (!d.has(k)) {
- d[k] = value;
- }
- }
+ for (Map<StringName, GDScript::MemberInfo>::Element *E = base->member_indices.front(); E; E = E->next()) {
+ if (!d.has(E->key())) {
+ d[E->key()] = ins->members[E->get().index];
}
-
- p = p->_base;
}
-
r_ret = d;
}
}
diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py
index 03aaa925f0..6e5273f5e0 100644
--- a/modules/mono/build_scripts/godot_tools_build.py
+++ b/modules/mono/build_scripts/godot_tools_build.py
@@ -82,7 +82,8 @@ def build(env_mono, api_sln_cmd):
target_filenames = [
'GodotTools.dll', 'GodotTools.IdeConnection.dll', 'GodotTools.BuildLogger.dll',
- 'GodotTools.ProjectEditor.dll', 'DotNet.Glob.dll', 'GodotTools.Core.dll'
+ 'GodotTools.ProjectEditor.dll', 'DotNet.Glob.dll', 'GodotTools.Core.dll',
+ 'JetBrains.Annotations.dll', 'Newtonsoft.Json.dll'
]
if env_mono['target'] == 'debug':
diff --git a/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs b/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs
index 4312ca0230..bb218c2f19 100644
--- a/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs
@@ -6,6 +6,7 @@ namespace GodotTools
VisualStudio, // TODO (Windows-only)
VisualStudioForMac, // Mac-only
MonoDevelop,
- VsCode
+ VsCode,
+ Rider
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 2a5d3de126..660971d912 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -6,8 +6,10 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using GodotTools.Ides;
+using GodotTools.Ides.Rider;
using GodotTools.Internals;
using GodotTools.ProjectEditor;
+using JetBrains.Annotations;
using static GodotTools.Internals.Globals;
using File = GodotTools.Utils.File;
using OS = GodotTools.Utils.OS;
@@ -189,6 +191,7 @@ namespace GodotTools
"code", "code-oss", "vscode", "vscode-oss", "visual-studio-code", "visual-studio-code-oss"
};
+ [UsedImplicitly]
public Error OpenInExternalEditor(Script script, int line, int col)
{
var editor = (ExternalEditorId) editorSettings.GetSetting("mono/editor/external_editor");
@@ -202,6 +205,12 @@ namespace GodotTools
throw new NotSupportedException();
case ExternalEditorId.VisualStudioForMac:
goto case ExternalEditorId.MonoDevelop;
+ case ExternalEditorId.Rider:
+ {
+ string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath);
+ RiderPathManager.OpenFile(GodotSharpDirs.ProjectSlnPath, scriptPath, line);
+ return Error.Ok;
+ }
case ExternalEditorId.MonoDevelop:
{
string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath);
@@ -306,6 +315,7 @@ namespace GodotTools
return Error.Ok;
}
+ [UsedImplicitly]
public bool OverridesExternalEditor()
{
return (ExternalEditorId) editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None;
@@ -419,18 +429,21 @@ namespace GodotTools
if (OS.IsWindows)
{
settingsHintStr += $",MonoDevelop:{(int) ExternalEditorId.MonoDevelop}" +
- $",Visual Studio Code:{(int) ExternalEditorId.VsCode}";
+ $",Visual Studio Code:{(int) ExternalEditorId.VsCode}" +
+ $",JetBrains Rider:{(int) ExternalEditorId.Rider}";
}
else if (OS.IsOSX)
{
settingsHintStr += $",Visual Studio:{(int) ExternalEditorId.VisualStudioForMac}" +
$",MonoDevelop:{(int) ExternalEditorId.MonoDevelop}" +
- $",Visual Studio Code:{(int) ExternalEditorId.VsCode}";
+ $",Visual Studio Code:{(int) ExternalEditorId.VsCode}" +
+ $",JetBrains Rider:{(int) ExternalEditorId.Rider}";
}
else if (OS.IsUnixLike())
{
settingsHintStr += $",MonoDevelop:{(int) ExternalEditorId.MonoDevelop}" +
- $",Visual Studio Code:{(int) ExternalEditorId.VsCode}";
+ $",Visual Studio Code:{(int) ExternalEditorId.VsCode}" +
+ $",JetBrains Rider:{(int) ExternalEditorId.Rider}";
}
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
@@ -448,6 +461,7 @@ namespace GodotTools
exportPluginWeak = WeakRef(exportPlugin);
BuildManager.Initialize();
+ RiderPathManager.Initialize();
GodotIdeManager = new GodotIdeManager();
AddChild(GodotIdeManager);
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index fb2cbabc8e..be2b70529e 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -30,7 +30,15 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="JetBrains.Annotations, Version=2019.1.3.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325">
+ <HintPath>..\packages\JetBrains.Annotations.2019.1.3\lib\net20\JetBrains.Annotations.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
<Reference Include="Mono.Posix" />
+ <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
+ <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
<Reference Include="System" />
<Reference Include="GodotSharp">
<HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharp.dll</HintPath>
@@ -47,6 +55,8 @@
<Compile Include="Ides\GodotIdeServer.cs" />
<Compile Include="Ides\MonoDevelop\EditorId.cs" />
<Compile Include="Ides\MonoDevelop\Instance.cs" />
+ <Compile Include="Ides\Rider\RiderPathLocator.cs" />
+ <Compile Include="Ides\Rider\RiderPathManager.cs" />
<Compile Include="Internals\BindingsGenerator.cs" />
<Compile Include="Internals\EditorProgress.cs" />
<Compile Include="Internals\GodotSharpDirs.cs" />
@@ -67,6 +77,7 @@
<Compile Include="BottomPanel.cs" />
<Compile Include="CsProjOperations.cs" />
<Compile Include="Utils\CollectionExtensions.cs" />
+ <Compile Include="Utils\User32Dll.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj">
@@ -86,5 +97,11 @@
<Name>GodotTools.Core</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Ides\Rider\.editorconfig" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
index f94d6f998c..3213de0127 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
@@ -72,6 +72,7 @@ namespace GodotTools.Ides
case ExternalEditorId.None:
case ExternalEditorId.VisualStudio:
case ExternalEditorId.VsCode:
+ case ExternalEditorId.Rider:
throw new NotSupportedException();
case ExternalEditorId.VisualStudioForMac:
goto case ExternalEditorId.MonoDevelop;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/.editorconfig b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/.editorconfig
new file mode 100644
index 0000000000..aca19790ca
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/.editorconfig
@@ -0,0 +1,6 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf \ No newline at end of file
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
new file mode 100644
index 0000000000..901ade71e3
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
@@ -0,0 +1,416 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Godot;
+using JetBrains.Annotations;
+using Microsoft.Win32;
+using Newtonsoft.Json;
+using Directory = System.IO.Directory;
+using Environment = System.Environment;
+using File = System.IO.File;
+using Path = System.IO.Path;
+using OS = GodotTools.Utils.OS;
+
+namespace GodotTools.Ides.Rider
+{
+ /// <summary>
+ /// This code is a modified version of the JetBrains resharper-unity plugin listed under Apache License 2.0 license:
+ /// https://github.com/JetBrains/resharper-unity/blob/master/unity/JetBrains.Rider.Unity.Editor/EditorPlugin/RiderPathLocator.cs
+ /// </summary>
+ public static class RiderPathLocator
+ {
+ public static RiderInfo[] GetAllRiderPaths()
+ {
+ try
+ {
+ if (OS.IsWindows)
+ {
+ return CollectRiderInfosWindows();
+ }
+ if (OS.IsOSX)
+ {
+ return CollectRiderInfosMac();
+ }
+ if (OS.IsUnixLike())
+ {
+ return CollectAllRiderPathsLinux();
+ }
+ throw new Exception("Unexpected OS.");
+ }
+ catch (Exception e)
+ {
+ GD.PushWarning(e.Message);
+ }
+
+ return new RiderInfo[0];
+ }
+
+ private static RiderInfo[] CollectAllRiderPathsLinux()
+ {
+ var installInfos = new List<RiderInfo>();
+ var home = Environment.GetEnvironmentVariable("HOME");
+ if (!string.IsNullOrEmpty(home))
+ {
+ var toolboxRiderRootPath = GetToolboxBaseDir();
+ installInfos.AddRange(CollectPathsFromToolbox(toolboxRiderRootPath, "bin", "rider.sh", false)
+ .Select(a => new RiderInfo(a, true)).ToList());
+
+ //$Home/.local/share/applications/jetbrains-rider.desktop
+ var shortcut = new FileInfo(Path.Combine(home, @".local/share/applications/jetbrains-rider.desktop"));
+
+ if (shortcut.Exists)
+ {
+ var lines = File.ReadAllLines(shortcut.FullName);
+ foreach (var line in lines)
+ {
+ if (!line.StartsWith("Exec=\""))
+ continue;
+ var path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault();
+ if (string.IsNullOrEmpty(path))
+ continue;
+
+ if (installInfos.Any(a => a.Path == path)) // avoid adding similar build as from toolbox
+ continue;
+ installInfos.Add(new RiderInfo(path, false));
+ }
+ }
+ }
+
+ // snap install
+ var snapInstallPath = "/snap/rider/current/bin/rider.sh";
+ if (new FileInfo(snapInstallPath).Exists)
+ installInfos.Add(new RiderInfo(snapInstallPath, false));
+
+ return installInfos.ToArray();
+ }
+
+ private static RiderInfo[] CollectRiderInfosMac()
+ {
+ var installInfos = new List<RiderInfo>();
+ // "/Applications/*Rider*.app"
+ var folder = new DirectoryInfo("/Applications");
+ if (folder.Exists)
+ {
+ installInfos.AddRange(folder.GetDirectories("*Rider*.app")
+ .Select(a => new RiderInfo(a.FullName, false))
+ .ToList());
+ }
+
+ // /Users/user/Library/Application Support/JetBrains/Toolbox/apps/Rider/ch-1/181.3870.267/Rider EAP.app
+ var toolboxRiderRootPath = GetToolboxBaseDir();
+ var paths = CollectPathsFromToolbox(toolboxRiderRootPath, "", "Rider*.app", true)
+ .Select(a => new RiderInfo(a, true));
+ installInfos.AddRange(paths);
+
+ return installInfos.ToArray();
+ }
+
+ private static RiderInfo[] CollectRiderInfosWindows()
+ {
+ var installInfos = new List<RiderInfo>();
+ var toolboxRiderRootPath = GetToolboxBaseDir();
+ var installPathsToolbox = CollectPathsFromToolbox(toolboxRiderRootPath, "bin", "rider64.exe", false).ToList();
+ installInfos.AddRange(installPathsToolbox.Select(a => new RiderInfo(a, true)).ToList());
+
+ var installPaths = new List<string>();
+ const string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
+ CollectPathsFromRegistry(registryKey, installPaths);
+ const string wowRegistryKey = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
+ CollectPathsFromRegistry(wowRegistryKey, installPaths);
+
+ installInfos.AddRange(installPaths.Select(a => new RiderInfo(a, false)).ToList());
+
+ return installInfos.ToArray();
+ }
+
+ private static string GetToolboxBaseDir()
+ {
+ if (OS.IsWindows)
+ {
+ var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ return Path.Combine(localAppData, @"JetBrains\Toolbox\apps\Rider");
+ }
+
+ if (OS.IsOSX)
+ {
+ var home = Environment.GetEnvironmentVariable("HOME");
+ if (!string.IsNullOrEmpty(home))
+ {
+ return Path.Combine(home, @"Library/Application Support/JetBrains/Toolbox/apps/Rider");
+ }
+ }
+
+ if (OS.IsUnixLike())
+ {
+ var home = Environment.GetEnvironmentVariable("HOME");
+ if (!string.IsNullOrEmpty(home))
+ {
+ return Path.Combine(home, @".local/share/JetBrains/Toolbox/apps/Rider");
+ }
+ }
+
+ throw new Exception("Unexpected OS.");
+ }
+
+ internal static ProductInfo GetBuildVersion(string path)
+ {
+ var buildTxtFileInfo = new FileInfo(Path.Combine(path, GetRelativePathToBuildTxt()));
+ var dir = buildTxtFileInfo.DirectoryName;
+ if (!Directory.Exists(dir))
+ return null;
+ var buildVersionFile = new FileInfo(Path.Combine(dir, "product-info.json"));
+ if (!buildVersionFile.Exists)
+ return null;
+ var json = File.ReadAllText(buildVersionFile.FullName);
+ return ProductInfo.GetProductInfo(json);
+ }
+
+ internal static Version GetBuildNumber(string path)
+ {
+ var file = new FileInfo(Path.Combine(path, GetRelativePathToBuildTxt()));
+ if (!file.Exists)
+ return null;
+ var text = File.ReadAllText(file.FullName);
+ if (text.Length <= 3)
+ return null;
+
+ var versionText = text.Substring(3);
+ return Version.TryParse(versionText, out var v) ? v : null;
+ }
+
+ internal static bool IsToolbox(string path)
+ {
+ return path.StartsWith(GetToolboxBaseDir());
+ }
+
+ private static string GetRelativePathToBuildTxt()
+ {
+ if (OS.IsWindows || OS.IsUnixLike())
+ return "../../build.txt";
+ if (OS.IsOSX)
+ return "Contents/Resources/build.txt";
+ throw new Exception("Unknown OS.");
+ }
+
+ private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
+ {
+ using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
+ {
+ if (key == null) return;
+ foreach (var subkeyName in key.GetSubKeyNames().Where(a => a.Contains("Rider")))
+ {
+ using (var subkey = key.OpenSubKey(subkeyName))
+ {
+ var folderObject = subkey?.GetValue("InstallLocation");
+ if (folderObject == null) continue;
+ var folder = folderObject.ToString();
+ var possiblePath = Path.Combine(folder, @"bin\rider64.exe");
+ if (File.Exists(possiblePath))
+ installPaths.Add(possiblePath);
+ }
+ }
+ }
+ }
+
+ private static string[] CollectPathsFromToolbox(string toolboxRiderRootPath, string dirName, string searchPattern,
+ bool isMac)
+ {
+ if (!Directory.Exists(toolboxRiderRootPath))
+ return new string[0];
+
+ var channelDirs = Directory.GetDirectories(toolboxRiderRootPath);
+ var paths = channelDirs.SelectMany(channelDir =>
+ {
+ try
+ {
+ // use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D
+ var historyFile = Path.Combine(channelDir, ".history.json");
+ if (File.Exists(historyFile))
+ {
+ var json = File.ReadAllText(historyFile);
+ var build = ToolboxHistory.GetLatestBuildFromJson(json);
+ if (build != null)
+ {
+ var buildDir = Path.Combine(channelDir, build);
+ var executablePaths = GetExecutablePaths(dirName, searchPattern, isMac, buildDir);
+ if (executablePaths.Any())
+ return executablePaths;
+ }
+ }
+
+ var channelFile = Path.Combine(channelDir, ".channel.settings.json");
+ if (File.Exists(channelFile))
+ {
+ var json = File.ReadAllText(channelFile).Replace("active-application", "active_application");
+ var build = ToolboxInstallData.GetLatestBuildFromJson(json);
+ if (build != null)
+ {
+ var buildDir = Path.Combine(channelDir, build);
+ var executablePaths = GetExecutablePaths(dirName, searchPattern, isMac, buildDir);
+ if (executablePaths.Any())
+ return executablePaths;
+ }
+ }
+
+ // changes in toolbox json files format may brake the logic above, so return all found Rider installations
+ return Directory.GetDirectories(channelDir)
+ .SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir));
+ }
+ catch (Exception e)
+ {
+ // do not write to Debug.Log, just log it.
+ Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
+ }
+
+ return new string[0];
+ })
+ .Where(c => !string.IsNullOrEmpty(c))
+ .ToArray();
+ return paths;
+ }
+
+ private static string[] GetExecutablePaths(string dirName, string searchPattern, bool isMac, string buildDir)
+ {
+ var folder = new DirectoryInfo(Path.Combine(buildDir, dirName));
+ if (!folder.Exists)
+ return new string[0];
+
+ if (!isMac)
+ return new[] {Path.Combine(folder.FullName, searchPattern)}.Where(File.Exists).ToArray();
+ return folder.GetDirectories(searchPattern).Select(f => f.FullName)
+ .Where(Directory.Exists).ToArray();
+ }
+
+ // Disable the "field is never assigned" compiler warning. We never assign it, but Unity does.
+ // Note that Unity disable this warning in the generated C# projects
+#pragma warning disable 0649
+
+ [Serializable]
+ class ToolboxHistory
+ {
+ public List<ItemNode> history;
+
+ public static string GetLatestBuildFromJson(string json)
+ {
+ try
+ {
+ return JsonConvert.DeserializeObject<ToolboxHistory>(json).history.LastOrDefault()?.item.build;
+ }
+ catch (Exception)
+ {
+ Logger.Warn($"Failed to get latest build from json {json}");
+ }
+
+ return null;
+ }
+ }
+
+ [Serializable]
+ class ItemNode
+ {
+ public BuildNode item;
+ }
+
+ [Serializable]
+ class BuildNode
+ {
+ public string build;
+ }
+
+ [Serializable]
+ public class ProductInfo
+ {
+ public string version;
+ public string versionSuffix;
+
+ [CanBeNull]
+ internal static ProductInfo GetProductInfo(string json)
+ {
+ try
+ {
+ var productInfo = JsonConvert.DeserializeObject<ProductInfo>(json);
+ return productInfo;
+ }
+ catch (Exception)
+ {
+ Logger.Warn($"Failed to get version from json {json}");
+ }
+
+ return null;
+ }
+ }
+
+ // ReSharper disable once ClassNeverInstantiated.Global
+ [Serializable]
+ class ToolboxInstallData
+ {
+ // ReSharper disable once InconsistentNaming
+ public ActiveApplication active_application;
+
+ [CanBeNull]
+ public static string GetLatestBuildFromJson(string json)
+ {
+ try
+ {
+ var toolbox = JsonConvert.DeserializeObject<ToolboxInstallData>(json);
+ var builds = toolbox.active_application.builds;
+ if (builds != null && builds.Any())
+ return builds.First();
+ }
+ catch (Exception)
+ {
+ Logger.Warn($"Failed to get latest build from json {json}");
+ }
+
+ return null;
+ }
+ }
+
+ [Serializable]
+ class ActiveApplication
+ {
+ // ReSharper disable once InconsistentNaming
+ public List<string> builds;
+ }
+
+#pragma warning restore 0649
+
+ public struct RiderInfo
+ {
+ public bool IsToolbox;
+ public string Presentation;
+ public Version BuildNumber;
+ public ProductInfo ProductInfo;
+ public string Path;
+
+ public RiderInfo(string path, bool isToolbox)
+ {
+ BuildNumber = GetBuildNumber(path);
+ ProductInfo = GetBuildVersion(path);
+ Path = new FileInfo(path).FullName; // normalize separators
+ var presentation = $"Rider {BuildNumber}";
+
+ if (ProductInfo != null && !string.IsNullOrEmpty(ProductInfo.version))
+ {
+ var suffix = string.IsNullOrEmpty(ProductInfo.versionSuffix) ? "" : $" {ProductInfo.versionSuffix}";
+ presentation = $"Rider {ProductInfo.version}{suffix}";
+ }
+
+ if (isToolbox)
+ presentation += " (JetBrains Toolbox)";
+
+ Presentation = presentation;
+ IsToolbox = isToolbox;
+ }
+ }
+
+ private static class Logger
+ {
+ internal static void Warn(string message, Exception e = null)
+ {
+ throw new Exception(message, e);
+ }
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
new file mode 100644
index 0000000000..b7dba13bbe
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Godot;
+using GodotTools.Internals;
+
+namespace GodotTools.Ides.Rider
+{
+ public static class RiderPathManager
+ {
+ private static readonly string editorPathSettingName= "mono/editor/editor_path_optional";
+
+ private static string GetRiderPathFromSettings()
+ {
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+ if (editorSettings.HasSetting(editorPathSettingName))
+ return (string) editorSettings.GetSetting(editorPathSettingName);
+ return null;
+ }
+
+ public static void Initialize()
+ {
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+ var editor = (ExternalEditorId) editorSettings.GetSetting("mono/editor/external_editor");
+ if (editor == ExternalEditorId.Rider)
+ {
+ if (!editorSettings.HasSetting(editorPathSettingName))
+ {
+ Globals.EditorDef(editorPathSettingName, "Optional");
+ editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
+ {
+ ["type"] = Variant.Type.String,
+ ["name"] = editorPathSettingName,
+ ["hint"] = PropertyHint.File,
+ ["hint_string"] = ""
+ });
+ }
+
+ var riderPath = (string) editorSettings.GetSetting(editorPathSettingName);
+ if (IsRiderAndExists(riderPath))
+ {
+ Globals.EditorDef(editorPathSettingName, riderPath);
+ return;
+ }
+
+ var paths = RiderPathLocator.GetAllRiderPaths();
+
+ if (!paths.Any())
+ return;
+
+ var newPath = paths.Last().Path;
+ Globals.EditorDef(editorPathSettingName, newPath);
+ editorSettings.SetSetting(editorPathSettingName, newPath);
+ }
+ }
+
+ private static bool IsRider(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ return false;
+ }
+
+ var fileInfo = new FileInfo(path);
+ var filename = fileInfo.Name.ToLowerInvariant();
+ return filename.StartsWith("rider", StringComparison.Ordinal);
+ }
+
+ private static string CheckAndUpdatePath(string riderPath)
+ {
+ if (IsRiderAndExists(riderPath))
+ {
+ return riderPath;
+ }
+
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+ var paths = RiderPathLocator.GetAllRiderPaths();
+
+ if (!paths.Any())
+ return null;
+
+ var newPath = paths.Last().Path;
+ editorSettings.SetSetting(editorPathSettingName, newPath);
+ Globals.EditorDef(editorPathSettingName, newPath);
+ return newPath;
+ }
+
+ private static bool IsRiderAndExists(string riderPath)
+ {
+ return !string.IsNullOrEmpty(riderPath) && IsRider(riderPath) && new FileInfo(riderPath).Exists;
+ }
+
+ public static void OpenFile(string slnPath, string scriptPath, int line)
+ {
+ var pathFromSettings = GetRiderPathFromSettings();
+ var path = CheckAndUpdatePath(pathFromSettings);
+
+ var args = new List<string>();
+ args.Add(slnPath);
+ if (line >= 0)
+ {
+ args.Add("--line");
+ args.Add(line.ToString());
+ }
+ args.Add(scriptPath);
+ try
+ {
+ Utils.OS.RunProcess(path, args);
+ }
+ catch (Exception e)
+ {
+ GD.PushError($"Error when trying to run code editor: JetBrains Rider. Exception message: '{e.Message}'");
+ }
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index e89ea0c476..1fe07e0bb6 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -157,6 +157,8 @@ namespace GodotTools.Utils
process.BeginOutputReadLine();
process.BeginErrorReadLine();
+ if (IsWindows && process.Id>0)
+ User32Dll.AllowSetForegroundWindow(process.Id); // allows application to focus itself
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/User32Dll.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/User32Dll.cs
new file mode 100644
index 0000000000..6810a991b3
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/User32Dll.cs
@@ -0,0 +1,10 @@
+using System.Runtime.InteropServices;
+
+namespace GodotTools.Utils
+{
+ public static class User32Dll
+ {
+ [DllImport("user32.dll")]
+ public static extern bool AllowSetForegroundWindow(int dwProcessId);
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/packages.config b/modules/mono/editor/GodotTools/GodotTools/packages.config
new file mode 100644
index 0000000000..2db4b4acc6
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="JetBrains.Annotations" version="2019.1.3" targetFramework="net45" />
+ <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index b37a21f37f..500736bd3f 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -151,14 +151,14 @@ def setup_msvc_auto(env):
env['bits'] = '64'
else:
env['bits'] = '32'
- print(" Found MSVC version %s, arch %s, bits=%s" % (env['MSVC_VERSION'], env['TARGET_ARCH'], env['bits']))
+ print("Found MSVC version %s, arch %s, bits=%s" % (env['MSVC_VERSION'], env['TARGET_ARCH'], env['bits']))
if env['TARGET_ARCH'] in ('amd64', 'x86_64'):
env["x86_libtheora_opt_vc"] = False
def setup_mingw(env):
"""Set up env for use with mingw"""
# Nothing to do here
- print("Using Mingw")
+ print("Using MinGW")
pass
def configure_msvc(env, manual_msvc_config):
@@ -294,7 +294,10 @@ def configure_mingw(env):
## Compiler configuration
if (os.name == "nt"):
- env['ENV']['TMP'] = os.environ['TMP'] # way to go scons, you can be so stupid sometimes
+ # Force splitting libmodules.a in multiple chunks to work around
+ # issues reaching the linker command line size limit, which also
+ # seem to induce huge slowdown for 'ar' (GH-30892).
+ env['split_libmodules'] = True
else:
env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 99a2881d58..7524571956 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -657,6 +657,7 @@ void DynamicFont::_reload_cache() {
if (!data.is_valid()) {
data_at_size.unref();
outline_data_at_size.unref();
+ fallbacks.resize(0);
fallback_data_at_size.resize(0);
fallback_outline_data_at_size.resize(0);
return;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 593c399f62..b21546af2f 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -1333,6 +1333,7 @@ void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) {
void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) {
ERR_FAIL_COND(p_texture == this);
+ ERR_FAIL_COND(p_texture.is_null());
ERR_FAIL_INDEX(p_idx, pieces.size());
pieces.write[p_idx].texture = p_texture;
};
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index c897365b21..bf9079c9f4 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -720,7 +720,10 @@ void Theme::clear() {
while ((K = icon_map.next(K))) {
const StringName *L = NULL;
while ((L = icon_map[*K].next(L))) {
- icon_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed");
+ Ref<Texture> icon = icon_map[*K][*L];
+ if (icon.is_valid()) {
+ icon->disconnect("changed", this, "_emit_theme_changed");
+ }
}
}
}
@@ -730,7 +733,10 @@ void Theme::clear() {
while ((K = style_map.next(K))) {
const StringName *L = NULL;
while ((L = style_map[*K].next(L))) {
- style_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed");
+ Ref<StyleBox> style = style_map[*K][*L];
+ if (style.is_valid()) {
+ style->disconnect("changed", this, "_emit_theme_changed");
+ }
}
}
}
@@ -740,7 +746,10 @@ void Theme::clear() {
while ((K = font_map.next(K))) {
const StringName *L = NULL;
while ((L = font_map[*K].next(L))) {
- font_map[*K][*L]->disconnect("changed", this, "_emit_theme_changed");
+ Ref<Font> font = font_map[*K][*L];
+ if (font.is_valid()) {
+ font->disconnect("changed", this, "_emit_theme_changed");
+ }
}
}
}
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 9f99732714..797de1d863 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -2259,6 +2259,8 @@ void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) {
int index = 0;
for (int i = 0; i < inputs_strings.size(); i++) {
Vector<String> arr = inputs_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
if (arr[0].to_int() == p_id) {
index += arr[0].size();
count = arr[1].size() - 1;
@@ -2292,6 +2294,8 @@ void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_na
int index = 0;
for (int i = 0; i < inputs_strings.size(); i++) {
Vector<String> arr = inputs_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
if (arr[0].to_int() == p_id) {
index += arr[0].size() + arr[1].size();
count = arr[2].size() - 1;
@@ -2325,6 +2329,8 @@ void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) {
int index = 0;
for (int i = 0; i < output_strings.size(); i++) {
Vector<String> arr = output_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
if (arr[0].to_int() == p_id) {
index += arr[0].size();
count = arr[1].size() - 1;
@@ -2358,6 +2364,8 @@ void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_n
int index = 0;
for (int i = 0; i < output_strings.size(); i++) {
Vector<String> arr = output_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
if (arr[0].to_int() == p_id) {
index += arr[0].size() + arr[1].size();
count = arr[2].size() - 1;
@@ -2405,6 +2413,8 @@ void VisualShaderNodeGroupBase::_apply_port_changes() {
for (int i = 0; i < inputs_strings.size(); i++) {
Vector<String> arr = inputs_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
Port port;
port.type = (PortType)arr[1].to_int();
port.name = arr[2];
@@ -2412,6 +2422,8 @@ void VisualShaderNodeGroupBase::_apply_port_changes() {
}
for (int i = 0; i < outputs_strings.size(); i++) {
Vector<String> arr = outputs_strings[i].split(",");
+ ERR_FAIL_COND(arr.size() != 3);
+
Port port;
port.type = (PortType)arr[1].to_int();
port.name = arr[2];
diff --git a/thirdparty/vhacd/0003-fix-musl-build.patch b/thirdparty/vhacd/0003-fix-musl-build.patch
new file mode 100644
index 0000000000..67af8546f3
--- /dev/null
+++ b/thirdparty/vhacd/0003-fix-musl-build.patch
@@ -0,0 +1,15 @@
+diff --git a/thirdparty/vhacd/inc/vhacdMutex.h b/thirdparty/vhacd/inc/vhacdMutex.h
+index 6b09259200..d587dd6387 100644
+--- a/thirdparty/vhacd/inc/vhacdMutex.h
++++ b/thirdparty/vhacd/inc/vhacdMutex.h
+@@ -71,7 +71,9 @@
+ #include <pthread.h>
+ #endif
+
+-#if defined(__APPLE__)
++// -- GODOT start --
++#if defined(__APPLE__) || !defined(__GLIBC__)
++// -- GODOT end --
+ #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+ #endif
+
diff --git a/thirdparty/vhacd/inc/vhacdMutex.h b/thirdparty/vhacd/inc/vhacdMutex.h
index 6b09259200..d587dd6387 100644
--- a/thirdparty/vhacd/inc/vhacdMutex.h
+++ b/thirdparty/vhacd/inc/vhacdMutex.h
@@ -71,7 +71,9 @@
#include <pthread.h>
#endif
-#if defined(__APPLE__)
+// -- GODOT start --
+#if defined(__APPLE__) || !defined(__GLIBC__)
+// -- GODOT end --
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#endif