summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bcdec/image_decompress_bcdec.cpp35
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp15
-rw-r--r--modules/gdscript/gdscript_editor.cpp14
-rw-r--r--modules/mono/editor/bindings_generator.cpp69
-rw-r--r--modules/mono/editor/bindings_generator.h3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs68
6 files changed, 167 insertions, 37 deletions
diff --git a/modules/bcdec/image_decompress_bcdec.cpp b/modules/bcdec/image_decompress_bcdec.cpp
index 30ca1fccb3..c76470e3cc 100644
--- a/modules/bcdec/image_decompress_bcdec.cpp
+++ b/modules/bcdec/image_decompress_bcdec.cpp
@@ -92,8 +92,20 @@ static void decompress_image(BCdecFormat format, const void *src, void *dst, con
void image_decompress_bcdec(Image *p_image) {
uint64_t start_time = OS::get_singleton()->get_ticks_msec();
- int w = p_image->get_width();
- int h = p_image->get_height();
+ int width = p_image->get_width();
+ int height = p_image->get_height();
+
+ // Compressed images' dimensions should be padded to the upper multiple of 4.
+ // If they aren't, they need to be realigned (the actual data is correctly padded though).
+ if (width % 4 != 0 || height % 4 != 0) {
+ int new_width = width + (4 - (width % 4));
+ int new_height = height + (4 - (height % 4));
+
+ print_verbose(vformat("Compressed image's dimensions are not multiples of 4 (%dx%d), aligning to (%dx%d)", width, height, new_width, new_height));
+
+ width = new_width;
+ height = new_height;
+ }
Image::Format source_format = p_image->get_format();
Image::Format target_format = Image::FORMAT_MAX;
@@ -148,30 +160,27 @@ void image_decompress_bcdec(Image *p_image) {
}
int mm_count = p_image->get_mipmap_count();
- int64_t target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
+ int64_t target_size = Image::get_image_data_size(width, height, target_format, p_image->has_mipmaps());
+ // Decompressed data.
Vector<uint8_t> data;
data.resize(target_size);
+ uint8_t *wb = data.ptrw();
+ // Source data.
const uint8_t *rb = p_image->get_data().ptr();
- uint8_t *wb = data.ptrw();
// Decompress mipmaps.
for (int i = 0; i <= mm_count; i++) {
- int64_t src_ofs = 0, mipmap_size = 0;
int mipmap_w = 0, mipmap_h = 0;
- p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h);
-
- int64_t dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i);
+ int64_t src_ofs = Image::get_image_mipmap_offset_and_dimensions(width, height, source_format, i, mipmap_w, mipmap_h);
+ int64_t dst_ofs = Image::get_image_mipmap_offset(width, height, target_format, i);
decompress_image(bcdec_format, rb + src_ofs, wb + dst_ofs, mipmap_w, mipmap_h);
-
- w >>= 1;
- h >>= 1;
}
- p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
+ p_image->set_data(width, height, p_image->has_mipmaps(), target_format, data);
- // Swap channels if necessary.
+ // Swap channels if the format is using a channel swizzle.
if (source_format == Image::FORMAT_DXT5_RA_AS_RG) {
p_image->convert_ra_rgba8_to_rg();
}
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 7f0d5005cb..4a3a3a4b61 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -148,6 +148,15 @@ static GDScriptParser::DataType make_enum_type(const StringName &p_enum_name, co
return type;
}
+static GDScriptParser::DataType make_class_enum_type(const StringName &p_enum_name, GDScriptParser::ClassNode *p_class, const String &p_script_path, bool p_meta = true) {
+ GDScriptParser::DataType type = make_enum_type(p_enum_name, p_class->fqcn, p_meta);
+
+ type.class_type = p_class;
+ type.script_path = p_script_path;
+
+ return type;
+}
+
static GDScriptParser::DataType make_native_enum_type(const StringName &p_enum_name, const StringName &p_native_class, bool p_meta = true) {
// Find out which base class declared the enum, so the name is always the same even when coming from other contexts.
StringName native_base = p_native_class;
@@ -1101,7 +1110,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
check_class_member_name_conflict(p_class, member.m_enum->identifier->name, member.m_enum);
member.m_enum->set_datatype(resolving_datatype);
- GDScriptParser::DataType enum_type = make_enum_type(member.m_enum->identifier->name, p_class->fqcn, true);
+ GDScriptParser::DataType enum_type = make_class_enum_type(member.m_enum->identifier->name, p_class, parser->script_path, true);
const GDScriptParser::EnumNode *prev_enum = current_enum;
current_enum = member.m_enum;
@@ -1194,7 +1203,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
// Also update the original references.
member.enum_value.parent_enum->values.set(member.enum_value.index, member.enum_value);
- member.enum_value.identifier->set_datatype(make_enum_type(UNNAMED_ENUM, p_class->fqcn, false));
+ member.enum_value.identifier->set_datatype(make_class_enum_type(UNNAMED_ENUM, p_class, parser->script_path, false));
} break;
case GDScriptParser::ClassNode::Member::CLASS:
check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
@@ -4249,7 +4258,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
const GDScriptParser::EnumNode::Value &element = current_enum->values[i];
if (element.identifier->name == p_identifier->name) {
StringName enum_name = current_enum->identifier ? current_enum->identifier->name : UNNAMED_ENUM;
- GDScriptParser::DataType type = make_enum_type(enum_name, parser->current_class->fqcn, false);
+ GDScriptParser::DataType type = make_class_enum_type(enum_name, parser->current_class, parser->script_path, false);
if (element.parent_enum->identifier) {
type.enum_type = element.parent_enum->identifier->name;
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 0fd891aa80..3de1decc18 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -3782,7 +3782,19 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
} break;
case GDScriptParser::DataType::ENUM: {
- if (base_type.enum_values.has(p_symbol)) {
+ if (base_type.class_type && base_type.class_type->has_member(base_type.enum_type)) {
+ GDScriptParser::EnumNode *base_enum = base_type.class_type->get_member(base_type.enum_type).m_enum;
+ for (const GDScriptParser::EnumNode::Value &value : base_enum->values) {
+ if (value.identifier && value.identifier->name == p_symbol) {
+ r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION;
+ r_result.class_path = base_type.script_path;
+ r_result.location = value.line;
+ Error err = OK;
+ r_result.script = GDScriptCache::get_shallow_script(r_result.class_path, err);
+ return err;
+ }
+ }
+ } else if (base_type.enum_values.has(p_symbol)) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT;
r_result.class_name = String(base_type.native_type).get_slicec('.', 0);
r_result.class_member = p_symbol;
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 89655e0b56..946e997c1b 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -2348,9 +2348,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
int method_bind_count = 0;
for (const MethodInterface &imethod : itype.methods) {
- Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output);
+ Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output, false);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
+ if (imethod.is_internal) {
+ // No need to generate span overloads for internal methods.
+ continue;
+ }
+
+ method_err = _generate_cs_method(itype, imethod, method_bind_count, output, true);
+ ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
+ "Failed to generate span overload method '" + imethod.name + "' for class '" + itype.name + "'.");
}
// Signals
@@ -2776,7 +2784,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
return OK;
}
-Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) {
+Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span) {
const TypeInterface *return_type = _get_type_or_singleton_or_null(p_imethod.return_type);
ERR_FAIL_NULL_V_MSG(return_type, ERR_BUG, "Return type '" + p_imethod.return_type.cname + "' was not found.");
@@ -2789,6 +2797,35 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
"' from the editor API. Core API cannot have dependencies on the editor API.");
}
+ if (p_imethod.is_virtual && p_use_span) {
+ return OK;
+ }
+
+ bool has_span_argument = false;
+
+ if (p_use_span) {
+ if (p_imethod.is_vararg) {
+ has_span_argument = true;
+ } else {
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
+ const TypeInterface *arg_type = _get_type_or_singleton_or_null(iarg.type);
+ ERR_FAIL_NULL_V_MSG(arg_type, ERR_BUG, "Argument type '" + iarg.type.cname + "' was not found.");
+
+ if (arg_type->is_span_compatible) {
+ has_span_argument = true;
+ break;
+ }
+ }
+ }
+
+ if (has_span_argument) {
+ // Span overloads use the same method bind as the array overloads.
+ // Since both overloads are generated one after the other, we can decrease the count here
+ // to ensure the span overload uses the same method bind.
+ p_method_bind_count--;
+ }
+ }
+
String method_bind_field = CS_STATIC_FIELD_METHOD_BIND_PREFIX + itos(p_method_bind_count);
String arguments_sig;
@@ -2835,6 +2872,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
+ bool use_span_for_arg = p_use_span && arg_type->is_span_compatible;
+
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
@@ -2846,7 +2885,11 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += "Nullable<";
}
- arguments_sig += arg_cs_type;
+ if (use_span_for_arg) {
+ arguments_sig += arg_type->c_type_in;
+ } else {
+ arguments_sig += arg_cs_type;
+ }
if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "> ";
@@ -2856,7 +2899,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += iarg.name;
- if (!p_imethod.is_compat && iarg.default_argument.size()) {
+ if (!p_use_span && !p_imethod.is_compat && iarg.default_argument.size()) {
if (iarg.def_param_mode != ArgumentInterface::CONSTANT) {
arguments_sig += " = null";
} else {
@@ -2867,7 +2910,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
icall_params += ", ";
- if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
+ if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT && !use_span_for_arg) {
// The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
// Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
String arg_or_defval_local = iarg.name;
@@ -2927,6 +2970,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe;
}
+ if (p_use_span && !has_span_argument) {
+ return OK;
+ }
+
// Collect caller name for MethodBind
if (p_imethod.is_vararg) {
icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue";
@@ -2934,7 +2981,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
- if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
+ if (!p_imethod.is_virtual && !p_imethod.requires_object_call && !p_use_span) {
p_output << MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
<< INDENT1 "private static readonly IntPtr " << method_bind_field << " = ";
@@ -4734,13 +4781,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "VarArg";
itype.cname = itype.name;
- itype.proxy_name = "Variant[]";
+ itype.proxy_name = "ReadOnlySpan<Variant>";
itype.cs_type = "params Variant[]";
- itype.cs_in_expr = "%0 ?? Array.Empty<Variant>()";
+ itype.cs_in_expr = "%0";
// c_type, c_in and c_arg_in are hard-coded in the generator.
// c_out and c_type_out are not applicable to VarArg.
itype.c_arg_in = "&%s_in";
- itype.c_type_in = "Variant[]";
+ itype.c_type_in = "ReadOnlySpan<Variant>";
+ itype.is_span_compatible = true;
builtin_types.insert(itype.cname, itype);
#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \
@@ -4754,9 +4802,10 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \
itype.c_arg_in = "&%s_in"; \
itype.c_type = #m_managed_type; \
- itype.c_type_in = itype.proxy_name; \
+ itype.c_type_in = "ReadOnlySpan<" #m_proxy_t ">"; \
itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \
+ itype.is_span_compatible = true; \
builtin_types.insert(itype.name, itype); \
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 556d287af4..1670aca4b3 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -265,6 +265,7 @@ class BindingsGenerator {
bool is_singleton = false;
bool is_singleton_instance = false;
bool is_ref_counted = false;
+ bool is_span_compatible = false;
/**
* Class is a singleton, but can't be declared as a static class as that would
@@ -840,7 +841,7 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
- Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
+ Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span);
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 15b7ce7c73..fc68b11932 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -394,7 +394,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
+ public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
+ {
+ return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan<byte>)p_array);
+ }
+
+ public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(ReadOnlySpan<byte> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_byte_array();
@@ -417,7 +422,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
+ public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
+ {
+ return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan<int>)p_array);
+ }
+
+ public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(ReadOnlySpan<int> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int32_array();
@@ -440,7 +450,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
+ public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
+ {
+ return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan<long>)p_array);
+ }
+
+ public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(ReadOnlySpan<long> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int64_array();
@@ -463,8 +478,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(Span<float> p_array)
+ {
+ return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan<float>)p_array);
+ }
+
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(
- Span<float> p_array)
+ ReadOnlySpan<float> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float32_array();
@@ -487,8 +507,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(Span<double> p_array)
+ {
+ return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan<double>)p_array);
+ }
+
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(
- Span<double> p_array)
+ ReadOnlySpan<double> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float64_array();
@@ -512,6 +537,11 @@ namespace Godot.NativeInterop
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array)
{
+ return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan<string>)p_array);
+ }
+
+ public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(ReadOnlySpan<string> p_array)
+ {
godot_packed_string_array dest = new godot_packed_string_array();
if (p_array.IsEmpty)
@@ -544,8 +574,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(Span<Vector2> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan<Vector2>)p_array);
+ }
+
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(
- Span<Vector2> p_array)
+ ReadOnlySpan<Vector2> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector2_array();
@@ -568,8 +603,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(Span<Vector3> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan<Vector3>)p_array);
+ }
+
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(
- Span<Vector3> p_array)
+ ReadOnlySpan<Vector3> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector3_array();
@@ -592,8 +632,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(Span<Vector4> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan<Vector4>)p_array);
+ }
+
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(
- Span<Vector4> p_array)
+ ReadOnlySpan<Vector4> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector4_array();
@@ -616,7 +661,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
+ public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
+ {
+ return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan<Color>)p_array);
+ }
+
+ public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(ReadOnlySpan<Color> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_color_array();