summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/collision_object_bullet.h2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp1
-rw-r--r--modules/bullet/shape_bullet.cpp2
-rw-r--r--modules/csg/icons/CSGBox3D.svg7
-rw-r--r--modules/csg/icons/CSGCapsule3D.svg7
-rw-r--r--modules/csg/icons/CSGCombiner3D.svg9
-rw-r--r--modules/csg/icons/CSGCylinder3D.svg7
-rw-r--r--modules/csg/icons/CSGMesh3D.svg7
-rw-r--r--modules/csg/icons/CSGPolygon3D.svg7
-rw-r--r--modules/csg/icons/CSGSphere3D.svg7
-rw-r--r--modules/csg/icons/CSGTorus3D.svg7
-rw-r--r--modules/denoise/lightmap_denoiser.h2
-rw-r--r--modules/gdnative/icons/GDNativeLibrary.svg6
-rw-r--r--modules/gdnative/icons/NativeScript.svg6
-rw-r--r--modules/gdnative/xr/config.py6
-rw-r--r--modules/gdnavigation/rvo_agent.h3
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp77
-rw-r--r--modules/gdscript/gdscript_analyzer.h3
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp9
-rw-r--r--modules/gdscript/gdscript_compiler.h14
-rw-r--r--modules/gdscript/gdscript_editor.cpp8
-rw-r--r--modules/gdscript/icons/GDScript.svg6
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp76
-rw-r--r--modules/glslang/SCsub6
-rw-r--r--modules/glslang/register_types.cpp111
-rw-r--r--modules/gridmap/grid_map.cpp2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h2
-rw-r--r--modules/gridmap/icons/GridMap.svg6
-rw-r--r--modules/jsonrpc/jsonrpc.h2
-rw-r--r--modules/mono/SCsub5
-rw-r--r--modules/mono/build_scripts/godot_net_sdk_build.py45
-rw-r--r--modules/mono/csharp_script.cpp205
-rw-r--r--modules/mono/csharp_script.h3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj19
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs65
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs5
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets36
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.sln6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs339
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs (renamed from modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs)10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs (renamed from modules/mono/editor/GodotTools/GodotTools/BuildManager.cs)132
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs (renamed from modules/mono/editor/GodotTools/GodotTools/BuildTab.cs)212
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildResult.cs8
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs42
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs185
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs8
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs296
-rwxr-xr-xmodules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs13
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs79
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs6
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs12
-rw-r--r--modules/mono/editor/bindings_generator.cpp4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs13
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs29
-rw-r--r--modules/mono/glue/base_object_glue.cpp1
-rw-r--r--modules/mono/glue/glue_header.h1
-rw-r--r--modules/mono/glue/rid_glue.cpp2
-rw-r--r--modules/mono/icons/CSharpScript.svg6
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
-rw-r--r--modules/opensimplex/icons/NoiseTexture.svg4
-rw-r--r--modules/visual_script/icons/VisualScript.svg7
-rw-r--r--modules/visual_script/visual_script_editor.cpp6
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp1
-rw-r--r--modules/webrtc/doc_classes/WebRTCPeerConnection.xml2
74 files changed, 1305 insertions, 941 deletions
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index f1423a69e4..36b3a9550c 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -31,9 +31,9 @@
#ifndef COLLISION_OBJECT_BULLET_H
#define COLLISION_OBJECT_BULLET_H
+#include "core/class_db.h"
#include "core/math/transform.h"
#include "core/math/vector3.h"
-#include "core/object.h"
#include "core/vset.h"
#include "shape_owner_bullet.h"
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 76c0e0e607..eb599df74c 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -264,6 +264,7 @@ RigidBodyBullet::RigidBodyBullet() :
btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, nullptr, localInertia);
btBody = bulletnew(btRigidBody(cInfo));
+ btBody->setFriction(1.0);
reload_shapes();
setupBulletCollisionObject(btBody);
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 340680c8d9..fdc2944dad 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -275,7 +275,7 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) {
}
btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
- return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge));
+ return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1]));
}
/* Cylinder */
diff --git a/modules/csg/icons/CSGBox3D.svg b/modules/csg/icons/CSGBox3D.svg
index 67e34df444..ceef9196a7 100644
--- a/modules/csg/icons/CSGBox3D.svg
+++ b/modules/csg/icons/CSGBox3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/>
-<path transform="translate(0 1036.4)" d="m8 0.94531-7 3.5v7.2227l7 3.5 0.29492-0.14844c-0.18282-0.30101-0.29492-0.64737-0.29492-1.0195v-2c0-0.72651 0.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c0.36419 0 0.70336 0.10754 1 0.2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc9c9c" stroke-width="1.0667"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m8 .94531-7 3.5v7.2227l7 3.5.29492-.14844c-.18282-.30101-.29492-.64737-.29492-1.0195v-2c0-.72651.40824-1.3664 1-1.7168v-1.6699l4-2v1.3867h1c.36419 0 .70336.10754 1 .2832v-3.8379zm0 2.1152 3.9395 1.9707-3.9395 1.9688-3.9395-1.9688zm-5 3.5527 4 2v3.9414l-4-2.002z" fill="#fc9c9c" stroke-width="1.0667"/></svg>
diff --git a/modules/csg/icons/CSGCapsule3D.svg b/modules/csg/icons/CSGCapsule3D.svg
index 92a7b5a870..14e582ee84 100644
--- a/modules/csg/icons/CSGCapsule3D.svg
+++ b/modules/csg/icons/CSGCapsule3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g>
-<path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922 0.092943 0 0.18367-0.008623 0.27539-0.013672-0.17055-0.29341-0.27539-0.62792-0.27539-0.98633v-2c0-0.72887 0.41095-1.3691 1.0059-1.7188v-0.28125c0.34771-0.034464 0.68259-0.10691 1.0156-0.19922 0.10394-0.99856 0.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-0.66556-0.1047-1.2974-0.37231-1.9941-0.66211v-1.3223c0-1.3474 0.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957 0.4088 1.9941 1.5256 1.9941 2.873v1.3457c-0.68406 0.3054-1.3142 0.57292-1.9941 0.66602v-4.8848zm-4.0059 6.334c0.67836 0.2231 1.3126 0.44599 1.9941 0.52539v2.8848c-1.1957-0.4092-1.9941-1.5237-1.9941-2.8711v-0.53906z" fill="#fc9c9c"/>
-<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.7527 0-5 2.2418-5 4.9902v4.0176c0 2.7484 2.2473 4.9922 5 4.9922.092943 0 .18367-.008623.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72887.41095-1.3691 1.0059-1.7188v-.28125c.34771-.034464.68259-.10691 1.0156-.19922.10394-.99856.95603-1.8008 1.9785-1.8008h1v-2.0098c0-2.7484-2.2473-4.9902-5-4.9902zm-1.0059 2.127v4.8574c-.66556-.1047-1.2974-.37231-1.9941-.66211v-1.3223c0-1.3474.79841-2.4642 1.9941-2.873zm2.0117 0c1.1957.4088 1.9941 1.5256 1.9941 2.873v1.3457c-.68406.3054-1.3142.57292-1.9941.66602v-4.8848zm-4.0059 6.334c.67836.2231 1.3126.44599 1.9941.52539v2.8848c-1.1957-.4092-1.9941-1.5237-1.9941-2.8711v-.53906z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
diff --git a/modules/csg/icons/CSGCombiner3D.svg b/modules/csg/icons/CSGCombiner3D.svg
index cce2902e24..50ce4179d9 100644
--- a/modules/csg/icons/CSGCombiner3D.svg
+++ b/modules/csg/icons/CSGCombiner3D.svg
@@ -1,8 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/>
-<g fill="#fc9c9c">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-0.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046 0.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc9c9c"/>
-</g>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/><path d="m3 1c-1.1046 0-2 .89543-2 2h2zm2 0v2h2v-2zm4 0v2h2v-2zm4 0v2h2c0-1.1046-.89543-2-2-2zm-12 4v2h2v-2zm12 0v2h2v-2zm-12 4v2h2v-2zm0 4c0 1.1046.89543 2 2 2v-2zm4 0v2h2v-2z" fill="#fc9c9c"/></svg>
diff --git a/modules/csg/icons/CSGCylinder3D.svg b/modules/csg/icons/CSGCylinder3D.svg
index 645a74c79b..c84594928a 100644
--- a/modules/csg/icons/CSGCylinder3D.svg
+++ b/modules/csg/icons/CSGCylinder3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 14.999999 14.999999" xmlns="http://www.w3.org/2000/svg">
-<g>
-<path transform="scale(.9375)" d="m8 1c-1.7469 0-3.328 0.22648-4.5586 0.63672-0.61528 0.20512-1.1471 0.45187-1.5898 0.80078-0.44272 0.34891-0.85156 0.88101-0.85156 1.5625v8c0 0.68149 0.40884 1.2155 0.85156 1.5645 0.44272 0.34891 0.97457 0.59577 1.5898 0.80078 1.2306 0.41024 2.8117 0.63477 4.5586 0.63477 0.095648 0 0.18467-0.008426 0.2793-0.009766-0.1722-0.29446-0.2793-0.62995-0.2793-0.99023v-1c-1.5668 0-2.9867-0.2195-3.9277-0.5332-0.46329-0.15435-0.90474-0.33752-1.0723-0.4668v-5.8125c0.1468 0.058667 0.2835 0.12515 0.44141 0.17773 1.2306 0.41024 2.8117 0.63477 4.5586 0.63477s3.328-0.22453 4.5586-0.63477c0.15791-0.052267 0.29461-0.11864 0.44141-0.17773v1.8125h1c0.36396 0 0.70348 0.10774 1 0.2832v-4.2832c0-0.68149-0.40884-1.2136-0.85156-1.5625-0.44272-0.34891-0.97457-0.59566-1.5898-0.80078-1.2306-0.41024-2.8117-0.63672-4.5586-0.63672zm0 2c1.5668 0 2.9867 0.22145 3.9277 0.53516 0.46368 0.15456 0.80138 0.33741 0.96875 0.4668-0.16752 0.12928-0.50546 0.3105-0.96875 0.46484-0.94102 0.31371-2.361 0.5332-3.9277 0.5332s-2.9867-0.2195-3.9277-0.5332c-0.46329-0.15435-0.80123-0.33556-0.96875-0.46484 0.16737-0.12939 0.50507-0.31224 0.96875-0.4668 0.94102-0.31371 2.361-0.53516 3.9277-0.53516z" fill="#fc9c9c" stroke-width="1.0667"/>
-<path d="m11.25 8.4375c-0.51938 0-0.9375 0.41812-0.9375 0.9375v0.9375h1.875v1.875h0.9375c0.51938 0 0.9375-0.41812 0.9375-0.9375v-1.875c0-0.51938-0.41812-0.9375-0.9375-0.9375zm0.9375 3.75h-1.875v-1.875h-0.9375c-0.51938 0-0.9375 0.41812-0.9375 0.9375v1.875c0 0.51938 0.41812 0.9375 0.9375 0.9375h1.875c0.51938 0 0.9375-0.41812 0.9375-0.9375z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.7469 0-3.328.22648-4.5586.63672-.61528.20512-1.1471.45187-1.5898.80078-.44272.34891-.85156.88101-.85156 1.5625v8c0 .68149.40884 1.2155.85156 1.5645.44272.34891.97457.59577 1.5898.80078 1.2306.41024 2.8117.63477 4.5586.63477.095648 0 .18467-.008426.2793-.009766-.1722-.29446-.2793-.62995-.2793-.99023v-1c-1.5668 0-2.9867-.2195-3.9277-.5332-.46329-.15435-.90474-.33752-1.0723-.4668v-5.8125c.1468.058667.2835.12515.44141.17773 1.2306.41024 2.8117.63477 4.5586.63477s3.328-.22453 4.5586-.63477c.15791-.052267.29461-.11864.44141-.17773v1.8125h1c.36396 0 .70348.10774 1 .2832v-4.2832c0-.68149-.40884-1.2136-.85156-1.5625-.44272-.34891-.97457-.59566-1.5898-.80078-1.2306-.41024-2.8117-.63672-4.5586-.63672zm0 2c1.5668 0 2.9867.22145 3.9277.53516.46368.15456.80138.33741.96875.4668-.16752.12928-.50546.3105-.96875.46484-.94102.31371-2.361.5332-3.9277.5332s-2.9867-.2195-3.9277-.5332c-.46329-.15435-.80123-.33556-.96875-.46484.16737-.12939.50507-.31224.96875-.4668.94102-.31371 2.361-.53516 3.9277-.53516z" fill="#fc9c9c" stroke-width="1.0667" transform="scale(.9375)"/><path d="m11.25 8.4375c-.51938 0-.9375.41812-.9375.9375v.9375h1.875v1.875h.9375c.51938 0 .9375-.41812.9375-.9375v-1.875c0-.51938-.41812-.9375-.9375-.9375zm.9375 3.75h-1.875v-1.875h-.9375c-.51938 0-.9375.41812-.9375.9375v1.875c0 .51938.41812.9375.9375.9375h1.875c.51938 0 .9375-.41812.9375-.9375z" fill="#84c2ff"/></svg>
diff --git a/modules/csg/icons/CSGMesh3D.svg b/modules/csg/icons/CSGMesh3D.svg
index 6e940a4aa5..962e71f6ae 100644
--- a/modules/csg/icons/CSGMesh3D.svg
+++ b/modules/csg/icons/CSGMesh3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g>
-<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h3.2695v-2h-3.2715c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-5.8555l4.916 4.916c0.31428-0.20669 0.68609-0.33008 1.084-0.33008 0-0.3979 0.12338-0.76971 0.33008-1.084l-4.916-4.916h5.8574c0.17478 0.30301 0.42598 0.55488 0.72852 0.73047v3.2695h2v-3.2715c0.61771-0.35663 0.99874-1.0152 1-1.7285 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1z" fill="#fc9c9c"/>
-<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2 .0005649.71397.38169 1.3735 1 1.7305v6.541c-.61771.35663-.99874 1.0152-1 1.7285 0 1.1046.89543 2 2 2 .71397-.000565 1.3735-.38169 1.7305-1h3.2695v-2h-3.2715c-.17478-.30301-.42598-.55488-.72852-.73047v-5.8555l4.916 4.916c.31428-.20669.68609-.33008 1.084-.33008 0-.3979.12338-.76971.33008-1.084l-4.916-4.916h5.8574c.17478.30301.42598.55488.72852.73047v3.2695h2v-3.2715c.61771-.35663.99874-1.0152 1-1.7285 0-1.1046-.89543-2-2-2-.71397.0005648-1.3735.38169-1.7305 1h-6.541c-.35663-.61771-1.0152-.99874-1.7285-1z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
diff --git a/modules/csg/icons/CSGPolygon3D.svg b/modules/csg/icons/CSGPolygon3D.svg
index 71b03cb8e6..1d496e5fd9 100644
--- a/modules/csg/icons/CSGPolygon3D.svg
+++ b/modules/csg/icons/CSGPolygon3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m7.9629 1.002c-0.14254 0.00487-0.28238 0.04016-0.41016 0.10352l-6 3c-0.33878 0.16944-0.55276 0.51574-0.55273 0.89453v5.832c-0.105 0.61631 0.37487 1.1768 1 1.168h5v2c2.16e-5 0.67546 0.64487 1.1297 1.2617 0.95898-0.16118-0.28721-0.26172-0.61135-0.26172-0.95898v-2c0-0.72673 0.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c0.36397 0 0.70348 0.10774 1 0.2832v-3.2773c6e-6 -0.00195 6e-6 -0.0039094 0-0.0058594 2.6e-5 -0.37879-0.21395-0.72509-0.55273-0.89453l-6-3c-0.15022-0.074574-0.31679-0.11017-0.48438-0.10352zm0.037109 2.1172l3.7637 1.8809-2.7637 1.3809v-1.3809c-5.52e-5 -0.55226-0.44774-0.99994-1-1h-1.7617l1.7617-0.88086zm-5 2.8809h4v4h-4v-4z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9629 1.002c-.14254.00487-.28238.04016-.41016.10352l-6 3c-.33878.16944-.55276.51574-.55273.89453v5.832c-.105.61631.37487 1.1768 1 1.168h5v2c.0000216.67546.64487 1.1297 1.2617.95898-.16118-.28721-.26172-.61135-.26172-.95898v-2c0-.72673.40794-1.3664 1-1.7168v-1.666l4-2v1.3828h1c.36397 0 .70348.10774 1 .2832v-3.2773c.000006-.00195.000006-.0039094 0-.0058594.000026-.37879-.21395-.72509-.55273-.89453l-6-3c-.15022-.074574-.31679-.11017-.48438-.10352zm.037109 2.1172 3.7637 1.8809-2.7637 1.3809v-1.3809c-.0000552-.55226-.44774-.99994-1-1h-1.7617l1.7617-.88086zm-5 2.8809h4v4h-4z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
diff --git a/modules/csg/icons/CSGSphere3D.svg b/modules/csg/icons/CSGSphere3D.svg
index f81b566993..639e38f49f 100644
--- a/modules/csg/icons/CSGSphere3D.svg
+++ b/modules/csg/icons/CSGSphere3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g>
-<path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 0.093042 0 0.18321-0.01004 0.27539-0.013672-0.17055-0.29341-0.27539-0.62792-0.27539-0.98633v-2c0-0.72673 0.40794-1.3664 1-1.7168v-0.33398c0.34074-0.019259 0.67728-0.069097 1.0156-0.10547 0.083091-1.0187 0.94713-1.8438 1.9844-1.8438h2c0.35841 0 0.69292 0.10484 0.98633 0.27539 0.003633-0.092184 0.013672-0.18235 0.013672-0.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-0.071342-2.6061-0.29819-3.9434-0.69141 0.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549 0.41253 3.637 2.0767 3.9414 4.1699-1.3046 0.36677-2.6158 0.60259-3.9414 0.6875v-4.8574zm-5.7793 6.2988c1.2733 0.31892 2.5337 0.50215 3.7793 0.5625v2.9414c-1.8291-0.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc9c9c"/>
-<path d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 .093042 0 .18321-.01004.27539-.013672-.17055-.29341-.27539-.62792-.27539-.98633v-2c0-.72673.40794-1.3664 1-1.7168v-.33398c.34074-.019259.67728-.069097 1.0156-.10547.083091-1.0187.94713-1.8438 1.9844-1.8438h2c.35841 0 .69292.10484.98633.27539.003633-.092184.013672-.18235.013672-.27539 0-3.8541-3.1459-7-7-7zm-1 2.0977v4.8711c-1.2931-.071342-2.6061-.29819-3.9434-.69141.30081-2.0978 1.8852-3.7665 3.9434-4.1797zm2 0c2.0549.41253 3.637 2.0767 3.9414 4.1699-1.3046.36677-2.6158.60259-3.9414.6875zm-5.7793 6.2988c1.2733.31892 2.5337.50215 3.7793.5625v2.9414c-1.8291-.36719-3.266-1.7339-3.7793-3.5039z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
diff --git a/modules/csg/icons/CSGTorus3D.svg b/modules/csg/icons/CSGTorus3D.svg
index 3d30aa47b2..eb8c0f37cb 100644
--- a/modules/csg/icons/CSGTorus3D.svg
+++ b/modules/csg/icons/CSGTorus3D.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 3c-1.8145 0-3.4691 0.41721-4.7461 1.1621-1.277 0.745-2.2539 1.9082-2.2539 3.3379 0 1.4298 0.9769 2.5949 2.2539 3.3398 1.277 0.7449 2.9316 1.1602 4.7461 1.1602 0-1.0907 0.90931-2 2-2 0-0.080836 0.013744-0.15778 0.023438-0.23633-0.61769 0.14673-1.3008 0.23633-2.0234 0.23633-1.4992 0-2.8437-0.36687-3.7383-0.88867-0.89456-0.5219-1.2617-1.108-1.2617-1.6113 0-0.5032 0.36716-1.0876 1.2617-1.6094 0.89456-0.5219 2.2391-0.89062 3.7383-0.89062s2.8437 0.36872 3.7383 0.89062c0.89456 0.5218 1.2617 1.1062 1.2617 1.6094 0 0.15978-0.053679 0.32822-0.13281 0.5h1.1328c0.32481 0 0.62893 0.088408 0.90234 0.23047 0.057552-0.23582 0.097656-0.47718 0.097656-0.73047 0-1.4297-0.9769-2.5929-2.2539-3.3379-1.277-0.7449-2.9316-1.1621-4.7461-1.1621z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-<path transform="translate(0 1036.4)" d="m12 9c-0.55401 0-1 0.44599-1 1v1h2v2h1c0.55401 0 1-0.44599 1-1v-2c0-0.55401-0.44599-1-1-1h-2zm1 4h-2v-2h-1c-0.55401 0-1 0.44599-1 1v2c0 0.55401 0.44599 1 1 1h2c0.55401 0 1-0.44599 1-1v-1z" fill="#84c2ff"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3c-1.8145 0-3.4691.41721-4.7461 1.1621-1.277.745-2.2539 1.9082-2.2539 3.3379 0 1.4298.9769 2.5949 2.2539 3.3398s2.9316 1.1602 4.7461 1.1602c0-1.0907.90931-2 2-2 0-.080836.013744-.15778.023438-.23633-.61769.14673-1.3008.23633-2.0234.23633-1.4992 0-2.8437-.36687-3.7383-.88867-.89456-.5219-1.2617-1.108-1.2617-1.6113 0-.5032.36716-1.0876 1.2617-1.6094.89456-.5219 2.2391-.89062 3.7383-.89062s2.8437.36872 3.7383.89062c.89456.5218 1.2617 1.1062 1.2617 1.6094 0 .15978-.053679.32822-.13281.5h1.1328c.32481 0 .62893.088408.90234.23047.057552-.23582.097656-.47718.097656-.73047 0-1.4297-.9769-2.5929-2.2539-3.3379-1.277-.7449-2.9316-1.1621-4.7461-1.1621z" fill="#fc9c9c"/><path d="m12 9c-.55401 0-1 .44599-1 1v1h2v2h1c.55401 0 1-.44599 1-1v-2c0-.55401-.44599-1-1-1zm1 4h-2v-2h-1c-.55401 0-1 .44599-1 1v2c0 .55401.44599 1 1 1h2c.55401 0 1-.44599 1-1z" fill="#84c2ff"/></svg>
diff --git a/modules/denoise/lightmap_denoiser.h b/modules/denoise/lightmap_denoiser.h
index d01bbd10a5..74a9d8af86 100644
--- a/modules/denoise/lightmap_denoiser.h
+++ b/modules/denoise/lightmap_denoiser.h
@@ -31,7 +31,7 @@
#ifndef LIGHTMAP_DENOISER_H
#define LIGHTMAP_DENOISER_H
-#include "core/object.h"
+#include "core/class_db.h"
#include "scene/3d/lightmapper.h"
struct OIDNDeviceImpl;
diff --git a/modules/gdnative/icons/GDNativeLibrary.svg b/modules/gdnative/icons/GDNativeLibrary.svg
index b494c7af6e..0ddfd4e6f2 100644
--- a/modules/gdnative/icons/GDNativeLibrary.svg
+++ b/modules/gdnative/icons/GDNativeLibrary.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625v2l2.2578 0.56445a5 5 0 0 0 0.2793 0.6875l-1.1934 1.9902 1.4141 1.4141 1.9941-1.1953a5 5 0 0 0 0.68555 0.28516l0.5625 2.2539v-5.2695a2 2 0 0 1 -1 -1.7305 2 2 0 0 1 1 -1.7285v-0.27148h1 4.5762a5 5 0 0 0 -0.11328 -0.25195l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2zm2 7v1 5 1h5c0.55228 0 1-0.4477 1-1v-5c0-0.5523-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#e0e0e0"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625v2l2.2578.56445a5 5 0 0 0 .2793.6875l-1.1934 1.9902 1.4141 1.4141 1.9941-1.1953a5 5 0 0 0 .68555.28516l.5625 2.2539v-5.2695a2 2 0 0 1 -1-1.7305 2 2 0 0 1 1-1.7285v-.27148h1 4.5762a5 5 0 0 0 -.11328-.25195l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2zm2 7v1 5 1h5c.55228 0 1-.4477 1-1v-5c0-.5523-.44772-1-1-1v4l-1-1-1 1v-4z" fill="#e0e0e0"/></svg>
diff --git a/modules/gdnative/icons/NativeScript.svg b/modules/gdnative/icons/NativeScript.svg
index fb9e135627..2224b36b29 100644
--- a/modules/gdnative/icons/NativeScript.svg
+++ b/modules/gdnative/icons/NativeScript.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625h3v1 1h2v-0.95117a2 2 0 0 1 0 -0.048828 2 2 0 0 1 2 -2 2 2 0 0 1 2 2v1h5v-2l-2.2578-0.56445a5 5 0 0 0 -0.2793 -0.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2zm-6 7v4 4h2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm6 0v2h2v-2h-2zm3 2v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2zm-7 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2zm4 0v4h2v-4h-2z" fill="#e0e0e0"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625h3v1 1h2v-.95117a2 2 0 0 1 0-.048828 2 2 0 0 1 2-2 2 2 0 0 1 2 2v1h5v-2l-2.2578-.56445a5 5 0 0 0 -.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2zm-6 7v4 4h2a3 3 0 0 0 3-3 3 3 0 0 0 -3-3v-2zm6 0v2h2v-2zm3 2v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3-3zm-7 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1zm4 0v4h2v-4z" fill="#e0e0e0"/></svg>
diff --git a/modules/gdnative/xr/config.py b/modules/gdnative/xr/config.py
deleted file mode 100644
index d22f9454ed..0000000000
--- a/modules/gdnative/xr/config.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def can_build(env, platform):
- return True
-
-
-def configure(env):
- pass
diff --git a/modules/gdnavigation/rvo_agent.h b/modules/gdnavigation/rvo_agent.h
index f5c579ba84..1ad9d3ed76 100644
--- a/modules/gdnavigation/rvo_agent.h
+++ b/modules/gdnavigation/rvo_agent.h
@@ -31,8 +31,9 @@
#ifndef RVO_AGENT_H
#define RVO_AGENT_H
-#include "core/object.h"
+#include "core/class_db.h"
#include "nav_rid.h"
+
#include <Agent.h>
/**
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index fc27892099..e170667a30 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -7,6 +7,7 @@
List of core built-in GDScript functions. Math functions and other utilities. Everything else is provided by objects. (Keywords: builtin, built in, global functions.)
</description>
<tutorials>
+ <link title="Random number generation">https://docs.godotengine.org/en/latest/tutorials/math/random_number_generation.html</link>
</tutorials>
<methods>
<method name="Color8">
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 943a49060f..5250115608 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -577,6 +577,12 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
GDScriptParser::DataType datatype = member.constant->get_datatype();
if (member.constant->initializer) {
+ if (member.constant->initializer->type == GDScriptParser::Node::ARRAY) {
+ const_fold_array(static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer));
+ } else if (member.constant->initializer->type == GDScriptParser::Node::DICTIONARY) {
+ const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(member.constant->initializer));
+ }
+
if (!member.constant->initializer->is_constant) {
push_error(R"(Initializer for a constant must be a constant expression.)", member.constant->initializer);
}
@@ -1113,6 +1119,11 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
GDScriptParser::DataType type;
reduce_expression(p_constant->initializer);
+ if (p_constant->initializer->type == GDScriptParser::Node::ARRAY) {
+ const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_constant->initializer));
+ } else if (p_constant->initializer->type == GDScriptParser::Node::DICTIONARY) {
+ const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_constant->initializer));
+ }
if (!p_constant->initializer->is_constant) {
push_error(vformat(R"(Assigned value for constant "%s" isn't a constant expression.)", p_constant->identifier->name), p_constant->initializer);
@@ -1422,22 +1433,9 @@ void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expre
}
void GDScriptAnalyzer::reduce_array(GDScriptParser::ArrayNode *p_array) {
- bool all_is_constant = true;
-
for (int i = 0; i < p_array->elements.size(); i++) {
GDScriptParser::ExpressionNode *element = p_array->elements[i];
reduce_expression(element);
- all_is_constant = all_is_constant && element->is_constant;
- }
-
- if (all_is_constant) {
- Array array;
- array.resize(p_array->elements.size());
- for (int i = 0; i < p_array->elements.size(); i++) {
- array[i] = p_array->elements[i]->reduced_value;
- }
- p_array->is_constant = true;
- p_array->reduced_value = array;
}
// It's array in any case.
@@ -1984,8 +1982,6 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
}
void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
- bool all_is_constant = true;
-
HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, VariantComparator> elements;
for (int i = 0; i < p_dictionary->elements.size(); i++) {
@@ -1994,7 +1990,6 @@ void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dicti
reduce_expression(element.key);
}
reduce_expression(element.value);
- all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
if (element.key->is_constant) {
if (elements.has(element.key->reduced_value)) {
@@ -2005,16 +2000,6 @@ void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dicti
}
}
- if (all_is_constant) {
- Dictionary dict;
- for (int i = 0; i < p_dictionary->elements.size(); i++) {
- const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
- dict[element.key->reduced_value] = element.value->reduced_value;
- }
- p_dictionary->is_constant = true;
- p_dictionary->reduced_value = dict;
- }
-
// It's dictionary in any case.
GDScriptParser::DataType dict_type;
dict_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
@@ -2737,6 +2722,46 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
p_unary_op->set_datatype(result);
}
+void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array) {
+ bool all_is_constant = true;
+
+ for (int i = 0; i < p_array->elements.size(); i++) {
+ GDScriptParser::ExpressionNode *element = p_array->elements[i];
+ all_is_constant = all_is_constant && element->is_constant;
+ if (!all_is_constant) {
+ return;
+ }
+ }
+
+ Array array;
+ array.resize(p_array->elements.size());
+ for (int i = 0; i < p_array->elements.size(); i++) {
+ array[i] = p_array->elements[i]->reduced_value;
+ }
+ p_array->is_constant = true;
+ p_array->reduced_value = array;
+}
+
+void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
+ bool all_is_constant = true;
+
+ for (int i = 0; i < p_dictionary->elements.size(); i++) {
+ const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
+ all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
+ if (!all_is_constant) {
+ return;
+ }
+ }
+
+ Dictionary dict;
+ for (int i = 0; i < p_dictionary->elements.size(); i++) {
+ const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
+ dict[element.key->reduced_value] = element.value->reduced_value;
+ }
+ p_dictionary->is_constant = true;
+ p_dictionary->reduced_value = dict;
+}
+
GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
GDScriptParser::DataType result;
result.is_constant = true;
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index c3911cce76..f3cbb320b7 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -89,6 +89,9 @@ class GDScriptAnalyzer {
void reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op);
void reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op);
+ void const_fold_array(GDScriptParser::ArrayNode *p_array);
+ void const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary);
+
// Helpers.
GDScriptParser::DataType type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source);
GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type) const;
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 8f0ce99de6..cc9e87b882 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -529,6 +529,7 @@ void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant
append(p_arguments[i]);
}
append(p_target);
+ alloc_call(p_arguments.size());
}
void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) {
@@ -579,8 +580,8 @@ void GDScriptByteCodeGenerator::write_endif() {
}
void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Address &p_list) {
- int counter_pos = increase_stack() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
- int container_pos = increase_stack() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ int counter_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+ int container_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
current_breaks_to_patch.push_back(List<int>());
@@ -628,7 +629,9 @@ void GDScriptByteCodeGenerator::write_endfor() {
}
current_breaks_to_patch.pop_back();
- current_stack_size -= 2; // Remove loop temporaries.
+ // Remove loop temporaries.
+ pop_temporary();
+ pop_temporary();
}
void GDScriptByteCodeGenerator::start_while_condition() {
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index db02079d26..fe34d6cba3 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -51,12 +51,11 @@ class GDScriptCompiler {
GDScriptCodeGenerator *generator = nullptr;
Map<StringName, GDScriptCodeGenerator::Address> parameters;
Map<StringName, GDScriptCodeGenerator::Address> locals;
- List<Set<StringName>> locals_in_scope;
+ List<Map<StringName, GDScriptCodeGenerator::Address>> locals_stack;
GDScriptCodeGenerator::Address add_local(const StringName &p_name, const GDScriptDataType &p_type) {
uint32_t addr = generator->add_local(p_name, p_type);
locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::LOCAL_VARIABLE, addr, p_type);
- locals_in_scope.back()->get().insert(p_name);
return locals[p_name];
}
@@ -102,17 +101,14 @@ class GDScriptCompiler {
}
void start_block() {
- Set<StringName> scope;
- locals_in_scope.push_back(scope);
+ Map<StringName, GDScriptCodeGenerator::Address> old_locals = locals;
+ locals_stack.push_back(old_locals);
generator->start_block();
}
void end_block() {
- Set<StringName> &scope = locals_in_scope.back()->get();
- for (Set<StringName>::Element *E = scope.front(); E; E = E->next()) {
- locals.erase(E->get());
- }
- locals_in_scope.pop_back();
+ locals = locals_stack.back()->get();
+ locals_stack.pop_back();
generator->end_block();
}
};
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 2e372575da..aec05b6771 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -792,6 +792,9 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
continue;
}
option = ScriptCodeCompletionOption(member.constant->identifier->name, ScriptCodeCompletionOption::KIND_CONSTANT);
+ if (member.constant->initializer) {
+ option.default_value = member.constant->initializer->reduced_value;
+ }
break;
case GDScriptParser::ClassNode::Member::CLASS:
if (p_only_functions) {
@@ -2404,6 +2407,11 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
Variant::get_constants_for_type(completion_context.builtin_type, &constants);
for (const List<StringName>::Element *E = constants.front(); E != nullptr; E = E->next()) {
ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ bool valid = false;
+ Variant default_value = Variant::get_constant_value(completion_context.builtin_type, E->get(), &valid);
+ if (valid) {
+ option.default_value = default_value;
+ }
options.insert(option.display, option);
}
} break;
diff --git a/modules/gdscript/icons/GDScript.svg b/modules/gdscript/icons/GDScript.svg
index 953bb9ae9e..aa59125ea9 100644
--- a/modules/gdscript/icons/GDScript.svg
+++ b/modules/gdscript/icons/GDScript.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625v2l2.2578 0.56445a5 5 0 0 0 0.2793 0.6875l-1.1934 1.9902 1.4141 1.4141 1.9941-1.1953a5 5 0 0 0 0.68555 0.28516l0.5625 2.2539h2l0.56445-2.2578a5 5 0 0 0 0.6875 -0.2793l1.9902 1.1934 1.4141-1.4141-1.1953-1.9941a5 5 0 0 0 0.28516 -0.68555l2.2539-0.5625v-2l-2.2578-0.56445a5 5 0 0 0 -0.2793 -0.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2zm1 5a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z" fill="#e0e0e0"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625v2l2.2578.56445a5 5 0 0 0 .2793.6875l-1.1934 1.9902 1.4141 1.4141 1.9941-1.1953a5 5 0 0 0 .68555.28516l.5625 2.2539h2l.56445-2.2578a5 5 0 0 0 .6875-.2793l1.9902 1.1934 1.4141-1.4141-1.1953-1.9941a5 5 0 0 0 .28516-.68555l2.2539-.5625v-2l-2.2578-.56445a5 5 0 0 0 -.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2zm1 5a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z" fill="#e0e0e0"/></svg>
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 68d9984b43..931b683a44 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -30,10 +30,13 @@
#include "test_gdscript.h"
+#include "core/io/file_access_pack.h"
#include "core/os/file_access.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
+#include "core/project_settings.h"
#include "core/string_builder.h"
+#include "scene/resources/packed_scene.h"
#include "modules/gdscript/gdscript_analyzer.h"
#include "modules/gdscript/gdscript_compiler.h"
@@ -179,6 +182,60 @@ static void test_compiler(const String &p_code, const String &p_script_path, con
}
}
+void init_autoloads() {
+ Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+
+ // First pass, add the constants so they exist before any script is loaded.
+ for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+ const ProjectSettings::AutoloadInfo &info = E->get();
+
+ if (info.is_singleton) {
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->add_global_constant(info.name, Variant());
+ }
+ }
+ }
+
+ // Second pass, load into global constants.
+ for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
+ const ProjectSettings::AutoloadInfo &info = E->get();
+
+ if (!info.is_singleton) {
+ // Skip non-singletons since we don't have a scene tree here anyway.
+ continue;
+ }
+
+ RES res = ResourceLoader::load(info.path);
+ ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
+ Node *n = nullptr;
+ if (res->is_class("PackedScene")) {
+ Ref<PackedScene> ps = res;
+ n = ps->instance();
+ } else if (res->is_class("Script")) {
+ Ref<Script> script_res = res;
+ StringName ibt = script_res->get_instance_base_type();
+ bool valid_type = ClassDB::is_parent_class(ibt, "Node");
+ ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path);
+
+ Object *obj = ClassDB::instance(ibt);
+
+ ERR_CONTINUE_MSG(obj == nullptr,
+ "Cannot instance script for autoload, expected 'Node' inheritance, got: " +
+ String(ibt));
+
+ n = Object::cast_to<Node>(obj);
+ n->set_script(script_res);
+ }
+
+ ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + info.path);
+ n->set_name(info.name);
+
+ for (int i = 0; i < ScriptServer::get_language_count(); i++) {
+ ScriptServer::get_language(i)->add_global_constant(info.name, n);
+ }
+ }
+}
+
void test(TestType p_type) {
List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
@@ -195,6 +252,21 @@ void test(TestType p_type) {
FileAccessRef fa = FileAccess::open(test, FileAccess::READ);
ERR_FAIL_COND_MSG(!fa, "Could not open file: " + test);
+ // Init PackedData since it's used by ProjectSettings.
+ PackedData *packed_data = memnew(PackedData);
+
+ // Setup project settings since it's needed by the languages to get the global scripts.
+ // This also sets up the base resource path.
+ Error err = ProjectSettings::get_singleton()->setup(fa->get_path_absolute().get_base_dir(), String(), true);
+ if (err) {
+ print_line("Could not load project settings.");
+ // Keep going since some scripts still work without this.
+ }
+
+ // Initialize the language for the test routine.
+ ScriptServer::init_languages();
+ init_autoloads();
+
Vector<uint8_t> buf;
int flen = fa->get_len();
buf.resize(fa->get_len() + 1);
@@ -226,6 +298,10 @@ void test(TestType p_type) {
case TEST_BYTECODE:
print_line("Not implemented.");
}
+
+ // Destroy stuff we set up earlier.
+ ScriptServer::finish_languages();
+ memdelete(packed_data);
}
} // namespace TestGDScript
diff --git a/modules/glslang/SCsub b/modules/glslang/SCsub
index c1d23a138b..58c033c75d 100644
--- a/modules/glslang/SCsub
+++ b/modules/glslang/SCsub
@@ -9,6 +9,7 @@ env_glslang = env_modules.Clone()
if env["builtin_glslang"]:
thirdparty_dir = "#thirdparty/glslang/"
thirdparty_sources = [
+ "glslang/CInterface/glslang_c_interface.cpp",
"glslang/MachineIndependent/RemoveTree.cpp",
"glslang/MachineIndependent/ParseHelper.cpp",
"glslang/MachineIndependent/iomapper.cpp",
@@ -30,7 +31,6 @@ if env["builtin_glslang"]:
"glslang/MachineIndependent/intermOut.cpp",
"glslang/MachineIndependent/SymbolTable.cpp",
"glslang/MachineIndependent/glslang_tab.cpp",
- "glslang/MachineIndependent/pch.cpp",
"glslang/MachineIndependent/Versions.cpp",
"glslang/MachineIndependent/ShaderLang.cpp",
"glslang/MachineIndependent/parseConst.cpp",
@@ -40,6 +40,7 @@ if env["builtin_glslang"]:
"glslang/GenericCodeGen/Link.cpp",
"glslang/GenericCodeGen/CodeGen.cpp",
"OGLCompilersDLL/InitializeDll.cpp",
+ "SPIRV/CInterface/spirv_c_interface.cpp",
"SPIRV/InReadableOrder.cpp",
"SPIRV/GlslangToSpv.cpp",
"SPIRV/SpvBuilder.cpp",
@@ -49,6 +50,7 @@ if env["builtin_glslang"]:
"SPIRV/SPVRemapper.cpp",
"SPIRV/SpvPostProcess.cpp",
"SPIRV/Logger.cpp",
+ "StandAlone/ResourceLimits.cpp",
]
if env["platform"] == "windows":
@@ -64,6 +66,8 @@ if env["builtin_glslang"]:
else:
env_glslang.Prepend(CPPPATH=[thirdparty_dir])
+ env_glslang.Append(CPPDEFINES=["ENABLE_OPT=0"])
+
env_thirdparty = env_glslang.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp
index dd28c4ad4a..3238e0108e 100644
--- a/modules/glslang/register_types.cpp
+++ b/modules/glslang/register_types.cpp
@@ -33,115 +33,10 @@
#include "servers/rendering/rendering_device.h"
#include <SPIRV/GlslangToSpv.h>
+#include <StandAlone/ResourceLimits.h>
#include <glslang/Include/Types.h>
#include <glslang/Public/ShaderLang.h>
-static const TBuiltInResource default_builtin_resource = {
- /*maxLights*/ 32,
- /*maxClipPlanes*/ 6,
- /*maxTextureUnits*/ 32,
- /*maxTextureCoords*/ 32,
- /*maxVertexAttribs*/ 64,
- /*maxVertexUniformComponents*/ 4096,
- /*maxVaryingFloats*/ 64,
- /*maxVertexTextureImageUnits*/ 32,
- /*maxCombinedTextureImageUnits*/ 80,
- /*maxTextureImageUnits*/ 32,
- /*maxFragmentUniformComponents*/ 4096,
- /*maxDrawBuffers*/ 32,
- /*maxVertexUniformVectors*/ 128,
- /*maxVaryingVectors*/ 8,
- /*maxFragmentUniformVectors*/ 16,
- /*maxVertexOutputVectors*/ 16,
- /*maxFragmentInputVectors*/ 15,
- /*minProgramTexelOffset*/ -8,
- /*maxProgramTexelOffset*/ 7,
- /*maxClipDistances*/ 8,
- /*maxComputeWorkGroupCountX*/ 65535,
- /*maxComputeWorkGroupCountY*/ 65535,
- /*maxComputeWorkGroupCountZ*/ 65535,
- /*maxComputeWorkGroupSizeX*/ 1024,
- /*maxComputeWorkGroupSizeY*/ 1024,
- /*maxComputeWorkGroupSizeZ*/ 64,
- /*maxComputeUniformComponents*/ 1024,
- /*maxComputeTextureImageUnits*/ 16,
- /*maxComputeImageUniforms*/ 8,
- /*maxComputeAtomicCounters*/ 8,
- /*maxComputeAtomicCounterBuffers*/ 1,
- /*maxVaryingComponents*/ 60,
- /*maxVertexOutputComponents*/ 64,
- /*maxGeometryInputComponents*/ 64,
- /*maxGeometryOutputComponents*/ 128,
- /*maxFragmentInputComponents*/ 128,
- /*maxImageUnits*/ 8,
- /*maxCombinedImageUnitsAndFragmentOutputs*/ 8,
- /*maxCombinedShaderOutputResources*/ 8,
- /*maxImageSamples*/ 0,
- /*maxVertexImageUniforms*/ 0,
- /*maxTessControlImageUniforms*/ 0,
- /*maxTessEvaluationImageUniforms*/ 0,
- /*maxGeometryImageUniforms*/ 0,
- /*maxFragmentImageUniforms*/ 8,
- /*maxCombinedImageUniforms*/ 8,
- /*maxGeometryTextureImageUnits*/ 16,
- /*maxGeometryOutputVertices*/ 256,
- /*maxGeometryTotalOutputComponents*/ 1024,
- /*maxGeometryUniformComponents*/ 1024,
- /*maxGeometryVaryingComponents*/ 64,
- /*maxTessControlInputComponents*/ 128,
- /*maxTessControlOutputComponents*/ 128,
- /*maxTessControlTextureImageUnits*/ 16,
- /*maxTessControlUniformComponents*/ 1024,
- /*maxTessControlTotalOutputComponents*/ 4096,
- /*maxTessEvaluationInputComponents*/ 128,
- /*maxTessEvaluationOutputComponents*/ 128,
- /*maxTessEvaluationTextureImageUnits*/ 16,
- /*maxTessEvaluationUniformComponents*/ 1024,
- /*maxTessPatchComponents*/ 120,
- /*maxPatchVertices*/ 32,
- /*maxTessGenLevel*/ 64,
- /*maxViewports*/ 16,
- /*maxVertexAtomicCounters*/ 0,
- /*maxTessControlAtomicCounters*/ 0,
- /*maxTessEvaluationAtomicCounters*/ 0,
- /*maxGeometryAtomicCounters*/ 0,
- /*maxFragmentAtomicCounters*/ 8,
- /*maxCombinedAtomicCounters*/ 8,
- /*maxAtomicCounterBindings*/ 1,
- /*maxVertexAtomicCounterBuffers*/ 0,
- /*maxTessControlAtomicCounterBuffers*/ 0,
- /*maxTessEvaluationAtomicCounterBuffers*/ 0,
- /*maxGeometryAtomicCounterBuffers*/ 0,
- /*maxFragmentAtomicCounterBuffers*/ 1,
- /*maxCombinedAtomicCounterBuffers*/ 1,
- /*maxAtomicCounterBufferSize*/ 16384,
- /*maxTransformFeedbackBuffers*/ 4,
- /*maxTransformFeedbackInterleavedComponents*/ 64,
- /*maxCullDistances*/ 8,
- /*maxCombinedClipAndCullDistances*/ 8,
- /*maxSamples*/ 4,
- /*maxMeshOutputVerticesNV*/ 0,
- /*maxMeshOutputPrimitivesNV*/ 0,
- /*maxMeshWorkGroupSizeX_NV*/ 0,
- /*maxMeshWorkGroupSizeY_NV*/ 0,
- /*maxMeshWorkGroupSizeZ_NV*/ 0,
- /*maxTaskWorkGroupSizeX_NV*/ 0,
- /*maxTaskWorkGroupSizeY_NV*/ 0,
- /*maxTaskWorkGroupSizeZ_NV*/ 0,
- /*maxMeshViewCountNV*/ 0,
- /*limits*/ {
- /*nonInductiveForLoops*/ true,
- /*whileLoops*/ true,
- /*doWhileLoops*/ true,
- /*generalUniformIndexing*/ true,
- /*generalAttributeMatrixVectorIndexing*/ true,
- /*generalVaryingIndexing*/ true,
- /*generalSamplerIndexing*/ true,
- /*generalVariableIndexing*/ true,
- /*generalConstantMatrixVectorIndexing*/ true,
- }
-};
-
static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) {
Vector<uint8_t> ret;
@@ -175,7 +70,7 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
std::string pre_processed_code;
//preprocess
- if (!shader.preprocess(&default_builtin_resource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) {
+ if (!shader.preprocess(&glslang::DefaultTBuiltInResource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) {
if (r_error) {
(*r_error) = "Failed pre-process:\n";
(*r_error) += shader.getInfoLog();
@@ -190,7 +85,7 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
shader.setStrings(&cs_strings, 1);
//parse
- if (!shader.parse(&default_builtin_resource, DefaultVersion, false, messages)) {
+ if (!shader.parse(&glslang::DefaultTBuiltInResource, DefaultVersion, false, messages)) {
if (r_error) {
(*r_error) = "Failed parse:\n";
(*r_error) += shader.getInfoLog();
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index ccf1e49693..21fa83278b 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -706,7 +706,7 @@ void GridMap::_update_visibility() {
Octant *octant = e->value();
for (int i = 0; i < octant->multimesh_instances.size(); i++) {
const Octant::MultimeshInstance &mi = octant->multimesh_instances[i];
- RS::get_singleton()->instance_set_visible(mi.instance, is_visible());
+ RS::get_singleton()->instance_set_visible(mi.instance, is_visible_in_tree());
}
}
}
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 7e136ff9bb..ee17a52d31 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -93,7 +93,7 @@ class GridMapEditor : public VBoxContainer {
List<SetItem> set_items;
- GridMap *node;
+ GridMap *node = nullptr;
MeshLibrary *last_mesh_library;
ClipMode clip_mode;
diff --git a/modules/gridmap/icons/GridMap.svg b/modules/gridmap/icons/GridMap.svg
index eafe1211f2..7a36fd888c 100644
--- a/modules/gridmap/icons/GridMap.svg
+++ b/modules/gridmap/icons/GridMap.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1-6 3v8l6 3 6-3v-2l-2-1-4 2-2-1v-4l2-1v-2l2-1zm4 2-2 1v2l2 1 2-1v-2z" fill="#fc9c9c" fill-opacity=".99608"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1-6 3v8l6 3 6-3v-2l-2-1-4 2-2-1v-4l2-1v-2l2-1zm4 2-2 1v2l2 1 2-1v-2z" fill="#fc9c9c" fill-opacity=".99608"/></svg>
diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h
index e2b7ab0975..6f3f8003e0 100644
--- a/modules/jsonrpc/jsonrpc.h
+++ b/modules/jsonrpc/jsonrpc.h
@@ -31,7 +31,7 @@
#ifndef GODOT_JSON_RPC_H
#define GODOT_JSON_RPC_H
-#include "core/object.h"
+#include "core/class_db.h"
#include "core/variant.h"
class JSONRPC : public Object {
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index e8f3174a0a..3b94949470 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -40,6 +40,11 @@ if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]:
godot_tools_build.build(env_mono, api_sln_cmd)
+ # Build Godot.NET.Sdk
+ import build_scripts.godot_net_sdk_build as godot_net_sdk_build
+
+ godot_net_sdk_build.build(env_mono)
+
# Add sources
env_mono.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/mono/build_scripts/godot_net_sdk_build.py b/modules/mono/build_scripts/godot_net_sdk_build.py
new file mode 100644
index 0000000000..3bfba0f0f6
--- /dev/null
+++ b/modules/mono/build_scripts/godot_net_sdk_build.py
@@ -0,0 +1,45 @@
+# Build Godot.NET.Sdk solution
+
+import os
+
+from SCons.Script import Dir
+
+
+def build_godot_net_sdk(source, target, env):
+ # source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
+
+ module_dir = env["module_dir"]
+
+ solution_path = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
+ build_config = "Release"
+
+ from .solution_builder import build_solution
+
+ extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]]
+
+ build_solution(env, solution_path, build_config, extra_msbuild_args)
+ # No need to copy targets. The Godot.NET.Sdk csproj takes care of copying them.
+
+
+def build(env_mono):
+ assert env_mono["tools"]
+
+ output_dir = Dir("#bin").abspath
+ editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools")
+ nupkgs_dir = os.path.join(editor_tools_dir, "nupkgs")
+
+ module_dir = os.getcwd()
+
+ package_version_file = os.path.join(
+ module_dir, "editor", "Godot.NET.Sdk", "Godot.NET.Sdk", "Godot.NET.Sdk_PackageVersion.txt"
+ )
+
+ with open(package_version_file, mode="r") as f:
+ version = f.read().strip()
+
+ target_filenames = ["Godot.NET.Sdk.%s.nupkg" % version]
+
+ targets = [os.path.join(nupkgs_dir, filename) for filename in target_filenames]
+
+ cmd = env_mono.CommandNoCache(targets, [], build_godot_net_sdk, module_dir=module_dir)
+ env_mono.AlwaysBuild(cmd)
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index a05b38b8bf..8928b6e5e3 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -940,8 +940,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Use a placeholder for now to avoid losing the state when saving a scene
- obj->set_script(scr);
-
PlaceHolderScriptInstance *placeholder = scr->placeholder_instance_create(obj);
obj->set_script_instance(placeholder);
@@ -968,14 +966,13 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
Ref<CSharpScript> script = E->get();
- if (!script->get_path().empty()) {
#ifdef TOOLS_ENABLED
- script->exports_invalidated = true;
+ script->exports_invalidated = true;
#endif
- script->signals_invalidated = true;
+ script->signals_invalidated = true;
+ if (!script->get_path().empty()) {
script->reload(p_soft_reload);
- script->update_exports();
if (!script->valid) {
script->pending_reload_instances.clear();
@@ -1950,6 +1947,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
}
void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
+ // Must make sure event signals are not left dangling
disconnect_event_signals();
#ifdef DEBUG_ENABLED
@@ -1965,6 +1963,9 @@ void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_f
CRASH_COND(gchandle.is_released());
#endif
+ // Must make sure event signals are not left dangling
+ disconnect_event_signals();
+
r_remove_script_instance = false;
if (_unreference_owner_unsafe()) {
@@ -2224,6 +2225,9 @@ CSharpInstance::~CSharpInstance() {
destructing_script_instance = true;
+ // Must make sure event signals are not left dangling
+ disconnect_event_signals();
+
if (!gchandle.is_released()) {
if (!predelete_notified && !ref_dying) {
// This destructor is not called from the owners destructor.
@@ -2955,13 +2959,24 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
CRASH_COND(p_script->native == nullptr);
+ p_script->valid = true;
+
+ update_script_class_info(p_script);
+
+#ifdef TOOLS_ENABLED
+ p_script->_update_member_info_no_exports();
+#endif
+}
+
+// Extract information about the script using the mono class.
+void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
GDMonoClass *base = p_script->script_class->get_parent_class();
+ // `base` should only be set if the script is a user defined type.
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) {
@@ -2996,17 +3011,74 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon
p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
- // Need to fetch method from base classes as well
+ p_script->rpc_functions.clear();
+ p_script->rpc_variables.clear();
+
GDMonoClass *top = p_script->script_class;
while (top && top != p_script->native) {
+ // Fetch methods from base classes as well
top->fetch_methods_with_godot_api_checks(p_script->native);
+
+ // Update RPC info
+ {
+ Vector<GDMonoMethod *> methods = top->get_all_methods();
+ for (int i = 0; i < methods.size(); i++) {
+ if (!methods[i]->is_static()) {
+ MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
+ if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
+ ScriptNetData nd;
+ nd.name = methods[i]->get_name();
+ nd.mode = mode;
+ if (-1 == p_script->rpc_functions.find(nd)) {
+ p_script->rpc_functions.push_back(nd);
+ }
+ }
+ }
+ }
+ }
+
+ {
+ Vector<GDMonoField *> fields = top->get_all_fields();
+ for (int i = 0; i < fields.size(); i++) {
+ if (!fields[i]->is_static()) {
+ MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(fields[i]);
+ if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
+ ScriptNetData nd;
+ nd.name = fields[i]->get_name();
+ nd.mode = mode;
+ if (-1 == p_script->rpc_variables.find(nd)) {
+ p_script->rpc_variables.push_back(nd);
+ }
+ }
+ }
+ }
+ }
+
+ {
+ Vector<GDMonoProperty *> properties = top->get_all_properties();
+ for (int i = 0; i < properties.size(); i++) {
+ if (!properties[i]->is_static()) {
+ MultiplayerAPI::RPCMode mode = p_script->_member_get_rpc_mode(properties[i]);
+ if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
+ ScriptNetData nd;
+ nd.name = properties[i]->get_name();
+ nd.mode = mode;
+ if (-1 == p_script->rpc_variables.find(nd)) {
+ p_script->rpc_variables.push_back(nd);
+ }
+ }
+ }
+ }
+ }
+
top = top->get_parent_class();
}
+ // Sort so we are 100% that they are always the same.
+ p_script->rpc_functions.sort_custom<SortNetData>();
+ p_script->rpc_variables.sort_custom<SortNetData>();
+
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 {
@@ -3305,124 +3377,15 @@ Error CSharpScript::reload(bool p_keep_state) {
print_verbose("Found class " + script_class->get_full_name() + " for script " + get_path());
#endif
- tool = script_class->has_attribute(CACHED_CLASS(ToolAttribute));
-
- if (!tool) {
- GDMonoClass *nesting_class = script_class->get_nesting_class();
- tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
- }
-
-#if TOOLS_ENABLED
- if (!tool) {
- tool = script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
- }
-#endif
-
native = GDMonoUtils::get_class_native_base(script_class);
CRASH_COND(native == nullptr);
- GDMonoClass *base_class = script_class->get_parent_class();
-
- if (base_class != native) {
- base = base_class;
- }
-
-#ifdef DEBUG_ENABLED
- // For debug builds, we must fetch from all native base methods as well.
- // Native base methods must be fetched before the current class.
- // Not needed if the script class itself is a native class.
-
- if (script_class != native) {
- GDMonoClass *native_top = native;
- while (native_top) {
- native_top->fetch_methods_with_godot_api_checks(native);
-
- if (native_top == CACHED_CLASS(GodotObject)) {
- break;
- }
-
- native_top = native_top->get_parent_class();
- }
- }
-#endif
-
- script_class->fetch_methods_with_godot_api_checks(native);
+ update_script_class_info(this);
- // Need to fetch method from base classes as well
- GDMonoClass *top = script_class;
- while (top && top != native) {
- top->fetch_methods_with_godot_api_checks(native);
- top = top->get_parent_class();
- }
-
- load_script_signals(script_class, native);
_update_exports();
}
- rpc_functions.clear();
- rpc_variables.clear();
-
- GDMonoClass *top = script_class;
- while (top && top != native) {
- {
- Vector<GDMonoMethod *> methods = top->get_all_methods();
- for (int i = 0; i < methods.size(); i++) {
- if (!methods[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(methods[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = methods[i]->get_name();
- nd.mode = mode;
- if (-1 == rpc_functions.find(nd)) {
- rpc_functions.push_back(nd);
- }
- }
- }
- }
- }
-
- {
- Vector<GDMonoField *> fields = top->get_all_fields();
- for (int i = 0; i < fields.size(); i++) {
- if (!fields[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(fields[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = fields[i]->get_name();
- nd.mode = mode;
- if (-1 == rpc_variables.find(nd)) {
- rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
- {
- Vector<GDMonoProperty *> properties = top->get_all_properties();
- for (int i = 0; i < properties.size(); i++) {
- if (!properties[i]->is_static()) {
- MultiplayerAPI::RPCMode mode = _member_get_rpc_mode(properties[i]);
- if (MultiplayerAPI::RPC_MODE_DISABLED != mode) {
- ScriptNetData nd;
- nd.name = properties[i]->get_name();
- nd.mode = mode;
- if (-1 == rpc_variables.find(nd)) {
- rpc_variables.push_back(nd);
- }
- }
- }
- }
- }
-
- top = top->get_parent_class();
- }
-
- // Sort so we are 100% that they are always the same.
- rpc_functions.sort_custom<SortNetData>();
- rpc_variables.sort_custom<SortNetData>();
-
return OK;
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index f0b43a40f9..316fd78f2a 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -164,6 +164,7 @@ private:
// 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 update_script_class_info(Ref<CSharpScript> p_script);
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
@@ -287,7 +288,7 @@ public:
void mono_object_disposed(MonoObject *p_obj);
/*
- * If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, ifevent_signal
+ * If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, if
* 'r_remove_script_instance' is set to true, the caller must destroy the script instance by removing it from its owner.
*/
void mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
index 86a0a4393e..8304d9e321 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.Build.NoTargets/2.0.1">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
+ <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Description>MSBuild .NET Sdk for Godot projects.</Description>
<Authors>Godot Engine contributors</Authors>
<PackageId>Godot.NET.Sdk</PackageId>
<Version>4.0.0</Version>
- <PackageVersion>4.0.0-dev2</PackageVersion>
<PackageProjectUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</PackageProjectUrl>
<PackageType>MSBuildSdk</PackageType>
<PackageTags>MSBuildSdk</PackageTags>
@@ -19,7 +19,13 @@
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);SetNuSpecProperties</GenerateNuspecDependsOn>
</PropertyGroup>
- <Target Name="SetNuSpecProperties" Condition=" Exists('$(NuspecFile)') ">
+ <Target Name="ReadGodotNETSdkVersion" BeforeTargets="BeforeBuild;BeforeRebuild;CoreCompile">
+ <PropertyGroup>
+ <PackageVersion>$([System.IO.File]::ReadAllText('$(ProjectDir)Godot.NET.Sdk_PackageVersion.txt').Trim())</PackageVersion>
+ </PropertyGroup>
+ </Target>
+
+ <Target Name="SetNuSpecProperties" Condition=" Exists('$(NuspecFile)') " DependsOnTargets="ReadGodotNETSdkVersion">
<PropertyGroup>
<NuspecProperties>
id=$(PackageId);
@@ -32,4 +38,13 @@
</NuspecProperties>
</PropertyGroup>
</Target>
+
+ <Target Name="CopyNupkgToSConsOutputDir" AfterTargets="Pack">
+ <PropertyGroup>
+ <GodotSourceRootPath>$(SolutionDir)\..\..\..\..\</GodotSourceRootPath>
+ <GodotOutputDataDir>$(GodotSourceRootPath)\bin\GodotSharp\</GodotOutputDataDir>
+ </PropertyGroup>
+ <Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg"
+ DestinationFolder="$(GodotOutputDataDir)Tools\nupkgs\" />
+ </Target>
</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
index 5b5cefe80e..ba68a4da43 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.nuspec
@@ -17,6 +17,6 @@
<repository url="$projecturl$" />
</metadata>
<files>
- <file src="Sdk\**" target="Sdk" />\
+ <file src="Sdk\**" target="Sdk" />
</files>
</package>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
new file mode 100644
index 0000000000..34749489b9
--- /dev/null
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk_PackageVersion.txt
@@ -0,0 +1 @@
+4.0.0-dev3
diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
index 5edf72d63e..9b7b422276 100644
--- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs
@@ -15,14 +15,14 @@ namespace GodotTools.BuildLogger
public void Initialize(IEventSource eventSource)
{
if (null == Parameters)
- throw new LoggerException("Log directory was not set.");
+ throw new LoggerException("Log directory parameter not specified.");
var parameters = Parameters.Split(new[] { ';' });
string logDir = parameters[0];
if (string.IsNullOrEmpty(logDir))
- throw new LoggerException("Log directory was not set.");
+ throw new LoggerException("Log directory parameter is empty.");
if (parameters.Length > 1)
throw new LoggerException("Too many parameters passed.");
@@ -51,22 +51,31 @@ namespace GodotTools.BuildLogger
{
throw new LoggerException("Failed to create log file: " + ex.Message);
}
- else
- {
- // Unexpected failure
- throw;
- }
+
+ // Unexpected failure
+ throw;
}
eventSource.ProjectStarted += eventSource_ProjectStarted;
- eventSource.TaskStarted += eventSource_TaskStarted;
+ eventSource.ProjectFinished += eventSource_ProjectFinished;
eventSource.MessageRaised += eventSource_MessageRaised;
eventSource.WarningRaised += eventSource_WarningRaised;
eventSource.ErrorRaised += eventSource_ErrorRaised;
- eventSource.ProjectFinished += eventSource_ProjectFinished;
}
- void eventSource_ErrorRaised(object sender, BuildErrorEventArgs e)
+ private void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
+ {
+ WriteLine(e.Message);
+ indent++;
+ }
+
+ private void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
+ {
+ indent--;
+ WriteLine(e.Message);
+ }
+
+ private void eventSource_ErrorRaised(object sender, BuildErrorEventArgs e)
{
string line = $"{e.File}({e.LineNumber},{e.ColumnNumber}): error {e.Code}: {e.Message}";
@@ -81,7 +90,7 @@ namespace GodotTools.BuildLogger
issuesStreamWriter.WriteLine(errorLine);
}
- void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
+ private void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
{
string line = $"{e.File}({e.LineNumber},{e.ColumnNumber}): warning {e.Code}: {e.Message}";
@@ -108,40 +117,6 @@ namespace GodotTools.BuildLogger
}
}
- private void eventSource_TaskStarted(object sender, TaskStartedEventArgs e)
- {
- // TaskStartedEventArgs adds ProjectFile, TaskFile, TaskName
- // To keep this log clean, this logger will ignore these events.
- }
-
- private void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
- {
- WriteLine(e.Message);
- indent++;
- }
-
- private void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
- {
- indent--;
- WriteLine(e.Message);
- }
-
- /// <summary>
- /// Write a line to the log, adding the SenderName
- /// </summary>
- private void WriteLineWithSender(string line, BuildEventArgs e)
- {
- if (0 == string.Compare(e.SenderName, "MSBuild", StringComparison.OrdinalIgnoreCase))
- {
- // Well, if the sender name is MSBuild, let's leave it out for prettiness
- WriteLine(line);
- }
- else
- {
- WriteLine(e.SenderName + ": " + line);
- }
- }
-
/// <summary>
/// Write a line to the log, adding the SenderName and Message
/// (these parameters are on all MSBuild event argument objects)
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
index e4d6b2e010..37123ba2b2 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
@@ -10,6 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
+ <ProjectReference Include="..\GodotTools.Shared\GodotTools.Shared.csproj" />
</ItemGroup>
<!--
The Microsoft.Build.Runtime package is too problematic so we create a MSBuild.exe stub. The workaround described
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
index 01d7c99662..7d49d251dd 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs
@@ -3,14 +3,13 @@ using System.IO;
using System.Text;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
+using GodotTools.Shared;
namespace GodotTools.ProjectEditor
{
public static class ProjectGenerator
{
- public const string GodotSdkVersionToUse = "4.0.0-dev2";
-
- public static string GodotSdkAttrValue => $"Godot.NET.Sdk/{GodotSdkVersionToUse}";
+ public static string GodotSdkAttrValue => $"Godot.NET.Sdk/{GeneratedGodotNupkgsVersions.GodotNETSdk}";
public static ProjectRootElement GenGameProject(string name)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
new file mode 100644
index 0000000000..1d382dcb43
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets
@@ -0,0 +1,36 @@
+<Project>
+ <!-- Generate C# file with the version of all the nupkgs bundled with Godot -->
+
+ <Target Name="SetPropertiesForGenerateGodotNupkgsVersions">
+ <PropertyGroup>
+ <GodotNETSdkPackageVersionFile>$(SolutionDir)..\Godot.NET.Sdk\Godot.NET.Sdk\Godot.NET.Sdk_PackageVersion.txt</GodotNETSdkPackageVersionFile>
+ <GeneratedGodotNupkgsVersionsFile>$(IntermediateOutputPath)GodotNupkgsVersions.g.cs</GeneratedGodotNupkgsVersionsFile>
+ </PropertyGroup>
+ </Target>
+
+ <Target Name="GenerateGodotNupkgsVersionsFile"
+ DependsOnTargets="PrepareForBuild;_GenerateGodotNupkgsVersionsFile"
+ BeforeTargets="BeforeCompile;CoreCompile">
+ <ItemGroup>
+ <Compile Include="$(GeneratedGodotNupkgsVersionsFile)" />
+ <FileWrites Include="$(GeneratedGodotNupkgsVersionsFile)" />
+ </ItemGroup>
+ </Target>
+ <Target Name="_GenerateGodotNupkgsVersionsFile"
+ DependsOnTargets="SetPropertiesForGenerateGodotNupkgsVersions"
+ Inputs="$(MSBuildProjectFile);@(GodotNETSdkPackageVersionFile)"
+ Outputs="$(GeneratedGodotNupkgsVersionsFile)">
+ <PropertyGroup>
+ <GenerateGodotNupkgsVersionsCode><![CDATA[
+namespace $(RootNamespace) {
+ public class GeneratedGodotNupkgsVersions {
+ public const string GodotNETSdk = "$([System.IO.File]::ReadAllText('$(GodotNETSdkPackageVersionFile)').Trim())"%3b
+ }
+}
+]]></GenerateGodotNupkgsVersionsCode>
+ </PropertyGroup>
+ <WriteLinesToFile Lines="$(GenerateGodotNupkgsVersionsCode)"
+ File="$(GeneratedGodotNupkgsVersionsFile)"
+ Overwrite="True" WriteOnlyWhenDifferent="True" />
+ </Target>
+</Project>
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
new file mode 100644
index 0000000000..3bc1698c15
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
@@ -0,0 +1,6 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ </PropertyGroup>
+ <Import Project="GenerateGodotNupkgsVersions.targets" />
+</Project>
diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln
index ba5379e562..d3107a69db 100644
--- a/modules/mono/editor/GodotTools/GodotTools.sln
+++ b/modules/mono/editor/GodotTools/GodotTools.sln
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.IdeMessaging", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.OpenVisualStudio", "GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj", "{EAFFF236-FA96-4A4D-BD23-0E51EF988277}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.Shared", "GodotTools.Shared\GodotTools.Shared.csproj", "{2758FFAF-8237-4CF2-B569-66BF8B3587BB}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -43,5 +45,9 @@ Global
{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2758FFAF-8237-4CF2-B569-66BF8B3587BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2758FFAF-8237-4CF2-B569-66BF8B3587BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2758FFAF-8237-4CF2-B569-66BF8B3587BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2758FFAF-8237-4CF2-B569-66BF8B3587BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs
deleted file mode 100644
index 3ab669a9f3..0000000000
--- a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs
+++ /dev/null
@@ -1,339 +0,0 @@
-using Godot;
-using System;
-using System.IO;
-using Godot.Collections;
-using GodotTools.Internals;
-using static GodotTools.Internals.Globals;
-using File = GodotTools.Utils.File;
-using Path = System.IO.Path;
-
-namespace GodotTools
-{
- public class BottomPanel : VBoxContainer
- {
- private EditorInterface editorInterface;
-
- private TabContainer panelTabs;
-
- private VBoxContainer panelBuildsTab;
-
- private ItemList buildTabsList;
- private TabContainer buildTabs;
-
- private Button warningsBtn;
- private Button errorsBtn;
- private Button viewLogBtn;
-
- private void _UpdateBuildTab(int index, int? currentTab)
- {
- var tab = (BuildTab)buildTabs.GetChild(index);
-
- string itemName = Path.GetFileNameWithoutExtension(tab.BuildInfo.Solution);
- itemName += " [" + tab.BuildInfo.Configuration + "]";
-
- buildTabsList.AddItem(itemName, tab.IconTexture);
-
- string itemTooltip = "Solution: " + tab.BuildInfo.Solution;
- itemTooltip += "\nConfiguration: " + tab.BuildInfo.Configuration;
- itemTooltip += "\nStatus: ";
-
- if (tab.BuildExited)
- itemTooltip += tab.BuildResult == BuildTab.BuildResults.Success ? "Succeeded" : "Errored";
- else
- itemTooltip += "Running";
-
- if (!tab.BuildExited || tab.BuildResult == BuildTab.BuildResults.Error)
- itemTooltip += $"\nErrors: {tab.ErrorCount}";
-
- itemTooltip += $"\nWarnings: {tab.WarningCount}";
-
- buildTabsList.SetItemTooltip(index, itemTooltip);
-
- // If this tab was already selected before the changes or if no tab was selected
- if (currentTab == null || currentTab == index)
- {
- buildTabsList.Select(index);
- _BuildTabsItemSelected(index);
- }
- }
-
- private void _UpdateBuildTabsList()
- {
- buildTabsList.Clear();
-
- int? currentTab = buildTabs.CurrentTab;
-
- if (currentTab < 0 || currentTab >= buildTabs.GetTabCount())
- currentTab = null;
-
- for (int i = 0; i < buildTabs.GetChildCount(); i++)
- _UpdateBuildTab(i, currentTab);
- }
-
- public BuildTab GetBuildTabFor(BuildInfo buildInfo)
- {
- foreach (var buildTab in new Array<BuildTab>(buildTabs.GetChildren()))
- {
- if (buildTab.BuildInfo.Equals(buildInfo))
- return buildTab;
- }
-
- var newBuildTab = new BuildTab(buildInfo);
- AddBuildTab(newBuildTab);
-
- return newBuildTab;
- }
-
- private void _BuildTabsItemSelected(int idx)
- {
- if (idx < 0 || idx >= buildTabs.GetTabCount())
- throw new IndexOutOfRangeException();
-
- buildTabs.CurrentTab = idx;
- if (!buildTabs.Visible)
- buildTabs.Visible = true;
-
- warningsBtn.Visible = true;
- errorsBtn.Visible = true;
- viewLogBtn.Visible = true;
- }
-
- private void _BuildTabsNothingSelected()
- {
- if (buildTabs.GetTabCount() != 0)
- {
- // just in case
- buildTabs.Visible = false;
-
- // This callback is called when clicking on the empty space of the list.
- // ItemList won't deselect the items automatically, so we must do it ourselves.
- buildTabsList.UnselectAll();
- }
-
- warningsBtn.Visible = false;
- errorsBtn.Visible = false;
- viewLogBtn.Visible = false;
- }
-
- private void _WarningsToggled(bool pressed)
- {
- int currentTab = buildTabs.CurrentTab;
-
- if (currentTab < 0 || currentTab >= buildTabs.GetTabCount())
- throw new InvalidOperationException("No tab selected");
-
- var buildTab = (BuildTab)buildTabs.GetChild(currentTab);
- buildTab.WarningsVisible = pressed;
- buildTab.UpdateIssuesList();
- }
-
- private void _ErrorsToggled(bool pressed)
- {
- int currentTab = buildTabs.CurrentTab;
-
- if (currentTab < 0 || currentTab >= buildTabs.GetTabCount())
- throw new InvalidOperationException("No tab selected");
-
- var buildTab = (BuildTab)buildTabs.GetChild(currentTab);
- buildTab.ErrorsVisible = pressed;
- buildTab.UpdateIssuesList();
- }
-
- public void BuildProjectPressed()
- {
- if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
- return; // No solution to build
-
- string editorScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor");
- string playerScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor_player");
-
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, editorScriptsMetadataPath);
-
- if (File.Exists(editorScriptsMetadataPath))
- {
- try
- {
- File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath);
- }
- catch (IOException e)
- {
- GD.PushError($"Failed to copy scripts metadata file. Exception message: {e.Message}");
- return;
- }
- }
-
- bool buildSuccess = BuildManager.BuildProjectBlocking("Debug");
-
- if (!buildSuccess)
- return;
-
- // Notify running game for hot-reload
- Internal.EditorDebuggerNodeReloadScripts();
-
- // Hot-reload in the editor
- GodotSharpEditor.Instance.GetNode<HotReloadAssemblyWatcher>("HotReloadAssemblyWatcher").RestartTimer();
-
- if (Internal.IsAssembliesReloadingNeeded())
- Internal.ReloadAssemblies(softReload: false);
- }
-
- private void _ViewLogPressed()
- {
- if (!buildTabsList.IsAnythingSelected())
- return;
-
- var selectedItems = buildTabsList.GetSelectedItems();
-
- if (selectedItems.Length != 1)
- throw new InvalidOperationException($"Expected 1 selected item, got {selectedItems.Length}");
-
- int selectedItem = selectedItems[0];
-
- var buildTab = (BuildTab)buildTabs.GetTabControl(selectedItem);
-
- OS.ShellOpen(Path.Combine(buildTab.BuildInfo.LogsDirPath, BuildManager.MsBuildLogFileName));
- }
-
- public override void _Notification(int what)
- {
- base._Notification(what);
-
- if (what == EditorSettings.NotificationEditorSettingsChanged)
- {
- var editorBaseControl = editorInterface.GetBaseControl();
- panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles"));
- panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles"));
- panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles"));
- }
- }
-
- public void AddBuildTab(BuildTab buildTab)
- {
- buildTabs.AddChild(buildTab);
- RaiseBuildTab(buildTab);
- }
-
- public void RaiseBuildTab(BuildTab buildTab)
- {
- if (buildTab.GetParent() != buildTabs)
- throw new InvalidOperationException("Build tab is not in the tabs list");
-
- buildTabs.MoveChild(buildTab, 0);
- _UpdateBuildTabsList();
- }
-
- public void ShowBuildTab()
- {
- for (int i = 0; i < panelTabs.GetTabCount(); i++)
- {
- if (panelTabs.GetTabControl(i) == panelBuildsTab)
- {
- panelTabs.CurrentTab = i;
- GodotSharpEditor.Instance.MakeBottomPanelItemVisible(this);
- return;
- }
- }
-
- GD.PushError("Builds tab not found");
- }
-
- public override void _Ready()
- {
- base._Ready();
-
- editorInterface = GodotSharpEditor.Instance.GetEditorInterface();
-
- var editorBaseControl = editorInterface.GetBaseControl();
-
- SizeFlagsVertical = (int)SizeFlags.ExpandFill;
- SetAnchorsAndMarginsPreset(LayoutPreset.Wide);
-
- panelTabs = new TabContainer
- {
- TabAlign = TabContainer.TabAlignEnum.Left,
- RectMinSize = new Vector2(0, 228) * EditorScale,
- SizeFlagsVertical = (int)SizeFlags.ExpandFill
- };
- panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles"));
- panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles"));
- panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles"));
- AddChild(panelTabs);
-
- {
- // Builds tab
- panelBuildsTab = new VBoxContainer
- {
- Name = "Builds".TTR(),
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill
- };
- panelTabs.AddChild(panelBuildsTab);
-
- var toolBarHBox = new HBoxContainer {SizeFlagsHorizontal = (int)SizeFlags.ExpandFill};
- panelBuildsTab.AddChild(toolBarHBox);
-
- var buildProjectBtn = new Button
- {
- Text = "Build Project".TTR(),
- FocusMode = FocusModeEnum.None
- };
- buildProjectBtn.PressedSignal += BuildProjectPressed;
- toolBarHBox.AddChild(buildProjectBtn);
-
- toolBarHBox.AddSpacer(begin: false);
-
- warningsBtn = new Button
- {
- Text = "Warnings".TTR(),
- ToggleMode = true,
- Pressed = true,
- Visible = false,
- FocusMode = FocusModeEnum.None
- };
- warningsBtn.Toggled += _WarningsToggled;
- toolBarHBox.AddChild(warningsBtn);
-
- errorsBtn = new Button
- {
- Text = "Errors".TTR(),
- ToggleMode = true,
- Pressed = true,
- Visible = false,
- FocusMode = FocusModeEnum.None
- };
- errorsBtn.Toggled += _ErrorsToggled;
- toolBarHBox.AddChild(errorsBtn);
-
- toolBarHBox.AddSpacer(begin: false);
-
- viewLogBtn = new Button
- {
- Text = "View log".TTR(),
- FocusMode = FocusModeEnum.None,
- Visible = false
- };
- viewLogBtn.PressedSignal += _ViewLogPressed;
- toolBarHBox.AddChild(viewLogBtn);
-
- var hsc = new HSplitContainer
- {
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill,
- SizeFlagsVertical = (int)SizeFlags.ExpandFill
- };
- panelBuildsTab.AddChild(hsc);
-
- buildTabsList = new ItemList {SizeFlagsHorizontal = (int)SizeFlags.ExpandFill};
- buildTabsList.ItemSelected += _BuildTabsItemSelected;
- buildTabsList.NothingSelected += _BuildTabsNothingSelected;
- hsc.AddChild(buildTabsList);
-
- buildTabs = new TabContainer
- {
- TabAlign = TabContainer.TabAlignEnum.Left,
- SizeFlagsHorizontal = (int)SizeFlags.ExpandFill,
- TabsVisible = false
- };
- hsc.AddChild(buildTabs);
- }
- }
- }
-}
diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
index ab090c46e7..51055dc9b9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
@@ -4,7 +4,7 @@ using Godot.Collections;
using GodotTools.Internals;
using Path = System.IO.Path;
-namespace GodotTools
+namespace GodotTools.Build
{
[Serializable]
public sealed class BuildInfo : Reference // TODO Remove Reference once we have proper serialization
@@ -20,7 +20,9 @@ namespace GodotTools
public override bool Equals(object obj)
{
if (obj is BuildInfo other)
- return other.Solution == Solution && other.Configuration == Configuration;
+ return other.Solution == Solution && other.Targets == Targets &&
+ other.Configuration == Configuration && other.Restore == Restore &&
+ other.CustomProperties == CustomProperties && other.LogsDirPath == LogsDirPath;
return false;
}
@@ -31,7 +33,11 @@ namespace GodotTools
{
int hash = 17;
hash = hash * 29 + Solution.GetHashCode();
+ hash = hash * 29 + Targets.GetHashCode();
hash = hash * 29 + Configuration.GetHashCode();
+ hash = hash * 29 + Restore.GetHashCode();
+ hash = hash * 29 + CustomProperties.GetHashCode();
+ hash = hash * 29 + LogsDirPath.GetHashCode();
return hash;
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
index ff7ce97c47..b96b0c8175 100644
--- a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
@@ -1,20 +1,18 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
-using GodotTools.Build;
using GodotTools.Ides.Rider;
using GodotTools.Internals;
-using GodotTools.Utils;
using JetBrains.Annotations;
using static GodotTools.Internals.Globals;
using File = GodotTools.Utils.File;
+using OS = GodotTools.Utils.OS;
-namespace GodotTools
+namespace GodotTools.Build
{
public static class BuildManager
{
- private static readonly List<BuildInfo> BuildsInProgress = new List<BuildInfo>();
+ private static BuildInfo _buildInProgress;
public const string PropNameMSBuildMono = "MSBuild (Mono)";
public const string PropNameMSBuildVs = "MSBuild (VS Build Tools)";
@@ -24,6 +22,14 @@ namespace GodotTools
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
public const string MsBuildLogFileName = "msbuild_log.txt";
+ public delegate void BuildLaunchFailedEventHandler(BuildInfo buildInfo, string reason);
+
+ public static event BuildLaunchFailedEventHandler BuildLaunchFailed;
+ public static event Action<BuildInfo> BuildStarted;
+ public static event Action<BuildResult> BuildFinished;
+ public static event Action<string> StdOutputReceived;
+ public static event Action<string> StdErrorReceived;
+
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
{
var issuesFile = GetIssuesFilePath(buildInfo);
@@ -36,12 +42,13 @@ namespace GodotTools
private static void ShowBuildErrorDialog(string message)
{
- GodotSharpEditor.Instance.ShowErrorDialog(message, "Build error");
- GodotSharpEditor.Instance.BottomPanel.ShowBuildTab();
+ var plugin = GodotSharpEditor.Instance;
+ plugin.ShowErrorDialog(message, "Build error");
+ plugin.MakeBottomPanelItemVisible(plugin.MSBuildPanel);
}
- public static void RestartBuild(BuildTab buildTab) => throw new NotImplementedException();
- public static void StopBuild(BuildTab buildTab) => throw new NotImplementedException();
+ public static void RestartBuild(BuildOutputView buildOutputView) => throw new NotImplementedException();
+ public static void StopBuild(BuildOutputView buildOutputView) => throw new NotImplementedException();
private static string GetLogFilePath(BuildInfo buildInfo)
{
@@ -61,15 +68,14 @@ namespace GodotTools
public static bool Build(BuildInfo buildInfo)
{
- if (BuildsInProgress.Contains(buildInfo))
+ if (_buildInProgress != null)
throw new InvalidOperationException("A build is already in progress");
- BuildsInProgress.Add(buildInfo);
+ _buildInProgress = buildInfo;
try
{
- BuildTab buildTab = GodotSharpEditor.Instance.BottomPanel.GetBuildTabFor(buildInfo);
- buildTab.OnBuildStart();
+ BuildStarted?.Invoke(buildInfo);
// Required in order to update the build tasks list
Internal.GodotMainIteration();
@@ -80,44 +86,44 @@ namespace GodotTools
}
catch (IOException e)
{
- buildTab.OnBuildExecFailed($"Cannot remove issues file: {GetIssuesFilePath(buildInfo)}");
+ BuildLaunchFailed?.Invoke(buildInfo, $"Cannot remove issues file: {GetIssuesFilePath(buildInfo)}");
Console.Error.WriteLine(e);
}
try
{
- int exitCode = BuildSystem.Build(buildInfo);
+ int exitCode = BuildSystem.Build(buildInfo, StdOutputReceived, StdErrorReceived);
if (exitCode != 0)
PrintVerbose($"MSBuild exited with code: {exitCode}. Log file: {GetLogFilePath(buildInfo)}");
- buildTab.OnBuildExit(exitCode == 0 ? BuildTab.BuildResults.Success : BuildTab.BuildResults.Error);
+ BuildFinished?.Invoke(exitCode == 0 ? BuildResult.Success : BuildResult.Error);
return exitCode == 0;
}
catch (Exception e)
{
- buildTab.OnBuildExecFailed($"The build method threw an exception.\n{e.GetType().FullName}: {e.Message}");
+ BuildLaunchFailed?.Invoke(buildInfo, $"The build method threw an exception.\n{e.GetType().FullName}: {e.Message}");
Console.Error.WriteLine(e);
return false;
}
}
finally
{
- BuildsInProgress.Remove(buildInfo);
+ _buildInProgress = null;
}
}
public static async Task<bool> BuildAsync(BuildInfo buildInfo)
{
- if (BuildsInProgress.Contains(buildInfo))
+ if (_buildInProgress != null)
throw new InvalidOperationException("A build is already in progress");
- BuildsInProgress.Add(buildInfo);
+ _buildInProgress = buildInfo;
try
{
- BuildTab buildTab = GodotSharpEditor.Instance.BottomPanel.GetBuildTabFor(buildInfo);
+ BuildStarted?.Invoke(buildInfo);
try
{
@@ -125,43 +131,57 @@ namespace GodotTools
}
catch (IOException e)
{
- buildTab.OnBuildExecFailed($"Cannot remove issues file: {GetIssuesFilePath(buildInfo)}");
+ BuildLaunchFailed?.Invoke(buildInfo, $"Cannot remove issues file: {GetIssuesFilePath(buildInfo)}");
Console.Error.WriteLine(e);
}
try
{
- int exitCode = await BuildSystem.BuildAsync(buildInfo);
+ int exitCode = await BuildSystem.BuildAsync(buildInfo, StdOutputReceived, StdErrorReceived);
if (exitCode != 0)
PrintVerbose($"MSBuild exited with code: {exitCode}. Log file: {GetLogFilePath(buildInfo)}");
- buildTab.OnBuildExit(exitCode == 0 ? BuildTab.BuildResults.Success : BuildTab.BuildResults.Error);
+ BuildFinished?.Invoke(exitCode == 0 ? BuildResult.Success : BuildResult.Error);
return exitCode == 0;
}
catch (Exception e)
{
- buildTab.OnBuildExecFailed($"The build method threw an exception.\n{e.GetType().FullName}: {e.Message}");
+ BuildLaunchFailed?.Invoke(buildInfo, $"The build method threw an exception.\n{e.GetType().FullName}: {e.Message}");
Console.Error.WriteLine(e);
return false;
}
}
finally
{
- BuildsInProgress.Remove(buildInfo);
+ _buildInProgress = null;
}
}
- public static bool BuildProjectBlocking(string config, [CanBeNull] string platform = null)
+ public static bool BuildProjectBlocking(string config, [CanBeNull] string[] targets = null, [CanBeNull] string platform = null)
{
- if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
+ var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets ?? new[] {"Build"}, config, restore: true);
+
+ // If a platform was not specified, try determining the current one. If that fails, let MSBuild auto-detect it.
+ if (platform != null || OS.PlatformNameMap.TryGetValue(Godot.OS.GetName(), out platform))
+ buildInfo.CustomProperties.Add($"GodotTargetPlatform={platform}");
+
+ if (Internal.GodotIsRealTDouble())
+ buildInfo.CustomProperties.Add("GodotRealTIsDouble=true");
+
+ return BuildProjectBlocking(buildInfo);
+ }
+
+ private static bool BuildProjectBlocking(BuildInfo buildInfo)
+ {
+ if (!File.Exists(buildInfo.Solution))
return true; // No solution to build
// Make sure the API assemblies are up to date before building the project.
// We may not have had the chance to update the release API assemblies, and the debug ones
// may have been deleted by the user at some point after they were loaded by the Godot editor.
- string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(config == "ExportRelease" ? "Release" : "Debug");
+ string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(buildInfo.Configuration == "ExportRelease" ? "Release" : "Debug");
if (!string.IsNullOrEmpty(apiAssembliesUpdateError))
{
@@ -173,15 +193,6 @@ namespace GodotTools
{
pr.Step("Building project solution", 0);
- var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets: new[] {"Build"}, config, restore: true);
-
- // If a platform was not specified, try determining the current one. If that fails, let MSBuild auto-detect it.
- if (platform != null || OS.PlatformNameMap.TryGetValue(Godot.OS.GetName(), out platform))
- buildInfo.CustomProperties.Add($"GodotTargetPlatform={platform}");
-
- if (Internal.GodotIsRealTDouble())
- buildInfo.CustomProperties.Add("GodotRealTIsDouble=true");
-
if (!Build(buildInfo))
{
ShowBuildErrorDialog("Failed to build project solution");
@@ -197,18 +208,51 @@ namespace GodotTools
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
return true; // No solution to build
+ try
+ {
+ // Make sure our packages are added to the fallback folder
+ NuGetUtils.AddBundledPackagesToFallbackFolder(NuGetUtils.GodotFallbackFolderPath);
+ }
+ catch (Exception e)
+ {
+ Godot.GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
+ }
+
+ GenerateEditorScriptMetadata();
+
+ if (GodotSharpEditor.Instance.SkipBuildBeforePlaying)
+ return true; // Requested play from an external editor/IDE which already built the project
+
+ return BuildProjectBlocking("Debug");
+ }
+
+ // NOTE: This will be replaced with C# source generators in 4.0
+ public static void GenerateEditorScriptMetadata()
+ {
string editorScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor");
string playerScriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, "scripts_metadata.editor_player");
CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, editorScriptsMetadataPath);
- if (File.Exists(editorScriptsMetadataPath))
- File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath);
+ if (!File.Exists(editorScriptsMetadataPath))
+ return;
- if (GodotSharpEditor.Instance.SkipBuildBeforePlaying)
- return true; // Requested play from an external editor/IDE which already built the project
+ try
+ {
+ File.Copy(editorScriptsMetadataPath, playerScriptsMetadataPath);
+ }
+ catch (IOException e)
+ {
+ throw new IOException("Failed to copy scripts metadata file.", innerException: e);
+ }
+ }
- return BuildProjectBlocking("Debug");
+ // NOTE: This will be replaced with C# source generators in 4.0
+ public static string GenerateExportedGameScriptMetadata(bool isDebug)
+ {
+ string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}");
+ CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath);
+ return scriptsMetadataPath;
}
public static void Initialize()
@@ -254,8 +298,6 @@ namespace GodotTools
["hint"] = Godot.PropertyHint.Enum,
["hint_string"] = hintString
});
-
- EditorDef("mono/builds/print_build_output", false);
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
index 8596cd24af..9514cc9622 100644
--- a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs
@@ -5,16 +5,10 @@ using GodotTools.Internals;
using File = GodotTools.Utils.File;
using Path = System.IO.Path;
-namespace GodotTools
+namespace GodotTools.Build
{
- public class BuildTab : VBoxContainer
+ public class BuildOutputView : VBoxContainer, ISerializationListener
{
- public enum BuildResults
- {
- Error,
- Success
- }
-
[Serializable]
private class BuildIssue : Reference // TODO Remove Reference once we have proper serialization
{
@@ -29,10 +23,14 @@ namespace GodotTools
private readonly Array<BuildIssue> issues = new Array<BuildIssue>(); // TODO Use List once we have proper serialization
private ItemList issuesList;
+ private TextEdit buildLog;
+ private PopupMenu issuesListContextMenu;
- public bool BuildExited { get; private set; } = false;
+ [Signal] public event Action BuildStateChanged;
- public BuildResults? BuildResult { get; private set; } = null;
+ public bool HasBuildExited { get; private set; } = false;
+
+ public BuildResult? BuildResult { get; private set; } = null;
public int ErrorCount { get; private set; } = 0;
@@ -41,23 +39,31 @@ namespace GodotTools
public bool ErrorsVisible { get; set; } = true;
public bool WarningsVisible { get; set; } = true;
- public Texture2D IconTexture
+ public Texture2D BuildStateIcon
{
get
{
- if (!BuildExited)
+ if (!HasBuildExited)
return GetThemeIcon("Stop", "EditorIcons");
- if (BuildResult == BuildResults.Error)
- return GetThemeIcon("StatusError", "EditorIcons");
+ if (BuildResult == Build.BuildResult.Error)
+ return GetThemeIcon("Error", "EditorIcons");
+
+ if (WarningCount > 1)
+ return GetThemeIcon("Warning", "EditorIcons");
- return GetThemeIcon("StatusSuccess", "EditorIcons");
+ return null;
}
}
- public BuildInfo BuildInfo { get; private set; }
+ private BuildInfo BuildInfo { get; set; }
- private void _LoadIssuesFromFile(string csvFile)
+ public bool LogVisible
+ {
+ set => buildLog.Visible = value;
+ }
+
+ private void LoadIssuesFromFile(string csvFile)
{
using (var file = new Godot.File())
{
@@ -107,7 +113,7 @@ namespace GodotTools
}
}
- private void _IssueActivated(int idx)
+ private void IssueActivated(int idx)
{
if (idx < 0 || idx >= issuesList.GetItemCount())
throw new IndexOutOfRangeException("Item list index out of range");
@@ -190,49 +196,79 @@ namespace GodotTools
}
}
- public void OnBuildStart()
+ private void BuildLaunchFailed(BuildInfo buildInfo, string cause)
+ {
+ HasBuildExited = true;
+ BuildResult = Build.BuildResult.Error;
+
+ issuesList.Clear();
+
+ var issue = new BuildIssue {Message = cause, Warning = false};
+
+ ErrorCount += 1;
+ issues.Add(issue);
+
+ UpdateIssuesList();
+
+ EmitSignal(nameof(BuildStateChanged));
+ }
+
+ private void BuildStarted(BuildInfo buildInfo)
{
- BuildExited = false;
+ BuildInfo = buildInfo;
+ HasBuildExited = false;
issues.Clear();
WarningCount = 0;
ErrorCount = 0;
+ buildLog.Text = string.Empty;
+
UpdateIssuesList();
- GodotSharpEditor.Instance.BottomPanel.RaiseBuildTab(this);
+ EmitSignal(nameof(BuildStateChanged));
}
- public void OnBuildExit(BuildResults result)
+ private void BuildFinished(BuildResult result)
{
- BuildExited = true;
+ HasBuildExited = true;
BuildResult = result;
- _LoadIssuesFromFile(Path.Combine(BuildInfo.LogsDirPath, BuildManager.MsBuildIssuesFileName));
+ LoadIssuesFromFile(Path.Combine(BuildInfo.LogsDirPath, BuildManager.MsBuildIssuesFileName));
+
UpdateIssuesList();
- GodotSharpEditor.Instance.BottomPanel.RaiseBuildTab(this);
+ EmitSignal(nameof(BuildStateChanged));
}
- public void OnBuildExecFailed(string cause)
+ private void StdOutputReceived(string text)
{
- BuildExited = true;
- BuildResult = BuildResults.Error;
-
- issuesList.Clear();
+ buildLog.Text += text + "\n";
+ ScrollToLastNonEmptyLogLine();
+ }
- var issue = new BuildIssue { Message = cause, Warning = false };
+ private void StdErrorReceived(string text)
+ {
+ buildLog.Text += text + "\n";
+ ScrollToLastNonEmptyLogLine();
+ }
- ErrorCount += 1;
- issues.Add(issue);
+ private void ScrollToLastNonEmptyLogLine()
+ {
+ int line;
+ for (line = buildLog.GetLineCount(); line > 0; line--)
+ {
+ string lineText = buildLog.GetLine(line);
- UpdateIssuesList();
+ if (!string.IsNullOrEmpty(lineText) || !string.IsNullOrEmpty(lineText?.Trim()))
+ break;
+ }
- GodotSharpEditor.Instance.BottomPanel.RaiseBuildTab(this);
+ buildLog.CursorSetLine(line);
}
public void RestartBuild()
{
- if (!BuildExited)
+ if (!HasBuildExited)
throw new InvalidOperationException("Build already started");
BuildManager.RestartBuild(this);
@@ -240,28 +276,118 @@ namespace GodotTools
public void StopBuild()
{
- if (!BuildExited)
+ if (!HasBuildExited)
throw new InvalidOperationException("Build is not in progress");
BuildManager.StopBuild(this);
}
+ private enum IssuesContextMenuOption
+ {
+ Copy
+ }
+
+ private void IssuesListContextOptionPressed(int id)
+ {
+ switch ((IssuesContextMenuOption)id)
+ {
+ case IssuesContextMenuOption.Copy:
+ {
+ // We don't allow multi-selection but just in case that changes later...
+ string text = null;
+
+ foreach (int issueIndex in issuesList.GetSelectedItems())
+ {
+ if (text != null)
+ text += "\n";
+ text += issuesList.GetItemText(issueIndex);
+ }
+
+ if (text != null)
+ DisplayServer.ClipboardSet(text);
+ break;
+ }
+ default:
+ throw new ArgumentOutOfRangeException(nameof(id), id, "Invalid issue context menu option");
+ }
+ }
+
+ private void IssuesListRmbSelected(int index, Vector2 atPosition)
+ {
+ _ = index; // Unused
+
+ issuesListContextMenu.Clear();
+ issuesListContextMenu.Size = new Vector2i(1, 1);
+
+ if (issuesList.IsAnythingSelected())
+ {
+ // Add menu entries for the selected item
+ issuesListContextMenu.AddIconItem(GetThemeIcon("ActionCopy", "EditorIcons"),
+ label: "Copy Error".TTR(), (int)IssuesContextMenuOption.Copy);
+ }
+
+ if (issuesListContextMenu.GetItemCount() > 0)
+ {
+ issuesListContextMenu.Position = (Vector2i)(issuesList.RectGlobalPosition + atPosition);
+ issuesListContextMenu.Popup();
+ }
+ }
+
public override void _Ready()
{
base._Ready();
- issuesList = new ItemList { SizeFlagsVertical = (int)SizeFlags.ExpandFill };
- issuesList.ItemActivated += _IssueActivated;
- AddChild(issuesList);
+ SizeFlagsVertical = (int)SizeFlags.ExpandFill;
+
+ var hsc = new HSplitContainer
+ {
+ SizeFlagsHorizontal = (int)SizeFlags.ExpandFill,
+ SizeFlagsVertical = (int)SizeFlags.ExpandFill
+ };
+ AddChild(hsc);
+
+ issuesList = new ItemList
+ {
+ SizeFlagsVertical = (int)SizeFlags.ExpandFill,
+ SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the build log
+ };
+ issuesList.ItemActivated += IssueActivated;
+ issuesList.AllowRmbSelect = true;
+ issuesList.ItemRmbSelected += IssuesListRmbSelected;
+ hsc.AddChild(issuesList);
+
+ issuesListContextMenu = new PopupMenu();
+ issuesListContextMenu.IdPressed += IssuesListContextOptionPressed;
+ issuesList.AddChild(issuesListContextMenu);
+
+ buildLog = new TextEdit
+ {
+ Readonly = true,
+ SizeFlagsVertical = (int)SizeFlags.ExpandFill,
+ SizeFlagsHorizontal = (int)SizeFlags.ExpandFill // Avoid being squashed by the issues list
+ };
+ hsc.AddChild(buildLog);
+
+ AddBuildEventListeners();
}
- private BuildTab()
+ private void AddBuildEventListeners()
{
+ BuildManager.BuildLaunchFailed += BuildLaunchFailed;
+ BuildManager.BuildStarted += BuildStarted;
+ BuildManager.BuildFinished += BuildFinished;
+ // StdOutput/Error can be received from different threads, so we need to use CallDeferred
+ BuildManager.StdOutputReceived += line => CallDeferred(nameof(StdOutputReceived), line);
+ BuildManager.StdErrorReceived += line => CallDeferred(nameof(StdErrorReceived), line);
}
- public BuildTab(BuildInfo buildInfo)
+ public void OnBeforeSerialize()
{
- BuildInfo = buildInfo;
+ }
+
+ public void OnAfterDeserialize()
+ {
+ AddBuildEventListeners(); // Re-add them
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildResult.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildResult.cs
new file mode 100644
index 0000000000..59055b60c3
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildResult.cs
@@ -0,0 +1,8 @@
+namespace GodotTools.Build
+{
+ public enum BuildResult
+ {
+ Error,
+ Success
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
index d9862ae361..bac7a2e6db 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
@@ -44,10 +44,7 @@ namespace GodotTools.Build
}
}
- private static bool PrintBuildOutput =>
- (bool)EditorSettings.GetSetting("mono/builds/print_build_output");
-
- private static Process LaunchBuild(BuildInfo buildInfo)
+ private static Process LaunchBuild(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler)
{
(string msbuildPath, BuildTool buildTool) = MsBuildFinder.FindMsBuild();
@@ -58,13 +55,13 @@ namespace GodotTools.Build
var startInfo = new ProcessStartInfo(msbuildPath, compilerArgs);
- bool redirectOutput = !IsDebugMsBuildRequested() && !PrintBuildOutput;
-
- if (!redirectOutput || Godot.OS.IsStdoutVerbose())
- Console.WriteLine($"Running: \"{startInfo.FileName}\" {startInfo.Arguments}");
+ string launchMessage = $"Running: \"{startInfo.FileName}\" {startInfo.Arguments}";
+ stdOutHandler?.Invoke(launchMessage);
+ if (Godot.OS.IsStdoutVerbose())
+ Console.WriteLine(launchMessage);
- startInfo.RedirectStandardOutput = redirectOutput;
- startInfo.RedirectStandardError = redirectOutput;
+ startInfo.RedirectStandardOutput = true;
+ startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
if (UsingMonoMsBuildOnWindows)
@@ -82,20 +79,22 @@ namespace GodotTools.Build
var process = new Process {StartInfo = startInfo};
+ if (stdOutHandler != null)
+ process.OutputDataReceived += (s, e) => stdOutHandler.Invoke(e.Data);
+ if (stdErrHandler != null)
+ process.ErrorDataReceived += (s, e) => stdErrHandler.Invoke(e.Data);
+
process.Start();
- if (redirectOutput)
- {
- process.BeginOutputReadLine();
- process.BeginErrorReadLine();
- }
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
return process;
}
- public static int Build(BuildInfo buildInfo)
+ public static int Build(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler)
{
- using (var process = LaunchBuild(buildInfo))
+ using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler))
{
process.WaitForExit();
@@ -103,9 +102,9 @@ namespace GodotTools.Build
}
}
- public static async Task<int> BuildAsync(BuildInfo buildInfo)
+ public static async Task<int> BuildAsync(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler)
{
- using (var process = LaunchBuild(buildInfo))
+ using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler))
{
await process.WaitForExitAsync();
@@ -152,10 +151,5 @@ namespace GodotTools.Build
foreach (string env in platformEnvironmentVariables)
environmentVariables.Remove(env);
}
-
- private static bool IsDebugMsBuildRequested()
- {
- return Environment.GetEnvironmentVariable("GODOT_DEBUG_MSBUILD")?.Trim() == "1";
- }
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
new file mode 100644
index 0000000000..708ec73454
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs
@@ -0,0 +1,185 @@
+using System;
+using Godot;
+using GodotTools.Internals;
+using JetBrains.Annotations;
+using static GodotTools.Internals.Globals;
+using File = GodotTools.Utils.File;
+
+namespace GodotTools.Build
+{
+ public class MSBuildPanel : VBoxContainer
+ {
+ public BuildOutputView BuildOutputView { get; private set; }
+
+ private Button errorsBtn;
+ private Button warningsBtn;
+ private Button viewLogBtn;
+
+ private void WarningsToggled(bool pressed)
+ {
+ BuildOutputView.WarningsVisible = pressed;
+ BuildOutputView.UpdateIssuesList();
+ }
+
+ private void ErrorsToggled(bool pressed)
+ {
+ BuildOutputView.ErrorsVisible = pressed;
+ BuildOutputView.UpdateIssuesList();
+ }
+
+ [UsedImplicitly]
+ public void BuildSolution()
+ {
+ if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
+ return; // No solution to build
+
+ try
+ {
+ // Make sure our packages are added to the fallback folder
+ NuGetUtils.AddBundledPackagesToFallbackFolder(NuGetUtils.GodotFallbackFolderPath);
+ }
+ catch (Exception e)
+ {
+ GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
+ }
+
+ BuildManager.GenerateEditorScriptMetadata();
+
+ if (!BuildManager.BuildProjectBlocking("Debug"))
+ return; // Build failed
+
+ // Notify running game for hot-reload
+ Internal.EditorDebuggerNodeReloadScripts();
+
+ // Hot-reload in the editor
+ GodotSharpEditor.Instance.GetNode<HotReloadAssemblyWatcher>("HotReloadAssemblyWatcher").RestartTimer();
+
+ if (Internal.IsAssembliesReloadingNeeded())
+ Internal.ReloadAssemblies(softReload: false);
+ }
+
+ [UsedImplicitly]
+ private void RebuildSolution()
+ {
+ if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
+ return; // No solution to build
+
+ try
+ {
+ // Make sure our packages are added to the fallback folder
+ NuGetUtils.AddBundledPackagesToFallbackFolder(NuGetUtils.GodotFallbackFolderPath);
+ }
+ catch (Exception e)
+ {
+ GD.PushError("Failed to setup Godot NuGet Offline Packages: " + e.Message);
+ }
+
+ BuildManager.GenerateEditorScriptMetadata();
+
+ if (!BuildManager.BuildProjectBlocking("Debug", targets: new[] {"Rebuild"}))
+ return; // Build failed
+
+ // Notify running game for hot-reload
+ Internal.EditorDebuggerNodeReloadScripts();
+
+ // Hot-reload in the editor
+ GodotSharpEditor.Instance.GetNode<HotReloadAssemblyWatcher>("HotReloadAssemblyWatcher").RestartTimer();
+
+ if (Internal.IsAssembliesReloadingNeeded())
+ Internal.ReloadAssemblies(softReload: false);
+ }
+
+ [UsedImplicitly]
+ private void CleanSolution()
+ {
+ if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
+ return; // No solution to build
+
+ BuildManager.BuildProjectBlocking("Debug", targets: new[] {"Clean"});
+ }
+
+ private void ViewLogToggled(bool pressed) => BuildOutputView.LogVisible = pressed;
+
+ private void BuildMenuOptionPressed(int id)
+ {
+ switch ((BuildMenuOptions)id)
+ {
+ case BuildMenuOptions.BuildSolution:
+ BuildSolution();
+ break;
+ case BuildMenuOptions.RebuildSolution:
+ RebuildSolution();
+ break;
+ case BuildMenuOptions.CleanSolution:
+ CleanSolution();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(id), id, "Invalid build menu option");
+ }
+ }
+
+ private enum BuildMenuOptions
+ {
+ BuildSolution,
+ RebuildSolution,
+ CleanSolution
+ }
+
+ public override void _Ready()
+ {
+ base._Ready();
+
+ RectMinSize = new Vector2(0, 228) * EditorScale;
+ SizeFlagsVertical = (int)SizeFlags.ExpandFill;
+
+ var toolBarHBox = new HBoxContainer {SizeFlagsHorizontal = (int)SizeFlags.ExpandFill};
+ AddChild(toolBarHBox);
+
+ var buildMenuBtn = new MenuButton {Text = "Build", Icon = GetThemeIcon("Play", "EditorIcons")};
+ toolBarHBox.AddChild(buildMenuBtn);
+
+ var buildMenu = buildMenuBtn.GetPopup();
+ buildMenu.AddItem("Build Solution".TTR(), (int)BuildMenuOptions.BuildSolution);
+ buildMenu.AddItem("Rebuild Solution".TTR(), (int)BuildMenuOptions.RebuildSolution);
+ buildMenu.AddItem("Clean Solution".TTR(), (int)BuildMenuOptions.CleanSolution);
+ buildMenu.IdPressed += BuildMenuOptionPressed;
+
+ errorsBtn = new Button
+ {
+ HintTooltip = "Show Errors".TTR(),
+ Icon = GetThemeIcon("StatusError", "EditorIcons"),
+ ExpandIcon = false,
+ ToggleMode = true,
+ Pressed = true,
+ FocusMode = FocusModeEnum.None
+ };
+ errorsBtn.Toggled += ErrorsToggled;
+ toolBarHBox.AddChild(errorsBtn);
+
+ warningsBtn = new Button
+ {
+ HintTooltip = "Show Warnings".TTR(),
+ Icon = GetThemeIcon("NodeWarning", "EditorIcons"),
+ ExpandIcon = false,
+ ToggleMode = true,
+ Pressed = true,
+ FocusMode = FocusModeEnum.None
+ };
+ warningsBtn.Toggled += WarningsToggled;
+ toolBarHBox.AddChild(warningsBtn);
+
+ viewLogBtn = new Button
+ {
+ Text = "Show Output".TTR(),
+ ToggleMode = true,
+ Pressed = true,
+ FocusMode = FocusModeEnum.None
+ };
+ viewLogBtn.Toggled += ViewLogToggled;
+ toolBarHBox.AddChild(viewLogBtn);
+
+ BuildOutputView = new BuildOutputView();
+ AddChild(BuildOutputView);
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
index 7bfba779fb..e2feb66e35 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
@@ -31,7 +31,7 @@ namespace GodotTools.Build
string dotnetCliPath = OS.PathWhich("dotnet");
if (!string.IsNullOrEmpty(dotnetCliPath))
return (dotnetCliPath, BuildTool.DotnetCli);
- GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Visual Studio.");
+ GD.PushError($"Cannot find executable for '{BuildManager.PropNameDotnetCli}'. Fallback to MSBuild from Visual Studio.");
goto case BuildTool.MsBuildVs;
}
case BuildTool.MsBuildVs:
@@ -89,7 +89,7 @@ namespace GodotTools.Build
string dotnetCliPath = OS.PathWhich("dotnet");
if (!string.IsNullOrEmpty(dotnetCliPath))
return (dotnetCliPath, BuildTool.DotnetCli);
- GD.PushError("Cannot find dotnet CLI executable. Fallback to MSBuild from Mono.");
+ GD.PushError($"Cannot find executable for '{BuildManager.PropNameDotnetCli}'. Fallback to MSBuild from Mono.");
goto case BuildTool.MsBuildMono;
}
case BuildTool.MsBuildMono:
@@ -119,7 +119,7 @@ namespace GodotTools.Build
{
var result = new List<string>();
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
result.Add("/Library/Frameworks/Mono.framework/Versions/Current/bin/");
result.Add("/usr/local/var/homebrew/linked/mono/bin/");
@@ -161,7 +161,7 @@ namespace GodotTools.Build
// Try to find 15.0 with vswhere
- var envNames = Internal.GodotIs32Bits() ? new[] { "ProgramFiles", "ProgramW6432" } : new[] { "ProgramFiles(x86)", "ProgramFiles" };
+ var envNames = Internal.GodotIs32Bits() ? new[] {"ProgramFiles", "ProgramW6432"} : new[] {"ProgramFiles(x86)", "ProgramFiles"};
string vsWherePath = null;
foreach (var envName in envNames)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
new file mode 100644
index 0000000000..793ef7fd71
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
@@ -0,0 +1,296 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Xml;
+using Godot;
+using GodotTools.Internals;
+using GodotTools.Shared;
+using Directory = GodotTools.Utils.Directory;
+using Environment = System.Environment;
+using File = GodotTools.Utils.File;
+
+namespace GodotTools.Build
+{
+ public static class NuGetUtils
+ {
+ public const string GodotFallbackFolderName = "Godot Offline Packages";
+
+ public static string GodotFallbackFolderPath
+ => Path.Combine(GodotSharpDirs.MonoUserDir, "GodotNuGetFallbackFolder");
+
+ private static void AddFallbackFolderToNuGetConfig(string nuGetConfigPath, string name, string path)
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(nuGetConfigPath);
+
+ const string nuGetConfigRootName = "configuration";
+
+ var rootNode = xmlDoc.DocumentElement;
+
+ if (rootNode == null)
+ {
+ // No root node, create it
+ rootNode = xmlDoc.CreateElement(nuGetConfigRootName);
+ xmlDoc.AppendChild(rootNode);
+
+ // Since this can be considered pretty much a new NuGet.Config, add the default nuget.org source as well
+ XmlElement nugetOrgSourceEntry = xmlDoc.CreateElement("add");
+ nugetOrgSourceEntry.Attributes.Append(xmlDoc.CreateAttribute("key")).Value = "nuget.org";
+ nugetOrgSourceEntry.Attributes.Append(xmlDoc.CreateAttribute("value")).Value = "https://api.nuget.org/v3/index.json";
+ nugetOrgSourceEntry.Attributes.Append(xmlDoc.CreateAttribute("protocolVersion")).Value = "3";
+ rootNode.AppendChild(xmlDoc.CreateElement("packageSources")).AppendChild(nugetOrgSourceEntry);
+ }
+ else
+ {
+ // Check that the root node is the expected one
+ if (rootNode.Name != nuGetConfigRootName)
+ throw new Exception("Invalid root Xml node for NuGet.Config. " +
+ $"Expected '{nuGetConfigRootName}' got '{rootNode.Name}'.");
+ }
+
+ var fallbackFoldersNode = rootNode["fallbackPackageFolders"] ??
+ rootNode.AppendChild(xmlDoc.CreateElement("fallbackPackageFolders"));
+
+ // Check if it already has our fallback package folder
+ for (var xmlNode = fallbackFoldersNode.FirstChild; xmlNode != null; xmlNode = xmlNode.NextSibling)
+ {
+ if (xmlNode.NodeType != XmlNodeType.Element)
+ continue;
+
+ var xmlElement = (XmlElement)xmlNode;
+ if (xmlElement.Name == "add" &&
+ xmlElement.Attributes["key"]?.Value == name &&
+ xmlElement.Attributes["value"]?.Value == path)
+ {
+ return;
+ }
+ }
+
+ XmlElement newEntry = xmlDoc.CreateElement("add");
+ newEntry.Attributes.Append(xmlDoc.CreateAttribute("key")).Value = name;
+ newEntry.Attributes.Append(xmlDoc.CreateAttribute("value")).Value = path;
+
+ fallbackFoldersNode.AppendChild(newEntry);
+
+ xmlDoc.Save(nuGetConfigPath);
+ }
+
+ /// <summary>
+ /// Returns all the paths where the user NuGet.Config files can be found.
+ /// Does not determine whether the returned files exist or not.
+ /// </summary>
+ private static string[] GetAllUserNuGetConfigFilePaths()
+ {
+ // Where to find 'NuGet/NuGet.Config':
+ //
+ // - Mono/.NETFramework (standalone NuGet):
+ // Uses Environment.SpecialFolder.ApplicationData
+ // - Windows: '%APPDATA%'
+ // - Linux/macOS: '$HOME/.config'
+ // - CoreCLR (dotnet CLI NuGet):
+ // - Windows: '%APPDATA%'
+ // - Linux/macOS: '$DOTNET_CLI_HOME/.nuget' otherwise '$HOME/.nuget'
+
+ string applicationData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+
+ if (Utils.OS.IsWindows)
+ {
+ // %APPDATA% for both
+ return new[] {Path.Combine(applicationData, "NuGet", "NuGet.Config")};
+ }
+
+ var paths = new string[2];
+
+ // CoreCLR (dotnet CLI NuGet)
+
+ string dotnetCliHome = Environment.GetEnvironmentVariable("DOTNET_CLI_HOME");
+ if (!string.IsNullOrEmpty(dotnetCliHome))
+ {
+ paths[0] = Path.Combine(dotnetCliHome, ".nuget", "NuGet", "NuGet.Config");
+ }
+ else
+ {
+ string home = Environment.GetEnvironmentVariable("HOME");
+ if (string.IsNullOrEmpty(home))
+ throw new InvalidOperationException("Required environment variable 'HOME' is not set.");
+ paths[0] = Path.Combine(home, ".nuget", "NuGet", "NuGet.Config");
+ }
+
+ // Mono/.NETFramework (standalone NuGet)
+
+ // ApplicationData is $HOME/.config on Linux/macOS
+ paths[1] = Path.Combine(applicationData, "NuGet", "NuGet.Config");
+
+ return paths;
+ }
+
+ // nupkg extraction
+ //
+ // Exclude: (NuGet.Client -> NuGet.Packaging.PackageHelper.ExcludePaths)
+ // package/
+ // _rels/
+ // [Content_Types].xml
+ //
+ // Don't ignore files that begin with a dot (.)
+ //
+ // The nuspec is not lower case inside the nupkg but must be made lower case when extracted.
+
+ /// <summary>
+ /// Adds the specified fallback folder to the user NuGet.Config files,
+ /// for both standalone NuGet (Mono/.NETFramework) and dotnet CLI NuGet.
+ /// </summary>
+ public static void AddFallbackFolderToUserNuGetConfigs(string name, string path)
+ {
+ foreach (string nuGetConfigPath in GetAllUserNuGetConfigFilePaths())
+ {
+ if (!System.IO.File.Exists(nuGetConfigPath))
+ {
+ // It doesn't exist, so we create a default one
+ const string defaultConfig = @"<?xml version=""1.0"" encoding=""utf-8""?>
+<configuration>
+ <packageSources>
+ <add key=""nuget.org"" value=""https://api.nuget.org/v3/index.json"" protocolVersion=""3"" />
+ </packageSources>
+</configuration>
+";
+ System.IO.File.WriteAllText(nuGetConfigPath, defaultConfig, Encoding.UTF8); // UTF-8 with BOM
+ }
+
+ AddFallbackFolderToNuGetConfig(nuGetConfigPath, name, path);
+ }
+ }
+
+ private static void AddPackageToFallbackFolder(string fallbackFolder,
+ string nupkgPath, string packageId, string packageVersion)
+ {
+ // dotnet CLI provides no command for this, but we can do it manually.
+ //
+ // - The expected structure is as follows:
+ // fallback_folder/
+ // <package.name>/<version>/
+ // <package.name>.<version>.nupkg
+ // <package.name>.<version>.nupkg.sha512
+ // <package.name>.nuspec
+ // ... extracted nupkg files (check code for excluded files) ...
+ //
+ // - <package.name> and <version> must be in lower case.
+ // - The sha512 of the nupkg is base64 encoded.
+ // - We can get the nuspec from the nupkg which is a Zip file.
+
+ string packageIdLower = packageId.ToLower();
+ string packageVersionLower = packageVersion.ToLower();
+
+ string destDir = Path.Combine(fallbackFolder, packageIdLower, packageVersionLower);
+ string nupkgDestPath = Path.Combine(destDir, $"{packageIdLower}.{packageVersionLower}.nupkg");
+ string nupkgSha512DestPath = Path.Combine(destDir, $"{packageIdLower}.{packageVersionLower}.nupkg.sha512");
+
+ if (File.Exists(nupkgDestPath) && File.Exists(nupkgSha512DestPath))
+ return; // Already added (for speed we don't check if every file is properly extracted)
+
+ Directory.CreateDirectory(destDir);
+
+ // Generate .nupkg.sha512 file
+
+ using (var alg = SHA512.Create())
+ {
+ alg.ComputeHash(File.ReadAllBytes(nupkgPath));
+ string base64Hash = Convert.ToBase64String(alg.Hash);
+ File.WriteAllText(nupkgSha512DestPath, base64Hash);
+ }
+
+ // Extract nupkg
+ ExtractNupkg(destDir, nupkgPath, packageId, packageVersion);
+
+ // Copy .nupkg
+ File.Copy(nupkgPath, nupkgDestPath);
+ }
+
+ private static readonly string[] NupkgExcludePaths =
+ {
+ "_rels/",
+ "package/",
+ "[Content_Types].xml"
+ };
+
+ private static void ExtractNupkg(string destDir, string nupkgPath, string packageId, string packageVersion)
+ {
+ // NOTE: Must use SimplifyGodotPath to make sure we don't extract files outside the destination directory.
+
+ using (var archive = ZipFile.OpenRead(nupkgPath))
+ {
+ // Extract .nuspec manually as it needs to be in lower case
+
+ var nuspecEntry = archive.GetEntry(packageId + ".nuspec");
+
+ if (nuspecEntry == null)
+ throw new InvalidOperationException($"Failed to extract package {packageId}.{packageVersion}. Could not find the nuspec file.");
+
+ nuspecEntry.ExtractToFile(Path.Combine(destDir, nuspecEntry.Name.ToLower().SimplifyGodotPath()));
+
+ // Extract the other package files
+
+ foreach (var entry in archive.Entries)
+ {
+ // NOTE: SimplifyGodotPath() removes trailing slash and backslash,
+ // so we can't use the result to check if the entry is a directory.
+
+ string entryFullName = entry.FullName.Replace('\\', '/');
+
+ // Check if the file must be ignored
+ if ( // Excluded files.
+ NupkgExcludePaths.Any(e => entryFullName.StartsWith(e, StringComparison.OrdinalIgnoreCase)) ||
+ // Nupkg hash files and nupkg metadata files on all directory.
+ entryFullName.EndsWith(".nupkg.sha512", StringComparison.OrdinalIgnoreCase) ||
+ entryFullName.EndsWith(".nupkg.metadata", StringComparison.OrdinalIgnoreCase) ||
+ // Nuspec at root level. We already extracted it previously but in lower case.
+ entryFullName.IndexOf('/') == -1 && entryFullName.EndsWith(".nuspec"))
+ {
+ continue;
+ }
+
+ string entryFullNameSimplified = entryFullName.SimplifyGodotPath();
+ string destFilePath = Path.Combine(destDir, entryFullNameSimplified);
+ bool isDir = entryFullName.EndsWith("/");
+
+ if (isDir)
+ {
+ Directory.CreateDirectory(destFilePath);
+ }
+ else
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(destFilePath));
+ entry.ExtractToFile(destFilePath, overwrite: true);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies and extracts all the Godot bundled packages to the Godot NuGet fallback folder.
+ /// Does nothing if the packages were already copied.
+ /// </summary>
+ public static void AddBundledPackagesToFallbackFolder(string fallbackFolder)
+ {
+ GD.Print("Copying Godot Offline Packages...");
+
+ string nupkgsLocation = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "nupkgs");
+
+ void AddPackage(string packageId, string packageVersion)
+ {
+ string nupkgPath = Path.Combine(nupkgsLocation, $"{packageId}.{packageVersion}.nupkg");
+ AddPackageToFallbackFolder(fallbackFolder, nupkgPath, packageId, packageVersion);
+ }
+
+ foreach (var (packageId, packageVersion) in PackagesToAdd)
+ AddPackage(packageId, packageVersion);
+ }
+
+ private static readonly (string packageId, string packageVersion)[] PackagesToAdd =
+ {
+ ("Godot.NET.Sdk", GeneratedGodotNupkgsVersions.GodotNETSdk)
+ };
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 42ede3f3f3..5bb8d444c2 100755
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -120,7 +120,7 @@ namespace GodotTools.Export
string assemblyPath = assembly.Value;
string outputFileExtension = platform == OS.Platforms.Windows ? ".dll" :
- platform == OS.Platforms.OSX ? ".dylib" :
+ platform == OS.Platforms.MacOS ? ".dylib" :
".so";
string outputFileName = assemblyName + ".dll" + outputFileExtension;
@@ -132,7 +132,7 @@ namespace GodotTools.Export
ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir);
- if (platform == OS.Platforms.OSX)
+ if (platform == OS.Platforms.MacOS)
{
exporter.AddSharedObject(tempOutputFilePath, tags: null);
}
@@ -581,7 +581,7 @@ MONO_AOT_MODE_LAST = 1000,
string arch = bits == "64" ? "x86_64" : "i686";
return $"windows-{arch}";
}
- case OS.Platforms.OSX:
+ case OS.Platforms.MacOS:
{
Debug.Assert(bits == null || bits == "64");
string arch = "x86_64";
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index 599ca94699..e18ed7f107 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -5,6 +5,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
+using GodotTools.Build;
using GodotTools.Core;
using GodotTools.Internals;
using JetBrains.Annotations;
@@ -143,6 +144,8 @@ namespace GodotTools.Export
private void _ExportBeginImpl(string[] features, bool isDebug, string path, int flags)
{
+ _ = flags; // Unused
+
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
return;
@@ -154,12 +157,10 @@ namespace GodotTools.Export
string buildConfig = isDebug ? "ExportDebug" : "ExportRelease";
- string scriptsMetadataPath = Path.Combine(GodotSharpDirs.ResMetadataDir, $"scripts_metadata.{(isDebug ? "debug" : "release")}");
- CsProjOperations.GenerateScriptsMetadata(GodotSharpDirs.ProjectCsProjPath, scriptsMetadataPath);
-
+ string scriptsMetadataPath = BuildManager.GenerateExportedGameScriptMetadata(isDebug);
AddFile(scriptsMetadataPath, scriptsMetadataPath);
- if (!BuildManager.BuildProjectBlocking(buildConfig, platform))
+ if (!BuildManager.BuildProjectBlocking(buildConfig, platform: platform))
throw new Exception("Failed to build project");
// Add dependency assemblies
@@ -340,7 +341,7 @@ namespace GodotTools.Export
private static bool PlatformHasTemplateDir(string platform)
{
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
- return !new[] {OS.Platforms.OSX, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform);
+ return !new[] {OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform);
}
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
@@ -411,7 +412,7 @@ namespace GodotTools.Export
case OS.Platforms.Windows:
case OS.Platforms.UWP:
return "net_4_x_win";
- case OS.Platforms.OSX:
+ case OS.Platforms.MacOS:
case OS.Platforms.LinuxBSD:
case OS.Platforms.Server:
case OS.Platforms.Haiku:
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 2a450c5b87..58561c5097 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -4,9 +4,9 @@ using GodotTools.Export;
using GodotTools.Utils;
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
+using GodotTools.Build;
using GodotTools.Ides;
using GodotTools.Ides.Rider;
using GodotTools.Internals;
@@ -19,7 +19,6 @@ using Path = System.IO.Path;
namespace GodotTools
{
- [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
public class GodotSharpEditor : EditorPlugin, ISerializationListener
{
private EditorSettings editorSettings;
@@ -37,7 +36,7 @@ namespace GodotTools
private WeakRef exportPluginWeak; // TODO Use WeakReference once we have proper serialization
- public BottomPanel BottomPanel { get; private set; }
+ public MSBuildPanel MSBuildPanel { get; private set; }
public bool SkipBuildBeforePlaying { get; set; } = false;
@@ -148,12 +147,27 @@ namespace GodotTools
case MenuOptions.AboutCSharp:
_ShowAboutDialog();
break;
+ case MenuOptions.SetupGodotNugetFallbackFolder:
+ {
+ try
+ {
+ string fallbackFolder = NuGetUtils.GodotFallbackFolderPath;
+ NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, fallbackFolder);
+ NuGetUtils.AddBundledPackagesToFallbackFolder(fallbackFolder);
+ }
+ catch (Exception e)
+ {
+ ShowErrorDialog("Failed to setup Godot NuGet Offline Packages: " + e.Message);
+ }
+
+ break;
+ }
default:
throw new ArgumentOutOfRangeException(nameof(id), id, "Invalid menu option");
}
}
- private void _BuildSolutionPressed()
+ private void BuildSolutionPressed()
{
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
{
@@ -161,23 +175,22 @@ namespace GodotTools
return; // Failed to create solution
}
- Instance.BottomPanel.BuildProjectPressed();
+ Instance.MSBuildPanel.BuildSolution();
}
- public override void _Notification(int what)
+ public override void _Ready()
{
- base._Notification(what);
+ base._Ready();
- if (what == NotificationReady)
+ MSBuildPanel.BuildOutputView.BuildStateChanged += BuildStateChanged;
+
+ bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
+ if (showInfoDialog)
{
- bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
- if (showInfoDialog)
- {
- aboutDialog.Exclusive = true;
- _ShowAboutDialog();
- // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on.
- aboutDialog.Exclusive = false;
- }
+ aboutDialog.Exclusive = true;
+ _ShowAboutDialog();
+ // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on.
+ aboutDialog.Exclusive = false;
}
}
@@ -185,6 +198,7 @@ namespace GodotTools
{
CreateSln,
AboutCSharp,
+ SetupGodotNugetFallbackFolder,
}
public void ShowErrorDialog(string message, string title = "Error")
@@ -272,7 +286,7 @@ namespace GodotTools
bool osxAppBundleInstalled = false;
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
// The package path is '/Applications/Visual Studio Code.app'
const string vscodeBundleId = "com.microsoft.VSCode";
@@ -312,7 +326,7 @@ namespace GodotTools
string command;
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath))
{
@@ -393,6 +407,12 @@ namespace GodotTools
}
}
+ private void BuildStateChanged()
+ {
+ if (bottomPanelBtn != null)
+ bottomPanelBtn.Icon = MSBuildPanel.BuildOutputView.BuildStateIcon;
+ }
+
public override void EnablePlugin()
{
base.EnablePlugin();
@@ -409,20 +429,20 @@ namespace GodotTools
errorDialog = new AcceptDialog();
editorBaseControl.AddChild(errorDialog);
- BottomPanel = new BottomPanel();
-
- bottomPanelBtn = AddControlToBottomPanel(BottomPanel, "Mono".TTR());
+ MSBuildPanel = new MSBuildPanel();
+ bottomPanelBtn = AddControlToBottomPanel(MSBuildPanel, "MSBuild".TTR());
AddChild(new HotReloadAssemblyWatcher {Name = "HotReloadAssemblyWatcher"});
menuPopup = new PopupMenu();
menuPopup.Hide();
- AddToolSubmenuItem("Mono", menuPopup);
+ AddToolSubmenuItem("C#", menuPopup);
// TODO: Remove or edit this info dialog once Mono support is no longer in alpha
{
menuPopup.AddItem("About C# support".TTR(), (int)MenuOptions.AboutCSharp);
+ menuPopup.AddItem("Setup Godot NuGet Offline Packages".TTR(), (int)MenuOptions.SetupGodotNugetFallbackFolder);
aboutDialog = new AcceptDialog();
editorBaseControl.AddChild(aboutDialog);
aboutDialog.Title = "Important: C# support is not feature-complete";
@@ -476,7 +496,7 @@ namespace GodotTools
HintTooltip = "Build solution",
FocusMode = Control.FocusModeEnum.None
};
- toolBarBuildButton.PressedSignal += _BuildSolutionPressed;
+ toolBarBuildButton.PressedSignal += BuildSolutionPressed;
AddControlToContainer(CustomControlContainer.Toolbar, toolBarBuildButton);
if (File.Exists(GodotSharpDirs.ProjectSlnPath) && File.Exists(GodotSharpDirs.ProjectCsProjPath))
@@ -504,7 +524,7 @@ namespace GodotTools
$",Visual Studio Code:{(int)ExternalEditorId.VsCode}" +
$",JetBrains Rider:{(int)ExternalEditorId.Rider}";
}
- else if (OS.IsOSX)
+ else if (OS.IsMacOS)
{
settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudioForMac}" +
$",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" +
@@ -532,6 +552,16 @@ namespace GodotTools
exportPlugin.RegisterExportSettings();
exportPluginWeak = WeakRef(exportPlugin);
+ try
+ {
+ // At startup we make sure NuGet.Config files have our Godot NuGet fallback folder included
+ NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, NuGetUtils.GodotFallbackFolderPath);
+ }
+ catch (Exception e)
+ {
+ GD.PushError("Failed to add Godot NuGet Offline Packages to NuGet.Config: " + e.Message);
+ }
+
BuildManager.Initialize();
RiderPathManager.Initialize();
@@ -570,6 +600,7 @@ namespace GodotTools
public static GodotSharpEditor Instance { get; private set; }
+ [UsedImplicitly]
private GodotSharpEditor()
{
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
index e4932ca217..451ce39f5c 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs
@@ -111,7 +111,7 @@ namespace GodotTools.Ides
{
MonoDevelop.Instance GetMonoDevelopInstance(string solutionPath)
{
- if (Utils.OS.IsOSX && editorId == ExternalEditorId.VisualStudioForMac)
+ if (Utils.OS.IsMacOS && editorId == ExternalEditorId.VisualStudioForMac)
{
vsForMacInstance = (vsForMacInstance?.IsDisposed ?? true ? null : vsForMacInstance) ??
new MonoDevelop.Instance(solutionPath, MonoDevelop.EditorId.VisualStudioForMac);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
index d6fa2eeba7..fd7bbd5578 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs
@@ -26,7 +26,7 @@ namespace GodotTools.Ides.MonoDevelop
string command;
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
string bundleId = BundleIds[editorId];
@@ -85,7 +85,7 @@ namespace GodotTools.Ides.MonoDevelop
public Instance(string solutionFile, EditorId editorId)
{
- if (editorId == EditorId.VisualStudioForMac && !OS.IsOSX)
+ if (editorId == EditorId.VisualStudioForMac && !OS.IsMacOS)
throw new InvalidOperationException($"{nameof(EditorId.VisualStudioForMac)} not supported on this platform");
this.solutionFile = solutionFile;
@@ -103,7 +103,7 @@ namespace GodotTools.Ides.MonoDevelop
static Instance()
{
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
ExecutableNames = new Dictionary<EditorId, string>
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
index e22e9af919..94fc5da425 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
@@ -32,7 +32,7 @@ namespace GodotTools.Ides.Rider
{
return CollectRiderInfosWindows();
}
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
return CollectRiderInfosMac();
}
@@ -138,7 +138,7 @@ namespace GodotTools.Ides.Rider
return GetToolboxRiderRootPath(localAppData);
}
- if (OS.IsOSX)
+ if (OS.IsMacOS)
{
var home = Environment.GetEnvironmentVariable("HOME");
if (string.IsNullOrEmpty(home))
@@ -211,7 +211,7 @@ namespace GodotTools.Ides.Rider
{
if (OS.IsWindows || OS.IsUnixLike)
return "../../build.txt";
- if (OS.IsOSX)
+ if (OS.IsMacOS)
return "Contents/Resources/build.txt";
throw new Exception("Unknown OS.");
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index 6c05891f2c..e745966435 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -21,7 +21,7 @@ namespace GodotTools.Utils
public static class Names
{
public const string Windows = "Windows";
- public const string OSX = "OSX";
+ public const string MacOS = "macOS";
public const string Linux = "Linux";
public const string FreeBSD = "FreeBSD";
public const string NetBSD = "NetBSD";
@@ -37,7 +37,7 @@ namespace GodotTools.Utils
public static class Platforms
{
public const string Windows = "windows";
- public const string OSX = "osx";
+ public const string MacOS = "osx";
public const string LinuxBSD = "linuxbsd";
public const string Server = "server";
public const string UWP = "uwp";
@@ -50,7 +50,7 @@ namespace GodotTools.Utils
public static readonly Dictionary<string, string> PlatformNameMap = new Dictionary<string, string>
{
[Names.Windows] = Platforms.Windows,
- [Names.OSX] = Platforms.OSX,
+ [Names.MacOS] = Platforms.MacOS,
[Names.Linux] = Platforms.LinuxBSD,
[Names.FreeBSD] = Platforms.LinuxBSD,
[Names.NetBSD] = Platforms.LinuxBSD,
@@ -77,11 +77,11 @@ namespace GodotTools.Utils
new[] {Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD};
private static readonly IEnumerable<string> UnixLikePlatforms =
- new[] {Names.OSX, Names.Server, Names.Haiku, Names.Android, Names.iOS}
+ new[] {Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS}
.Concat(LinuxBSDPlatforms).ToArray();
private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows));
- private static readonly Lazy<bool> _isOSX = new Lazy<bool>(() => IsOS(Names.OSX));
+ private static readonly Lazy<bool> _isMacOS = new Lazy<bool>(() => IsOS(Names.MacOS));
private static readonly Lazy<bool> _isLinuxBSD = new Lazy<bool>(() => IsAnyOS(LinuxBSDPlatforms));
private static readonly Lazy<bool> _isServer = new Lazy<bool>(() => IsOS(Names.Server));
private static readonly Lazy<bool> _isUWP = new Lazy<bool>(() => IsOS(Names.UWP));
@@ -92,7 +92,7 @@ namespace GodotTools.Utils
private static readonly Lazy<bool> _isUnixLike = new Lazy<bool>(() => IsAnyOS(UnixLikePlatforms));
public static bool IsWindows => _isWindows.Value || IsUWP;
- public static bool IsOSX => _isOSX.Value;
+ public static bool IsMacOS => _isMacOS.Value;
public static bool IsLinuxBSD => _isLinuxBSD.Value;
public static bool IsServer => _isServer.Value;
public static bool IsUWP => _isUWP.Value;
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index a17c371117..4c137a2ba4 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -97,7 +97,7 @@
#define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL "::signal_info_to_callable"
#define C_METHOD_MANAGED_FROM_SIGNAL C_NS_MONOMARSHAL "::callable_to_signal_info"
-#define BINDINGS_GENERATOR_VERSION UINT32_C(11)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(12)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n");
@@ -1368,7 +1368,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
output.append(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
output.append("." + ctor_method);
- output.append("(this);\n" CLOSE_BLOCK_L2);
+ output.append("(this);\n" INDENT3 "_InitializeGodotScriptInstanceInternals();\n" CLOSE_BLOCK_L2);
} else {
// Hide the constructor
output.append(MEMBER_BEGIN "internal ");
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
index 42610c5ef7..48582d5ad8 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs
@@ -15,14 +15,13 @@ namespace Godot
public Object() : this(false)
{
if (ptr == IntPtr.Zero)
- {
ptr = godot_icall_Object_Ctor(this);
- }
- else
- {
- // This is called inside godot_icall_Object_Ctor, so we must call it as well in this case.
- godot_icall_Object_ConnectEventSignals(ptr);
- }
+ _InitializeGodotScriptInstanceInternals();
+ }
+
+ internal void _InitializeGodotScriptInstanceInternals()
+ {
+ godot_icall_Object_ConnectEventSignals(ptr);
}
internal Object(bool memoryOwn)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index bd1dbc1229..d63db0f905 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -393,6 +393,35 @@ namespace Godot
return instance.Substring(sep + 1);
}
+ /// <summary>
+ /// Converts the given byte array of ASCII encoded text to a string.
+ /// Faster alternative to <see cref="GetStringFromUTF8"/> if the
+ /// content is ASCII-only. Unlike the UTF-8 function this function
+ /// maps every byte to a character in the array. Multibyte sequences
+ /// will not be interpreted correctly. For parsing user input always
+ /// use <see cref="GetStringFromUTF8"/>.
+ /// </summary>
+ /// <param name="bytes">A byte array of ASCII characters (on the range of 0-127).</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromASCII(this byte[] bytes)
+ {
+ return Encoding.ASCII.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Converts the given byte array of UTF-8 encoded text to a string.
+ /// Slower than <see cref="GetStringFromASCII"/> but supports UTF-8
+ /// encoded data. Use this function if you are unsure about the
+ /// source of the data. For user input this function
+ /// should always be preferred.
+ /// </summary>
+ /// <param name="bytes">A byte array of UTF-8 characters (a character may take up multiple bytes).</param>
+ /// <returns>A string created from the bytes.</returns>
+ public static string GetStringFromUTF8(this byte[] bytes)
+ {
+ return Encoding.UTF8.GetString(bytes);
+ }
+
// <summary>
// Hash the string and return a 32 bits integer.
// </summary>
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index ebcd6d5e9c..439fb1ab0a 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -31,7 +31,6 @@
#ifdef MONO_GLUE_ENABLED
#include "core/class_db.h"
-#include "core/object.h"
#include "core/reference.h"
#include "core/string_name.h"
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index c1f1936711..dc3bf47838 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -64,7 +64,6 @@ void godot_register_glue_header_icalls() {
#include "core/engine.h"
#include "core/method_bind.h"
#include "core/node_path.h"
-#include "core/object.h"
#include "core/reference.h"
#include "core/typedefs.h"
#include "core/ustring.h"
diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/rid_glue.cpp
index 6d2e6b559f..a7b18c36dd 100644
--- a/modules/mono/glue/rid_glue.cpp
+++ b/modules/mono/glue/rid_glue.cpp
@@ -30,7 +30,7 @@
#ifdef MONO_GLUE_ENABLED
-#include "core/object.h"
+#include "core/class_db.h"
#include "core/resource.h"
#include "core/rid.h"
diff --git a/modules/mono/icons/CSharpScript.svg b/modules/mono/icons/CSharpScript.svg
index 69664ca553..0b2cc840f8 100644
--- a/modules/mono/icons/CSharpScript.svg
+++ b/modules/mono/icons/CSharpScript.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path d="m6 1046.4c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h1v-2h-1c-0.55228 0-1-0.4478-1-1 0-0.5523 0.44772-1 1-1h1v-2zm1-9-0.56445 2.2578c-0.23643 0.076-0.46689 0.1692-0.68945 0.2793l-1.9883-1.1933-1.4141 1.414 1.1953 1.9942c-0.11191 0.2211-0.20723 0.4502-0.28516 0.6855l-2.2539 0.5625v2h5.2715c-0.17677-0.3037-0.27041-0.6486-0.27148-1 9.6e-6 -1.1046 0.89543-2 2-2s2 0.8954 2 2c-4.817e-4 0.3512-0.093442 0.6961-0.26953 1h5.2695v-2l-2.2578-0.5645c-0.07594-0.2357-0.1693-0.4655-0.2793-0.6875l1.1934-1.9902-1.4141-1.414-1.9941 1.1953c-0.22113-0.1119-0.45028-0.2073-0.68555-0.2852l-0.5625-2.2539zm4 9c-0.71466-1e-4 -1.3751 0.3811-1.7324 1-0.35727 0.6188-0.35727 1.3812 0 2 0.35733 0.6189 1.0178 1.0001 1.7324 1h-2v2h2c0.71466 1e-4 1.3751-0.3811 1.7324-1 0.35727-0.6188 0.35727-1.3812 0-2-0.35733-0.6189-1.0178-1.0001-1.7324-1h2v-2z" fill="#e0e0e0"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1046.4c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h1v-2h-1c-.55228 0-1-.4478-1-1 0-.5523.44772-1 1-1h1v-2zm1-9-.56445 2.2578c-.23643.076-.46689.1692-.68945.2793l-1.9883-1.1933-1.4141 1.414 1.1953 1.9942c-.11191.2211-.20723.4502-.28516.6855l-2.2539.5625v2h5.2715c-.17677-.3037-.27041-.6486-.27148-1 .0000096-1.1046.89543-2 2-2s2 .8954 2 2c-.0004817.3512-.093442.6961-.26953 1h5.2695v-2l-2.2578-.5645c-.07594-.2357-.1693-.4655-.2793-.6875l1.1934-1.9902-1.4141-1.414-1.9941 1.1953c-.22113-.1119-.45028-.2073-.68555-.2852l-.5625-2.2539zm4 9c-.71466-.0001-1.3751.3811-1.7324 1-.35727.6188-.35727 1.3812 0 2 .35733.6189 1.0178 1.0001 1.7324 1h-2v2h2c.71466.0001 1.3751-.3811 1.7324-1 .35727-.6188.35727-1.3812 0-2-.35733-.6189-1.0178-1.0001-1.7324-1h2v-2z" fill="#e0e0e0" transform="translate(0 -1036.4)"/></svg>
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index fe1c2d28dd..0ed9e441ef 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -109,8 +109,6 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
unmanaged->set_script_and_instance(script, csharp_instance);
-
- csharp_instance->connect_event_signals();
}
void unhandled_exception(MonoException *p_exc) {
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 038d17f782..cf7efdecd6 100644
--- a/modules/mono/mono_gd/gd_mono_internals.h
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -35,7 +35,7 @@
#include "../utils/macros.h"
-#include "core/object.h"
+#include "core/class_db.h"
namespace GDMonoInternals {
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 5958bf3cc1..80569cb1c7 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -37,7 +37,7 @@
#include "../utils/macros.h"
#include "gd_mono_header.h"
-#include "core/object.h"
+#include "core/class_db.h"
#include "core/reference.h"
#define UNHANDLED_EXCEPTION(m_exc) \
diff --git a/modules/opensimplex/icons/NoiseTexture.svg b/modules/opensimplex/icons/NoiseTexture.svg
index 5908c2b2d4..479684cde2 100644
--- a/modules/opensimplex/icons/NoiseTexture.svg
+++ b/modules/opensimplex/icons/NoiseTexture.svg
@@ -1,3 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="m2 1c-0.55228 0-1 0.44772-1 1v12c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-12c0-0.55228-0.44772-1-1-1zm1 2h10v8h-10zm3 1v2h2v-2zm2 2v2h2v2h2v-6h-2v2zm0 2h-2v-2h-2v4h4z" fill="#e0e0e0" fill-opacity=".99608"/>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55228 0-1 .44772-1 1v12c0 .55228.44772 1 1 1h12c.55228 0 1-.44772 1-1v-12c0-.55228-.44772-1-1-1zm1 2h10v8h-10zm3 1v2h2v-2zm2 2v2h2v2h2v-6h-2v2zm0 2h-2v-2h-2v4h4z" fill="#e0e0e0" fill-opacity=".99608"/></svg>
diff --git a/modules/visual_script/icons/VisualScript.svg b/modules/visual_script/icons/VisualScript.svg
index f6475d590e..2352ba5d87 100644
--- a/modules/visual_script/icons/VisualScript.svg
+++ b/modules/visual_script/icons/VisualScript.svg
@@ -1,6 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<ellipse cx="3" cy="1039.4" r="2" fill="#6e6e6e"/>
-<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625v2h5.2715a2 2 0 0 1 -0.27148 -1 2 2 0 0 1 2 -2 2 2 0 0 1 2 2 2 2 0 0 1 -0.26953 1h5.2695v-2l-2.2578-0.56445a5 5 0 0 0 -0.2793 -0.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2zm-4 9v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2zm8 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0 -2 2 2 0 0 0 -1.7324 -1h2v-2h-2z" fill="#e0e0e0"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><ellipse cx="3" cy="1039.4" fill="#6e6e6e"/><path d="m7 1-.56445 2.2578a5 5 0 0 0 -.68945.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -.28516.68555l-2.2539.5625v2h5.2715a2 2 0 0 1 -.27148-1 2 2 0 0 1 2-2 2 2 0 0 1 2 2 2 2 0 0 1 -.26953 1h5.2695v-2l-2.2578-.56445a5 5 0 0 0 -.2793-.6875l1.1934-1.9902-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -.68555-.28516l-.5625-2.2539h-2zm-4 9v6h2a3 3 0 0 0 3-3v-3h-2v3a1 1 0 0 1 -1 1v-4zm8 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324-1 2 2 0 0 0 0-2 2 2 0 0 0 -1.7324-1h2v-2z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg>
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index b1d8c05d87..01c674d086 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -30,8 +30,8 @@
#include "visual_script_editor.h"
+#include "core/class_db.h"
#include "core/input/input.h"
-#include "core/object.h"
#include "core/os/keyboard.h"
#include "core/script_language.h"
#include "core/variant.h"
@@ -4783,8 +4783,8 @@ VisualScriptEditor::VisualScriptEditor() {
graph->set_v_size_flags(Control::SIZE_EXPAND_FILL);
graph->set_anchors_and_margins_preset(Control::PRESET_WIDE);
graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected));
- graph->connect("_begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move));
- graph->connect("_end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move));
+ graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move));
+ graph->connect("end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move));
graph->connect("delete_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_delete));
graph->connect("duplicate_nodes_request", callable_mp(this, &VisualScriptEditor::_on_nodes_duplicate));
graph->connect("gui_input", callable_mp(this, &VisualScriptEditor::_graph_gui_input));
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index f13377f3c8..68de686272 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -2088,6 +2088,7 @@ void VisualScriptPropertyGet::_bind_methods() {
BIND_ENUM_CONSTANT(CALL_MODE_SELF);
BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH);
BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE);
+ BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE);
}
class VisualScriptNodeInstancePropertyGet : public VisualScriptNodeInstance {
diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
index c80b903e39..e21dee8eff 100644
--- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
+++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml
@@ -40,7 +40,6 @@
<argument index="0" name="label" type="String">
</argument>
<argument index="1" name="options" type="Dictionary" default="{
-
}">
</argument>
<description>
@@ -82,7 +81,6 @@
<return type="int" enum="Error">
</return>
<argument index="0" name="configuration" type="Dictionary" default="{
-
}">
</argument>
<description>