summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/shape_bullet.cpp2
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp14
-rw-r--r--modules/gdscript/gdscript_compiler.cpp26
-rw-r--r--modules/gdscript/gdscript_function.cpp2
-rw-r--r--modules/mono/editor/bindings_generator.cpp437
-rw-r--r--modules/mono/editor/bindings_generator.h8
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp6
8 files changed, 284 insertions, 213 deletions
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 77a583ad86..cf6bcb6c85 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -422,7 +422,7 @@ void ConcavePolygonShapeBullet::setup(Vector<Vector3> p_faces) {
meshShape = bulletnew(btBvhTriangleMeshShape(shapeInterface, useQuantizedAabbCompression));
- if (GLOBAL_DEF("physics/3d/smooth_trimesh_collision", false)) {
+ if (GLOBAL_GET("physics/3d/smooth_trimesh_collision")) {
btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap();
btGenerateInternalEdgeInfo(meshShape, triangleInfoMap);
}
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 58a788e255..8bf5fd1eda 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -796,7 +796,7 @@ void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
String GDScript::_get_debug_path() const {
if (is_built_in() && !get_name().is_empty()) {
- return get_name() + " (" + get_path().get_slice("::", 0) + ")";
+ return get_name() + " (" + get_path() + ")";
} else {
return get_path();
}
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 204dde4d6a..3ff8b2b91a 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1424,7 +1424,7 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
parser->push_warning(p_variable->initializer, GDScriptWarning::NARROWING_CONVERSION);
#endif
}
- if (p_variable->initializer->get_datatype().is_variant()) {
+ if (p_variable->initializer->get_datatype().is_variant() && !type.is_variant()) {
// TODO: Warn unsafe assign.
mark_node_unsafe(p_variable->initializer);
p_variable->use_conversion_assign = true;
@@ -2575,18 +2575,24 @@ void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node)
}
GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source) {
+ GDScriptParser::DataType type;
+
Ref<GDScriptParserRef> ref = get_parser_for(ScriptServer::get_global_class_path(p_class_name));
- Error err = ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
+ if (ref.is_null()) {
+ push_error(vformat(R"(Could not find script for class "%s".)", p_class_name), p_source);
+ type.type_source = GDScriptParser::DataType::UNDETECTED;
+ type.kind = GDScriptParser::DataType::VARIANT;
+ return type;
+ }
+ Error err = ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
if (err) {
push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source);
- GDScriptParser::DataType type;
type.type_source = GDScriptParser::DataType::UNDETECTED;
type.kind = GDScriptParser::DataType::VARIANT;
return type;
}
- GDScriptParser::DataType type;
type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
type.kind = GDScriptParser::DataType::CLASS;
type.builtin_type = Variant::OBJECT;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 108c988add..8190eecbc7 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -98,6 +98,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
case GDScriptParser::DataType::NATIVE: {
result.kind = GDScriptDataType::NATIVE;
result.native_type = p_datatype.native_type;
+ result.builtin_type = p_datatype.builtin_type;
} break;
case GDScriptParser::DataType::SCRIPT: {
result.kind = GDScriptDataType::SCRIPT;
@@ -132,11 +133,13 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.kind = GDScriptDataType::GDSCRIPT;
result.script_type = script.ptr();
result.native_type = script->get_instance_base_type();
+ result.builtin_type = p_datatype.builtin_type;
} else {
result.kind = GDScriptDataType::GDSCRIPT;
result.script_type_ref = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path);
result.script_type = result.script_type_ref.ptr();
result.native_type = p_datatype.native_type;
+ result.builtin_type = p_datatype.builtin_type;
}
}
} break;
@@ -291,16 +294,21 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// Try signals and methods (can be made callables).
{
- if (codegen.class_node->members_indices.has(identifier)) {
- const GDScriptParser::ClassNode::Member &member = codegen.class_node->members[codegen.class_node->members_indices[identifier]];
- if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
- // Get like it was a property.
- GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
- GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
-
- gen->write_get_named(temp, identifier, self);
- return temp;
+ // Search upwards through parent classes:
+ const GDScriptParser::ClassNode *base_class = codegen.class_node;
+ while (base_class != nullptr) {
+ if (base_class->has_member(identifier)) {
+ const GDScriptParser::ClassNode::Member &member = base_class->get_member(identifier);
+ if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
+ // Get like it was a property.
+ GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
+ GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
+
+ gen->write_get_named(temp, identifier, self);
+ return temp;
+ }
}
+ base_class = base_class->base_type.class_type;
}
// Try in native base.
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 9424de9d22..3d708955ed 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -95,7 +95,7 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
int oc = 0;
Map<StringName, _GDFKC> sdmap;
for (const StackDebug &sd : stack_debug) {
- if (sd.line > p_line) {
+ if (sd.line >= p_line) {
break;
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 07128770b7..272283432d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -278,12 +278,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} 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 ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) {
const int tag_end = tag.find(" ");
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
- Vector<String> link_target_parts = link_target.split(".");
+ const Vector<String> link_target_parts = link_target.split(".");
if (link_target_parts.size() <= 0 || link_target_parts.size() > 2) {
ERR_PRINT("Invalid reference format: '" + tag + "'.");
@@ -311,201 +311,18 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
}
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("\"/>");
- }
- }
+ _append_xml_method(xml_output, target_itype, target_cname, link_target, link_target_parts);
} 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("\"/>");
- }
- }
+ _append_xml_member(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "signal") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from signal 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 SignalInterface *target_isignal = target_itype->find_signal_by_name(target_cname);
-
- if (target_isignal) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_isignal->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve signal reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
+ _append_xml_signal(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "enum") {
- const 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_PRINT("Cannot resolve enum reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
+ _append_xml_enum(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "constant") {
- 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) {
- const 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 = nullptr;
-
- for (const EnumInterface &ienum : global_enums) {
- target_ienum = &ienum;
- 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_PRINT("Cannot resolve global constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- } else {
- const 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 = nullptr;
-
- for (const EnumInterface &ienum : target_itype->enums) {
- target_ienum = &ienum;
- 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_PRINT("Cannot resolve constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- }
+ _append_xml_constant(xml_output, target_itype, target_cname, link_target, link_target_parts);
+ } else if (link_tag == "theme_item") {
+ // We do not declare theme_items in any way in C#, so there is nothing to reference
+ _append_xml_undeclared(xml_output, link_target);
}
pos = brk_end + 1;
@@ -670,6 +487,240 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
return xml_output.as_string();
}
+void BindingsGenerator::_append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Cannot resolve @GlobalScope method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ if (p_target_cname == "_init") {
+ // The _init method is not declared in C#, reference the constructor instead
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append("()\"/>");
+ } else {
+ const MethodInterface *target_imethod = p_target_itype->find_method_by_name(p_target_cname);
+
+ if (target_imethod) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_imethod->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve method reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target.find("/") >= 0) {
+ // Properties with '/' (slash) in the name are not declared in C#, so there is nothing to reference.
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const TypeInterface *current_itype = p_target_itype;
+ const PropertyInterface *target_iprop = nullptr;
+
+ while (target_iprop == nullptr && current_itype != nullptr) {
+ target_iprop = current_itype->find_property_by_name(p_target_cname);
+ if (target_iprop == nullptr) {
+ current_itype = _get_type_or_null(TypeReference(current_itype->base_name));
+ }
+ }
+
+ if (target_iprop) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(current_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iprop->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve member reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const SignalInterface *target_isignal = p_target_itype->find_signal_by_name(p_target_cname);
+
+ if (target_isignal) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_isignal->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve signal reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ const StringName search_cname = !p_target_itype ? p_target_cname : StringName(p_target_itype->name + "." + (String)p_target_cname);
+
+ const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
+
+ if (!enum_match && search_cname != p_target_cname) {
+ enum_match = enum_types.find(p_target_cname);
+ }
+
+ if (enum_match) {
+ const TypeInterface &target_enum_itype = enum_match->value();
+
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve enum reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+}
+
+void BindingsGenerator::_append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ // Search in @GlobalScope as a last resort if no class was specified
+ if (p_link_target_parts.size() == 1) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ return;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ // Try to find the constant in the current class
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, p_target_itype->constants);
+
+ if (target_iconst) {
+ // Found constant in current class
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as enum constant in the current class
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : p_target_itype->enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else if (p_link_target_parts.size() == 1) {
+ // Also search in @GlobalScope as a last resort if no class was specified
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else {
+ ERR_PRINT("Cannot resolve constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target) {
+ // Try to find as a global constant
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, global_constants);
+
+ if (target_iconst) {
+ // Found global constant
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as global enum constant
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : global_enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve global constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target) {
+ p_xml_output.append("<c>");
+ p_xml_output.append(p_link_target);
+ p_xml_output.append("</c>");
+}
+
int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
CRASH_COND(p_ienum.constants.is_empty());
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 5460f018f0..f601ffde2b 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -658,6 +658,14 @@ class BindingsGenerator {
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
+ void _append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target);
+ void _append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target);
+
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/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index bc3c0d9265..0bc42b104c 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -353,10 +353,8 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
ch += CH_RESERVED_MAX - 1;
}
- Map<int, Ref<ConnectedPeer>>::Element *E = nullptr;
-
if (target_peer > 0) {
- E = peer_map.find(target_peer);
+ Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(target_peer);
ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + ".");
ERR_FAIL_COND_V_MSG(E->value()->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
@@ -372,7 +370,7 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
continue;
}
- ERR_CONTINUE_MSG(F.value->channels.size() <= ch, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
+ ERR_CONTINUE_MSG(F.value->channels.size() <= ch, vformat("Unable to send packet on channel %d, max channels: %d", ch, F.value->channels.size()));
ERR_CONTINUE(F.value->channels[ch].is_null());
F.value->channels[ch]->put_packet(p_buffer, p_buffer_size);
}