Sync C# Array with Core

- Add `AddRange` method.
- Add `Fill` method.
- Add `Max` and `Min` methods.
- Add `PickRandom` method.
- Add `Reverse` method.
- Add `RecursiveEqual` method.
- Add `Sort` method.
- Add `Slice` and `GetSliceRange` methods.
- Add `IndexOf` overload that takes an index parameter.
- Add `LastIndexOf` method.
- Add `BinarySearch` method.
- Add/update documentation.
This commit is contained in:
Raul Santos 2023-01-20 20:18:56 +01:00
parent d01ac9c736
commit 54f8fb010c
No known key found for this signature in database
GPG key ID: B532473AE3A803E4
6 changed files with 1008 additions and 49 deletions

View file

@ -612,14 +612,14 @@ void Array::shuffle() {
} }
} }
int Array::bsearch(const Variant &p_value, bool p_before) { int Array::bsearch(const Variant &p_value, bool p_before) const {
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1); ERR_FAIL_COND_V(!_p->typed.validate(value, "binary search"), -1);
SearchArray<Variant, _ArrayVariantSort> avs; SearchArray<Variant, _ArrayVariantSort> avs;
return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before); return avs.bisect(_p->array.ptrw(), _p->array.size(), value, p_before);
} }
int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) { int Array::bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before) const {
Variant value = p_value; Variant value = p_value;
ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1); ERR_FAIL_COND_V(!_p->typed.validate(value, "custom binary search"), -1);

View file

@ -84,8 +84,8 @@ public:
void sort(); void sort();
void sort_custom(const Callable &p_callable); void sort_custom(const Callable &p_callable);
void shuffle(); void shuffle();
int bsearch(const Variant &p_value, bool p_before = true); int bsearch(const Variant &p_value, bool p_before = true) const;
int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true); int bsearch_custom(const Variant &p_value, const Callable &p_callable, bool p_before = true) const;
void reverse(); void reverse();
int find(const Variant &p_value, int p_from = 0) const; int find(const Variant &p_value, int p_from = 0) const;

View file

