Skip to content

Instantly share code, notes, and snippets.

@gnysek
Last active February 20, 2024 14:18
Show Gist options
  • Save gnysek/cdea64d18c10daf344fd2d1084f7baaa to your computer and use it in GitHub Desktop.
Save gnysek/cdea64d18c10daf344fd2d1084f7baaa to your computer and use it in GitHub Desktop.
Foreach GML
/// @return N/A (0)
///
/// Executes a method call for each element of the given struct/array/data structure.
/// This iterator is shallow and will not also iterate over nested structs/arrays (though
/// you can of course call foreach() inside the specified method)
///
/// This function can also iterate over all members of a ds_map, ds_list, or ds_grid.
/// You will need to specify a value for [dsType] to iterate over a data structure
///
/// The specified method is passed the following parameters:
///
/// arg0 - v - Value found in the given struct/array
/// arg1 - i - 0-indexed index of the value e.g. =0 for the first element, =1 for the second element etc.
/// arg2 - k - When iterating over structs, the name of the variable that contains the given value; otherwise <undefined>
/// arg3 - s - Struct or anything you wish to be also passed into function (as temp variables are invicible)
///
/// The order that values are sent into <method> is guaranteed for arrays (starting at
/// index 0 and ascending), but is not guaranteed for structs due to the behaviour of
/// GameMaker's internal hashmap
///
/// @param {Any} _ds Struct/array/data structure to be iterated over
/// @param {Function} _function method_viks Method to call for each element of this given struct/array/ds | value, index, key, customval
/// @param {Constant.DsType} _ds_type Data structure type if iterating over a data structure
/// @param {Any} _specialargs
///
/// @jujuadams 2020-06-16
/// _specialargs added by @gnysek
function foreach(_ds, _function, _ds_type = undefined, _specialargs = undefined)
{
//var _ds = argument[0];
//var _function = argument[1];
//var _ds_type = (argument_count > 2)? argument[2] : undefined;
var _i;
if (is_struct(_ds))
{
var _names = variable_struct_get_names(_ds);
_i = 0;
repeat(array_length(_names))
{
var _name = _names[_i];
_function(variable_struct_get(_ds, _name), _i, _name, _specialargs);
++_i;
}
}
else if (is_array(_ds))
{
_i = 0;
repeat(array_length(_ds))
{
_function(_ds[_i], _i, undefined, _specialargs);
++_i;
}
}
else switch(_ds_type)
{
case ds_type_list:
_i = 0;
repeat(ds_list_size(_ds))
{
_function(_ds[| _i], _i, undefined, _specialargs);
++_i;
}
break;
case ds_type_map:
_i = 0;
var _key = ds_map_find_first(_ds);
repeat(ds_map_size(_ds))
{
_function(_ds[? _key], _i, _key, _specialargs);
_key = ds_map_find_next(_ds, _key);
++_i;
}
break;
case ds_type_grid:
var _w = ds_grid_width( _ds);
var _h = ds_grid_height(_ds);
var _y = 0;
repeat(_h)
{
var _x = 0;
repeat(_w)
{
_function(_ds[# _x, _y], _x, _y, _specialargs);
++_x;
}
++_y;
}
break;
default:
show_error("Cannot iterate over datatype \"" + string(typeof(_ds)) + "\"\n ", false);
break;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment