enum NODE_SCATTER_DIST {
	area,
	border,
	map,
	data,
	path,
	tile
}

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