summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml2
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsServer.xml2
-rw-r--r--modules/bullet/shape_bullet.cpp9
-rw-r--r--modules/csg/csg.cpp6
-rw-r--r--modules/csg/csg_gizmos.cpp4
-rw-r--r--modules/csg/csg_gizmos.h1
-rw-r--r--modules/csg/csg_shape.cpp8
-rw-r--r--modules/csg/doc_classes/CSGBox.xml2
-rw-r--r--modules/csg/doc_classes/CSGCombiner.xml2
-rw-r--r--modules/csg/doc_classes/CSGCylinder.xml2
-rw-r--r--modules/csg/doc_classes/CSGMesh.xml2
-rw-r--r--modules/csg/doc_classes/CSGPolygon.xml2
-rw-r--r--modules/csg/doc_classes/CSGPrimitive.xml2
-rw-r--r--modules/csg/doc_classes/CSGShape.xml2
-rw-r--r--modules/csg/doc_classes/CSGSphere.xml2
-rw-r--r--modules/csg/doc_classes/CSGTorus.xml2
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml2
-rw-r--r--modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml2
-rw-r--r--modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/NativeScript.xml2
-rw-r--r--modules/gdnative/doc_classes/PacketPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/PluginScript.xml2
-rw-r--r--modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/StreamPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/VideoStreamGDNative.xml2
-rw-r--r--modules/gdnative/gdnative.cpp1
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp4
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp65
-rw-r--r--modules/gdnative/nativescript/nativescript.h1
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp22
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptFunctionState.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml2
-rw-r--r--modules/gdscript/gdscript.cpp141
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp195
-rw-r--r--modules/gdscript/gdscript_compiler.h9
-rw-r--r--modules/gdscript/gdscript_function.cpp13
-rw-r--r--modules/gdscript/gdscript_functions.cpp57
-rw-r--r--modules/gdscript/gdscript_parser.cpp128
-rw-r--r--modules/gdscript/gdscript_parser.h6
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp10
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml2
-rw-r--r--modules/gridmap/grid_map.cpp2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp59
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h7
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml2
-rw-r--r--modules/mono/csharp_script.cpp110
-rw-r--r--modules/mono/csharp_script.h20
-rw-r--r--modules/mono/doc_classes/@C#.xml2
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs24
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj1
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/IdentifierUtils.cs199
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs5
-rw-r--r--modules/mono/editor/bindings_generator.cpp642
-rw-r--r--modules/mono/editor/bindings_generator.h33
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp8
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp25
-rw-r--r--modules/mono/editor/godotsharp_editor.h2
-rw-r--r--modules/mono/editor/script_class_parser.cpp39
-rw-r--r--modules/mono/glue/Managed/Files/DebuggingUtils.cs6
-rw-r--r--modules/mono/glue/Managed/Files/DynamicObject.cs213
-rw-r--r--modules/mono/glue/Managed/Files/GD.cs16
-rw-r--r--modules/mono/glue/Managed/Files/GodotTraceListener.cs37
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs4
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs5
-rw-r--r--modules/mono/glue/Managed/Files/Object.base.cs28
-rw-r--r--modules/mono/glue/arguments_vector.h68
-rw-r--r--modules/mono/glue/base_object_glue.cpp69
-rw-r--r--modules/mono/glue/base_object_glue.h12
-rw-r--r--modules/mono/glue/collections_glue.cpp16
-rw-r--r--modules/mono/glue/collections_glue.h16
-rw-r--r--modules/mono/glue/gd_glue.cpp12
-rw-r--r--modules/mono/glue/gd_glue.h6
-rw-r--r--modules/mono/glue/glue_header.h2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp72
-rw-r--r--modules/mono/mono_gd/gd_mono.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp20
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp2
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp8
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml4
-rw-r--r--modules/opensimplex/doc_classes/OpenSimplexNoise.xml2
-rw-r--r--modules/opensimplex/noise_texture.cpp30
-rw-r--r--modules/opensimplex/noise_texture.h5
-rw-r--r--modules/opus/SCsub13
-rw-r--r--modules/regex/doc_classes/RegEx.xml2
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml2
-rw-r--r--modules/theora/doc_classes/VideoStreamTheora.xml2
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp37
-rw-r--r--modules/upnp/doc_classes/UPNP.xml2
-rw-r--r--modules/upnp/doc_classes/UPNPDevice.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScript.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptClassConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptComment.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCondition.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstructor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptDeconstruct.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEditor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEmitSignal.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptExpression.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIterator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVar.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptMathConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptOperator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPreload.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptResourcePath.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptReturn.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneTree.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelect.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelf.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSequence.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSubCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSwitch.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptWhile.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYield.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml2
-rw-r--r--modules/visual_script/visual_script.cpp21
-rw-r--r--modules/visual_script/visual_script.h1
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp43
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp5
-rw-r--r--modules/webm/doc_classes/VideoStreamWebm.xml2
-rw-r--r--modules/webp/SCsub7
-rw-r--r--modules/websocket/SCsub117
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketPeer.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml2
-rw-r--r--modules/websocket/lws_client.cpp8
-rw-r--r--modules/websocket/packet_buffer.h2
156 files changed, 2243 insertions, 701 deletions
diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
index a4dc61d0bc..1f91349f32 100644
--- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
+++ b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.1">
+<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/doc_classes/BulletPhysicsServer.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml
index 1486936cf4..8adc659b2c 100644
--- a/modules/bullet/doc_classes/BulletPhysicsServer.xml
+++ b/modules/bullet/doc_classes/BulletPhysicsServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.1">
+<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 1aba31f03d..b590d63167 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -510,16 +510,17 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
// Compute min and max heights if not specified.
if (!d.has("min_height") && !d.has("max_height")) {
- PoolVector<real_t>::Read r = heights.read();
- int heights_size = heights.size();
+ PoolVector<real_t>::Read r = l_heights.read();
+ int heights_size = l_heights.size();
for (int i = 0; i < heights_size; ++i) {
real_t h = r[i];
- if (h < l_min_height)
+ if (h < l_min_height) {
l_min_height = h;
- else if (h > l_max_height)
+ } else if (h > l_max_height) {
l_max_height = h;
+ }
}
}
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index fb7f829cf0..0eb539b182 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -953,13 +953,15 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build
//duplicate point
int insert_at = with_outline_vertex;
- polys.write[i].points.insert(insert_at, polys[i].points[insert_at]);
+ int point = polys[i].points[insert_at];
+ polys.write[i].points.insert(insert_at, point);
insert_at++;
//insert all others, outline should be backwards (must check)
int holesize = polys[i].holes[j].size();
for (int k = 0; k <= holesize; k++) {
int idx = (from_hole_vertex + k) % holesize;
- polys.write[i].points.insert(insert_at, polys[i].holes[j][idx]);
+ int point2 = polys[i].holes[j][idx];
+ polys.write[i].points.insert(insert_at, point2);
insert_at++;
}
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index 3044887ef5..d4069b901f 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -283,6 +283,10 @@ String CSGShapeSpatialGizmoPlugin::get_name() const {
return "CSGShapes";
}
+int CSGShapeSpatialGizmoPlugin::get_priority() const {
+ return -1;
+}
+
bool CSGShapeSpatialGizmoPlugin::is_selectable_when_hidden() const {
return true;
}
diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h
index b208c39938..0915d05111 100644
--- a/modules/csg/csg_gizmos.h
+++ b/modules/csg/csg_gizmos.h
@@ -42,6 +42,7 @@ class CSGShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin {
public:
bool has_gizmo(Spatial *p_spatial);
String get_name() const;
+ int get_priority() const;
bool is_selectable_when_hidden() const;
void redraw(EditorSpatialGizmo *p_gizmo);
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index f274fff3f3..775ec67ba6 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -806,8 +806,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
} else {
int as = vertices.size();
@@ -849,8 +849,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
}
}
diff --git a/modules/csg/doc_classes/CSGBox.xml b/modules/csg/doc_classes/CSGBox.xml
index 5ec7b5089d..1684850f0a 100644
--- a/modules/csg/doc_classes/CSGBox.xml
+++ b/modules/csg/doc_classes/CSGBox.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGBox" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGBox" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Box shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGCombiner.xml b/modules/csg/doc_classes/CSGCombiner.xml
index 69c5df5840..819a4a3a22 100644
--- a/modules/csg/doc_classes/CSGCombiner.xml
+++ b/modules/csg/doc_classes/CSGCombiner.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGCombiner" inherits="CSGShape" category="Core" version="3.1">
+<class name="CSGCombiner" inherits="CSGShape" category="Core" version="3.2">
<brief_description>
A CSG node that allows you to combine other CSG modifiers.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder.xml
index 92b170ed1f..50a88d6773 100644
--- a/modules/csg/doc_classes/CSGCylinder.xml
+++ b/modules/csg/doc_classes/CSGCylinder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGCylinder" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGCylinder" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Cylinder shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml
index 58e2bc1c4b..fc9815d7c0 100644
--- a/modules/csg/doc_classes/CSGMesh.xml
+++ b/modules/csg/doc_classes/CSGMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGMesh" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGMesh" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Mesh shape that uses a mesh resource.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon.xml
index a33e5557cb..ae75f7e01b 100644
--- a/modules/csg/doc_classes/CSGPolygon.xml
+++ b/modules/csg/doc_classes/CSGPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGPolygon" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGPolygon" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
Extrudes a 2D polygon shape to create a 3D mesh.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGPrimitive.xml b/modules/csg/doc_classes/CSGPrimitive.xml
index 2591bab7e3..502a8230e4 100644
--- a/modules/csg/doc_classes/CSGPrimitive.xml
+++ b/modules/csg/doc_classes/CSGPrimitive.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGPrimitive" inherits="CSGShape" category="Core" version="3.1">
+<class name="CSGPrimitive" inherits="CSGShape" category="Core" version="3.2">
<brief_description>
Base class for CSG primitives.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index d304d0179f..ccfc5a04c0 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.1">
+<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.2">
<brief_description>
The CSG base class.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere.xml
index a0069879cb..088c9f14eb 100644
--- a/modules/csg/doc_classes/CSGSphere.xml
+++ b/modules/csg/doc_classes/CSGSphere.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGSphere" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGSphere" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Sphere shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus.xml
index 187d71a2fa..946637bd2c 100644
--- a/modules/csg/doc_classes/CSGTorus.xml
+++ b/modules/csg/doc_classes/CSGTorus.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGTorus" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGTorus" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Torus shape.
</brief_description>
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index c9a7d96ae7..c1bec533dd 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
PacketPeer implementation using the ENet library.
</brief_description>
diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
index be86ff0541..afb014d608 100644
--- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
+++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.1">
+<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.2">
<brief_description>
GDNative wrapper for an ARVR interface
</brief_description>
diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml
index ca0457623f..e5a59aad07 100644
--- a/modules/gdnative/doc_classes/GDNative.xml
+++ b/modules/gdnative/doc_classes/GDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNative" inherits="Reference" category="Core" version="3.1">
+<class name="GDNative" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
index 754a6d2514..ba5278d440 100644
--- a/modules/gdnative/doc_classes/GDNativeLibrary.xml
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.1">
+<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
index 4433179726..ba481a6d6e 100644
--- a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerPeerGDNative" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="MultiplayerPeerGDNative" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml
index 37d5b79e7a..c50f9eee22 100644
--- a/modules/gdnative/doc_classes/NativeScript.xml
+++ b/modules/gdnative/doc_classes/NativeScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeScript" inherits="Script" category="Core" version="3.1">
+<class name="NativeScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/PacketPeerGDNative.xml b/modules/gdnative/doc_classes/PacketPeerGDNative.xml
index 0ae54bc9c7..f4d7d22f5b 100644
--- a/modules/gdnative/doc_classes/PacketPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/PacketPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeerGDNative" inherits="PacketPeer" category="Core" version="3.1">
+<class name="PacketPeerGDNative" inherits="PacketPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml
index 1876d06c20..8510708124 100644
--- a/modules/gdnative/doc_classes/PluginScript.xml
+++ b/modules/gdnative/doc_classes/PluginScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PluginScript" inherits="Script" category="Core" version="3.1">
+<class name="PluginScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml b/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
index 61a7f60499..8e7f4698ff 100644
--- a/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
+++ b/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceFormatLoaderVideoStreamGDNative" inherits="ResourceFormatLoader" category="Core" version="3.1">
+<class name="ResourceFormatLoaderVideoStreamGDNative" inherits="ResourceFormatLoader" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/StreamPeerGDNative.xml b/modules/gdnative/doc_classes/StreamPeerGDNative.xml
index d86cd2c25a..eddebf4889 100644
--- a/modules/gdnative/doc_classes/StreamPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/StreamPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeerGDNative" inherits="StreamPeer" category="Core" version="3.1">
+<class name="StreamPeerGDNative" inherits="StreamPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/VideoStreamGDNative.xml b/modules/gdnative/doc_classes/VideoStreamGDNative.xml
index 20575c768b..d5c5ed7ccf 100644
--- a/modules/gdnative/doc_classes/VideoStreamGDNative.xml
+++ b/modules/gdnative/doc_classes/VideoStreamGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 34325db9fd..e8278825bc 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -414,6 +414,7 @@ bool GDNative::terminate() {
if (error || !library_terminate) {
OS::get_singleton()->close_dynamic_library(native_handle);
native_handle = NULL;
+ initialized = false;
return true;
}
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index b99c5d31ab..7eb4294732 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -279,7 +279,7 @@ List<ClassAPI> generate_c_api_classes() {
MethodInfo &method_info = m->get();
//method name
- method_api.method_name = m->get().name;
+ method_api.method_name = method_info.name;
//method return type
if (method_api.method_name.find(":") != -1) {
method_api.return_type = method_api.method_name.get_slice(":", 1);
@@ -321,6 +321,8 @@ List<ClassAPI> generate_c_api_classes() {
arg_type = arg_info.hint_string;
} else if (arg_info.type == Variant::NIL) {
arg_type = "Variant";
+ } else if (arg_info.type == Variant::OBJECT) {
+ arg_type = arg_info.class_name;
} else {
arg_type = Variant::get_type_name(arg_info.type);
}
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index c2b772df85..5cf144d4fe 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -160,8 +160,10 @@ bool NativeScript::can_instance() const {
NativeScriptDesc *script_data = get_script_desc();
#ifdef TOOLS_ENABLED
-
- return script_data || (!is_tool() && !ScriptServer::is_scripting_enabled());
+ // Only valid if this is either a tool script or a "regular" script.
+ // (so an environment whre scripting is disabled (and not the editor) would not
+ // create objects).
+ return script_data && (is_tool() || ScriptServer::is_scripting_enabled());
#else
return script_data;
#endif
@@ -199,25 +201,6 @@ ScriptInstance *NativeScript::instance_create(Object *p_this) {
return NULL;
}
-#ifdef TOOLS_ENABLED
- if (!ScriptServer::is_scripting_enabled() && !is_tool()) {
- // placeholder for nodes. For tools we want the rool thing.
-
- PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(NSL, Ref<Script>(this), p_this));
- placeholders.insert(sins);
-
- if (script_data->create_func.create_func) {
- script_data->create_func.create_func(
- (godot_object *)p_this,
- script_data->create_func.method_data);
- }
-
- _update_placeholder(sins);
-
- return sins;
- }
-#endif
-
NativeScriptInstance *nsi = memnew(NativeScriptInstance);
nsi->owner = p_this;
@@ -246,6 +229,19 @@ ScriptInstance *NativeScript::instance_create(Object *p_this) {
return nsi;
}
+PlaceHolderScriptInstance *NativeScript::placeholder_instance_create(Object *p_this) {
+#ifdef TOOLS_ENABLED
+ PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(NSL, Ref<Script>(this), p_this));
+ placeholders.insert(sins);
+
+ _update_placeholder(sins);
+
+ return sins;
+#else
+ return NULL;
+#endif
+}
+
bool NativeScript::instance_has(const Object *p_this) const {
return instance_owners.has((Object *)p_this);
}
@@ -1036,8 +1032,16 @@ NativeScriptLanguage::~NativeScriptLanguage() {
for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
- if (L->get().is_valid())
- L->get()->terminate();
+ Ref<GDNative> lib = L->get();
+ // only shut down valid libs, duh!
+ if (lib.is_valid()) {
+
+ // If it's a singleton-library then the gdnative module
+ // manages the destruction at engine shutdown, not NativeScript.
+ if (!lib->get_library()->is_singleton()) {
+ lib->terminate();
+ }
+ }
}
NSL->library_classes.clear();
@@ -1641,10 +1645,19 @@ void NativeReloadNode::_notification(int p_what) {
continue;
}
+ // Don't unload what should not be reloaded!
if (!gdn->get_library()->is_reloadable()) {
continue;
}
+ // singleton libraries might have alive pointers living inside the
+ // editor. Also reloading a singleton library would mean that
+ // the singleton entry will not be called again, as this only
+ // happens at engine startup.
+ if (gdn->get_library()->is_singleton()) {
+ continue;
+ }
+
gdn->terminate();
}
@@ -1672,6 +1685,12 @@ void NativeReloadNode::_notification(int p_what) {
continue;
}
+ // since singleton libraries are not unloaded there is no point
+ // in loading them again.
+ if (gdn->get_library()->is_singleton()) {
+ continue;
+ }
+
if (!gdn->initialize()) {
libs_to_remove.insert(L->key());
continue;
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index 8dd5ba3b9c..a6865c6243 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -149,6 +149,7 @@ public:
virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so
virtual ScriptInstance *instance_create(Object *p_this);
+ virtual PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this);
virtual bool instance_has(const Object *p_this) const;
virtual bool has_source_code() const;
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index d1794b6c36..8fcebe7855 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -117,18 +117,20 @@ bool VideoStreamPlaybackGDNative::open_file(const String &p_file) {
file = FileAccess::open(p_file, FileAccess::READ);
bool file_opened = interface->open_file(data_struct, file);
- num_channels = interface->get_channels(data_struct);
- mix_rate = interface->get_mix_rate(data_struct);
+ if (file_opened) {
+ num_channels = interface->get_channels(data_struct);
+ mix_rate = interface->get_mix_rate(data_struct);
- godot_vector2 vec = interface->get_texture_size(data_struct);
- texture_size = *(Vector2 *)&vec;
+ godot_vector2 vec = interface->get_texture_size(data_struct);
+ texture_size = *(Vector2 *)&vec;
- pcm = (float *)memalloc(num_channels * AUX_BUFFER_SIZE * sizeof(float));
- memset(pcm, 0, num_channels * AUX_BUFFER_SIZE * sizeof(float));
- pcm_write_idx = -1;
- samples_decoded = 0;
+ pcm = (float *)memalloc(num_channels * AUX_BUFFER_SIZE * sizeof(float));
+ memset(pcm, 0, num_channels * AUX_BUFFER_SIZE * sizeof(float));
+ pcm_write_idx = -1;
+ samples_decoded = 0;
- texture->create((int)texture_size.width, (int)texture_size.height, Image::FORMAT_RGBA8, Texture::FLAG_FILTER | Texture::FLAG_VIDEO_SURFACE);
+ texture->create((int)texture_size.width, (int)texture_size.height, Image::FORMAT_RGBA8, Texture::FLAG_FILTER | Texture::FLAG_VIDEO_SURFACE);
+ }
return file_opened;
}
@@ -355,9 +357,9 @@ RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const St
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
- memdelete(f);
return RES();
}
+ memdelete(f);
VideoStreamGDNative *stream = memnew(VideoStreamGDNative);
stream->set_file(p_path);
Ref<VideoStreamGDNative> ogv_stream = Ref<VideoStreamGDNative>(stream);
diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index 4cefdbd7cb..46796c68eb 100644
--- a/modules/gdscript/doc_classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScript" inherits="Script" category="Core" version="3.1">
+<class name="GDScript" inherits="Script" category="Core" version="3.2">
<brief_description>
A script implemented in the GDScript programming language.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
index c205cedef5..f38f39b612 100644
--- a/modules/gdscript/doc_classes/GDScriptFunctionState.xml
+++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.1">
+<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.2">
<brief_description>
State of a function call after yielding.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
index 90935b5c22..e86b69c31c 100644
--- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml
+++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1">
+<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index e07911fa44..4385cf12ad 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1835,73 +1835,92 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
PoolVector<uint8_t> sourcef;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
return String();
}
- int len = f->get_len();
- sourcef.resize(len + 1);
- PoolVector<uint8_t>::Write w = sourcef.write();
- int r = f->get_buffer(w.ptr(), len);
- f->close();
- memdelete(f);
- ERR_FAIL_COND_V(r != len, String());
- w[len] = 0;
-
- String s;
- if (s.parse_utf8((const char *)w.ptr())) {
- return String();
- }
+ String source = f->get_as_utf8_string();
GDScriptParser parser;
-
- parser.parse(s, p_path.get_base_dir(), true, p_path);
+ parser.parse(source, p_path.get_base_dir(), true, p_path, false, NULL, true);
if (parser.get_parse_tree() && parser.get_parse_tree()->type == GDScriptParser::Node::TYPE_CLASS) {
const GDScriptParser::ClassNode *c = static_cast<const GDScriptParser::ClassNode *>(parser.get_parse_tree());
+ if (r_icon_path) {
+ if (c->icon_path.empty() || c->icon_path.is_abs_path())
+ *r_icon_path = c->icon_path;
+ else if (c->icon_path.is_rel_path())
+ *r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path();
+ }
if (r_base_type) {
- GDScriptParser::DataType base_type;
- if (c->base_type.has_type) {
- base_type = c->base_type;
- while (base_type.has_type && base_type.kind != GDScriptParser::DataType::NATIVE) {
- switch (base_type.kind) {
- case GDScriptParser::DataType::CLASS: {
- base_type = base_type.class_type->base_type;
- } break;
- case GDScriptParser::DataType::GDSCRIPT: {
- Ref<GDScript> gds = base_type.script_type;
- if (gds.is_valid()) {
- base_type.kind = GDScriptParser::DataType::NATIVE;
- base_type.native_type = gds->get_instance_base_type();
- } else {
- base_type = GDScriptParser::DataType();
+
+ const GDScriptParser::ClassNode *subclass = c;
+ String path = p_path;
+ GDScriptParser subparser;
+ while (subclass) {
+ if (subclass->extends_used) {
+ if (subclass->extends_file) {
+ if (subclass->extends_class.size() == 0) {
+ get_global_class_name(subclass->extends_file, r_base_type);
+ subclass = NULL;
+ break;
+ } else {
+ Vector<StringName> extend_classes = subclass->extends_class;
+
+ FileAccessRef subfile = FileAccess::open(subclass->extends_file, FileAccess::READ);
+ if (!subfile) {
+ break;
+ }
+ String subsource = subfile->get_as_utf8_string();
+
+ if (subsource.empty()) {
+ break;
+ }
+ String subpath = subclass->extends_file;
+ if (subpath.is_rel_path()) {
+ subpath = path.get_base_dir().plus_file(subpath).simplify_path();
+ }
+
+ if (OK != subparser.parse(subsource, subpath.get_base_dir(), true, subpath, false, NULL, true)) {
+ break;
+ }
+ path = subpath;
+ if (!subparser.get_parse_tree() || subparser.get_parse_tree()->type != GDScriptParser::Node::TYPE_CLASS) {
+ break;
}
- } break;
- default: {
- base_type = GDScriptParser::DataType();
- } break;
+ subclass = static_cast<const GDScriptParser::ClassNode *>(subparser.get_parse_tree());
+
+ while (extend_classes.size() > 0) {
+ bool found = false;
+ for (int i = 0; i < subclass->subclasses.size(); i++) {
+ const GDScriptParser::ClassNode *inner_class = subclass->subclasses[i];
+ if (inner_class->name == extend_classes[0]) {
+ extend_classes.remove(0);
+ found = true;
+ subclass = inner_class;
+ break;
+ }
+ }
+ if (!found) {
+ subclass = NULL;
+ break;
+ }
+ }
+ }
+ } else if (subclass->extends_class.size() == 1) {
+ *r_base_type = subclass->extends_class[0];
+ subclass = NULL;
+ } else {
+ break;
}
- }
- }
- if (base_type.has_type) {
- *r_base_type = base_type.native_type;
- } else {
- // Fallback
- if (c->extends_used && c->extends_class.size() == 1) {
- *r_base_type = c->extends_class[0];
- } else if (!c->extends_used) {
+ } else {
*r_base_type = "Reference";
+ subclass = NULL;
}
}
}
- if (r_icon_path) {
- if (c->icon_path.empty() || c->icon_path.is_abs_path())
- *r_icon_path = c->icon_path;
- else if (c->icon_path.is_rel_path())
- *r_icon_path = p_path.get_base_dir().plus_file(c->icon_path).simplify_path();
- }
return c->name;
}
@@ -1946,7 +1965,7 @@ String GDScriptWarning::get_message() const {
return "Assignment operation, but the function '" + symbols[0] + "()' returns void.";
} break;
case NARROWING_CONVERSION: {
- return "Narrowing coversion (float is converted to int and lose precision).";
+ return "Narrowing conversion (float is converted to int and loses precision).";
} break;
case FUNCTION_MAY_YIELD: {
CHECK_SYMBOLS(1);
@@ -2183,6 +2202,26 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con
return "";
}
+void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
+
+ FileAccessRef file = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND(!file);
+
+ String source = file->get_as_utf8_string();
+ if (source.empty()) {
+ return;
+ }
+
+ GDScriptParser parser;
+ if (OK != parser.parse(source, p_path.get_base_dir(), true, p_path, false, NULL, true)) {
+ return;
+ }
+
+ for (const List<String>::Element *E = parser.get_dependencies().front(); E; E = E->next()) {
+ p_dependencies->push_back(E->get());
+ }
+}
+
Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
Ref<GDScript> sqscr = p_resource;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 86c00c0b59..ded873c7d3 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -511,6 +511,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
};
class ResourceFormatSaverGDScript : public ResourceFormatSaver {
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index b2b7b1c260..ae67521749 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -139,17 +139,32 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.native_type = result.script_type->get_instance_base_type();
} break;
case GDScriptParser::DataType::CLASS: {
- result.kind = GDScriptDataType::GDSCRIPT;
- if (!p_datatype.class_type->owner) {
- result.script_type = Ref<GDScript>(main_script);
- } else {
- result.script_type = class_map[p_datatype.class_type->name];
+ // Locate class by constructing the path to it and following that path
+ GDScriptParser::ClassNode *class_type = p_datatype.class_type;
+ List<StringName> names;
+ while (class_type->owner) {
+ names.push_back(class_type->name);
+ class_type = class_type->owner;
}
- result.native_type = result.script_type->get_instance_base_type();
+
+ Ref<GDScript> script = Ref<GDScript>(main_script);
+ while (names.back()) {
+ if (!script->subclasses.has(names.back()->get())) {
+ ERR_PRINT("Parser bug: Cannot locate datatype class.");
+ result.has_type = false;
+ return GDScriptDataType();
+ }
+ script = script->subclasses[names.back()->get()];
+ names.pop_back();
+ }
+
+ result.kind = GDScriptDataType::GDSCRIPT;
+ result.script_type = script;
+ result.native_type = script->get_instance_base_type();
} break;
default: {
ERR_PRINT("Parser bug: converting unresolved type.");
- result.has_type = false;
+ return GDScriptDataType();
}
}
@@ -460,12 +475,14 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.alloc_stack(slevel);
}
- switch (cn->cast_type.kind) {
- case GDScriptParser::DataType::BUILTIN: {
+ GDScriptDataType cast_type = _gdtype_from_datatype(cn->cast_type);
+
+ switch (cast_type.kind) {
+ case GDScriptDataType::BUILTIN: {
codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
codegen.opcodes.push_back(cn->cast_type.builtin_type);
} break;
- case GDScriptParser::DataType::NATIVE: {
+ case GDScriptDataType::NATIVE: {
int class_idx;
if (GDScriptLanguage::get_singleton()->get_global_map().has(cn->cast_type.native_type)) {
@@ -478,32 +495,8 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_NATIVE); // perform operator
codegen.opcodes.push_back(class_idx); // variable type
} break;
- case GDScriptParser::DataType::CLASS: {
-
- Variant script;
- int idx = -1;
- if (!cn->cast_type.class_type->owner) {
- script = codegen.script;
- } else {
- StringName name = cn->cast_type.class_type->name;
- if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) {
- idx = codegen.get_name_map_pos(name);
- idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS;
- } else {
- script = class_map[name];
- }
- }
-
- if (idx < 0) {
- idx = codegen.get_constant_pos(script);
- idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access)
- }
-
- codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_SCRIPT); // perform operator
- codegen.opcodes.push_back(idx); // variable type
- } break;
- case GDScriptParser::DataType::SCRIPT:
- case GDScriptParser::DataType::GDSCRIPT: {
+ case GDScriptDataType::SCRIPT:
+ case GDScriptDataType::GDSCRIPT: {
Variant script = cn->cast_type.script_type;
int idx = codegen.get_constant_pos(script);
@@ -1149,18 +1142,18 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
if (src_address_b < 0)
return -1;
- GDScriptParser::DataType assign_type = on->arguments[0]->get_datatype();
+ GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype());
if (assign_type.has_type && !on->arguments[1]->get_datatype().has_type) {
// Typed assignment
switch (assign_type.kind) {
- case GDScriptParser::DataType::BUILTIN: {
+ case GDScriptDataType::BUILTIN: {
codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); // perform operator
codegen.opcodes.push_back(assign_type.builtin_type); // variable type
codegen.opcodes.push_back(dst_address_a); // argument 1
codegen.opcodes.push_back(src_address_b); // argument 2
} break;
- case GDScriptParser::DataType::NATIVE: {
+ case GDScriptDataType::NATIVE: {
int class_idx;
if (GDScriptLanguage::get_singleton()->get_global_map().has(assign_type.native_type)) {
@@ -1175,34 +1168,8 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(dst_address_a); // argument 1
codegen.opcodes.push_back(src_address_b); // argument 2
} break;
- case GDScriptParser::DataType::CLASS: {
-
- Variant script;
- int idx = -1;
- if (!assign_type.class_type->owner) {
- script = codegen.script;
- } else {
- StringName name = assign_type.class_type->name;
- if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) {
- idx = codegen.get_name_map_pos(name);
- idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS;
- } else {
- script = class_map[name];
- }
- }
-
- if (idx < 0) {
- idx = codegen.get_constant_pos(script);
- idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access)
- }
-
- codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT); // perform operator
- codegen.opcodes.push_back(idx); // variable type
- codegen.opcodes.push_back(dst_address_a); // argument 1
- codegen.opcodes.push_back(src_address_b); // argument 2
- } break;
- case GDScriptParser::DataType::SCRIPT:
- case GDScriptParser::DataType::GDSCRIPT: {
+ case GDScriptDataType::SCRIPT:
+ case GDScriptDataType::GDSCRIPT: {
Variant script = assign_type.script_type;
int idx = codegen.get_constant_pos(script);
@@ -1396,11 +1363,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
case GDScriptParser::ControlFlowNode::CF_IF: {
-#ifdef DEBUG_ENABLED
- codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE);
- codegen.opcodes.push_back(cf->line);
- codegen.current_line = cf->line;
-#endif
int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false);
if (ret2 < 0)
return ERR_PARSE_ERROR;
@@ -1850,22 +1812,21 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
return OK;
}
-Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+
+ parsing_classes.insert(p_script);
if (p_class->owner && p_class->owner->owner) {
// Owner is not root
- StringName owner_name = p_class->owner->name;
- if (!parsed_classes.has(owner_name)) {
- if (parsing_classes.has(owner_name)) {
- _set_error("Cyclic class reference for '" + String(owner_name) + "'.", p_class);
+ if (!parsed_classes.has(p_script->_owner)) {
+ if (parsing_classes.has(p_script->_owner)) {
+ _set_error("Cyclic class reference for '" + String(p_class->name) + "'.", p_class);
return ERR_PARSE_ERROR;
}
- parsing_classes.insert(owner_name);
- Error err = _parse_class_level(class_map[owner_name].ptr(), class_map[owner_name]->_owner, p_class->owner, p_keep_state);
+ Error err = _parse_class_level(p_script->_owner, p_class->owner, p_keep_state);
if (err) {
return err;
}
- parsing_classes.erase(owner_name);
}
}
@@ -1883,47 +1844,26 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
p_script->_signals.clear();
p_script->initializer = NULL;
- p_script->subclasses.clear();
- p_script->_owner = p_owner;
p_script->tool = p_class->tool;
p_script->name = p_class->name;
Ref<GDScriptNativeClass> native;
+ GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type);
// Inheritance
- switch (p_class->base_type.kind) {
- case GDScriptParser::DataType::CLASS: {
- StringName base_name = p_class->base_type.class_type->name;
- // Make sure dependency is parsed first
- if (!parsed_classes.has(base_name)) {
- if (parsing_classes.has(base_name)) {
- _set_error("Cyclic class reference for '" + String(base_name) + "'.", p_class);
- return ERR_PARSE_ERROR;
- }
- parsing_classes.insert(base_name);
- Error err = _parse_class_level(class_map[base_name].ptr(), class_map[base_name]->_owner, p_class->base_type.class_type, p_keep_state);
- if (err) {
- return err;
- }
- parsing_classes.erase(base_name);
- }
- Ref<GDScript> base = class_map[base_name];
- p_script->base = base;
- p_script->_base = p_script->base.ptr();
- p_script->member_indices = base->member_indices;
- } break;
- case GDScriptParser::DataType::GDSCRIPT: {
- Ref<GDScript> base = p_class->base_type.script_type;
- p_script->base = base;
- p_script->_base = p_script->base.ptr();
- p_script->member_indices = base->member_indices;
- } break;
- case GDScriptParser::DataType::NATIVE: {
- int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_class->base_type.native_type];
+ switch (base_type.kind) {
+ case GDScriptDataType::NATIVE: {
+ int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
ERR_FAIL_COND_V(native.is_null(), ERR_BUG);
p_script->native = native;
} break;
+ case GDScriptDataType::GDSCRIPT: {
+ Ref<GDScript> base = base_type.script_type;
+ p_script->base = base;
+ p_script->_base = base.ptr();
+ p_script->member_indices = base->member_indices;
+ } break;
default: {
_set_error("Parser bug: invalid inheritance.", p_class);
return ERR_BUG;
@@ -2017,24 +1957,19 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
p_script->_signals[name] = p_class->_signals[i].arguments;
}
- if (p_class->owner) {
- parsed_classes.insert(p_class->name);
- if (parsing_classes.has(p_class->name)) {
- parsing_classes.erase(p_class->name);
- }
- }
+ parsed_classes.insert(p_script);
+ parsing_classes.erase(p_script);
//parse sub-classes
for (int i = 0; i < p_class->subclasses.size(); i++) {
StringName name = p_class->subclasses[i]->name;
- Ref<GDScript> subclass = class_map[name];
+ GDScript *subclass = p_script->subclasses[name].ptr();
// Subclass might still be parsing, just skip it
- if (!parsed_classes.has(name) && !parsing_classes.has(name)) {
- parsing_classes.insert(name);
- Error err = _parse_class_level(subclass.ptr(), p_script, p_class->subclasses[i], p_keep_state);
+ if (!parsed_classes.has(subclass) && !parsing_classes.has(subclass)) {
+ Error err = _parse_class_level(subclass, p_class->subclasses[i], p_keep_state);
if (err)
return err;
}
@@ -2045,7 +1980,6 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
#endif
p_script->constants.insert(name, subclass); //once parsed, goes to the list of constants
- p_script->subclasses.insert(name, subclass);
}
return OK;
@@ -2144,9 +2078,9 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
for (int i = 0; i < p_class->subclasses.size(); i++) {
StringName name = p_class->subclasses[i]->name;
- Ref<GDScript> subclass = class_map[name];
+ GDScript *subclass = p_script->subclasses[name].ptr();
- Error err = _parse_class_blocks(subclass.ptr(), p_class->subclasses[i], p_keep_state);
+ Error err = _parse_class_blocks(subclass, p_class->subclasses[i], p_keep_state);
if (err) {
return err;
}
@@ -2156,7 +2090,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
return OK;
}
-void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
Map<StringName, Ref<GDScript> > old_subclasses;
@@ -2164,6 +2098,8 @@ void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptPar
old_subclasses = p_script->subclasses;
}
+ p_script->subclasses.clear();
+
for (int i = 0; i < p_class->subclasses.size(); i++) {
StringName name = p_class->subclasses[i]->name;
@@ -2175,10 +2111,10 @@ void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptPar
subclass.instance();
}
- subclass->_owner = const_cast<GDScript *>(p_script);
- class_map.insert(name, subclass);
+ subclass->_owner = p_script;
+ p_script->subclasses.insert(name, subclass);
- _make_scripts(subclass.ptr(), p_class->subclasses[i], p_keep_state);
+ _make_scripts(subclass.ptr(), p_class->subclasses[i], false);
}
}
@@ -2197,7 +2133,8 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
// Create scripts for subclasses beforehand so they can be referenced
_make_scripts(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
- Error err = _parse_class_level(p_script, NULL, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
+ p_script->_owner = NULL;
+ Error err = _parse_class_level(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
if (err)
return err;
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 8440807a56..2cf630ba72 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -38,9 +38,8 @@
class GDScriptCompiler {
const GDScriptParser *parser;
- Map<StringName, Ref<GDScript> > class_map;
- Set<StringName> parsed_classes;
- Set<StringName> parsing_classes;
+ Set<GDScript *> parsed_classes;
+ Set<GDScript *> parsing_classes;
GDScript *main_script;
struct CodeGen {
@@ -149,9 +148,9 @@ class GDScriptCompiler {
int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1);
Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
- Error _parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ void _make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line;
int err_column;
StringName source;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 98871ddec3..cff9ba55b8 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -329,10 +329,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (!argument_types[i].is_type(*p_args[i], true)) {
- r_err.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_err.argument = i;
- r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
- return Variant();
+ if (argument_types[i].is_type(Variant(), true)) {
+ memnew_placement(&stack[i], Variant);
+ continue;
+ } else {
+ r_err.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_err.argument = i;
+ r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
+ return Variant();
+ }
}
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
Variant arg = Variant::construct(argument_types[i].builtin_type, &p_args[i], 1, r_err);
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 44d44462ca..46c9efd54f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -768,11 +768,30 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
(void)VariantParser::parse(&ss, r_ret, errs, line);
} break;
case VAR_TO_BYTES: {
- VALIDATE_ARG_COUNT(1);
+ bool full_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ full_objects = *p_args[1];
+ }
PoolByteArray barr;
int len;
- Error err = encode_variant(*p_args[0], NULL, len);
+ Error err = encode_variant(*p_args[0], NULL, len, full_objects);
if (err) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
@@ -784,15 +803,35 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(*p_args[0], w.ptr(), len);
+ encode_variant(*p_args[0], w.ptr(), len, full_objects);
}
r_ret = barr;
} break;
case BYTES_TO_VAR: {
- VALIDATE_ARG_COUNT(1);
+ bool allow_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ allow_objects = *p_args[1];
+ }
+
if (p_args[0]->get_type() != Variant::POOL_BYTE_ARRAY) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
+ r_error.argument = 1;
r_error.expected = Variant::POOL_BYTE_ARRAY;
r_ret = Variant();
return;
@@ -802,7 +841,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Variant ret;
{
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
if (err != OK) {
r_ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@@ -1805,13 +1844,15 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case VAR_TO_BYTES: {
- MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
+ MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "full_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::POOL_BYTE_ARRAY;
return mi;
} break;
case BYTES_TO_VAR: {
- MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"));
+ MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::NIL;
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
return mi;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 5ebf68177d..e75b8a14a3 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -473,29 +473,31 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
Ref<Resource> res;
- if (!validating) {
+ dependencies.push_back(path);
+ if (!dependencies_only) {
+ if (!validating) {
- //this can be too slow for just validating code
- if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) {
- res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
- } else if (!for_completion || FileAccess::exists(path)) {
- res = ResourceLoader::load(path);
- }
- } else {
+ //this can be too slow for just validating code
+ if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) {
+ res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
+ } else if (!for_completion || FileAccess::exists(path)) {
+ res = ResourceLoader::load(path);
+ }
+ } else {
- if (!FileAccess::exists(path)) {
+ if (!FileAccess::exists(path)) {
+ _set_error("Can't preload resource at path: " + path);
+ return NULL;
+ } else if (ScriptCodeCompletionCache::get_singleton()) {
+ res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
+ }
+ }
+ if (!res.is_valid()) {
_set_error("Can't preload resource at path: " + path);
return NULL;
- } else if (ScriptCodeCompletionCache::get_singleton()) {
- res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
}
}
- if (!res.is_valid()) {
- _set_error("Can't preload resource at path: " + path);
- return NULL;
- }
-
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' after 'preload' path");
return NULL;
@@ -775,7 +777,8 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
_add_warning(GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, -1, identifier.operator String());
}
- } // fallthrough
+ FALLTHROUGH;
+ }
case GDScriptTokenizer::TK_OP_ASSIGN: {
lv->assignments += 1;
lv->usages--; // Assignment is not really usage
@@ -812,19 +815,31 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
bfn = true;
}
- // Check parents for the constant
- if (!bfn && cln->extends_file != StringName()) {
- Ref<GDScript> parent = ResourceLoader::load(cln->extends_file);
- if (parent.is_valid() && parent->is_valid()) {
- Map<StringName, Variant> parent_constants;
- parent->get_constants(&parent_constants);
- if (parent_constants.has(identifier)) {
+ if (!dependencies_only) {
+ if (!bfn && ScriptServer::is_global_class(identifier)) {
+ Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(identifier));
+ if (scr.is_valid() && scr->is_valid()) {
ConstantNode *constant = alloc_node<ConstantNode>();
- constant->value = parent_constants[identifier];
+ constant->value = scr;
expr = constant;
bfn = true;
}
}
+
+ // Check parents for the constant
+ if (!bfn && cln->extends_file != StringName()) {
+ Ref<GDScript> parent = ResourceLoader::load(cln->extends_file);
+ if (parent.is_valid() && parent->is_valid()) {
+ Map<StringName, Variant> parent_constants;
+ parent->get_constants(&parent_constants);
+ if (parent_constants.has(identifier)) {
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ constant->value = parent_constants[identifier];
+ expr = constant;
+ bfn = true;
+ }
+ }
+ }
}
}
@@ -2082,7 +2097,7 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) {
return NULL;
}
pattern->pt_type = GDScriptParser::PatternNode::PT_BIND;
- pattern->bind = tokenizer->get_token_identifier();
+ pattern->bind = tokenizer->get_token_literal();
// Check if variable name is already used
BlockNode *bl = current_block;
while (bl) {
@@ -2211,6 +2226,8 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) {
void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static) {
int indent_level = tab_level.back()->get();
+ p_block->has_return = true;
+
while (true) {
while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
@@ -2268,8 +2285,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
current_block = p_block;
- if (catch_all && branch->body->has_return) {
- p_block->has_return = true;
+ if (!branch->body->has_return) {
+ p_block->has_return = false;
}
p_branches.push_back(branch);
@@ -2727,6 +2744,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
} break;
case GDScriptTokenizer::TK_NEWLINE: {
+ int line = tokenizer->get_token_line();
+
if (!_parse_newline()) {
if (!error_set) {
p_block->end_line = tokenizer->get_token_line();
@@ -2736,7 +2755,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
NewLineNode *nl2 = alloc_node<NewLineNode>();
- nl2->line = tokenizer->get_token_line();
+ nl2->line = line;
p_block->statements.push_back(nl2);
} break;
@@ -3053,7 +3072,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
DataType iter_type;
- iter_type.is_constant = true;
if (container->type == Node::TYPE_OPERATOR) {
@@ -3378,6 +3396,13 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) {
p_class->extends_file = constant;
tokenizer->advance();
+ // Add parent script as a dependency
+ String parent = constant;
+ if (parent.is_rel_path()) {
+ parent = base_path.plus_file(parent).simplify_path();
+ }
+ dependencies.push_back(parent);
+
if (tokenizer->get_token() != GDScriptTokenizer::TK_PERIOD) {
return;
} else
@@ -3612,7 +3637,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- }; //fallthrough to function
+ FALLTHROUGH;
+ }
case GDScriptTokenizer::TK_PR_FUNCTION: {
bool _static = false;
@@ -4062,7 +4088,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
break;
}
- }; //fallthrough to use the same
+ FALLTHROUGH;
+ }
case Variant::REAL: {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
@@ -4487,6 +4514,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#ifdef DEBUG_ENABLED
_add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet");
#endif
+ FALLTHROUGH;
case GDScriptTokenizer::TK_PR_PUPPET: {
//may be fallthrough from export, ignore if so
@@ -4554,7 +4582,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
continue;
} break;
case GDScriptTokenizer::TK_PR_VAR: {
- //variale declaration and (eventual) initialization
+ // variable declaration and (eventual) initialization
ClassNode::Member member;
@@ -5266,7 +5294,8 @@ String GDScriptParser::DataType::to_string() const {
if (!gds_class.empty()) {
return gds_class;
}
- } // fallthrough
+ FALLTHROUGH;
+ }
case SCRIPT: {
if (is_meta_type) {
return script_type->get_class_name().operator String();
@@ -5434,7 +5463,7 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
String script_path = ScriptServer::get_global_class_path(id);
if (script_path == self_path) {
result.kind = DataType::CLASS;
- result.class_type = current_class;
+ result.class_type = static_cast<ClassNode *>(head);
} else {
Ref<Script> script = ResourceLoader::load(script_path);
Ref<GDScript> gds = script;
@@ -7237,6 +7266,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
DataType result;
result.has_type = true;
result.script_type = scr;
+ result.is_constant = true;
result.is_meta_type = true;
Ref<GDScript> gds = scr;
if (gds.is_valid()) {
@@ -7287,6 +7317,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
if (singleton.is_valid()) {
DataType result;
result.has_type = true;
+ result.is_constant = true;
result.script_type = singleton;
Ref<GDScript> gds = singleton;
@@ -7842,13 +7873,16 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
return;
}
- if (!lh_type.has_type && check_types) {
- if (op->arguments[0]->type == Node::TYPE_OPERATOR) {
- _mark_line_as_unsafe(op->line);
+ if (check_types) {
+ if (!lh_type.has_type) {
+ if (op->arguments[0]->type == Node::TYPE_OPERATOR) {
+ _mark_line_as_unsafe(op->line);
+ }
+ }
+ if (lh_type.is_constant) {
+ _set_error("Cannot assign a new value to a constant.", op->line);
+ return;
}
- } else if (lh_type.is_constant) {
- _set_error("Cannot assign a new value to a constant.", op->line);
- return;
}
DataType rh_type;
@@ -8017,7 +8051,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (cn->value.get_type() == Variant::STRING) {
break;
}
- } // falthrough
+ FALLTHROUGH;
+ }
default: {
_mark_line_as_safe(statement->line);
_reduce_node_type(statement); // Test for safety anyway
@@ -8149,6 +8184,10 @@ Error GDScriptParser::_parse(const String &p_base_path) {
return ERR_PARSE_ERROR;
}
+ if (dependencies_only) {
+ return OK;
+ }
+
_determine_inheritance(main_class);
if (error_set) {
@@ -8227,7 +8266,7 @@ Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const St
return ret;
}
-Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion, Set<int> *r_safe_lines) {
+Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion, Set<int> *r_safe_lines, bool p_dependencies_only) {
clear();
@@ -8237,6 +8276,7 @@ Error GDScriptParser::parse(const String &p_code, const String &p_base_path, boo
validating = p_just_validate;
for_completion = p_for_completion;
+ dependencies_only = p_dependencies_only;
#ifdef DEBUG_ENABLED
safe_lines = r_safe_lines;
#endif // DEBUG_ENABLED
@@ -8293,6 +8333,8 @@ void GDScriptParser::clear() {
parenthesis = 0;
current_export.type = Variant::NIL;
check_types = true;
+ dependencies_only = false;
+ dependencies.clear();
error = "";
#ifdef DEBUG_ENABLED
safe_lines = NULL;
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 9c1ea1c7e4..809bff8f20 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -533,6 +533,8 @@ private:
int error_line;
int error_column;
bool check_types;
+ bool dependencies_only;
+ List<String> dependencies;
#ifdef DEBUG_ENABLED
Set<int> *safe_lines;
#endif // DEBUG_ENABLED
@@ -634,7 +636,7 @@ public:
#ifdef DEBUG_ENABLED
const List<GDScriptWarning> &get_warnings() const { return warnings; }
#endif // DEBUG_ENABLED
- Error parse(const String &p_code, const String &p_base_path = "", bool p_just_validate = false, const String &p_self_path = "", bool p_for_completion = false, Set<int> *r_safe_lines = NULL);
+ Error parse(const String &p_code, const String &p_base_path = "", bool p_just_validate = false, const String &p_self_path = "", bool p_for_completion = false, Set<int> *r_safe_lines = NULL, bool p_dependencies_only = false);
Error parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path = "", const String &p_self_path = "");
bool is_tool_script() const;
@@ -653,6 +655,8 @@ public:
int get_completion_argument_index();
int get_completion_identifier_is_function();
+ const List<String> &get_dependencies() const { return dependencies; }
+
void clear();
GDScriptParser();
~GDScriptParser();
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 8b22d6f085..abc739d645 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -744,7 +744,7 @@ void GDScriptTokenizerText::_advance() {
}
INCPOS(1);
is_node_path = true;
-
+ FALLTHROUGH;
case '\'':
case '"': {
@@ -1199,7 +1199,8 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer)
Variant v;
int len;
- Error err = decode_variant(v, b, total_len, &len);
+ // An object cannot be constant, never decode objects
+ Error err = decode_variant(v, b, total_len, &len, false);
if (err)
return err;
b += len;
@@ -1367,11 +1368,12 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code)
for (Map<int, Variant>::Element *E = rev_constant_map.front(); E; E = E->next()) {
int len;
- Error err = encode_variant(E->get(), NULL, len);
+ // Objects cannot be constant, never encode objects
+ Error err = encode_variant(E->get(), NULL, len, false);
ERR_FAIL_COND_V(err != OK, Vector<uint8_t>());
int pos = buf.size();
buf.resize(pos + len);
- encode_variant(E->get(), &buf.write[pos], len);
+ encode_variant(E->get(), &buf.write[pos], len, false);
}
for (Map<int, uint32_t>::Element *E = rev_line_map.front(); E; E = E->next()) {
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 2ea116d79b..655be4eb20 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GridMap" inherits="Spatial" category="Core" version="3.1">
+<class name="GridMap" inherits="Spatial" category="Core" version="3.2">
<brief_description>
Node for 3D tile-based maps.
</brief_description>
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index fe1eac6dc9..32a014e76d 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -517,7 +517,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Ref<NavigationMesh> navmesh = mesh_library->get_item_navmesh(c.item);
if (navmesh.is_valid()) {
Octant::NavMesh nm;
- nm.xform = xform;
+ nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item);
if (navigation) {
nm.id = navigation->navmesh_add(navmesh, xform, this);
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index bc7a576785..17eb6f674c 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -717,6 +717,26 @@ void GridMapEditor::_set_display_mode(int p_mode) {
update_palette();
}
+void GridMapEditor::_text_changed(const String &p_text) {
+ update_palette();
+}
+
+void GridMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
+
+ Ref<InputEventKey> k = p_ie;
+
+ if (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_PAGEUP || k->get_scancode() == KEY_PAGEDOWN)) {
+
+ mesh_library_palette->call("_gui_input", k);
+ search_box->accept_event();
+ }
+}
+
+void GridMapEditor::_icon_size_changed(float p_value) {
+ mesh_library_palette->set_icon_scale(p_value);
+ update_palette();
+}
+
void GridMapEditor::update_palette() {
int selected = mesh_library_palette->get_current();
@@ -730,8 +750,9 @@ void GridMapEditor::update_palette() {
}
float min_size = EDITOR_DEF("editors/grid_map/preview_size", 64);
+ min_size *= EDSCALE;
mesh_library_palette->set_fixed_icon_size(Size2(min_size, min_size));
- mesh_library_palette->set_fixed_column_width(min_size * 3 / 2);
+ mesh_library_palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1.5));
mesh_library_palette->set_max_text_lines(2);
Ref<MeshLibrary> mesh_library = node->get_mesh_library();
@@ -754,23 +775,28 @@ void GridMapEditor::update_palette() {
}
il.sort();
+ String filter = search_box->get_text().strip_edges();
+
int item = 0;
for (List<_CGMEItemSort>::Element *E = il.front(); E; E = E->next()) {
int id = E->get().id;
-
- mesh_library_palette->add_item("");
-
String name = mesh_library->get_item_name(id);
Ref<Texture> preview = mesh_library->get_item_preview(id);
+ if (name == "") {
+ name = "#" + itos(id);
+ }
+
+ if (filter != "" && !filter.is_subsequence_ofi(name))
+ continue;
+
+ mesh_library_palette->add_item("");
if (!preview.is_null()) {
mesh_library_palette->set_item_icon(item, preview);
mesh_library_palette->set_item_tooltip(item, name);
}
- if (name != "") {
- mesh_library_palette->set_item_text(item, name);
- }
+ mesh_library_palette->set_item_text(item, name);
mesh_library_palette->set_item_metadata(item, id);
item++;
@@ -985,6 +1011,7 @@ void GridMapEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
options->set_icon(get_icon("GridMap", "EditorIcons"));
+ search_box->set_right_icon(get_icon("Search", "EditorIcons"));
} break;
}
}
@@ -1031,6 +1058,9 @@ void GridMapEditor::_floor_changed(float p_value) {
void GridMapEditor::_bind_methods() {
+ ClassDB::bind_method("_text_changed", &GridMapEditor::_text_changed);
+ ClassDB::bind_method("_sbox_input", &GridMapEditor::_sbox_input);
+ ClassDB::bind_method("_icon_size_changed", &GridMapEditor::_icon_size_changed);
ClassDB::bind_method("_menu_option", &GridMapEditor::_menu_option);
ClassDB::bind_method("_configure", &GridMapEditor::_configure);
ClassDB::bind_method("_item_selected_cbk", &GridMapEditor::_item_selected_cbk);
@@ -1132,6 +1162,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
add_child(hb);
hb->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_box = memnew(LineEdit);
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ hb->add_child(search_box);
+ search_box->connect("text_changed", this, "_text_changed");
+ search_box->connect("gui_input", this, "_sbox_input");
+
mode_thumbnail = memnew(ToolButton);
mode_thumbnail->set_toggle_mode(true);
mode_thumbnail->set_pressed(true);
@@ -1146,6 +1182,15 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
hb->add_child(mode_list);
mode_list->connect("pressed", this, "_set_display_mode", varray(DISPLAY_LIST));
+ size_slider = memnew(HSlider);
+ size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
+ size_slider->set_min(0.1f);
+ size_slider->set_max(4.0f);
+ size_slider->set_step(0.1f);
+ size_slider->set_value(1.0f);
+ size_slider->connect("value_changed", this, "_icon_size_changed");
+ add_child(size_slider);
+
EDITOR_DEF("editors/grid_map/preview_size", 64);
display_mode = DISPLAY_THUMBNAIL;
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 81a21a76ae..59b8ac13da 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -79,6 +79,8 @@ class GridMapEditor : public VBoxContainer {
double accumulated_floor_delta;
ToolButton *mode_thumbnail;
ToolButton *mode_list;
+ LineEdit *search_box;
+ HSlider *size_slider;
HBoxContainer *spatial_editor_hb;
ConfirmationDialog *settings_dialog;
VBoxContainer *settings_vbc;
@@ -193,6 +195,11 @@ class GridMapEditor : public VBoxContainer {
void _update_cursor_instance();
void _update_clip();
+ void _text_changed(const String &p_text);
+ void _sbox_input(const Ref<InputEvent> &p_ie);
+
+ void _icon_size_changed(float p_value);
+
void _update_duplicate_indicator();
void _duplicate_paste();
void _update_selection_transform();
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index 359d654433..0a75ad4784 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.1">
+<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.2">
<brief_description>
Generic mobile VR implementation
</brief_description>
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index a7ac7f46c5..dfdb4a0b3a 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -499,6 +499,47 @@ String CSharpLanguage::_get_indentation() const {
return "\t";
}
+String CSharpLanguage::debug_get_error() const {
+
+ return _debug_error;
+}
+
+int CSharpLanguage::debug_get_stack_level_count() const {
+
+ if (_debug_parse_err_line >= 0)
+ return 1;
+
+ // TODO: StackTrace
+ return 1;
+}
+
+int CSharpLanguage::debug_get_stack_level_line(int p_level) const {
+
+ if (_debug_parse_err_line >= 0)
+ return _debug_parse_err_line;
+
+ // TODO: StackTrace
+ return 1;
+}
+
+String CSharpLanguage::debug_get_stack_level_function(int p_level) const {
+
+ if (_debug_parse_err_line >= 0)
+ return String();
+
+ // TODO: StackTrace
+ return String();
+}
+
+String CSharpLanguage::debug_get_stack_level_source(int p_level) const {
+
+ if (_debug_parse_err_line >= 0)
+ return _debug_parse_err_file;
+
+ // TODO: StackTrace
+ return String();
+}
+
Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
#ifdef DEBUG_ENABLED
@@ -958,12 +999,11 @@ void CSharpLanguage::thread_exit() {
bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const String &p_error) {
- // Break because of parse error
+ // Not a parser error in our case, but it's still used for other type of errors
if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
- // TODO
- //_debug_parse_err_line = p_line;
- //_debug_parse_err_file = p_file;
- //_debug_error = p_error;
+ _debug_parse_err_line = p_line;
+ _debug_parse_err_file = p_file;
+ _debug_error = p_error;
ScriptDebugger::get_singleton()->debug(this, false);
return true;
} else {
@@ -974,10 +1014,9 @@ bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const S
bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
- // TODO
- //_debug_parse_err_line = -1;
- //_debug_parse_err_file = "";
- //_debug_error = p_error;
+ _debug_parse_err_line = -1;
+ _debug_parse_err_file = "";
+ _debug_error = p_error;
ScriptDebugger::get_singleton()->debug(this, p_allow_continue);
return true;
} else {
@@ -985,6 +1024,13 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
}
}
+void CSharpLanguage::_uninitialize_script_bindings() {
+ for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
+ CSharpScriptBinding &script_binding = E->value();
+ script_binding.inited = false;
+ }
+}
+
void CSharpLanguage::set_language_index(int p_idx) {
ERR_FAIL_COND(lang_idx != -1);
@@ -1269,14 +1315,14 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
GDMonoClass *top = script->script_class;
while (top && top != script->native) {
- GDMonoField *field = script->script_class->get_field(p_name);
+ GDMonoField *field = top->get_field(p_name);
if (field) {
field->set_value_from_variant(mono_object, p_value);
return true;
}
- GDMonoProperty *property = script->script_class->get_property(p_name);
+ GDMonoProperty *property = top->get_property(p_name);
if (property) {
property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value, property->get_type()));
@@ -1528,6 +1574,15 @@ MonoObject *CSharpInstance::_internal_new_managed() {
CRASH_COND(!gchandle.is_valid());
#endif
+ // Search the constructor first, to fail with an error if it's not found before allocating anything else.
+ GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
+ if (ctor == NULL) {
+ ERR_PRINTS("Cannot create script instance because the class does not define a parameterless constructor: " + script->get_path());
+
+ ERR_EXPLAIN("Constructor not found");
+ ERR_FAIL_V(NULL);
+ }
+
CSharpLanguage::get_singleton()->release_script_gchandle(gchandle);
ERR_FAIL_NULL_V(owner, NULL);
@@ -1557,7 +1612,6 @@ MonoObject *CSharpInstance::_internal_new_managed() {
CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, owner);
// Construct
- GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
ctor->invoke_raw(mono_object, NULL);
return mono_object;
@@ -1879,6 +1933,9 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
bool CSharpScript::_update_exports() {
#ifdef TOOLS_ENABLED
+ if (!Engine::get_singleton()->is_editor_hint())
+ return false;
+
placeholder_fallback_enabled = true; // until proven otherwise
if (!valid)
@@ -1900,13 +1957,21 @@ bool CSharpScript::_update_exports() {
MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_mono_ptr());
if (!tmp_object) {
- ERR_PRINT("Failed to create temporary MonoObject");
+ ERR_PRINT("Failed to allocate temporary MonoObject");
return false;
}
uint32_t tmp_pinned_gchandle = MonoGCHandle::new_strong_handle_pinned(tmp_object); // pin it (not sure if needed)
GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
+
+ if (ctor == NULL) {
+ ERR_PRINTS("Cannot construct temporary MonoObject because the class does not define a parameterless constructor: " + get_path());
+
+ ERR_EXPLAIN("Constructor not found");
+ ERR_FAIL_V(NULL);
+ }
+
MonoException *ctor_exc = NULL;
ctor->invoke(tmp_object, NULL, &ctor_exc);
@@ -2187,8 +2252,11 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
hint_string = name_only_hint_string;
}
} else if (variant_type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(type.type_class)) {
+ GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(type.type_class);
+ CRASH_COND(field_native_class == NULL);
+
hint = PROPERTY_HINT_RESOURCE_TYPE;
- hint_string = NATIVE_GDMONOCLASS_NAME(type.type_class);
+ hint_string = NATIVE_GDMONOCLASS_NAME(field_native_class);
} else {
hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr);
@@ -2387,6 +2455,18 @@ StringName CSharpScript::get_instance_base_type() const {
CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
/* STEP 1, CREATE */
+
+ // Search the constructor first, to fail with an error if it's not found before allocating anything else.
+ GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount);
+ if (ctor == NULL) {
+ if (p_argcount == 0) {
+ ERR_PRINTS("Cannot create script instance because the class does not define a parameterless constructor: " + get_path());
+ }
+
+ ERR_EXPLAIN("Constructor not found");
+ ERR_FAIL_V(NULL);
+ }
+
Ref<Reference> ref;
if (p_isref) {
// Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance.
@@ -2453,7 +2533,6 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, instance->owner);
// Construct
- GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount);
ctor->invoke(mono_object, p_args);
/* STEP 3, PARTY */
@@ -2672,6 +2751,7 @@ Error CSharpScript::reload(bool p_keep_state) {
}
load_script_signals(script_class, native);
+ _update_exports();
}
return OK;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 8b1a4b5f7e..99877a4379 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -162,7 +162,7 @@ public:
virtual bool has_script_signal(const StringName &p_signal) const;
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const;
- /* TODO */ virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const;
+ virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const;
virtual void get_script_property_list(List<PropertyInfo> *p_list) const;
virtual void update_exports();
@@ -309,6 +309,14 @@ class CSharpLanguage : public ScriptLanguage {
Dictionary scripts_metadata;
+ // For debug_break and debug_break_parse
+ int _debug_parse_err_line;
+ String _debug_parse_err_file;
+ String _debug_error;
+
+ friend class GDMono;
+ void _uninitialize_script_bindings();
+
public:
StringNameCache string_names;
@@ -365,11 +373,11 @@ public:
/* TODO */ virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) {}
/* DEBUGGER FUNCTIONS */
- /* TODO */ virtual String debug_get_error() const { return ""; }
- /* TODO */ virtual int debug_get_stack_level_count() const { return 1; }
- /* TODO */ virtual int debug_get_stack_level_line(int p_level) const { return 1; }
- /* TODO */ virtual String debug_get_stack_level_function(int p_level) const { return ""; }
- /* TODO */ virtual String debug_get_stack_level_source(int p_level) const { return ""; }
+ virtual String debug_get_error() const;
+ virtual int debug_get_stack_level_count() const;
+ virtual int debug_get_stack_level_line(int p_level) const;
+ virtual String debug_get_stack_level_function(int p_level) const;
+ virtual String debug_get_stack_level_source(int p_level) const;
/* TODO */ virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
/* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml
index 082bc30fd8..a821713d0d 100644
--- a/modules/mono/doc_classes/@C#.xml
+++ b/modules/mono/doc_classes/@C#.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@C#" category="Core" version="3.1">
+<class name="@C#" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
index a1f7399653..7f22388132 100644
--- a/modules/mono/doc_classes/CSharpScript.xml
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSharpScript" inherits="Script" category="Core" version="3.1">
+<class name="CSharpScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index 921c1ca825..21835e639c 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GodotSharp" inherits="Object" category="Core" version="3.1">
+<class name="GodotSharp" inherits="Object" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
index e7d0486c76..967e3bcc19 100644
--- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
@@ -21,6 +21,8 @@ namespace GodotSharpTools.Build
private extern static string godot_icall_BuildInstance_get_MonoWindowsBinDir();
[MethodImpl(MethodImplOptions.InternalCall)]
private extern static bool godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows();
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private extern static bool godot_icall_BuildInstance_get_PrintBuildOutput();
private static string GetMSBuildPath()
{
@@ -53,6 +55,14 @@ namespace GodotSharpTools.Build
}
}
+ private static bool PrintBuildOutput
+ {
+ get
+ {
+ return godot_icall_BuildInstance_get_PrintBuildOutput();
+ }
+ }
+
private string solution;
private string config;
@@ -71,8 +81,6 @@ namespace GodotSharpTools.Build
public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
{
- bool debugMSBuild = IsDebugMSBuildRequested();
-
List<string> customPropertiesList = new List<string>();
if (customProperties != null)
@@ -82,7 +90,10 @@ namespace GodotSharpTools.Build
ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
- bool redirectOutput = !debugMSBuild;
+ bool redirectOutput = !IsDebugMSBuildRequested() && !PrintBuildOutput;
+
+ if (!redirectOutput) // TODO: or if stdout verbose
+ Console.WriteLine($"Running: \"{startInfo.FileName}\" {startInfo.Arguments}");
startInfo.RedirectStandardOutput = redirectOutput;
startInfo.RedirectStandardError = redirectOutput;
@@ -123,8 +134,6 @@ namespace GodotSharpTools.Build
public bool BuildAsync(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
{
- bool debugMSBuild = IsDebugMSBuildRequested();
-
if (process != null)
throw new InvalidOperationException("Already in use");
@@ -137,7 +146,10 @@ namespace GodotSharpTools.Build
ProcessStartInfo startInfo = new ProcessStartInfo(GetMSBuildPath(), compilerArgs);
- bool redirectOutput = !debugMSBuild;
+ bool redirectOutput = !IsDebugMSBuildRequested() && !PrintBuildOutput;
+
+ if (!redirectOutput) // TODO: or if stdout verbose
+ Console.WriteLine($"Running: \"{startInfo.FileName}\" {startInfo.Arguments}");
startInfo.RedirectStandardOutput = redirectOutput;
startInfo.RedirectStandardError = redirectOutput;
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
index 9a5dd24bb1..2871c041f5 100644
--- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
@@ -41,6 +41,7 @@
<Compile Include="Build\BuildSystem.cs" />
<Compile Include="Editor\MonoDevelopInstance.cs" />
<Compile Include="Project\ProjectExtensions.cs" />
+ <Compile Include="Project\IdentifierUtils.cs" />
<Compile Include="Project\ProjectGenerator.cs" />
<Compile Include="Project\ProjectUtils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/modules/mono/editor/GodotSharpTools/Project/IdentifierUtils.cs b/modules/mono/editor/GodotSharpTools/Project/IdentifierUtils.cs
new file mode 100644
index 0000000000..83e2d2cf8d
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Project/IdentifierUtils.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace GodotSharpTools.Project
+{
+ public static class IdentifierUtils
+ {
+ public static string SanitizeQualifiedIdentifier(string qualifiedIdentifier, bool allowEmptyIdentifiers)
+ {
+ if (string.IsNullOrEmpty(qualifiedIdentifier))
+ throw new ArgumentException($"{nameof(qualifiedIdentifier)} cannot be empty", nameof(qualifiedIdentifier));
+
+ string[] identifiers = qualifiedIdentifier.Split(new[] { '.' });
+
+ for (int i = 0; i < identifiers.Length; i++)
+ {
+ identifiers[i] = SanitizeIdentifier(identifiers[i], allowEmpty: allowEmptyIdentifiers);
+ }
+
+ return string.Join(".", identifiers);
+ }
+
+ public static string SanitizeIdentifier(string identifier, bool allowEmpty)
+ {
+ if (string.IsNullOrEmpty(identifier))
+ {
+ if (allowEmpty)
+ return "Empty"; // Default value for empty identifiers
+
+ throw new ArgumentException($"{nameof(identifier)} cannot be empty if {nameof(allowEmpty)} is false", nameof(identifier));
+ }
+
+ if (identifier.Length > 511)
+ identifier = identifier.Substring(0, 511);
+
+ var identifierBuilder = new StringBuilder();
+ int startIndex = 0;
+
+ if (identifier[0] == '@')
+ {
+ identifierBuilder.Append('@');
+ startIndex += 1;
+ }
+
+ for (int i = startIndex; i < identifier.Length; i++)
+ {
+ char @char = identifier[i];
+
+ switch (Char.GetUnicodeCategory(@char))
+ {
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.LetterNumber:
+ case UnicodeCategory.OtherLetter:
+ identifierBuilder.Append(@char);
+ break;
+ case UnicodeCategory.NonSpacingMark:
+ case UnicodeCategory.SpacingCombiningMark:
+ case UnicodeCategory.ConnectorPunctuation:
+ case UnicodeCategory.DecimalDigitNumber:
+ // Identifiers may start with underscore
+ if (identifierBuilder.Length > startIndex || @char == '_')
+ identifierBuilder.Append(@char);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (identifierBuilder.Length == startIndex)
+ {
+ // All characters were invalid so now it's empty. Fill it with something.
+ identifierBuilder.Append("Empty");
+ }
+
+ identifier = identifierBuilder.ToString();
+
+ if (identifier[0] != '@' && IsKeyword(identifier, anyDoubleUnderscore: true))
+ identifier = '@' + identifier;
+
+ return identifier;
+ }
+
+ static bool IsKeyword(string value, bool anyDoubleUnderscore)
+ {
+ // Identifiers that start with double underscore are meant to be used for reserved keywords.
+ // Only existing keywords are enforced, but it may be useful to forbid any identifier
+ // that begins with double underscore to prevent issues with future C# versions.
+ if (anyDoubleUnderscore)
+ {
+ if (value.Length > 2 && value[0] == '_' && value[1] == '_' && value[2] != '_')
+ return true;
+ }
+ else
+ {
+ if (_doubleUnderscoreKeywords.Contains(value))
+ return true;
+ }
+
+ return _keywords.Contains(value);
+ }
+
+ static HashSet<string> _doubleUnderscoreKeywords = new HashSet<string>
+ {
+ "__arglist",
+ "__makeref",
+ "__reftype",
+ "__refvalue",
+ };
+
+ static HashSet<string> _keywords = new HashSet<string>
+ {
+ "as",
+ "do",
+ "if",
+ "in",
+ "is",
+ "for",
+ "int",
+ "new",
+ "out",
+ "ref",
+ "try",
+ "base",
+ "bool",
+ "byte",
+ "case",
+ "char",
+ "else",
+ "enum",
+ "goto",
+ "lock",
+ "long",
+ "null",
+ "this",
+ "true",
+ "uint",
+ "void",
+ "break",
+ "catch",
+ "class",
+ "const",
+ "event",
+ "false",
+ "fixed",
+ "float",
+ "sbyte",
+ "short",
+ "throw",
+ "ulong",
+ "using",
+ "where",
+ "while",
+ "yield",
+ "double",
+ "extern",
+ "object",
+ "params",
+ "public",
+ "return",
+ "sealed",
+ "sizeof",
+ "static",
+ "string",
+ "struct",
+ "switch",
+ "typeof",
+ "unsafe",
+ "ushort",
+ "checked",
+ "decimal",
+ "default",
+ "finally",
+ "foreach",
+ "partial",
+ "private",
+ "virtual",
+ "abstract",
+ "continue",
+ "delegate",
+ "explicit",
+ "implicit",
+ "internal",
+ "operator",
+ "override",
+ "readonly",
+ "volatile",
+ "interface",
+ "namespace",
+ "protected",
+ "unchecked",
+ "stackalloc",
+ };
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs
index 9135006172..89279c69a6 100644
--- a/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs
@@ -140,6 +140,9 @@ namespace GodotSharpTools.Project
public static ProjectRootElement CreateLibraryProject(string name, out ProjectPropertyGroupElement mainGroup)
{
+ if (string.IsNullOrEmpty(name))
+ throw new ArgumentException($"{nameof(name)} cannot be empty", nameof(name));
+
var root = ProjectRootElement.Create();
root.DefaultTargets = "Build";
@@ -149,7 +152,7 @@ namespace GodotSharpTools.Project
mainGroup.AddProperty("ProjectGuid", "{" + Guid.NewGuid().ToString().ToUpper() + "}");
mainGroup.AddProperty("OutputType", "Library");
mainGroup.AddProperty("OutputPath", Path.Combine("bin", "$(Configuration)"));
- mainGroup.AddProperty("RootNamespace", name);
+ mainGroup.AddProperty("RootNamespace", IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true));
mainGroup.AddProperty("AssemblyName", name);
mainGroup.AddProperty("TargetFrameworkVersion", "v4.5");
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 890bea0d1d..84e2303cf6 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -38,6 +38,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
+#include "core/string_builder.h"
#include "core/ucaps.h"
#include "../glue/cs_compressed.gen.h"
@@ -97,7 +98,7 @@
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
-#define BINDINGS_GENERATOR_VERSION UINT32_C(7)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(8)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
@@ -105,6 +106,16 @@ bool BindingsGenerator::verbose_output = false;
BindingsGenerator *BindingsGenerator::singleton = NULL;
+static String fix_doc_description(const String &p_bbcode) {
+
+ // This seems to be the correct way to do this. It's the same EditorHelp does.
+
+ return p_bbcode.dedent()
+ .replace("\t", "")
+ .replace("\r", "")
+ .strip_edges();
+}
+
static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false) {
String ret;
@@ -173,6 +184,457 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up
return ret;
}
+String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype) {
+
+ // Based on the version in EditorHelp
+
+ if (p_bbcode.empty())
+ return String();
+
+ DocData *doc = EditorHelp::get_doc_data();
+
+ String bbcode = p_bbcode;
+
+ StringBuilder xml_output;
+
+ xml_output.append("<para>");
+
+ List<String> tag_stack;
+ bool code_tag = false;
+
+ int pos = 0;
+ while (pos < bbcode.length()) {
+ int brk_pos = bbcode.find("[", pos);
+
+ if (brk_pos < 0)
+ brk_pos = bbcode.length();
+
+ if (brk_pos > pos) {
+ String text = bbcode.substr(pos, brk_pos - pos);
+ if (code_tag || tag_stack.size() > 0) {
+ xml_output.append(text.xml_escape());
+ } else {
+ Vector<String> lines = text.split("\n");
+ for (int i = 0; i < lines.size(); i++) {
+ if (i != 0)
+ xml_output.append("<para>");
+
+ xml_output.append(lines[i].xml_escape());
+
+ if (i != lines.size() - 1)
+ xml_output.append("</para>\n");
+ }
+ }
+ }
+
+ if (brk_pos == bbcode.length())
+ break; // nothing else to add
+
+ int brk_end = bbcode.find("]", brk_pos + 1);
+
+ if (brk_end == -1) {
+ String text = bbcode.substr(brk_pos, bbcode.length() - brk_pos);
+ if (code_tag || tag_stack.size() > 0) {
+ xml_output.append(text.xml_escape());
+ } else {
+ Vector<String> lines = text.split("\n");
+ for (int i = 0; i < lines.size(); i++) {
+ if (i != 0)
+ xml_output.append("<para>");
+
+ xml_output.append(lines[i].xml_escape());
+
+ if (i != lines.size() - 1)
+ xml_output.append("</para>\n");
+ }
+ }
+
+ break;
+ }
+
+ String tag = bbcode.substr(brk_pos + 1, brk_end - brk_pos - 1);
+
+ if (tag.begins_with("/")) {
+ bool tag_ok = tag_stack.size() && tag_stack.front()->get() == tag.substr(1, tag.length());
+
+ if (!tag_ok) {
+ xml_output.append("[");
+ pos = brk_pos + 1;
+ continue;
+ }
+
+ tag_stack.pop_front();
+ pos = brk_end + 1;
+ code_tag = false;
+
+ if (tag == "/url") {
+ xml_output.append("</a>");
+ } else if (tag == "/code") {
+ xml_output.append("</c>");
+ } else if (tag == "/codeblock") {
+ xml_output.append("</code>");
+ }
+ } else if (code_tag) {
+ xml_output.append("[");
+ pos = brk_pos + 1;
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
+ String link_target = tag.substr(tag.find(" ") + 1, tag.length());
+ String link_tag = tag.substr(0, tag.find(" "));
+
+ Vector<String> link_target_parts = link_target.split(".");
+
+ if (link_target_parts.size() <= 0 || link_target_parts.size() > 2) {
+ ERR_PRINTS("Invalid reference format: " + tag);
+
+ xml_output.append("<c>");
+ xml_output.append(tag);
+ xml_output.append("</c>");
+
+ pos = brk_end + 1;
+ continue;
+ }
+
+ const TypeInterface *target_itype;
+ StringName target_cname;
+
+ if (link_target_parts.size() == 2) {
+ target_itype = _get_type_or_null(TypeReference(link_target_parts[0]));
+ if (!target_itype) {
+ target_itype = _get_type_or_null(TypeReference("_" + link_target_parts[0]));
+ }
+ target_cname = link_target_parts[1];
+ } else {
+ target_itype = p_itype;
+ target_cname = link_target_parts[0];
+ }
+
+ if (link_tag == "method") {
+ if (!target_itype || !target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (target_itype) {
+ OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ } else {
+ const MethodInterface *target_imethod = target_itype->find_method_by_name(target_cname);
+
+ if (target_imethod) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_imethod->proxy_name);
+ xml_output.append("\"/>");
+ }
+ }
+ } else if (link_tag == "member") {
+ if (!target_itype || !target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (target_itype) {
+ OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ } else {
+ const PropertyInterface *target_iprop = target_itype->find_property_by_name(target_cname);
+
+ if (target_iprop) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_iprop->proxy_name);
+ xml_output.append("\"/>");
+ }
+ }
+ } else if (link_tag == "signal") {
+ // We do not declare signals in any way in C#, so there is nothing to reference
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ } else if (link_tag == "enum") {
+ StringName search_cname = !target_itype ? target_cname :
+ StringName(target_itype->name + "." + (String)target_cname);
+
+ const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
+
+ if (!enum_match && search_cname != target_cname) {
+ enum_match = enum_types.find(target_cname);
+ }
+
+ if (enum_match) {
+ const TypeInterface &target_enum_itype = enum_match->value();
+
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve enum reference in documentation: " + link_target);
+
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ }
+ } else if (link_tag == "const") {
+ if (!target_itype || !target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (target_itype) {
+ OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ } else if (!target_itype && target_cname == name_cache.type_at_GlobalScope) {
+ String target_name = (String)target_cname;
+
+ // Try to find as a global constant
+ const ConstantInterface *target_iconst = find_constant_by_name(target_name, global_constants);
+
+ if (target_iconst) {
+ // Found global constant
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ // Try to find as global enum constant
+ const EnumInterface *target_ienum = NULL;
+
+ for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
+ target_ienum = &E->get();
+ target_iconst = find_constant_by_name(target_name, target_ienum->constants);
+ if (target_iconst)
+ break;
+ }
+
+ if (target_iconst) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_ienum->cname);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve global constant reference in documentation: " + link_target);
+
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ }
+ }
+ } else {
+ String target_name = (String)target_cname;
+
+ // Try to find the constant in the current class
+ const ConstantInterface *target_iconst = find_constant_by_name(target_name, target_itype->constants);
+
+ if (target_iconst) {
+ // Found constant in current class
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ // Try to find as enum constant in the current class
+ const EnumInterface *target_ienum = NULL;
+
+ for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
+ target_ienum = &E->get();
+ target_iconst = find_constant_by_name(target_name, target_ienum->constants);
+ if (target_iconst)
+ break;
+ }
+
+ if (target_iconst) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_ienum->cname);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve constant reference in documentation: " + link_target);
+
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ }
+ }
+ }
+ }
+
+ pos = brk_end + 1;
+ } else if (doc->class_list.has(tag)) {
+ if (tag == "Array" || tag == "Dictionary") {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE_COLLECTIONS ".");
+ xml_output.append(tag);
+ xml_output.append("\"/>");
+ } else if (tag == "bool" || tag == "int") {
+ xml_output.append("<see cref=\"");
+ xml_output.append(tag);
+ xml_output.append("\"/>");
+ } else if (tag == "float") {
+ xml_output.append("<see cref=\""
+#ifdef REAL_T_IS_DOUBLE
+ "double"
+#else
+ "float"
+#endif
+ "\"/>");
+ } else if (tag == "Variant") {
+ // We use System.Object for Variant, so there is no Variant type in C#
+ xml_output.append("<c>Variant</c>");
+ } else if (tag == "String") {
+ xml_output.append("<see cref=\"string\"/>");
+ } else if (tag == "Nil") {
+ xml_output.append("<see langword=\"null\"/>");
+ } else if (tag.begins_with("@")) {
+ // @GlobalScope, @GDScript, etc
+ xml_output.append("<c>");
+ xml_output.append(tag);
+ xml_output.append("</c>");
+ } else if (tag == "PoolByteArray") {
+ xml_output.append("<see cref=\"byte\"/>");
+ } else if (tag == "PoolIntArray") {
+ xml_output.append("<see cref=\"int\"/>");
+ } else if (tag == "PoolRealArray") {
+#ifdef REAL_T_IS_DOUBLE
+ xml_output.append("<see cref=\"double\"/>");
+#else
+ xml_output.append("<see cref=\"float\"/>");
+#endif
+ } else if (tag == "PoolStringArray") {
+ xml_output.append("<see cref=\"string\"/>");
+ } else if (tag == "PoolVector2Array") {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector2\"/>");
+ } else if (tag == "PoolVector3Array") {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector3\"/>");
+ } else if (tag == "PoolColorArray") {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Color\"/>");
+ } else {
+ const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag));
+
+ if (!target_itype) {
+ target_itype = _get_type_or_null(TypeReference("_" + tag));
+ }
+
+ if (target_itype) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve type reference in documentation: " + tag);
+
+ xml_output.append("<c>");
+ xml_output.append(tag);
+ xml_output.append("</c>");
+ }
+ }
+
+ pos = brk_end + 1;
+ } else if (tag == "b") {
+ // bold is not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "i") {
+ // italics is not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "code") {
+ xml_output.append("<c>");
+
+ code_tag = true;
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "codeblock") {
+ xml_output.append("<code>");
+
+ code_tag = true;
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "center") {
+ // center is alignment not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "br") {
+ xml_output.append("\n"); // FIXME: Should use <para> instead. Luckily this tag isn't used for now.
+ pos = brk_end + 1;
+ } else if (tag == "u") {
+ // underline is not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "s") {
+ // strikethrough is not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag == "url") {
+ int end = bbcode.find("[", brk_end);
+ if (end == -1)
+ end = bbcode.length();
+ String url = bbcode.substr(brk_end + 1, end - brk_end - 1);
+ xml_output.append("<a href=\"");
+ xml_output.append(url);
+ xml_output.append("\">");
+ xml_output.append(url);
+
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
+ } else if (tag.begins_with("url=")) {
+ String url = tag.substr(4, tag.length());
+ xml_output.append("<a href=\"");
+ xml_output.append(url);
+ xml_output.append("\">");
+
+ pos = brk_end + 1;
+ tag_stack.push_front("url");
+ } else if (tag == "img") {
+ int end = bbcode.find("[", brk_end);
+ if (end == -1)
+ end = bbcode.length();
+ String image = bbcode.substr(brk_end + 1, end - brk_end - 1);
+
+ // Not supported. Just append the bbcode.
+ xml_output.append("[img]");
+ xml_output.append(image);
+ xml_output.append("[/img]");
+
+ pos = end;
+ tag_stack.push_front(tag);
+ } else if (tag.begins_with("color=")) {
+ // Not supported.
+ pos = brk_end + 1;
+ tag_stack.push_front("color");
+ } else if (tag.begins_with("font=")) {
+ // Not supported.
+ pos = brk_end + 1;
+ tag_stack.push_front("font");
+ } else {
+ xml_output.append("["); // ignore
+ pos = brk_pos + 1;
+ }
+ }
+
+ xml_output.append("</para>");
+
+ return xml_output.as_string();
+}
+
int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
CRASH_COND(p_ienum.constants.empty());
@@ -299,6 +761,9 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
// Constants (in partial GD class)
+ p_output.push_back("\n#pragma warning disable CS1591 // Disable warning: "
+ "'Missing XML comment for publicly visible type or member'\n");
+
p_output.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
p_output.push_back(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
@@ -306,20 +771,20 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
const ConstantInterface &iconstant = E->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+ if (summary_lines.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_line.xml_escape());
+ p_output.push_back(summary_lines[i]);
p_output.push_back("\n");
}
- }
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
}
p_output.push_back(MEMBER_BEGIN "public const int ");
@@ -369,20 +834,20 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
const ConstantInterface &iconstant = F->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- p_output.push_back(INDENT2 "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+ if (summary_lines.size()) {
+ p_output.push_back(INDENT2 "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_line.xml_escape());
+ p_output.push_back(summary_lines[i]);
p_output.push_back("\n");
}
- }
- p_output.push_back(INDENT2 "/// </summary>\n");
+ p_output.push_back(INDENT2 "/// </summary>\n");
+ }
}
p_output.push_back(INDENT2);
@@ -399,6 +864,8 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
}
p_output.push_back(CLOSE_BLOCK); // end of namespace
+
+ p_output.push_back("\n#pragma warning restore CS1591\n");
}
Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
@@ -712,28 +1179,31 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back("using System;\n"); // IntPtr
output.push_back("using System.Diagnostics;\n"); // DebuggerBrowsable
- output.push_back("\n#pragma warning disable CS1591 // Disable warning: "
- "'Missing XML comment for publicly visible type or member'\n");
+ output.push_back("\n"
+ "#pragma warning disable CS1591 // Disable warning: "
+ "'Missing XML comment for publicly visible type or member'\n"
+ "#pragma warning disable CS1573 // Disable warning: "
+ "'Parameter has no matching param tag in the XML comment'\n");
output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
const DocData::ClassDoc *class_doc = itype.class_doc;
if (class_doc && class_doc->description.size()) {
- output.push_back(INDENT1 "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(class_doc->description), &itype);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = class_doc->description.split("\n");
+ if (summary_lines.size()) {
+ output.push_back(INDENT1 "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
output.push_back(INDENT1 "/// ");
- output.push_back(description_line.xml_escape());
+ output.push_back(summary_lines[i]);
output.push_back("\n");
}
- }
- output.push_back(INDENT1 "/// </summary>\n");
+ output.push_back(INDENT1 "/// </summary>\n");
+ }
}
output.push_back(INDENT1 "public ");
@@ -767,20 +1237,20 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
const ConstantInterface &iconstant = E->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+ if (summary_lines.size()) {
+ output.push_back(MEMBER_BEGIN "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
output.push_back(INDENT2 "/// ");
- output.push_back(description_line.xml_escape());
+ output.push_back(summary_lines[i]);
output.push_back("\n");
}
- }
- output.push_back(INDENT2 "/// </summary>");
+ output.push_back(INDENT2 "/// </summary>");
+ }
}
output.push_back(MEMBER_BEGIN "public const int ");
@@ -808,20 +1278,20 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
const ConstantInterface &iconstant = F->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- output.push_back(INDENT3 "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+ if (summary_lines.size()) {
+ output.push_back(INDENT3 "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
output.push_back(INDENT3 "/// ");
- output.push_back(description_line.xml_escape());
+ output.push_back(summary_lines[i]);
output.push_back("\n");
}
- }
- output.push_back(INDENT3 "/// </summary>\n");
+ output.push_back(INDENT3 "/// </summary>\n");
+ }
}
output.push_back(INDENT3);
@@ -928,7 +1398,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back(INDENT1 CLOSE_BLOCK /* class */
CLOSE_BLOCK /* namespace */);
- output.push_back("\n#pragma warning restore CS1591\n");
+ output.push_back("\n"
+ "#pragma warning restore CS1591\n"
+ "#pragma warning restore CS1573\n");
return _save_file(p_output_file, output);
}
@@ -978,33 +1450,21 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
const TypeInterface *prop_itype = _get_type_or_null(proptype_name);
ERR_FAIL_NULL_V(prop_itype, ERR_BUG); // Property type not found
- String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_iprop.cname));
-
- // Prevent property and enclosing type from sharing the same name
- if (prop_proxy_name == p_itype.proxy_name) {
- if (verbose_output) {
- WARN_PRINTS("Name of property `" + prop_proxy_name + "` is ambiguous with the name of its class `" +
- p_itype.proxy_name + "`. Renaming property to `" + prop_proxy_name + "_`");
- }
-
- prop_proxy_name += "_";
- }
-
if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(p_iprop.prop_doc->description), &p_itype);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = p_iprop.prop_doc->description.split("\n");
+ if (summary_lines.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_line.xml_escape());
+ p_output.push_back(summary_lines[i]);
p_output.push_back("\n");
}
- }
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
}
p_output.push_back(MEMBER_BEGIN "public ");
@@ -1014,7 +1474,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.push_back(prop_itype->cs_type);
p_output.push_back(" ");
- p_output.push_back(prop_proxy_name.replace("/", "__"));
+ p_output.push_back(p_iprop.proxy_name);
p_output.push_back("\n" INDENT2 OPEN_BLOCK);
if (getter) {
@@ -1135,7 +1595,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
icall_params += arg_type->cs_in.empty() ? arg_in : sformat(arg_type->cs_in, arg_in);
- default_args_doc.push_back(INDENT2 "/// <param name=\"" + iarg.name + "\">If the param is null, then the default value is " + def_arg + "</param>\n");
+ // Apparently the name attribute must not include the @
+ String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
+
+ default_args_doc.push_back(INDENT2 "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>\n");
} else {
icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1151,24 +1614,24 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
}
if (p_imethod.method_doc && p_imethod.method_doc->description.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ String xml_summary = bbcode_to_xml(fix_doc_description(p_imethod.method_doc->description), &p_itype);
+ Vector<String> summary_lines = xml_summary.split("\n");
- Vector<String> description_lines = p_imethod.method_doc->description.split("\n");
+ if (summary_lines.size() || default_args_doc.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- for (int i = 0; i < description_lines.size(); i++) {
- String description_line = description_lines[i].strip_edges();
- if (description_line.size()) {
+ for (int i = 0; i < summary_lines.size(); i++) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_line.xml_escape());
+ p_output.push_back(summary_lines[i]);
p_output.push_back("\n");
}
- }
- for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
- p_output.push_back(E->get().xml_escape());
- }
+ for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
+ p_output.push_back(E->get());
+ }
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
}
if (!p_imethod.is_internal) {
@@ -1540,20 +2003,13 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
String vararg_arg = "arg" + argc_str;
String real_argc_str = itos(p_imethod.arguments.size() - 1); // Arguments count without vararg
- p_output.push_back("\tVector<Variant> varargs;\n"
- "\tint vararg_length = mono_array_length(");
+ p_output.push_back("\tint vararg_length = mono_array_length(");
p_output.push_back(vararg_arg);
p_output.push_back(");\n\tint total_length = ");
p_output.push_back(real_argc_str);
- p_output.push_back(" + vararg_length;\n\t");
- p_output.push_back(err_fail_macro);
- p_output.push_back("(varargs.resize(vararg_length) != OK");
- p_output.push_back(fail_ret);
- p_output.push_back(");\n\tVector<Variant*> " C_LOCAL_PTRCALL_ARGS ";\n\t");
- p_output.push_back(err_fail_macro);
- p_output.push_back("(call_args.resize(total_length) != OK");
- p_output.push_back(fail_ret);
- p_output.push_back(");\n");
+ p_output.push_back(" + vararg_length;\n"
+ "\tArgumentsVector<Variant> varargs(vararg_length);\n"
+ "\tArgumentsVector<const Variant *> " C_LOCAL_PTRCALL_ARGS "(total_length);\n");
p_output.push_back(c_in_statements);
p_output.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
"\t\tMonoObject* elem = mono_array_get(");
@@ -1562,7 +2018,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
"\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
"\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
p_output.push_back(real_argc_str);
- p_output.push_back(" + i, &varargs.write[i]);\n\t" CLOSE_BLOCK);
+ p_output.push_back(" + i, &varargs.get(i));\n\t" CLOSE_BLOCK);
} else {
p_output.push_back(c_in_statements);
p_output.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
@@ -1584,7 +2040,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
- p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+ p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
p_output.push_back(", total_length, vcall_error);\n");
// See the comment on the C_LOCAL_VARARG_RET declaration
@@ -1728,7 +2184,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
PropertyInterface iprop;
iprop.cname = property.name;
- iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname));
iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname);
iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname);
@@ -1736,6 +2191,8 @@ void BindingsGenerator::_populate_object_type_interfaces() {
iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid);
ERR_FAIL_COND(!valid);
+ iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname));
+
// Prevent property and enclosing type from sharing the same name
if (iprop.proxy_name == itype.proxy_name) {
if (verbose_output) {
@@ -1746,6 +2203,8 @@ void BindingsGenerator::_populate_object_type_interfaces() {
iprop.proxy_name += "_";
}
+ iprop.proxy_name = iprop.proxy_name.replace("/", "__"); // Some members have a slash...
+
iprop.prop_doc = NULL;
for (int i = 0; i < itype.class_doc->properties.size(); i++) {
@@ -2038,6 +2497,7 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
r_iarg.default_argument = "null";
break;
}
+ FALLTHROUGH;
case Variant::DICTIONARY:
case Variant::_RID:
r_iarg.default_argument = "new %s()";
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 8a1c942f6b..42071f9c0d 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -87,8 +87,13 @@ class BindingsGenerator {
StringName cname;
bool is_enum;
- TypeReference() {
- is_enum = false;
+ TypeReference() :
+ is_enum(false) {
+ }
+
+ TypeReference(const StringName &p_cname) :
+ cname(p_cname),
+ is_enum(false) {
}
};
@@ -321,6 +326,15 @@ class BindingsGenerator {
return NULL;
}
+ const PropertyInterface *find_property_by_name(const StringName &p_cname) const {
+ for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
+ if (E->get().cname == p_cname)
+ return &E->get();
+ }
+
+ return NULL;
+ }
+
const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
if (E->get().proxy_name == p_proxy_name)
@@ -482,6 +496,8 @@ class BindingsGenerator {
StringName type_VarArg;
StringName type_Object;
StringName type_Reference;
+ StringName type_String;
+ StringName type_at_GlobalScope;
StringName enum_Error;
NameCache() {
@@ -493,6 +509,8 @@ class BindingsGenerator {
type_VarArg = StaticCString::create("VarArg");
type_Object = StaticCString::create("Object");
type_Reference = StaticCString::create("Reference");
+ type_String = StaticCString::create("String");
+ type_at_GlobalScope = StaticCString::create("@GlobalScope");
enum_Error = StaticCString::create("Error");
}
@@ -511,6 +529,15 @@ class BindingsGenerator {
return NULL;
}
+ const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
+ for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
+ if (E->get().name == p_name)
+ return &E->get();
+ }
+
+ return NULL;
+ }
+
inline String get_unique_sig(const TypeInterface &p_type) {
if (p_type.is_reference)
return "Ref";
@@ -522,6 +549,8 @@ class BindingsGenerator {
return p_type.name;
}
+ String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
+
int _determine_enum_prefix(const EnumInterface &p_ienum);
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index 5e1c9875f0..00c780d1b7 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -195,6 +195,11 @@ MonoBoolean godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows() {
#endif
}
+MonoBoolean godot_icall_BuildInstance_get_PrintBuildOutput() {
+
+ return (bool)EDITOR_GET("mono/builds/print_build_output");
+}
+
void GodotSharpBuilds::register_internal_calls() {
static bool registered = false;
@@ -205,6 +210,7 @@ void GodotSharpBuilds::register_internal_calls() {
mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath);
mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MonoWindowsBinDir", (void *)godot_icall_BuildInstance_get_MonoWindowsBinDir);
mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows", (void *)godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows);
+ mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_PrintBuildOutput", (void *)godot_icall_BuildInstance_get_PrintBuildOutput);
}
void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
@@ -457,6 +463,8 @@ GodotSharpBuilds::GodotSharpBuilds() {
"," PROP_NAME_MSBUILD_VS
#endif
"," PROP_NAME_XBUILD));
+
+ EDITOR_DEF("mono/builds/print_build_output", false);
}
GodotSharpBuilds::~GodotSharpBuilds() {
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 5b68810017..921b9f987b 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -185,6 +185,16 @@ void GodotSharpEditor::_toggle_about_dialog_on_start(bool p_enabled) {
}
}
+void GodotSharpEditor::_build_solution_pressed() {
+
+ if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) {
+ if (!_create_project_solution())
+ return; // Failed to create solution
+ }
+
+ MonoBottomPanel::get_singleton()->call("_build_project_pressed");
+}
+
void GodotSharpEditor::_menu_option_pressed(int p_id) {
switch (p_id) {
@@ -220,6 +230,7 @@ void GodotSharpEditor::_notification(int p_notification) {
void GodotSharpEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_build_solution_pressed"), &GodotSharpEditor::_build_solution_pressed);
ClassDB::bind_method(D_METHOD("_create_project_solution"), &GodotSharpEditor::_create_project_solution);
ClassDB::bind_method(D_METHOD("_make_api_solutions_if_needed"), &GodotSharpEditor::_make_api_solutions_if_needed);
ClassDB::bind_method(D_METHOD("_remove_create_sln_menu_option"), &GodotSharpEditor::_remove_create_sln_menu_option);
@@ -446,12 +457,12 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
about_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
about_label->set_autowrap(true);
String about_text =
- String("C# support in Godot Engine is a brand new feature and a work in progress.\n") +
- "It is currently in an alpha stage and is not suitable for use in production.\n\n" +
- "As of Godot 3.1, C# support is not feature-complete and may crash in some situations. " +
- "Bugs and usability issues will be addressed gradually over future 3.x releases, " +
- "including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" +
- "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, Mono version, IDE, etc:\n\n" +
+ String("C# support in Godot Engine is in late alpha stage and, while already usable, ") +
+ "it is not meant for use in production.\n\n" +
+ "Projects can be exported to Linux, macOS and Windows, but not yet to mobile or web platforms. " +
+ "Bugs and usability issues will be addressed gradually over future releases, " +
+ "potentially including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" +
+ "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, MSBuild version, IDE, etc.:\n\n" +
" https://github.com/godotengine/godot/issues\n\n" +
"Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!";
about_label->set_text(about_text);
@@ -482,7 +493,7 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
build_button->set_text("Build");
build_button->set_tooltip("Build solution");
build_button->set_focus_mode(Control::FOCUS_NONE);
- build_button->connect("pressed", MonoBottomPanel::get_singleton(), "_build_project_pressed");
+ build_button->connect("pressed", this, "_build_solution_pressed");
editor->get_menu_hb()->add_child(build_button);
// External editor settings
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index c9744a9eed..cf0d2aec84 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -65,6 +65,8 @@ class GodotSharpEditor : public Node {
void _menu_option_pressed(int p_id);
+ void _build_solution_pressed();
+
static GodotSharpEditor *singleton;
protected:
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
index fcc58c22e8..dfb652a7aa 100644
--- a/modules/mono/editor/script_class_parser.cpp
+++ b/modules/mono/editor/script_class_parser.cpp
@@ -266,6 +266,20 @@ Error ScriptClassParser::_skip_generic_type_params() {
if (tk == TK_IDENTIFIER) {
tk = get_token();
+ // Type specifications can end with "?" to denote nullable types, such as IList<int?>
+ if (tk == TK_SYMBOL) {
+ tk = get_token();
+ if (value.operator String() != "?") {
+ error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found unexpected symbol '" + value + "'";
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ if (tk != TK_OP_GREATER && tk != TK_COMMA) {
+ error_str = "Nullable type symbol '?' is only allowed after an identifier, but found " + get_token_name(tk) + " next.";
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ }
if (tk == TK_PERIOD) {
while (true) {
@@ -322,6 +336,15 @@ Error ScriptClassParser::_parse_type_full_name(String &r_full_name) {
r_full_name += String(value);
+ if (code[idx] == '<') {
+ idx++;
+
+ // We don't mind if the base is generic, but we skip it any ways since this information is not needed
+ Error err = _skip_generic_type_params();
+ if (err)
+ return err;
+ }
+
if (code[idx] != '.') // We only want to take the next token if it's a period
return OK;
@@ -344,16 +367,6 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
Token tk = get_token();
- bool generic = false;
- if (tk == TK_OP_LESS) {
- err = _skip_generic_type_params();
- if (err)
- return err;
- // We don't add it to the base list if it's generic
- generic = true;
- tk = get_token();
- }
-
if (tk == TK_COMMA) {
err = _parse_class_base(r_base);
if (err)
@@ -373,9 +386,7 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
return ERR_PARSE_ERROR;
}
- if (!generic) {
- r_base.push_back(name);
- }
+ r_base.push_back(name);
return OK;
}
@@ -567,7 +578,7 @@ Error ScriptClassParser::parse(const String &p_code) {
if (full_name.length())
full_name += ".";
full_name += class_decl.name;
- OS::get_singleton()->print("%s", String("Ignoring generic class declaration: " + class_decl.name).utf8().get_data());
+ OS::get_singleton()->print("Ignoring generic class declaration: %s\n", class_decl.name.utf8().get_data());
}
}
} else if (tk == TK_IDENTIFIER && String(value) == "struct") {
diff --git a/modules/mono/glue/Managed/Files/DebuggingUtils.cs b/modules/mono/glue/Managed/Files/DebuggingUtils.cs
index b27816084e..edfe3464ec 100644
--- a/modules/mono/glue/Managed/Files/DebuggingUtils.cs
+++ b/modules/mono/glue/Managed/Files/DebuggingUtils.cs
@@ -19,6 +19,12 @@ namespace Godot
sb.Append(" ");
}
+ public static void InstallTraceListener()
+ {
+ Trace.Listeners.Clear();
+ Trace.Listeners.Add(new GodotTraceListener());
+ }
+
public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl)
{
fileName = frame.GetFileName();
diff --git a/modules/mono/glue/Managed/Files/DynamicObject.cs b/modules/mono/glue/Managed/Files/DynamicObject.cs
new file mode 100644
index 0000000000..9504415664
--- /dev/null
+++ b/modules/mono/glue/Managed/Files/DynamicObject.cs
@@ -0,0 +1,213 @@
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+
+namespace Godot
+{
+ /// <summary>
+ /// Represents an <see cref="Godot.Object"/> whose members can be dynamically accessed at runtime through the Variant API.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="Godot.DynamicGodotObject"/> class enables access to the Variant
+ /// members of a <see cref="Godot.Object"/> instance at runtime.
+ /// </para>
+ /// <para>
+ /// This allows accessing the class members using their original names in the engine as well as the members from the
+ /// script attached to the <see cref="Godot.Object"/>, regardless of the scripting language it was written in.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>.
+ /// <code>
+ /// dynamic sprite = GetNode("Sprite").DynamicGodotObject;
+ /// sprite.add_child(this);
+ ///
+ /// if ((sprite.hframes * sprite.vframes) > 0)
+ /// sprite.frame = 0;
+ /// </code>
+ /// </example>
+ /// <example>
+ /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Godot.Object"/>.
+ /// <code>
+ /// dynamic childNode = GetNode("ChildNode").DynamicGodotObject;
+ ///
+ /// if (childNode.print_allowed)
+ /// {
+ /// childNode.message = "Hello from C#";
+ /// childNode.print_message(3);
+ /// }
+ /// </code>
+ /// The <c>ChildNode</c> node has the following GDScript script attached:
+ /// <code>
+ /// // # ChildNode.gd
+ /// // var print_allowed = true
+ /// // var message = ""
+ /// //
+ /// // func print_message(times):
+ /// // for i in times:
+ /// // print(message)
+ /// </code>
+ /// </example>
+ public class DynamicGodotObject : DynamicObject
+ {
+ /// <summary>
+ /// Gets the <see cref="Godot.Object"/> associated with this <see cref="Godot.DynamicGodotObject"/>.
+ /// </summary>
+ public Object Value { get; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Godot.DynamicGodotObject"/> class.
+ /// </summary>
+ /// <param name="godotObject">
+ /// The <see cref="Godot.Object"/> that will be associated with this <see cref="Godot.DynamicGodotObject"/>.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException">
+ /// Thrown when the <paramref name="godotObject"/> parameter is null.
+ /// </exception>
+ public DynamicGodotObject(Object godotObject)
+ {
+ if (godotObject == null)
+ throw new ArgumentNullException(nameof(godotObject));
+
+ this.Value = godotObject;
+ }
+
+ public override IEnumerable<string> GetDynamicMemberNames()
+ {
+ return godot_icall_DynamicGodotObject_SetMemberList(Object.GetPtr(Value));
+ }
+
+ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
+ {
+ switch (binder.Operation)
+ {
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ if (binder.ReturnType == typeof(bool) || binder.ReturnType.IsAssignableFrom(typeof(bool)))
+ {
+ if (arg == null)
+ {
+ bool boolResult = Object.IsInstanceValid(Value);
+
+ if (binder.Operation == ExpressionType.Equal)
+ boolResult = !boolResult;
+
+ result = boolResult;
+ return true;
+ }
+
+ if (arg is Object other)
+ {
+ bool boolResult = (Value == other);
+
+ if (binder.Operation == ExpressionType.NotEqual)
+ boolResult = !boolResult;
+
+ result = boolResult;
+ return true;
+ }
+ }
+
+ break;
+ default:
+ // We're not implementing operators <, <=, >, and >= (LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual).
+ // These are used on the actual pointers in variant_op.cpp. It's better to let the user do that explicitly.
+ break;
+ }
+
+ return base.TryBinaryOperation(binder, arg, out result);
+ }
+
+ public override bool TryConvert(ConvertBinder binder, out object result)
+ {
+ if (binder.Type == typeof(Object))
+ {
+ result = Value;
+ return true;
+ }
+
+ if (typeof(Object).IsAssignableFrom(binder.Type))
+ {
+ // Throws InvalidCastException when the cast fails
+ result = Convert.ChangeType(Value, binder.Type);
+ return true;
+ }
+
+ return base.TryConvert(binder, out result);
+ }
+
+ public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
+ {
+ if (indexes.Length == 1)
+ {
+ if (indexes[0] is string name)
+ {
+ return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), name, out result);
+ }
+ }
+
+ return base.TryGetIndex(binder, indexes, out result);
+ }
+
+ public override bool TryGetMember(GetMemberBinder binder, out object result)
+ {
+ return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), binder.Name, out result);
+ }
+
+ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
+ {
+ return godot_icall_DynamicGodotObject_InvokeMember(Object.GetPtr(Value), binder.Name, args, out result);
+ }
+
+ public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
+ {
+ if (indexes.Length == 1)
+ {
+ if (indexes[0] is string name)
+ {
+ return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), name, value);
+ }
+ }
+
+ return base.TrySetIndex(binder, indexes, value);
+ }
+
+ public override bool TrySetMember(SetMemberBinder binder, object value)
+ {
+ return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), binder.Name, value);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
+
+ #region We don't override these methods
+
+ // Looks like this is not usable from C#
+ //public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
+
+ // Object members cannot be deleted
+ //public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
+ //public override bool TryDeleteMember(DeleteMemberBinder binder);
+
+ // Invokation on the object itself, e.g.: obj(param)
+ //public override bool TryInvoke(InvokeBinder binder, object[] args, out object result);
+
+ // No unnary operations to handle
+ //public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result);
+
+ #endregion
+ }
+}
diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs
index 3afaf5d08b..d968f8a78f 100644
--- a/modules/mono/glue/Managed/Files/GD.cs
+++ b/modules/mono/glue/Managed/Files/GD.cs
@@ -13,12 +13,12 @@ namespace Godot
{
public static partial class GD
{
- public static object Bytes2Var(byte[] bytes)
+ public static object Bytes2Var(byte[] bytes, bool allow_objects = false)
{
- return godot_icall_GD_bytes2var(bytes);
+ return godot_icall_GD_bytes2var(bytes, allow_objects);
}
- public static object Convert(object what, int type)
+ public static object Convert(object what, Variant.Type type)
{
return godot_icall_GD_convert(what, type);
}
@@ -186,9 +186,9 @@ namespace Godot
return godot_icall_GD_type_exists(type);
}
- public static byte[] Var2Bytes(object var)
+ public static byte[] Var2Bytes(object var, bool full_objects = false)
{
- return godot_icall_GD_var2bytes(var);
+ return godot_icall_GD_var2bytes(var, full_objects);
}
public static string Var2Str(object var)
@@ -197,10 +197,10 @@ namespace Godot
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_bytes2var(byte[] bytes);
+ internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allow_objects);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_convert(object what, int type);
+ internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_GD_hash(object var);
@@ -251,7 +251,7 @@ namespace Godot
internal extern static bool godot_icall_GD_type_exists(string type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static byte[] godot_icall_GD_var2bytes(object what);
+ internal extern static byte[] godot_icall_GD_var2bytes(object what, bool full_objects);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string godot_icall_GD_var2str(object var);
diff --git a/modules/mono/glue/Managed/Files/GodotTraceListener.cs b/modules/mono/glue/Managed/Files/GodotTraceListener.cs
new file mode 100644
index 0000000000..f1a00ae0fa
--- /dev/null
+++ b/modules/mono/glue/Managed/Files/GodotTraceListener.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Diagnostics;
+
+namespace Godot
+{
+ internal class GodotTraceListener : TraceListener
+ {
+ public override void Write(string message)
+ {
+ GD.PrintRaw(message);
+ }
+
+ public override void WriteLine(string message)
+ {
+ GD.Print(message);
+ }
+
+ public override void Fail(string message, string detailMessage)
+ {
+ GD.PrintErr("Assertion failed: ", message);
+ if (detailMessage != null)
+ {
+ GD.PrintErr(" Details: ", detailMessage);
+ }
+
+ try
+ {
+ var stackTrace = new StackTrace(true).ToString();
+ GD.PrintErr(stackTrace);
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ }
+}
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index dcab3c1ffc..5f5de12959 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -289,13 +289,13 @@ namespace Godot
public static int Wrap(int value, int min, int max)
{
int rng = max - min;
- return min + ((value - min) % rng + rng) % rng;
+ return rng != 0 ? min + ((value - min) % rng + rng) % rng : min;
}
public static real_t Wrap(real_t value, real_t min, real_t max)
{
real_t rng = max - min;
- return min + ((value - min) % rng + rng) % rng;
+ return !IsEqualApprox(rng, default(real_t)) ? min + ((value - min) % rng + rng) % rng : min;
}
}
}
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index 2ef02cc288..414762f7b1 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -35,5 +35,10 @@ namespace Godot
{
return (int)Math.Round(s);
}
+
+ public static bool IsEqualApprox(real_t a, real_t b, real_t ratio = Mathf.Epsilon)
+ {
+ return Abs(a - b) < ratio;
+ }
}
} \ No newline at end of file
diff --git a/modules/mono/glue/Managed/Files/Object.base.cs b/modules/mono/glue/Managed/Files/Object.base.cs
index 41fc43996f..e152d56871 100644
--- a/modules/mono/glue/Managed/Files/Object.base.cs
+++ b/modules/mono/glue/Managed/Files/Object.base.cs
@@ -73,11 +73,39 @@ namespace Godot
disposed = true;
}
+ /// <summary>
+ /// Returns a new <see cref="Godot.SignalAwaiter"/> awaiter configured to complete when the instance
+ /// <paramref name="source"/> emits the signal specified by the <paramref name="signal"/> parameter.
+ /// </summary>
+ /// <param name="source">
+ /// The instance the awaiter will be listening to.
+ /// </param>
+ /// <param name="signal">
+ /// The signal the awaiter will be waiting for.
+ /// </param>
+ /// <example>
+ /// This sample prints a message once every frame up to 100 times.
+ /// <code>
+ /// public override void _Ready()
+ /// {
+ /// for (int i = 0; i < 100; i++)
+ /// {
+ /// await ToSignal(GetTree(), "idle_frame");
+ /// GD.Print($"Frame {i}");
+ /// }
+ /// }
+ /// </code>
+ /// </example>
public SignalAwaiter ToSignal(Object source, string signal)
{
return new SignalAwaiter(source, signal, this);
}
+ /// <summary>
+ /// Gets a new <see cref="Godot.DynamicGodotObject"/> associated with this instance.
+ /// </summary>
+ public dynamic DynamicObject => new DynamicGodotObject(this);
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Object_Ctor(Object obj);
diff --git a/modules/mono/glue/arguments_vector.h b/modules/mono/glue/arguments_vector.h
new file mode 100644
index 0000000000..8c0f308c15
--- /dev/null
+++ b/modules/mono/glue/arguments_vector.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* arguments_vector.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef ARGUMENTS_VECTOR_H
+#define ARGUMENTS_VECTOR_H
+
+#include "core/os/memory.h"
+
+template <typename T, int POOL_SIZE = 5>
+struct ArgumentsVector {
+
+private:
+ T pool[POOL_SIZE];
+ T *_ptr;
+ int size;
+
+ ArgumentsVector();
+ ArgumentsVector(const ArgumentsVector &);
+
+public:
+ T *ptr() { return _ptr; }
+ T &get(int p_idx) { return _ptr[p_idx]; }
+ void set(int p_idx, const T &p_value) { _ptr[p_idx] = p_value; }
+
+ explicit ArgumentsVector(int p_size) :
+ size(p_size) {
+ if (p_size <= POOL_SIZE) {
+ _ptr = pool;
+ } else {
+ _ptr = memnew_arr(T, p_size);
+ }
+ }
+
+ ~ArgumentsVector() {
+ if (size > POOL_SIZE) {
+ memdelete_arr(_ptr);
+ }
+ }
+};
+
+#endif // ARGUMENTS_VECTOR_H
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index fad02b01d3..b690de0d20 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -36,9 +36,11 @@
#include "core/string_name.h"
#include "../csharp_script.h"
+#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_internals.h"
#include "../mono_gd/gd_mono_utils.h"
#include "../signal_awaiter_utils.h"
+#include "arguments_vector.h"
Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
Object *instance = memnew(Object);
@@ -75,7 +77,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer) {
+void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
#ifdef DEBUG_ENABLED
CRASH_COND(p_ptr == NULL);
// This is only called with Reference derived classes
@@ -155,6 +157,67 @@ Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal,
return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
}
+MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
+ List<PropertyInfo> property_list;
+ p_ptr->get_property_list(&property_list);
+
+ MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
+
+ int i = 0;
+ for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
+ mono_array_set(result, MonoString *, i, boxed);
+ i++;
+ }
+
+ return result;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+ int argc = mono_array_length(p_args);
+
+ ArgumentsVector<Variant> arg_store(argc);
+ ArgumentsVector<const Variant *> args(argc);
+
+ for (int i = 0; i < argc; i++) {
+ MonoObject *elem = mono_array_get(p_args, MonoObject *, i);
+ arg_store.set(i, GDMonoMarshal::mono_object_to_variant(elem));
+ args.set(i, &arg_store.get(i));
+ }
+
+ Variant::CallError error;
+ Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
+
+ *r_result = GDMonoMarshal::variant_to_mono_object(result);
+
+ return error.error == OK;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+
+ bool valid;
+ Variant value = p_ptr->get(StringName(name), &valid);
+
+ if (valid) {
+ *r_result = GDMonoMarshal::variant_to_mono_object(value);
+ }
+
+ return valid;
+}
+
+MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value) {
+ String name = GDMonoMarshal::mono_string_to_godot(p_name);
+ Variant value = GDMonoMarshal::mono_object_to_variant(p_value);
+
+ bool valid;
+ p_ptr->set(StringName(name), value, &valid);
+
+ return valid;
+}
+
void godot_register_object_icalls() {
mono_add_internal_call("Godot.Object::godot_icall_Object_Ctor", (void *)godot_icall_Object_Ctor);
mono_add_internal_call("Godot.Object::godot_icall_Object_Disposed", (void *)godot_icall_Object_Disposed);
@@ -162,6 +225,10 @@ void godot_register_object_icalls() {
mono_add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", (void *)godot_icall_Object_ClassDB_get_method);
mono_add_internal_call("Godot.Object::godot_icall_Object_weakref", (void *)godot_icall_Object_weakref);
mono_add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", (void *)godot_icall_SignalAwaiter_connect);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", (void *)godot_icall_DynamicGodotObject_SetMemberList);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_InvokeMember", (void *)godot_icall_DynamicGodotObject_InvokeMember);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", (void *)godot_icall_DynamicGodotObject_GetMember);
+ mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", (void *)godot_icall_DynamicGodotObject_SetMember);
}
#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/base_object_glue.h b/modules/mono/glue/base_object_glue.h
index e126fac6ca..9b5224a347 100644
--- a/modules/mono/glue/base_object_glue.h
+++ b/modules/mono/glue/base_object_glue.h
@@ -42,7 +42,7 @@ Object *godot_icall_Object_Ctor(MonoObject *p_obj);
void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr);
-void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer);
+void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer);
MethodBind *godot_icall_Object_ClassDB_get_method(MonoString *p_type, MonoString *p_method);
@@ -50,6 +50,16 @@ MonoObject *godot_icall_Object_weakref(Object *p_obj);
Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter);
+// DynamicGodotObject
+
+MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr);
+
+MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result);
+
+MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result);
+
+MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value);
+
// Register internal calls
void godot_register_object_icalls();
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 1065ff0868..1aad1c53bc 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -81,7 +81,7 @@ void godot_icall_Array_Clear(Array *ptr) {
ptr->clear();
}
-bool godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
+MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
}
@@ -113,7 +113,7 @@ void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item) {
ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
}
-bool godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
+MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
if (idx >= 0) {
ptr->remove(idx);
@@ -208,21 +208,21 @@ void godot_icall_Dictionary_Clear(Dictionary *ptr) {
ptr->clear();
}
-bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
+MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
// no dupes
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
return ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value);
}
-bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
+MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
}
-bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
+MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
return ptr->erase(GDMonoMarshal::mono_object_to_variant(key));
}
-bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
+MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
// no dupes
@@ -235,7 +235,7 @@ bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject
return false;
}
-bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
+MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
if (ret == NULL) {
*value = NULL;
@@ -245,7 +245,7 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb
return true;
}
-bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
+MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
if (ret == NULL) {
*value = NULL;
diff --git a/modules/mono/glue/collections_glue.h b/modules/mono/glue/collections_glue.h
index c0056d3bce..85a2e243a2 100644
--- a/modules/mono/glue/collections_glue.h
+++ b/modules/mono/glue/collections_glue.h
@@ -55,7 +55,7 @@ void godot_icall_Array_Add(Array *ptr, MonoObject *item);
void godot_icall_Array_Clear(Array *ptr);
-bool godot_icall_Array_Contains(Array *ptr, MonoObject *item);
+MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item);
void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index);
@@ -63,7 +63,7 @@ int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item);
void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item);
-bool godot_icall_Array_Remove(Array *ptr, MonoObject *item);
+MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item);
void godot_icall_Array_RemoveAt(Array *ptr, int index);
@@ -93,17 +93,17 @@ void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *va
void godot_icall_Dictionary_Clear(Dictionary *ptr);
-bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value);
+MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value);
-bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key);
+MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key);
-bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key);
+MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key);
-bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value);
+MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value);
-bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
+MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
-bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class);
+MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class);
void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
index 5edf49d2bf..d756131ac9 100644
--- a/modules/mono/glue/gd_glue.cpp
+++ b/modules/mono/glue/gd_glue.cpp
@@ -41,11 +41,11 @@
#include "../mono_gd/gd_mono_utils.h"
-MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes) {
+MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) {
Variant ret;
PoolByteArray varr = GDMonoMarshal::mono_array_to_PoolByteArray(p_bytes);
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, p_allow_objects);
if (err != OK) {
ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
}
@@ -175,7 +175,7 @@ MonoObject *godot_icall_GD_str2var(MonoString *p_str) {
return GDMonoMarshal::variant_to_mono_object(ret);
}
-bool godot_icall_GD_type_exists(MonoString *p_type) {
+MonoBoolean godot_icall_GD_type_exists(MonoString *p_type) {
return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type));
}
@@ -187,19 +187,19 @@ void godot_icall_GD_pushwarning(MonoString *p_str) {
WARN_PRINTS(GDMonoMarshal::mono_string_to_godot(p_str));
}
-MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var) {
+MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects) {
Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
PoolByteArray barr;
int len;
- Error err = encode_variant(var, NULL, len);
+ Error err = encode_variant(var, NULL, len, p_full_objects);
ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
ERR_FAIL_COND_V(err != OK, NULL);
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(var, w.ptr(), len);
+ encode_variant(var, w.ptr(), len, p_full_objects);
}
return GDMonoMarshal::PoolByteArray_to_mono_array(barr);
diff --git a/modules/mono/glue/gd_glue.h b/modules/mono/glue/gd_glue.h
index ba75d85343..910979aae3 100644
--- a/modules/mono/glue/gd_glue.h
+++ b/modules/mono/glue/gd_glue.h
@@ -35,7 +35,7 @@
#include "../mono_gd/gd_mono_marshal.h"
-MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes);
+MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects);
MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type);
@@ -69,9 +69,9 @@ MonoString *godot_icall_GD_str(MonoArray *p_what);
MonoObject *godot_icall_GD_str2var(MonoString *p_str);
-bool godot_icall_GD_type_exists(MonoString *p_type);
+MonoBoolean godot_icall_GD_type_exists(MonoString *p_type);
-MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var);
+MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects);
MonoString *godot_icall_GD_var2str(MonoObject *p_var);
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index b6e8ac6909..1836130b76 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -74,4 +74,6 @@ void godot_register_glue_header_icalls() {
} \
Object *m_instance = ci->creation_func();
+#include "arguments_vector.h"
+
#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index dfabfddd64..bba7df2c6a 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -34,6 +34,7 @@
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/mono-gc.h>
+#include <mono/metadata/profiler.h>
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
@@ -54,6 +55,10 @@
#include "main/main.h"
#endif
+#define OUT_OF_SYNC_ERR_MESSAGE(m_assembly_name) "The assembly '" m_assembly_name "' is out of sync. " \
+ "This error is expected if you just upgraded to a newer Godot version. " \
+ "Building the project will update the assembly to the correct version."
+
GDMono *GDMono::singleton = NULL;
namespace {
@@ -79,6 +84,14 @@ void setup_runtime_main_args() {
mono_runtime_set_main_args(main_args.size(), main_args.ptrw());
}
+void gdmono_profiler_init() {
+ String profiler_args = GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd");
+ bool profiler_enabled = GLOBAL_DEF("mono/profiler/enabled", false);
+ if (profiler_enabled) {
+ mono_profiler_load(profiler_args.utf8());
+ }
+}
+
#ifdef DEBUG_ENABLED
static bool _wait_for_debugger_msecs(uint32_t p_msecs) {
@@ -265,6 +278,8 @@ void GDMono::initialize() {
GDMonoAssembly::initialize();
+ gdmono_profiler_init();
+
#ifdef DEBUG_ENABLED
gdmono_debug_init();
#endif
@@ -273,7 +288,7 @@ void GDMono::initialize() {
mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL);
-#ifdef TOOLS_ENABLED
+#ifndef TOOLS_ENABLED
if (!DirAccess::exists("res://.mono")) {
// 'res://.mono/' is missing so there is nothing to load. We don't need to initialize mono, but
// we still do so unless mscorlib is missing (which is the case for projects that don't use C#).
@@ -353,15 +368,15 @@ void GDMono::initialize() {
// metadata, so we invalidate the version in the metadata and unload the script domain.
if (core_api_assembly_out_of_sync) {
- ERR_PRINT("The loaded Core API assembly is out of sync");
+ ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(CORE_API_ASSEMBLY_NAME));
metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
} else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
- ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed");
+ ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed");
metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
}
if (editor_api_assembly_out_of_sync) {
- ERR_PRINT("The loaded Editor API assembly is out of sync");
+ ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(EDITOR_API_ASSEMBLY_NAME));
metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true);
}
@@ -572,6 +587,8 @@ bool GDMono::_load_core_api_assembly() {
CS_GLUE_VERSION != api_assembly_ver.cs_glue_version;
if (!core_api_assembly_out_of_sync) {
GDMonoUtils::update_godot_api_cache();
+
+ _install_trace_listener();
}
#else
GDMonoUtils::update_godot_api_cache();
@@ -675,6 +692,23 @@ bool GDMono::_load_api_assemblies() {
return true;
}
+void GDMono::_install_trace_listener() {
+
+#ifdef DEBUG_ENABLED
+ // Install the trace listener now before the project assembly is loaded
+ typedef void (*DebuggingUtils_InstallTraceListener)(MonoObject **);
+ MonoException *exc = NULL;
+ GDMonoClass *debug_utils = core_api_assembly->get_class(BINDINGS_NAMESPACE, "DebuggingUtils");
+ DebuggingUtils_InstallTraceListener install_func =
+ (DebuggingUtils_InstallTraceListener)debug_utils->get_method_thunk("InstallTraceListener");
+ install_func((MonoObject **)&exc);
+ if (exc) {
+ ERR_PRINT("Failed to install System.Diagnostics.Trace listener");
+ GDMonoUtils::debug_print_unhandled_exception(exc);
+ }
+#endif
+}
+
#ifdef TOOLS_ENABLED
String GDMono::_get_api_assembly_metadata_path() {
@@ -764,8 +798,6 @@ Error GDMono::_unload_scripts_domain() {
if (mono_domain_get() != root_domain)
mono_domain_set(root_domain, true);
- mono_gc_collect(mono_gc_max_generation());
-
finalizing_scripts_domain = true;
if (!mono_domain_finalize(scripts_domain, 2000)) {
@@ -833,6 +865,8 @@ Error GDMono::reload_scripts_domain() {
}
}
+ CSharpLanguage::get_singleton()->_uninitialize_script_bindings();
+
Error err = _load_scripts_domain();
if (err != OK) {
ERR_PRINT("Mono: Failed to load scripts domain");
@@ -852,7 +886,7 @@ Error GDMono::reload_scripts_domain() {
// metadata, so we invalidate the version in the metadata and unload the script domain.
if (core_api_assembly_out_of_sync) {
- ERR_PRINT("The loaded Core API assembly is out of sync");
+ ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(CORE_API_ASSEMBLY_NAME));
metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
} else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed");
@@ -860,7 +894,7 @@ Error GDMono::reload_scripts_domain() {
}
if (editor_api_assembly_out_of_sync) {
- ERR_PRINT("The loaded Editor API assembly is out of sync");
+ ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(EDITOR_API_ASSEMBLY_NAME));
metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true);
}
@@ -901,14 +935,20 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
if (mono_domain_get() == p_domain)
mono_domain_set(root_domain, true);
- mono_gc_collect(mono_gc_max_generation());
if (!mono_domain_finalize(p_domain, 2000)) {
ERR_PRINT("Mono: Domain finalization timeout");
}
+
mono_gc_collect(mono_gc_max_generation());
_domain_assemblies_cleanup(mono_domain_get_id(p_domain));
+#ifdef TOOLS_ENABLED
+ if (p_domain == tools_domain) {
+ editor_tools_assembly = NULL;
+ }
+#endif
+
MonoException *exc = NULL;
mono_domain_try_unload(p_domain, (MonoObject **)&exc);
@@ -1010,11 +1050,19 @@ GDMono::~GDMono() {
if (is_runtime_initialized()) {
- if (scripts_domain) {
+#ifdef TOOLS_ENABLED
+ if (tools_domain) {
+ Error err = finalize_and_unload_domain(tools_domain);
+ if (err != OK) {
+ ERR_PRINT("Mono: Failed to unload tools domain");
+ }
+ }
+#endif
+ if (scripts_domain) {
Error err = _unload_scripts_domain();
if (err != OK) {
- WARN_PRINT("Mono: Failed to unload scripts domain");
+ ERR_PRINT("Mono: Failed to unload scripts domain");
}
}
@@ -1035,6 +1083,8 @@ GDMono::~GDMono() {
mono_jit_cleanup(root_domain);
+ print_verbose("Mono: Finalized");
+
runtime_initialized = false;
}
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index 785b65ce13..216c96a612 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -125,6 +125,8 @@ class GDMono {
String _get_api_assembly_metadata_path();
#endif
+ void _install_trace_listener();
+
void _register_internal_calls();
Error _load_scripts_domain();
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 85273bfdb4..8fec28b186 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -50,7 +50,7 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin
const char *rootdir = mono_assembly_getrootdir();
if (rootdir) {
- String framework_dir = String(rootdir).plus_file("mono").plus_file("4.5");
+ String framework_dir = String::utf8(rootdir).plus_file("mono").plus_file("4.5");
r_search_dirs.push_back(framework_dir);
r_search_dirs.push_back(framework_dir.plus_file("Facades"));
}
@@ -277,6 +277,7 @@ Error GDMonoAssembly::load(bool p_refonly) {
ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN);
#ifdef DEBUG_ENABLED
+ Vector<uint8_t> pdb_data;
String pdb_path(path + ".pdb");
if (!FileAccess::exists(pdb_path)) {
@@ -286,8 +287,9 @@ Error GDMonoAssembly::load(bool p_refonly) {
goto no_pdb;
}
- pdb_data.clear();
pdb_data = FileAccess::get_file_as_array(pdb_path);
+
+ // mono_debug_close_image doesn't seem to be needed
mono_debug_open_image_from_memory(image, &pdb_data[0], pdb_data.size());
no_pdb:
@@ -306,6 +308,9 @@ no_pdb:
ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
+ // Decrement refcount which was previously incremented by mono_image_open_from_data_with_name
+ mono_image_close(image);
+
loaded = true;
modified_time = last_modified_time;
@@ -321,8 +326,6 @@ Error GDMonoAssembly::wrapper_for_image(MonoImage *p_image) {
image = p_image;
- mono_image_addref(image);
-
loaded = true;
return OK;
@@ -332,13 +335,6 @@ void GDMonoAssembly::unload() {
ERR_FAIL_COND(!loaded);
-#ifdef DEBUG_ENABLED
- if (pdb_data.size()) {
- mono_debug_close_image(image);
- pdb_data.clear();
- }
-#endif
-
for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) {
memdelete(E->value());
}
@@ -346,8 +342,6 @@ void GDMonoAssembly::unload() {
cached_classes.clear();
cached_raw.clear();
- mono_image_close(image);
-
assembly = NULL;
image = NULL;
loaded = false;
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 8f47ee26f8..32432af37d 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -84,10 +84,6 @@ class GDMonoAssembly {
bool gdobject_class_cache_updated;
Map<StringName, GDMonoClass *> gdobject_class_cache;
-#ifdef DEBUG_ENABLED
- Vector<uint8_t> pdb_data;
-#endif
-
static bool no_search;
static bool in_preload;
static Vector<String> search_dirs;
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 48fa380456..5e9d4db122 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -49,7 +49,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
#define SET_FROM_ARRAY(m_type) \
{ \
MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator ::m_type()); \
- mono_field_set_value(p_object, mono_field, &managed); \
+ mono_field_set_value(p_object, mono_field, managed); \
}
switch (type.type_encoding) {
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
index 0eb4b3b8b3..d7f9b22c31 100644
--- a/modules/mono/utils/mono_reg_utils.cpp
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "mono_reg_utils.h"
+#include "core/os/dir_access.h"
#ifdef WINDOWS_ENABLED
@@ -200,6 +201,13 @@ String find_msbuild_tools_path() {
val += "\\";
}
+ // Since VS2019, the directory is simply named "Current"
+ String msBuildDirectory = val + "MSBuild\\Current\\Bin";
+ if (DirAccess::exists(msBuildDirectory)) {
+ return msBuildDirectory;
+ }
+
+ // Directory name "15.0" is used in VS 2017
return val + "MSBuild\\15.0\\Bin";
}
}
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index ba54160a90..25f104b221 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NoiseTexture" inherits="Texture" category="Core" version="3.1">
+<class name="NoiseTexture" inherits="Texture" category="Core" version="3.2">
<brief_description>
[OpenSimplexNoise] filled texture.
</brief_description>
@@ -17,6 +17,8 @@
<member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap">
If true, the resulting texture contains a normal map created from the original noise interpreted as a bump map.
</member>
+ <member name="bump_strength" type="float" setter="set_bump_strength" getter="get_bump_strength">
+ </member>
<member name="height" type="int" setter="set_height" getter="get_height">
Height of the generated texture.
</member>
diff --git a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
index 31f13f341c..b5bc35df69 100644
--- a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
+++ b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OpenSimplexNoise" inherits="Resource" category="Core" version="3.1">
+<class name="OpenSimplexNoise" inherits="Resource" category="Core" version="3.2">
<brief_description>
Noise generator based on Open Simplex.
</brief_description>
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index b8126ab775..9240183265 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -41,6 +41,7 @@ NoiseTexture::NoiseTexture() {
size = Vector2i(512, 512);
seamless = false;
as_normalmap = false;
+ bump_strength = 8.0;
flags = FLAGS_DEFAULT;
noise = Ref<OpenSimplexNoise>();
@@ -68,6 +69,9 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_as_normalmap", "as_normalmap"), &NoiseTexture::set_as_normalmap);
ClassDB::bind_method(D_METHOD("is_normalmap"), &NoiseTexture::is_normalmap);
+ ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength);
+ ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength);
+
ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture);
ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture);
ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done);
@@ -76,9 +80,19 @@ void NoiseTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normalmap"), "set_as_normalmap", "is_normalmap");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
}
+void NoiseTexture::_validate_property(PropertyInfo &property) const {
+
+ if (property.name == "bump_strength") {
+ if (!as_normalmap) {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+ }
+}
+
void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
data = p_image;
if (data.is_valid()) {
@@ -129,7 +143,7 @@ Ref<Image> NoiseTexture::_generate_texture() {
}
if (as_normalmap) {
- image->bumpmap_to_normalmap();
+ image->bumpmap_to_normalmap(bump_strength);
}
return image;
@@ -202,12 +216,26 @@ void NoiseTexture::set_as_normalmap(bool p_as_normalmap) {
if (p_as_normalmap == as_normalmap) return;
as_normalmap = p_as_normalmap;
_queue_update();
+ _change_notify();
}
bool NoiseTexture::is_normalmap() {
return as_normalmap;
}
+void NoiseTexture::set_bump_strength(float p_bump_strength) {
+
+ if (p_bump_strength == bump_strength) return;
+ bump_strength = p_bump_strength;
+ if (as_normalmap)
+ _queue_update();
+}
+
+float NoiseTexture::get_bump_strength() {
+
+ return bump_strength;
+}
+
int NoiseTexture::get_width() const {
return size.x;
diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h
index d1705f4070..0d00ee154d 100644
--- a/modules/opensimplex/noise_texture.h
+++ b/modules/opensimplex/noise_texture.h
@@ -58,6 +58,7 @@ private:
Vector2i size;
bool seamless;
bool as_normalmap;
+ float bump_strength;
void _thread_done(const Ref<Image> &p_image);
static void _thread_function(void *p_ud);
@@ -69,6 +70,7 @@ private:
protected:
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const;
public:
void set_noise(Ref<OpenSimplexNoise> p_noise);
@@ -83,6 +85,9 @@ public:
void set_as_normalmap(bool p_seamless);
bool is_normalmap();
+ void set_bump_strength(float p_bump_strength);
+ float get_bump_strength();
+
int get_width() const;
int get_height() const;
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index cd5da75bab..b72144c679 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -138,7 +138,7 @@ if env['builtin_opus']:
opus_sources_silk = []
- if("opus_fixed_point" in env and env.opus_fixed_point == "yes"):
+ if env["platform"] in ["android", "iphone", "javascript"]:
env_opus.Append(CFLAGS=["-DFIXED_POINT"])
opus_sources_silk = [
"silk/fixed/LTP_analysis_filter_FIX.c",
@@ -220,6 +220,17 @@ if env['builtin_opus']:
]
env_opus.Append(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths])
+ if env["platform"] == "android":
+ if ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ elif ("android_arch" in env and env["android_arch"] == "arm64v8"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ elif env["platform"] == "iphone":
+ if ("arch" in env and env["arch"] == "arm"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ elif ("arch" in env and env["arch"] == "arm64"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+
env_thirdparty = env_opus.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index 75e8903ff8..20857572f3 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" category="Core" version="3.1">
+<class name="RegEx" inherits="Reference" category="Core" version="3.2">
<brief_description>
Class for searching text for patterns using regular expressions.
</brief_description>
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index 3d070d2786..9efec91bdc 100644
--- a/modules/regex/doc_classes/RegExMatch.xml
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegExMatch" inherits="Reference" category="Core" version="3.1">
+<class name="RegExMatch" inherits="Reference" category="Core" version="3.2">
<brief_description>
Contains the results of a regex search.
</brief_description>
diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
index e2281babf7..574ff1ff2a 100644
--- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.1">
+<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.2">
<brief_description>
OGG Vorbis audio stream driver.
</brief_description>
diff --git a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
index 018f4734ec..ade485e717 100644
--- a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.1">
+<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml
index e7c4727332..2bd8ad862f 100644
--- a/modules/theora/doc_classes/VideoStreamTheora.xml
+++ b/modules/theora/doc_classes/VideoStreamTheora.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index e69d9a0ae3..bd84a28c84 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -107,22 +107,31 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
}
}
- if (idxR == -1) {
- ERR_PRINT("TinyEXR: R channel not found.");
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
- }
+ if (exr_header.num_channels == 1) {
+ // Grayscale channel only.
+ idxR = 0;
+ idxG = 0;
+ idxB = 0;
+ idxA = 0;
+ } else {
+ // Assume RGB(A)
+ if (idxR == -1) {
+ ERR_PRINT("TinyEXR: R channel not found.");
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
- if (idxG == -1) {
- ERR_PRINT("TinyEXR: G channel not found.")
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
- }
+ if (idxG == -1) {
+ ERR_PRINT("TinyEXR: G channel not found.")
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
- if (idxB == -1) {
- ERR_PRINT("TinyEXR: B channel not found.")
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
+ if (idxB == -1) {
+ ERR_PRINT("TinyEXR: B channel not found.")
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
}
// EXR image data loaded, now parse it into Godot-friendly image data
diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml
index b98327c60d..0f967c993b 100644
--- a/modules/upnp/doc_classes/UPNP.xml
+++ b/modules/upnp/doc_classes/UPNP.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNP" inherits="Reference" category="Core" version="3.1">
+<class name="UPNP" inherits="Reference" category="Core" version="3.2">
<brief_description>
UPNP network functions.
</brief_description>
diff --git a/modules/upnp/doc_classes/UPNPDevice.xml b/modules/upnp/doc_classes/UPNPDevice.xml
index 9de8042daf..c9b695a651 100644
--- a/modules/upnp/doc_classes/UPNPDevice.xml
+++ b/modules/upnp/doc_classes/UPNPDevice.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNPDevice" inherits="Reference" category="Core" version="3.1">
+<class name="UPNPDevice" inherits="Reference" category="Core" version="3.2">
<brief_description>
UPNP device.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml
index 70849c5a80..f4a9bc68e6 100644
--- a/modules/visual_script/doc_classes/VisualScript.xml
+++ b/modules/visual_script/doc_classes/VisualScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScript" inherits="Script" category="Core" version="3.1">
+<class name="VisualScript" inherits="Script" category="Core" version="3.2">
<brief_description>
A script implemented in the Visual Script programming environment.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
index 5ec155fbc6..ce49cdf3a0 100644
--- a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node representing a constant from the base types.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 3a1d773058..dd14d60327 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node used to call built-in functions.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
index dc9044e9ed..32b5924cdc 100644
--- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a constant from a given class.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml
index a4a890ea8a..990e0ecb85 100644
--- a/modules/visual_script/doc_classes/VisualScriptComment.xml
+++ b/modules/visual_script/doc_classes/VisualScriptComment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node used to annotate the script.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml
index a7b1028c0c..94c075205d 100644
--- a/modules/visual_script/doc_classes/VisualScriptCondition.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which branches the flow.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml
index ed633c4135..0fc4e87db4 100644
--- a/modules/visual_script/doc_classes/VisualScriptConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a contant's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
index 14c44c6970..05fc3f318d 100644
--- a/modules/visual_script/doc_classes/VisualScriptConstructor.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which calls a base type constructor.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index ff3ed66e81..0ad4e7c1f5 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A scripted Visual Script node.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
index d3158df357..b933a25f1d 100644
--- a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
+++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which deconstructs a base type instance into its parts.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml
index fc49cfc07b..be4606b57c 100644
--- a/modules/visual_script/doc_classes/VisualScriptEditor.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.1">
+<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
index 4bb05525bd..3282269811 100644
--- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Emits a specified signal.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
index 93d7ce3516..3e52fb818c 100644
--- a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node returning a singleton from [@GlobalScope]
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml
index 343e83cb55..4760685bfb 100644
--- a/modules/visual_script/doc_classes/VisualScriptExpression.xml
+++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml
index ec8e955cf7..dc021196cd 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
index f6116cf539..e978437542 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
index c75dd0cdbc..a5e15b8da2 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.1">
+<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
index 9d43204f02..2d609ed262 100644
--- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
index 73c1f47e1a..16499e9ec9 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
index 652c29a9ac..06844ac4ae 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
index ab4c23012b..01887e0764 100644
--- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml
index 7090621bd7..496c24dee4 100644
--- a/modules/visual_script/doc_classes/VisualScriptIterator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Steps through items in a given input.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
index 5c8ee6453c..cd7286b59b 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a local variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
index f2e6c48907..f8fe2f4b6b 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Changes a local variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
index d456e880b7..733b48203d 100644
--- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Commonly used mathematical constants.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml
index 941a0cd91a..86bd469d5c 100644
--- a/modules/visual_script/doc_classes/VisualScriptNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.1">
+<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.2">
<brief_description>
A node which is part of a [VisualScript].
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml
index e60d50c977..d722477653 100644
--- a/modules/visual_script/doc_classes/VisualScriptOperator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml
index 5a2886ccac..b811252c42 100644
--- a/modules/visual_script/doc_classes/VisualScriptPreload.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Creates a new [Resource] or loads one from the filesystem.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
index 60cc8fdd4f..7f652b7012 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
index 8f29e9d152..ef9938c6a7 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
index f6300e03f0..2a5c56cf69 100644
--- a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
+++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml
index 0ca3e3b612..7daddc7639 100644
--- a/modules/visual_script/doc_classes/VisualScriptReturn.xml
+++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Exits a function and returns an optional value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
index 7704eaba04..8604a0f5eb 100644
--- a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Node reference.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
index 2c2af9262d..72a2faaa78 100644
--- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml
index 0731fc77e1..c87f77ea65 100644
--- a/modules/visual_script/doc_classes/VisualScriptSelect.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Chooses between two input values.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml
index 61a73e104c..42c75e56a6 100644
--- a/modules/visual_script/doc_classes/VisualScriptSelf.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Outputs a reference to the current instance.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml
index c71e068045..c26c72dd50 100644
--- a/modules/visual_script/doc_classes/VisualScriptSequence.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Executes a series of Sequence ports.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
index 46aeebab9c..712b4ed09b 100644
--- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
index a00811a29b..0053733b34 100644
--- a/modules/visual_script/doc_classes/VisualScriptSwitch.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Branches program flow based on a given input's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
index 0bdc4ce89d..85b3980e21 100644
--- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
+++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
index 06178a399d..27bf223aac 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
index 5969f25060..c55c72d55e 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Changes a variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml
index b9e7f6a553..b7ed56e7d2 100644
--- a/modules/visual_script/doc_classes/VisualScriptWhile.xml
+++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Conditional loop.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml
index c4698f746a..5aa0f76a55 100644
--- a/modules/visual_script/doc_classes/VisualScriptYield.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYield.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
index b67e4ab1b8..8e3b2aec1d 100644
--- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 2c89e5a35c..581809fec9 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -48,22 +48,12 @@ bool VisualScriptNode::is_breakpoint() const {
void VisualScriptNode::_notification(int p_what) {
if (p_what == NOTIFICATION_POSTINITIALIZE) {
- _update_input_ports();
- }
-}
-
-void VisualScriptNode::_update_input_ports() {
- default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize
- int port_count = get_input_value_port_count();
- for (int i = 0; i < port_count; i++) {
- Variant::Type expected = get_input_value_port_info(i).type;
- Variant::CallError ce;
- set_default_input_value(i, Variant::construct(expected, NULL, 0, ce, false));
+ validate_input_default_values();
}
}
void VisualScriptNode::ports_changed_notify() {
- _update_input_ports();
+ validate_input_default_values();
emit_signal("ports_changed");
}
@@ -92,8 +82,7 @@ void VisualScriptNode::_set_default_input_values(Array p_values) {
}
void VisualScriptNode::validate_input_default_values() {
-
- default_input_values.resize(get_input_value_port_count());
+ default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize
//actually validate on save
for (int i = 0; i < get_input_value_port_count(); i++) {
@@ -119,8 +108,10 @@ void VisualScriptNode::validate_input_default_values() {
Array VisualScriptNode::_get_default_input_values() const {
//validate on save, since on load there is little info about this
+ Array values = default_input_values;
+ values.resize(get_input_value_port_count());
- return default_input_values;
+ return values;
}
String VisualScriptNode::get_text() const {
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 0768ff61f7..0171b8e6f1 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -52,7 +52,6 @@ class VisualScriptNode : public Resource {
Array _get_default_input_values() const;
void validate_input_default_values();
- void _update_input_ports();
protected:
void _notification(int p_what);
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 9f2d1a49c0..0d379205e4 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -183,10 +183,10 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case TEXT_PRINTRAW:
case VAR_TO_STR:
case STR_TO_VAR:
- case VAR_TO_BYTES:
- case BYTES_TO_VAR:
case TYPE_EXISTS:
return 1;
+ case VAR_TO_BYTES:
+ case BYTES_TO_VAR:
case MATH_ATAN2:
case MATH_FMOD:
case MATH_FPOSMOD:
@@ -491,12 +491,18 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::STRING, "string");
} break;
case VAR_TO_BYTES: {
- return PropertyInfo(Variant::NIL, "var");
+ if (p_idx == 0)
+ return PropertyInfo(Variant::NIL, "var");
+ else
+ return PropertyInfo(Variant::BOOL, "full_objects");
} break;
case BYTES_TO_VAR: {
- return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes");
+ if (p_idx == 0)
+ return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes");
+ else
+ return PropertyInfo(Variant::BOOL, "allow_objects");
} break;
case COLORN: {
@@ -655,11 +661,15 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
} break;
case VAR_TO_BYTES: {
- t = Variant::POOL_BYTE_ARRAY;
+ if (p_idx == 0)
+ t = Variant::POOL_BYTE_ARRAY;
+ else
+ t = Variant::BOOL;
} break;
case BYTES_TO_VAR: {
-
+ if (p_idx == 1)
+ t = Variant::BOOL;
} break;
case COLORN: {
t = Variant::COLOR;
@@ -1192,9 +1202,16 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
} break;
case VisualScriptBuiltinFunc::VAR_TO_BYTES: {
+ if (p_inputs[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ return;
+ }
PoolByteArray barr;
int len;
- Error err = encode_variant(*p_inputs[0], NULL, len);
+ bool full_objects = *p_inputs[1];
+ Error err = encode_variant(*p_inputs[0], NULL, len, full_objects);
if (err) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
@@ -1206,7 +1223,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(*p_inputs[0], w.ptr(), len);
+ encode_variant(*p_inputs[0], w.ptr(), len, full_objects);
}
*r_return = barr;
} break;
@@ -1216,15 +1233,21 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::POOL_BYTE_ARRAY;
-
+ return;
+ }
+ if (p_inputs[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
return;
}
PoolByteArray varr = *p_inputs[0];
+ bool allow_objects = *p_inputs[1];
Variant ret;
{
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
if (err != OK) {
r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format.");
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 7dba8fd488..bb0435a679 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -129,9 +129,8 @@ StringName VisualScriptFunctionCall::_get_base_type() const {
int VisualScriptFunctionCall::get_input_value_port_count() const {
if (call_mode == CALL_MODE_BASIC_TYPE) {
-
- Vector<StringName> names = Variant::get_method_argument_names(basic_type, function);
- return names.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1;
+ Vector<Variant::Type> types = Variant::get_method_argument_types(basic_type, function);
+ return types.size() + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) + 1;
} else {
diff --git a/modules/webm/doc_classes/VideoStreamWebm.xml b/modules/webm/doc_classes/VideoStreamWebm.xml
index c02a7a8016..33dff0e93b 100644
--- a/modules/webm/doc_classes/VideoStreamWebm.xml
+++ b/modules/webm/doc_classes/VideoStreamWebm.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/webp/SCsub b/modules/webp/SCsub
index d215f19cef..fa3896c457 100644
--- a/modules/webp/SCsub
+++ b/modules/webp/SCsub
@@ -29,13 +29,11 @@ if env['builtin_libwebp']:
"dsp/cost.c",
"dsp/cost_mips32.c",
"dsp/cost_mips_dsp_r2.c",
+ "dsp/cost_neon.c",
"dsp/cost_sse2.c",
"dsp/cpu.c",
"dsp/dec.c",
"dsp/dec_clip_tables.c",
- "dsp/ssim.c",
- "dsp/ssim_sse2.c",
- "dsp/yuv_neon.c",
"dsp/dec_mips32.c",
"dsp/dec_mips_dsp_r2.c",
"dsp/dec_msa.c",
@@ -72,6 +70,8 @@ if env['builtin_libwebp']:
"dsp/rescaler_msa.c",
"dsp/rescaler_neon.c",
"dsp/rescaler_sse2.c",
+ "dsp/ssim.c",
+ "dsp/ssim_sse2.c",
"dsp/upsampling.c",
"dsp/upsampling_mips_dsp_r2.c",
"dsp/upsampling_msa.c",
@@ -81,6 +81,7 @@ if env['builtin_libwebp']:
"dsp/yuv.c",
"dsp/yuv_mips32.c",
"dsp/yuv_mips_dsp_r2.c",
+ "dsp/yuv_neon.c",
"dsp/yuv_sse2.c",
"dsp/yuv_sse41.c",
"enc/alpha_enc.c",
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub
index b67a836fe8..0345e533bc 100644
--- a/modules/websocket/SCsub
+++ b/modules/websocket/SCsub
@@ -9,85 +9,90 @@ env_lws = env_modules.Clone()
if env['builtin_libwebsockets'] and not env["platform"] == "javascript": # already builtin for javascript
thirdparty_dir = "#thirdparty/libwebsockets/"
- helper_dir = "win32helpers/"
+ helper_dir = "#thirdparty/libwebsockets/win32helpers/"
thirdparty_sources = [
- "core/alloc.c",
- "core/context.c",
- "core/libwebsockets.c",
- "core/output.c",
- "core/pollfd.c",
- "core/service.c",
-
- "event-libs/poll/poll.c",
-
- "misc/base64-decode.c",
- "misc/lejp.c",
- "misc/sha-1.c",
-
- "roles/h1/ops-h1.c",
- "roles/http/header.c",
- "roles/http/client/client.c",
- "roles/http/client/client-handshake.c",
- "roles/http/server/fops-zip.c",
- "roles/http/server/lejp-conf.c",
- "roles/http/server/parsers.c",
- "roles/http/server/server.c",
- "roles/listen/ops-listen.c",
- "roles/pipe/ops-pipe.c",
- "roles/raw/ops-raw.c",
-
- "roles/ws/client-ws.c",
- "roles/ws/client-parser-ws.c",
- "roles/ws/ops-ws.c",
- "roles/ws/server-ws.c",
-
- "tls/tls.c",
- "tls/tls-client.c",
- "tls/tls-server.c",
-
- "tls/mbedtls/wrapper/library/ssl_cert.c",
- "tls/mbedtls/wrapper/library/ssl_pkey.c",
- "tls/mbedtls/wrapper/library/ssl_stack.c",
- "tls/mbedtls/wrapper/library/ssl_methods.c",
- "tls/mbedtls/wrapper/library/ssl_lib.c",
- "tls/mbedtls/wrapper/library/ssl_x509.c",
- "tls/mbedtls/wrapper/platform/ssl_port.c",
- "tls/mbedtls/wrapper/platform/ssl_pm.c",
- "tls/mbedtls/lws-genhash.c",
- "tls/mbedtls/mbedtls-client.c",
- "tls/mbedtls/lws-genrsa.c",
- "tls/mbedtls/ssl.c",
- "tls/mbedtls/mbedtls-server.c"
+ "lib/core/adopt.c",
+ "lib/core/alloc.c",
+ "lib/core/connect.c",
+ "lib/core/context.c",
+ "lib/core/dummy-callback.c",
+ "lib/core/libwebsockets.c",
+ "lib/core/output.c",
+ "lib/core/pollfd.c",
+ "lib/core/service.c",
+
+ "lib/event-libs/poll/poll.c",
+
+ "lib/misc/base64-decode.c",
+ "lib/misc/lejp.c",
+ "lib/misc/sha-1.c",
+
+ "lib/roles/h1/ops-h1.c",
+ "lib/roles/http/header.c",
+ "lib/roles/http/client/client.c",
+ "lib/roles/http/client/client-handshake.c",
+ "lib/roles/http/server/fops-zip.c",
+ "lib/roles/http/server/lejp-conf.c",
+ "lib/roles/http/server/parsers.c",
+ "lib/roles/http/server/server.c",
+ "lib/roles/listen/ops-listen.c",
+ "lib/roles/pipe/ops-pipe.c",
+ "lib/roles/raw-skt/ops-raw-skt.c",
+ "lib/roles/raw-file/ops-raw-file.c",
+
+ "lib/roles/ws/client-ws.c",
+ "lib/roles/ws/client-parser-ws.c",
+ "lib/roles/ws/ops-ws.c",
+ "lib/roles/ws/server-ws.c",
+
+ "lib/tls/tls.c",
+ "lib/tls/tls-client.c",
+ "lib/tls/tls-server.c",
+
+ "lib/tls/mbedtls/wrapper/library/ssl_cert.c",
+ "lib/tls/mbedtls/wrapper/library/ssl_pkey.c",
+ "lib/tls/mbedtls/wrapper/library/ssl_stack.c",
+ "lib/tls/mbedtls/wrapper/library/ssl_methods.c",
+ "lib/tls/mbedtls/wrapper/library/ssl_lib.c",
+ "lib/tls/mbedtls/wrapper/library/ssl_x509.c",
+ "lib/tls/mbedtls/wrapper/platform/ssl_port.c",
+ "lib/tls/mbedtls/wrapper/platform/ssl_pm.c",
+ "lib/tls/mbedtls/lws-genhash.c",
+ "lib/tls/mbedtls/mbedtls-client.c",
+ "lib/tls/mbedtls/lws-genrsa.c",
+ "lib/tls/mbedtls/ssl.c",
+ "lib/tls/mbedtls/mbedtls-server.c"
]
if env["platform"] == "android": # Builtin getifaddrs
- thirdparty_sources += ["misc/getifaddrs.c"]
+ thirdparty_sources += ["lib/misc/getifaddrs.c"]
+
+ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
if env["platform"] == "windows" or env["platform"] == "uwp": # Winsock
- thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"]
+ thirdparty_sources += Glob(thirdparty_dir + "lib/plat/windows/*.c") + [helper_dir + src for src in ["getopt.c", "getopt_long.c", "gettimeofday.c"]]
else: # Unix socket
- thirdparty_sources += ["plat/lws-plat-unix.c"]
-
- thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
+ thirdparty_sources += Glob(thirdparty_dir + "lib/plat/unix/*.c")
- env_lws.Append(CPPPATH=[thirdparty_dir])
+ env_lws.Append(CPPPATH=[thirdparty_dir + 'include/'])
if env['builtin_mbedtls']:
mbedtls_includes = "#thirdparty/mbedtls/include"
env_lws.Prepend(CPPPATH=[mbedtls_includes])
- wrapper_includes = ["#thirdparty/libwebsockets/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]]
+ wrapper_includes = ["#thirdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]]
env_lws.Prepend(CPPPATH=wrapper_includes)
if env["platform"] == "windows" or env["platform"] == "uwp":
- env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir])
+ env_lws.Append(CPPPATH=[helper_dir])
if env["platform"] == "uwp":
env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"])
env_thirdparty = env_lws.Clone()
env_thirdparty.disable_warnings()
+ env_thirdparty.Append(CPPPATH=[thirdparty_dir + 'lib/'])
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
env_lws.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index ffb6d40e30..cb85fe864d 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.2">
<brief_description>
A WebSocket client implementation
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
index 1a841f85ed..139480c31f 100644
--- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
+++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
Base class for WebSocket server and client.
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml
index 5dda012899..3b3692dd87 100644
--- a/modules/websocket/doc_classes/WebSocketPeer.xml
+++ b/modules/websocket/doc_classes/WebSocketPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.1">
+<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.2">
<brief_description>
A class representing a specific WebSocket connection.
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 2932bf782a..4740bd6dcf 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.2">
<brief_description>
A WebSocket server implementation
</brief_description>
diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp
index 2dce0ed1f5..d09558ab22 100644
--- a/modules/websocket/lws_client.cpp
+++ b/modules/websocket/lws_client.cpp
@@ -34,7 +34,10 @@
#include "core/io/ip.h"
#include "core/io/stream_peer_ssl.h"
#include "core/project_settings.h"
-#include "tls/mbedtls/wrapper/include/openssl/ssl.h"
+#if defined(LWS_OPENSSL_SUPPORT)
+// Not openssl, just the mbedtls wrapper
+#include "openssl/ssl.h"
+#endif
Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) {
@@ -121,6 +124,7 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi
LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user;
switch (reason) {
+#if defined(LWS_OPENSSL_SUPPORT)
case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: {
PoolByteArray arr = StreamPeerSSL::get_project_cert_array();
if (arr.size() > 0)
@@ -128,7 +132,7 @@ int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, voi
else if (verify_ssl)
WARN_PRINTS("No CA cert specified in project settings, SSL will not work");
} break;
-
+#endif
case LWS_CALLBACK_CLIENT_ESTABLISHED:
peer->set_wsi(wsi, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
peer_data->peer_id = 0;
diff --git a/modules/websocket/packet_buffer.h b/modules/websocket/packet_buffer.h
index 47786a87a6..057fecfb56 100644
--- a/modules/websocket/packet_buffer.h
+++ b/modules/websocket/packet_buffer.h
@@ -59,7 +59,7 @@ public:
ERR_FAIL_V(ERR_OUT_OF_MEMORY);
}
#else
- ERR_FAIL_COND_V(p_payload && _payload.space_left() < p_size, ERR_OUT_OF_MEMORY);
+ ERR_FAIL_COND_V(p_payload && (uint32_t)_payload.space_left() < p_size, ERR_OUT_OF_MEMORY);
ERR_FAIL_COND_V(p_info && _packets.space_left() < 1, ERR_OUT_OF_MEMORY);
#endif