Pixel-Composer/scripts/node_scatter/node_scatter.gml

681 lines
20 KiB
Text
Raw Normal View History

2023-11-28 06:50:54 +01:00
enum NODE_SCATTER_DIST {
area,
border,
map,
data,
path,
tile
}
2023-02-28 09:43:01 +01:00
function Node_Scatter(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
2022-01-13 05:24:03 +01:00
name = "Scatter";
2023-02-14 05:32:32 +01:00
dimension_index = 1;
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(0, nodeValue_Surface("Surface in", self));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(1, nodeValue_Dimension(self));
2022-01-13 05:24:03 +01:00
2024-08-18 09:13:41 +02:00
newInput(2, nodeValue_Int("Amount", self, 8))
.setValidator(VV_min(0));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(3, nodeValue_Vec2_Range("Scale", self, [ 1, 1, 1, 1 ] , { linked : true }));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(4, nodeValue_Rotation_Random("Angle", self, [ 0, 0, 0, 0, 0 ] ));
2022-01-13 05:24:03 +01:00
2023-11-24 10:41:53 +01:00
onSurfaceSize = function() { return getInputData(1, DEF_SURF); };
2024-08-18 09:13:41 +02:00
newInput(5, nodeValue_Area("Area", self, DEF_AREA_REF, { onSurfaceSize }))
.setUnitRef(onSurfaceSize, VALUE_UNIT.reference);
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(6, nodeValue_Enum_Scroll("Distribution", self, 5, [ "Area", "Border", "Map", "Direct Data", "Path", "Full image + Tile" ]));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(7, nodeValue_Bool("Point at center", self, false, "Rotate each copy to face the spawn center."));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(8, nodeValue_Bool("Uniform scaling", self, true));
2022-01-13 05:24:03 +01:00
2024-08-18 06:16:20 +02:00
newInput(9, nodeValue_Enum_Button("Scatter", self, 1, [ "Uniform", "Random" ]));
2022-01-13 05:24:03 +01:00
2024-11-07 07:59:04 +01:00
newInput(10, nodeValueSeed(self));
2023-01-17 08:11:55 +01:00
2024-08-18 09:13:41 +02:00
newInput(11, nodeValue_Gradient("Random blend", self, new gradientObject(cola(c_white))))
2024-01-22 10:46:04 +01:00
.setMappable(28);
2023-01-17 08:11:55 +01:00
2024-08-18 06:16:20 +02:00
newInput(12, nodeValue_Slider_Range("Alpha", self, [ 1, 1 ]));
2023-02-14 05:32:32 +01:00
2024-08-18 06:16:20 +02:00
newInput(13, nodeValue_Surface("Distribution map", self));
2023-02-14 05:32:32 +01:00
2024-08-18 06:16:20 +02:00
newInput(14, nodeValue_Vector("Distribution data", self, []));
2024-08-08 06:57:51 +02:00
inputs[14].array_depth = 1;
2022-01-13 05:24:03 +01:00
2024-08-20 10:15:53 +02:00
newInput(15, nodeValue_Int("Array", self, 0, @"What to do when input array of surface.
2023-02-19 02:13:19 +01:00
- Spread: Create Array of output each scattering single surface.
2024-08-20 10:15:53 +02:00
- Mixed: Create single output scattering multiple images."))
2024-01-17 14:57:32 +01:00
.setDisplay(VALUE_DISPLAY.enum_scroll, [ "Spread output", "Index", "Random", "Data", "Texture" ]);
2023-02-14 05:32:32 +01:00
2024-08-18 06:16:20 +02:00
newInput(16, nodeValue_Bool("Multiply alpha", self, true));
2023-02-19 02:13:19 +01:00
2024-10-03 12:20:00 +02:00
newInput(17, nodeValue_Text("Use extra value", self, [ "Scale" ], "Apply the third value in each data point (if exist) on given properties."))
.setDisplay(VALUE_DISPLAY.text_array, { data: [ "Scale", "Rotation", "Color" ] });
2023-02-21 04:48:50 +01:00
2024-08-18 06:16:20 +02:00
newInput(18, nodeValue_Enum_Scroll("Blend mode", self, 0, [ "Normal", "Add", "Max" ]));
2023-03-28 06:58:28 +02:00
2024-08-18 06:16:20 +02:00
newInput(19, nodeValue_PathNode("Path", self, noone));
2023-04-16 15:26:52 +02:00
2024-08-18 06:16:20 +02:00
newInput(20, nodeValue_Bool("Rotate along path", self, true));
2023-07-21 12:40:20 +02:00
2024-08-18 09:13:41 +02:00
newInput(21, nodeValue_Float("Path Shift", self, 0))
.setDisplay(VALUE_DISPLAY.slider);
2023-08-12 12:35:35 +02:00
2024-08-18 06:16:20 +02:00
newInput(22, nodeValue_Float("Scatter Distance", self, 0));
2024-01-12 05:03:35 +01:00
2024-08-18 06:16:20 +02:00
newInput(23, nodeValue_Bool("Sort Y", self, false));
2024-01-17 14:57:32 +01:00
2024-08-18 09:13:41 +02:00
newInput(24, nodeValue_Int("Array indices", self, []))
2024-01-17 14:57:32 +01:00
.setArrayDepth(1);
2024-08-18 06:16:20 +02:00
newInput(25, nodeValue_Surface("Array texture", self));
2024-01-17 14:57:32 +01:00
2024-08-18 06:16:20 +02:00
newInput(26, nodeValue_Range("Animated array", self, [ 0, 0 ], { linked : true }));
2024-01-19 09:33:37 +01:00
2024-08-18 06:16:20 +02:00
newInput(27, nodeValue_Enum_Scroll("Animated array end", self, 0, [ "Loop", "Ping Pong" ]));
2024-01-19 09:33:37 +01:00
2024-08-25 10:18:22 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2024-01-22 10:46:04 +01:00
2024-08-18 06:16:20 +02:00
newInput(28, nodeValueMap("Gradient map", self));
2024-01-22 10:46:04 +01:00
2024-08-18 06:16:20 +02:00
newInput(29, nodeValueGradientRange("Gradient map range", self, inputs[11]));
2024-01-22 10:46:04 +01:00
2024-08-25 10:18:22 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2024-01-22 10:46:04 +01:00
2024-08-18 06:16:20 +02:00
newInput(30, nodeValue_Vec2("Uniform amount", self, [ 4, 4 ]));
2024-01-24 06:19:34 +01:00
2024-08-18 06:16:20 +02:00
newInput(31, nodeValue_Bool("Auto amount", self, false));
2024-01-24 06:19:34 +01:00
2024-08-18 06:16:20 +02:00
newInput(32, nodeValue_Rotation("Rotate per radius", self, 0));
2024-01-24 06:19:34 +01:00
2024-08-18 06:16:20 +02:00
newInput(33, nodeValue_Vec2_Range("Random position", self, [ 0, 0, 0, 0 ]));
2024-01-24 06:19:34 +01:00
2024-08-18 06:16:20 +02:00
newInput(34, nodeValue_Vec2("Scale per radius", self, [ 0, 0 ]));
2024-02-15 14:23:26 +01:00
2024-08-18 06:16:20 +02:00
newInput(35, nodeValue_Rotation_Range("Angle range", self, [ 0, 360 ]));
2024-03-02 10:08:44 +01:00
2024-08-18 06:16:20 +02:00
newInput(36, nodeValue_Vec2("Shift position", self, [ 0, 0 ]));
2024-03-14 14:35:19 +01:00
2024-08-18 09:13:41 +02:00
newInput(37, nodeValue_Bool("Exact", self, false))
2024-03-14 14:35:19 +01:00
2024-08-18 06:16:20 +02:00
newInput(38, nodeValue_Enum_Button("Spacing", self, 0, [ "After", "Between", "Around" ]));
2024-08-25 10:18:22 +02:00
newInput(39, nodeValue_Range("Shift radial", self, [ 0, 0 ]));
2024-10-03 12:20:00 +02:00
newInput(40, nodeValue_Vec2("Anchor", self, [ 0.5, 0.5 ]))
.setDisplay(VALUE_DISPLAY.vector, {
side_button : new buttonAnchor(function(ind) {
switch(ind) {
case 0 : inputs[40].setValue([ 0.0, 0.0 ]); break;
case 1 : inputs[40].setValue([ 0.5, 0.0 ]); break;
case 2 : inputs[40].setValue([ 1.0, 0.0 ]); break;
case 3 : inputs[40].setValue([ 0.0, 0.5 ]); break;
case 4 : inputs[40].setValue([ 0.5, 0.5 ]); break;
case 5 : inputs[40].setValue([ 1.0, 0.5 ]); break;
case 6 : inputs[40].setValue([ 0.0, 1.0 ]); break;
case 7 : inputs[40].setValue([ 0.5, 1.0 ]); break;
case 8 : inputs[40].setValue([ 1.0, 1.0 ]); break;
}
})
});
2024-08-25 10:18:22 +02:00
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2024-09-04 03:57:11 +02:00
newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone));
2023-04-16 15:26:52 +02:00
2024-11-15 09:39:23 +01:00
newOutput(1, nodeValue_Output("Atlas data", self, VALUE_TYPE.atlas, []))
2024-01-24 06:19:34 +01:00
.setVisible(false)
2023-05-28 20:00:51 +02:00
.rejectArrayProcess();
2022-01-13 05:24:03 +01:00
2024-03-02 10:08:44 +01:00
input_display_list = [ 10,
["Surfaces", true], 0, 1, 15, 24, 25, 26, 27,
2024-02-15 14:23:26 +01:00
["Scatter", false], 6, 5, 13, 14, 17, 9, 31, 2, 30, 35,
["Path", false], 19, 38, 20, 21, 22,
2024-10-03 12:20:00 +02:00
["Position", false], 40, 33, 36, 37, 39,
2024-01-24 06:19:34 +01:00
["Rotation", false], 7, 4, 32,
2024-02-15 14:23:26 +01:00
["Scale", false], 3, 8, 34,
2024-01-22 10:46:04 +01:00
["Render", false], 18, 11, 28, 12, 16, 23,
2022-01-13 05:24:03 +01:00
];
2023-03-19 09:17:39 +01:00
attribute_surface_depth();
2024-01-24 06:19:34 +01:00
attribute_interpolation();
2024-11-15 09:39:23 +01:00
surface_size_map = {};
surface_valid_map = {};
2023-03-19 09:17:39 +01:00
2023-04-16 15:26:52 +02:00
scatter_data = [];
scatter_map = noone;
scatter_mapa = 0;
scatter_maps = 0;
scatter_mapp = [];
2023-04-16 15:26:52 +02:00
2024-08-25 10:18:22 +02:00
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
PROCESSOR_OVERLAY_CHECK
2024-01-22 10:46:04 +01:00
var _distType = current_data[6];
2024-07-02 12:18:32 +02:00
var _hov = false;
2024-01-22 10:46:04 +01:00
if(_distType < 3) { var hv = inputs[ 5].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !hv; _hov |= hv; }
if(_distType == 4) { var hv = inputs[19].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !hv; _hov |= hv; }
2024-08-08 06:57:51 +02:00
var hv = inputs[29].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, current_data[1]); active &= !hv; _hov |= hv;
2024-07-02 12:18:32 +02:00
return _hov;
2024-08-25 10:18:22 +02:00
}
2022-01-13 05:24:03 +01:00
static getTool = function() {
var _path = getInputData(19);
return is_instanceof(_path, Node)? _path : self;
}
2024-08-25 10:18:22 +02:00
static onValueUpdate = function(index) {
2023-02-14 05:32:32 +01:00
if(index == 15) {
var _arr = getInputData(15);
2024-08-08 06:57:51 +02:00
inputs[0].array_depth = _arr;
2023-02-14 05:32:32 +01:00
2023-04-16 15:26:52 +02:00
update();
2023-02-14 05:32:32 +01:00
}
2024-08-25 10:18:22 +02:00
}
2023-02-14 05:32:32 +01:00
2024-08-25 10:18:22 +02:00
static step = function() {
2024-01-24 06:19:34 +01:00
var _are = getInputData(5);
var _dis = getInputData(6);
2024-01-24 06:19:34 +01:00
var _sct = getInputData(9);
var _arr = getInputData(15);
2024-01-19 09:33:37 +01:00
var _amn = getInputData(26);
var _spa = getInputData(38);
2024-01-24 06:19:34 +01:00
update_on_frame = _arr && (_amn[0] != 0 || _amn[1] != 0);
2024-08-08 06:57:51 +02:00
inputs[0].array_depth = bool(_arr);
inputs[13].setVisible(_dis == 2, _dis == 2);
inputs[14].setVisible(_dis == 3, _dis == 3);
inputs[17].setVisible(_dis == 3);
inputs[ 9].setVisible(_dis != 2 && _dis != 3);
inputs[19].setVisible(_dis == 4, _dis == 4);
inputs[20].setVisible(_dis == 4);
inputs[21].setVisible(_dis == 4 && _spa == 0);
inputs[22].setVisible(_dis == 4);
inputs[38].setVisible(_dis == 4 && _sct == 0);
inputs[24].setVisible(_arr == 3, _arr == 3);
inputs[25].setVisible(_arr == 4, _arr == 4);
inputs[26].setVisible(_arr);
inputs[27].setVisible(_arr);
inputs[ 5].setVisible(_dis < 3);
inputs[ 2].setVisible( true);
inputs[30].setVisible(false);
inputs[31].setVisible(false);
inputs[32].setVisible(false);
inputs[34].setVisible(false);
inputs[35].setVisible(false);
2024-01-24 06:19:34 +01:00
if(_dis == 0 && _sct == 0) {
if(_are[AREA_INDEX.shape] == AREA_SHAPE.elipse) {
var _aut = getInputData(31);
2024-08-08 06:57:51 +02:00
inputs[ 2].setVisible( _aut);
inputs[30].setVisible(!_aut);
inputs[31].setVisible( true);
inputs[32].setVisible(!_aut);
inputs[34].setVisible(!_aut);
inputs[35].setVisible(!_aut);
2024-02-15 14:23:26 +01:00
2024-01-24 06:19:34 +01:00
} else {
2024-08-08 06:57:51 +02:00
inputs[ 2].setVisible(false);
inputs[30].setVisible( true);
2024-01-24 06:19:34 +01:00
}
} else if(_dis == 5) {
2024-08-08 06:57:51 +02:00
inputs[ 2].setVisible(_sct == 1);
inputs[30].setVisible(_sct == 0);
2024-01-24 06:19:34 +01:00
}
2024-01-22 10:46:04 +01:00
2024-08-08 06:57:51 +02:00
inputs[11].mappableStep();
2024-08-25 10:18:22 +02:00
}
2023-02-14 05:32:32 +01:00
////=========== PROCESS ===========
2024-10-03 12:20:00 +02:00
static processData = function(_outData, _data, _output_index, _array_index) {
2023-02-14 05:32:32 +01:00
var _inSurf = _data[0];
2022-12-22 03:09:55 +01:00
var _dim = _data[1];
var _amount = _data[2];
var _scale = _data[3];
var _rota = _data[4];
2022-01-13 05:24:03 +01:00
2022-12-22 03:09:55 +01:00
var _area = _data[5];
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
var _dist = _data[ 6];
var _distMap = _data[13];
var _distData = _data[14];
var _scat = _data[ 9];
2022-01-13 05:24:03 +01:00
2022-12-22 03:09:55 +01:00
var _pint = _data[7];
var _unis = _data[8];
2022-01-13 05:24:03 +01:00
2022-12-22 03:09:55 +01:00
var seed = _data[10];
2023-02-14 05:32:32 +01:00
var color = _data[11];
2024-01-22 10:46:04 +01:00
var clr_map = _data[28];
var clr_rng = _data[29];
2023-01-17 08:11:55 +01:00
var alpha = _data[12];
2024-01-17 14:57:32 +01:00
var _arr = _data[15];
2023-02-19 02:13:19 +01:00
var mulpA = _data[16];
2023-02-21 04:48:50 +01:00
var useV = _data[17];
2023-03-28 06:58:28 +02:00
var blend = _data[18];
2023-07-21 12:40:20 +02:00
2023-04-16 15:26:52 +02:00
var path = _data[19];
2023-07-21 12:40:20 +02:00
var pathRot = _data[20];
2023-08-12 12:35:35 +02:00
var pathShf = _data[21];
var pathDis = _data[22];
2024-01-12 05:03:35 +01:00
var sortY = _data[23];
2024-01-17 14:57:32 +01:00
var arrId = _data[24];
var arrTex = _data[25], useArrTex = is_surface(arrTex);
2024-01-19 09:33:37 +01:00
var arrAnim = _data[26];
var arrAnimEnd = _data[27];
2022-01-13 05:24:03 +01:00
2024-01-24 06:19:34 +01:00
var uniAmo = _data[30];
var uniAut = _data[31];
var uniRot = _data[32];
var posWig = _data[33];
2024-02-15 14:23:26 +01:00
var uniSca = _data[34];
var cirRng = _data[35];
2024-03-02 10:08:44 +01:00
var posShf = _data[36];
2024-03-14 14:35:19 +01:00
var posExt = _data[37];
var pthSpac = _data[38];
2024-08-25 10:18:22 +02:00
var shfRad = _data[39];
2024-10-03 12:20:00 +02:00
var anchor = _data[40];
2024-01-24 06:19:34 +01:00
2022-01-13 05:24:03 +01:00
var _in_w, _in_h;
2023-02-21 04:48:50 +01:00
var vSca = array_exists(useV, "Scale");
var vRot = array_exists(useV, "Rotation");
var vCol = array_exists(useV, "Color");
2024-01-24 06:19:34 +01:00
var surfArray = is_array(_inSurf);
2024-10-03 12:20:00 +02:00
if(surfArray && array_empty(_inSurf)) return _outData;
2024-01-24 06:19:34 +01:00
#region cache value
2024-11-15 09:39:23 +01:00
surface_size_map = {};
surface_valid_map = {};
2024-01-24 06:19:34 +01:00
if(!surfArray) {
2024-11-15 09:39:23 +01:00
surface_size_map[$ _inSurf] = surface_get_dimension(_inSurf);
surface_valid_map[$ _inSurf] = is_surface(_inSurf);
2024-01-24 06:19:34 +01:00
} else {
for( var i = 0, n = array_length(_inSurf); i < n; i++ ) {
2024-11-15 09:39:23 +01:00
surface_size_map[$ _inSurf[i]] = surface_get_dimension(_inSurf[i]);
surface_valid_map[$ _inSurf[i]] = is_surface(_inSurf[i]);
2024-01-24 06:19:34 +01:00
}
}
2023-11-28 06:50:54 +01:00
2024-01-24 06:19:34 +01:00
color.cache();
#endregion
#region data
var _posDist = [];
if(_dist == NODE_SCATTER_DIST.map) {
if(!is_surface(_distMap))
2024-10-03 12:20:00 +02:00
return _outData;
2024-10-03 12:20:00 +02:00
scatter_mapp = get_points_from_dist(_distMap, _amount, seed);
scatter_map = _distMap;
scatter_maps = seed;
scatter_mapa = _amount;
_posDist = scatter_mapp;
2024-01-24 06:19:34 +01:00
}
2023-11-28 06:50:54 +01:00
2024-01-24 06:19:34 +01:00
if(_dist == NODE_SCATTER_DIST.area) { // Area
if(_scat == 0 && (!uniAut || _area[AREA_INDEX.shape] == AREA_SHAPE.rectangle))
_amount = uniAmo[0] * uniAmo[1];
2023-11-28 06:50:54 +01:00
2024-01-24 06:19:34 +01:00
} else if(_dist == NODE_SCATTER_DIST.path) { // Path
var path_valid = path != noone && struct_has(path, "getPointRatio");
2023-11-28 06:50:54 +01:00
2024-10-03 12:20:00 +02:00
if(!path_valid) return _outData;
2024-01-24 06:19:34 +01:00
var _pathProgress = 0;
var path_amount = struct_has(path, "getLineCount")? path.getLineCount() : 1;
var _pre_amount = _amount;
_amount *= path_amount;
var path_line_index = 0;
} else if(_dist == NODE_SCATTER_DIST.tile) {
if(_scat == 0) _amount = uniAmo[0] * uniAmo[1];
}
2023-11-28 06:50:54 +01:00
2024-01-24 06:19:34 +01:00
var _sed = seed;
2024-11-15 09:39:23 +01:00
var _sct = array_verify(_outData[1], _amount);
2024-01-24 06:19:34 +01:00
var _sct_len = 0;
var _arrLen = array_safe_length(_inSurf);
random_set_seed(_sed);
var _wigX = posWig[0] != 0 || posWig[1] != 0;
var _wigY = posWig[2] != 0 || posWig[3] != 0;
var _scaUniX = _scale[0] == _scale[1];
var _scaUniY = _scale[2] == _scale[3];
var _alpUni = alpha[0] == alpha[1];
2024-08-08 06:57:51 +02:00
var _clrUni = !inputs[11].attributes.mapped && color.keyLength == 1;
2024-01-24 06:19:34 +01:00
var _clrSin = color.evalFast(0);
2024-08-08 06:57:51 +02:00
var _useAtl = outputs[1].visible;
2024-01-24 06:19:34 +01:00
var _datLen = array_length(scatter_data);
var _p = [ 0, 0 ];
#endregion
2022-01-13 05:24:03 +01:00
2024-11-15 09:39:23 +01:00
var _outSurf = _outData[0];
2023-02-14 05:32:32 +01:00
surface_set_target(_outSurf);
gpu_set_tex_filter(getAttribute("interpolate") > 1);
2024-01-24 06:19:34 +01:00
2023-03-19 09:17:39 +01:00
DRAW_CLEAR
2023-03-28 06:58:28 +02:00
switch(blend) {
case 0 :
2024-08-25 10:18:22 +02:00
if(mulpA) BLEND_ALPHA_MULP
else BLEND_ALPHA
break;
case 1 :
BLEND_ADD;
2023-03-28 06:58:28 +02:00
break;
2024-02-01 08:38:21 +01:00
case 2 :
BLEND_ALPHA_MULP
gpu_set_blendequation(bm_eq_max);
break;
2023-03-28 06:58:28 +02:00
}
2023-02-19 02:13:19 +01:00
2024-01-12 05:03:35 +01:00
var positions = array_create(_amount);
var posIndex = 0;
2023-02-14 05:32:32 +01:00
for(var i = 0; i < _amount; i++) {
var sp = noone, _x = 0, _y = 0;
2023-02-21 04:48:50 +01:00
var _v = noone;
2024-08-25 10:18:22 +02:00
var _scx = _scaUniX? _scale[0] : random_range_seed(_scale[0], _scale[1], _sed++);
var _scy = _scaUniY? _scale[2] : random_range_seed(_scale[2], _scale[3], _sed++);
2024-02-15 14:23:26 +01:00
2024-11-15 09:39:23 +01:00
switch(_dist) { // position
2024-01-24 06:19:34 +01:00
case NODE_SCATTER_DIST.area :
if(_scat == 0) {
var _axc = _area[AREA_INDEX.center_x];
var _ayc = _area[AREA_INDEX.center_y];
var _aw = _area[AREA_INDEX.half_w], _aw2 = _aw * 2;
var _ah = _area[AREA_INDEX.half_h], _ah2 = _ah * 2;
var _ax0 = _axc - _aw, _ax1 = _axc + _aw;
var _ay0 = _ayc - _ah, _ay1 = _ayc + _ah;
var _acol = i % uniAmo[0];
var _arow = floor(i / uniAmo[0]);
if(_area[AREA_INDEX.shape] == AREA_SHAPE.rectangle) {
_x = uniAmo[0] == 1? _axc : _ax0 + (_acol + 0.5) * _aw2 / ( uniAmo[0] );
_y = uniAmo[1] == 1? _ayc : _ay0 + (_arow + 0.5) * _ah2 / ( uniAmo[1] );
} else if(_area[AREA_INDEX.shape] == AREA_SHAPE.elipse) {
if(uniAut) {
sp = area_get_random_point(_area, _dist, _scat, i, _amount);
_x = sp[0];
_y = sp[1];
} else {
2024-02-15 14:23:26 +01:00
var _ang = cirRng[0] + _acol * (cirRng[1] - cirRng[0]) / uniAmo[0];
2024-01-24 06:19:34 +01:00
var _rad = uniAmo[1] == 1? 0.5 : _arow / (uniAmo[1] - 1);
2024-01-24 08:38:57 +01:00
_ang += _arow * uniRot;
2024-01-24 06:19:34 +01:00
_x += _axc + lengthdir_x(_rad * _aw, _ang);
_y += _ayc + lengthdir_y(_rad * _ah, _ang);
2024-02-15 14:23:26 +01:00
_scx += _arow * uniSca[0];
_scy += _arow * uniSca[1];
2024-01-24 06:19:34 +01:00
}
}
} else {
sp = area_get_random_point(_area, _dist, _scat, i, _amount);
_x = sp[0];
_y = sp[1];
}
break;
case NODE_SCATTER_DIST.border :
sp = area_get_random_point(_area, _dist, _scat, i, _amount);
_x = sp[0];
_y = sp[1];
break;
case NODE_SCATTER_DIST.map :
2024-04-22 08:08:37 +02:00
sp = array_safe_get_fast(_posDist, i);
2024-01-24 06:19:34 +01:00
if(!is_array(sp)) continue;
2024-01-24 06:19:34 +01:00
_x = _area[0] + _area[2] * (sp[0] * 2 - 1.);
_y = _area[1] + _area[3] * (sp[1] * 2 - 1.);
break;
case NODE_SCATTER_DIST.data :
2024-03-31 05:36:11 +02:00
sp = array_safe_get_fast(_distData, i);
2024-01-24 06:19:34 +01:00
if(!is_array(sp)) continue;
2024-03-31 05:36:11 +02:00
_x = array_safe_get_fast(sp, 0);
_y = array_safe_get_fast(sp, 1);
_v = array_safe_get_fast(sp, 2, noone);
2024-01-24 06:19:34 +01:00
break;
case NODE_SCATTER_DIST.path :
if(_scat == 0) {
switch(pthSpac) {
case 0 :
_pathProgress = i / max(1, _pre_amount);
_pathProgress = frac(_pathProgress + pathShf);
break;
case 1 :
_pathProgress = i / max(1, _pre_amount - 1);
break;
case 2 :
_pathProgress = (i + 0.5) / max(1, _pre_amount);
break;
}
} else {
2024-08-25 10:18:22 +02:00
_pathProgress = random_seed(1, _sed++);
_pathProgress = frac(_pathProgress + pathShf);
}
2024-01-24 06:19:34 +01:00
var pp = path.getPointRatio(_pathProgress, path_line_index);
2024-08-25 10:18:22 +02:00
_x = pp.x + random_range_seed(-pathDis, pathDis, _sed++);
_y = pp.y + random_range_seed(-pathDis, pathDis, _sed++);
2024-01-24 06:19:34 +01:00
break;
2024-01-17 14:57:32 +01:00
2024-01-24 06:19:34 +01:00
case NODE_SCATTER_DIST.tile :
if(_scat == 0) {
var _acol = i % uniAmo[0];
var _arow = floor(i / uniAmo[0]);
_x = uniAmo[0] == 1? _dim[0] / 2 : (_acol + 0.5) * _dim[0] / ( uniAmo[0] );
_y = uniAmo[1] == 1? _dim[1] / 2 : (_arow + 0.5) * _dim[1] / ( uniAmo[1] );
} else if(_scat == 1) {
2024-08-25 10:18:22 +02:00
_x = random_range_seed(0, _dim[0], _sed++);
_y = random_range_seed(0, _dim[1], _sed++);
2024-01-24 06:19:34 +01:00
}
break;
2024-11-15 09:39:23 +01:00
}
2024-01-24 06:19:34 +01:00
2024-08-25 10:18:22 +02:00
if(_wigX) _x += random_range_seed(posWig[0], posWig[1], _sed++);
if(_wigY) _y += random_range_seed(posWig[2], posWig[3], _sed++);
2023-02-21 04:48:50 +01:00
2024-03-02 10:08:44 +01:00
_x += posShf[0] * i;
_y += posShf[1] * i;
2024-08-25 10:18:22 +02:00
var shrRad = random_range_seed(shfRad[0], shfRad[1], _sed++);
var shrAng = point_direction(_x, _y, _area[0], _area[1]);
_x -= lengthdir_x(shrRad, shrAng);
_y -= lengthdir_y(shrRad, shrAng);
2024-02-15 14:23:26 +01:00
if(_unis) {
_scy = max(_scx, _scy);
_scx = _scy;
}
2023-02-14 05:32:32 +01:00
2023-02-21 04:48:50 +01:00
if(vSca && _v != noone) {
_scx *= _v;
_scy *= _v;
}
2024-08-25 10:18:22 +02:00
var _r = (_pint? point_direction(_area[0], _area[1], _x, _y) : 0) + angle_random_eval_fast(_rota, _sed++);
2023-02-21 04:48:50 +01:00
if(vRot && _v != noone)
_r *= _v;
2023-07-21 12:40:20 +02:00
2023-11-28 06:50:54 +01:00
if(_dist == NODE_SCATTER_DIST.path && pathRot) {
var pr1 = clamp(_pathProgress + 0.01, 0, 1);
var pr0 = pr1 - 0.02;
var p0 = path.getPointRatio(pr0, path_line_index);
var p1 = path.getPointRatio(pr1, path_line_index);
2023-07-21 12:40:20 +02:00
var dirr = point_direction(p0.x, p0.y, p1.x, p1.y);
_r += dirr;
}
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
var surf = _inSurf;
2023-04-16 15:26:52 +02:00
var ind = 0;
2024-01-17 14:57:32 +01:00
2024-08-25 10:18:22 +02:00
if(surfArray) {
2024-01-17 14:57:32 +01:00
switch(_arr) {
2024-10-03 12:20:00 +02:00
case 1 : ind = safe_mod(i, _arrLen); break;
case 2 : ind = irandom(_arrLen - 1); break;
2024-03-31 05:36:11 +02:00
case 3 : ind = array_safe_get_fast(arrId, i, 0); break;
2024-02-10 07:03:50 +01:00
case 4 : if(useArrTex) ind = colorBrightness(surface_get_pixel(arrTex, _x, _y)) * (_arrLen - 1); break;
2024-01-19 09:33:37 +01:00
}
if(arrAnim[0] != 0 || arrAnim[1] != 0) {
2024-01-24 06:19:34 +01:00
var _arrAnim_spd = random_range(arrAnim[0], arrAnim[1]);
var _arrAnim_shf = random(_arrLen);
2024-01-19 09:33:37 +01:00
var _animInd = ind + _arrAnim_shf + CURRENT_FRAME * _arrAnim_spd;
switch(arrAnimEnd) {
case 0 :
ind = safe_mod(_animInd, _arrLen);
break;
case 1 :
var pp = safe_mod(_animInd, _arrLen * 2 - 1);
ind = pp < _arrLen? pp : _arrLen * 2 - pp;
break;
}
2024-01-17 14:57:32 +01:00
}
2023-04-16 15:26:52 +02:00
2024-03-31 05:36:11 +02:00
surf = array_safe_get_fast(_inSurf, ind, 0);
2024-08-25 10:18:22 +02:00
}
2024-01-24 06:19:34 +01:00
2024-11-15 09:39:23 +01:00
if(surf == 0 || !surface_valid_map[$ surf]) continue;
2023-04-16 15:26:52 +02:00
2024-11-15 09:39:23 +01:00
var dim = surface_size_map[$ surf];
2024-01-24 06:19:34 +01:00
var sw = dim[0];
var sh = dim[1];
2024-01-17 14:57:32 +01:00
2024-10-03 12:20:00 +02:00
var _shf_x = sw * _scx * anchor[0];
var _shf_y = sh * _scy * anchor[1];
2024-01-24 06:19:34 +01:00
if(_r == 0) {
2024-10-03 12:20:00 +02:00
_x -= _shf_x;
_y -= _shf_y;
2024-01-24 06:19:34 +01:00
} else {
2024-10-03 12:20:00 +02:00
_p = point_rotate(_x - _shf_x, _y - _shf_y, _x, _y, _r, _p);
2024-01-24 06:19:34 +01:00
_x = _p[0];
_y = _p[1];
}
2023-02-21 04:48:50 +01:00
2024-08-25 10:18:22 +02:00
var grSamp = random_seed(1, _sed++);
2023-02-21 04:48:50 +01:00
if(vCol && _v != noone)
grSamp *= _v;
var clr = _clrUni? _clrSin : evaluate_gradient_map(grSamp, color, clr_map, clr_rng, inputs[11], true);
2024-08-25 10:18:22 +02:00
var alp = _alpUni? alpha[0] : random_range_seed(alpha[0], alpha[1], _sed++);
2024-01-24 06:19:34 +01:00
var _atl = _sct_len >= _datLen? noone : scatter_data[_sct_len];
2024-08-25 10:18:22 +02:00
if(posExt) {
_x = round(_x);
_y = round(_y);
2024-03-14 14:35:19 +01:00
}
2024-01-24 06:19:34 +01:00
if(_useAtl) {
if(!is(_atl, SurfaceAtlasFast)) _atl = new SurfaceAtlasFast(surf, _x, _y, _r, _scx, _scy, clr, alp);
2024-01-24 06:19:34 +01:00
else _atl.set(surf, _x, _y, _r, _scx, _scy, clr, alp);
_atl.w = sw;
_atl.h = sh;
} else {
if(!is(_atl, SurfaceAtlasFast)) _atl = new SurfaceAtlasFast(surf, _x, _y, _r, _scx, _scy, clr, alp);
2024-01-24 06:19:34 +01:00
_atl.w = sw;
_atl.h = sh;
2024-01-24 06:19:34 +01:00
}
2023-02-14 05:32:32 +01:00
2023-11-28 06:50:54 +01:00
_sct[_sct_len] = _atl;
_sct_len++;
2024-01-12 05:03:35 +01:00
if(_dist == NODE_SCATTER_DIST.path)
path_line_index = floor(i / _pre_amount);
}
2024-01-15 13:53:46 +01:00
array_resize(_sct, _sct_len);
2024-10-03 12:20:00 +02:00
if(sortY) array_sort(_sct, function(a1, a2) /*=>*/ {return a1.y - a2.y});
2024-01-12 05:03:35 +01:00
for( var i = 0; i < _sct_len; i++ ) {
var _atl = _sct[i];
2024-01-24 06:19:34 +01:00
surf = _atl.surface;
2024-01-12 05:03:35 +01:00
_x = _atl.x;
_y = _atl.y;
_scx = _atl.sx;
_scy = _atl.sy;
_r = _atl.rotation;
clr = _atl.blend;
alp = _atl.alpha;
2024-01-24 06:19:34 +01:00
draw_surface_ext(surf, _x, _y, _scx, _scy, _r, clr, alp);
2023-04-22 11:34:56 +02:00
2024-01-12 05:03:35 +01:00
if(_dist == NODE_SCATTER_DIST.tile) {
2024-01-24 06:19:34 +01:00
var _sw = _atl.w * _scx;
var _sh = _atl.h * _scy;
2023-04-22 11:34:56 +02:00
2024-01-24 06:19:34 +01:00
if(_x < _sw) draw_surface_ext(surf, _dim[0] + _x, _y, _scx, _scy, _r, clr, alp);
if(_y < _sh) draw_surface_ext(surf, _x, _dim[1] + _y, _scx, _scy, _r, clr, alp);
if(_x < _sw && _y < _sh) draw_surface_ext(surf, _dim[0] + _x, _dim[1] + _y, _scx, _scy, _r, clr, alp);
2023-04-22 11:34:56 +02:00
2024-01-24 06:19:34 +01:00
if(_x > _dim[0] - _sw) draw_surface_ext(surf, _x - _dim[0], _y, _scx, _scy, _r, clr, alp);
if(_y > _dim[1] - _sh) draw_surface_ext(surf, _x, _y - _dim[1], _scx, _scy, _r, clr, alp);
if(_x > _dim[0] - _sw || _y > _dim[1] - _sh) draw_surface_ext(surf, _x - _dim[0], _y - _dim[1], _scx, _scy, _r, clr, alp);
2023-04-22 11:34:56 +02:00
}
2023-02-14 05:32:32 +01:00
}
2024-01-12 05:03:35 +01:00
2024-01-24 06:19:34 +01:00
BLEND_NORMAL
gpu_set_blendequation(bm_eq_add);
2024-01-24 06:19:34 +01:00
gpu_set_tex_filter(false);
2022-12-27 04:00:50 +01:00
surface_reset_target();
2022-12-22 03:09:55 +01:00
2023-11-28 06:50:54 +01:00
scatter_data = _sct;
2024-11-15 09:39:23 +01:00
_outData[0] = _outSurf;
_outData[1] = _sct;
return _outData;
2024-08-25 10:18:22 +02:00
}
2022-01-13 05:24:03 +01:00
}