@ -207,7 +207,7 @@
[b]Note:[/b] Calling this function is not the same as writing [code]array[-1][/code]. If the array is empty, accessing by index will pause project execution when running from the editor. [b]Note:[/b] Calling this function is not the same as writing [code]array[-1][/code]. If the array is empty, accessing by index will pause project execution when running from the editor.
</description> </description>
</method> </method>
<method name="bsearch"> <method name="bsearch" qualifiers="const">
<return type="int" /> <return type="int" />
<param index="0" name="value" type="Variant" /> <param index="0" name="value" type="Variant" />
<param index="1" name="before" type="bool" default="true" /> <param index="1" name="before" type="bool" default="true" />
@ -216,7 +216,7 @@
[b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior. [b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
</description> </description>
</method> </method>
<method name="bsearch_custom"> <method name="bsearch_custom" qualifiers="const">
<return type="int" /> <return type="int" />
<param index="0" name="value" type="Variant" /> <param index="0" name="value" type="Variant" />
<param index="1" name="func" type="Callable" /> <param index="1" name="func" type="Callable" />
@ -269,7 +269,7 @@
array.fill(0) # Initialize the 10 elements to 0. array.fill(0) # Initialize the 10 elements to 0.
[/gdscript] [/gdscript]
[csharp] [csharp]
var array = new Godot.Collections.Array{}; var array = new Godot.Collections.Array();
array.Resize(10); array.Resize(10);
array.Fill(0); // Initialize the 10 elements to 0. array.Fill(0); // Initialize the 10 elements to 0.
[/csharp] [/csharp]
@ -340,7 +340,7 @@
print(["inside", 7].has("7")) # False print(["inside", 7].has("7")) # False
[/gdscript] [/gdscript]
[csharp] [csharp]
var arr = new Godot.Collections.Array{"inside", 7}; var arr = new Godot.Collections.Array { "inside", 7 };
// has is renamed to Contains // has is renamed to Contains
GD.Print(arr.Contains("inside")); // True GD.Print(arr.Contains("inside")); // True
GD.Print(arr.Contains("outside")); // False GD.Print(arr.Contains("outside")); // False
@ -357,7 +357,7 @@
[/gdscript] [/gdscript]
[csharp] [csharp]
// As there is no "in" keyword in C#, you have to use Contains // As there is no "in" keyword in C#, you have to use Contains
var array = new Godot.Collections.Array{2, 4, 6, 8}; var array = new Godot.Collections.Array { 2, 4, 6, 8 };
if (array.Contains(2)) if (array.Contains(2))
{ {
GD.Print("Contains!"); GD.Print("Contains!");
@ -440,10 +440,16 @@
<return type="Variant" /> <return type="Variant" />
<description> <description>
Returns a random value from the target array. Returns a random value from the target array.
[codeblock] [codeblocks]
[gdscript]
var array: Array[int] = [1, 2, 3, 4] var array: Array[int] = [1, 2, 3, 4]
print(array.pick_random()) # Prints either of the four numbers. print(array.pick_random()) # Prints either of the four numbers.
[/codeblock] [/gdscript]
[csharp]
var array = new Godot.Collections.Array { 1, 2, 3, 4 };
GD.Print(array.PickRandom()); // Prints either of the four numbers.
[/csharp]
[/codeblocks]
</description> </description>
</method> </method>
<method name="pop_at"> <method name="pop_at">
@ -562,7 +568,7 @@
Returns the slice of the [Array], from [param begin] (inclusive) to [param end] (exclusive), as a new [Array]. Returns the slice of the [Array], from [param begin] (inclusive) to [param end] (exclusive), as a new [Array].
The absolute value of [param begin] and [param end] will be clamped to the array size, so the default value for [param end] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]). The absolute value of [param begin] and [param end] will be clamped to the array size, so the default value for [param end] makes it slice to the size of the array by default (i.e. [code]arr.slice(1)[/code] is a shorthand for [code]arr.slice(1, arr.size())[/code]).
If either [param begin] or [param end] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]). If either [param begin] or [param end] are negative, they will be relative to the end of the array (i.e. [code]arr.slice(0, -2)[/code] is a shorthand for [code]arr.slice(0, arr.size() - 2)[/code]).
If specified, [param step] is the relative index between source elements. It can be negative, then [param begin] must be higher than [param end]. For example, [code][0, 1, 2, 3, 4, 5].slice(5, 1, -2)[/code] returns [code][5, 3][/code]). If specified, [param step] is the relative index between source elements. It can be negative, then [param begin] must be higher than [param end]. For example, [code][0, 1, 2, 3, 4, 5].slice(5, 1, -2)[/code] returns [code][5, 3][/code].
If [param deep] is true, each element will be copied by value rather than by reference. If [param deep] is true, each element will be copied by value rather than by reference.
</description> </description>
</method> </method>
@ -579,7 +585,9 @@
print(strings) # Prints [string1, string10, string11, string2] print(strings) # Prints [string1, string10, string11, string2]
[/gdscript] [/gdscript]
[csharp] [csharp]
// There is no sort support for Godot.Collections.Array var strings = new Godot.Collections.Array { "string1", "string2", "string10", "string11" };
strings.Sort();
GD.Print(strings); // Prints [string1, string10, string11, string2]
[/csharp] [/csharp]
[/codeblocks] [/codeblocks]
To perform natural order sorting, you can use [method sort_custom] with [method String.naturalnocasecmp_to] as follows: To perform natural order sorting, you can use [method sort_custom] with [method String.naturalnocasecmp_to] as follows:

File diff suppressed because it is too large Load diff

View file

