Add array slice method
This commit is contained in:
parent
24e1039eb6
commit
757c509437
7 changed files with 101 additions and 0 deletions
|
@ -222,6 +222,63 @@ Array Array::duplicate(bool p_deep) const {
|
|||
|
||||
return new_arr;
|
||||
}
|
||||
|
||||
int Array::_fix_slice_index(int p_index, int p_arr_len, int p_top_mod) {
|
||||
p_index = CLAMP(p_index, -p_arr_len, p_arr_len + p_top_mod);
|
||||
if (p_index < 0) {
|
||||
p_index = (p_index % p_arr_len + p_arr_len) % p_arr_len; // positive modulo
|
||||
}
|
||||
return p_index;
|
||||
}
|
||||
|
||||
int Array::_clamp_index(int p_index) const {
|
||||
return CLAMP(p_index, -size() + 1, size() - 1);
|
||||
}
|
||||
|
||||
#define ARRAY_GET_DEEP(idx, is_deep) is_deep ? get(idx).duplicate(is_deep) : get(idx)
|
||||
|
||||
Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound
|
||||
Array new_arr;
|
||||
|
||||
p_begin = Array::_fix_slice_index(p_begin, size(), -1); // can't start out of range
|
||||
p_end = Array::_fix_slice_index(p_end, size(), 0);
|
||||
|
||||
int x = p_begin;
|
||||
int new_arr_i = 0;
|
||||
|
||||
ERR_FAIL_COND_V(p_step == 0, new_arr);
|
||||
if (Array::_clamp_index(p_begin) == Array::_clamp_index(p_end)) { // don't include element twice
|
||||
new_arr.resize(1);
|
||||
// new_arr[0] = 1;
|
||||
new_arr[0] = ARRAY_GET_DEEP(Array::_clamp_index(p_begin), p_deep);
|
||||
return new_arr;
|
||||
} else {
|
||||
int element_count = ceil((int)MAX(0, (p_end - p_begin) / p_step)) + 1;
|
||||
if (element_count == 1) { // delta going in wrong direction to reach end
|
||||
new_arr.resize(0);
|
||||
return new_arr;
|
||||
}
|
||||
new_arr.resize(element_count);
|
||||
}
|
||||
|
||||
// if going backwards, have to have a different terminating condition
|
||||
if (p_step < 0) {
|
||||
while (x >= p_end) {
|
||||
new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
|
||||
x += p_step;
|
||||
new_arr_i += 1;
|
||||
}
|
||||
} else if (p_step > 0) {
|
||||
while (x <= p_end) {
|
||||
new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep);
|
||||
x += p_step;
|
||||
new_arr_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return new_arr;
|
||||
}
|
||||
|
||||
struct _ArrayVariantSort {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||
|
|
|
@ -44,6 +44,9 @@ class Array {
|
|||
void _ref(const Array &p_from) const;
|
||||
void _unref() const;
|
||||
|
||||
int _clamp_index(int p_index) const;
|
||||
static int _fix_slice_index(int p_index, int p_arr_len, int p_top_mod);
|
||||
|
||||
public:
|
||||
Variant &operator[](int p_idx);
|
||||
const Variant &operator[](int p_idx) const;
|
||||
|
@ -91,6 +94,8 @@ public:
|
|||
|
||||
Array duplicate(bool p_deep = false) const;
|
||||
|
||||
Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const;
|
||||
|
||||
Variant min() const;
|
||||
Variant max() const;
|
||||
|
||||
|
|
|
@ -534,6 +534,7 @@ struct _VariantCall {
|
|||
VCALL_LOCALMEM2R(Array, bsearch);
|
||||
VCALL_LOCALMEM4R(Array, bsearch_custom);
|
||||
VCALL_LOCALMEM1R(Array, duplicate);
|
||||
VCALL_LOCALMEM4R(Array, slice);
|
||||
VCALL_LOCALMEM0(Array, invert);
|
||||
VCALL_LOCALMEM0R(Array, max);
|
||||
VCALL_LOCALMEM0R(Array, min);
|
||||
|
@ -1759,6 +1760,7 @@ void register_variant_methods() {
|
|||
ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true));
|
||||
ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
|
||||
ADDFUNC1R(ARRAY, ARRAY, Array, duplicate, BOOL, "deep", varray(false));
|
||||
ADDFUNC4R(ARRAY, ARRAY, Array, slice, INT, "begin", INT, "end", INT, "step", BOOL, "deep", varray(1, false));
|
||||
ADDFUNC0R(ARRAY, NIL, Array, max, varray());
|
||||
ADDFUNC0R(ARRAY, NIL, Array, min, varray());
|
||||
|
||||
|
|
|
@ -124,6 +124,21 @@
|
|||
[b]Note:[/b] Calling [method bsearch] on an unsorted array results in unexpected behavior.
|
||||
</description>
|
||||
</method>
|
||||
<method name="slice">
|
||||
<return type="Array">
|
||||
</return>
|
||||
<argument index="0" name="begin" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="end" type="int">
|
||||
</argument>
|
||||
<argument index="2" name="step" type="int" default="1">
|
||||
</argument>
|
||||
<argument index="3" name="deep" type="bool" default="False">
|
||||
</argument>
|
||||
<description>
|
||||
Duplicates the subset described in the function and returns it in an array, deeply copying the array if [code]deep[/code] is true. Lower and upper index are inclusive, with the [code]step[/code] describing the change between indices while slicing.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear">
|
||||
<description>
|
||||
Clears the array. This is equivalent to using [method resize] with a size of [code]0[/code].
|
||||
|
|
|
@ -327,6 +327,15 @@ godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_b
|
|||
return res;
|
||||
}
|
||||
|
||||
godot_array GDAPI godot_array_slice(const godot_array *p_self, const godot_int p_begin, const godot_int p_end, const godot_int p_step, const godot_bool p_deep) {
|
||||
const Array *self = (const Array *)p_self;
|
||||
godot_array res;
|
||||
Array *val = (Array *)&res;
|
||||
memnew_placement(val, Array);
|
||||
*val = self->slice(p_begin, p_end, p_step, p_deep);
|
||||
return res;
|
||||
}
|
||||
|
||||
godot_variant GDAPI godot_array_max(const godot_array *p_self) {
|
||||
const Array *self = (const Array *)p_self;
|
||||
godot_variant v;
|
||||
|
|
|
@ -80,6 +80,17 @@
|
|||
["const godot_vector2 *", "p_self"],
|
||||
["const godot_vector2 *", "p_to"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "godot_array_slice",
|
||||
"return_type": "godot_array",
|
||||
"arguments": [
|
||||
["const godot_array *", "p_self"],
|
||||
["const godot_int", "p_begin"],
|
||||
["const godot_int", "p_end"],
|
||||
["const godot_int", "p_step"],
|
||||
["const godot_bool", "p_deep"]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -132,6 +132,8 @@ void GDAPI godot_array_destroy(godot_array *p_self);
|
|||
|
||||
godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_bool p_deep);
|
||||
|
||||
godot_array GDAPI godot_array_slice(const godot_array *p_self, const godot_int p_begin, const godot_int p_end, const godot_int p_delta, const godot_bool p_deep);
|
||||
|
||||
godot_variant GDAPI godot_array_max(const godot_array *p_self);
|
||||
|
||||
godot_variant GDAPI godot_array_min(const godot_array *p_self);
|
||||
|
|
Loading…
Reference in a new issue