@ -365,21 +365,44 @@ namespace Godot.NativeInterop
public static partial int godotsharp_array_add(ref godot_array p_self, in godot_variant p_item); public static partial int godotsharp_array_add(ref godot_array p_self, in godot_variant p_item);
public static partial int godotsharp_array_add_range(ref godot_array p_self, in godot_array p_collection);
public static partial int godotsharp_array_binary_search(ref godot_array p_self, int p_index, int p_count, in godot_variant p_value);
public static partial void public static partial void
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest); godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
public static partial int godotsharp_array_index_of(ref godot_array p_self, in godot_variant p_item); public static partial void godotsharp_array_fill(ref godot_array p_self, in godot_variant p_value);
public static partial int godotsharp_array_index_of(ref godot_array p_self, in godot_variant p_item, int p_index = 0);
public static partial void godotsharp_array_insert(ref godot_array p_self, int p_index, in godot_variant p_item); public static partial void godotsharp_array_insert(ref godot_array p_self, int p_index, in godot_variant p_item);
public static partial int godotsharp_array_last_index_of(ref godot_array p_self, in godot_variant p_item, int p_index);
public static partial void godotsharp_array_make_read_only(ref godot_array p_self);
public static partial void godotsharp_array_max(ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_min(ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_pick_random(ref godot_array p_self, out godot_variant r_value);
public static partial godot_bool godotsharp_array_recursive_equal(ref godot_array p_self, in godot_array p_other);
public static partial void godotsharp_array_remove_at(ref godot_array p_self, int p_index); public static partial void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
public static partial Error godotsharp_array_resize(ref godot_array p_self, int p_new_size); public static partial Error godotsharp_array_resize(ref godot_array p_self, int p_new_size);
public static partial void godotsharp_array_make_read_only(ref godot_array p_self); public static partial void godotsharp_array_reverse(ref godot_array p_self);
public static partial void godotsharp_array_shuffle(ref godot_array p_self); public static partial void godotsharp_array_shuffle(ref godot_array p_self);
public static partial void godotsharp_array_slice(ref godot_array p_self, int p_start, int p_end,
int p_step, godot_bool p_deep, out godot_array r_dest);
public static partial void godotsharp_array_sort(ref godot_array p_self);
public static partial void godotsharp_array_to_string(ref godot_array p_self, out godot_string r_str); public static partial void godotsharp_array_to_string(ref godot_array p_self, out godot_string r_str);
// Dictionary // Dictionary

View file

@ -992,18 +992,78 @@ int32_t godotsharp_array_add(Array *p_self, const Variant *p_item) {
return p_self->size(); return p_self->size();
} }
int32_t godotsharp_array_add_range(Array *p_self, const Array *p_collection) {
p_self->append_array(*p_collection);
return p_self->size();
}
int32_t godotsharp_array_binary_search(const Array *p_self, int32_t p_index, int32_t p_length, const Variant *p_value) {
ERR_FAIL_COND_V(p_index < 0, -1);
ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V(p_self->size() - p_index < p_length, -1);
const Variant &value = *p_value;
const Array &array = *p_self;
int lo = p_index;
int hi = p_index + p_length - 1;
while (lo <= hi) {
int mid = lo + ((hi - lo) >> 1);
const Variant &mid_item = array[mid];
if (mid_item == value) {
return mid;
}
if (mid_item < value) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return ~lo;
}
void godotsharp_array_duplicate(const Array *p_self, bool p_deep, Array *r_dest) { void godotsharp_array_duplicate(const Array *p_self, bool p_deep, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->duplicate(p_deep))); memnew_placement(r_dest, Array(p_self->duplicate(p_deep)));
} }
int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item) { void godotsharp_array_fill(Array *p_self, const Variant *p_value) {
return p_self->find(*p_item); p_self->fill(*p_value);
}
int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item, int32_t p_index = 0) {
return p_self->find(*p_item, p_index);
} }
void godotsharp_array_insert(Array *p_self, int32_t p_index, const Variant *p_item) { void godotsharp_array_insert(Array *p_self, int32_t p_index, const Variant *p_item) {
p_self->insert(p_index, *p_item); p_self->insert(p_index, *p_item);
} }
int32_t godotsharp_array_last_index_of(const Array *p_self, const Variant *p_item, int32_t p_index) {
return p_self->rfind(*p_item, p_index);
}
void godotsharp_array_make_read_only(Array *p_self) {
p_self->make_read_only();
}
void godotsharp_array_max(const Array *p_self, Variant *r_value) {
*r_value = p_self->max();
}
void godotsharp_array_min(const Array *p_self, Variant *r_value) {
*r_value = p_self->min();
}
void godotsharp_array_pick_random(const Array *p_self, Variant *r_value) {
*r_value = p_self->pick_random();
}
bool godotsharp_array_recursive_equal(const Array *p_self, const Array *p_other) {
return p_self->recursive_equal(*p_other, 0);
}
void godotsharp_array_remove_at(Array *p_self, int32_t p_index) { void godotsharp_array_remove_at(Array *p_self, int32_t p_index) {
p_self->remove_at(p_index); p_self->remove_at(p_index);
} }
@ -1012,14 +1072,22 @@ int32_t godotsharp_array_resize(Array *p_self, int32_t p_new_size) {
return (int32_t)p_self->resize(p_new_size); return (int32_t)p_self->resize(p_new_size);
} }
void godotsharp_array_make_read_only(Array *p_self) { void godotsharp_array_reverse(Array *p_self) {
p_self->make_read_only(); p_self->reverse();
} }
void godotsharp_array_shuffle(Array *p_self) { void godotsharp_array_shuffle(Array *p_self) {
p_self->shuffle(); p_self->shuffle();
} }
void godotsharp_array_slice(Array *p_self, int32_t p_start, int32_t p_end, int32_t p_step, bool p_deep, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->slice(p_start, p_end, p_step, p_deep)));
}
void godotsharp_array_sort(Array *p_self) {
p_self->sort();
}
void godotsharp_array_to_string(const Array *p_self, String *r_str) { void godotsharp_array_to_string(const Array *p_self, String *r_str) {
*r_str = Variant(*p_self).operator String(); *r_str = Variant(*p_self).operator String();
} }
@ -1442,13 +1510,24 @@ static const void *unmanaged_callbacks[]{
(void *)godotsharp_array_destroy, (void *)godotsharp_array_destroy,
(void *)godotsharp_dictionary_destroy, (void *)godotsharp_dictionary_destroy,
(void *)godotsharp_array_add, (void *)godotsharp_array_add,
(void *)godotsharp_array_add_range,
(void *)godotsharp_array_binary_search,
(void *)godotsharp_array_duplicate, (void *)godotsharp_array_duplicate,
(void *)godotsharp_array_fill,
(void *)godotsharp_array_index_of, (void *)godotsharp_array_index_of,
(void *)godotsharp_array_insert, (void *)godotsharp_array_insert,
(void *)godotsharp_array_last_index_of,
(void *)godotsharp_array_make_read_only,
(void *)godotsharp_array_max,
(void *)godotsharp_array_min,
(void *)godotsharp_array_pick_random,
(void *)godotsharp_array_recursive_equal,
(void *)godotsharp_array_remove_at, (void *)godotsharp_array_remove_at,
(void *)godotsharp_array_resize, (void *)godotsharp_array_resize,
(void *)godotsharp_array_make_read_only, (void *)godotsharp_array_reverse,
(void *)godotsharp_array_shuffle, (void *)godotsharp_array_shuffle,
(void *)godotsharp_array_slice,
(void *)godotsharp_array_sort,
(void *)godotsharp_array_to_string, (void *)godotsharp_array_to_string,
(void *)godotsharp_dictionary_try_get_value, (void *)godotsharp_dictionary_try_get_value,
(void *)godotsharp_dictionary_set_value, (void *)godotsharp_dictionary_set_value,