diff --git a/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup0 b/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup0 new file mode 100644 index 000000000..692dd7a49 --- /dev/null +++ b/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup0 @@ -0,0 +1,537 @@ +// 2024-04-26 09:58:54 +function Node_VFX_Spawner_Base(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "Spawner"; + update_on_frame = true; + + inputs[| 0] = nodeValue("Particle sprite", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone ); + + inputs[| 1] = nodeValue("Spawn delay", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4, "Frames delay between each particle spawn." ) + .rejectArray(); + + inputs[| 2] = nodeValue("Spawn amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 2, 2 ], "Amount of particle spawn in that frame." ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 3] = nodeValue("Spawn area", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, DEF_AREA ) + .setDisplay(VALUE_DISPLAY.area); + + inputs[| 4] = nodeValue("Spawn distribution", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Area", "Border", "Map" ] ); + + inputs[| 5] = nodeValue("Lifespan", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 20, 30 ] ) + .setDisplay(VALUE_DISPLAY.range); + + inputs[| 6] = nodeValue("Spawn direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 45, 135, 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.rotation_random); + + inputs[| 7] = nodeValue("Acceleration", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 8] = nodeValue("Orientation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 0, 0, 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.rotation_random); + + inputs[| 9] = nodeValue("Rotational speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 10] = nodeValue("Spawn scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1, 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.vector_range, { linked : true }); + + inputs[| 11] = nodeValue("Scale over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11 ); + + inputs[| 12] = nodeValue("Color over lifetime", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 13] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ]) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 14] = nodeValue("Alpha over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11); + + inputs[| 15] = nodeValue("Rotate by direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Make the particle rotates to follow its movement."); + + inputs[| 16] = nodeValue("Spawn type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Stream", "Burst", "Trigger" ]); + + inputs[| 17] = nodeValue("Spawn size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 18] = nodeValue("Spawn velocity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 2 ] ) + .setDisplay(VALUE_DISPLAY.range); + + inputs[| 19] = nodeValue("Gravity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }) + .rejectArray(); + + inputs[| 20] = nodeValue("Direction wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 21] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true ) + .rejectArray(); + + inputs[| 22] = nodeValue("Surface array", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "Whether to select image from an array in order, at random, or treat array as animation." ) + .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Random", "Order", "Animation", "Scale" ]) + .setVisible(false); + + inputs[| 23] = nodeValue("Animation speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }) + .rejectArray() + .setVisible(false); + + inputs[| 24] = nodeValue("Scatter", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Uniform", "Random" ]); + + inputs[| 25] = nodeValue("Boundary data", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, []) + .setVisible(false, true); + + inputs[| 26] = nodeValue("On animation end", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, ANIM_END_ACTION.loop) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Loop", "Ping pong", "Destroy" ]) + .setVisible(false); + + inputs[| 27] = nodeValue("Spawn", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true) + .rejectArray(); + + inputs[| 28] = nodeValue("Random blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 29] = nodeValue("Directed from center", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Make particle move away from the spawn center.") + .rejectArray(); + + inputs[| 30] = nodeValue("Distribution map", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone) + .rejectArray() + + inputs[| 31] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [] ); + + inputs[| 32] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(100000, 999999)) + .rejectArray(); + + inputs[| 33] = nodeValue("Gravity direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, -90 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 34] = nodeValue("Turning", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 35] = nodeValue("Turn both directions", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply randomized 1, -1 multiplier to the turning speed." ) + .rejectArray(); + + inputs[| 36] = nodeValue("Turn scale with speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, false ) + .rejectArray(); + + inputs[| 37] = nodeValue("Collide ground", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ) + .rejectArray(); + + inputs[| 38] = nodeValue("Ground offset", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0 ) + .rejectArray(); + + inputs[| 39] = nodeValue("Bounce amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 40] = nodeValue("Bounce friction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1, "Apply horizontal friction once particle stop bouncing." ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 41] = nodeValue("Position wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 42] = nodeValue("Rotation wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 43] = nodeValue("Scale wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 44] = nodeValue("Spawn", self, JUNCTION_CONNECT.input, VALUE_TYPE.trigger, false ) + .setDisplay(VALUE_DISPLAY.button, { name: "Trigger" }) + .rejectArray(); + + inputs[| 45] = nodeValue("Follow Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ) + .rejectArray(); + + inputs[| 46] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone ) + .rejectArray(); + + inputs[| 47] = nodeValue("Path Deviation", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11 ) + .rejectArray(); + + input_len = ds_list_size(inputs); + + input_display_list = [ 32, + ["Sprite", false], 0, 22, 23, 26, + ["Spawn", true], 27, 16, 44, 1, 2, 3, 4, 30, 24, 5, + ["Movement", true], 29, 6, 18, + ["Follow path", true, 45], 46, 47, + ["Physics", true], 7, 19, 33, 34, 35, 36, + ["Ground", true, 37], 38, 39, 40, + ["Rotation", true], 15, 8, 9, + ["Scale", true], 10, 17, 11, + ["Wiggles", true], 20, 41, 42, 43, + ["Color", true], 12, 28, 13, 14, + ["Render", true], 21, + ]; + + attributes.part_amount = 512; + array_push(attributeEditors, ["Maximum particles", function() { return attributes.part_amount; }, + new textBox(TEXTBOX_INPUT.number, function(val) { attributes.part_amount = val; }) ]); + + parts = array_create(attributes.part_amount); + parts_runner = 0; + + seed = 0; + spawn_index = 0; + scatter_index = 0; + def_surface = -1; + + surface_cache = {}; + + wiggle_maps = { + wig_psx: new wiggleMap(seed, 1, 1000), + wig_psy: new wiggleMap(seed, 1, 1000), + wig_scx: new wiggleMap(seed, 1, 1000), + wig_scy: new wiggleMap(seed, 1, 1000), + wig_rot: new wiggleMap(seed, 1, 1000), + wig_dir: new wiggleMap(seed, 1, 1000), + }; + + curve_scale = noone; + curve_alpha = noone; + curve_path_div = noone; + + for( var i = 0; i < attributes.part_amount; i++ ) + parts[i] = new __part(self); + + static spawn = function(_time = CURRENT_FRAME, _pos = -1) { #region + var _inSurf = getInputData( 0); + + var _spawn_amount = getInputData( 2); + + var _spawn_area = getInputData( 3); + var _distrib = getInputData( 4); + var _dist_map = getInputData(30); + var _scatter = getInputData(24); + + var _life = getInputData( 5); + var _direction = getInputData( 6); + var _directCenter = getInputData(29); + var _velocity = getInputData(18); + + var _accel = getInputData( 7); + var _grav = getInputData(19); + var _gvDir = getInputData(33); + var _turn = getInputData(34); + var _turnBi = getInputData(35); + var _turnSc = getInputData(36); + + var _follow = getInputData(15); + var _rotation = getInputData( 8); + var _rotation_speed = getInputData( 9); + var _scale = getInputData(10); + var _size = getInputData(17); + + var _color = getInputData(12); + var _blend = getInputData(28); + var _alpha = getInputData(13); + + var _arr_type = getInputData(22); + var _anim_speed = getInputData(23); + var _anim_end = getInputData(26); + + var _ground = getInputData(37); + var _ground_offset = getInputData(38); + var _ground_bounce = getInputData(39); + var _ground_frict = getInputData(40); + + var _path = getInputData(46); + + if(_rotation[1] < _rotation[0]) _rotation[1] += 360; + + var _posDist = []; + + random_set_seed(seed); seed++; + var _amo = irandom_range(_spawn_amount[0], _spawn_amount[1]); + if(_distrib == 2) _posDist = get_points_from_dist(_dist_map, _amo, seed); + + for( var i = 0; i < _amo; i++ ) { + parts_runner = clamp(parts_runner, 0, array_length(parts) - 1); + var part = parts[parts_runner]; + + part.reset(); + + var _spr = _inSurf, _index = 0; + if(is_array(_inSurf)) { + switch(_arr_type) { + case 0 : + _index = irandom(array_length(_inSurf) - 1); + _spr = _inSurf[_index]; + break; + case 1 : + _index = safe_mod(spawn_index, array_length(_inSurf)); + _spr = _inSurf[_index]; + break; + case 2 : + case 3 : + _spr = _inSurf; + break; + } + } + var xx = 0; + var yy = 0; + + if(_pos == -1) { + if(is_instanceof(_spr, SurfaceAtlas)) { + xx = _spawn_area[0] + _spr.x + _spr.w / 2; + yy = _spawn_area[1] + _spr.y + _spr.h / 2; + part.atlas = _spr; + } else if(_distrib < 2) { + var sp = area_get_random_point(_spawn_area, _distrib, _scatter, spawn_index, _amo); + xx = sp[0]; + yy = sp[1]; + } else if(_distrib == 2) { + var sp = array_safe_get_fast(_posDist, i); + if(!is_array(sp)) continue; + + xx = _spawn_area[0] + _spawn_area[2] * (sp[0] * 2 - 1.); + yy = _spawn_area[1] + _spawn_area[3] * (sp[1] * 2 - 1.); + } + } else { + xx = _pos[0]; + yy = _pos[1]; + } + + var _lif = irandom_range(_life[0], _life[1]); + + var _rot = angle_random_eval(_rotation); + var _rot_spd = random_range(_rotation_speed[0], _rotation_speed[1]); + + var _dirr = _directCenter? point_direction(_spawn_area[0], _spawn_area[1], xx, yy) : angle_random_eval(_direction); + + var _velo = random_range(_velocity[0], _velocity[1]); + var _vx = lengthdir_x(_velo, _dirr); + var _vy = lengthdir_y(_velo, _dirr); + var _acc = random_range(_accel[0], _accel[1]); + + var _ss = random_range(_size[0], _size[1]); + var _scx = random_range(_scale[0], _scale[1]) * _ss; + var _scy = random_range(_scale[2], _scale[3]) * _ss; + + var _alp = random_range(_alpha[0], _alpha[1]); + var _bld = _blend.eval(random(1)); + + part.seed = irandom_range(100000, 999999); + part.create(_spr, xx, yy, _lif); + part.anim_speed = random_range(_anim_speed[0], _anim_speed[1]); + part.anim_end = _anim_end; + part.arr_type = _arr_type; + + var _trn = random_range(_turn[0], _turn[1]); + if(_turnBi) _trn *= choose(-1, 1); + + var _gravity = random_range(_grav[0], _grav[1]); + + part.setPhysic(_vx, _vy, _acc, _gravity, _gvDir, _trn, _turnSc); + part.setWiggle(wiggle_maps); + part.setGround(_ground, _ground_offset, _ground_bounce, _ground_frict); + part.setTransform(_scx, _scy, curve_scale, _rot, _rot_spd, _follow); + part.setDraw(_color, _bld, _alp, curve_alpha); + part.setPath(_path, curve_path_div); + + spawn_index = safe_mod(spawn_index + 1, attributes.part_amount); + onSpawn(_time, part); + + parts_runner = safe_mod(parts_runner + 1, attributes.part_amount); + } + } #endregion + + static onSpawn = function(_time, part) {} + + static updateParticleForward = function() {} + + static getSurfaceCache = function() { #region + var surfs = getInputData(0); + + if(!is_array(surfs)) surfs = [ surfs ]; + if(array_empty(surfs)) return; + + for( var i = 0, n = array_length(surfs); i < n; i++ ) { + if(is_surface(surface_cache[$ surfs[i]])) continue; + surface_cache[$ surfs[i]] = surface_clone(surfs[i]); + } + } #endregion + + function reset() { #region + getInputs(0); + + var keys = variable_struct_get_names(surface_cache); + for( var i = 0, n = array_length(keys); i < n; i++ ) + surface_free_safe(surface_cache[$ keys[i]]); + surface_cache = {}; + getSurfaceCache(); + + spawn_index = 0; + scatter_index = 0; + + for(var i = 0; i < array_length(parts); i++) { + if(!parts[i].active) continue; + parts[i].kill(false); + } + + #region ----- precomputes ----- + resetSeed(); + + var _wigg_pos = getInputData(41); + var _wigg_rot = getInputData(42); + var _wigg_sca = getInputData(43); + var _wigg_dir = getInputData(20); + + wiggle_maps.wig_psx.check(_wigg_pos[0], _wigg_pos[1], seed + 10); + wiggle_maps.wig_psy.check(_wigg_pos[0], _wigg_pos[1], seed + 20); + wiggle_maps.wig_rot.check(_wigg_rot[0], _wigg_rot[1], seed + 30); + wiggle_maps.wig_scx.check(_wigg_sca[0], _wigg_sca[1], seed + 40); + wiggle_maps.wig_scy.check(_wigg_sca[0], _wigg_sca[1], seed + 50); + wiggle_maps.wig_dir.check(_wigg_dir[0], _wigg_dir[1], seed + 60); + + var _curve_sca = getInputData(11); + var _curve_alp = getInputData(14); + var _curve_pth = getInputData(47); + + curve_scale = new curveMap(_curve_sca, TOTAL_FRAMES); + curve_alpha = new curveMap(_curve_alp, TOTAL_FRAMES); + curve_path_div = new curveMap(_curve_pth, TOTAL_FRAMES); + #endregion + + render(); + } #endregion + + static resetSeed = function() { #region + seed = getInputData(32); + } #endregion + + function checkPartPool() { #region + var _part_amo = attributes.part_amount; + var _curr_amo = array_length(parts); + + if(_part_amo > _curr_amo) { + repeat(_part_amo - _curr_amo) + array_push(parts, new __part(self)); + } else if(_part_amo < _curr_amo) { + array_resize(parts, _part_amo); + } + } #endregion + + static runVFX = function(_time = CURRENT_FRAME, _render = true) { #region + var _spawn_delay = inputs[| 1].getValue(_time); + var _spawn_type = inputs[| 16].getValue(_time); + var _spawn_active = inputs[| 27].getValue(_time); + var _spawn_trig = inputs[| 44].getValue(_time); + + //print($"{_time} : {_spawn_trig} | {ds_list_to_array(inputs[| 44].animator.values)}"); + + getInputs(_time); + getSurfaceCache(); + + if(_spawn_active) { + switch(_spawn_type) { + case 0 : if(safe_mod(_time, _spawn_delay) == 0) spawn(_time); break; + case 1 : if(_time == _spawn_delay) spawn(_time); break; + case 2 : if(_spawn_trig) spawn(_time); break; + } + } + + //print($"\n===== Running VFX {_time} =====") + //var activeParts = 0; + for(var i = 0; i < array_length(parts); i++) { + //activeParts++; + parts[i].step(_time); + } + + //print($"Run VFX frame {_time} seed {seed}"); + //print($"[{display_name}] Running VFX frame {_time}: {activeParts} active particles."); + + if(!_render) return; + + render(_time); + } #endregion + + static onStep = function() {} + + static step = function() { #region + var _inSurf = getInputData(0); + var _dist = getInputData(4); + var _scatt = getInputData(24); + var _dirAng = getInputData(29); + var _turn = getInputData(34); + var _spwTyp = getInputData(16); + var _usePth = getInputData(45); + + inputs[| 6].setVisible(!_dirAng); + + inputs[| 24].setVisible(_dist < 2); + + inputs[| 30].setVisible(_dist == 2, _dist == 2); + + inputs[| 35].setVisible(_turn[0] != 0 && _turn[1] != 0); + inputs[| 36].setVisible(_turn[0] != 0 && _turn[1] != 0); + + inputs[| 22].setVisible(false); + inputs[| 23].setVisible(false); + inputs[| 26].setVisible(false); + + inputs[| 46].setVisible(true, _usePth); + + inputs[| 1].setVisible(_spwTyp < 2); + if(_spwTyp == 0) inputs[| 1].name = "Spawn delay"; + else if(_spwTyp == 1) inputs[| 1].name = "Spawn frame"; + + inputs[| 44].setVisible(_spwTyp == 2); + + if(is_array(_inSurf)) { + inputs[| 22].setVisible(true); + var _type = getInputData(22); + if(_type == 2) { + inputs[| 23].setVisible(true); + inputs[| 26].setVisible(true); + } + } + + onStep(); + } #endregion + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + var _spr = getInputData(0); + if(is_array(_spr)) _spr = _spr[0]; + var _flag = is_instanceof(_spr, SurfaceAtlas)? 0b0001 : 0b0011; + + inputs[| 3].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, _flag); + if(onDrawOverlay != -1) + onDrawOverlay(active, _x, _y, _s, _mx, _my); + } #endregion + + static onDrawOverlay = -1; + + static update = function(frame = CURRENT_FRAME) { #region + checkPartPool(); + onUpdate(frame); + } #endregion + + static onUpdate = function(frame = CURRENT_FRAME) {} + + static render = function() {} + + static onPartCreate = noone; + static onPartStep = noone; + static onPartDestroy = noone; + + static doSerialize = function(_map) { #region + _map.part_base_length = input_len; + } #endregion + + static postDeserialize = function() { #region + var _tlen = struct_try_get(load_map, "part_base_length", 40); + + for( var i = _tlen; i < input_len; i++ ) + array_insert(load_map.inputs, i, noone); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup1 b/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup1 new file mode 100644 index 000000000..4f5e7a332 --- /dev/null +++ b/#backups/scripts/_node_VFX_spawner/_node_VFX_spawner.gml.backup1 @@ -0,0 +1,539 @@ +// 2024-04-26 09:57:25 +function Node_VFX_Spawner_Base(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "Spawner"; + update_on_frame = true; + + inputs[| 0] = nodeValue("Particle sprite", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone ); + + inputs[| 1] = nodeValue("Spawn delay", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4, "Frames delay between each particle spawn." ) + .rejectArray(); + + inputs[| 2] = nodeValue("Spawn amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 2, 2 ], "Amount of particle spawn in that frame." ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 3] = nodeValue("Spawn area", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, DEF_AREA ) + .setDisplay(VALUE_DISPLAY.area); + + inputs[| 4] = nodeValue("Spawn distribution", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Area", "Border", "Map" ] ); + + inputs[| 5] = nodeValue("Lifespan", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 20, 30 ] ) + .setDisplay(VALUE_DISPLAY.range); + + inputs[| 6] = nodeValue("Spawn direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 45, 135, 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.rotation_random); + + inputs[| 7] = nodeValue("Acceleration", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 8] = nodeValue("Orientation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 0, 0, 0, 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.rotation_random); + + inputs[| 9] = nodeValue("Rotational speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 10] = nodeValue("Spawn scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1, 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.vector_range, { linked : true }); + + inputs[| 11] = nodeValue("Scale over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11 ); + + inputs[| 12] = nodeValue("Color over lifetime", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 13] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ]) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 14] = nodeValue("Alpha over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11); + + inputs[| 15] = nodeValue("Rotate by direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Make the particle rotates to follow its movement."); + + inputs[| 16] = nodeValue("Spawn type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Stream", "Burst", "Trigger" ]); + + inputs[| 17] = nodeValue("Spawn size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 18] = nodeValue("Spawn velocity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 2 ] ) + .setDisplay(VALUE_DISPLAY.range); + + inputs[| 19] = nodeValue("Gravity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }) + .rejectArray(); + + inputs[| 20] = nodeValue("Direction wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 21] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true ) + .rejectArray(); + + inputs[| 22] = nodeValue("Surface array", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, "Whether to select image from an array in order, at random, or treat array as animation." ) + .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Random", "Order", "Animation", "Scale" ]) + .setVisible(false); + + inputs[| 23] = nodeValue("Animation speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }) + .rejectArray() + .setVisible(false); + + inputs[| 24] = nodeValue("Scatter", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Uniform", "Random" ]); + + inputs[| 25] = nodeValue("Boundary data", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, []) + .setVisible(false, true); + + inputs[| 26] = nodeValue("On animation end", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, ANIM_END_ACTION.loop) + .rejectArray() + .setDisplay(VALUE_DISPLAY.enum_button, [ "Loop", "Ping pong", "Destroy" ]) + .setVisible(false); + + inputs[| 27] = nodeValue("Spawn", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true) + .rejectArray(); + + inputs[| 28] = nodeValue("Random blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 29] = nodeValue("Directed from center", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Make particle move away from the spawn center.") + .rejectArray(); + + inputs[| 30] = nodeValue("Distribution map", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone) + .rejectArray() + + inputs[| 31] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [] ) + .setArrayDepth(1) + .rejectArray(); + + inputs[| 32] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(100000, 999999)) + .rejectArray(); + + inputs[| 33] = nodeValue("Gravity direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, -90 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 34] = nodeValue("Turning", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.range, { linked : true }); + + inputs[| 35] = nodeValue("Turn both directions", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply randomized 1, -1 multiplier to the turning speed." ) + .rejectArray(); + + inputs[| 36] = nodeValue("Turn scale with speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, false ) + .rejectArray(); + + inputs[| 37] = nodeValue("Collide ground", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ) + .rejectArray(); + + inputs[| 38] = nodeValue("Ground offset", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0 ) + .rejectArray(); + + inputs[| 39] = nodeValue("Bounce amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5 ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 40] = nodeValue("Bounce friction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1, "Apply horizontal friction once particle stop bouncing." ) + .rejectArray() + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 41] = nodeValue("Position wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 42] = nodeValue("Rotation wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 43] = nodeValue("Scale wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) + .setDisplay(VALUE_DISPLAY.vector, { label: [ "Amplitude", "Period" ], linkable: false, per_line: true }) + .rejectArray(); + + inputs[| 44] = nodeValue("Spawn", self, JUNCTION_CONNECT.input, VALUE_TYPE.trigger, false ) + .setDisplay(VALUE_DISPLAY.button, { name: "Trigger" }) + .rejectArray(); + + inputs[| 45] = nodeValue("Follow Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ) + .rejectArray(); + + inputs[| 46] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone ) + .rejectArray(); + + inputs[| 47] = nodeValue("Path Deviation", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11 ) + .rejectArray(); + + input_len = ds_list_size(inputs); + + input_display_list = [ 32, + ["Sprite", false], 0, 22, 23, 26, + ["Spawn", true], 27, 16, 44, 1, 2, 3, 4, 30, 24, 5, + ["Movement", true], 29, 6, 18, + ["Follow path", true, 45], 46, 47, + ["Physics", true], 7, 19, 33, 34, 35, 36, + ["Ground", true, 37], 38, 39, 40, + ["Rotation", true], 15, 8, 9, + ["Scale", true], 10, 17, 11, + ["Wiggles", true], 20, 41, 42, 43, + ["Color", true], 12, 28, 13, 14, + ["Render", true], 21, + ]; + + attributes.part_amount = 512; + array_push(attributeEditors, ["Maximum particles", function() { return attributes.part_amount; }, + new textBox(TEXTBOX_INPUT.number, function(val) { attributes.part_amount = val; }) ]); + + parts = array_create(attributes.part_amount); + parts_runner = 0; + + seed = 0; + spawn_index = 0; + scatter_index = 0; + def_surface = -1; + + surface_cache = {}; + + wiggle_maps = { + wig_psx: new wiggleMap(seed, 1, 1000), + wig_psy: new wiggleMap(seed, 1, 1000), + wig_scx: new wiggleMap(seed, 1, 1000), + wig_scy: new wiggleMap(seed, 1, 1000), + wig_rot: new wiggleMap(seed, 1, 1000), + wig_dir: new wiggleMap(seed, 1, 1000), + }; + + curve_scale = noone; + curve_alpha = noone; + curve_path_div = noone; + + for( var i = 0; i < attributes.part_amount; i++ ) + parts[i] = new __part(self); + + static spawn = function(_time = CURRENT_FRAME, _pos = -1) { #region + var _inSurf = getInputData( 0); + + var _spawn_amount = getInputData( 2); + + var _spawn_area = getInputData( 3); + var _distrib = getInputData( 4); + var _dist_map = getInputData(30); + var _scatter = getInputData(24); + + var _life = getInputData( 5); + var _direction = getInputData( 6); + var _directCenter = getInputData(29); + var _velocity = getInputData(18); + + var _accel = getInputData( 7); + var _grav = getInputData(19); + var _gvDir = getInputData(33); + var _turn = getInputData(34); + var _turnBi = getInputData(35); + var _turnSc = getInputData(36); + + var _follow = getInputData(15); + var _rotation = getInputData( 8); + var _rotation_speed = getInputData( 9); + var _scale = getInputData(10); + var _size = getInputData(17); + + var _color = getInputData(12); + var _blend = getInputData(28); + var _alpha = getInputData(13); + + var _arr_type = getInputData(22); + var _anim_speed = getInputData(23); + var _anim_end = getInputData(26); + + var _ground = getInputData(37); + var _ground_offset = getInputData(38); + var _ground_bounce = getInputData(39); + var _ground_frict = getInputData(40); + + var _path = getInputData(46); + + if(_rotation[1] < _rotation[0]) _rotation[1] += 360; + + var _posDist = []; + + random_set_seed(seed); seed++; + var _amo = irandom_range(_spawn_amount[0], _spawn_amount[1]); + if(_distrib == 2) _posDist = get_points_from_dist(_dist_map, _amo, seed); + + for( var i = 0; i < _amo; i++ ) { + parts_runner = clamp(parts_runner, 0, array_length(parts) - 1); + var part = parts[parts_runner]; + + part.reset(); + + var _spr = _inSurf, _index = 0; + if(is_array(_inSurf)) { + switch(_arr_type) { + case 0 : + _index = irandom(array_length(_inSurf) - 1); + _spr = _inSurf[_index]; + break; + case 1 : + _index = safe_mod(spawn_index, array_length(_inSurf)); + _spr = _inSurf[_index]; + break; + case 2 : + case 3 : + _spr = _inSurf; + break; + } + } + var xx = 0; + var yy = 0; + + if(_pos == -1) { + if(is_instanceof(_spr, SurfaceAtlas)) { + xx = _spawn_area[0] + _spr.x + _spr.w / 2; + yy = _spawn_area[1] + _spr.y + _spr.h / 2; + part.atlas = _spr; + } else if(_distrib < 2) { + var sp = area_get_random_point(_spawn_area, _distrib, _scatter, spawn_index, _amo); + xx = sp[0]; + yy = sp[1]; + } else if(_distrib == 2) { + var sp = array_safe_get_fast(_posDist, i); + if(!is_array(sp)) continue; + + xx = _spawn_area[0] + _spawn_area[2] * (sp[0] * 2 - 1.); + yy = _spawn_area[1] + _spawn_area[3] * (sp[1] * 2 - 1.); + } + } else { + xx = _pos[0]; + yy = _pos[1]; + } + + var _lif = irandom_range(_life[0], _life[1]); + + var _rot = angle_random_eval(_rotation); + var _rot_spd = random_range(_rotation_speed[0], _rotation_speed[1]); + + var _dirr = _directCenter? point_direction(_spawn_area[0], _spawn_area[1], xx, yy) : angle_random_eval(_direction); + + var _velo = random_range(_velocity[0], _velocity[1]); + var _vx = lengthdir_x(_velo, _dirr); + var _vy = lengthdir_y(_velo, _dirr); + var _acc = random_range(_accel[0], _accel[1]); + + var _ss = random_range(_size[0], _size[1]); + var _scx = random_range(_scale[0], _scale[1]) * _ss; + var _scy = random_range(_scale[2], _scale[3]) * _ss; + + var _alp = random_range(_alpha[0], _alpha[1]); + var _bld = _blend.eval(random(1)); + + part.seed = irandom_range(100000, 999999); + part.create(_spr, xx, yy, _lif); + part.anim_speed = random_range(_anim_speed[0], _anim_speed[1]); + part.anim_end = _anim_end; + part.arr_type = _arr_type; + + var _trn = random_range(_turn[0], _turn[1]); + if(_turnBi) _trn *= choose(-1, 1); + + var _gravity = random_range(_grav[0], _grav[1]); + + part.setPhysic(_vx, _vy, _acc, _gravity, _gvDir, _trn, _turnSc); + part.setWiggle(wiggle_maps); + part.setGround(_ground, _ground_offset, _ground_bounce, _ground_frict); + part.setTransform(_scx, _scy, curve_scale, _rot, _rot_spd, _follow); + part.setDraw(_color, _bld, _alp, curve_alpha); + part.setPath(_path, curve_path_div); + + spawn_index = safe_mod(spawn_index + 1, attributes.part_amount); + onSpawn(_time, part); + + parts_runner = safe_mod(parts_runner + 1, attributes.part_amount); + } + } #endregion + + static onSpawn = function(_time, part) {} + + static updateParticleForward = function() {} + + static getSurfaceCache = function() { #region + var surfs = getInputData(0); + + if(!is_array(surfs)) surfs = [ surfs ]; + if(array_empty(surfs)) return; + + for( var i = 0, n = array_length(surfs); i < n; i++ ) { + if(is_surface(surface_cache[$ surfs[i]])) continue; + surface_cache[$ surfs[i]] = surface_clone(surfs[i]); + } + } #endregion + + function reset() { #region + getInputs(0); + + var keys = variable_struct_get_names(surface_cache); + for( var i = 0, n = array_length(keys); i < n; i++ ) + surface_free_safe(surface_cache[$ keys[i]]); + surface_cache = {}; + getSurfaceCache(); + + spawn_index = 0; + scatter_index = 0; + + for(var i = 0; i < array_length(parts); i++) { + if(!parts[i].active) continue; + parts[i].kill(false); + } + + #region ----- precomputes ----- + resetSeed(); + + var _wigg_pos = getInputData(41); + var _wigg_rot = getInputData(42); + var _wigg_sca = getInputData(43); + var _wigg_dir = getInputData(20); + + wiggle_maps.wig_psx.check(_wigg_pos[0], _wigg_pos[1], seed + 10); + wiggle_maps.wig_psy.check(_wigg_pos[0], _wigg_pos[1], seed + 20); + wiggle_maps.wig_rot.check(_wigg_rot[0], _wigg_rot[1], seed + 30); + wiggle_maps.wig_scx.check(_wigg_sca[0], _wigg_sca[1], seed + 40); + wiggle_maps.wig_scy.check(_wigg_sca[0], _wigg_sca[1], seed + 50); + wiggle_maps.wig_dir.check(_wigg_dir[0], _wigg_dir[1], seed + 60); + + var _curve_sca = getInputData(11); + var _curve_alp = getInputData(14); + var _curve_pth = getInputData(47); + + curve_scale = new curveMap(_curve_sca, TOTAL_FRAMES); + curve_alpha = new curveMap(_curve_alp, TOTAL_FRAMES); + curve_path_div = new curveMap(_curve_pth, TOTAL_FRAMES); + #endregion + + render(); + } #endregion + + static resetSeed = function() { #region + seed = getInputData(32); + } #endregion + + function checkPartPool() { #region + var _part_amo = attributes.part_amount; + var _curr_amo = array_length(parts); + + if(_part_amo > _curr_amo) { + repeat(_part_amo - _curr_amo) + array_push(parts, new __part(self)); + } else if(_part_amo < _curr_amo) { + array_resize(parts, _part_amo); + } + } #endregion + + static runVFX = function(_time = CURRENT_FRAME, _render = true) { #region + var _spawn_delay = inputs[| 1].getValue(_time); + var _spawn_type = inputs[| 16].getValue(_time); + var _spawn_active = inputs[| 27].getValue(_time); + var _spawn_trig = inputs[| 44].getValue(_time); + + //print($"{_time} : {_spawn_trig} | {ds_list_to_array(inputs[| 44].animator.values)}"); + + getInputs(_time); + getSurfaceCache(); + + if(_spawn_active) { + switch(_spawn_type) { + case 0 : if(safe_mod(_time, _spawn_delay) == 0) spawn(_time); break; + case 1 : if(_time == _spawn_delay) spawn(_time); break; + case 2 : if(_spawn_trig) spawn(_time); break; + } + } + + //print($"\n===== Running VFX {_time} =====") + //var activeParts = 0; + for(var i = 0; i < array_length(parts); i++) { + //activeParts++; + parts[i].step(_time); + } + + //print($"Run VFX frame {_time} seed {seed}"); + //print($"[{display_name}] Running VFX frame {_time}: {activeParts} active particles."); + + if(!_render) return; + + render(_time); + } #endregion + + static onStep = function() {} + + static step = function() { #region + var _inSurf = getInputData(0); + var _dist = getInputData(4); + var _scatt = getInputData(24); + var _dirAng = getInputData(29); + var _turn = getInputData(34); + var _spwTyp = getInputData(16); + var _usePth = getInputData(45); + + inputs[| 6].setVisible(!_dirAng); + + inputs[| 24].setVisible(_dist < 2); + + inputs[| 30].setVisible(_dist == 2, _dist == 2); + + inputs[| 35].setVisible(_turn[0] != 0 && _turn[1] != 0); + inputs[| 36].setVisible(_turn[0] != 0 && _turn[1] != 0); + + inputs[| 22].setVisible(false); + inputs[| 23].setVisible(false); + inputs[| 26].setVisible(false); + + inputs[| 46].setVisible(true, _usePth); + + inputs[| 1].setVisible(_spwTyp < 2); + if(_spwTyp == 0) inputs[| 1].name = "Spawn delay"; + else if(_spwTyp == 1) inputs[| 1].name = "Spawn frame"; + + inputs[| 44].setVisible(_spwTyp == 2); + + if(is_array(_inSurf)) { + inputs[| 22].setVisible(true); + var _type = getInputData(22); + if(_type == 2) { + inputs[| 23].setVisible(true); + inputs[| 26].setVisible(true); + } + } + + onStep(); + } #endregion + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + var _spr = getInputData(0); + if(is_array(_spr)) _spr = _spr[0]; + var _flag = is_instanceof(_spr, SurfaceAtlas)? 0b0001 : 0b0011; + + inputs[| 3].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, _flag); + if(onDrawOverlay != -1) + onDrawOverlay(active, _x, _y, _s, _mx, _my); + } #endregion + + static onDrawOverlay = -1; + + static update = function(frame = CURRENT_FRAME) { #region + checkPartPool(); + onUpdate(frame); + } #endregion + + static onUpdate = function(frame = CURRENT_FRAME) {} + + static render = function() {} + + static onPartCreate = noone; + static onPartStep = noone; + static onPartDestroy = noone; + + static doSerialize = function(_map) { #region + _map.part_base_length = input_len; + } #endregion + + static postDeserialize = function() { #region + var _tlen = struct_try_get(load_map, "part_base_length", 40); + + for( var i = _tlen; i < input_len; i++ ) + array_insert(load_map.inputs, i, noone); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/buffer_functions/buffer_functions.gml.backup0 b/#backups/scripts/buffer_functions/buffer_functions.gml.backup0 new file mode 100644 index 000000000..f706da6e4 --- /dev/null +++ b/#backups/scripts/buffer_functions/buffer_functions.gml.backup0 @@ -0,0 +1,103 @@ +// 2024-04-26 10:28:56 +function buffer_get_color(buffer, _x, _y, w, h) { #region + buffer_seek(buffer, buffer_seek_start, (w * _y + _x) * 4); + var c = buffer_read(buffer, buffer_u32); + + return c; +} #endregion + +function buffer_get_string(buffer, text = true, limit = 400) { #region + if(is_array(buffer)) return "[buffer array]"; + if(!buffer_exists(buffer)) return ""; + + buffer_seek(buffer, buffer_seek_start, 0); + var len = min(limit, buffer_get_size(buffer)); + var ss = ""; + + for (var i = 0; i < len; i++) { + var _r = buffer_read(buffer, buffer_u8); + var _s = text? chr(_r) : dec_to_hex(_r, 2); + ss += _s; + if(!text && i % 2) ss += " "; + } + + return ss; +} #endregion + +function buffer_from_string(str) { #region + var _b = buffer_create(string_length(str) * 1, buffer_fast, 1); + for( var i = 1; i <= string_length(str); i++ ) + buffer_write(_b, buffer_u8, ord(string_char_at(str, i))); + return _b; +} #endregion + +function buffer_from_surface(surface, header = true) { #region + static header_length = 24; + if(!is_surface(surface)) return noone; + + var bitSize = surface_format_get_bytes(surface_get_format(surface)); + + var _b = buffer_create((header_length * header) + surface_get_width_safe(surface) * surface_get_height_safe(surface) * bitSize, buffer_fixed, 1); + if(header) { + buffer_write(_b, buffer_text, "PXCS"); + buffer_write(_b, buffer_u16, surface_get_width_safe(surface)); + buffer_write(_b, buffer_u16, surface_get_height_safe(surface)); + buffer_write(_b, buffer_u8, surface_get_format(surface)); + } + + buffer_get_surface(_b, surface, header_length * header); + return _b; +} #endregion + +function buffer_from_file(path) { #region + if(!file_exists_empty(path)) return; + var _b = buffer_load(path); + return _b; +} #endregion + +function buffer_read_at(buffer, position, type) { #region + buffer_seek(buffer, buffer_seek_start, position); + return buffer_read(buffer, type); +} #endregion + +function buffer_serialize(buffer, compress = true) { #region + INLINE + if(!buffer_exists(buffer)) return ""; + + if(compress) { + var comp = buffer_compress(buffer, 0, buffer_get_size(buffer)); + return buffer_base64_encode(comp, 0, buffer_get_size(comp)); + } + + return buffer_base64_encode(buffer, 0, buffer_get_size(buffer)); +} #endregion + +function buffer_deserialize(buffer, compress = true) { #region + INLINE + var buff = buffer_base64_decode(buffer); + + if(!compress) return buff; + return buffer_decompress(buff); +} #endregion + +function buffer_getPixel(buffer, _w, _h, _x, _y) { #region + if(_x < 0 || _y < 0 || _x >= _w || _y >= _h) return 0; + + buffer_seek(buffer, buffer_seek_start, (_w * _y + _x) * 4); + return buffer_read(buffer, buffer_u32); +} #endregion + +function buffer_setPixel(buffer, _w, _h, _x, _y, _c) { #region + if(_x < 0 || _y < 0 || _x >= _w || _y >= _h) return 0; + + buffer_seek(buffer, buffer_seek_start, (_w * _y + _x) * 4); + buffer_write(buffer, buffer_u32, _c); +} #endregion + +function buffer_compress_string(str) { #region + var _len = string_length(str); + var buffer = buffer_create(1, buffer_grow, 1); + + buffer_write(buffer, buffer_string, str); + return buffer_compress(buffer, 0, buffer_get_size(buffer)); +} #endregion \ No newline at end of file diff --git a/#backups/scripts/buffer_functions/buffer_functions.gml.backup1 b/#backups/scripts/buffer_functions/buffer_functions.gml.backup1 new file mode 100644 index 000000000..b62c3f3c3 --- /dev/null +++ b/#backups/scripts/buffer_functions/buffer_functions.gml.backup1 @@ -0,0 +1,103 @@ +// 2024-04-26 10:28:10 +function buffer_get_color(buffer, _x, _y, w, h) { #region + buffer_seek(buffer, buffer_seek_start, (w * _y + _x) * 4); + var c = buffer_read(buffer, buffer_u32); + + return c; +} #endregion + +function buffer_get_string(buffer, text = true, limit = 400) { #region + if(is_array(buffer)) return "[buffer array]"; + if(!buffer_exists(buffer)) return ""; + + buffer_seek(buffer, buffer_seek_start, 0); + var len = min(limit, buffer_get_size(buffer)); + var ss = ""; + + for (var i = 0; i < len; i++) { + var _r = buffer_read(buffer, buffer_u8); + var _s = text? chr(_r) : dec_to_hex(_r, 2); + ss += _s; + if(!text && i % 2) ss += " "; + } + + return ss; +} #endregion + +function buffer_from_string(str) { #region + var _b = buffer_create(string_length(str) * 1, buffer_fast, 1); + for( var i = 1; i <= string_length(str); i++ ) + buffer_write(_b, buffer_u8, ord(string_char_at(str, i))); + return _b; +} #endregion + +function buffer_from_surface(surface, header = true) { #region + static header_length = 24; + if(!is_surface(surface)) return noone; + + var bitSize = surface_format_get_bytes(surface_get_format(surface)); + + var _b = buffer_create((header_length * header) + surface_get_width_safe(surface) * surface_get_height_safe(surface) * bitSize, buffer_fixed, 1); + if(header) { + buffer_write(_b, buffer_text, "PXCS"); + buffer_write(_b, buffer_u16, surface_get_width_safe(surface)); + buffer_write(_b, buffer_u16, surface_get_height_safe(surface)); + buffer_write(_b, buffer_u8, surface_get_format(surface)); + } + + buffer_get_surface(_b, surface, header_length * header); + return _b; +} #endregion + +function buffer_from_file(path) { #region + if(!file_exists_empty(path)) return; + var _b = buffer_load(path); + return _b; +} #endregion + +function buffer_read_at(buffer, position, type) { #region + buffer_seek(buffer, buffer_seek_start, position); + return buffer_read(buffer, type); +} #endregion + +function buffer_serialize(buffer, compress = true) { #region + INLINE + if(!buffer_exists(buffer)) return ""; + + if(compress) { + var comp = buffer_compress(buffer, 0, buffer_get_size(buffer)); + return buffer_base64_encode(comp, 0, buffer_get_size(comp)); + } + + return buffer_base64_encode(buffer, 0, buffer_get_size(buffer)); +} #endregion + +function buffer_deserialize(buffer, compress = true) { #region + INLINE + var buff = buffer_base64_decode(buffer); + + if(!compress) return buff; + return buffer_decompress(buff); +} #endregion + +function buffer_getPixel(buffer, _w, _h, _x, _y) { #region + if(_x < 0 || _y < 0 || _x >= _w || _y >= _h) return 0; + + buffer_seek(buffer, buffer_seek_start, (_w * _y + _x) * 4); + return buffer_read(buffer, buffer_u32); +} #endregion + +function buffer_setPixel(buffer, _w, _h, _x, _y, _c) { #region + if(_x < 0 || _y < 0 || _x >= _w || _y >= _h) return 0; + + buffer_seek(buffer, buffer_seek_start, (_w * _y + _x) * 4); + buffer_write(buffer, buffer_u32, _c); +} #endregion + +function buffer_compress_string(str) { #region + var _len = string_length(str); + var buffer = buffer_create(1, buffer_grow, 1); + + buffer_write(buffer, buffer_string, str); + return buffer_compress(buffer, 0, buffer_get_size(buffer)); +} #endregion \ No newline at end of file diff --git a/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup0 b/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup0 new file mode 100644 index 000000000..4076bec6b --- /dev/null +++ b/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup0 @@ -0,0 +1,167 @@ +// 2024-04-26 12:05:51 +function __vec3Sub(_x = 0, _y = _x, _z = _x) : __vec3(_x, _y, _z) constructor { + old = false; + connected = []; + + static smooth = function() { + if(array_empty(connected)) return; + + var _n = array_length(connected); + var _k = _n / 2; + var beta = 3 / (5 * _k); + var _sx = x * (1 - _k * beta); + var _sy = y * (1 - _k * beta); + var _sz = z * (1 - _k * beta); + var _cx = 0; + var _cy = 0; + var _cz = 0; + + for( var i = 0; i < _n; i++ ) { + _cx += connected[i].x; + _cy += connected[i].y; + _cz += connected[i].z; + } + + x = _cx * 0.5 * beta + _sx; + y = _cy * 0.5 * beta + _sy; + z = _cz * 0.5 * beta + _sz; + } + + static connectTo = function(point) { array_push(connected, point); } +} + +function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() constructor { + VF = global.VF_POS_NORM_TEX_COL; + render_type = pr_trianglelist; + + self.radius = radius; + self.level = level; + self.smooth = smt; + + _vhash = ds_map_create(); + + static getVertex = function(vertex) { + var h = $"[{vertex.x},{vertex.y},{vertex.z}]"; + if(ds_map_exists(_vhash, h)) + return _vhash[? h]; + _vhash[? h] = vertex; + return vertex; + } + + static initModel = function() { // swap H, V because fuck me + var _vertices = ds_list_create(); + var _normals = ds_list_create(); + + var phi = (1 + sqrt(5)) * 0.5; // golden ratio + var a = 1.0; + var b = 1.0 / phi; + + icoverts = [ + new __vec3Sub( 1, 1, 1)._normalize()._multiply(radius), + new __vec3Sub( 0, b, -a)._normalize()._multiply(radius), + new __vec3Sub( b, a, 0)._normalize()._multiply(radius), + new __vec3Sub(-b, a, 0)._normalize()._multiply(radius), + new __vec3Sub( 0, b, a)._normalize()._multiply(radius), + new __vec3Sub( 0, -b, a)._normalize()._multiply(radius), + new __vec3Sub(-a, 0, b)._normalize()._multiply(radius), + new __vec3Sub( 0, -b, -a)._normalize()._multiply(radius), + new __vec3Sub( a, 0, -b)._normalize()._multiply(radius), + new __vec3Sub( a, 0, b)._normalize()._multiply(radius), + new __vec3Sub(-a, 0, -b)._normalize()._multiply(radius), + new __vec3Sub( b, -a, 0)._normalize()._multiply(radius), + new __vec3Sub(-b, -a, 0)._normalize()._multiply(radius), + ] + + array_foreach(icoverts, function(vert) { vert.old = true; }); + + // Generate icosphere vertices + ds_list_add(_vertices, icoverts[ 3], icoverts[ 1], icoverts[ 2]); + ds_list_add(_vertices, icoverts[ 2], icoverts[ 4], icoverts[ 3]); + ds_list_add(_vertices, icoverts[ 6], icoverts[ 4], icoverts[ 5]); + ds_list_add(_vertices, icoverts[ 5], icoverts[ 4], icoverts[ 9]); + ds_list_add(_vertices, icoverts[ 8], icoverts[ 1], icoverts[ 7]); + ds_list_add(_vertices, icoverts[ 7], icoverts[ 1], icoverts[10]); + ds_list_add(_vertices, icoverts[12], icoverts[ 5], icoverts[11]); + ds_list_add(_vertices, icoverts[11], icoverts[ 7], icoverts[12]); + ds_list_add(_vertices, icoverts[10], icoverts[ 3], icoverts[ 6]); + ds_list_add(_vertices, icoverts[ 6], icoverts[12], icoverts[10]); + ds_list_add(_vertices, icoverts[ 9], icoverts[ 2], icoverts[ 8]); + ds_list_add(_vertices, icoverts[ 8], icoverts[11], icoverts[ 9]); + ds_list_add(_vertices, icoverts[ 3], icoverts[ 4], icoverts[ 6]); + ds_list_add(_vertices, icoverts[ 9], icoverts[ 4], icoverts[ 2]); + ds_list_add(_vertices, icoverts[10], icoverts[ 1], icoverts[ 3]); + ds_list_add(_vertices, icoverts[ 2], icoverts[ 1], icoverts[ 8]); + ds_list_add(_vertices, icoverts[12], icoverts[ 7], icoverts[10]); + ds_list_add(_vertices, icoverts[ 8], icoverts[ 7], icoverts[11]); + ds_list_add(_vertices, icoverts[ 6], icoverts[ 5], icoverts[12]); + ds_list_add(_vertices, icoverts[11], icoverts[ 5], icoverts[ 9]); + + var lv = min(level, 5); + repeat(lv) { #region subdivide + ds_map_clear(_vhash); + var newVertices = ds_list_create(); + + for (var i = 0, n = ds_list_size(_vertices) / 3; i < n; i++) { + var v1 = _vertices[| i * 3 + 0]; + var v2 = _vertices[| i * 3 + 1]; + var v3 = _vertices[| i * 3 + 2]; + + var mid12Pos = getVertex(new __vec3Sub(v1.add(v2).divide(2))); + var mid23Pos = getVertex(new __vec3Sub(v2.add(v3).divide(2))); + var mid31Pos = getVertex(new __vec3Sub(v3.add(v1).divide(2))); + + v1.connectTo(mid12Pos); v1.connectTo(mid31Pos); + v2.connectTo(mid12Pos); v2.connectTo(mid23Pos); + v3.connectTo(mid23Pos); v3.connectTo(mid31Pos); + + ds_list_add(newVertices, v1, mid12Pos, mid31Pos); + ds_list_add(newVertices, mid12Pos, v2, mid23Pos); + ds_list_add(newVertices, mid31Pos, mid23Pos, v3); + ds_list_add(newVertices, mid12Pos, mid23Pos, mid31Pos); + } + + for (var i = 0, n = ds_list_size(newVertices); i < n; i++) { + var _v = newVertices[| i]; + if(_v.old) _v.smooth(); + + _v.old = true; + _v.connected = []; + } + + ds_list_destroy(_vertices); + _vertices = newVertices; + } #endregion + + for( var i = 0, n = ds_list_size(_vertices) / 3; i < n; i++ ) { #region normal, uv generation + var _v0 = _vertices[| i * 3 + 0]; + var _v1 = _vertices[| i * 3 + 1]; + var _v2 = _vertices[| i * 3 + 2]; + if(smooth) { + ds_list_add(_normals, _v0.normalize(), _v1.normalize(), _v2.normalize()); + } else { + var _n = _v2.subtract(_v0).cross(_v1.subtract(_v0)); + ds_list_add(_normals, _n, _n, _n); + } + } #endregion + + vertex = [ array_create(ds_list_size(_vertices)) ]; + + for( var i = 0, n = ds_list_size(_vertices); i < n; i++ ) { + var _v = _vertices[| i]; + var _n = _normals[| i]; + + var _ha = point_direction(0, 0, _v.x, _v.y); + var _va = (point_direction(0, 0, _v.x, _v.z) + 90) % 360; + if(_va > 180) _va = 360 - _va; + + vertex[0][i] = new __vertex(_v.x, _v.y, _v.z).setNormal(_n.x, _n.y, _n.z).setUV(_ha / 360, _va / 180); + } + + ds_list_destroy(_vertices); + ds_list_destroy(_normals); + + VB = build(); + } initModel(); + + static onParameterUpdate = initModel; +} \ No newline at end of file diff --git a/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup1 b/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup1 new file mode 100644 index 000000000..fcdc03ad4 --- /dev/null +++ b/#backups/scripts/d3d_icosphere/d3d_icosphere.gml.backup1 @@ -0,0 +1,167 @@ +// 2024-04-26 12:02:52 +function __vec3Sub(_x = 0, _y = _x, _z = _x) : __vec3(_x, _y, _z) constructor { + old = false; + connected = []; + + static smooth = function() { + if(array_empty(connected)) return; + + var _n = array_length(connected); + var _k = _n / 2; + var beta = 3 / (5 * _k); + var _sx = x * (1 - _k * beta); + var _sy = y * (1 - _k * beta); + var _sz = z * (1 - _k * beta); + var _cx = 0; + var _cy = 0; + var _cz = 0; + + for( var i = 0; i < _n; i++ ) { + _cx += connected[i].x; + _cy += connected[i].y; + _cz += connected[i].z; + } + + x = _cx * 0.5 * beta + _sx; + y = _cy * 0.5 * beta + _sy; + z = _cz * 0.5 * beta + _sz; + } + + static connectTo = function(point) { array_push(connected, point); } +} + +function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() constructor { + VF = global.VF_POS_NORM_TEX_COL; + render_type = pr_trianglelist; + + self.radius = radius; + self.level = level; + self.smooth = smt; + + _vhash = ds_map_create(); + + static getVertex = function(vertex) { + var h = $"[{vertex.x},{vertex.y},{vertex.z}]"; + if(ds_map_exists(_vhash, h)) + return _vhash[? h]; + _vhash[? h] = vertex; + return vertex; + } + + static initModel = function() { // swap H, V because fuck me + var _vertices = ds_list_create(); + var _normals = ds_list_create(); + + var phi = (1 + sqrt(5)) * 0.5; // golden ratio + var a = 1.0; + var b = 1.0 / phi; + + icoverts = [ + new __vec3Sub( 1, 1, 1)._normalize()._multiply(radius), + new __vec3Sub( 0, b, -a)._normalize()._multiply(radius), + new __vec3Sub( b, a, 0)._normalize()._multiply(radius), + new __vec3Sub(-b, a, 0)._normalize()._multiply(radius), + new __vec3Sub( 0, b, a)._normalize()._multiply(radius), + new __vec3Sub( 0, -b, a)._normalize()._multiply(radius), + new __vec3Sub(-a, 0, b)._normalize()._multiply(radius), + new __vec3Sub( 0, -b, -a)._normalize()._multiply(radius), + new __vec3Sub( a, 0, -b)._normalize()._multiply(radius), + new __vec3Sub( a, 0, b)._normalize()._multiply(radius), + new __vec3Sub(-a, 0, -b)._normalize()._multiply(radius), + new __vec3Sub( b, -a, 0)._normalize()._multiply(radius), + new __vec3Sub(-b, -a, 0)._normalize()._multiply(radius), + ] + + array_foreach(icoverts, function(vert) { vert.old = true; }); + + // Generate icosphere vertices + ds_list_add(_vertices, icoverts[ 3], icoverts[ 1], icoverts[ 2]); + ds_list_add(_vertices, icoverts[ 2], icoverts[ 4], icoverts[ 3]); + ds_list_add(_vertices, icoverts[ 6], icoverts[ 4], icoverts[ 5]); + ds_list_add(_vertices, icoverts[ 5], icoverts[ 4], icoverts[ 9]); + ds_list_add(_vertices, icoverts[ 8], icoverts[ 1], icoverts[ 7]); + ds_list_add(_vertices, icoverts[ 7], icoverts[ 1], icoverts[10]); + ds_list_add(_vertices, icoverts[12], icoverts[ 5], icoverts[11]); + ds_list_add(_vertices, icoverts[11], icoverts[ 7], icoverts[12]); + ds_list_add(_vertices, icoverts[10], icoverts[ 3], icoverts[ 6]); + ds_list_add(_vertices, icoverts[ 6], icoverts[12], icoverts[10]); + ds_list_add(_vertices, icoverts[ 9], icoverts[ 2], icoverts[ 8]); + ds_list_add(_vertices, icoverts[ 8], icoverts[11], icoverts[ 9]); + ds_list_add(_vertices, icoverts[ 3], icoverts[ 4], icoverts[ 6]); + ds_list_add(_vertices, icoverts[ 9], icoverts[ 4], icoverts[ 2]); + ds_list_add(_vertices, icoverts[10], icoverts[ 1], icoverts[ 3]); + ds_list_add(_vertices, icoverts[ 2], icoverts[ 1], icoverts[ 8]); + ds_list_add(_vertices, icoverts[12], icoverts[ 7], icoverts[10]); + ds_list_add(_vertices, icoverts[ 8], icoverts[ 7], icoverts[11]); + ds_list_add(_vertices, icoverts[ 6], icoverts[ 5], icoverts[12]); + ds_list_add(_vertices, icoverts[11], icoverts[ 5], icoverts[ 9]); + + var lv = min(level, 5); + repeat(lv) { #region subdivide + ds_map_clear(_vhash); + var newVertices = ds_list_create(); + + for (var i = 0, n = ds_list_size(_vertices) / 3; i < n; i++) { + var v1 = _vertices[| i * 3 + 0]; + var v2 = _vertices[| i * 3 + 1]; + var v3 = _vertices[| i * 3 + 2]; + + var mid12Pos = getVertex(new __vec3Sub(v1.add(v2).divide(2))); + var mid23Pos = getVertex(new __vec3Sub(v2.add(v3).divide(2))); + var mid31Pos = getVertex(new __vec3Sub(v3.add(v1).divide(2))); + + v1.connectTo(mid12Pos); v1.connectTo(mid31Pos); + v2.connectTo(mid12Pos); v2.connectTo(mid23Pos); + v3.connectTo(mid23Pos); v3.connectTo(mid31Pos); + + ds_list_add(newVertices, v1, mid12Pos, mid31Pos); + ds_list_add(newVertices, mid12Pos, v2, mid23Pos); + ds_list_add(newVertices, mid31Pos, mid23Pos, v3); + ds_list_add(newVertices, mid12Pos, mid23Pos, mid31Pos); + } + + for (var i = 0, n = ds_list_size(newVertices); i < n; i++) { + var _v = newVertices[| i]; + if(_v.old) _v.smooth(); + + _v.old = true; + _v.connected = []; + } + + ds_list_destroy(_vertices); + _vertices = newVertices; + } #endregion + + for( var i = 0, n = ds_list_size(_vertices) / 3; i < n; i++ ) { #region normal, uv generation + var _v0 = _vertices[| i * 3 + 0]; + var _v1 = _vertices[| i * 3 + 1]; + var _v2 = _vertices[| i * 3 + 2]; + if(smooth) { + ds_list_add(_normals, _v0.normalize(), _v1.normalize(), _v2.normalize()); + } else { + var _n = _v2.subtract(_v0).cross(_v1.subtract(_v0)); + ds_list_add(_normals, _n, _n, _n); + } + } #endregion + + vertex = [ array_create(ds_list_size(_vertices)) ]; + + for( var i = 0, n = ds_list_size(_vertices); i < n; i++ ) { + var _v = _vertices[| i]; + var _n = _normals[| i]; + + var _ha = point_direction(0, 0, _v.x, _v.y); + var _va = (point_direction(0, 0, _v.x, _v.z) + 90) % 360; + if(_va > 180) _va = 360 - _va; + + vertex[0][i] = new __vertex(_v.x, _v.y, _v.z).setNormal(_n.x, _n.y, _n.z).setUV(_ha / 360, _va / 180); + } + + ds_list_destroy(_vertices); + ds_list_destroy(_normals); + + VB = build(); + } initModel(); + + static onParameterUpdate = initModel; +} \ No newline at end of file diff --git a/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup0 b/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup0 new file mode 100644 index 000000000..d10b079d0 --- /dev/null +++ b/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup0 @@ -0,0 +1,57 @@ +// 2024-04-26 10:18:35 +function Node_3D_Mesh_Extrude(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group) constructor { + name = "Surface Extrude"; + + object_class = __3dSurfaceExtrude; + + inputs[| in_mesh + 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial()) + .setVisible(true, true); + + inputs[| in_mesh + 1] = nodeValue("Height map", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| in_mesh + 2] = nodeValue("Smooth", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + + inputs[| in_mesh + 3] = nodeValue("Always update", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + input_display_list = [ + __d3d_input_list_mesh, + __d3d_input_list_transform, + ["Extrude", false], in_mesh + 0, in_mesh + 1, in_mesh + 3, + ] + + temp_surface = [ noone, noone ]; + + static processData = function(_output, _data, _output_index, _array_index = 0) { #region + var _mat = _data[in_mesh + 0]; + if(!is_instanceof(_mat, __d3dMaterial)) return noone; + + var _hght = _data[in_mesh + 1]; + var _smt = _data[in_mesh + 2]; + var _updt = _data[in_mesh + 3]; + var _surf = _mat.surface; + if(!is_surface(_surf)) return noone; + + temp_surface[0] = surface_cvt_8unorm(temp_surface[0], _surf); + temp_surface[1] = surface_cvt_8unorm(temp_surface[1], _hght); + + var object = getObject(_array_index); + object.checkParameter({ surface: temp_surface[0], height: temp_surface[1], smooth: _smt }, _updt); + + var _matN = _mat.clone(); + var _nSurf = surface_create(surface_get_width(_surf), surface_get_height(_surf)); + + surface_set_shader(_nSurf, sh_d3d_extrude_extends); + shader_set_dim("dimension", _surf); + draw_surface_safe(_surf); + surface_reset_shader(); + + _matN.surface = _nSurf; + object.materials = [ _matN ]; + + setTransform(object, _data); + + return object; + } #endregion + + static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 0, noone); } +} \ No newline at end of file diff --git a/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup1 b/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup1 new file mode 100644 index 000000000..9ce2035a8 --- /dev/null +++ b/#backups/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml.backup1 @@ -0,0 +1,57 @@ +// 2024-04-26 10:18:30 +function Node_3D_Mesh_Extrude(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group) constructor { + name = "Surface Extrude"; + + object_class = __3dSurfaceExtrude; + + inputs[| in_mesh + 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial()) + .setVisible(true, true); + + inputs[| in_mesh + 1] = nodeValue("Height map", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| in_mesh + 2] = nodeValue("Smooth", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + + inputs[| in_mesh + 3] = nodeValue("Always update", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + input_display_list = [ + __d3d_input_list_mesh, + __d3d_input_list_transform, + ["Extrude", false], in_mesh + 0, in_mesh + 1, in_mesh + 3, + ] + + temp_surface = [ noone, noone ]; + + static processData = function(_output, _data, _output_index, _array_index = 0) { #region + var _mat = _data[in_mesh + 0]; + if(!is_instanceof(_mat, __d3dMaterial)) return noone; + + var _hght = _data[in_mesh + 1]; + var _smt = _data[in_mesh + 2]; + var _updt = _data[in_mesh + 3]; + var _surf = _mat.surface; + if(!is_surface(_surf)) return noone; + + temp_surface[0] = surface_cvt_8unorm(temp_surface[0], _surf); + temp_surface[1] = surface_cvt_8unorm(temp_surface[1], _hght); + + var object = getObject(_array_index); + object.checkParameter({ surface: temp_surface[0], height: temp_surface[1], smooth: _smt }, _updt); + + var _matN = _mat.clone(); + var _nSurf = surface_create(surface_get_width(_surf), surface_get_height(_surf)); + + surface_set_shader(_nSurf, sh_d3d_extrude_extends); + shader_set_dim("dimension", _surf); + draw_surface_safe(_surf); + surface_reset_shader(); + + _matN.surface = _nSurf; + object.materials = [ _matN ]; + + setTransform(object, _data); + + return object; + } #endregion + + static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 0, noone); } +} \ No newline at end of file diff --git a/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup0 b/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup0 index a0e734cfb..407846988 100644 --- a/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup0 +++ b/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup0 @@ -1,4 +1,4 @@ -// 2024-04-25 16:11:38 +// 2024-04-26 08:55:06 function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Replace Colors"; diff --git a/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup1 b/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup1 index 7f8f00481..9f6471de9 100644 --- a/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup1 +++ b/#backups/scripts/node_colors_replace/node_colors_replace.gml.backup1 @@ -1,4 +1,4 @@ -// 2024-04-25 16:11:37 +// 2024-04-26 08:55:01 function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Replace Colors"; diff --git a/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup0 b/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup0 new file mode 100644 index 000000000..25801e6b0 --- /dev/null +++ b/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup0 @@ -0,0 +1,105 @@ +// 2024-04-26 09:11:44 +function Node_Iterate_Inline(_x, _y, _group = noone) : Node_Collection_Inline(_x, _y, _group) constructor { + name = "Loop"; + color = COLORS.node_blend_loop; + icon = THEME.loop; + icon_24 = THEME.loop_24; + + is_root = false; + + inputs[| 0] = nodeValue("Repeat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1 ) + .uncache(); + + managedRenderOrder = true; + + attributes.junc_in = [ "", 0 ]; + attributes.junc_out = [ "", 0 ]; + + junc_in = noone; + junc_out = noone; + + value_buffer = undefined; + iterated = 0; + + static getIterationCount = function() { return getInputData(0); } + + static bypassConnection = function() { return iterated > 0 && !is_undefined(value_buffer); + } #endregion + + static bypassNextNode = function() { #region + return iterated < getIterationCount() - 1; + } #endregion + + static getNextNodes = function() { #region + LOG_BLOCK_START(); + LOG_IF(global.FLAG.render == 1, "[outputNextNode] Get next node from inline iterate"); + + resetRender(); + LOG_IF(global.FLAG.render == 1, $"Loop restart: iteration {iterated}"); + var _nodes = __nodeLeafList(nodes); + array_push_unique(_nodes, junc_in.node); + iterated++; + + LOG_BLOCK_END(); + + return _nodes; + } #endregion + + static scanJunc = function() { #region + var node_in = PROJECT.nodeMap[? attributes.junc_in[0]]; + var node_out = PROJECT.nodeMap[? attributes.junc_out[0]]; + + junc_in = node_in? node_in.inputs[| attributes.junc_in[1]] : noone; + junc_out = node_out? node_out.outputs[| attributes.junc_out[1]] : noone; + + if(junc_in) { junc_in.value_from_loop = self; addNode(junc_in.node); } + if(junc_out) { array_push(junc_out.value_to_loop, self); addNode(junc_out.node); } + } #endregion + + static updateValue = function() { #region + var type = junc_out.type; + var val = junc_out.getValue(); + + switch(type) { + case VALUE_TYPE.surface : + surface_array_free(value_buffer); + value_buffer = surface_array_clone(val); + break; + default : + value_buffer = variable_clone(val); + break; + } + } #endregion + + static getValue = function(arr) { #region + INLINE + + arr[@ 0] = value_buffer; + arr[@ 1] = junc_out; + } #endregion + + static update = function() { #region + iteration_count = inputs[| 0].getValue(); + iterated = 0; + value_buffer = undefined; + } #endregion + + static drawConnections = function(params = {}) { #region + if(!active) return; + if(!junc_in || !junc_out) return; + if(!junc_in.node.active || !junc_out.node.active) return; + + if(drawJuncConnection(junc_out, junc_in, params)) + return self; + } #endregion + + static postDeserialize = function() { #region + refreshMember(); + scanJunc(); + } #endregion + + static onDestroy = function() { #region + if(junc_in) junc_in.value_from_loop = noone; + if(junc_out) array_remove(junc_out.value_to_loop, self); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup1 b/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup1 new file mode 100644 index 000000000..fb32003a4 --- /dev/null +++ b/#backups/scripts/node_iterate_inline/node_iterate_inline.gml.backup1 @@ -0,0 +1,105 @@ +// 2024-04-26 09:08:27 +function Node_Iterate_Inline(_x, _y, _group = noone) : Node_Collection_Inline(_x, _y, _group) constructor { + name = "Loop"; + color = COLORS.node_blend_loop; + icon = THEME.loop; + icon_24 = THEME.loop_24; + + is_root = false; + + inputs[| 0] = nodeValue("Repeat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1 ) + .uncache(); + + managedRenderOrder = true; + + attributes.junc_in = [ "", 0 ]; + attributes.junc_out = [ "", 0 ]; + + junc_in = noone; + junc_out = noone; + + value_buffer = undefined; + iterated = 0; + + static getIterationCount = function() { return getInputData(0); } + + static bypassConnection = function() { return iterated > 0 && !is_undefined(value_buffer); + } #endregion + + static bypassNextNode = function() { #region + return iterated < getIterationCount() - 1; + } #endregion + + static getNextNodes = function() { #region + LOG_BLOCK_START(); + LOG_IF(global.FLAG.render == 1, "[outputNextNode] Get next node from inline iterate"); + + resetRender(); + LOG_IF(global.FLAG.render == 1, $"Loop restart: iteration {iterated}"); + var _nodes = __nodeLeafList(nodes); + array_push_unique(_nodes, junc_in.node); + iterated++; + + LOG_BLOCK_END(); + + return _nodes; + } #endregion + + static scanJunc = function() { #region + var node_in = PROJECT.nodeMap[? attributes.junc_in[0]]; + var node_out = PROJECT.nodeMap[? attributes.junc_out[0]]; + + junc_in = node_in? node_in.inputs[| attributes.junc_in[1]] : noone; + junc_out = node_out? node_out.outputs[| attributes.junc_out[1]] : noone; + + if(junc_in) { junc_in.value_from_loop = self; addNode(junc_in.node); } + if(junc_out) { array_push(junc_out.value_to_loop, self); addNode(junc_out.node); } + } #endregion + + static updateValue = function() { #region + var type = junc_out.type; + var val = junc_out.getValue(); + + switch(type) { + case VALUE_TYPE.surface : + surface_array_free(value_buffer); + value_buffer = surface_array_clone(val); + break; + default : + value_buffer = variable_clone(val); + break; + } + } #endregion + + static getValue = function(arr) { #region + INLINE + + arr[@ 0] = value_buffer; + arr[@ 1] = junc_out; + } #endregion + + static update = function() { #region + iteration_count = inputs[| 0].getValue(); + iterated = 0; + value_buffer = undefined; + } #endregion + + static drawConnections = function(params = {}) { #region + if(!active) return; + if(!junc_in || !junc_out) return; + if(!junc_in.node.active || !junc_out.node.active) return; + + if(drawJuncConnection(junc_out, junc_in, params)) + return self; + } #endregion + + static postDeserialize = function() { #region + refreshMember(); + scanJunc(); + } #endregion + + static onDestroy = function() { #region + if(junc_in) junc_in.value_from_loop = noone; + if(junc_out) array_remove(junc_out.value_to_loop, self); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_line/node_line.gml.backup0 b/#backups/scripts/node_line/node_line.gml.backup0 new file mode 100644 index 000000000..2884650e4 --- /dev/null +++ b/#backups/scripts/node_line/node_line.gml.backup0 @@ -0,0 +1,538 @@ +// 2024-04-26 14:34:25 +function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Line"; + + inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF ) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 1] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 2] = nodeValue("Segment", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1) + .setDisplay(VALUE_DISPLAY.slider, { range: [1, 32, 0.1] }); + + inputs[| 3] = nodeValue("Width", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 2, 2 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 4] = nodeValue("Wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.slider, { range: [0, 16, 0.01] }); + + inputs[| 5] = nodeValue("Random seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0); + + inputs[| 6] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 7] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone, "Draw line along path.") + .setVisible(true, true) + .setArrayDepth(1); + + inputs[| 8] = nodeValue("Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [0, 1], "Range of the path to draw.") + .setDisplay(VALUE_DISPLAY.slider_range); + + inputs[| 9] = nodeValue("Shift", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY._default, { slide_speed: 1 / 64 }); + + inputs[| 10] = nodeValue("Color over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 11] = nodeValue("Width over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11); + + inputs[| 12] = nodeValue("Span width over path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply the full 'width over length' to the trimmed path."); + + inputs[| 13] = nodeValue("Round cap", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 14] = nodeValue("Round segment", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4) + .setDisplay(VALUE_DISPLAY.slider, { range: [2, 16, 0.1] }); + + inputs[| 15] = nodeValue("Span color over path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply the full 'color over length' to the trimmed path."); + + inputs[| 16] = nodeValue("Greyscale over width", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 17] = nodeValue("1px mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Render pixel perfect 1px line."); + + inputs[| 18] = nodeValue("Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| 19] = nodeValue("Fix length", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Fix length of each segment instead of segment count."); + + inputs[| 20] = nodeValue("Segment length", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4); + + inputs[| 21] = nodeValue("Texture position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 22] = nodeValue("Texture rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 23] = nodeValue("Texture scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 24] = nodeValue("Random Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 25] = nodeValue("Invert", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); + + inputs[| 26] = nodeValue("Clamp range", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); + + input_display_list = [ + ["Output", true], 0, 1, + ["Line data", false], 6, 7, 19, 2, 20, + ["Line settings", false], 17, 3, 11, 12, 8, 25, 9, 26, 13, 14, + ["Wiggle", false], 4, 5, + ["Render", false], 10, 24, 15, 16, + ["Texture", false], 18, 21, 22, 23, + ]; + + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + + lines = []; + + widthMap = ds_map_create(); + + attribute_surface_depth(); + attribute_interpolation(); + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + draw_set_color(COLORS._main_accent); + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + for( var j = 1; j < array_length(points); j++ ) { + var x0 = points[j - 1].x; + var y0 = points[j - 1].y; + var x1 = points[j].x; + var y1 = points[j].y; + + x0 = _x + x0 * _s; + y0 = _y + y0 * _s; + x1 = _x + x1 * _s; + y1 = _y + y1 * _s; + + draw_line(x0, y0, x1, y1); + } + } + } #endregion + + static step = function() { #region + var px = !getInputData(17); + var _tex = inputs[| 18].value_from != noone; + var _flen = getInputData(19); + + inputs[| 3].setVisible(px); + inputs[| 11].setVisible(px); + inputs[| 12].setVisible(px); + inputs[| 13].setVisible(px && !_tex); + inputs[| 14].setVisible(px); + inputs[| 18].setVisible(px); + + inputs[| 15].setVisible(!_tex); + inputs[| 16].setVisible(!_tex); + + inputs[| 2].setVisible(!_flen); + inputs[| 20].setVisible( _flen); + } #endregion + + static onValueUpdate = function(index = 0) { #region + if(index == 11) ds_map_clear(widthMap); + } #endregion + + static processData = function(_outSurf, _data, _output_index, _array_index) { #region + #region data + var _dim = _data[0]; + var _bg = _data[1]; + var _seg = _data[2]; + var _wid = _data[3]; + var _wig = _data[4]; + var _sed = _data[5]; + var _ang = _data[6] % 360; + var _pat = _data[7]; + var _ratio = _data[8]; + var _shift = _data[9]; + + var _color = _data[10]; + var _widc = _data[11]; + var _widap = _data[12]; + + var _cap = _data[13]; + var _capP = _data[14]; + var _colP = _data[15]; + var _colW = _data[16]; + var _1px = _data[17]; + + var _fixL = _data[19]; + var _segL = _data[20]; + + var _tex = _data[18]; + var _texPos = _data[21]; + var _texRot = _data[22]; + var _texSca = _data[23]; + + var _colb = _data[24]; + var _ratInv = _data[25]; + var _clamp = _data[26]; + #endregion + + if(IS_FIRST_FRAME || inputs[| 11].is_anim) + ds_map_clear(widthMap); + + var __debug_timer = get_timer(); + + var _rangeMin = min(_ratio[0], _ratio[1]); + var _rangeMax = max(_ratio[0], _ratio[1]); + if(_rangeMax == 1) _rangeMax = 0.99999; + + var _rtStr = min(_rangeMin, _rangeMax); + var _rtMax = max(_rangeMin, _rangeMax); + + var _use_path = is_struct(_pat); + var _useTex = inputs[| 18].value_from != noone; + if(_useTex) { + _cap = false; + _1px = false; + } + + if(_ang < 0) _ang = 360 + _ang; + + inputs[| 6].setVisible(!_use_path); + + random_set_seed(_sed); + var _sedIndex = 0; + + _outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth()); + + var p = new __vec2(); + var _ox, _nx, _nx1, _oy, _ny, _ny1; + var _ow, _nw, _oa, _na, _oc, _nc, _owg, _nwg; + var _pathData = []; + + if(_use_path) { #region + var lineLen = 1; + if(struct_has(_pat, "getLineCount")) + lineLen = _pat.getLineCount(); + if(struct_has(_pat, "getPathData")) + _pathData = _pat.getPathData(); + + lines = array_verify(lines, lineLen); + var _lineAmo = 0; + + if(_rtMax > 0) + for( var i = 0; i < lineLen; i++ ) { + var _useDistance = _fixL && struct_has(_pat, "getLength"); + var _pathLength = _useDistance? _pat.getLength(i) : 1; + if(_pathLength == 0) continue; + + var _pathStr = _rtStr; + var _pathEnd = _rtMax; + + var _stepLen = min(_pathEnd, 1 / _seg); //Distance to move per step + if(_stepLen <= 0.00001) continue; + + var _total = _pathEnd; //Length remaining + var _total_prev = _total; //Use to prevent infinite loop + var _freeze = 0; //Use to prevent infinite loop + + var _prog_curr = _clamp? _shift : frac(_shift); //Pointer to the current position + var _prog_next = 0; + var _prog = _prog_curr + 1; //Record previous position to delete from _total + var _prog_total = 0; //Record the distance the pointer has moved so far + var points = is_array(lines[i])? lines[i] : []; + var pointArrLen = array_length(points); + var pointAmo = 0; + var wght; + var _pathPng; + + if(_useDistance) { + _pathStr *= _pathLength; + _pathEnd *= _pathLength; + _stepLen = min(_segL, _pathEnd); + + _total *= _pathLength; + _total_prev = _total; + + _prog_curr *= _pathLength; + } + + var _segLength = struct_has(_pat, "getAccuLength")? _pat.getAccuLength(i) : []; + var _segLengthAmo = array_length(_segLength); + var _segIndex = 0; + var _segIndexPrev = 0; + + if(_segLengthAmo) + while(_prog_curr > _segLength[_segIndex]) { + _segIndex++; + if(_segIndex == _segLengthAmo) { + _segIndex = 0; + break; + } + } + + // print($"===== {_prog_curr} / {_segLength} : {_segIndex} - {_pathLength} ====="); + + while(true) { + wght = 1; + _segIndexPrev = _segIndex; + + if(_useDistance) { + var segmentLength = array_safe_get_fast(_segLength, _segIndex, _pathLength); + + _prog_next = min(_prog_curr + _stepLen, _pathLength, segmentLength); + _pathPng = _ratInv? _pathLength - _prog_curr : _prog_curr; + + //print($"{segmentLength}/{_pathLength} = {_prog_next}"); + if(_prog_next == segmentLength) _segIndex++; + + var _pp = _clamp? clamp(_pathPng, 0, _pathLength) : _pathPng; + // print($"_pp = {_pp}, total = {_total}"); + + p = _pat.getPointDistance(_pp, i, p); + + if(struct_has(_pat, "getWeightDistance")) + wght = _pat.getWeightDistance(_pp, i); + } else { + _prog_next = min(_prog_curr + _stepLen, 1); //Move forward _stepLen or _total (if less) stop at 1 + _pathPng = _ratInv? 1 - _prog_curr : _prog_curr; + + var _pp = _clamp? clamp(_pathPng, 0, 1) : _pathPng + + p = _pat.getPointRatio(_pp, i, p); + if(struct_has(_pat, "getWeightRatio")) + wght = _pat.getWeightRatio(_pp, i); + } + + _nx = p.x; + _ny = p.y; + + if(_total < _pathEnd) { //Do not wiggle the last point. + var _d = point_direction(_ox, _oy, _nx, _ny); + _nx += lengthdir_x(random1D(_sed + _sedIndex, -_wig, _wig), _d + 90); _sedIndex++; + _ny += lengthdir_y(random1D(_sed + _sedIndex, -_wig, _wig), _d + 90); _sedIndex++; + } + + if(_prog_total >= _pathStr) { //Do not add point before range start. Do this instead of starting at _rtStr to prevent wiggle. + var _pntData; + if(pointAmo < pointArrLen && is_struct(points[pointAmo])) { + _pntData = points[pointAmo]; + _pntData.x = _nx; + _pntData.y = _ny; + _pntData.prog = (_prog_total - _pathStr) / (_pathEnd - _pathStr); + _pntData.progCrop = _prog_curr / _pathLength; + _pntData.weight = wght; + } else { + _pntData = { + x: _nx, + y: _ny, + prog: (_prog_total - _pathStr) / (_pathEnd - _pathStr), + progCrop: _prog_curr / _pathLength, + weight: wght + } + points[pointAmo] = _pntData; + } + + pointAmo++; + } + + if(_total <= 0) break; + + if(_prog_next == _prog_curr && _segIndexPrev == _segIndex) { print("Terminate line not moving"); break; } + else if(_prog_next > _prog_curr) { + _prog_total += _prog_next - _prog_curr; + _total -= _prog_next - _prog_curr; + } + _stepLen = min(_stepLen, _total); + + _prog_curr = _prog_next; + _ox = _nx; + _oy = _ny; + + if(_total_prev == _total && _segIndexPrev == _segIndex && ++_freeze > 16) { print("Terminate line not moving"); break; } + _total_prev = _total; + + if(_segIndex >= _segLengthAmo) { print("Terminate line finish last segment"); break; } + } + + array_resize(points, pointAmo); + lines[_lineAmo++] = points; + } + + array_resize(lines, _lineAmo); + #endregion + } else { #region + var x0, y0, x1, y1; + var _0 = point_rectangle_overlap(_dim[0], _dim[1], (_ang + 180) % 360); + var _1 = point_rectangle_overlap(_dim[0], _dim[1], _ang); + x0 = _0[0]; y0 = _0[1]; + x1 = _1[0]; y1 = _1[1]; + + var _l = point_distance(x0, y0, x1, y1); + var _d = point_direction(x0, y0, x1, y1); + var _od = _d, _nd = _d; + + var ww = _rtMax / _seg; + var _total = _rtMax; + var _prog_curr = frac(_shift) - ww; + var _prog = _prog_curr + 1; + var _prog_total = 0; + var points = []; + + while(_total > 0) { + if(_prog_curr >= 1) _prog_curr = 0; + else _prog_curr = min(_prog_curr + min(_total, ww), 1); + _prog_total += min(_total, ww); + + _nx = x0 + lengthdir_x(_l * _prog_curr, _d); + _ny = y0 + lengthdir_y(_l * _prog_curr, _d); + + var wgLen = random1D(_sed + _sedIndex, -_wig, _wig); _sedIndex++; + _nx += lengthdir_x(wgLen, _d + 90); + _ny += lengthdir_y(wgLen, _d + 90); + + if(_prog_total > _rtStr) //prevent drawing point before range start. + array_push(points, { x: _nx, y: _ny, prog: _prog_total / _rtMax, progCrop: _prog_curr, weight: 1 }); + + if(_prog_curr > _prog) + _total -= (_prog_curr - _prog); + _prog = _prog_curr; + _ox = _nx; + _oy = _ny; + } + + lines = [ points ]; + } #endregion + + #region draw + + surface_set_target(_outSurf); + if(_bg) draw_clear_alpha(0, 1); + else DRAW_CLEAR + + if(_useTex) { #region + var tex = surface_get_texture(_tex); + + shader_set(sh_draw_mapping); + shader_set_f("position", _texPos); + shader_set_f("rotation", degtorad(_texRot)); + shader_set_f("scale", _texSca); + + shader_set_interpolation(_tex); + } #endregion + + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + var _caps = []; + + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); + else draw_primitive_begin(pr_trianglestrip); + + random_set_seed(_sed + i); + var pxs = []; + var dat = array_safe_get_fast(_pathData, i, noone); + + var _col_base = dat == noone? _colb.eval(random(1)) : dat.color; + + for( var j = 0; j < array_length(points); j++ ) { + var p0 = points[j]; + var _nx = p0.x - 0.5 * _1px; + var _ny = p0.y - 0.5 * _1px; + var prog = p0.prog; + var prgc = p0.progCrop; + var _dir = j? point_direction(_ox, _oy, _nx, _ny) : 0; + + var widProg = value_snap_real(_widap? prog : prgc, 0.01); + + _nw = random_range(_wid[0], _wid[1]); + if(!ds_map_exists(widthMap, widProg)) + widthMap[? widProg] = eval_curve_x(_widc, widProg, 0.1); + _nw *= widthMap[? widProg]; + _nw *= p0.weight; + + _nc = colorMultiply(_col_base, _color.eval(_colP? prog : prgc)); + + if(_cap) { #region + if(j == 1) { + _d = _dir + 180; + _caps[0] = [ _oc, _ox, _oy, _ow / 2, _d - 90, _d ]; + _caps[1] = [ _oc, _ox, _oy, _ow / 2, _d, _d + 90 ]; + } + + if(j == array_length(points) - 1) { + _d = _dir; + _caps[2] = [ _nc, _nx, _ny, _nw / 2, _d - 90, _d ]; + _caps[3] = [ _nc, _nx, _ny, _nw / 2, _d, _d + 90 ]; + } + } #endregion + + if(_1px) { #region + if(j) { + var dst = point_distance(_ox, _oy, _nx, _ny); + if(dst <= 1 && i < array_length(points) - 1) continue; + draw_line_color(_ox, _oy, _nx, _ny, _oc, _nc); + } + + _ox = _nx; + _oy = _ny; + _oc = _nc; + #endregion + } else { #region + if(j) { + var _nd0 = _dir; + var _nd1 = _nd0; + + if(j < array_length(points) - 1) { + var p2 = points[j + 1]; + var _nnx = p2.x; + var _nny = p2.y; + + _nd1 = point_direction(_nx, _ny, _nnx, _nny); + _nd = _nd0 + angle_difference(_nd1, _nd0) / 2; + } else + _nd = _nd0; + + if(_useTex) { + var _len = array_length(points) - 1; + + var ox0 = _ox + lengthdir_x(_ow / 2, _od + 90); + var oy0 = _oy + lengthdir_y(_ow / 2, _od + 90); + var nx0 = _nx + lengthdir_x(_nw / 2, _nd + 90); + var ny0 = _ny + lengthdir_y(_nw / 2, _nd + 90); + + var ox1 = _ox + lengthdir_x(_ow / 2, _od + 90 + 180); + var oy1 = _oy + lengthdir_y(_ow / 2, _od + 90 + 180); + var nx1 = _nx + lengthdir_x(_nw / 2, _nd + 90 + 180); + var ny1 = _ny + lengthdir_y(_nw / 2, _nd + 90 + 180); + + draw_vertex_texture_color(ox0, oy0, 0, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(ox1, oy1, 1, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(nx0, ny0, 0, (j - 0) / _len, _nc, 1); + draw_vertex_texture_color(nx1, ny1, 1, (j - 0) / _len, _nc, 1); + } else if(_colW) + draw_line_width2_angle_width(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, merge_color(_oc, c_black, 0.5), merge_color(_nc, c_black, 0.5)); + else + draw_line_width2_angle(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, _oc, _nc); + } else { + var p1 = points[j + 1]; + _nd = point_direction(_nx, _ny, p1.x, p1.y); + } + + _ox = _nx; + _oy = _ny; + _od = _nd; + _ow = _nw; + _oc = _nc; + } + #endregion + } + + draw_primitive_end(); + + for( var j = 0, m = array_length(_caps); j < m; j++ ) { + var _cps = _caps[j]; + draw_set_color(_cps[0]); + draw_circle_angle(_cps[1], _cps[2], _cps[3], _cps[4], _cps[5], _capP); + } + } + + if(_useTex) shader_reset(); + surface_reset_target(); + #endregion + + return _outSurf; + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_line/node_line.gml.backup1 b/#backups/scripts/node_line/node_line.gml.backup1 new file mode 100644 index 000000000..1477d1900 --- /dev/null +++ b/#backups/scripts/node_line/node_line.gml.backup1 @@ -0,0 +1,538 @@ +// 2024-04-26 14:33:39 +function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Line"; + + inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF ) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 1] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 2] = nodeValue("Segment", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1) + .setDisplay(VALUE_DISPLAY.slider, { range: [1, 32, 0.1] }); + + inputs[| 3] = nodeValue("Width", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 2, 2 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 4] = nodeValue("Wiggle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.slider, { range: [0, 16, 0.01] }); + + inputs[| 5] = nodeValue("Random seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0); + + inputs[| 6] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 7] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone, "Draw line along path.") + .setVisible(true, true) + .setArrayDepth(1); + + inputs[| 8] = nodeValue("Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [0, 1], "Range of the path to draw.") + .setDisplay(VALUE_DISPLAY.slider_range); + + inputs[| 9] = nodeValue("Shift", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY._default, { slide_speed: 1 / 64 }); + + inputs[| 10] = nodeValue("Color over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 11] = nodeValue("Width over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11); + + inputs[| 12] = nodeValue("Span width over path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply the full 'width over length' to the trimmed path."); + + inputs[| 13] = nodeValue("Round cap", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 14] = nodeValue("Round segment", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4) + .setDisplay(VALUE_DISPLAY.slider, { range: [2, 16, 0.1] }); + + inputs[| 15] = nodeValue("Span color over path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply the full 'color over length' to the trimmed path."); + + inputs[| 16] = nodeValue("Greyscale over width", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + + inputs[| 17] = nodeValue("1px mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Render pixel perfect 1px line."); + + inputs[| 18] = nodeValue("Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| 19] = nodeValue("Fix length", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Fix length of each segment instead of segment count."); + + inputs[| 20] = nodeValue("Segment length", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4); + + inputs[| 21] = nodeValue("Texture position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 22] = nodeValue("Texture rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + + inputs[| 23] = nodeValue("Texture scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 24] = nodeValue("Random Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ); + + inputs[| 25] = nodeValue("Invert", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); + + inputs[| 26] = nodeValue("Clamp range", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); + + input_display_list = [ + ["Output", true], 0, 1, + ["Line data", false], 6, 7, 19, 2, 20, + ["Line settings", false], 17, 3, 11, 12, 8, 25, 9, 26, 13, 14, + ["Wiggle", false], 4, 5, + ["Render", false], 10, 24, 15, 16, + ["Texture", false], 18, 21, 22, 23, + ]; + + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + + lines = []; + + widthMap = ds_map_create(); + + attribute_surface_depth(); + attribute_interpolation(); + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + draw_set_color(COLORS._main_accent); + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + for( var j = 1; j < array_length(points); j++ ) { + var x0 = points[j - 1].x; + var y0 = points[j - 1].y; + var x1 = points[j].x; + var y1 = points[j].y; + + x0 = _x + x0 * _s; + y0 = _y + y0 * _s; + x1 = _x + x1 * _s; + y1 = _y + y1 * _s; + + draw_line(x0, y0, x1, y1); + } + } + } #endregion + + static step = function() { #region + var px = !getInputData(17); + var _tex = inputs[| 18].value_from != noone; + var _flen = getInputData(19); + + inputs[| 3].setVisible(px); + inputs[| 11].setVisible(px); + inputs[| 12].setVisible(px); + inputs[| 13].setVisible(px && !_tex); + inputs[| 14].setVisible(px); + inputs[| 18].setVisible(px); + + inputs[| 15].setVisible(!_tex); + inputs[| 16].setVisible(!_tex); + + inputs[| 2].setVisible(!_flen); + inputs[| 20].setVisible( _flen); + } #endregion + + static onValueUpdate = function(index = 0) { #region + if(index == 11) ds_map_clear(widthMap); + } #endregion + + static processData = function(_outSurf, _data, _output_index, _array_index) { #region + #region data + var _dim = _data[0]; + var _bg = _data[1]; + var _seg = _data[2]; + var _wid = _data[3]; + var _wig = _data[4]; + var _sed = _data[5]; + var _ang = _data[6] % 360; + var _pat = _data[7]; + var _ratio = _data[8]; + var _shift = _data[9]; + + var _color = _data[10]; + var _widc = _data[11]; + var _widap = _data[12]; + + var _cap = _data[13]; + var _capP = _data[14]; + var _colP = _data[15]; + var _colW = _data[16]; + var _1px = _data[17]; + + var _fixL = _data[19]; + var _segL = _data[20]; + + var _tex = _data[18]; + var _texPos = _data[21]; + var _texRot = _data[22]; + var _texSca = _data[23]; + + var _colb = _data[24]; + var _ratInv = _data[25]; + var _clamp = _data[26]; + #endregion + + if(IS_FIRST_FRAME || inputs[| 11].is_anim) + ds_map_clear(widthMap); + + var __debug_timer = get_timer(); + + var _rangeMin = min(_ratio[0], _ratio[1]); + var _rangeMax = max(_ratio[0], _ratio[1]); + if(_rangeMax == 1) _rangeMax = 0.99999; + + var _rtStr = min(_rangeMin, _rangeMax); + var _rtMax = max(_rangeMin, _rangeMax); + + var _use_path = is_struct(_pat); + var _useTex = inputs[| 18].value_from != noone; + if(_useTex) { + _cap = false; + _1px = false; + } + + if(_ang < 0) _ang = 360 + _ang; + + inputs[| 6].setVisible(!_use_path); + + random_set_seed(_sed); + var _sedIndex = 0; + + _outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth()); + + var p = new __vec2(); + var _ox, _nx, _nx1, _oy, _ny, _ny1; + var _ow, _nw, _oa, _na, _oc, _nc, _owg, _nwg; + var _pathData = []; + + if(_use_path) { #region + var lineLen = 1; + if(struct_has(_pat, "getLineCount")) + lineLen = _pat.getLineCount(); + if(struct_has(_pat, "getPathData")) + _pathData = _pat.getPathData(); + + lines = array_verify(lines, lineLen); + var _lineAmo = 0; + + if(_rtMax > 0) + for( var i = 0; i < lineLen; i++ ) { + var _useDistance = _fixL && struct_has(_pat, "getLength"); + var _pathLength = _useDistance? _pat.getLength(i) : 1; + if(_pathLength == 0) continue; + + var _pathStr = _rtStr; + var _pathEnd = _rtMax; + + var _stepLen = min(_pathEnd, 1 / _seg); //Distance to move per step + if(_stepLen <= 0.00001) continue; + + var _total = _pathEnd; //Length remaining + var _total_prev = _total; //Use to prevent infinite loop + var _freeze = 0; //Use to prevent infinite loop + + var _prog_curr = _clamp? _shift : frac(_shift); //Pointer to the current position + var _prog_next = 0; + var _prog = _prog_curr + 1; //Record previous position to delete from _total + var _prog_total = 0; //Record the distance the pointer has moved so far + var points = is_array(lines[i])? lines[i] : []; + var pointArrLen = array_length(points); + var pointAmo = 0; + var wght; + var _pathPng; + + if(_useDistance) { + _pathStr *= _pathLength; + _pathEnd *= _pathLength; + _stepLen = min(_segL, _pathEnd); + + _total *= _pathLength; + _total_prev = _total; + + _prog_curr *= _pathLength; + } + + var _segLength = struct_has(_pat, "getAccuLength")? _pat.getAccuLength(i) : []; + var _segLengthAmo = array_length(_segLength); + var _segIndex = 0; + var _segIndexPrev = 0; + + if(_segLengthAmo) + while(_prog_curr > _segLength[_segIndex]) { + _segIndex++; + if(_segIndex == _segLengthAmo) { + _segIndex = 0; + break; + } + } + + print($"===== {_prog_curr} / {_segLength} : {_segIndex} - {_pathLength} ====="); + + while(true) { + wght = 1; + _segIndexPrev = _segIndex; + + if(_useDistance) { + var segmentLength = array_safe_get_fast(_segLength, _segIndex, _pathLength); + + _prog_next = min(_prog_curr + _stepLen, _pathLength, segmentLength); + _pathPng = _ratInv? _pathLength - _prog_curr : _prog_curr; + + //print($"{segmentLength}/{_pathLength} = {_prog_next}"); + if(_prog_next == segmentLength) _segIndex++; + + var _pp = _clamp? clamp(_pathPng, 0, _pathLength) : _pathPng; + // print($"_pp = {_pp}, total = {_total}"); + + p = _pat.getPointDistance(_pp, i, p); + + if(struct_has(_pat, "getWeightDistance")) + wght = _pat.getWeightDistance(_pp, i); + } else { + _prog_next = min(_prog_curr + _stepLen, 1); //Move forward _stepLen or _total (if less) stop at 1 + _pathPng = _ratInv? 1 - _prog_curr : _prog_curr; + + var _pp = _clamp? clamp(_pathPng, 0, 1) : _pathPng + + p = _pat.getPointRatio(_pp, i, p); + if(struct_has(_pat, "getWeightRatio")) + wght = _pat.getWeightRatio(_pp, i); + } + + _nx = p.x; + _ny = p.y; + + if(_total < _pathEnd) { //Do not wiggle the last point. + var _d = point_direction(_ox, _oy, _nx, _ny); + _nx += lengthdir_x(random1D(_sed + _sedIndex, -_wig, _wig), _d + 90); _sedIndex++; + _ny += lengthdir_y(random1D(_sed + _sedIndex, -_wig, _wig), _d + 90); _sedIndex++; + } + + if(_prog_total >= _pathStr) { //Do not add point before range start. Do this instead of starting at _rtStr to prevent wiggle. + var _pntData; + if(pointAmo < pointArrLen && is_struct(points[pointAmo])) { + _pntData = points[pointAmo]; + _pntData.x = _nx; + _pntData.y = _ny; + _pntData.prog = (_prog_total - _pathStr) / (_pathEnd - _pathStr); + _pntData.progCrop = _prog_curr / _pathLength; + _pntData.weight = wght; + } else { + _pntData = { + x: _nx, + y: _ny, + prog: (_prog_total - _pathStr) / (_pathEnd - _pathStr), + progCrop: _prog_curr / _pathLength, + weight: wght + } + points[pointAmo] = _pntData; + } + + pointAmo++; + } + + if(_total <= 0) break; + + if(_prog_next == _prog_curr && _segIndexPrev == _segIndex) { print("Terminate line not moving"); break; } + else if(_prog_next > _prog_curr) { + _prog_total += _prog_next - _prog_curr; + _total -= _prog_next - _prog_curr; + } + _stepLen = min(_stepLen, _total); + + _prog_curr = _prog_next; + _ox = _nx; + _oy = _ny; + + if(_total_prev == _total && _segIndexPrev == _segIndex && ++_freeze > 16) { print("Terminate line not moving"); break; } + _total_prev = _total; + + if(_segIndex >= _segLengthAmo) { print("Terminate line finish last segment"); break; } + } + + array_resize(points, pointAmo); + lines[_lineAmo++] = points; + } + + array_resize(lines, _lineAmo); + #endregion + } else { #region + var x0, y0, x1, y1; + var _0 = point_rectangle_overlap(_dim[0], _dim[1], (_ang + 180) % 360); + var _1 = point_rectangle_overlap(_dim[0], _dim[1], _ang); + x0 = _0[0]; y0 = _0[1]; + x1 = _1[0]; y1 = _1[1]; + + var _l = point_distance(x0, y0, x1, y1); + var _d = point_direction(x0, y0, x1, y1); + var _od = _d, _nd = _d; + + var ww = _rtMax / _seg; + var _total = _rtMax; + var _prog_curr = frac(_shift) - ww; + var _prog = _prog_curr + 1; + var _prog_total = 0; + var points = []; + + while(_total > 0) { + if(_prog_curr >= 1) _prog_curr = 0; + else _prog_curr = min(_prog_curr + min(_total, ww), 1); + _prog_total += min(_total, ww); + + _nx = x0 + lengthdir_x(_l * _prog_curr, _d); + _ny = y0 + lengthdir_y(_l * _prog_curr, _d); + + var wgLen = random1D(_sed + _sedIndex, -_wig, _wig); _sedIndex++; + _nx += lengthdir_x(wgLen, _d + 90); + _ny += lengthdir_y(wgLen, _d + 90); + + if(_prog_total > _rtStr) //prevent drawing point before range start. + array_push(points, { x: _nx, y: _ny, prog: _prog_total / _rtMax, progCrop: _prog_curr, weight: 1 }); + + if(_prog_curr > _prog) + _total -= (_prog_curr - _prog); + _prog = _prog_curr; + _ox = _nx; + _oy = _ny; + } + + lines = [ points ]; + } #endregion + + #region draw + + surface_set_target(_outSurf); + if(_bg) draw_clear_alpha(0, 1); + else DRAW_CLEAR + + if(_useTex) { #region + var tex = surface_get_texture(_tex); + + shader_set(sh_draw_mapping); + shader_set_f("position", _texPos); + shader_set_f("rotation", degtorad(_texRot)); + shader_set_f("scale", _texSca); + + shader_set_interpolation(_tex); + } #endregion + + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + var _caps = []; + + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); + else draw_primitive_begin(pr_trianglestrip); + + random_set_seed(_sed + i); + var pxs = []; + var dat = array_safe_get_fast(_pathData, i, noone); + + var _col_base = dat == noone? _colb.eval(random(1)) : dat.color; + + for( var j = 0; j < array_length(points); j++ ) { + var p0 = points[j]; + var _nx = p0.x - 0.5 * _1px; + var _ny = p0.y - 0.5 * _1px; + var prog = p0.prog; + var prgc = p0.progCrop; + var _dir = j? point_direction(_ox, _oy, _nx, _ny) : 0; + + var widProg = value_snap_real(_widap? prog : prgc, 0.01); + + _nw = random_range(_wid[0], _wid[1]); + if(!ds_map_exists(widthMap, widProg)) + widthMap[? widProg] = eval_curve_x(_widc, widProg, 0.1); + _nw *= widthMap[? widProg]; + _nw *= p0.weight; + + _nc = colorMultiply(_col_base, _color.eval(_colP? prog : prgc)); + + if(_cap) { #region + if(j == 1) { + _d = _dir + 180; + _caps[0] = [ _oc, _ox, _oy, _ow / 2, _d - 90, _d ]; + _caps[1] = [ _oc, _ox, _oy, _ow / 2, _d, _d + 90 ]; + } + + if(j == array_length(points) - 1) { + _d = _dir; + _caps[2] = [ _nc, _nx, _ny, _nw / 2, _d - 90, _d ]; + _caps[3] = [ _nc, _nx, _ny, _nw / 2, _d, _d + 90 ]; + } + } #endregion + + if(_1px) { #region + if(j) { + var dst = point_distance(_ox, _oy, _nx, _ny); + if(dst <= 1 && i < array_length(points) - 1) continue; + draw_line_color(_ox, _oy, _nx, _ny, _oc, _nc); + } + + _ox = _nx; + _oy = _ny; + _oc = _nc; + #endregion + } else { #region + if(j) { + var _nd0 = _dir; + var _nd1 = _nd0; + + if(j < array_length(points) - 1) { + var p2 = points[j + 1]; + var _nnx = p2.x; + var _nny = p2.y; + + _nd1 = point_direction(_nx, _ny, _nnx, _nny); + _nd = _nd0 + angle_difference(_nd1, _nd0) / 2; + } else + _nd = _nd0; + + if(_useTex) { + var _len = array_length(points) - 1; + + var ox0 = _ox + lengthdir_x(_ow / 2, _od + 90); + var oy0 = _oy + lengthdir_y(_ow / 2, _od + 90); + var nx0 = _nx + lengthdir_x(_nw / 2, _nd + 90); + var ny0 = _ny + lengthdir_y(_nw / 2, _nd + 90); + + var ox1 = _ox + lengthdir_x(_ow / 2, _od + 90 + 180); + var oy1 = _oy + lengthdir_y(_ow / 2, _od + 90 + 180); + var nx1 = _nx + lengthdir_x(_nw / 2, _nd + 90 + 180); + var ny1 = _ny + lengthdir_y(_nw / 2, _nd + 90 + 180); + + draw_vertex_texture_color(ox0, oy0, 0, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(ox1, oy1, 1, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(nx0, ny0, 0, (j - 0) / _len, _nc, 1); + draw_vertex_texture_color(nx1, ny1, 1, (j - 0) / _len, _nc, 1); + } else if(_colW) + draw_line_width2_angle_width(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, merge_color(_oc, c_black, 0.5), merge_color(_nc, c_black, 0.5)); + else + draw_line_width2_angle(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, _oc, _nc); + } else { + var p1 = points[j + 1]; + _nd = point_direction(_nx, _ny, p1.x, p1.y); + } + + _ox = _nx; + _oy = _ny; + _od = _nd; + _ow = _nw; + _oc = _nc; + } + #endregion + } + + draw_primitive_end(); + + for( var j = 0, m = array_length(_caps); j < m; j++ ) { + var _cps = _caps[j]; + draw_set_color(_cps[0]); + draw_circle_angle(_cps[1], _cps[2], _cps[3], _cps[4], _cps[5], _capP); + } + } + + if(_useTex) shader_reset(); + surface_reset_target(); + #endregion + + return _outSurf; + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup0 b/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup0 new file mode 100644 index 000000000..6b2fb2c29 --- /dev/null +++ b/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup0 @@ -0,0 +1,265 @@ +// 2024-04-26 14:41:10 +function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "Bridge Path"; + w = 96; + + inputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone) + .setVisible(true, true) + .rejectArray(); + + inputs[| 1] = nodeValue("Amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4) + .rejectArray(); + + inputs[| 2] = nodeValue("Smooth", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + .rejectArray(); + + outputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.output, VALUE_TYPE.pathnode, self); + + input_display_list = [ 0, + ["Bridge", false], 1, 2, + ] + + cached_pos = ds_map_create(); + + #region ---- path ---- + anchors = []; + controls = []; + lengths = []; + lengthAccs = []; + boundary = []; + lengthTotal = []; + + cached_pos = ds_map_create(); + #endregion + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + var _path = getInputData(0); + var _smt = getInputData(2); + if(_path && struct_has(_path, "drawOverlay")) _path.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); + + var _amo = array_length(anchors); + var ox, oy, nx, ny; + var _p = new __vec2(); + + draw_set_color(COLORS._main_icon); + for( var i = 0, n = _amo; i < n; i++ ) { + var _a = anchors[i]; + + if(_smt) { + var _smp = 1 / 32; + for( var j = 0; j <= 1; j += _smp ) { + _p = getPointRatio(j, i, _p); + + nx = _x + _p.x * _s; + ny = _y + _p.y * _s; + + if(j > 0) draw_line_width(ox, oy, nx, ny, 3); + + ox = nx; + oy = ny; + } + } else { + for( var j = 0, m = array_length(_a); j < m; j++ ) { + nx = _x + _a[j][0] * _s; + ny = _y + _a[j][1] * _s; + + if(j) draw_line_width(ox, oy, nx, ny, 3); + + ox = nx; + oy = ny; + } + } + } + } #endregion + + static getLineCount = function() { return getInputData(1); } + + static getSegmentCount = function(ind = 0) { return array_safe_length(array_safe_get_fast(anchors, ind)); } + + static getLength = function(ind = 0) { return array_safe_get_fast(lengths, ind); } + + static getAccuLength = function(ind = 0) { return array_safe_get_fast(lengthAccs, ind); } + + static getBoundary = function(ind = 0) { return array_safe_get_fast(boundary, ind); } + + static getPointRatio = function(_rat, ind = 0, out = undefined) { return getPointDistance(clamp(_rat, 0, 1) * getLength(ind), ind, out); } + + static getPointDistance = function(_dist, ind = 0, out = undefined) { #region + if(out == undefined) out = new __vec2(); else { out.x = 0; out.y = 0; } + + var _cKey = $"{_dist},{ind}"; + if(ds_map_exists(cached_pos, _cKey)) { + var _p = cached_pos[? _cKey]; + out.x = _p.x; + out.y = _p.y; + return out; + } + + var _smt = getInputData(2); + var _a = anchors[ind]; + var _la = lengthAccs[ind]; + + if(_dist == 0) { + var _p = _a[0]; + out.x = _p[0]; + out.y = _p[1]; + + cached_pos[? _cKey] = out.clone(); + return out; + } + + var _ind = 0; + var n = array_length(_la); + + for(; _ind < n; _ind++ ) if(_dist < _la[_ind]) break; + + if(_ind >= n) { + var _p = _a[_ind]; + out.x = _p[0]; + out.y = _p[1]; + + cached_pos[? _cKey] = out.clone(); + return out; + } + + var _d = _ind == 0? _dist : _dist - _la[_ind - 1]; + var _rat = _d / (_la[_ind] - (_ind == 0? 0 : _la[_ind - 1])); + var p0 = _a[_ind]; + var p1 = _a[_ind + 1]; + + if(_smt) { + var _cnt = controls[ind]; + var _c0x = _cnt[_ind][0]; + var _c0y = _cnt[_ind][1]; + var _c1x = _cnt[_ind][2]; + var _c1y = _cnt[_ind][3]; + + var _p = eval_bezier(_rat, p0[0], p0[1], p1[0], p1[1], _c0x, _c0y, _c1x, _c1y); + out.x = _p[0]; + out.y = _p[1]; + } else { + out.x = lerp(p0[0], p1[0], _rat); + out.y = lerp(p0[1], p1[1], _rat); + } + + cached_pos[? _cKey] = out.clone(); + + return out; + } #endregion + + static update = function() { #region + ds_map_clear(cached_pos); + + var _path = getInputData(0); + var _amo = getInputData(1); + var _smt = getInputData(2); + + if(_path == noone) return; + + #region bridge + var _lines = _path.getLineCount(); + var _p = new __vec2(); + var _rat; + + anchors = array_create(_amo); + lengths = array_create(_amo); + lengthAccs = array_create(_amo); + + for( var i = 0; i < _amo; i++ ) { + var _a = array_create(_lines); + _rat = _amo == 1? 0.5 : i / (_amo - 1); + + for( var j = 0; j < _lines; j++ ) { + _p = _path.getPointRatio(clamp(_rat, 0, 0.999), j, _p); + _a[j] = [ _p.x, _p.y ]; + } + + anchors[i] = _a; + + if(_smt) { + var _cnt = array_create(_lines - 1); + + for( var j = 0; j < _lines - 1; j++ ) _cnt[j] = [ 0, 0, 0, 0 ]; + + _cnt[0] = [ _a[0][0], _a[ 0][1], _a[0][0], _a[0][1] ]; + _cnt[_lines - 2] = [ _a[_lines - 1][0], _a[_lines - 1][1], _a[_lines - 1][0], _a[_lines - 1][1] ]; + + for( var j = 1; j < _lines - 1; j++ ) { + var _a0 = _a[j - 1]; + var _a1 = _a[j]; + var _a2 = _a[j + 1]; + + var _dr = point_direction(_a0[0], _a0[1], _a2[0], _a2[1]); + var _ds0 = point_distance(_a1[0], _a1[1], _a0[0], _a0[1]) / 2; + var _ds2 = point_distance(_a1[0], _a1[1], _a2[0], _a2[1]) / 2; + + var c0x = _a1[0] - lengthdir_x(_ds0, _dr); + var c0y = _a1[1] - lengthdir_y(_ds0, _dr); + var c1x = _a1[0] + lengthdir_x(_ds2, _dr); + var c1y = _a1[1] + lengthdir_y(_ds2, _dr); + + _cnt[j - 1][2] = c0x; + _cnt[j - 1][3] = c0y; + _cnt[j][0] = c1x; + _cnt[j][1] = c1y; + } + + controls[i] = _cnt; + + var _l = 0, _la = []; + var ox, oy, nx, ny; + + for( var j = 0; j < _lines - 1; j++ ) { + var _a0 = _a[j]; + var _a1 = _a[j + 1]; + var _c0x = _cnt[j][0]; + var _c0y = _cnt[j][1]; + var _c1x = _cnt[j][2]; + var _c1y = _cnt[j][3]; + + var _smp = 1 / 32; + var _ll = 0; + + for( var k = 0; k < 1; k += _smp ) { + var _p = eval_bezier(k, _a0[0], _a0[1], _a1[0], _a1[1], _c0x, _c0y, _c1x, _c1y); + nx = _p[0]; + ny = _p[1]; + + if(k > 0) _ll += point_distance(ox, oy, nx, ny); + + ox = nx; + oy = ny; + } + + _l += _ll; + array_push(_la, _l); + } + + lengths[i] = _l; + lengthAccs[i] = _la; + + } else { + var _l = 0, _la = []; + var ox, oy, nx, ny; + + for( var j = 0, m = array_length(_a); j < m; j++ ) { + nx = _a[j][0]; + ny = _a[j][1]; + + if(j) { + var d = point_distance(ox, oy, nx, ny); + _l += d; + array_push(_la, _l); + } + + ox = nx; + oy = ny; + } + + lengths[i] = _l; + lengthAccs[i] = _la; + } + } + #endregion + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup1 b/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup1 new file mode 100644 index 000000000..dbf835b8c --- /dev/null +++ b/#backups/scripts/node_path_bridge/node_path_bridge.gml.backup1 @@ -0,0 +1,265 @@ +// 2024-04-26 14:39:57 +function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { + name = "Bridge Path"; + w = 96; + + inputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone) + .setVisible(true, true) + .rejectArray(); + + inputs[| 1] = nodeValue("Amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 4) + .rejectArray(); + + inputs[| 2] = nodeValue("Smooth", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) + .rejectArray(); + + outputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.output, VALUE_TYPE.pathnode, self); + + input_display_list = [ 0, + ["Bridge", false], 1, 2, + ] + + cached_pos = ds_map_create(); + + #region ---- path ---- + anchors = []; + controls = []; + lengths = []; + lengthAccs = []; + boundary = []; + lengthTotal = []; + + cached_pos = ds_map_create(); + #endregion + + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region + var _path = getInputData(0); + var _smt = getInputData(2); + if(_path && struct_has(_path, "drawOverlay")) _path.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); + + var _amo = array_length(anchors); + var ox, oy, nx, ny; + var _p = new __vec2(); + + draw_set_color(COLORS._main_icon); + for( var i = 0, n = _amo; i < n; i++ ) { + var _a = anchors[i]; + + if(_smt) { + var _smp = 1 / 32; + for( var j = 0; j <= 1; j += _smp ) { + _p = getPointRatio(j, i, _p); + + nx = _x + _p.x * _s; + ny = _y + _p.y * _s; + + if(j > 0) draw_line_width(ox, oy, nx, ny, 3); + + ox = nx; + oy = ny; + } + } else { + for( var j = 0, m = array_length(_a); j < m; j++ ) { + nx = _x + _a[j][0] * _s; + ny = _y + _a[j][1] * _s; + + if(j) draw_line_width(ox, oy, nx, ny, 3); + + ox = nx; + oy = ny; + } + } + } + } #endregion + + static getLineCount = function() { return getInputData(1); } + + static getSegmentCount = function(ind = 0) { return array_safe_length(array_safe_get_fast(anchors, ind)); } + + static getLength = function(ind = 0) { return array_safe_get_fast(lengths, ind); } + + static getAccuLength = function(ind = 0) { return array_safe_get_fast(lengthAccs, ind); } + + static getBoundary = function(ind = 0) { return array_safe_get_fast(boundary, ind); } + + static getPointRatio = function(_rat, ind = 0, out = undefined) { return getPointDistance(clamp(_rat, 0, 1) * getLength(ind), ind, out); } + + static getPointDistance = function(_dist, ind = 0, out = undefined) { #region + if(out == undefined) out = new __vec2(); else { out.x = 0; out.y = 0; } + + var _cKey = $"{_dist},{ind}"; + if(ds_map_exists(cached_pos, _cKey)) { + var _p = cached_pos[? _cKey]; + out.x = _p.x; + out.y = _p.y; + return out; + } + + var _smt = getInputData(2); + var _a = anchors[ind]; + var _la = lengthAccs[ind]; + + if(_dist == 0) { + var _p = _a[0]; + out.x = _p[0]; + out.y = _p[1]; + + cached_pos[? _cKey] = out.clone(); + return out; + } + + var _ind = 0; + var n = array_length(_la); + + for(; _ind < n; _ind++ ) if(_dist < _la[_ind]) break; + + if(_ind >= n) { + var _p = _a[_ind]; + out.x = _p[0]; + out.y = _p[1]; + + cached_pos[? _cKey] = out.clone(); + return out; + } + + var _d = _ind == 0? _dist : _dist - _la[_ind - 1]; + var _rat = _d / (_la[_ind] - (_ind == 0? 0 : _la[_ind - 1])); + var p0 = _a[_ind]; + var p1 = _a[_ind + 1]; + + if(_smt) { + var _cnt = controls[ind]; + var _c0x = _cnt[_ind][0]; + var _c0y = _cnt[_ind][1]; + var _c1x = _cnt[_ind][2]; + var _c1y = _cnt[_ind][3]; + + var _p = eval_bezier(_rat, p0[0], p0[1], p1[0], p1[1], _c0x, _c0y, _c1x, _c1y); + out.x = _p[0]; + out.y = _p[1]; + } else { + out.x = lerp(p0[0], p1[0], _rat); + out.y = lerp(p0[1], p1[1], _rat); + } + + cached_pos[? _cKey] = out.clone(); + + return out; + } #endregion + + static update = function() { #region + ds_map_clear(cached_pos); + + var _path = getInputData(0); + var _amo = getInputData(1); + var _smt = getInputData(2); + + if(_path == noone) return; + + #region bridge + var _lines = _path.getLineCount(); + var _p = new __vec2(); + var _rat; + + anchors = array_create(_amo); + lengths = array_create(_amo); + lengthAccs = array_create(_amo); + + for( var i = 0; i < _amo; i++ ) { + var _a = array_create(_lines); + _rat = _amo == 1? 0.5 : i / (_amo - 1); + + for( var j = 0; j < _lines; j++ ) { + _p = _path.getPointRatio(clamp(_rat, 0, 0.999), j, _p); + _a[j] = [ _p.x, _p.y ]; + } + + anchors[i] = _a; + + if(_smt) { + var _cnt = array_create(_lines - 1); + + for( var j = 0; j < _lines - 1; j++ ) _cnt[j] = [ 0, 0, 0, 0 ]; + + _cnt[0] = [ _a[0][0], _a[ 0][1], _a[0][0], _a[0][1] ]; + _cnt[_lines - 2] = [ _a[_lines - 1][0], _a[_lines - 1][1], _a[_lines - 1][0], _a[_lines - 1][1] ]; + + for( var j = 1; j < _lines - 1; j++ ) { + var _a0 = _a[j - 1]; + var _a1 = _a[j]; + var _a2 = _a[j + 1]; + + var _dr = point_direction(_a0[0], _a0[1], _a2[0], _a2[1]); + var _ds0 = point_distance(_a1[0], _a1[1], _a0[0], _a0[1]) / 2; + var _ds2 = point_distance(_a1[0], _a1[1], _a2[0], _a2[1]) / 2; + + var c0x = _a1[0] - lengthdir_x(_ds0, _dr); + var c0y = _a1[1] - lengthdir_y(_ds0, _dr); + var c1x = _a1[0] + lengthdir_x(_ds2, _dr); + var c1y = _a1[1] + lengthdir_y(_ds2, _dr); + + _cnt[j - 1][2] = c0x; + _cnt[j - 1][3] = c0y; + _cnt[j][0] = c1x; + _cnt[j][1] = c1y; + } + + controls[i] = _cnt; + + var _l = 0, _la = []; + var ox, oy, nx, ny; + + for( var j = 0; j < _lines - 1; j++ ) { + var _a0 = _a[j]; + var _a1 = _a[j + 1]; + var _c0x = _cnt[j][0]; + var _c0y = _cnt[j][1]; + var _c1x = _cnt[j][2]; + var _c1y = _cnt[j][3]; + + var _smp = 1 / 32; + var _ll = 0; + + for( var k = 0; k < 1; k += _smp ) { + var _p = eval_bezier(k, _a0[0], _a0[1], _a1[0], _a1[1], _c0x, _c0y, _c1x, _c1y); + nx = _p[0]; + ny = _p[1]; + + if(k > 0) _ll += point_distance(ox, oy, nx, ny); + + ox = nx; + oy = ny; + } + + _l += _ll; + array_push(_la, _l); + } + + lengths[i] = _l; + lengthAccs[i] = _la; + + } else { + var _l = 0, _la = []; + var ox, oy, nx, ny; + + for( var j = 0, m = array_length(_a); j < m; j++ ) { + nx = _a[j][0]; + ny = _a[j][1]; + + if(j) { + var d = point_distance(ox, oy, nx, ny); + _l += d; + array_push(_la, _l); + } + + ox = nx; + oy = ny; + } + + lengths[i] = _l; + lengthAccs[i] = _la; + } + } + #endregion + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/preferences/preferences.gml.backup0 b/#backups/scripts/preferences/preferences.gml.backup0 index 2a7fa1e8b..baca45674 100644 --- a/#backups/scripts/preferences/preferences.gml.backup0 +++ b/#backups/scripts/preferences/preferences.gml.backup0 @@ -1,4 +1,4 @@ -// 2024-04-23 15:29:21 +// 2024-04-26 12:17:59 #region preference globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA; PREFERENCES = {}; diff --git a/#backups/scripts/preferences/preferences.gml.backup1 b/#backups/scripts/preferences/preferences.gml.backup1 index 08f59cc8a..4204c1749 100644 --- a/#backups/scripts/preferences/preferences.gml.backup1 +++ b/#backups/scripts/preferences/preferences.gml.backup1 @@ -1,4 +1,4 @@ -// 2024-04-23 11:00:26 +// 2024-04-26 10:05:24 #region preference globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA; PREFERENCES = {}; diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 6275acd31..43fc32f41 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -303,11 +303,6 @@ {"$GMFolder":"","%Name":"text","folderPath":"folders/widgets/text.yy","name":"text","resourceType":"GMFolder","resourceVersion":"2.0",}, ], "IncludedFiles":[ - {"$GMIncludedFile":"","%Name":"ApolloHelp.html","ConfigValues":{ - "Itch":{ - "CopyToMask":"0", - }, - },"CopyToMask":0,"filePath":"datafiles","name":"ApolloHelp.html","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Actions.zip","CopyToMask":-1,"filePath":"datafiles/data","name":"Actions.zip","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"icons.ai","CopyToMask":-1,"filePath":"datafiles/data/Actions","name":"icons.ai","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Armature Build.json","CopyToMask":-1,"filePath":"datafiles/data/Actions/Nodes","name":"Armature Build.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, @@ -362,6 +357,11 @@ {"$GMIncludedFile":"","%Name":"related_node.json","CopyToMask":-1,"filePath":"datafiles/data","name":"related_node.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Theme.zip","CopyToMask":-1,"filePath":"datafiles/data","name":"Theme.zip","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"tooltip.zip","CopyToMask":3035426170322551022,"filePath":"datafiles/data","name":"tooltip.zip","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"dllcredits.txt","ConfigValues":{ + "Itch":{ + "CopyToMask":"0", + }, + },"CopyToMask":0,"filePath":"datafiles","name":"dllcredits.txt","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"ffmpeg.exe","CopyToMask":-1,"filePath":"datafiles/ffmpeg/bin","name":"ffmpeg.exe","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"LICENSE","CopyToMask":-1,"filePath":"datafiles/ffmpeg","name":"LICENSE","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"README.txt","CopyToMask":-1,"filePath":"datafiles/ffmpeg","name":"README.txt","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, @@ -416,11 +416,6 @@ {"$GMIncludedFile":"","%Name":"mf.dll","CopyToMask":-1,"filePath":"datafiles","name":"mf.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"mfcore.dll","CopyToMask":-1,"filePath":"datafiles","name":"mfcore.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"mfplat.dll","CopyToMask":-1,"filePath":"datafiles","name":"mfplat.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, - {"$GMIncludedFile":"","%Name":"README.txt","ConfigValues":{ - "Itch":{ - "CopyToMask":"0", - }, - },"CopyToMask":0,"filePath":"datafiles","name":"README.txt","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"data.win","CopyToMask":-1,"filePath":"datafiles/report","name":"data.win","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"execute_shell_simple_ext_x64.dll","CopyToMask":-1,"filePath":"datafiles/report","name":"execute_shell_simple_ext_x64.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"options.ini","CopyToMask":-1,"filePath":"datafiles/report","name":"options.ini","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, @@ -455,7 +450,6 @@ {"$GMIncludedFile":"","%Name":"CommonPS.hlsl","CopyToMask":-1,"filePath":"datafiles/Shaders/3dInstance","name":"CommonPS.hlsl","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"CommonVS.hlsl","CopyToMask":-1,"filePath":"datafiles/Shaders/3dInstance","name":"CommonVS.hlsl","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"rubber_duck_toy_1k.bin","CopyToMask":-1,"filePath":"datafiles/Shaders/3dInstance","name":"rubber_duck_toy_1k.bin","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, - {"$GMIncludedFile":"","%Name":"Steamworks_Extension_Documentation.html","CopyToMask":0,"filePath":"datafiles","name":"Steamworks_Extension_Documentation.html","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"ucrtbased.dll","ConfigValues":{},"CopyToMask":-1,"filePath":"datafiles","name":"ucrtbased.dll","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"webpmux.exe","CopyToMask":-1,"filePath":"datafiles/webp","name":"webpmux.exe","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Welcome files.zip","CopyToMask":-1,"filePath":"datafiles","name":"Welcome files.zip","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/datafiles/ApolloHelp.html b/datafiles/ApolloHelp.html deleted file mode 100644 index 0d4208756..000000000 --- a/datafiles/ApolloHelp.html +++ /dev/null @@ -1,988 +0,0 @@ - - -Apollo cheat sheet - - - - - - - - - - - - - - - - - -
- -
-

This is a function "cheat sheet" for Apollo extension by YellowAfterlife. -The extension can be acquired from GM:Marketplace or itch.io. -For questions/support, use forums (itch.io, GM forums), or send me an email. -A most up-to-date version of the manual is always available online. -The extension is currently available for Windows, Linux, and Mac (experimental).

-Click on sections to expand/collapse them.
-Quick display controls: CategoriesSectionsEverything
-

-

General

-

lua_error_handler : script(text, state_id)

- If you assign a script into this global variable, it will be called whenever an error occurs in Lua code. -

- So you could, for instance, make a script that displays a message box with error text, -

-/// scr_handle_lua_error(msg, state)
-var state = argument1;
-show_debug_message("A Lua error occurred: " + argument0);
-

and then link it up on game start: -

-lua_error_handler = scr_handle_lua_error;
-
-
lua_get_cwd()path

- Returns the current working directory (_wgetcwd on Windows, getcwd otherwise). -

-
lua_set_cwd(path)

- Previously lua_chdir. -

- Changes the current working directory (_wchdir on WIndows, chdir otherwise). -

- This affects where the Lua code would be reading/writing files from by default. -

-

-
Lua states

-

Introduction to states

- A state is a subject to most of the Apollo's functions. -

- To put it simply, a state is the Lua program along with it's variables and current execution stack. -

-
lua_state_create()state_id

- Creates a new Lua state and returns it's ID. -

-state = lua_state_create();
-

Lua' standard libraries are included by default. -

- If you don't want to expose certain API functions to the user, you can use lua_global_set to remove those entries: -

-lua_global_set(state, "io", undefined);
-
-
lua_state_destroy(state_id)

- Destroys the given state, freeing up any resources used by it. -

-lua_state_destroy(state);
-

It is generally recommended that you clean up your states once they are no longer needed to avoid memory leaks. -

-
lua_thread_create(state_id)thread_state_id

- Creates a Lua "thread"-state attached to the given state. -

- Not to be confused with OS-level threads, - Lua "threads" are separate execution states sharing the data from a parent state, - coroutine-style. -

- These share indexes with states. -

-
lua_thread_destroy(state_id)

- Destroys a previously created Lua "thread"-state. -

- Technically an alias for lua_state_destroy due to shared index space. -

-
lua_state_exists(state_id)

- Returns whether there's a state/thread with the given ID. -

-
lua_reset()

- Destroys all existing Lua states and threads. -

- This also causes newly made states to have IDs start at 0 again. -

-
lua_state_reuse_indexes()count

- Here's the deal: As you might know, reusing indexes can cause some really mysterious bugs - if your code accidentally continues to use an index (which is now taken up by something else). -

- So, by default, Apollo will not do that. Which, in turn, means that after states are destroyed, - 4 bytes worth of data (which were onece the state's address) will continue to be reserved per state. -

- While it would take about 500 000 states to run out of memory this way, - you might prefer not to have that anyway. -

- So, calling this function will mark that memory as available again, causing Apollo to reuse the - destroyed indexes for newly created states. This will only affect indexes of states that are - destroyed as of calling the function. -

- In other words, while developing your project, you would not call this at all - (so that if you use a destroyed state, you get an obvious error), and for final release - version you would call it once in a while (such as during room transitions - to further - reduce the odds of anything going strange). -

- The function returns the number of indexes that will be reused as result. -

-

-
Adding Lua code

-

lua_add_code(state_id, lua_code)

- Attempts to compile the given snippet of Lua code, add it to given Lua state, and execute it. - Returns whether all steps succeeded. -

-lua_add_code(state, "print('Hello!')");
-

Same as with other things, compilation/runtime errors are forwarded to lua_error_handler if it is defined. -

-
lua_add_file(state_id, path, chdir = true)

- Attempts to load and run a snippet of Lua code from the file at the given path. -

- The function mimics GMS' file handling rules, preferring files in game's save directory over the files in game's installation directory. -

- It will, however, also accept absolute paths, bypassing sandbox restrictions. -

- So, if you added an included file called "some.lua", you could then load it with -

-lua_add_file(state, "some.lua");
-

If chdir is left at true, the function will automatically call lua_chdir when given a relative path so that the Lua code would work with files in that directory. -

-

-
Using Lua variables

-

lua_global_get(state_id, name)value

- Returns the value of the state's given global variable. -

- Note that this returns undefined for unsupported types. -

-lua_add_code(state, "test = 'Hello!'");
-show_debug_message(lua_global_get(state, "test"));
-
-
lua_global_set(state_id, name, value)

- Changes the value of the state's given global variable. -

-lua_global_set(state, "test", "Hello!");
-lua_add_code(state, "print(test)"); // 'Hello!'
-
-
lua_global_type(state_id, name)lua_type

- Returns the type of a state's global variable as a constant. -

- Possible values are as following:

    -
  • lua_type_none: placeholder for type ID 0 -
  • lua_type_nil: an equivalent of GML's undefined. Not-yet-set values are nil. -
  • lua_type_bool: a boolean value (true or false). -
  • lua_type_number: a numeric type, same as GML's real. -
  • lua_type_string: same as GML's string type. -
  • lua_type_table: a Lua table (array or dictionary). -
  • lua_type_function: a Lua function (that can be called via lua_call group). -
  • lua_type_thread: a Lua "thread"/coroutine. -
  • lua_type_userdata: an external reference (see Lua doc). -
  • lua_type_lightuserdata: an external struct (see Lua doc). -
  • lua_type_unknown: unrecognized type (never returns with normal Lua library) -

- If the state does not exist, an error is thrown. -

-if (lua_global_type(state, "test") == lua_type_function) {
-    lua_call(state, "test");
-} else show_debug_message("The state does not have a function called `test`!");
-
-
lua_global_typeof(state_id, name)type_name

- Returns the type of a state's global variable as a string. -

- Outside of debugging, you should prefer to use lua_global_type, as numeric comparisons are much faster than string comparisons. -

- The usual returned values are as following: -

    -
  • "nil": an equivalent of GML's undefined. Not-yet-set values are nil. -
  • "boolean": a boolean value (true or false). -
  • "number": a numeric type, same as GML's real. -
  • "string": same as GML' string type. -
  • "table": a Lua table. You currently can't do much with these from GML side. -
  • "function": a Lua function - as such, a thing that could be called via lua_call. -
  • "thread": a Lua "thread"/coroutine (more on these later). -

- So you could use a snippet like this to check if a state has a function named "test": -

-if (lua_global_typeof(state, "test") == "function") {
-    lua_call(state, "test");
-} else show_debug_message("The state does not have a function called `test`!");
-
-

-
Calling Lua code

-

lua_call(state_id, name, ...arguments)

- Attempts to call a Lua function stored in the given global variable of the state. -

- Returns the first of the function's returned values. -

- If an error occurs, calls lua_error_handler and returns undefined. -

-lua_add_code(state, "function greet(s) return 'Hello, ' .. s end");
-show_debug_message(lua_call(state, "greet", "GameMaker"));
-

If the function returns multiple values, the first one returned (use lua_call_m / lua_call_xm / lua_call_wm / lua_call_wxm to support multiple returned values). -

- If the function returns no values, you get an undefined. -

-
lua_call_w(state_id, name, argument_array)

- Like lua_call, but allows to pass in the arguments as an array. -

-lua_add_code(state, "function add(a, b) return a + b end");
-var args = array_create(2, 7); // [7, 7]
-show_debug_message(lua_call_w(state, "add", args)); // 14
-
-
lua_call_m(state_id, name, ...arguments)results_array

- Like lua_call, but packs returned value(s) into an array. -

-lua_add_code(state, "function multi(v) return v, 1, 2 end");
-show_debug_message(lua_call_m(state, "multi", "test")); // ["test", 1, 2]
-

Returns the array with value(s) or an empty array if the function returned nothing. -

-
lua_call_xm(state_id, name, results_array, ...arguments)results_count

- Like lua_call_m, but instead writes returned value(s) into the specified array. -

- This allows to reuse the same array for frequently performed operations. -

- Returns the number of values written to the array. -

-lua_add_code(state, "function multi(v) return v, 1, 2 end");
-var arr = array_create(5);
-var n = lua_call_xm(state, "multi", arr, "test");
-show_debug_message(arr); // ["test", 1, 2, 0, 0]
-show_debug_message(n); // 3
-
-
lua_call_wm(state_id, name, argument_array)results_array

- A combination of lua_call_w and lua_call_m - takes arguments as an array and returns a new array with returned values. -

-
lua_call_wxm(state_id, name, argument_array, results_array)results_count

- A combination of lua_call_w and lua_call_xm - takes arguments as an array, writes results to another array, and returns the number of results written. -

-

-
Exposing GML to Lua

-

lua_add_function(state_id, name, script_id)

- Exposes the given GM script to a Lua state as a global function. -

- For example, if you have some -

-/// scr_alert(text)
-show_debug_message(argument0);
-

you could expose it to Lua via -

-lua_add_function(state, "alert", scr_alert);
-

If you want to organize your functions in Lua-like modules, you can use lua_add_code for that: -

-lua_add_function(state, "game_alert", scr_alert);
-lua_add_code(state, '
-    game = { alert: game_alert }
-');
-

which would then allow you to do -

game.alert("Hello!")

on Lua side of things. -

-
lua_return(...values)

- Lua allows to return multiple values from a function call at once. -

- This function helps to do that in scripts exposed to Lua via lua_add_function. -

- So, you could have -

-/// lengthdir_xy(len, dir)
-var len = argument0, dir = argument1;
-return lua_return(lengthdir_x(len, dir), lengthdir_y(len, dir));
-

expose it via -

-lua_add_function(state, "lengthdir_xy", lengthdir_xy);
-

and use it from Lua side like -

-
local x, y = lengthdir_xy(30, 45)
-print(x, y) -- 21.21, -21.21
-
-
lua_return_w(values:array)

- Same as aforementioned lua_return, but returns the contents of an array as a value list instead. - Note this will not work for nested arrays, however. -

-
lua_return_add(...values)

- Add zero or more values to the list of returned values. -

- This is particularly handy for any GML operations that are done in a loop, e.g. -

-/// instance_find_all(obj)
-with (argument0) lua_return_add(id);
-return lua_return_add();
-

The last line with an empty lua_return_add is needed to return 0 values if loop matches no instances (as runtime would otherwise assume that you are going to return something with a regular return). -

-
lua_bool(value)

- While Lua has a separate boolean type, GameMaker uses 1 as true-value and 0 as false-value. - This makes it hard to tell whether you were meaning to send 1 or true. -

- So there's this function, which returns either a lua_true or a lua_false depending on argument, which can be told apart by the extension explicitly, and will become the according Lua values once sent to Lua. -

-
lua_current

- When a Lua state calls the exposed GML script, this variable holds the ID of the "caller" state. Can be used if you want to do anything aside of just returning value(s). -

-
lua_show_error(text)

- Sends an error message to the currently executing Lua state. -

- This should only be used inside scripts exposed via lua_add_function. -

-/// scr_variable_global_get(name)
-if (is_string(argument0)) {
-    return variable_global_get(argument0);
-} else lua_show_error("Expected a variable name to be a string.");
-
-
Using GM instance variables from Lua

- If you are using GameMaker Studio 2 or an Early Access version of GameMaker: Studio 1, you can have Lua directly read and write variables on GameMaker instances. -

- To do so, you would add three scripts to your project: -

-/// ref_variable_instance_get(context, name)
-var q = argument0, s = argument1;
-with (q) return variable_instance_get(id, s);
-if (q < 100000) {
-    lua_show_error("Couldn't find any instances of " + string(q)
-        + " (" + object_get_name(q) + ")");
-} else lua_show_error("Couldn't find instance " + string(q));
-return undefined;
-

(reads a variable from an instance), -

-/// ref_variable_instance_set(context, name, value)
-var q = argument0, s = argument1, v = argument2, n = 0;
-with (q) { variable_instance_set(id, s, v); n++; }
-if (n) exit;
-if (q < 100000) {
-    lua_show_error("Couldn't find any instances of " + string(q)
-        + " (" + object_get_name(q) + ")");
-} else lua_show_error("Couldn't find instance " + string(q));
-

(writes a variable to an instance(s)), -

-/// ref_variable_instance_init(lua_state)
-var q = argument0;
-lua_add_function(q, "variable_instance_get", ref_variable_instance_get);
-lua_add_function(q, "variable_instance_set", ref_variable_instance_set);
-lua_add_code(q, '-- ref_variable_instance_init()
-    __idfields = __idfields or { };
-    debug.setmetatable(0, {
-        __index = function(self, name)
-            if (__idfields[name]) then
-                return _G[name];
-            else
-                return variable_instance_get(self, name);
-            end
-        end,
-        __newindex = variable_instance_set,
-    })
-');
-

(exposes the above scripts to a Lua state and sets it up to use them when trying to read/write a field on a numeric value (id)). -

- Then you can use them as following: -

-// create a Lua state:
-state = lua_state_create();
-// allow the state to work with GM instances:
-ref_variable_instance_init(state);
-// add a test function to the state -
-// function takes an instance and modifies it's `result` variable.
-lua_add_code(state, "function test(q) q.result = 'Hello!' end");
-// call the test-function for the current instance and display the result:
-result = "";
-lua_call(state, "test", id);
-show_debug_message(result);
-
-

- -

Automatically exposing scripts/functions

- If you are building a medium-scale scripting API, you may find yourself needing to expose a large number of scripts (and/or built-in functions), as well as introducing argument type checking to prevent GML-side errors. -

- To save you from having to deal with that, Apollo includes a small utility that generates wrapper and loader scripts. -

- It accepts function definitions in funcname(arg1:type1, arg2:type2, ...):rtype, -

    -
  • arg1, arg2, ...: argument names. Will be shown in errors returned to Lua. -
  • type1, type2, ...: argument types. Optional. - If defined, code will be added to ensure that each argument matches it's type. - Known types are real, bool, string; - color, int, index, id can also be used, but are treated same as real. -
  • rtype: returned type, if the function returns a specific one. - If set to bool, return-statement will be wrapped in lua_bool call. -
  • If prefixed with :, function will be marked as "instance function" and will accept an instance ID as first argument, also allowing to call it as inst.func(...) if instance access scripts are set up. -

- Constants can be defined either as name# (uses the value of same-named constant/variable) or name = value (computes the given GML value at inclusion time). -

- The tool is included with the extension as ApolloGen.exe; -

- A web-based version is available below: -

Whenever the contents of above field are changed, updated loader script will be output into the field below: -

You can then save them into a .gml file and import it to your project. - -

-

-
Writing Lua code

-

Learning Lua

- "getting started" page on the Lua' website houses a large collection of links to tutorials, wikis, and other learning materials. -

- Lua Manual provides detailed explanations on how internal elements and all standard functions lf the language work. -

-
Translating GML to Lua

- If you have pre-existing GML code that you'd like to quickly port for use with Apollo, I have also developed an online GML->Lua compiler. -

- While automatic conversion won't make extensive use of Lua-specific language features, it produces functional code in vast majority of cases and the output is clean enough to tweak it manually if needed. -

-

-
Lua coroutines

-

A summary on Lua coroutines

- A coroutine, in short, is a function that can pause/resume execution at arbitrary points. These can be used for iterators, cutscenes (pausing/resuming allows to write timing in an intuitive way), tweening, AI, or anything else that benefits from maintaining the state across multi-call execution. -

-
lua_thread_create(state_id)

- Creates a "thread" state for the given Lua state and returns it's ID. -

- Such "threads" share the global context (variables, functions, etc.) with their parent state, but have their own clal stack, meaning that they can do their own thing (namely, executing coroutines) while the parent state does something else. -

-thread = lua_thread_create(state);
-
-
lua_thread_destroy(state_id)

- Destroys a previously created "thread" state. -

- Does not free resources of the parent state, only what was owned by the thread itself. - Is a convenience function and is interchangeable with lua_state_destroy. -

-
lua_call_start(state_id, name, ...arguments)

- Starts a coroutine call on the given sate, returns whether the operation succeeded. -

- Note that some functions will work oddly (or not work at all) on a state that is currently amidst the coroutine call, which is why you should generally create a thread for the coroutine call. -

-
lua_call_start_w(state_id, name, arguments:array)

- Same as lua_call_start, but takes arguments as an array. -

-
lua_call_next(state_id)

- Executes the next iteration on the given state and returns whether the coroutine call is ongoing (as opposed to finishing or encountering a runtime error). -

- The general scheme of performing coroutine calls is thus as following: -

-lua_add_code(state, "
-    function test(num)
-        for i = 1, num do
-            coroutine.yield(i)
-        end
-        return 'rad!'
-    end
-");
-th = lua_thread_create(state);
-if (lua_call_start(th, "test", 4)) {
-    while (lua_call_next(th)) {
-        show_debug_message("yield: " + string(lua_call_result));
-    }
-    show_debug_message("result: " + string(lua_call_result));
-}
-lua_thread_destroy(th);
-
-
lua_call_result

- Holds the result of the last lua_call_next - yielded value when the execution continues, and final returned value when the execution stops. -

-

-
FAQ

-

What Lua version is used?

- Apollo uses Lua 5.3.4 as of writing this. -

- In case you'd like a custom version (such as to use LuaJIT, or to use a Lua fork with - different syntax), C++ source code is included - it will work with any Lua build - down to 5.1. -

-
What platforms does it run on?

- The extension runs on Windows, Mac, and Linux - linked dynamically in all cases. -

- Apollo v2 beta currently only comes with a Windows (GMS1,GMS2) binary, - but you can compile it yourself (code is portable). -

- Mac may require additional tinkering (via install_name_tool - example), as library inclusion paths may vary depending on whether the game is running from IDE, whether YYC is enabled, and GMS version. If you are familiar with Mac extension development yourself, feel free to get in touch about better ways of handling this. -

-

-
Limitations

-

Lua tables cannot be transmitted to GML automatically

- While these are roughly equivalent to GM's ds_maps, the two work very differently - - ds_maps are passed by-index and managed manually (ds_map_destroy), - Lua' tables are passed by-reference and managed by garbage collector. -

- While future iterations on GML should make it possible to automatically convert between tables and lightweight data structures, this would only allow to return a new table/structure rather than modifying an existing one. -

- The issue can be approached in several ways: -

    -
  • Expose ds_maps to Lua code and use them instead of tables for transfer. -
  • Have a wrapper function on Lua side to expand the table into multiple values prior to calling the GML script and/or wrap multiple returned values from GML back into a table. -
  • If you do not need to read data from the table (but store/retrieve it), you can convert it to index and back on Lua side via lookup tables (see below). -
-
Lua-specific reference types cannot be transmitted to GML automatically

- Lua supports several additional reference types (such as Lua function references), - but these cannot be safely sent to GML as pointers as they are garbage-collected, - and thus may get recycled while still referenced on the GML side of things - (resulting in hard crash when trying to use the passed back value). -

- A good way to deal with this is to make a pair of lookup tables - since Lua allows table indexes to be of any type, you can do something like the following: -

ref = {
-    __r2i = { },
-    __i2r = { },
-    __next = 0
-}
-function ref.toid(fn)
-    local id = ref.__r2i[fn]
-    if (id == nil) then
-        id = ref.__next
-        ref.__next = id + 1
-        ref.__r2i[fn] = id
-        ref.__i2r[id] = fn
-    end
-    return id
-end
-function ref.fromid(id)
-    return ref.__i2r[id]
-end
-function ref.free(fn)
-    local id
-    if (type(fn) == "number") then
-        id = fn
-        fn = ref.__i2r[id]
-    else
-        id = ref.__r2i[fn]
-    end
-    ref.__r2i[fn] = nil
-    ref.__i2r[id] = nil
-end

Which allow you to use ref.toid(some_reference) to return/create a numeric ID for a reference, ref.fromid(index) to convert one of those back to a reference, and ref.free(index_or_reference) to remove the lookup pairs (allowing Lua to safely recycle the reference when it is no longer used). -

-

-
- - diff --git a/datafiles/Getting started/4 Looping operation.pxc b/datafiles/Getting started/4 Looping operation.pxc index 59325a9e1..52263be00 100644 --- a/datafiles/Getting started/4 Looping operation.pxc +++ b/datafiles/Getting started/4 Looping operation.pxc @@ -1 +1 @@ -{"notes":[],"global_node":{"attri":{"update_graph":true,"show_update_trigger":false,"color":-1},"inputs":[]},"nodes":[{"x":160,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Shape","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"color_depth":1,"show_update_trigger":0,"node_param_width":192,"array_process":0,"node_width":0,"node_height":0,"use_project_dimension":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Dimension","loop_range":-1,"color":-1,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":300845,"speed":1,"amplitude":1,"octave":2}]],[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":617386,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[64,64],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":648683,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Background","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":613631,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":502555,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":[{"data":"Rectangle","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":0,"spr_blend":9404030,"name":"Rectangle"},{"data":"Ellipse","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":1,"spr_blend":9404030,"name":"Ellipse"},{"data":"Regular polygon","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":2,"spr_blend":9404030,"name":"Regular polygon"},{"data":"Star","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":3,"spr_blend":9404030,"name":"Star"},{"data":"Arc","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":4,"spr_blend":9404030,"name":"Arc"},{"data":"Teardrop","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":5,"spr_blend":9404030,"name":"Teardrop"},{"data":"Cross","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":6,"spr_blend":9404030,"name":"Cross"},{"data":"Leaf","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":7,"spr_blend":9404030,"name":"Leaf"},{"data":"Crescent","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":8,"spr_blend":9404030,"name":"Crescent"},{"data":"Donut","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":9,"spr_blend":9404030,"name":"Donut"}]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":515416,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":159417,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":301587,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":937136,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":680650,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":238022,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[32,32,9.0399999999999991,8.9600000000000009,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":191740,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"useShape":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Sides","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,3,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":403117,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Inner radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":569593,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Anti alising","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":776759,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Rotation","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":566671,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Angle range","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":203861,"speed":1,"amplitude":1,"octave":2}]],[[0,180,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":110837,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":349551,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Corner radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":593441,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"range":[0,0.5,0.01]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":802156,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Background color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4278190080,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":560844,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Height","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":809005,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Start radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":403276,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape path","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-4,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":662714,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Positioning Mode","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":110684,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"data":["Area","Center + Scale","Full Image"]},"name_custom":false},{"is_modified":false,"anim":false,"name":"Center","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":648524,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":191307,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":636478,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Half Size","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":582550,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":767284,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":122954,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Tile","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":245344,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Shape Rotation","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":943417,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Level","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":580002,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":820380,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[0,1],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":800538,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":138857,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":578436,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Shape","id":710959498,"type":"Node_Shape","group":-4,"array_process":0},{"x":-320,"y":96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Index","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":124690,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":157955,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Index","id":870229182,"type":"Node_Iterator_Index","group":171652176},{"x":-416,"y":-128,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":499115,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Looping allows you to repeat the same operation multiple times with slight variation.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":978915,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":700409,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":228744,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":969053,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":921038,"speed":1,"amplitude":1,"octave":2}]],[[0,-128,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":513684,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-416,-128],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":609379,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":564157,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":808600,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":588832,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":660826364,"type":"Node_Display_Text","group":-4},{"x":-320,"y":-96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Input","outputs":[{"visible":1,"color":-1},{"visible":1,"color":-1}],"tool":0,"attri":{"inherit_name":0,"inherit_type":0,"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Display type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":327232,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"update_hover":false,"data":["Default"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Range","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":350194,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":927223,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":730911,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":0},"name_custom":0},{"is_modified":true,"anim":false,"name":"Input type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":368892,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"update_hover":false,"data":["Integer","Float","Boolean","Color","Surface","File Path","Curve","Text","Object","Node",-1,"Any","Path","Particle","Rigidbody Object","Domain","Struct","Strands","Mesh","Trigger",-1,"3D Mesh","3D Light","3D Scene","3D Material",-1,"Audio"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Enum label","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":553045,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Vector size","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":719906,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["2","3","4"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Order","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":397961,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Display preview gizmo","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":326809,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Step","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0.01,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":245172,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Button Label","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,"Trigger",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":752111,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":677448,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":201378,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Input","id":794727501,"type":"Node_Iterator_Input","group":171652176},{"x":-160,"y":32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Array_Get","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Array","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":252000456,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":989093,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Index","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":870229182,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":216714,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Overflow","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":997044,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Clamp","Loop","Ping Pong"]},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":529477,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":908796,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Array Get","id":265354093,"type":"Node_Array_Get","group":171652176},{"x":-256,"y":-64,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Input","outputs":[{"visible":1,"color":-1},{"visible":1,"color":-1}],"tool":0,"attri":{"inherit_name":0,"inherit_type":0,"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Display type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":628164,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"update_hover":false,"data":["Default","Range","Rotation","Rotation range","Slider","Slider range","Padding","Vector","Vector range","Area","Enum button","Menu scroll"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Range","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":833970,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":799485,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":953922,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":0},"name_custom":0},{"is_modified":true,"anim":false,"name":"Input type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":653815,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"update_hover":false,"data":["Integer","Float","Boolean","Color","Surface","File Path","Curve","Text","Object","Node",-1,"Any","Path","Particle","Rigidbody Object","Domain","Struct","Strands","Mesh","Trigger",-1,"3D Mesh","3D Light","3D Scene","3D Material",-1,"Audio"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Enum label","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":152777,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Vector size","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":978690,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["2","3","4"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Order","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":687222,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Display preview gizmo","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":196758,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Step","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0.01,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":997484,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Button Label","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,"Trigger",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":890294,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":837586,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":380444,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Input","id":987418939,"type":"Node_Iterator_Input","group":130818950},{"x":-352,"y":224,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":783618,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Another node used in loop is index. Index node output the current loop index. This can be use to get value in array",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":116803,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":101429,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":616107,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,450,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":474945,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-352,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":365276,"speed":1,"amplitude":1,"octave":2}]],[[0,192,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":129525,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-352,224],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":832346,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":139209,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":378965,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":611994,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":869049526,"type":"Node_Display_Text","group":171652176},{"x":192,"y":-64,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Output","outputs":[],"tool":0,"attri":{"inherit_name":0,"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Value","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":331368383,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":158469,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Loop exit","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":275353,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":372999,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":294751,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Output","id":787085982,"type":"Node_Iterator_Output","group":130818950},{"x":-416,"y":-192,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":256108,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Getting started 4: Looping ",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":444344,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":896800,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":331526,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":309118,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":582562,"speed":1,"amplitude":1,"octave":2}]],[[0,-192,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":694622,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-416,-192],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":127751,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":916547,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":278310,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":198406,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":676613630,"type":"Node_Display_Text","group":-4},{"x":-192,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":420430,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"The only property in loop node defines how many times you want to loop.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":284035,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":477562,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":194610,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,300,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":418617,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-192,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":336286,"speed":1,"amplitude":1,"octave":2}]],[[0,-32,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":186765,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-192,-32],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":666782,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":555995,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":496984,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":895143,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":628179710,"type":"Node_Display_Text","group":-4},{"x":-320,"y":-128,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":948621,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Loop in-output have one special junction. This junction define which data to reuse in each loop.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":620710,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":129201,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":125849,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":135551,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-320,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":589408,"speed":1,"amplitude":1,"octave":2}]],[[0,-128,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":766032,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-320,-128],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":121490,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":447844,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":177718,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":261738,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":797189508,"type":"Node_Display_Text","group":130818950},{"x":-352,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"instance_base":-4,"iname":"Loop","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"input_display_list":[0,1],"output_display_list":[0],"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Repeat","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":708292,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Input","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":738998,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":627069,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":594773,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Loop","id":130818950,"type":"Node_Iterate","group":-4},{"x":256,"y":-96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Output","outputs":[],"tool":0,"attri":{"inherit_name":0,"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Value","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":400135540,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":986516,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Loop exit","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":794727501,"visible":1,"from_index":1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":399129,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":654176,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":350556,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Output","id":217889613,"type":"Node_Iterator_Output","group":171652176},{"x":-288,"y":128,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":503833,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"In this example, in each loop it will add value by 1. And use that value as a input in the next loop.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":314740,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":401352,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":460411,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":644414,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-288,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":428788,"speed":1,"amplitude":1,"octave":2}]],[[0,128,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":323343,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-288,128],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":712433,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":251254,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":826104,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":455807,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":551539294,"type":"Node_Display_Text","group":130818950},{"x":-416,"y":128,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":117254,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Rendering with loop can be unstable, try press multiple times until it output properly",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":318920,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":454581,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":106012,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,400,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":943017,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":522828,"speed":1,"amplitude":1,"octave":2}]],[[0,128,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":741291,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-416,128],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":195682,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":760363,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":144974,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":646279,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":741389209,"type":"Node_Display_Text","group":-4},{"x":-416,"y":-224,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":552731,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Welcome to Pixel Composer",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":338720,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":927344,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":208653,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":580195,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":997385,"speed":1,"amplitude":1,"octave":2}]],[[0,-224,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":810424,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-416,-224],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":191616,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":518184,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":671243,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":340265,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":593948373,"type":"Node_Display_Text","group":-4},{"x":-320,"y":0,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Palette","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"array_process":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Palette","loop_range":-1,"color":-1,"animators":[[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":948287,"speed":1,"amplitude":1,"octave":2}]],[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":988483,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[4293916155,4289450994,4289044422,4288441739,4286467401,4282656551],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":249531,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Trim range","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":558713,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":544975,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":505589,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":860398,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":672822,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Palette","id":252000456,"type":"Node_Palette","group":171652176,"array_process":0},{"x":0,"y":-96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Outline","outputs":[{"visible":1,"color":-1},{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"color_depth":2,"show_update_trigger":0,"node_param_width":192,"interpolate":0,"oversample":0,"array_process":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Surface in","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":794727501,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":685003,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0},{"is_modified":true,"anim":false,"name":"Width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{"mapped":false,"map_index":15},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":675311,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":265354093,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":311684,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Blend","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":399801,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Blend alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{"mapped":false,"map_index":16},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":419743,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":832221,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Inside","Outside"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Anti alising","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":600010,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Oversample mode","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":721302,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Empty","Clamp","Repeat"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Start","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{"mapped":false,"map_index":17},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":836649,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Mask","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":415219,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0},{"is_modified":true,"anim":false,"name":"Mix","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":258649,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Active","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":899213,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Crop border","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":931889,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Invert mask","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":358102,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Mask feather","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":628161,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"range":[0,32,0.10000000000000001]},"name_custom":false},{"is_modified":false,"anim":false,"name":"Width map","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":736581,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"atlas":true},"name_custom":false},{"is_modified":false,"anim":false,"name":"Blend alpha map","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":218123,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"atlas":true},"name_custom":false},{"is_modified":false,"anim":false,"name":"Start map","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":904201,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"atlas":true},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":424332,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":408289,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Outline","id":400135540,"type":"Node_Outline","group":171652176,"array_process":0},{"x":-416,"y":-96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":996209,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"This can be done using loop node . Which works similiar to group.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":403709,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":467201,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":775002,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":961059,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":139737,"speed":1,"amplitude":1,"octave":2}]],[[0,-96,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":354114,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-416,-96],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":568982,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":717541,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":308808,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":529946,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":714226318,"type":"Node_Display_Text","group":-4},{"x":320,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"instance_base":-4,"iname":"Loop","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"input_display_list":[0,1],"output_display_list":[0],"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Repeat","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":445246,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Input","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":710959498,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":487088,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":223106,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":131910,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Loop","id":171652176,"type":"Node_Iterate","group":-4},{"x":-32,"y":32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Math","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":950955,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Add","Subtract","Multiply","Divide","Power","Root","Sin","Cos","Tan","Modulo","Floor","Ceil","Round","Lerp","Abs"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"a","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":987418939,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":809718,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"b","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":818293,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Degree angle","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":910878,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"To integer","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":575611,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Amount","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":307319,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":667775,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":777105,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Math","id":331368383,"type":"Node_Math","group":130818950}],"addon":{},"animator":{"frames_total":12,"framerate":15,"frame_range":-4},"version":11690,"attributes":{"surface_dimension":[32,32],"palette_fix":false,"palette":[0,16777215]},"timelines":{"color":-1,"type":"Folder","contents":[],"name":"","show":true},"onion_skin":{"enabled":0,"alpha":0.5,"on_top":1,"range":[-1,1],"step":1,"color":[255,16711680]},"previewGrid":{"color":8482157,"size":[16,16],"snap":0,"opacity":0.5,"show":0},"preview":"","graphGrid":{"color":16777215,"highlight":12,"snap":1,"size":32,"show_origin":0,"opacity":0.050000000000000003,"show":1},"metadata":{"alias":"","tags":[],"contact":"","author":"MakhamDev","description":"","aut_id":0,"file_id":0,"version":11482}} \ No newline at end of file +{"metadata":{"version":11482,"alias":"","tags":[],"contact":"","author":"MakhamDev","description":"","aut_id":0,"file_id":0},"timelines":{"color":-1,"contents":[],"type":"Folder","name":"","show":true},"attributes":{"surface_dimension":[32,32],"palette_fix":false,"palette":[0,16777215],"strict":false},"nodes":[{"x":-352,"y":32,"array_process":0,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":300845,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":617386,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[64,64],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":648683,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Dimension","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":613631,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Background","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":502555,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":[{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Rectangle","name":"Rectangle","spr_ind":0},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Ellipse","name":"Ellipse","spr_ind":1},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Regular polygon","name":"Regular polygon","spr_ind":2},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Star","name":"Star","spr_ind":3},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Arc","name":"Arc","spr_ind":4},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Teardrop","name":"Teardrop","spr_ind":5},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Cross","name":"Cross","spr_ind":6},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Leaf","name":"Leaf","spr_ind":7},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Crescent","name":"Crescent","spr_ind":8},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Donut","name":"Donut","spr_ind":9}]}},{"on_end":0,"sep_axis":0,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":515416,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":159417,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":301587,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":937136,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":680650,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":238022,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[32,32,9.0399999999999991,8.9600000000000009,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":191740,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"useShape":false}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,3,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":403117,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Sides","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":569593,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Inner radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":776759,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Anti-aliasing","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":566671,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Rotation","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":203861,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,180,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":110837,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":349551,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Angle range","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":593441,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Corner radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"range":[0,0.5,0.01]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":802156,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4278190080,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":560844,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Background color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":809005,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Height","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":403276,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Start radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,-4,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":662714,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape path","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":110684,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Positioning Mode","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Area","Center + Scale","Full Image"]}},{"on_end":0,"sep_axis":false,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":648524,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":191307,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":636478,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Center","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":582550,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":767284,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":122954,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Half Size","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":245344,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Tile","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":943417,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape Rotation","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":580002,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":820380,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[0,1],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":800538,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Level","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Shape","id":710959498,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[{"visible":1,"color":-1}],"iname":"Shape","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"color":-1,"node_height":0,"use_project_dimension":0,"array_process":0,"node_param_width":192,"node_width":0,"color_depth":1,"update_graph":1},"type":"Node_Shape","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":138857,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":578436,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":160,"y":32,"array_process":0,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":710959498,"from_index":0,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":727306,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Surface in","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{"mapped":false,"map_index":15},"global_use":false,"global_key":"","raw_value":[[0,3,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":649158,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Width","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":"eAP82s513050fglaJyE3DVz26VXT8qEQ","from_index":0,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,4294967295,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":461341,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":237205,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Blend","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{"mapped":false,"map_index":16},"global_use":false,"global_key":"","raw_value":[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":424001,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Blend alpha","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,1,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":986712,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Inside","Outside"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":424864,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Anti aliasing","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":705194,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Oversample mode","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Empty","Clamp","Repeat"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{"mapped":false,"map_index":17},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":461254,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Start","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":101577,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Mask","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":529968,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Mix","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":928566,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Active","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":305438,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Crop border","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":537487,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Invert mask","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":688539,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Mask feather","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"range":[0,32,0.10000000000000001]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":901014,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Width map","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":572014,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Blend alpha map","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":722665,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Start map","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}}],"name":"Outline","id":"eAP82U489698ItuMWCpBPOKJl0YEReMj","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[{"visible":true,"color":-1},{"visible":true,"color":-1}],"iname":"Outline17496","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"color":-1,"interpolate":0,"oversample":0,"node_height":0,"array_process":0,"node_param_width":192,"node_width":0,"color_depth":2,"update_graph":true},"type":"Node_Outline","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":602479,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":424437,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":0,"y":128,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":"eAP82b496059z3C1128wGz7juiEXNXAy","from_index":0,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":716750,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Array","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":"eAP83L540437XX9W1Vnj1s2Hse674jiv","from_index":0,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":789661,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Index","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":414335,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Overflow","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Clamp","Loop","Ping Pong"]}}],"name":"Array Get","id":"eAP82s513050fglaJyE3DVz26VXT8qEQ","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[{"visible":true,"color":-1}],"iname":"Array_Get87735","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":true,"color":-1},"type":"Node_Array_Get","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":743502,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":527342,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":-416,"y":-128,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":499115,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Looping allows you to repeat the same operation multiple times with slight variation.\n\nThis can be done using loop node . Which works similiar to group.",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":978915,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":700409,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":228744,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":969053,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":921038,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-128,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":513684,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,-128],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":609379,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":564157,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":660826364,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":808600,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":588832,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-416,"y":-192,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":256108,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Getting started 4: Looping ",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":444344,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":896800,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":331526,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":309118,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":582562,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-192,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":694622,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,-192],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":127751,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":916547,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":676613630,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":278310,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":198406,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-128,"y":96,"array_process":0,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[[[0,4278190080,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":258789,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,4294967295,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":905706,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[4293916155,4289450994,4289044422,4288441739,4286467401,4282656551],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":793244,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Palette","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":421588,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":372356,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[0,1],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":671721,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Trim range","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Palette","id":"eAP82b496059z3C1128wGz7juiEXNXAy","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[{"visible":true,"color":-1}],"iname":"Palette31614","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"node_height":0,"array_process":0,"node_param_width":192,"node_width":0,"update_graph":true,"color":-1},"type":"Node_Palette","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":268996,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":479249,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":-416,"y":-64,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,4294967295,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":954446,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,"In version 1.17. Loop can now be create inline by connecting the output of the loop back to the beginning.",[0,1],[0,0],0,0,true,{"amplitude":1,"seed":702748,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,2,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":404378,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0.75,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":704626,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":576926,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":673036,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-64,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":785373,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,-64],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":975442,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":761159,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display Text","id":"eAP80X3727448fKEp4FiDljPO3hz4oZo","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[],"iname":"Display_Text93783","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":true,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":376214,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":541334,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":-416,"y":416,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":117254,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Rendering with loop can be unstable, try press multiple times until it output properly",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":318920,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":454581,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":106012,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":943017,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":522828,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,128,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":741291,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,416],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":195682,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":760363,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":741389209,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":144974,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":646279,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":0,"y":0,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,6,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":904014,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Repeat","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Loop","id":"eAP832521042IEOFs6c3vPTy2wUcis7J","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[],"iname":"Loop11147","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"color":-1,"node_height":0,"junc_in":["eAP82U489698ItuMWCpBPOKJl0YEReMj",0],"junc_out":["eAP82U489698ItuMWCpBPOKJl0YEReMj",0],"node_param_width":192,"members":["eAP82U489698ItuMWCpBPOKJl0YEReMj","eAP82s513050fglaJyE3DVz26VXT8qEQ","eAP82b496059z3C1128wGz7juiEXNXAy","eAP83L540437XX9W1Vnj1s2Hse674jiv"],"node_width":0,"update_graph":true},"type":"Node_Iterate_Inline","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":176344,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":923313,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":-416,"y":-224,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":552731,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Welcome to Pixel Composer",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":338720,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":927344,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":208653,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":580195,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":997385,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-224,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":810424,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,-224],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":191616,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":518184,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":593948373,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":671243,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":340265,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-128,"y":192,"buffer":{},"inputs":[],"name":"Index","id":"eAP83L540437XX9W1Vnj1s2Hse674jiv","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[{"visible":true,"color":-1}],"iname":"Index89088","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":true,"color":-1},"type":"Node_Iterator_Index","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":528615,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":256101,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]},{"x":-416,"y":384,"buffer":{},"inputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,4294967295,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":981289,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0," on the loop area to adjust repeatition count.",[0,1],[0,0],0,0,true,{"amplitude":1,"seed":596243,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,2,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":989682,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0.75,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":645065,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":960923,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-416,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":230046,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,352,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":595672,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-416,384],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":206785,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":257210,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display Text","id":"eAP85N013505WJexgbn9MgfD260EEhdw","renamed":true,"previewable":true,"tool":false,"render":true,"outputs":[],"iname":"Display_Text76200","group":-4,"show_parameter":false,"attri":{"show_update_trigger":false,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":true,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":744479,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":641416,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"visible":true,"color":-1}]}],"version":11690,"preview":"","animator":{"framerate":15,"frame_range":-4,"frames_total":12},"onion_skin":{"on_top":1,"range":[-1,1],"enabled":0,"step":1,"alpha":0.5,"color":[255,16711680]},"previewGrid":{"opacity":0.5,"snap":0,"size":[16,16],"show":0,"color":8482157},"graphGrid":{"show_origin":0,"opacity":0.050000000000000003,"size":32,"show":1,"highlight":12,"snap":1,"color":16777215},"notes":[],"global_node":{"attri":{"color":-1,"update_graph":true,"show_update_trigger":false},"inputs":[]},"addon":{}} \ No newline at end of file diff --git a/datafiles/Getting started/5 Particle and effectors.pxc b/datafiles/Getting started/5 Particle and effectors.pxc index db3f71bda..0f64cd8a9 100644 --- a/datafiles/Getting started/5 Particle and effectors.pxc +++ b/datafiles/Getting started/5 Particle and effectors.pxc @@ -1 +1 @@ -{"notes":[],"global_node":{"attri":{"update_graph":true,"show_update_trigger":false,"color":-1},"inputs":[]},"nodes":[{"x":-384,"y":-96,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":858762,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Press to start a simulation.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":717577,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":827642,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":887018,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":653697,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":747508,"speed":1,"amplitude":1,"octave":2}]],[[0,-96,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":489704,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-384,-96],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":554918,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":526412,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":967451,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":141463,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":899910864,"type":"Node_Display_Text","group":-4},{"x":-224,"y":160,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":222095,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"There are a lot of properties that control particle spawning, movement, etc.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":188753,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":450379,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":259892,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":383898,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-224,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":152259,"speed":1,"amplitude":1,"octave":2}]],[[0,160,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":450041,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-224,160],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":266309,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":514711,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":458543,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":556469,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":406135373,"type":"Node_Display_Text","group":-4},{"x":32,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Particle","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"show_update_trigger":0,"part_amount":512,"node_param_width":192,"node_width":0,"node_height":0,"use_project_dimension":0,"color":-1,"color_depth":2,"interpolate":0,"oversample":0},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Particle sprite","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":930439119,"visible":1,"from_index":0,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":858516,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn delay","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":548249,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn amount","loop_range":-1,"color":-1,"animators":[[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":328028,"speed":1,"amplitude":1,"octave":2}]],[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":365048,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[2,2],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":638459,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn area","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":622308,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":328573,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":219194,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":925083,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":136905,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":293969,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[16,27,16,5,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":114796,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn distribution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":213082,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Area","Border","Map"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Lifespan","loop_range":-1,"color":-1,"animators":[[[0,20,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":218098,"speed":1,"amplitude":1,"octave":2}]],[[0,30,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":368751,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[20,30],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":717375,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":0},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn direction","loop_range":-1,"color":-1,"animators":[[[0,45,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":432829,"speed":1,"amplitude":1,"octave":2}]],[[0,135,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":932553,"speed":1,"amplitude":1,"octave":2}]],[[0,135,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":666912,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":746875,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":169270,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[80,110],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":906120,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Acceleration","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":298405,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":935639,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[-0.02,-0.029999999999999999],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":781177,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Orientation","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":410354,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":573668,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":110565,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":609308,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":675339,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":164317,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Rotational speed","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":574147,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":785400,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":696164,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn scale","loop_range":-1,"color":-1,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":959256,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":416057,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":872146,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":758597,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[1,1,1,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":292314,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Scale over time","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":506457,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":854972,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":517198,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":127674,"speed":1,"amplitude":1,"octave":2}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":879309,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":125844,"speed":1,"amplitude":1,"octave":2}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":785601,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":376248,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":512782,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":422310,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":361456,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":906244,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.109375,0.58750000000000002,1,0,0.109375,-0.58750000000000002],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":837144,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Color over lifetime","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"{\"keys\":[{\"value\":4294924800.0,\"time\":0.0},{\"value\":4278255462.0,\"time\":0.40000000000000002},{\"value\":4278190335.0,\"time\":1.0}],\"type\":0.0}",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":859795,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":301597,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":680030,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":544572,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha over time","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":177185,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":589530,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":537581,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":523131,"speed":1,"amplitude":1,"octave":2}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":718111,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":827164,"speed":1,"amplitude":1,"octave":2}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":830186,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":742043,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":384003,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":762619,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":104480,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":986809,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.33333333333333331,0,1,1,0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":689415,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Rotate by direction","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,362,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":807320,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":916128,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Stream","Burst","Trigger"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn size","loop_range":-1,"color":-1,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":110727,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":656470,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":725930,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn velocity","loop_range":-1,"color":-1,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":798905,"speed":1,"amplitude":1,"octave":2}]],[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":950977,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":576869,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":0},"name_custom":0},{"is_modified":true,"anim":false,"name":"Gravity","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":334870,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":197689,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":656875,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Direction wiggle","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":190343,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":366754,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":549948,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"per_line":true,"label":["Amplitude","Period"],"linkable":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Loop","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":315346,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Surface array","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":375025,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Random","Order","Animation","Scale"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Animation speed","loop_range":-1,"color":-1,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":892190,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":166122,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":516372,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Scatter","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":549292,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Uniform","Random"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Boundary data","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":457539,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"On animation end","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,217,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":857149,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Loop","Ping pong","Destroy"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":103955,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Random blend","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"{\"keys\":[{\"value\":4294967295.0,\"time\":0.0}],\"type\":0.0}",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":934719,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Directed from center","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":310634,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Distribution map","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,493,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":114107,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0},{"is_modified":true,"anim":false,"name":"Atlas","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0,0,0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":464841,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"atlas":true},"name_custom":0},{"is_modified":true,"anim":false,"name":"Seed","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":106033,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Gravity direction","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,490,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":666524,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Turning","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":547761,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":417817,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":997533,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"linked":1},"name_custom":0},{"is_modified":true,"anim":false,"name":"Turn both directions","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":886433,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Turn scale with speed","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":721891,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Collide ground","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":887845,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Ground offset","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":358898,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Bounce amount","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":783531,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Bounce friction","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":730228,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Position wiggle","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":367663,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":679257,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":180391,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"per_line":true,"label":["Amplitude","Period"],"linkable":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Rotation wiggle","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":346208,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":191114,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":646082,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"per_line":true,"label":["Amplitude","Period"],"linkable":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Scale wiggle","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":269033,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":394474,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":947470,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"per_line":true,"label":["Amplitude","Period"],"linkable":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Spawn","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{"output":true,"name":"Trigger"},"name_custom":0},{"is_modified":false,"anim":false,"name":"Follow Path","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":945755,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Path","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":465680,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Path Deviation","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":873472,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":719755,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":826282,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":543104,"speed":1,"amplitude":1,"octave":2}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":292053,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":699825,"speed":1,"amplitude":1,"octave":2}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":962481,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":900223,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":380355,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":130403,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":925079,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":678604,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.33333333333333331,0,1,1,0,0],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":789744,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":true,"anim":false,"name":"Output dimension","loop_range":-1,"color":-1,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":765502,"speed":1,"amplitude":1,"octave":2}]],[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":311503,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,[32,32],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":587157,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Round position","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":761885,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Blend mode","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":244248,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Normal","Alpha","Additive"]},"name_custom":0},{"is_modified":false,"anim":false,"name":"Background","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":true,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":456549,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"atlas":true},"name_custom":false},{"is_modified":false,"anim":false,"name":"Render Type","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":149607,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"data":["Surface","Line"]},"name_custom":false},{"is_modified":false,"anim":false,"name":"Line life","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,4,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":125208,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":110997,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Clear cache","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":761344,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Particle","id":254863834,"type":"Node_Particle","group":-4,"part_base_length":48},{"x":-384,"y":-128,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":802773,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Particle is one of a node in Pixel Composer which allow you to simulate particle effect.",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":763305,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":401908,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":566417,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":891240,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":281793,"speed":1,"amplitude":1,"octave":2}]],[[0,-128,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":426146,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-384,-128],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":144304,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":461544,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":960956,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":395548,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":660826364,"type":"Node_Display_Text","group":-4},{"x":-384,"y":-192,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":544209,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Getting started 5: Particle and effectors",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":302567,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":842916,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":870703,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":991902,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":664603,"speed":1,"amplitude":1,"octave":2}]],[[0,-192,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":189409,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-384,-192],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":418320,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":721513,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":522234,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":139157,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":676613630,"type":"Node_Display_Text","group":-4},{"x":-160,"y":-32,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Shape","outputs":[{"visible":1,"color":-1}],"tool":0,"attri":{"update_graph":1,"color_depth":1,"show_update_trigger":0,"node_param_width":192,"array_process":0,"node_width":0,"node_height":0,"use_project_dimension":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Dimension","loop_range":-1,"color":-1,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":903520,"speed":1,"amplitude":1,"octave":2}]],[[0,32,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":625982,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[4,4],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":207569,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Background","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":874111,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":490080,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":[{"data":"Rectangle","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":0,"spr_blend":9404030,"name":"Rectangle"},{"data":"Ellipse","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":1,"spr_blend":9404030,"name":"Ellipse"},{"data":"Regular polygon","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":2,"spr_blend":9404030,"name":"Regular polygon"},{"data":"Star","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":3,"spr_blend":9404030,"name":"Star"},{"data":"Arc","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":4,"spr_blend":9404030,"name":"Arc"},{"data":"Teardrop","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":5,"spr_blend":9404030,"name":"Teardrop"},{"data":"Cross","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":6,"spr_blend":9404030,"name":"Cross"},{"data":"Leaf","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":7,"spr_blend":9404030,"name":"Leaf"},{"data":"Crescent","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":8,"spr_blend":9404030,"name":"Crescent"},{"data":"Donut","tooltip":"","spr":"@ref sprite(s_node_shape_type)","spr_ind":9,"spr_blend":9404030,"name":"Donut"}]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":621302,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":752536,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":242173,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":593371,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":392829,"speed":1,"amplitude":1,"octave":2}]],[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":265613,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[2,2,2,2,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":555612,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"useShape":false},"name_custom":0},{"is_modified":true,"anim":false,"name":"Sides","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,3,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":454329,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Inner radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":939150,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Anti alising","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":128342,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Rotation","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":808462,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Angle range","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":552816,"speed":1,"amplitude":1,"octave":2}]],[[0,180,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":243700,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":652140,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Corner radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":589822,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"range":[0,0.5,0.01]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":404195,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Background color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4278190080,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":130899,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Height","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":728630,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Start radius","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":675810,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Shape path","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,-4,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":698991,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Positioning Mode","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":727748,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{"data":["Area","Center + Scale","Full Image"]},"name_custom":false},{"is_modified":false,"anim":false,"name":"Center","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":883302,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":218458,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":934227,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Half Size","loop_range":-1,"color":-1,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":823660,"speed":1,"amplitude":1,"octave":2}]],[[0,16,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":995747,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":462196,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Tile","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":525523,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Shape Rotation","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":197834,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Level","loop_range":-1,"color":-1,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":357038,"speed":1,"amplitude":1,"octave":2}]],[[0,1,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":669422,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[0,1],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":691771,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":967508,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":295834,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Shape","id":930439119,"type":"Node_Shape","group":-4,"array_process":0},{"x":-384,"y":-224,"show_parameter":0,"buffer":{},"previewable":true,"iname":"Display_text","outputs":[],"tool":0,"attri":{"update_graph":1,"node_param_width":192,"show_update_trigger":0,"node_width":0,"node_height":0,"color":-1},"renamed":true,"inputs":[{"is_modified":true,"anim":false,"name":"Color","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":885836,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Text","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,"Welcome to Pixel Composer",[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":194960,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Style","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":809895,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{"data":["Header","Sub header","Normal"]},"name_custom":0},{"is_modified":true,"anim":false,"name":"Alpha","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":913079,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Line width","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":0,"from_index":-1,"global_use":0,"unit":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":246815,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":false,"anim":false,"name":"Position","loop_range":-1,"color":-1,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":811586,"speed":1,"amplitude":1,"octave":2}]],[[0,-224,[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":717897,"speed":1,"amplitude":1,"octave":2}]]],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,[-384,-224],[0,1],[0,0],0,0,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":951255,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false},{"is_modified":false,"anim":false,"name":"Smooth transform","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":false,"from_index":-1,"global_use":false,"unit":0,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":994991,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":false,"display_data":{},"name_custom":false}],"render":1,"inspectInputs":[{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":792589,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Toggle execution","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"frequency":4,"type":0,"axis_sync":false,"phase":0,"seed":511894,"speed":1,"amplitude":1,"octave":2}]],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"is_modified":true,"anim":false,"name":"Update","loop_range":-1,"color":-1,"animators":[],"shift_x":0,"shift_y":0,"attributes":{},"from_node":-1,"visible":1,"from_index":-1,"global_use":0,"unit":0,"global_key":"","raw_value":[],"on_end":0,"sep_axis":0,"display_data":{},"name_custom":0},{"visible":1,"color":-1}],"name":"Display text","id":593948373,"type":"Node_Display_Text","group":-4}],"addon":{},"animator":{"frames_total":30,"framerate":30,"frame_range":-4},"version":11690,"attributes":{"surface_dimension":[32,32],"palette_fix":false,"palette":[0,16777215]},"timelines":{"color":-1,"type":"Folder","contents":[],"name":"","show":true},"onion_skin":{"enabled":0,"alpha":0.5,"on_top":1,"range":[-1,1],"step":1,"color":[255,16711680]},"previewGrid":{"color":8482157,"size":[16,16],"snap":0,"opacity":0.5,"show":0},"preview":"","graphGrid":{"color":16777215,"highlight":12,"snap":1,"size":32,"show_origin":0,"opacity":0.050000000000000003,"show":1},"metadata":{"alias":"","tags":[],"contact":"","author":"MakhamDev","description":"","aut_id":0,"file_id":0,"version":11482}} \ No newline at end of file +{"metadata":{"version":11482,"alias":"","tags":[],"contact":"","author":"MakhamDev","description":"","aut_id":0,"file_id":0},"timelines":{"color":-1,"contents":[],"type":"Folder","name":"","show":true},"attributes":{"surface_dimension":[32,32],"palette_fix":false,"palette":[0,16777215],"strict":false},"nodes":[{"x":-384,"y":-96,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":858762,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Press to start a simulation.",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":717577,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":827642,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":887018,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":653697,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":747508,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-96,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":489704,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-384,-96],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":554918,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":526412,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":899910864,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":967451,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":141463,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-224,"y":160,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":222095,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"There are a lot of properties that control particle spawning, movement, etc.",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":188753,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":450379,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":259892,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":383898,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-224,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":152259,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,160,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":450041,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-224,160],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":266309,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":514711,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":406135373,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":458543,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":556469,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":32,"y":-32,"part_base_length":48,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":930439119,"from_index":0,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":858516,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Particle sprite","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":548249,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn delay","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":328028,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":365048,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[2,2],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":638459,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn amount","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":622308,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":328573,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":219194,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":925083,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":136905,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":293969,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[16,27,16,5,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":114796,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn area","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":213082,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn distribution","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Area","Border","Map"]}},{"on_end":0,"sep_axis":0,"animators":[[[0,20,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":218098,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,30,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":368751,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[20,30],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":717375,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Lifespan","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":0}},{"on_end":0,"sep_axis":0,"animators":[[[0,45,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":432829,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,135,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":932553,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,135,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":666912,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":746875,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":169270,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{"mapped":false},"global_use":0,"global_key":0,"raw_value":[[0,[0,45,135,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":906120,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn direction","color":-1,"name_custom":0,"visible":0,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":298405,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":935639,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[-0.02,-0.029999999999999999],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":781177,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Acceleration","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":410354,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":573668,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":110565,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":609308,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":675339,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0,0,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":164317,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Orientation","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":574147,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":785400,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":696164,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Rotational speed","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":959256,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":416057,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":872146,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":758597,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[1,1,1,1],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":292314,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn scale","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":506457,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":854972,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":517198,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":127674,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":879309,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":125844,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":785601,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":376248,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":512782,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":422310,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":361456,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":906244,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.109375,0.58750000000000002,1,0,0.109375,-0.58750000000000002],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":837144,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Scale over time","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"{\"keys\":[{\"time\":0.0,\"value\":4294924800.0},{\"time\":0.40000000000000002,\"value\":4278255462.0},{\"time\":1.0,\"value\":4278190335.0}],\"type\":0.0}",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":859795,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color over lifetime","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":301597,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":680030,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":544572,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":177185,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":589530,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":537581,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":523131,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":718111,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":827164,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":830186,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":742043,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":384003,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":762619,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":104480,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":986809,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.33333333333333331,0,1,1,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":689415,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha over time","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,362,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":807320,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Rotate by direction","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":916128,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn type","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Stream","Burst","Trigger"]}},{"on_end":0,"sep_axis":0,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":110727,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":656470,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":725930,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn size","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":798905,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":950977,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":576869,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn velocity","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":0}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":334870,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":197689,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":656875,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Gravity","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":190343,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":366754,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":549948,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Direction wiggle","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"label":["Amplitude","Period"],"linkable":false,"per_line":true}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":315346,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Loop","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":375025,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Surface array","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Random","Order","Animation","Scale"]}},{"on_end":0,"sep_axis":0,"animators":[[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":892190,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":166122,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[1,1],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":516372,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Animation speed","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":549292,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Scatter","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Uniform","Random"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":457539,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Boundary data","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,217,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":857149,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"On animation end","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Loop","Ping pong","Destroy"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":103955,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Spawn","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"{\"keys\":[{\"time\":0.0,\"value\":4294967295.0}],\"type\":0.0}",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":934719,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Random blend","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":310634,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Directed from center","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,493,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":114107,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Distribution map","color":-1,"name_custom":0,"visible":false,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0,0,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":464841,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Atlas","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":106033,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Seed","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,490,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":666524,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Gravity direction","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":547761,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":417817,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":997533,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Turning","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"linked":1}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":886433,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Turn both directions","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":721891,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Turn scale with speed","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":887845,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Collide ground","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":358898,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Ground offset","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":783531,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Bounce amount","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":730228,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Bounce friction","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":367663,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":679257,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":180391,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position wiggle","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"label":["Amplitude","Period"],"linkable":false,"per_line":true}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":346208,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":191114,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":646082,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Rotation wiggle","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"label":["Amplitude","Period"],"linkable":false,"per_line":true}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":269033,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":394474,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":947470,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Scale wiggle","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"label":["Amplitude","Period"],"linkable":false,"per_line":true}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Spawn","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"name":"Trigger"}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":945755,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Follow Path","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{"mapped":false},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":465680,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Path","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":873472,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":719755,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":826282,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":543104,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0.33333333333333331,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":292053,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":699825,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-0.33333333333333331,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":962481,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":900223,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":380355,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":130403,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":925079,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":678604,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[0,0,0,1,0.33333333333333331,0,-0.33333333333333331,0,1,1,0,0],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":789744,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Path Deviation","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":765502,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":311503,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,[32,32],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":587157,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Output dimension","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":761885,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Round position","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":244248,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Blend mode","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Normal","Alpha","Additive"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,-4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":456549,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Background","color":-1,"name_custom":false,"visible":true,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"atlas":true}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":149607,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Render Type","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Surface","Line"]}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,4,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":125208,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line life","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Particle","id":254863834,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[{"visible":1,"color":-1}],"iname":"Particle","group":-4,"show_parameter":0,"attri":{"oversample":0,"node_height":0,"part_amount":512,"update_graph":1,"color":-1,"show_update_trigger":0,"use_project_dimension":0,"node_param_width":192,"node_width":0,"color_depth":2,"interpolate":0},"type":"Node_Particle","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":110997,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":761344,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Clear cache","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-384,"y":-128,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":802773,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Particle is one of a node in Pixel Composer which allow you to simulate particle effect.",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":763305,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,2,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":401908,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":566417,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":891240,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":281793,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-128,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":426146,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-384,-128],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":144304,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":461544,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":660826364,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":960956,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":395548,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-384,"y":-192,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":544209,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Getting started 5: Particle and effectors",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":302567,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":842916,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":870703,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":991902,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":664603,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-192,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":189409,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-384,-192],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":418320,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":721513,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":676613630,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":522234,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":139157,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-160,"y":-32,"array_process":0,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":903520,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,32,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":625982,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[4,4],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":207569,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Dimension","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":874111,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Background","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":490080,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":[{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Rectangle","name":"Rectangle","spr_ind":0},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Ellipse","name":"Ellipse","spr_ind":1},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Regular polygon","name":"Regular polygon","spr_ind":2},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Star","name":"Star","spr_ind":3},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Arc","name":"Arc","spr_ind":4},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Teardrop","name":"Teardrop","spr_ind":5},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Cross","name":"Cross","spr_ind":6},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Leaf","name":"Leaf","spr_ind":7},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Crescent","name":"Crescent","spr_ind":8},{"spr_blend":9404030,"tooltip":"","spr":"@ref sprite(s_node_shape_type)","data":"Donut","name":"Donut","spr_ind":9}]}},{"on_end":0,"sep_axis":0,"animators":[[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":621302,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":752536,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":242173,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":593371,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":392829,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":265613,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[2,2,2,2,0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":555612,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"useShape":false}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,3,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":454329,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Sides","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.5,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":939150,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Inner radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":128342,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Anti-aliasing","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":808462,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Rotation","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":552816,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,180,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":243700,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,[0,0],[0,1],[0,0],0,0,1,{"amplitude":1,"seed":652140,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Angle range","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":589822,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Corner radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"range":[0,0.5,0.01]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":404195,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4278190080,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":130899,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Background color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":728630,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Height","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.10000000000000001,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":675810,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Start radius","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,-4,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":698991,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape path","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":727748,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Positioning Mode","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{"data":["Area","Center + Scale","Full Image"]}},{"on_end":0,"sep_axis":false,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":883302,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":218458,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":934227,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Center","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":823660,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,16,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":995747,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[16,16],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":462196,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Half Size","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,false,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":525523,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Tile","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":197834,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Shape Rotation","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,0,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":357038,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,1,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":669422,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[0,1],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":691771,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Level","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Shape","id":930439119,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[{"visible":1,"color":-1}],"iname":"Shape","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"color":-1,"node_height":0,"use_project_dimension":0,"array_process":0,"node_param_width":192,"node_width":0,"color_depth":1,"update_graph":1},"type":"Node_Shape","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":967508,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":295834,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]},{"x":-384,"y":-224,"buffer":{},"inputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,4294967295,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":885836,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Color","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,"Welcome to Pixel Composer",[0,1],[0,0],0,0,1,{"amplitude":1,"seed":194960,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Text","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":809895,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Style","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{"data":["Header","Sub header","Normal"]}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,0.75,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":913079,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Alpha","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":0,"raw_value":[[0,1000000,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":246815,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Line width","color":-1,"name_custom":0,"visible":0,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[[[0,-384,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":811586,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],[[0,-224,[0,1],[0,0],0,0,true,{"amplitude":1,"seed":717897,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]]],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,[-384,-224],[0,1],[0,0],0,0,true,{"amplitude":1,"seed":951255,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Position","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":false,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":false,"global_key":"","raw_value":[[0,true,[0,1],[0,0],2,2,true,{"amplitude":1,"seed":994991,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Smooth transform","color":-1,"name_custom":false,"visible":false,"is_modified":false,"loop_range":-1,"unit":0,"display_data":{}}],"name":"Display text","id":593948373,"renamed":true,"previewable":true,"tool":0,"render":1,"outputs":[],"iname":"Display_text","group":-4,"show_parameter":0,"attri":{"show_update_trigger":0,"node_height":0,"node_param_width":192,"node_width":0,"update_graph":1,"color":-1},"type":"Node_Display_Text","inspectInputs":[{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":792589,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[[0,0,[0,1],[0,0],0,0,1,{"amplitude":1,"seed":511894,"phase":0,"octave":2,"speed":1,"frequency":4,"axis_sync":false,"type":0}]],"name":"Toggle execution","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"on_end":0,"sep_axis":0,"animators":[],"shift_x":0,"shift_y":0,"from_node":-1,"from_index":-1,"anim":false,"attributes":{},"global_use":0,"global_key":"","raw_value":[],"name":"Update","color":-1,"name_custom":0,"visible":1,"is_modified":true,"loop_range":-1,"unit":0,"display_data":{}},{"visible":1,"color":-1}]}],"version":11690,"preview":"{\"width\":32.0,\"height\":32.0,\"buffer\":\"eJztj7EKwjAQhu8RHMTFyclZnH0EF1d3BxfxBVxEV8GtiItOji4u4i44+QK+gAiCIDidHOUkLZc01jZ1yAc\\\/ba5pvj8AHo\\\/H819ca4Dq+lmKrvNgHQBS8vao7Iehj91Z+\\\/svQEp8\\\/iiHM\\\/bnBfulDi4o2q92KMpvw+Rk32++A+Rk6Zc6rBaAFHof3AE5Nv7tGJBj4zb5Kaq\\\/Mjom3r1zaSKHZ61DDylJ\\\/8Y70JO9HHXPuQ1I0fm5A\\\/t1HaSzpe+6DvH9Jj9ltodPdOeaOpj26VDvL7nTnvst3Vs14inan5Z6sESOa7\\\/qlvyNzRQpv3psO0huVx2kuSu\\\/iSLdHjNv\\\/1Ad8Q==\"}","animator":{"framerate":30,"frame_range":-4,"frames_total":30},"onion_skin":{"on_top":1,"range":[-1,1],"enabled":0,"step":1,"alpha":0.5,"color":[255,16711680]},"previewGrid":{"opacity":0.5,"snap":0,"size":[16,16],"show":0,"color":8482157},"graphGrid":{"show_origin":0,"opacity":0.050000000000000003,"size":32,"show":1,"highlight":12,"snap":1,"color":16777215},"notes":[],"global_node":{"attri":{"color":-1,"update_graph":true,"show_update_trigger":false},"inputs":[]},"addon":{}} \ No newline at end of file diff --git a/datafiles/Steamworks_Extension_Documentation.html b/datafiles/Steamworks_Extension_Documentation.html deleted file mode 100644 index 5c3abc941..000000000 --- a/datafiles/Steamworks_Extension_Documentation.html +++ /dev/null @@ -1,13665 +0,0 @@ - - - - - - - Documentation - - - - - - - - - - - -
-
- - - -
-

Steamworks Extension

-

-

-

- This section is for those users that have been given access to the Steam API for publishing your game to that platform. To be able to use these functions you must have been accepted onto Steam previously, either through a publisher or through the self-publishing system.

-

Guides

-

This sections provides a variety of important guides to get you started using the extension:

- -

Management

-

This extension provides the following management functions:

- -

Modules

-

There are a great number of different functions related to the Steam API. We've split them up into the following sections to make it easier to navigate:

- -



-
-

Guides

-

- -

Back To Top

-

Setup Guide (IDE/Runtime 2022.6+)

-

To use the Steam API extension you should follow these steps:

-
    -
  1. Import this Steamworks extension into your project, if you haven't done that already.
  2. -
  3. The Steam app needs to be installed, running and with an account logged in (official site).
  4. -
  5. Download Steamworks SDK (1.55) from Steam's partner site and extract the contents of the zip into a directory of your choice (e.g.: C:\steamworks\sdk).
    -
  6. -
  7. To set up your AppID and environment status, double click on the Steamworks extension in your Asset Browser in the IDE.
    -
  8. -
  9. In the bottom section you will see the new extension options. Those are all you will need to configure to use this extension. The build options require the path to the SDK downloaded on step 3 and the application options required your Application ID.
    -
  10. -
-



-
- -

Back To Top

-

Migration Changes

-

During the migration of the Steamworks function library from the base GameMaker runner into this extension, there were some new functions that were added, and others that were slightly changed. This document covers the changes that happened during that migration.

-

Changed Functions

-

These are the functions that changed:

- -
-

This function is now asynchronous, meaning it will return an Async request ID that should be used inside a Steam Async Event to check when the task is finished.

-
-

New Functions

-

These are the new functions that were added to the Steam extension:

- -



-
-

Management

-

- -

Back To Top

-

steam_init

-

This function initialises the steam APIs.

-
-

ℹ️ NOTE

-

This function is already configured to be called at Game Start by the extension, and should not be called from your game code.

-
-


-

Syntax:

-
steam_init();


-

Returns:

-
N/A



-
- -

Back To Top

-

steam_update

-

This function updates the steam APIs.

-
-

⚠️ IMPORTANT

-

This function is required to be called in order for the Steamworks extension to work. We recommend you place this function in a persistent controller object that calls it inside its Step Event.

-
-


-

Syntax:

-
steam_update();


-

Returns:

-
N/A


-

Example:

-
steam_update();

The above code will update the steam APIs.

-



-
- -

Back To Top

-

steam_shutdown

-

This function shuts down the Steamworks API, releases pointers and frees memory.

-
-

⚠️ IMPORTANT

-

This function is required to be called in order for the Steamworks extension to work. We recommend you place this function in the GameEnd Event of a controller object. You need to check if this is not a game_restart().

-
-


-

Syntax:

-
steam_shutdown();


-

Returns:

-
N/A


-

Example:

-
global.is_game_restarting = true;
-game_restart();

The code above should be used when you want to restart your game. We set the is_game_restarting global variable to true announcing the game being restarted to true (this global variable should already be declared at the begining of your game and be set to false by default). - Now inside our Game End Event we can use the following code.

-
if (global.is_game_restarting == false) {
-    steam_shutdown();
-}
-global.is_game_restarting = false;

First we check if the game is not restarting and in that case we know we are actually ending so we call the steam_shutdown method.

-



-
-

General

-

- -

- -

Back To Top

-

General

-

The following set of functions are all for checking the availability of certain aspects of the Steam client or server API. This means that these functions should be used before any other Steam API function call to ensure that the client/server setup is correct and communicating with your game:

- -



-
- - -

Back To Top

-

steam_initialised

-

When using the Steam API, this function can be called to check that the Steam client API has been initialised correctly before any doing any further calls to Steam specific functions in your game.

-


-

Syntax:

-
steam_initialised();


-

Returns:

-
Bool


-

Example:

-
global.steam_api = false;
-if (steam_initialised())
-{
-    if (steam_stats_ready() && steam_is_overlay_enabled())
-    {
-        global.steam_api = true;
-    }
-}

The above code will set a global variable to true if the Steam client API is correctly initialised, along with the Steam statistics and overlay functionality, or it will set the variable to false otherwise.

- - -



-
- - -

Back To Top

-

steam_stats_ready

-

When using the Steam API, this function can be called to check that the Steam client API has correctly initialised the statistics for your game.

-


-

Syntax:

-
steam_stats_ready();


-

Returns:

-
Bool


-

Example:

-
global.steam_api = false;
-if steam_initialised()
-{
-    if steam_stats_ready() && steam_is_overlay_enabled()
-    {
-        global.steam_api = true;
-    }
-}

The above code will set a global variable to true if the Steam client API is correctly initialised, along with the Steam statistics and overlay functionality, or it will set the variable to false otherwise.

- - -



-
- - -

Back To Top

-

steam_get_app_id

-

This function is used retrieve the unique app ID that Steam assigns for your game, which is required for using some of the User Generated Content functions.

-


-

Syntax:

-
steam_get_app_id();


-

Returns:

-
Real


-

Example:

-
global.app_id = steam_get_app_id();

The above code gets the unique app ID for your game on Steam and stores it in a global variable.

- - -



-
- - -

Back To Top

-

steam_get_user_account_id

-

This function is used retrieve the unique User ID that Steam assigns to each user, which is required for using some of the User Generated Content functions.

-


-

Syntax:

-
steam_get_user_account_id();


-

Returns:

-
Real


-

Example:

-
global.user_id = steam_get_user_account_id();

The above code gets the unique user ID for the person who owns the game and stores it in a global variable.

- - -



-
- - -

Back To Top

-

steam_get_user_steam_id

-

You can use this function to return the unique Steam user id of the user currently logged into the Steam client. If you need to get the user's on screen user name you should refer to the function steam_get_persona_name.

-


-

Syntax:

-
steam_get_user_steam_id();


-

Returns:

-
int64


-

Example:

-
if steam_initialised()
-{
-    global.u_id = steam_get_user_steam_id();
-}

The above code will set a global variable to the current users unique Steam ID if the Steam client API is correctly initialised.

- - -



-
- - -

Back To Top

-

steam_get_persona_name

-

You can use this function to return the user name of the user currently logged into the Steam client. This is the visible screen name and not the unique user id (this can be found using the function steam_get_user_steam_id).

-


-

Syntax:

-
steam_get_persona_name();


-

Returns:

-
String


-

Example:

-
if steam_initialised()
-{
-    global.p_name = steam_get_persona_name();
-}

The above code will set a global variable to current users screen name if the Steam client API is correctly initialised.

- - -



-
- - -

Back To Top

-

steam_get_user_persona_name

-

This function can be used to retrieve the user name (screen name) for any specific user ID. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_get_user_persona_name(steamID);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
steamIDint64The unique Steam ID for a user.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "user_persona_name"
steamidint64The unique user id of the user currently logged into the Steam client
persona_namestringThe visible screen name of the user currently logged into the Steam client
-


-

Example:

-
request = steam_get_user_persona_name(global.UGC_UserID);

The above code will request the user name of the user ID stored in the global variable "UGC_UserID", storing the returned value in a variable for parsing in the Async Event.

- - -



-
- - -

Back To Top

-

steam_is_user_logged_on

-

This function will return true if the Steam client currently has a live connection to the Steam servers. If it returns false, it means there is no active connection due to either a networking issue on the local machine, or the Steam server being down or busy.

-


-

Syntax:

-
steam_is_user_logged_on();


-

Returns:

-
Bool


-

Example:

-
if (steam_is_user_logged_on())
-{
-    global.user_id = steam_get_user_account_id();
-}

The above code will check to see if the user is logged onto the Steam server and if it stores the user ID in a global variable.

- - -



-
- - -

Back To Top

-

steam_current_game_language

-

This function is used retrieve the current language that Steam is using (as a string), for example "english".

-


-

Syntax:

-
steam_current_game_language();


-

Returns:

-
String


-

Example:

-
language = steam_current_game_language();

The above code gets the language used for the current game.

- - -



-
- - -

Back To Top

-

steam_available_languages

-

This function can be used to retrieve a list of all available languages for Steam. The returned value is simply a comma-separated list of languages.

-


-

Syntax:

-
steam_available_languages();


-

Returns:

-
String


-

Example:

-
language = steam_available_languages();

The above gets the available languages for Steam as a string and stores it in a variable.

- - -



-
- -

Back To Top

-

steam_is_subscribed

-

This function checks if the active user is subscribed to the current App ID.

-
-

ℹ️ NOTE

-

This will always return true if you're using Steam DRM.

-
-


-

Syntax:

-
steam_is_subscribed();


-

Returns:

-
Bool


-

Example:

-
if (steam_is_subscribed())
-{
-    show_debug_message("is_subscribed")
-}

The above code will check to see if the user is logged onto the Steam server and if it stores the user ID in a global variable.

-



-
- -

Back To Top

-

steam_set_warning_message_hook

-

This function sets a warning message hook to receive SteamAPI warnings and info messages in the console.

-


-

Syntax:

-
steam_set_warning_message_hook();


-

Returns:

-
N/A


-

Example:

-
steam_set_warning_message_hook();

The above code start Steamworks logging messages in console.

-



-
-

Overlay

-

- -

- -

Back To Top

-

Overlay

-

The Steam Overlay is the visual display that can be brought up to display the Steam interface to the user. This is normally done by the user themselves using a combination of keys, but you also have the possibility of doing it from within your game, so that you can map a button or an event to show the overlay.

-

Functions

-

The extension provides you with the following functions:

- -

Constants

-

This section also provides the following constants to use with the functions:

- -



-
- - -

Back To Top

-

steam_is_overlay_enabled

-

When using the Steam API, this function can be called to check that the Steam client API has the overlay functionality enabled.

-


-

Syntax:

-
steam_is_overlay_enabled();


-

Returns:

-
Bool


-

Example:

-
global.steam_api = false;
-if steam_initialised()
-{
-    if steam_stats_ready() && steam_is_overlay_enabled()
-    {
-        global.steamapi = true;
-    }
-}

The above code will set a global variable to true if the Steam client API is correctly initialized, along with the Steam statistics and overlay functionality, or it will set the variable to false otherwise.

- - -



-
- - -

Back To Top

-

steam_is_overlay_activated

-

This function can be used to find out if the user has the Steam Overlay active or not. If the overlay is active and visible to the user the function will return true, and if it is not, then it will return false. An example of what this function can be used for would be for polling the Steam API for the overlay so that you can pause your game while the overlay is being shown.

-


-

Syntax:

-
steam_is_overlay_activated();


-

Returns:

-
Bool


-

Example:

-
if steam_is_overlay_activated()
-{
-    global.Pause = true;
-}

The above code will check to see if the Steam overlay is active and if it is it will set the global variable "Pause" to true.

- - -



-
- - -

Back To Top

-

steam_activate_overlay

-

The Steam overlay is a piece of the Steam user interface that can be activated over the top of almost any game launched through Steam. It lets the user access their friends list, web browser, chat, and in-game DLC purchasing. The default key for a user to access the overlay while in a game is SHIFT + TAB, but you can also bring up any page of the overlay using this function. It takes one of six constants that are listed below:

-


-

Syntax:

-
steam_activate_overlay(overlay_type);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
overlay_typeconstant.OverlayTypeThe page index of the Steam API UI to show (see OverlayType constants).
-


-

Returns:

-
N/A


-

Example:

-
var key = keyboard_lastkey;
-switch (key)
-{
-    case vk_f1: steam_activate_overlay(ov_friends); break;
-    case vk_f2: steam_activate_overlay(ov_community); break;
-    case vk_f3: steam_activate_overlay(ov_players); break;
-    case vk_f4: steam_activate_overlay(ov_settings); break;
-    case vk_f5: steam_activate_overlay(ov_gamegroup); break;
-    case vk_f6: steam_activate_overlay(ov_achievements); break;
-}

The above code polls the last keyboard key pressed and if it is any of the function keys from 1 to 6 it will open the corresponding page of the Steam overlay.

- - -



-
- - -

Back To Top

-

steam_activate_overlay_browser

-

With this function you can open the Steam game overlay to its web browser and then have it load the specified URL. you need to use the full URL as a string for this to resolve correctly, for example: &quot;http://www.steamgames.com/&quot;.

-


-

Syntax:

-
steam_activate_overlay(url);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
urlstringThe (full) URL for the overlay to open.
-


-

Returns:

-
N/A


-

Example:

-
if keyboard_check_pressed(vk_f1)
-{
-    steam_activate_overlay_browser("http://www.steamgames.com/");
-}

The above code polls the keyboard for the F1 key and if it is then Steam overlay will be opened and resolve to the given URL.

- - -



-
- - -

Back To Top

-

steam_activate_overlay_store

-

With this function you can open the Steam overlay on the store page for a game so that users can buy or download DLC (for example). You need to supply the unique App ID for the game or DLC which you would get from the Steam dashboard when you set it up.

-


-

Syntax:

-
steam_activate_overlay_store(app_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
app_idintegerThe unique App ID for your game.
-


-

Returns:

-
N/A


-

Example:

-
if keyboard_check_pressed(vk_f1)
-{
-    steam_activate_overlay_store(global.DLC_id);
-}

The above code polls the keyboard for the F1 key and if it is then Steam overlay will be opened on the page for the game content using the app ID stored in the global variable.

- - -



-
- - -

Back To Top

-

steam_activate_overlay_user

-

This function will open the Steam overlay to one of the chosen dialogues relating to the user ID given. - Note that Steam IDs can be large numbers and so you may need to cast your ID value as an int64() before supplying it to the function.

-


-

Syntax:

-
steam_activate_overlay_user(dialog_name, steamid);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
dialog_namestringThe dialogue to open the overlay on (see below).
steamidint64The Steam user ID or group ID to use.
- - - - - - - - - - - - - - - - - -
Dialog NamesDescription
"steamid"Opens the Steam Community web browser to the page of the user or group
"chat"Opens a chat window to the specified user
-


-

Returns:

-
N/A


-

Example:

-
var key = keyboard_lastkey;
-switch (key)
-{
-    case vk_f1: steam_activate_overlay_user("steamid", global.GameGroupID); break;
-    case vk_f2: steam_activate_overlay_user("chat", global.FriendID); break;
-}

The above code polls the last keyboard key pressed and if it is function key 1 or function key 2, it will open the Steam overlay to either see the Steam group stored in the global variable "GamegroupID", or it will open the chat window to chat with the user stored in the global "FriendID" variable.

- - -



-
- - -

Back To Top

-

steam_set_overlay_notification_inset

-

Sets the inset of the overlay notification from the corner specified by steam_set_overlay_notification_position

-


-

Syntax:

-
steam_set_overlay_notification_inset(hor_inset, vert_inset);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
hor_insetrealThe horizontal (left-right) distance in pixels from the corner.
vert_insetrealThe vertical (up-down) distance in pixels from the corner.
-


-

Returns:

-
Bool


-

Example:

-
steam_set_overlay_notification_inset(10, 10);

The code above will inset the over lay 10px on the horizontal axis and 10px in the vertical axis.

- - -



-
- - -

Back To Top

-

steam_set_overlay_notification_position

-

Changes the corner in which the overlay notifications will appear.

-


-

Syntax:

-
steam_set_overlay_notification_position(position);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
positionOverlayNotificationPositionA constant that indicates the position where the notification overlay should render
-


-

Returns:

-
N/A


-

Example:

-
steam_set_overlay_notification_position(steam_overlay_notification_position_bottom_right);

The above code will change the notification position to the bottom right corner.

- - -



-
- -

Back To Top

-

OverlayType

-

These constants specify the type of overlay to be activated when using the function steam_activate_overlay.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Overlay Type ConstantDescription
ov_friendsThe friends page for the current user
ov_communityThe community page for your game
ov_playersThe page showing others that are playing the same game or that you have recently played with
ov_settingsThe Steam client overlay settings
ov_gamegroupOpens the Steam Community web browser to the official game group for this game
ov_achievementsThe achievements page for your game
-



-
- -

Back To Top

-

OverlayNotificationPosition

-

These constants specify the position of the notification overlay onscreen an should be used with the function steam_set_overlay_notification_position.

- - - - - - - - - - - - - - - - - - - - - - - - - -
Overlay Notification Position ConstantDescription
steam_overlay_notification_position_top_leftPoint to the top left position
steam_overlay_notification_position_top_rightPoint to the top right position
steam_overlay_notification_position_bottom_leftPoint to the bottom left position
steam_overlay_notification_position_bottom_rightPoint to the bottom right position
-



-
-

Leaderboards

-

- -

- -

Back To Top

-

Leaderboards

-

The Steam API supports persistent leaderboards with automatically ordered entries. These leaderboards can be used to display global and friend leaderboards in your game and on the community web page for your game. Each game can have up to 10,000 leaderboards, and each leaderboard can be retrieved immediately after a player's score has been inserted into it, but note that for each leaderboard, a player can have only one entry, although there is no limit on the number of players per leaderboard.

-

Functions

-

Each leaderboard entry contains a name, a score and a rank for the leaderboard, and this data will be replaced when a new leaderboard entry is created for the user, and the following functions can be used to add and retrieve this data form the leaderboards for your game:

- -

Data Types

-

The following data types are used by the leaderboard functions:

- -

Constants

-

The following constants are used by the leaderboard functions:

- -



-
- - -

Back To Top

-

steam_create_leaderboard

-

With this function you can create a new leaderboard for your game. The first argument is a string which defines the name of your leaderboard, and this name should be used in any further function calls relating to the leaderboard being created. You can then define the sort order (see LeaderboardSortOrder constants) as well as the way in which the information is displayed (see LeaderboardDisplayType constants). - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If you have previously created a leaderboard with the same name (either through code or through your Steam page for the game), then this function will not create a new one.

-
-


-

Syntax:

-
steam_create_leaderboard(lb_name, sort_order, display_type);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are creating
sort_orderLeaderboardSortOrder constantThe method for sorting the leaderboard entries (see LeaderboardSortOrder constants)
display_typeLeaderboardDisplayType constantThe way to display the leaderboard to the user (see LeaderboardDisplayType constants)
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "create_leaderboard"
statusrealThe status code, 0 if the leaderboard was create and 1 if it already existed
lb_namestringThe name of the leaderboard
-


-

Example:

-
steam_create_leaderboard("Game Times", lb_sort_ascending, lb_disp_time_sec);

The above code will create a leaderboard called "Game Times", and set it to display the results in ascending order and with a display in seconds.

- - -



-
- - -

Back To Top

-

steam_upload_score

-

This function will send a score to the given leaderboard. The score to be uploaded is a real number, and the leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

-
-


-

Syntax:

-
steam_upload_score(lb_name, score);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are uploading the scores to
scorerealThe score to upload
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
post_idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_upload"
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
successboolWhether or not the request was successful
updatedboolWhether or not the leaderboard was updated (ie: the new score was better)
scorerealThe score that was posted to the leaderboard
-


-

Extended Example:

-

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading:

-
if (hp <= 0)
-{
-    upload_ID = steam_upload_score("Game Scores", score);
-    if (!upload_ID)
-    {
-        alarm[0] = room_speed;
-    }
-}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc... We now add the following into the Steam Async Event for the instance controlling the scores:

-
var type = ds_map_find_value(async_load, "event_type");
-if (type == "leaderboard_upload")
-{
-    var lb_ID = ds_map_find_value(async_load, "post_id");
-    if lb_ID == upload_ID
-    {
-        var lb_name = ds_map_find_value(async_load, "lb_name");
-        var lb_done = ds_map_find_value(async_load, "success");
-        var lb_score = ds_map_find_value(async_load, "score");
-        var lb_updated = ds_map_find_value(async_load, "updated");
-        show_debug_message("leaderboard post id:" + string(lb_ID) + " to lb:" + string(lb_name) + " with score:" + string(lb_score) + " updated=" + string(lb_updated));
-        if (lb_done)
-        {
-            show_debug_message("- Succeeded");
-        }
-        else
-        {
-            show_debug_message("- Failed");
-        }
-    }
-}

in the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.

- - -



-
- - -

Back To Top

-

steam_upload_score_ext

-

This function will send a score to the given leaderboard. It is similar to the function steam_upload_scorebut has an extra argument that will allow you to force the update of the score, as by default Steam only updates the score if it is better than the previous one. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

-
-


-

Syntax:

-
steam_upload_score_ext(lb_name, score, force_update);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are uploading the scores to
scorerealThe score to upload
force_updateboolWhether or not the value should be replaced
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
post_idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_upload"
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
successboolWhether or not the request was successful
updatedboolWhether or not the leaderboard was updated (ie: the new score was better or forceUpdate was set to true)
scorerealThe score that was posted to the leaderboard
-


-

Extended Example:

-

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading:

-
if (hp <= 0)
-{
-    upload_ID = steam_upload_score_ext("Game Scores", score, true);
-    if (!upload_ID)
-    {
-        alarm[0] = room_speed;
-    }
-}

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc... We now add the following into the Steam Async Event for the instance controlling the scores:

-
var type = ds_map_find_value(async_load, "event_type");
-if (type == "leaderboard_upload")
-{
-    var lb_ID = ds_map_find_value(async_load, "post_id");
-    if lb_ID == upload_ID
-    {
-        var lb_name = ds_map_find_value(async_load, "lb_name");
-        var lb_done = ds_map_find_value(async_load, "success");
-        var lb_score = ds_map_find_value(async_load, "score");
-        var lb_updated = ds_map_find_value(async_load, "updated");
-        show_debug_message("leaderboard post id:" + string(lb_ID) + " to lb:" + string(lb_name) + " with score:" + string(lb_score) + " updated=" + string(lb_updated));
-        if (lb_done)
-        {
-            show_debug_message("- Succeeded");
-        }
-        else
-        {
-            show_debug_message("- Failed");
-        }
-    }
-}

in the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.

- - -



-
- - -

Back To Top

-

steam_upload_score_buffer

-

This function will send a score to the given leaderboard along with a data package created from a buffer. The buffer should be no more than 256 bytes in size - anything beyond that will be chopped off - and can contain any data you require. The score to be uploaded should be a real number, and the leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

-
-


-

Syntax:

-
steam_upload_score_buffer(lb_name, score, buffer);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are uploading the scores to
scorerealThe score to upload
bufferbuffer IDThe ID of the buffer to attach
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
post_idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_upload"
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
successboolWhether or not the request was successful
updatedboolWhether or not the leaderboard was updated (ie: the new score was better). Note that if you score was not updated neither will be the data buffer.
scorerealThe score that was posted to the leaderboard
-


-

Extended Example:

-

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading, with a buffer being created to hold a string telling us which level the score was uploaded from:

-
if (hp <= 0)
-{
-    var buff = buffer_create(256, buffer_fixed, 1 );
-    buffer_write(buff, buffer_string, "Uploaded on level " + string(global.Level));
-    upload_ID = steam_upload_score("Game Scores", score, buff);
-
-    if (!upload_ID)
-    {
-        alarm[0] = room_speed;
-    }
-
-    buffer_delete(buff);
-}
-

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc... Also note that we immediately delete the buffer, since it is no longer required for the function. We now add the following into the Steam Async Event for the instance controlling the scores:

-
var type = ds_map_find_value(async_load, "event_type");
-if (type == "leaderboard_upload")
-{
-    var lb_ID = ds_map_find_value(async_load, "post_id");
-    if lb_ID == upload_ID
-    {
-        var lb_name = ds_map_find_value(async_load, "lb_name");
-        var lb_done = ds_map_find_value(async_load, "success");
-        var lb_score = ds_map_find_value(async_load, "score");
-        var lb_updated = ds_map_find_value(async_load, "updated");
-        show_debug_message("leaderboard post id:" + string(lb_ID) + " to lb:" + string(lb_name) + " with score:" + string(lb_score) + " updated=" + string(lb_updated));
-        if (lb_done)
-        {
-            show_debug_message("- Succeeded");
-        }
-        else
-        {
-            show_debug_message("- Failed");
-        }
-    }
-}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.

- - -



-
- - -

Back To Top

-

steam_upload_score_buffer_ext

-

This function will send a score to the given leaderboard along with a data package created from a buffer. The buffer should be no more than 256 bytes in size - anything beyond that will be chopped off - and can contain any data you require. This function is similar to steam_upload_score_buffer but has an extra argument that will allow you to force the update of the score, as by default Steam only updates the score if it is better than the previous one. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the Async event will not be triggered.

-
-


-

Syntax:

-
steam_upload_score_buffer_ext(lb_name, score, buffer, force_update);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are uploading the scores to
scorerealThe score to upload
bufferbuffer IDThe ID of the buffer to attach
force_updateboolWhether or not the value should be replaced
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
post_idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_upload"
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
successboolWhether or not the request was successful
updatedboolWhether or not the leaderboard was updated (ie: the new score was better or forceUpdate was set to true). Note that if you score was not updated neither will be the data buffer.
scorerealThe score that was posted to the leaderboard
-


-

Extended Example:

-

In this example, we first upload a score and then parse the async_load map returned if successful. The code below shows a typical example for uploading, with a buffer being created to hold a string telling us which level the score was uploaded from:

-
if (hp <= 0)
-{
-    var buff = buffer_create(256, buffer_fixed, 1 );
-    buffer_write(buff, buffer_string, "Uploaded on level " + string(global.Level));
-    upload_ID = steam_upload_score_buffer_ext("Game Scores", score, buff, true);
-
-    if (!upload_ID)
-    {
-        alarm[0] = room_speed;
-    }
-
-    buffer_delete(buff);
-}
-

Note that we have set an alarm if the call fails. This would be used to try the upload again at a later time and you can add extra code there to retry the upload or to save the score to a text file should it continue to fail, etc... Also note that we immediately delete the buffer, since it is no longer required for the function. We now add the following into the Steam Async Event for the instance controlling the scores:

-
var type = ds_map_find_value(async_load, "event_type");
-if (type == "leaderboard_upload")
-{
-    var lb_ID = ds_map_find_value(async_load, "post_id");
-    if lb_ID == upload_ID
-    {
-        var lb_name = ds_map_find_value(async_load, "lb_name");
-        var lb_done = ds_map_find_value(async_load, "success");
-        var lb_score = ds_map_find_value(async_load, "score");
-        var lb_updated = ds_map_find_value(async_load, "updated");
-        show_debug_message("leaderboard post id:" + string(lb_ID) + " to lb:" + string(lb_name) + " with score:" + string(lb_score) + " updated=" + string(lb_updated));
-        if (lb_done)
-        {
-            show_debug_message("- Succeeded");
-        }
-        else
-        {
-            show_debug_message("- Failed");
-        }
-    }
-}

In the example we are simply outputting the return values to the compiler window as debug messages, but you can use this event to deal with the information in any way you choose.

- - -



-
- - -

Back To Top

-

steam_download_scores

-

This function is used retrieve a sequential range of leaderboard entries by leaderboard ranking. The start_idx and end_idx parameters control the requested range of ranks, for example, you can display the top 10 on a leaderboard for your game by setting the start value to 1 and the end value to 10. The leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the async event will not be triggered.

-
-


-

Syntax:

-
steam_download_scores(lb_name, start_idx, end_idx);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are downloading the scores from
start_idxintegerThe start position within the leaderboard
end_idxintegerThe end position within the leaderboard
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_download"
statusint64The status code if download fails
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
entriesstringA json formatted string with all the downloaded entries (see LeaderboardEntry for details)
-


-

Extended Example:

-

In this extended example we will request the top ten ranking for the given leaderboard and parse its results in the Steam Async Event. to start with we need to request the scores with the following code:

-
score_get = steam_download_scores("Game Scores", 1, 10);

This will send off a request to the Steam Server for the scores from the leaderboard "Game Scores", storing the async id of the request in the variable "score_get". this will then be handled in the Steam Async Event in the following way:

-
var async_id = ds_map_find_value(async_load, "id");
-if async_id == score_get
-{
-    var entries = ds_map_find_value(async_load, "entries");
-    var map = json_decode(entries);
-    if ds_map_exists(map, "default")
-    {
-        ds_map_destroy(map);
-        exit;
-    }
-    else
-    {
-        var list = ds_map_find_value(map, "entries");
-        var len = ds_list_size(list);
-        var entry;
-        for(var i = 0; i < len; i++;)
-        {
-            entry = ds_list_find_value(list, i );
-            steam_name[i] = ds_map_find_value(entry, "name");
-            steam_score[i] = ds_map_find_value(entry, "score");
-            steam_rank[i] = ds_map_find_value(entry, "rank");
-            steam_data[i] = ds_map_find_value(entry, "data");
-        }
-    }
-    ds_map_destroy(map)
-}

What we do here is first check the "id" key of the special async_load DS map. If this value is the same as the value of the original call-back function (stored in the "score_get" variable) we then continue to process the data. The first thing we do is parse the async_load DS map for the key "entries" which will contain a JSON formatted string containing the leaderboard data. This JSON object is then decoded (see json_decode) as another DS map, and this new map id is stored in the variable "map". - This map is checked for the key "default" and if that is found then the map is destroyed and the event is exited. If no "default" key is found, the code will then parse the map to extract the necessary information about the leaderboard, by first extracting a DS list from the "entries" key of the DS map, and then looping through each entry of the list to get another DS map with the name, score and rank of each entry. These values are then stored to arrays. - Once the loop has finished, the JSON DS map is destroyed (which in turn destroys all the internal maps and lists). There is no need to destroy the async_load DS map as this is handled for you by GameMaker Studio 2.

- - -



-
- - -

Back To Top

-

steam_download_scores_around_user

-

This function is used to retrieve leaderboard entries relative the current users entry. The range_start parameter is the number of entries to retrieve before the current users entry, and the range_end parameter is the number of entries after the current user's entry, and the current user's entry is always included in the results. For example, if the current user is number 5 on a given leaderboard, then setting the start range to -2 and the end range to 2 will return 5 entries: 3 through 7. If there are not enough entries in the leaderboard before or after the user's entry, Steam will adjust the range start and end points trying to maintained the range size. For example, if the user is #1 on the leaderboard, start is set to -2, and end is set to 2, Steam will return the first 5 entries in the leaderboard. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the async event will not be triggered.

-
-


-

Syntax:

-
steam_download_scores_around_user(lb_name, range_start, range_end);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are downloading the scores from
range_startintegerThe start position within the leaderboard
range_endintegerThe end position within the leaderboard
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_download"
statusint64The status code if download fails
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
entriesstringA json formatted string with all the downloaded entries (see LeaderboardEntry for details)
-


-

Example:

-
request_id = steam_download_scores_around_user("Game Scores", -4, 5);

This will send off a request to the Steam Server for a range of 10 scores from the leaderboard &quot;Game Scores&quot;, centered on the player and will store the async id of the request in the variable request_id. This will then be handled in the Steam Async Event, as shown in the Extended Example for steam_download_scores.

- - -



-
- - -

Back To Top

-

steam_download_friends_scores

-

With this function you can retrieve only the scores on the leaderboard that belong to those people that are marked as "friends" in the Steam client. So, if your leaderboard has 200 entries, and 50 of them are your friends, this function will retrieve only those 50 results. The leaderboard name is a string that was defined when you created the leaderboard using the function steam_create_leaderboard. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

If the function call fails for any reason it will return -1 and the async event will not be triggered.

-
-


-

Syntax:

-
steam_download_friends_scores(lb_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
lb_namestringThe name of the leaderboard that you are downloading the scores from
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "leaderboard_download"
statusint64The status code if download fails
lb_namestringThe name of the leaderboard
num_entriesrealThe number of returned entries
entriesstringA json formatted string with all the downloaded entries (see LeaderboardEntry for details)
-


-

Example:

-
request_id = steam_download_friends_scores("Game Scores");

This will send off a request to the Steam Server for the users friends scores from the given leaderboard and will store the async id of the request in the variable request_id. This will then be handled in the Steam Async Event, as shown in the Extended Example for steam_download_scores.

- - -



-
- -

Back To Top

-

LeaderboardEntry

-

A leaderboard entry is represented by a json formatted string that can be returned by the async callback event of the following functions:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
rankrealThe rank of the entry on the specified leaderboard
datastringThe base64 encoded string with the data provided when uploading scores using the steam_upload_score_buffer or
steam_upload_score_buffer_ext functions ✴️ OPTIONAL
scorerealThe score attributed to this entry
namestringThe display name of the player for this entry
userIDint64The unique user id of the player for this entry
-
-

ℹ️ NOTE

-

If steam_upload_score_buffer or steam_upload_score_buffer_ext were used to upload the score, the decoded entry will now have a &quot;data&quot; key so you can retrieve the data of the uploaded buffer (see the Steam Async Event extended code example for further details). This data will be base64 encoded and so you will need to use the function buffer_base64_decode on the data before reading from the buffer.

-
-



-
- -

Back To Top

-

LeaderboardDisplayType

-

These constants specify the display type of a leaderboard and should be used with the function steam_create_leaderboard.

- - - - - - - - - - - - - - - - - - - - - - - - - -
Leaderboard Display Type ConstantDescription
lb_disp_noneShow the leaderboard "as is".
lb_disp_numericShow the leaderboard as a numeric display.
lb_disp_time_secShow the leaderboard values as times, with the base value being seconds.
lb_disp_time_msShow the leaderboard values as times, with the base value being milliseconds
-



-
- -

Back To Top

-

LeaderboardSortOrder

-

These constants specify the sort order of a leaderboard and should be used with the function steam_create_leaderboard.

- - - - - - - - - - - - - - - - - - - - - -
Leaderboard Sort Order ConstantDescription
lb_sort_noneNo sorting. The information will be displayed "as is".
lb_sort_ascendingSort the leaderboard in ascending order.
lb_sort_descendingSort the leaderboard in descending order.
-



-
-

Lobbies

-

- - -

Back To Top

-

Lobbies & Matchmaking

-

The following functions and constants allow you to use Steam's Lobbies and Matchmaking functionality.

-

Current Lobby

-

These functions are provided for handling the current lobby:

- -

Matchmaking

-

The following functions allow retrieving and handling lists of public lobbies.

- -

Constants

-

These are the constants used by this API:

- -



-
- -

Back To Top

-

steam_lobby_activate_invite_overlay

-

Displays an invitation overlay if currently in a lobby. - The invitation overlay is much akin to the friends-list overlay, but only shows online friends, and shows an "invite" buttons on each row.

-


-

Syntax:

-
steam_lobby_activate_invite_overlay();


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event (when an invitation is accepted)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_join_requested"
lobby_idint64The lobby unique identifier
successboolWhether or not the task was successful
resultrealThe code of the result
-


-

Example:

-
steam_lobby_activate_invite_overlay();

The above code will show the Steam invite overlay.

-



-
- -

Back To Top

-

steam_lobby_create

-

Starts creating a lobby. Returns whether or not the task was successfully created. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_lobby_create(type, max_members);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
typeLobbyTypeConstant that indicate the status of the lobby
max_membersrealIndicates the maximum allowed number of users in the lobby (including the lobby's creator)
-


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_created"
lobby_idint64The name of the leaderboard
successrealWhether or not the request was successful
resultboolThe status code (descriptions can be found in Steam API documentation)
-


-

Example:

-
steam_lobby_create(steam_lobby_type_public, 4);

The above code will create a lobby with a maximum of 4 users. We now add the following into the Steam Async Event for checking the success of task:

-
var type = async_load[? "type"];
-if (type == "lobby_created")
-{
-    if (async_load[? "success"])
-        show_debug_message("Lobby created");
-    else
-        show_debug_message("Failed to create lobby");
-}

in the example we are simply outputting the success of the lobby creation task.

-



-
- -

Back To Top

-

steam_lobby_get_chat_message_data

-

Returns the data of a message sent using steam_lobby_send_chat_message_buffer. Returns whether or not the buffer was successfully filled with the message data.

-


-

Syntax:

-
steam_lobby_get_chat_message_data(message_index, buffer);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
message_indexrealThe message unique identifier
bufferbuffer IDThe buffer to write the data to
-


-

Returns:

-
bool


-

Example:

-
chat_message_buf = buffer_create(steam_lobby_max_chat_message_size, buffer_fixed, 1);
-steam_lobby_get_chat_message_data(_msg_index, chat_message_buf)

The code above will get the current message data and place it into a buffer (resizing if required and allowed, ie.: buffer_grow ).

-



-
- -

Back To Top

-

steam_lobby_get_chat_message_size

-

Return the size of a message

-


-

Syntax:

-
steam_lobby_get_chat_message_size(message_index)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
message_indexrealThe argument to be passed in
-


-

Returns:

-
real


-

Example:

-
// ... INSIDE A STEAM ASYNC EVENT ...
-switch (async[? "event_type"])
-{
-    case "lobby_chat_message":
-        size = steam_lobby_get_chat_message_size(async_load[?"message_index"]);
-        break;
-}

The code above will get the current message size in bytes.

-



-
- -

Back To Top

-

steam_lobby_get_chat_message_text

-

Return the text of a message.

-


-

Syntax:

-
steam_lobby_get_chat_message_text(index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
indexrealMessage index
-


-

Returns:

-
string


-

Example:

-
// ... INSIDE A STEAM ASYNC EVENT ...
-switch (async[? "event_type"])
-{
-    case "lobby_chat_message":
-        text = steam_lobby_get_chat_message_text(async_load[?"message_index"]);
-        break;
-}

The code above will get the current message text.

-



-
- -

Back To Top

-

steam_lobby_get_data

-

Returns a lobby field value, as set by steam_lobby_set_data.

-


-

Syntax:

-
steam_lobby_get_data(key);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringString representation of the data
-


-

Returns:

-
string


-

Example:

-
var title = steam_lobby_get_data("title");

The code above will return the data of the title field of the current value.

-



-
- -

Back To Top

-

steam_lobby_get_lobby_id

-
-
- Returns the Steam ID of the current lobby. -
-
- -


-

Syntax:

-
steam_lobby_get_lobby_id();


-

Returns:

-
int64


-

Example:

-
var lobby_id = steam_lobby_get_lobby_id()

The code above will get the current lobby id and store it in a variable.

-



-
- -

Back To Top

-

steam_lobby_get_member_count

-

Returns the number of users in the current lobby (including you). - If the lobby is not valid, returns 0.

-


-

Syntax:

-
steam_lobby_get_member_count();


-

Returns:

-
real


-

Example:

-
for(var i = 0 ; i < steam_lobby_get_member_count() ; i++)
-{
-    var user_id = steam_lobby_get_member_id(i)
-    //Do something with the user id
-}

The code sample above will get the total number of member in the current lobby and iterate over all of them getting their unique ids, using the steam_lobby_get_member_id function.

-



-
- -

Back To Top

-

steam_lobby_get_member_id

-

Returns the user ID of the member at the given index in the current lobby.

-


-

Syntax:

-
steam_lobby_get_member_id(index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
indexrealPosition of the member of the lobby to return
-


-

Returns:

-
int64


-

Example:

-
for(var i = 0 ; i < steam_lobby_get_member_count() ; i++)
-{
-    var user_id = steam_lobby_get_member_id(i)
-    //Do something with the user id
-}

The code sample above will iterate over all of the members inside a lobby and get their unique ids.

-



-
- -

Back To Top

-

steam_lobby_get_owner_id

-

Returns the lobby's owner's Steam ID. If the lobby is not valid, returns ID 0.

-


-

Syntax:

-
steam_lobby_get_owner_id();


-

Returns:

-
int64


-

Example:

-
var lobby_owner = steam_lobby_get_owner_id()

The code above will return the unique id of the owner of the current lobby.

-



-
- -

Back To Top

-

steam_lobby_is_owner

-

Returns whether the local player is the lobby's owner.

-
-

ℹ️ NOTE

-

If the lobby is not valid, returns false.

-
-


-

Syntax:

-
steam_lobby_is_owner()


-

Returns:

-
bool


-

Example:

-
for (var i = 0; i < steam_lobby_get_member_count(); i++)
-{
-    if (!steam_lobby_is_owner())
-    {
-        var user_id = steam_lobby_get_member_id(i)
-        steam_lobby_set_owner_id(user_id)
-        break;
-    }
-}

The code example will loop through all the members in a lobby and transfers ownership to the first member that is not the owner.

-



-
- -

Back To Top

-

steam_lobby_join_id

-

Starts joining a lobby with the given ID. Returns whether or not the API was correctly initialized. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_lobby_join_id(lobby_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
lobby_idint64Identifier of the lobby
-


-

Returns:

-
N/A


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_joined"
lobby_idint64The lobby unique identifier
successboolWhether or not the task was successful
resultrealThe code of the result
-


-

Example:

-
steam_lobby_join_id(lobbyID)

The code will attempt the join a lobby with a given id, the task callback can be listened to inside the the Steam Async Event with the folllowing sample code:

-
var type = async_load[? "type"];
-if (type == "lobby_joined")
-{
-    var lobby_id = async_load[? "lobby_id"];
-    var success = async_load[? "success"];
-
-    // Do something with the data
-}
-

In the example we are simply caching the data into variables.

-



-
- -

Back To Top

-

steam_lobby_leave

-

Leaves the current lobby (if any). Does not raise any errors if currently not in a lobby.

-
-

ℹ️ NOTE

-

If you are the lobby owner and leave the lobby, Steam transfers lobby ownership to any other available user, so you may need to manually handle ownership transfer using steam_lobby_set_owner_id before leaving.

-
-


-

Syntax:

-
steam_lobby_leave();


-

Returns:

-
N/A


-

Example:

-
steam_lobby_leave();

The code sample above will make the user leave the current lobby.

-



-
- -

Back To Top

-

steam_lobby_send_chat_message

-

Broadcasts a chat text message to all the users in the lobby.

-


-

Syntax:

-
steam_lobby_send_chat_message(text);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
textstringThe string to be sent (up to 4000 characters)
-


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_chat_message"
user_idstringThe sender unique identifier
message_indexrealThe message unique identifier
-


-

Example:

-
steam_lobby_send_chat_message("Hello World");

The code will broadcast a text message to all the members in the current lobby, the message can be read using the Steam Async Event callback:

-
var type = async_load[? "type"];
-if (type == "lobby_chat_message")
-{
-    var user_id = async_load[? "user_id"];
-    var msg_id = async_load[? "message_index"];
-
-    var user_name = steam_get_user_persona_name_sync(user_id);
-    var message = steam_lobby_get_chat_message_text(msg_id);
-
-    // Do something with the data
-}
-

In the example we are simply caching the data into variables notice that use use the function steam_get_user_persona_name_sync and steam_lobby_get_chat_message_text to get both the user name and the text inside the message, respectively.

-



-
- -

Back To Top

-

steam_lobby_send_chat_message_buffer

-

Broadcasts a chat (text or binary data) message to all the users in the lobby.

-


-

Syntax:

-
steam_lobby_send_chat_message_buffer(buffer, size);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
bufferbuffer IDThe buffer to be sent (up to 4 Kilobytes in size)
sizerealThe amount of byte to be sent (there is no offset).
-


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_chat_message"
user_idstringThe sender unique identifier
entry_typerealType of message received.
message_indexrealThe message unique identifier
message_sizerealThe size of the message being broadcasted
-


-

Example:

-
var buff = buffer_create(256, buffer_fixed, 1);
-buffer_write(buff, buffer_string, "This is a buffer!");
-steam_lobby_send_chat_message_buffer(buff);

The code will broadcast a message (text or binary data) to all the members in the current lobby, the message can be read using the Steam Async Event callback:

-
var type = async_load[? "type"];
-if (type == "lobby_chat_message")
-{
-    var user_id = async_load[? "user_id"];
-    var msg_id = async_load[? "message_index"];
-
-    var user_name = steam_get_user_persona_name_sync(user_id);
-    var data = steam_lobby_get_chat_message_data(global.chat_buffer, msg_id);
-
-    // Do something with the data
-}
-

In the example we are simply caching the data into variables notice that use use the function steam_get_user_persona_name_sync and steam_lobby_get_chat_message_data to get both the user name and the data inside the message, respectively.

-



-
- -

Back To Top

-

steam_lobby_set_data

-

Changes a lobby's field. You must be the lobby's owner to do this. Returns whether or not the data was set. - Fields can then be used to filter lobbies via matchmaking functions.

-
-

ℹ️ NOTE

-

If your value is numeric, convert it to string prior to passing it to the function.

-
-


-

Syntax:

-
steam_lobby_set_data(key, value);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringThe key to set the data for
valuestringThe value to set
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_set_data("LobbyName","GreatLobby")

The code sample will set the &quot;LobbyName&quot; lobby field to the provided value (&quot;GreatLobby&quot;).

-



-
- -

Back To Top

-

steam_lobby_set_joinable

-

Sets whether or not a lobby is join-able by other players. This always defaults to enabled for a new lobby. Returns whether or not the property was set.

-
-

ℹ️ NOTE

-

If joining is disabled, then no players can join, even if they are a friend or have been invited.

-
-
-

ℹ️ NOTE

-

Lobbies with joining disabled will not be returned from a lobby search.

-
-


-

Syntax:

-
steam_lobby_set_joinable(joinable);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
joinableboolAllow ( true ) or prevent ( false ) users from joining this lobby
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_set_joinable(false);

The code above will prevent user from joining the current lobby.

-



-
- -

Back To Top

-

steam_lobby_set_owner_id

-

If you are a lobby owner, transfers the lobby ownership to the specified player, which must be in this same lobby. Returns whether or not the property was set.

-
-

ℹ️ NOTE

-

You need to be the lobby owner in order to use the function.

-
-


-

Syntax:

-
steam_lobby_set_owner_id(user_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
user_idboolThe user to set as owner of the lobby
-


-

Returns:

-
bool


-

Example:

-
for(var i = 0 ; i < steam_lobby_get_member_count() ; i++)
-{
-    if(!steam_lobby_is_owner())
-    {
-        var user_id = steam_lobby_get_member_id(i)
-        steam_lobby_set_owner_id(user_id)
-        break;
-    }
-}

The code example will loop through all the members in a lobby and transfers ownership to the first member that is not the owner.

-



-
- -

Back To Top

-

steam_lobby_set_type

-

Changes the lobby's type. Useful, if you don't allow mid-session joining, you could have the game make lobbies private on session start (or use steam_lobby_set_joinable).

-
-

ℹ️ NOTE

-

You need to be the lobby owner in order to use the function.

-
-


-

Syntax:

-
steam_lobby_set_type(type)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
typeLobbyTypeThe lobby visibility
-


-

Returns:

-
N/A


-

Example:

-
steam_lobby_set_type(steam_lobby_type_private)

The code above will change the lobby joining policy.

-



-
- -

Back To Top

-

steam_lobby_list_add_distance_filter

-

Restricts results by region and sorts them based on geographical proximity.

-


-

Syntax:

-
steam_lobby_list_add_distance_filter(mode);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
modeLobbyFilterDistanceModeDistance filter to be applied
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_list_add_distance_filter(steam_lobby_list_distance_filter_far);
-steam_lobby_list_add_near_filter("myNearFilter", 77);
-steam_lobby_list_add_numerical_filter("level", 10, steam_lobby_list_filter_gt);
-steam_lobby_list_add_string_filter("Stage","BattleZone", steam_lobby_list_filter_eq)
-steam_lobby_list_request();

The code above will apply some filters to be lobby list request before requesting the results.

-



-
- -

Back To Top

-

steam_lobby_list_add_near_filter

-

Sorts the results based on how close their field's (key)'s value is to the provided one.

-
-

ℹ️ NOTE

-

If multiple near-filters are specified, the earlier-set ones take precedence.

-
-


-

Syntax:

-
steam_lobby_list_add_near_filter(key, value);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringThe filter key name to match.
valuerealThe value that lobbies will be sorted on.
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_list_add_distance_filter(steam_lobby_list_distance_filter_far);
-steam_lobby_list_add_near_filter("myNearFilter", 77);
-steam_lobby_list_add_numerical_filter("level", 10, steam_lobby_list_filter_gt);
-steam_lobby_list_add_string_filter("Stage","BattleZone", steam_lobby_list_filter_eq)
-steam_lobby_list_request();

The code above will apply some filters to be lobby list request before requesting the results.

-



-
- -

Back To Top

-

steam_lobby_list_add_numerical_filter

-

Sets up a numeric filter for the next lobby list request. That is, lobbies not matching the condition will be excluded from results.

-
-

ℹ️ NOTE

-

Lobbies without the given field (key) will be excluded.

-
-


-

Syntax:

-
steam_lobby_list_add_numerical_filter(key, value, comparison_type)
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringThe filter key name to match
valuerealThe number to compare.
comparison_typeLobbyFilterComparisonTypeThe type of comparison to make.
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_list_add_distance_filter(steam_lobby_list_distance_filter_far);
-steam_lobby_list_add_near_filter("myNearFilter", 77);
-steam_lobby_list_add_numerical_filter("level", 10, steam_lobby_list_filter_gt);
-steam_lobby_list_add_string_filter("Stage","BattleZone", steam_lobby_list_filter_eq)
-steam_lobby_list_request();

The code above will apply some filters to be lobby list request before requesting the results.

-



-
- -

Back To Top

-

steam_lobby_list_add_string_filter

-

Sets up a string filter for the next lobby list request. That is, lobbies not matching the condition will be excluded from results.

-
-

ℹ️ NOTE

-

Lobbies without the given field (key) will be assumed to have it as &quot;&quot;.

-
-


-

Syntax:

-
steam_lobby_list_add_string_filter(key, value, comparison_type)
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringThe filter key name to match
valuestringThe string to compare
comparison_typeLobbyFilterComparisonTypeThe type of comparison to make (strings only accepts equal or not equal comparison)
-


-

Returns:

-
bool


-

Example:

-
steam_lobby_list_add_distance_filter(steam_lobby_list_distance_filter_far);
-steam_lobby_list_add_near_filter("myNearFilter", 77);
-steam_lobby_list_add_numerical_filter("level", 10, steam_lobby_list_filter_gt);
-steam_lobby_list_add_string_filter("Stage","BattleZone", steam_lobby_list_filter_eq)
-steam_lobby_list_request();

The code above will apply some filters to be lobby list request before requesting the results.

-



-
- -

Back To Top

-

steam_lobby_list_get_count

-

Return count of lobbies, after a successful call to steam_lobby_list_request.

-


-

Syntax:

-
steam_lobby_list_get_count();


-

Returns:

-
real


-

Example:

-
for(var a = 0 ; a < steam_lobby_list_get_count() ; a++)
-{
-    ins = instance_create_depth(600,200+90*a,0,Obj_Steam_Networking_List_Slot);
-    ins.index = a
-    ins.lobby_id = steam_lobby_list_get_lobby_id(a)
-    ins.creator = steam_lobby_list_get_data(a, "Creator")
-}

After a successful steam_lobby_list_request this function will return the number of results in the lobby query.

-



-
- -

Back To Top

-

steam_lobby_list_get_data

-

Gets the metadata associated with the specified key from the specified lobby.

-
-

ℹ️ NOTE

-

The argument lobby_index is not a lobby id but instead the position of the lobby (from 0 to steam_lobby_list_get_count) on the query array after a steam_lobby_list_request async event is triggered.

-
-


-

Syntax:

-
steam_lobby_list_get_data(lobby_index, key);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lobby_indexrealThe lobby list index from the queried result.
keystringThe key to get the value of.
-


-

Returns:

-
string


-

Example:

-
for(var a = 0 ; a < steam_lobby_list_get_count() ; a++)
-{
-    ins = instance_create_depth(600,200+90*a,0,Obj_Steam_Networking_List_Slot);
-    ins.index = a
-    ins.lobby_id = steam_lobby_list_get_lobby_id(a)
-    ins.creator = steam_lobby_list_get_data(a, "Creator")
-}

The above code will show a code example.

-



-
- -

Back To Top

-

steam_lobby_list_get_lobby_id

-

Gets the lobby id associated to the index.

-
-

ℹ️ NOTE

-

The argument lobby_index is not a lobby id but instead the position of the lobby (from 0 to steam_lobby_list_get_count) on the query array after a steam_lobby_list_request async event is triggered.

-
-


-

Syntax:

-
steam_lobby_list_get_lobby_id(lobby_index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
lobby_indexrealThe lobby index in the current lobby list
-


-

Returns:

-
int64


-

Example:

-
for(var a = 0; a < steam_lobby_list_get_count(); a++)
-{
-    ins = instance_create_depth(600, 200+90*a, 0, Obj_Steam_Networking_List_Slot);
-    ins.index = a;
-    ins.lobby_id = steam_lobby_list_get_lobby_id(a);
-    ins.creator = steam_lobby_list_get_data(a, "Creator");
-}

The above code will show a code example.

-



-
- -

Back To Top

-

steam_lobby_list_get_lobby_member_count

-

Gets the number of users in a lobby. **

-
-

ℹ️ NOTE

-

The argument lobby_index is not a lobby id but instead the position of the lobby (from 0 to steam_lobby_list_get_count) on the query array after a steam_lobby_list_request async event is triggered.

-
-


-

Syntax:

-
steam_lobby_list_get_lobby_member_count(lobby_index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
lobby_indexrealThe lobby ID of the lobby to get the number of members of.
-


-

Returns:

-
real


-

Example:

-
steam_lobby_list_get_lobby_member_count(steam_lobby_get_lobby_id());

The above code will show a code example.

-



-
- -

Back To Top

-

steam_lobby_list_get_lobby_member_id

-

Gets the Steam ID of the lobby member at the given index.

-
-

ℹ️ NOTE

-

The argument lobby_index is not a lobby id but instead the index representation of the lobby (ranging from 0 to steam_lobby_list_get_count) on the query array after a steam_lobby_list_request async event is triggered. By the same logic the member_index is also not the user id but the indexed representation of the user within the lobby (this value ranges from 0 to steam_lobby_list_get_lobby_member_count).

-
-


-

Syntax:

-
steam_lobby_list_get_lobby_member_id(lobby_index, member_index);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
lobby_indexrealThis MUST be an index ranging from 0 to steam_lobby_list_get_count
member_indexrealThis MUST be an index ranging from 0 to steam_lobby_list_get_lobby_member_count of the lobby index
-


-

Returns:

-
int64


-

Example:

-
var count = steam_lobby_list_get_lobby_member_count(steam_lobby_get_lobby_id())
-for(var i = 0 ; i < count ; i++)
-{
-     var member = steam_lobby_list_get_lobby_member_id(i)
-     //do something with the member id
-}

The above code will show a code example.

-



-
- -

Back To Top

-

steam_lobby_list_get_lobby_owner_id

-

Returns the current lobby owner.

-
-

ℹ️ NOTE

-

The argument lobby_index is not a lobby id but instead the position of the lobby (from 0 to steam_lobby_list_get_count) on the query array after a steam_lobby_list_request async event is triggered.

-
-


-

Syntax:

-
steam_lobby_list_get_lobby_owner_id(index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
indexrealThe lobby index from the lobby list request result
-


-

Returns:

-
int64


-

Example:

-
steam_lobby_list_get_lobby_owner_id(steam_lobby_get_lobby_id());

The above code will show a code example.

-



-
- -

Back To Top

-

steam_lobby_list_is_loading

-

Returns whether a lobby list request is currently underway.

-


-

Syntax:

-
steam_lobby_list_is_loading();


-

Returns:

-
bool


-

Example:

-
steam_lobby_list_request();
-
-// Later in code
-
-if (steam_lobby_list_is_loading)
-    show_message("Loading");
-

The above will code will check to see if the lobby list request is still loading or has finished.

-



-
- -

Back To Top

-

steam_lobby_list_join

-

Starts joining a lobby with the given ID. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_lobby_list_join(index);
- - - - - - - - - - - - -
ArgumentDescription
indexPosition of the lobby in the list
-


-

Returns:

-
N/A


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_joined"
lobby_idint64The lobby unique identifier
successboolWhether or not the task was successful
resultrealThe code of the result
-


-

Example:

-
steam_lobby_list_join(0)

The code sample above can be used to join a lobby with the given index after a steam_lobby_list_request as been preformed.

-



-
- -

Back To Top

-

steam_lobby_list_request

-

Starts loading the list of lobbies matching the current filters. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

Filters are reset afterwards and have to be set again for subsequent request(s).

-
-
-

ℹ️ NOTE

-

Existing results are kept up until the event is dispatched.

-
-


-

Syntax:

-
steam_lobby_list_request()


-

Returns:

-
N/A


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "lobby_list"
lobby_countint64The number of lobbies in retrieved (same as steam_lobby_list_get_count)
successboolWhether or not the task was successful
resultrealThe code of the result
-


-

Example:

-
steam_lobby_list_add_distance_filter(steam_lobby_list_distance_filter_far);
-steam_lobby_list_add_near_filter("myNearFilter", 77);
-steam_lobby_list_add_numerical_filter("level", 10, steam_lobby_list_filter_gt);
-steam_lobby_list_add_string_filter("Stage","BattleZone", steam_lobby_list_filter_eq)
-steam_lobby_list_request();

In this extended example we will request the lobby list that matches the requested filter criteria and parse its results in the Steam Async Event. to start with we need to request the lobbies with the code above. And afterwards proceed to catch the results after/during the corresponding asynchronous event:

-
var type = ds_map_find_value(async_load, "event_type");
-if (type == "lobby_list")
-{
-    var lb_count = steam_lobby_list_get_count();
-    for (var i = 0; i < lb_count; i++)
-    {
-        var lb_ID = steam_lobby_list_get_lobby_id(i);
-        var lb_owner = steam_lobby_list_get_lobby_owner_id(i);
-        var lb_members_count = steam_lobby_list_get_lobby_member_count(i);
-        for (var j = 0; j < lb_members_count; j++)
-        {
-            var lb_member_ID = steam_lobby_list_get_lobby_member_id(i, j);
-            // Do what even you need with the queried information
-        }
-    }
-}

This code will loop through all the loobies and respective members on the query result.

-



-
- -

Back To Top

-

LobbyFilterComparisonType

-

These constants specify the comparison type when applying a filter to a lobby list request by calling the following functions:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lobby Filter Comparison Type ConstantDescription
steam_lobby_list_filter_eqEqual (==).
steam_lobby_list_filter_neNot-equal (!=)
steam_lobby_list_filter_ltLess-than (<), only applies to steam_lobby_list_add_numerical_filter
steam_lobby_list_filter_gtGreater-than (>), only applies to steam_lobby_list_add_numerical_filter
steam_lobby_list_filter_leLess-than-or-equal (<=), only applies to steam_lobby_list_add_numerical_filter
steam_lobby_list_filter_geGreater-than-or-equal (>=), only applies to steam_lobby_list_add_numerical_filter
-



-
- -

Back To Top

-

LobbyFilterDistanceMode

-

These constants specify the distance mode to be used when applying a filter to a lobby list request by calling the steam_lobby_list_add_distance_filter function.

- - - - - - - - - - - - - - - - - - - - - - - - - -
ConstantDescription
steam_lobby_list_distance_filter_closeOnly allows lobbies in same immediate region
steam_lobby_list_distance_filter_defaultAllows lobbies in same or nearby regions (same continent)
steam_lobby_list_distance_filter_farAllows lobbies from up to half-way around the globe (nearby continents)
steam_lobby_list_distance_filter_worldwideAllows any lobbies. May result in very high latencies, so use with care
-



-
- -

Back To Top

-

LobbyType

-

These constants specify the type of lobby should be used creating a new lobby using the steam_lobby_create function.

- - - - - - - - - - - - - - - - - - - - - -
Lobby Type ConstantDescription
steam_lobby_type_privateThe lobby can only be joined by invitation
steam_lobby_type_friends_onlyThe lobby can be joined by invitation or via friends-list (by opening the user's menu and picking "Join game")
steam_lobby_type_publicThe lobby can be joined by invitation, via friends-list and shows up in the public list (see matchmaking functions)
-



-
-

Achievements

-

- -

- -

Back To Top

-

Stats and Achievements

-

The Steam Stats and Achievements API provides an easy way for your game to provide persistent, roaming achievement and statistics tracking for your users. The user's data is associated with their Steam account, and each user's achievements and statistics can be formatted and displayed in their Steam Community Profile.

-
-

ℹ️ NOTE

-

You must wait until steam_stats_ready has returned true, before attempting to read or write stats and achievements.

-
-

Achievements

-

In addition to providing highly-valued rewards to players of your games, achievements are useful for encouraging and rewarding teamwork and player interaction, providing extra dimensionality to the game objectives, and rewarding users for spending more of their time in-game, and as such it is recommended that your game has a few. They are easily set up from the Steam Dashboard, but will require that you create special Icons for them. - The following functions are provided for working with achievements:

- -

Statistics Functions

-

Statistics track fine-grained pieces of information, such as play time, number of power-ups used, etc. You may choose to use them simply for tracking internal game data - so that, for instance, you can grant an achievement based on multi-session game-play statistics collected from the user across multiple computers. Or, you can track interesting game data for display on the user's Steam Community page, where users can compare their own stats against their friends.

-
-

ℹ️ NOTE

-

Previously to being used statistics must be initialized from the Steamworks control panel for your game.

-
-

The following functions are provided for working with statistics:

- -

Debug Functions

-

The following functions are provided for debugging purposes and are not recommended in the production version of you game:

-
    -
  • steam_reset_all_stats
  • -
  • steam_reset_all_stats_achievements

    -

    If the user is in Offline Mode, Steam keeps a local cache of the stats and achievement data so that the APIs can be use as normal. Any stats unable to be committed are saved for the next time the user is online. In the event that there have been modifications on more than one machine, Steam will automatically merge achievements and choose the set of stats that has had more progress. Because Steam keeps a local cache of stats data it is not necessary for the game to also keep a local cache of the data on disk, especially as such caches often come in conflict and when they do it looks to a users as if their progress has been reverted, which is a frustrating experience.

    - - -
  • -
-



-
- - -

Back To Top

-

steam_set_achievement

-

With this function you can tell the Steam API to award ("set") an achievement for the player. These achievements should have been defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel. The Steam Game Overlay will display a notification panel to the user informing them of the achievement that they have received, unless the achievement has already been awarded, in which case nothing will happen.

-


-

Syntax:

-
steam_set_achievement(ach_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
ach_namestringThe name of the achievement to set.
-


-

Returns:

-
N/A


-

Example:

-
if hp <= 0
-{
-    global.Deaths += 1;
-    if global.Deaths == 10
-    {
-        if !steam_get_achievement("ach_Player_Dies_Ten_Times") steam_set_achievement("ach_Player_Dies_Ten_Times");
-    }
-}

The above code will reward the player an achievement if the global variable "Deaths" is equal to 10 and if the achievement has not already been awarded.

- - -



-
- - -

Back To Top

-

steam_get_achievement

-

With this function you can check the Steam API to see if a specific achievement has been awarded. The achievement should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel.

-


-

Syntax:

-
steam_get_achievement(ach_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
ach_namestringThe name of the achievement to get.
-


-

Returns:

-
Bool


-

Example:

-
if hp <= 0
-{
-    global.Deaths += 1;
-    if global.Deaths == 10
-    {
-        if !steam_get_achievement("ach_Player_Dies_Ten_Times") steam_set_achievement("ach_Player_Dies_Ten_Times");
-    }
-}

The above code will reward the player an achievement if the global variable "Deaths" is equal to 10 and if the achievement has not already been awarded.

- - -



-
- - -

Back To Top

-

steam_clear_achievement

-

With this function you can tell the Steam API to clear (reset) a specific achievement. The achievement should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel.

-


-

Syntax:

-
steam_clear_achievement(ach_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
ach_namestringThe name of the achievement to clear.
-


-

Returns:

-
N/A


-

Example:

-
if mouse_check_button_pressed(mb_left)
-{
-    steam_clear_achievement("Ach_Game_Win");
-    steam_clear_achievement("Ach_Died_10_Times");
-    steam_clear_achievement("Ach_Killed_100_Enemies");
-    steam_clear_achievement("Ach_Beat_Boss_Level_1");
-}

The above code will reset the achievements of the game when the user clicks the left mouse button.

-


- - -



-
- - -

Back To Top

-

steam_set_stat_int

-

With this function you can set a specific statistic to a new, signed integer, value. The statistic should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel. Examples of when you could use this are for tracking how many times the player dies or for tracking progress towards an achievement.

-


-

Syntax:

-
steam_set_stat_int(stat_name, value);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to set.
valueintegerThe value to set the stat to.
-


-

Returns:

-
N/A


-

Example:

-
xp += 100;
-steam_set_stat_int("Total_XP", steam_get_stat_int("Total_XP") + 100);
-if steam_get_stat_int("Total_XP") > 1000
-{
-    if !steam_get_achievement("Ach_1000XP") steam_set_achievement("Ach_1000XP");
-}

The above code sets a statistic and then checks the final value for it to decide whether to award an achievement or not.

- - -



-
- - -

Back To Top

-

steam_set_stat_float

-

With this function you can set a specific statistic to a new, floating point, value. The statistic should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel. Examples of when you could use this are for tracking how far your player has travelled, or what percentage of the game is complete.

-


-

Syntax:

-
steam_set_stat_float(stat_name, value);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to set.
valuerealThe value to set the stat to.
-


-

Returns:

-
N/A


-

Example:

-
var dist_pc = (dist / dist_max) * 100;
-steam_set_stat_float("Travelled", dist_pc);

The above code calculates a percentage based on the distance travelled variable "dist" and the maximum distance you can travel "dist_max" and then sets the stat "Travelled" to the new value.

- - -



-
- - -

Back To Top

-

steam_set_stat_avg_rate

-

This function permits you to set an average statistic type with a "sliding window" effect on the average. The "session_count" value is the current value that you wish to average out, while the "session_length" is the amount of game time since the last call to the function. Please see the extended Example below for further details on how this can be used.

-


-

Syntax:

-
steam_set_stat_avg_rate(stat_name, session_count, session_length);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to set.
session_countrealThe value to get the average of.
session_lengthrealThe time that has been taken since the last time the stat was set.
-


-

Returns:

-
N/A


-

Extended Example:

-

Since the average stat function can be complex to understand, we will illustrate its use with the following example. Consider the case where you'd like to track an average statistic, such as "Points earned per hour". One approach would be to have two stats: an integer stat, "TotalPoints", and a float stat "TotalPlayTimeHours", and then divide the total points by the total time to get the "Points per Hour" value. - However, once the player has accumulated a significant amount of playtime, the calculated average will change extremely slowly, and the more the user plays the game, the less responsive that average will be. If the user has spent 100 hours playing the game, the calculated average will "lag" by about 50 hours of that, and if they increase their skill, they will not see the increase in "Points Per Hour" that they expect. To get around that we can use a "sliding window" to only calculate the "Points per hour" for the last 10 hours played. - So, to use this function, we would need to create a Steam stat (in the control panel for the game on the Workshop) called "AvgPointsPerHour" and set its Window property to 10. Now in your game you would have to add some global variables into an instance at the start:

-
global.Points = 0;
-global.Time = 0;

You would then have some controller object to count up the global "Time" variable in an alarm (for example) every second, while your game-play would affect the global "Points" variable. At regular intervals while playing (again, in a controller object, perhaps in an Alarm, or at intervals from polling the "Time" value) you would set the stat like this:

-
steam_set_stat_avg_rate("AvgPointsPerHour", global.Points, (global.Time / 3600));
-global.Points = 0;
-global.Time = 0;

Note that we divide time by 3600 since we want the time in hours and not in seconds, and afterward we reset the global "Points" variable and the global "Time" variable to 0 so that the next time the function is called, we get a new average for the statistic. Now, what Steam will do is take this value that you have sent and create an average value over the time that was set for our "window".

- - -



-
- - -

Back To Top

-

steam_get_stat_int

-

With this function you can get the value of a specific signed integer statistic. The statistic should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel.

-


-

Syntax:

-
steam_get_stat_int(stat_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to get.
-


-

Returns:

-
Real


-

Example:

-
xp += 100;
-steam_set_stat_int("Total_XP", steam_get_stat_int("Total_XP") + 100);
-if steam_get_stat_int("Total_XP") > 1000
-{
-    if !steam_get_achievement("Ach_1000XP") steam_set_achievement("Ach_1000XP");
-}

The above code sets a statistic and then checks the final value for it to decide whether to award an achievement or not.

- - -



-
- - -

Back To Top

-

steam_get_stat_float

-

With this function you can get the value of a specific floating point statistic. The statistic should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel.

-


-

Syntax:

-
steam_get_stat_float(stat_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to get.
-


-

Returns:

-
Real


-

Example:

-
var dist_pc = (dist / dist_max) * 100;
-if steam_get_stat_float("Travelled") < dist_pc
-{
-    steam_set_stat_int("Travelled", dist_pc);
-}

The above code calculates a percentage based on the distance travelled variable "dist" and the maximum distance you can travel "dist_max". It then polls the current value for the statistic "Travelled" and if it is less than the calculated value, it sets the stat again.

- - -



-
- - -

Back To Top

-

steam_get_stat_avg_rate

-

With this function you can get the value of a specific average statistic. The statistic should have been previously defined on the Steamworks control panel accounts page for your game and the string that is passed to the function should match that used as the API Name on the control panel.

-


-

Syntax:

-
steam_get_stat_avg_rate(stat_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
stat_namestringThe name of the statistic to get.
-


-

Returns:

-
Real


-

Example:

-
var avg = steam_get_stat_avg_rate("PointsPerHour");
-draw_text(8, 8, "PPH = " + string(avg);

The above code gets the current value for the average statistic "PointsPerHour" and draws it on the screen.

- - -



-
- - -

Back To Top

-

steam_reset_all_stats

-

With this function you can reset all the statistics for the current user to their default values (as defined in the Steamworks control panel for your game). If need to also reset the achievement to their default values use the steam_reset_all_stats_achievements instead.

-
-

ℹ️ TIP

-

It is recommended that you only use this function as a debug tool when developing your game.

-
-


-

Syntax:

-
steam_reset_all_stats();


-

Returns:

-
N/A


-

Example:

-
ini_open("Save.ini");
-if global.Version != ini_read_real("Data", "Version", 0)
-{
-    ini_write_real("Data", "Version", global.Version);
-    steam_reset_all_stats();
-}
-ini_close();

The above code checks a stored value in an ini file against that of a global variable and if they are different, it resets the statistics for the game.

- - -



-
- - -

Back To Top

-

steam_reset_all_stats_achievements

-

With this function you can reset all the statistics and achievements for the current user to their default values (as defined in the Steamworks control panel for your game). If you only need to reset the stats to their default values use the steam_reset_all_stats instead.

-
-

ℹ️ TIP

-

It is recommended that you only use this function as a debug tool when developing your game.

-
-


-

Syntax:

-
steam_reset_all_stats_achievements();


-

Returns:

-
N/A


-

Example:

-
ini_open("Save.ini");
-if global.Version != ini_read_real("Data", "Version", 0)
-{
-    ini_write_real("Data", "Version", global.Version);
-    steam_reset_all_stats_achievements();
-}
-ini_close();

The above code checks a stored value in an ini file against that of a global variable and if they are different, it resets the statistics and achievements for the game.

- - -



-
-

Cloud

-

- -

- -

Back To Top

-

Cloud

-

The Steam Cloud provides an easy and transparent remote file storage system for your game. All files written to disk using the cloud functions will be replicated to the Steam servers after the game exits. If the user then changes computers, the files will then be downloaded to the new computer before the game launches, meaning that the game can then access the files by reading them using the appropriate Steam functions. The Steam Client does the work of ensuring that the files are kept synchronized across all computers the user may be accessing.

-
-

ℹ️ NOTE

-

By default, the Cloud is not enabled for a game on Steamworks. it must be enabled previously from the 'Cloud' tab of the Steamworks game admin, where you should set the byte and file quota. The next time you publish your games Steamworks configuration, the Cloud storage will be ready to use.

-
-

The following functions can be used to access the Steam Cloud from within GameMaker Studio 2

- -



-
- - -

Back To Top

-

steam_is_cloud_enabled_for_app

-

With this function you can check to make sure that the Steam Cloud service is enabled for your game. It will return true if it is and false otherwise.

-
-

⚠️ IMPORTANT

-

This does not automatically mean that you can use the Cloud functions as the user can switch off Cloud synchronization from their Steam Client. You can check this using the function steam_is_cloud_enabled_for_account, but, even if it is disabled for the user (and enabled for the game), the functions will still work to store and retrieve data from a local copy of all files, it will just not upload them to the cloud on the game end, nor synchronize on the game start.

-
-


-

Syntax:

-
steam_is_cloud_enabled_for_app();


-

Returns:

-
Bool


-

Example:

-
if (steam_is_cloud_enabled_for_app())
-{
-    quota = steam_get_quota_total();
-}

The above code checks to see if the steam cloud is enabled for the game and if so it gets the size of the storage quota and stores it in a variable.

- - -



-
- - -

Back To Top

-

steam_is_cloud_enabled_for_account

-

With this function you can check to make sure that the Steam Cloud service is enabled by the user in their Steam Client settings. It will return true if it is and false otherwise.

-
-

⚠️ IMPORTANT

-

This does not automatically mean that you can store data to the Cloud, as it will also have to have been enabled for your game (you can check this using the function steam_is_cloud_enabled_for_app). If the Steam Cloud is enabled for your game, but the user has it switched off locally, you can still use the Cloud functions to store and retrieve data from a local copy of all files, it will just not upload them to the cloud on the game end, nor synchronize on the game start.

-
-


-

Syntax:

-
steam_is_cloud_enabled_for_account();


-

Returns:

-
Bool


-

Example:

-
if (steam_is_cloud_enabled_for_account())
-{
-    steam_file_share("Save.txt");
-}

The above code checks to see if the user has the Steam Cloud enabled and if it returns true, it will then synchronize the given file.

- - -



-
- - -

Back To Top

-

steam_get_quota_total

-

When using the Steam Cloud to store and synchronize files, you must set up the quota of space that your game will need. This quota is enforced on each Cloud-enabled game, on a per-user-per-game basis, so, for example, if the quota for Game X is 1 megabyte, then each Steam account that owns Game X may store, at most, 1 megabyte of data associated with that game in the Cloud. Any other Cloud-enabled games that the user owns (say, Game Y) will not be affected by the data stored by Game X. The default quota for new Steamworks games is one gigabyte, but you can change this from the Steamworks control panel for your game.

-
-

ℹ️ NOTE

-

Once the quota is exhausted file writes will fail. If you think it may be possible for the quota to be exhausted for the user of your game, you should create code to handle it, as by doing nothing you leave users in a situation where they are unable to fix things and that will lead to a poor experience of your game.

-
-


-

Syntax:

-
steam_get_quota_total();


-

Returns:

-
Real


-

Example:

-
if (steam_is_cloud_enabled_for_app())
-{
-    quota = steam_get_quota_total();
-}

The above code checks to see if the steam cloud is enabled for the game and if so it gets the size of the storage quota and stores it in a variable.

- - -



-
- - -

Back To Top

-

steam_get_quota_free

-

With this function you can find out how much free space is left for the user of the Steam Cloud quota. The value returned is in bytes.

-


-

Syntax:

-
steam_get_quota_free();


-

Returns:

-
Real


-

Example:

-
if (steam_is_cloud_enabled_for_app())
-{
-    quota = steam_get_quota_free();
-}

The above code checks to see if the steam cloud is enabled for the game and if so it gets the size of the free storage space and stores it in a variable.

- - -



-
- - -

Back To Top

-

steam_file_exists

-

With this function you can check to see if a file from the Steam Cloud exists or not, with a return value of true if it exists, or false otherwise.

-


-

Syntax:

-
steam_file_exists(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file to check for.
-


-

Returns:

-
Bool


-

Example:

-
if (steam_file_exists("Save.txt"))
-{
-    save_str = steam_file_read("Save.txt");
-}

The above code checks to see if a file exists on the Steam Cloud and if it does, it opens it and reads its contents into the variable "save_str".

- - -



-
- - -

Back To Top

-

steam_file_size

-

With this function you can check the size of a file stored on the Steam Cloud. The returned real number is the size, in bytes, of the file.

-


-

Syntax:

-
steam_file_size(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file to check the size of.
-


-

Returns:

-
Real


-

Example:

-
file_bytes = steam_file_size("Save.txt");

The above code stores the size of a file from the Steam Cloud in the variable "file_bytes".

- - -



-
- - -

Back To Top

-

steam_file_persisted

-

With this function you can check the given file to see if it has been synchronized with the Steam Cloud. A return value of true means that it is, while false means it is not.

-


-

Syntax:

-
steam_file_persisted(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file to check.
-


-

Returns:

-
Bool


-

Example:

-
if (!steam_file_persisted("Save.txt"))
-{
-    steam_file_share("Save.txt");
-}

The above code will check to see if a file has been stored to the Steam Cloud, and if it has not it will then synchronize it.

- - -



-
- - -

Back To Top

-

steam_file_write

-

You can use this function to write data to a file, which will then be synchronized with the Steam Cloud when the user exits the game. if the file does not exist, this function will create it for you, and if it does already exists, it will overwrite any data that is already stored within the file with the new data string. The function will return a value of 0 if it fails for whatever reason and a value greater than 0 if it succeeds.

-


-

Syntax:

-
steam_file_write(filename, data, size);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file to write to.
datastringThe data to write (a string).
sizeintegerthe size of the data to be written.
-


-

Returns:

-
Real


-

Example:

-
var fname = "SaveData.txt";
-var data = string(global.Level) + "|" + string(global.Points) + "|" + string(global.HP);
-var len = string_length(data);
-steam_file_write_file(fname, data, len);

The above code will prepare a number of local variables and then use them to write to (or create) a file which will then be synchronized with the Steam Cloud.

- - -



-
- - -

Back To Top

-

steam_file_write_file

-

With this function you can copy the contents of a locally saved file to a file that is synchronized with the Steam Cloud. The local file must exist before using this function, and it will return a value of 0 if it fails for whatever reason and a value greater than 0 if it succeeds.

-


-

Syntax:

-
steam_file_write_file(steam_filename, local_filename);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
steam_filenamestringThe Steam Cloud file to copy over.
local_filenamestringThe local file to use to copy from.
-


-

Returns:

-
real


-

Example:

-
steam_file_write_file("rm_koala.png", "Koala2.png");

The above code will copy the contents of the file "Koala2.png" to the Steam Cloud file "rm_koala.png".

- - -



-
- - -

Back To Top

-

steam_file_read

-

This function will read the contents of the given file into a string which can later be parsed in your game.

-


-

Syntax:

-
steam_file_read(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file to read from.
-


-

Returns:

-
String


-

Example:

-
if steam_file_exists("Save.txt")
-{
-    save_str = steam_file_read("Save.txt");
-}

The above code checks to see if a file exists on the Steam Cloud and if it does, it opens it and reads its contents into the variable "save_str".

- - -



-
- - -

Back To Top

-

steam_file_share

-

With this function you can force your game to synchronize the given file with the Steam Cloud. This is not normally necessary due to the fact that the game will synchronize automatically at the end of the player's session, nor is it recommended by Steam, but it can be useful to ensure sensitive information is synchronized immediately. The function will return a value of 0 if it fails for whatever reason and a value greater than 0 if it succeeds.

-


-

Syntax:

-
steam_file_share(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file synchronize.
-


-

Returns:

-
Real


-

Example:

-
if (!steam_file_persisted("Save.txt"))
-{
-    steam_file_share("Save.txt");
-}

The above code will check to see if a file has been stored to the Steam Cloud, and if it has not it will then synchronize it.

- - -



-
- - -

Back To Top

-

steam_file_delete

-

This function will delete the given file from the Steam Cloud. The function will return a value of 0 if it fails for whatever reason and a value greater than 0 if it succeeds.

-


-

Syntax:

-
steam_file_delete(filename);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the file delete.
-


-

Returns:

-
Real


-

Example:

-
if (steam_file_exists("Save.txt"))
-{
-    steam_file_delete("Save.txt");
-}

The above code will check to see if a file exists, and if it does, it deletes the file from the Steam Cloud.

- - -



-
-

DLC

-

- -

- -

Back To Top

-

DLC

-

Steam supports both free and paid downloadable content (DLC), and in the Steam client, a game with downloadable content appears as a single application in the user's game list with the downloadable content viewable through the games properties dialog. Once owned, downloadable content is treated as an integral part of the game and Steam will automatically update the content when a patch is available and installs the content when the user installs the game. - Since this is all handled by the Steam servers and the configuration of any DLC is done through the Steamworks control panel, there are only a couple of functions necessary in GameMaker Studio 2 to check for this extra content:

- -



-
- - -

Back To Top

-

steam_user_owns_dlc

-

If your game has DLC created for it, you can use this function to check whether the user has bought it before accessing any files associated with it. The function will return true (1) if the player owns the content, false (0) if they don't own it or the given DLC ID is invalid, or -1 if they're not logged into Steam.

-
-

ℹ️ NOTE

-

Even if the user owns the DLC it doesn't mean that they have it installed in their local account, so you should additionally use the function steam_user_installed_dlc to make sure that it is before using it.

-
-


-

Syntax:

-
steam_user_owns_dlc(dlc_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
dlc_idint64The unique identifier for the DLC to be checked.
-


-

Returns:

-
Integer


-

Example:

-
global.Level_Max = 100;
-if steam_user_owns_dlc(10354)
-{
-    if steam_user_installed_dlc(10354)
-    {
-        global.Level_max = 200;
-    }
-}

The above code will check to see if the user has bought, and installed, the DLC with the id 10354, and if so set a global variable to a different value.

- - -



-
- - -

Back To Top

-

steam_user_installed_dlc

-

If your game has DLC created for it, you can use this function to check and see whether the user has installed it before accessing any files associated with it. The function returns true if the player has the content installed, and false if the user does not, but note that the user must also own the DLC, so you should use the additional function of steam_user_owns_dlc to check that it is owned as well before using it.

-


-

Syntax:

-
steam_user_installed_dlc(dlc_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
dlc_idint64The unique identifier for the DLC to be checked.
-


-

Returns:

-
Bool


-

Example:

-
global.Level_Max = 100;
-if (steam_user_owns_dlc(10354))
-{
-    if (steam_user_installed_dlc(10354))
-    {
-        global.Level_max = 200;
-    }
-}

The above code will check to see if the user has bought, and installed, the DLC with the id 10354, and if so set a global variable to a different value.

- - -



-
-

UGC

-

- -

- -

Back To Top

-

UGC

-

This section is for those users that have been given access to the Steam API for publishing your game to that platform and that want to use the possibilities that the Steam Workshop and Community gives you for adding and generating user content in your projects. The simplest form of user generated content is the ability for the user to take and share screenshots, which is facilitated using the following two functions:

- -
-

ℹ️ NOTE

-

You need to have your game accepted for the Steam online store and have access to the developer areas of the Steam API documentation.

-
-

All subscribed UGC items will be downloaded by the Steam client automatically, and you should have code in the Steam Asynchronous Event to catch this and store the ID of the UGC that has been downloaded for use in the other UGC functions.

-
-

⚠️ IMPORTANT

-

Steam UGC IDs can be huge numbers This means that sometimes you may need to store these as a string rather than try and store them as a real value, especially if working with buffers or trying to write the value to a text file (since this will convert it to a simplified standard format like "6.6624e+003" which will cause issues being read back).

-
-

The normal workflow for getting UGC into your game would be as follows:

-
    -
  1. The user would subscribe to an item (either from your game using steam_ugc_subscribe_item or from the client/browser). If done from the game you are able to "listen" to the callback from the Steam Async Event.
  2. -
  3. When you get a successful subscription callback this means that your game is now downloading the UGC. You would then check if the item is installed (ie: download completed) with steam_ugc_get_item_install_info.
  4. -
  5. If the item is not completely installed, you can use steam_ugc_get_item_update_info to track the download progress.

    -

    The following sections explain all the functions required to get UGC functioning in GameMaker Studio 2:

    -
  6. -
-

Creating And Editing Content

-

The following functions are essentially "wrapper" functions for those supplied in the Steam API for creating and uploading content to their servers. As such, we recommend that you read over the linked Steam documentation before using them to gain a greater understanding of how they work: Creating And Uploading Content.

- -

Consuming Content

-

Once your user content has been created and the workshop has it available for download, people can subscribe to it through the Steam App or through the Web portal. However GameMaker Studio 2 also includes the following functions to use the Steam API for creating and canceling subscriptions as well as for getting information about what the user is subscribed to currently:

- -

Querying Content

-

There are also a large number of functions available to query the Steam API about the UGC items available:

- -

Constants

-

This section also provides a set of constants to be used along side the functions provided above:

- -



-
- - -

Back To Top

-

steam_is_screenshot_requested

-

This function will poll the Steam API to see if the key for taking a screenshot of the game has been pressed. The function will only return true for one step (game tick) when the key is pressed, and will returnfalse at all other times. - Please note that if the screenshot key is pressed, this function will only return true once for each step that it is pressed, and return false for any subsequent calls within the same step . For example, if a screenshot is requested in the current frame and you call this function in the Step event to find that out, you will get true; however, if you call it again in Draw GUI to check whether a screenshot was requested, you will get false as the function had already been "used up" in the Step event. To use the function's return value multiple times within the same frame, it is recommended to store it in a variable and read that instead of calling the function again.

-
-

ℹ️ NOTE

-

This function does not take a screenshot for you. This only signals that the key has been pressed and you must use the GameMaker Studio 2 functions screen_save or screen_save_part to save a local copy of the file to be uploaded.

-
-


-

Syntax:

-
steam_is_screenshot_requested();


-

Returns:

-
Bool


-

Example:

-
if steam_is_screenshot_requested()
-{
-    var file = "Catch_The_Haggis_" + string(global.scrn_num) + ".png");
-    screen_save(file)
-    steam_send_screenshot(file, window_get_width(), window_get_height());
-    global.scrn_num += 1;
-}

The above code will poll the Steam API for a screenshot request and if it has been, a unique name for the image file will be generated, a screenshot will be taken, and the file will be sent to the Steam Community page for the user.

- - -



-
- - -

Back To Top

-

steam_send_screenshot

-

With this function you can upload a screenshot to the Steam Community profile page of the currently logged in user. The filename you supply is the name of the local file that was created when you took the screenshot using the GameMaker Studio 2 functions screen_save or screen_save_part. The width and height define the image size, and the function will return a value of 0 if it fails for whatever reason and a value greater than 0 if it succeeds.

-


-

Syntax:

-
steam_send_screenshot(filename, width, height);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
filenamestringThe name of the image file to upload.
widthrealThe width of the image.
heightrealThe height of the image.
-


-

Returns:

-
Real


-

Example:

-
if steam_is_screenshot_requested()
-{
-    var file = "Catch_The_Haggis_" + string(global.scrn_num) + ".png");
-    screen_save(file)
-    steam_send_screenshot(file, window_get_width(), window_get_height());
-    global.scrn_num += 1;
-}

The above code will poll the Steam API for a screenshot request and if it has been, a unique name for the image file will be generated, a screenshot will be taken, and the file will be sent to the Steam Community page for the user.

- - -



-
- - -

Back To Top

-

steam_ugc_create_item

-

This function is used to prepare the Workshop API and generate a published file ID for the item to be added. The function must be called before doing anything else with the item to be uploaded, as you will be required to use the unique published ID value that it returns in the Steam Async Event for updating. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_create_item(consumer_app_id, file_type);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
consumer_app_idintegerThe unique App ID for your game on Steam.
file_typeconstant.UGCFileTypeOne of the available file type constants (see UGCFileType constants).
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_create_item"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
legal_agreement_requiredboolWill be true or false (see the Steam docs for more details)
published_file_idint64This key holds the unique published ID for the item (you may need to cast it using the int64() function)
-


-

Extended Example:

-

In this example we first call the function and store the async ID value in a variable:

-
var app_id = steam_get_app_id();
-new_item = steam_ugc_create_item(app_id, ugc_filetype_community);

This would then send off a request to the Steam API to create the new Workshop item, generating an async event which we would deal with as follows:

-
var event_id = async_load[? "id"];
-if event_id == new_item
-{
-    var type = async_load[? "event_type"];
-    if type == "ugc_create_item"
-    {
-        global.Publish_ID = async_load[? "published_file_id"];
-    }
-}

The above code checks the event type and if it is "ugc_create_item" then it retrieves the published file ID and stores it in a global variable for future reference.

- - -



-
- -

Back To Top

-

steam_ugc_delete_item

-

This function attempts to delete a previously published UGC item. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_delete_item(ugc_query_handle);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to use.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_item_delete"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
-


-

Example:

-
steam_ugc_delete_item(ugc_query_handle);

The above code creates a deletion request for ugc_query_handle.

-



-
- - -

Back To Top

-

steam_ugc_start_item_update

-

This function must be called before adding or updating information on a UGC item. You need to supply the unique App ID for your game on Steam, along with the unique published file ID that was returned for the item when you created it using the function steam_ugc_create_item. The function will return a unique update handle for the item, which you can then use in the UGC item functions to update (or add) information for uploading.

-


-

Syntax:

-
steam_ugc_start_item_update(consumer_app_id, published_file_id);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
consumer_app_idrealThe unique App ID for your game on Steam.
published_file_idint64The unique published file ID value for the item.
-


-

Returns:

-
Real


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_title

-

This function will set the title to be used for the given item. - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_title(ugc_update_handle, title);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
titlestringThe title (max 128 characters) to be used for the item.
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_description

-

This function will set the description to be used for the given item. - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_description(ugc_update_handle, description);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
descriptionstringThe description (max 8000 characters) to be used for the item.
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_visibility

-

This function will set the visibility of the given item, using one of the UGCFileVisibility constants. - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_visibility(ugc_update_handle, visibility);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
visibilityconstant.UGCFileVisibilityThe visibility to be used for the item (see UGCFileVisibility constant)
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_tags

-

This function will set the tags to be used for the given item. The tags should be added to a 1D array as string elements and the array passed to the function. - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_tags(ugc_update_handle, tags);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
tagsstringThe tags (as an string json array) to be used for the item.
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, string(tagArray));
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_content

-

This function will set the content path to be used for the given item, and it should be a relative path to the folder which contains the content files to upload - which in turn should be in the save are or the game bundle (ie: an included file). - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_content(ugc_update_handle, content);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
contentstringThe content path to be used for the item
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_set_item_preview

-

This function will set the preview image to be used for the given item. The image should be supplied as either a PNG, JPG or GIF format file with a maximum size of 1MB. The path to the image should be a relative path in the save are or the game bundle (ie: an included file). - The function will return true if the API was successfully accessed and false if there was an issue.

-


-

Syntax:

-
steam_ugc_set_item_preview(ugc_update_handle, preview);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
previewstringThe preview image (JPG, GIF or PNG - max size 1MB) to be used for the item.
-


-

Returns:

-
Bool


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-
- - -

Back To Top

-

steam_ugc_submit_item_update

-

This function will submit the UGC item indexed by the given handle to the Steam Workshop servers, adding the change notes to be used for the given item. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_submit_item_update(ugc_update_handle, change_note);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handlerealThe unique handle for the UGC to be updated (returned from steam_ugc_start_item_update)
change_notestringThe change notes to be used for the item.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_update_item"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
legal_agreement_requiredboolWill be true or false (see the Steam docs for more details)
-


-

Example:

-
var app_id = steam_get_app_id();
-var updateHandle = steam_ugc_start_item_update(app_id, global.Publish_ID);
-steam_ugc_set_item_title(updateHandle, "My workshop item(3)!");
-steam_ugc_set_item_description( updateHandle, "testing workshop...");
-steam_ugc_set_item_visibility(updateHandle, ugc_visibility_public);
-var tagArray;
-tagArray[0] = "Test";
-tagArray[1] = "New";
-steam_ugc_set_item_tags(updateHandle, tagArray);
-steam_ugc_set_item_preview(updateHandle, "promo.jpg");
-steam_ugc_set_item_content(updateHandle, "WorkshopContent1");
-requestId = steam_ugc_submit_item_update(updateHandle, "Version 1.2");

The above code gets the game ID, then uses that along with a previously stored published file ID to generate an update handle for the item. This handle is then used to update various pieces of information before the update is pushed to the Workshop servers.

- - -



-

---

- -

Back To Top

-

steam_ugc_get_item_update_progress

-
This function can be used to track the update status for an item. You give the item handle (as returned by the function [steam_ugc_start_item_update](#steam_ugc_start_item_update)) and an empty [DS map](https://manual.yoyogames.com/GameMaker_Language/GML_Reference/Data_Structures/DS_Maps/DS_Maps.htm) which will then be populated with the update information (see table below)
-If there is an error the function will return `false` and the map will be empty, otherwise the function returns `true`.


-

Syntax:

-
steam_ugc_get_item_update_progress(ugc_update_handle, info_map);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_update_handleintegerThe unique handle for the UGC to be updated.
info_mapDS Map IDA (previously created) DS map index.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
status_coderealThe Steam status code
status_stringstringA string for the current status
bytes_processedrealThe bytes processed so far
bytes_totalrealThe total number of bytes in the update
-


-

Returns:

-
Bool


-

Example:

-
var uploadMap = ds_map_create();
-
-  steam_ugc_get_item_update_progress(global.itemHandle, uploadMap);
-
-  var statusCode = uploadMap[? "status_code"];
-
-  var status = uploadMap[? "status_string"];
-
-  var processed = uploadMap[? "bytes_processed"];
-
-  var total = uploadMap[? "bytes_total"];
-
-  draw_text(32, 0, "Upload info for item:" + string(global.itemHandle));
-
-  draw_text(32, 15, "status code:" + string(statusCode));
-
-  draw_text(32, 30, "status:" + string(status));
-
-  draw_text(32, 45, "bytes processed:" +string(processed));
-
-  draw_text(32, 60, "bytes total:" + string( total));
-
-  ds_map_destroy(uploadMap);
The above code will query the upload status of the item indexed in the global variable &quot;itemHandle&quot;, using a `DS Map` to store the information. This is then parsed and the resulting values drawn to the screen.
-
-<!-- KEYWORDS

steam_ugc_get_item_update_progress ---> -

-
- - -

Back To Top

-

steam_ugc_subscribe_item

-

This function can be used to subscribe to a UGC item. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_subscribe_item(published_file_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
published_file_idint64The unique file ID for the UGC to subscribe to.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_subscribe_item"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
published_file_idint64This key holds the unique published ID for the item (you may need to cast it using the int64 function, before passing it to subsequent functions)
-


-

Example:

-
steam_sub = steam_ugc_subscribe_item(global.pubFileID);

The above code will subscribe (and download) the item with the file ID stored in the global variable "pubFileID".

- - -



-
- - -

Back To Top

-

steam_ugc_unsubscribe_item

-

This function can be used to unsubscribe from a UGC item. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_unsubscribe_item(published_file_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
published_file_idint64The unique file ID for the UGC to unsubscribe from.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_unsubscribe_item"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
published_file_idint64This key holds the unique published ID for the item (you may need to cast it using the int64 function)
-


-

Example:

-
steam_sub = steam_ugc_unsubscribe_item(global.pubFileID);

The above code will unsubscribe (and remove) the item with the file ID stored in the global variable "pubFileID".

- - -



-
- - -

Back To Top

-

steam_ugc_num_subscribed_items

-

This function can be used to get the number of items that the current user has subscribed to.

-


-

Syntax:

-
steam_ugc_num_subscribed_items();


-

Returns:

-
Real


-

Example:

-
numSub = steam_ugc_num_subscribed_items();

The above code will store the number of subscribed items in a variable.

- - -



-

---

- -

Back To Top

-

steam_ugc_get_subscribed_items

-
This function will populate a DS list with all the published file IDs for the items that the user is currently subscribed to. You must first create the list and store the index in a variable, then pass this to the function.
-The function will return ```true` if everything is correct and the Steam API is initialized, or `false` if there is an error.


-

Syntax:

-
steam_ugc_get_subscribed_items(item_list);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
item_listDS List IDA (previously created) DS list index.
-


-

Returns:

-
Bool


-

Example:

-
steam_list = ds_list_create();
-
-  steam_ugc_get_subscribed_items(steam_list);
The above code will create an empty DS list and then populate it with the file IDs for all subscribed items for the user.
-
-<!-- KEYWORDS

steam_ugc_get_subscribed_items ---> -

-

---

- -

Back To Top

-

steam_ugc_get_item_install_info

-
This function can be used to retrieve information about any given published file item that has been subscribed to and downloaded to the Steam local storage area for your game. You give the item ID and supply the index to an empty [DS map](https://manual.yoyogames.com/GameMaker_Language/GML_Reference/Data_Structures/DS_Maps/DS_Maps.htm) which will then be populated with the install information (see table below).
-If the item exists (ie.: as been subscribed and download was complete) then the function will return `true` and populate the map, otherwise it will return `false` and the map will remain empty.


-

Syntax:

-
steam_ugc_get_item_install_info(published_file_id, info_map);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
published_file_idint64The unique handle for the UGC to be updated.
info_mapDS Map IDA (previously created) DS map index.
- - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
size_on_diskrealThe file size on disk (in bytes)
legacy_itemboolWill be true or false depending on whether it is a legacy file or not
folderstringThis is the full path to the installed content ( please refer to "Item Installation" in Steam SDK docs, as "legacy" items uploaded with the old method, are treated differently)
-


-

Returns:

-
Bool


-

Example:

-
var item_map = ds_map_create();
-
-  steam_ugc_get_item_install_info(global.fileID, item_map);
The above code will query the install status of the item indexed in the global variable &quot;fileID&quot;, using a `DS Map` to store the information.
-
-<!-- KEYWORDS

steam_ugc_get_item_install_info ---> -

-

---

- -

Back To Top

-

steam_ugc_get_item_update_info

-
This function can be used to retrieve information about the current download state for the given file ID. You give the item ID and supply the index to an empty [DS map](https://manual.yoyogames.com/GameMaker_Language/GML_Reference/Data_Structures/DS_Maps/DS_Maps.htm) which will then be populated with the update information (see table below).
-If the item exists then the function will return `true` and populate the map, otherwise it will return `false` and the map will remain empty.


-

Syntax:

-
steam_ugc_get_item_update_info(published_file_id, info_map);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
published_file_idint64The unique file ID for the UGC to be checked.
info_mapDS Map IDA (previously created) DS map index.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
needs_updateboolWhether the item needs an update or not
is_downloadingboolWhether the item is currently downloading or not
bytes_downloadedrealThe number of bytes that has been downloaded
bytes_totalrealThe total size (number of bytes) required for the item on disk
-


-

Returns:

-
Bool


-

Example:

-
var info_map = ds_map_create();
-
-  var info = steam_ugc_get_item_update_info(global.fileID, info_map);
-
-  if info
-
-  {
-
-  draw_text(32, 15, "needs_update: " + string(info_map[? "needs_update"]));
-
-  draw_text(32, 30, "is_downloading: " + string(info_map[? "is_downloading"]));
-
-  draw_text(32, 45, "bytes_downloaded: " + string(info_map[? "bytes_downloaded"]));
-
-  draw_text(32, 60, "bytes_total: " + string(info_map[? "bytes_total"]));
-
-  }
The above code will query the download status of the item indexed in the global variable &quot;fileID&quot;, using a `DS Map` to store the information.
-
-<!-- KEYWORDS

steam_ugc_get_item_update_info ---> -

-
- - -

Back To Top

-

steam_ugc_request_item_details

-

This function can be used to retrieve information about a given file ID. You give the file ID and supply a maximum age for checking (see the Steam docs for more information). - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_request_item_details(published_file_id, max_age_seconds);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
published_file_idrealThe unique file ID for the UGC to be checked.
max_age_secondsrealThe age of the data to check (recommended 30 - 60 seconds).
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_item_details"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
cached_databoolWill be true if the returned details are from the local cache or false if they are taken from the server
published_file_idint64This key holds the unique published ID for the item (you may need to cast it using the int64 function)
file_typestringThe type of file used
creator_app_idrealThe Steam ID of the item creator
consumer_app_idrealThe Steam ID of the item consumer
titlestringThe title of the item
descriptionstringThe description of the item
steam_id_ownerrealThe Steam ID of the item owner
time_createdrealThe time the item was first created
time_uploadedrealThe last time the item was updated
time_added_to_user_listrealThe time that the item was subscribed to
visibilityconstant.UGCFileVisibilityThe visibility of the item (see UGCFileVisibility constant)
bannedboolWhether the item has been banned or not
accepted_for_useboolWhether the item has been accepted for use or not
tags_truncatedarrayShort version of the tags as an array
tagsarrayAn array of the tags for the item
handle_fileint64The unique file handle for the item
handle_preview_fileint64The unique handle for the image preview for the item (can be used with steam_ugc_download to download a preview image)
filenamestringThe name of the item file
file_sizerealThe size of the item file
preview_file_sizerealThe size of the preview image
urlstringThe full URL for the item
up_votesrealThe number of up-votes received
down_votesrealThe number of down-votes received
scorerealThe overall score of the item
account_id_ownerrealThe account ID from the Steam ID owner (this can be used in function steam_ugc_create_query_user_ex)
-


-

Extended Example:

-

In this example we send off a details request for an item and then parse the resulting async_load DS map to set some variables. First we send of the request:

-
steam_details = steam_ugc_request_item_details(global.fileID, 60);

The above code will request details on the item with the file ID stored in the global variable and will trigger a Steam Async event with the returned information. In this event we can then parse the map and store some of the values in variables which can then be used to display the information to the user:

-
var map_id = async_load[? "id"];
-var result = async_load[? "result"];
-if (map_id == steam_details) && (result == ugc_result_success)
-{
-    mTitle = async_load[? "title"];
-    mDesc = async_load[? "description"];
-    mTags = async_load[? "tags"];
-    m_hPreviewFile = async_load[? "handle_preview_file"];
-    m_hOwnerSteamId = async_load[? "steam_id_owner"];
-    mOwnerAccountId = async_load[? "account_id_owner"];
-    mPubFileId = async_load[? "published_file_id"];
-    mScore = async_load[? "score"];
-}
- -



-
- - -

Back To Top

-

steam_ugc_create_query_user

-

This function can be used to query the UGC data base. The function automatically uses the default ID for the app, user and assumes that the query is being done by the consumer (rather than the creator). The function requires you to use the following constants for the type of data to query (UGCListType), the type of item to match (UGCMatchType) and the order in which the returned items will be sorted (UGCListSortOrder), as well as a page number - note that a query will return a maximum number of 50 items. - The function returns a unique query handle value which should be stored in a variable for use in the other query functions. Note that this function only prepares the query but does not actually send it - for that you must call the function steam_ugc_send_query - and you can use further steam_ugc_query_*() functions to refine the search request before it is actually sent.

-


-

Syntax:

-
steam_ugc_create_query_user(list_type, match_type, sort_order, page);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
list_typeconstant.UGCListTypeThe type of data list to create (see UGCListType constants)
match_typeconstant.UGCMatchTypeThe type of UGC items to query (see UGCMatchType constants)
sort_orderconstant.UGCListSortOrderThe way that data should be ordered (see UGCListSortOrder constants)
pagerealThe page number to query.
-


-

Returns:

-
Real


-

Example:

-
query_handle = steam_ugc_create_query_user(ugc_list_Published, ugc_match_Items, ugc_sortorder_TitleAsc, 1);

The above code creates a query request and stores it's handle in a variable for future use.

- - -



-
- - -

Back To Top

-

steam_ugc_create_query_user_ex

-

This function can be used to query the UGC data base. The function requires the ID value for the user and the ID of the game that is going to consume the item and/or the ID of the game that created the item. You also need to use the following constants for the type of data to query (UGCListType), the type of item to query (UGCMatchType) and the order in which the returned items will be sorted (UGCListSortOrder), as well as a page number - note that a query will return a maximum number of 50 items. - The function returns a unique query handle value which should be stored in a variable for use in the other query functions. Note that this function only prepares the query but does not actually send it - for that you must call the function steam_ugc_send_query - and you can use further steam_ugc_query_*() functions to refine the search request before it is actually sent.

-


-

Syntax:

-
steam_ugc_create_query_user_ex(list_type, match_type, sort_order, page, account_id, creator_app_id, consumer_app_id);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
list_typeconstant.UGCListTypeThe type of data list to create (see UGCListType constants)
match_typeconstant.UGCMatchTypeThe type of UGC items to query (see UGCMatchType constants)
sort_orderconstant.UGCListSortOrderThe way that data should be ordered (see UGCListSortOrder constants)
pagerealThe page number to query
account_idrealThe Steam account ID
creator_app_idrealThe item creator app ID
consumer_app_idrealThe consumer app ID
-


-

Returns:

-
Real


-

Example:

-
query_handle = steam_ugc_create_query_user_ex(ugc_list_Published, ugc_match_Items, ugc_sortorder_TitleAsc, page, global.AccountID, 0, global.GameID);

The above code creates a query request and stores it's handle in a variable for future use.

- - -



-
- - -

Back To Top

-

steam_ugc_create_query_all

-

This function can be used to query the UGC data base using some predefined query types. The function requires the following constants for the type of query to create (UGCQueryType), the type of item to match (UGCMatchType) and the page number to query - note that a query will return a maximum number of 50 items. - The function returns a unique query handle value which should be stored in a variable for use in the other query functions. Note that this function only prepares the query but does not actually send it - for that you must call the function steam_ugc_send_query - and you can use further steam_ugc_query_*() functions to refine the search request before it is actually sent.

-


-

Syntax:

-
steam_ugc_create_query_all(query_type, match_type, page);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
query_typeconstant.UGCQueryTypeThe type of query to create (see UGCQueryType constants)
match_typeconstant.UGCMatchTypeThe type of UGC items to query (see UGCMatchType constants)
pagerealThe page number to query
-


-

Returns:

-
Real


-

Example:

-
query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);

The above code creates a general query request and stores it's handle in a variable for future use.

- - -



-
- - -

Back To Top

-

steam_ugc_create_query_all_ex

-

This function can be used to query the UGC data base. The function requires the ID of the game that is going to consume the item and/or the ID of the game that created the item, and you need to use the following constants for the type of query to create (UGCQueryType), the type of item to match (UGCMatchType) and the page number to query. Note that a query will return a maximum number of 50 items. - The function returns a unique query handle value which should be stored in a variable for use in the other query functions. Note that this function only prepares the query but does not actually send it - for that you must call the function steam_ugc_send_query - and you can use further steam_ugc_query_*() functions to refine the search request before it is actually sent.

-


-

Syntax:

-
steam_ugc_create_query_all_ex(query_type, match_type, page, creator_app_id, consumer_app_id);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
query_typeconstant.UGCQueryTypeThe type of query to create (see UGCQueryType constants)
match_typeconstant.UGCMatchTypeThe type of UGC items to query (see UGCMatchType constants)
pagerealThe page number to query
creator_app_idintegerThe item creator app ID
consumer_app_idintegerThe consumer app ID
-


-

Returns:

-
Real


-

Example:

-
query_handle = steam_ugc_create_query_all_ex(ugc_query_RankedByVote, page, global.AccountID, 0, global.GameID);

The above code creates a query request and stores it's handle in a variable for future use.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_cloud_filename_filter

-

This function can be used to further filter any given UGC query, specifically to check and see if a Workshop item file name must match or not. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is either true orfalse` depending on whether you require the file names to match. - The function will returntrueif the query filter was correctly set, orfalse` otherwise.

-


-

Syntax:

-
steam_ugc_query_set_cloud_filename_filter(ugc_query_handle, should_match);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handleintegerThe query handle to use.
match_cloud_filenameboolSets whether the UGC item file name should match or not.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_set_cloud_filename_filter(query_handle, true);
-steam_ugc_query_add_excluded_tag(query_handle, "nasty chips");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_match_any_tag

-

This function can be used to further filter any given UGC query, specifically to switch on or off tag matching. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is either true orfalse``depending on whether you require a check for matching tags. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_match_any_tag(ugc_query_handle, match_any_tag);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handleintegerThe query handle to use.
match_any_tagboolSets whether the UGC item tags should match anything or not.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_set_match_any_tag(query_handle, false);
-steam_ugc_query_add_excluded_tag(query_handle, "walking simulator");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_search_text

-

This function can be used to further filter any given UGC query, specifically to search for the given string in the title and description of the UGC items. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is a string you want to use as the search term. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_search_text(ugc_query_handle , search_text);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to use.
search_textstringThe search text to use for the query.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_set_search_text(query_handle, "texture");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_ranked_by_trend_days

-

This function can be used to further filter any UGC query made using the ugc_query_RankedByTrend constant (UGCQueryType), specifically to search over a number of days. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is the number of days over which you want the query to run. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_ranked_by_trend_days(ugc_query_handle, days);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to use.
daysrealThe number of days to query.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByTrend, ugc_match_Items, 1);
-steam_ugc_query_set_ranked_by_trend_days(query_handle, 5);
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_add_required_tag

-

This function can be used to further filter any given UGC query, specifically to search only those UGC items with the given tag. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is a string you want to use as the tag to include. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_add_required_tag(ugc_query_handle, tag_name);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handleintegerThe query handle to use.
tag_namestringThe tag name to include.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByTrend, ugc_match_Items, 1);
-steam_ugc_query_add_required_tag(query_handle, "RPG");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_add_excluded_tag

-

This function can be used to further filter any given UGC query, specifically to exclude a given UGC from the query request. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is a string you want to use as the tag to exclude. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_add_excluded_tag(ugc_query_handle, tag_name);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handleintegerThe query handle to use.
tag_namestringThe tag name to exclude.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_add_excluded_tag(query_handle, "walking simulator");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_return_long_description

-

This function can be used to further filter any given UGC query, specifically to retrieve the long description text in the call back event triggered when the query was sent. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is either true orfalse``. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_return_long_description(ugc_query_handle, should_return);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to use.
long_descriptionboolWhether to have the query return the long description text.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_return_total_only

-

This function can be used to further filter any given UGC query, specifically to request only the number of results without any other information (meaning that the DS map generated by the send function will contain the key "num_results" without any further map data). The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is either true orfalse``. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_return_total_only(ugc_query_handle , total_only);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to use.
total_onlyboolWhether to have the query return only the total number of hits or not.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByVote, ugc_match_Items, 1);
-steam_ugc_query_set_return_total_only(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-
- - -

Back To Top

-

steam_ugc_query_set_allow_cached_response

-

This function can be used to further filter any given UGC query, specifically to request that the query check the local cache rather than online. The query handle is the value returned when you created the query (using, for example, steam_ugc_create_query_user) and the second argument is either true orfalse````. - The function will return true if the query filter was correctly set, or false otherwise.

-


-

Syntax:

-
steam_ugc_query_set_allow_cached_response(ugc_query_handle , check_cache);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handleintegerThe query handle to use.
cacheboolWhether to have the query check the local cache or not.
-


-

Returns:

-
Bool


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByTrend, ugc_match_Items, 1);
-steam_ugc_query_add_required_tag(query_handle, "RPG");
-steam_ugc_query_set_return_long_description(query_handle, true);
-steam_ugc_query_set_allow_cached_response(query_handle, true);
-query_ID = steam_ugc_send_query(query_handle);

The above code creates a query request and stores it's handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.

- - -



-

---

- -

Back To Top

-

steam_ugc_send_query

-
This function can be used to send a query request. You first define the query using one of the following function:
-


-

Syntax:

-
steam_ugc_send_query(ugc_query_handle);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_query_handlerealThe query handle to send.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_query"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs, for more details)
cached_databoolWill be true if the returned details are from the local cache or false if they are taken from the server
total_matchingrealThe total number of matching results
num_resultsrealThe number of results returned (max 50)
results_listDS List IDA DS list index, where each list entry is a DS Map index containing details of the particular item (see table below)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
published_file_idint64This key holds the unique published ID for the item (you may need to cast it using the int64 function)
file_typestringThe type of file used
creator_app_idrealThe Steam ID of the item creator
consumer_app_idrealThe Steam ID of the item consumer
titlestringThe title of the item
descriptionstringThe description of the item
steam_id_ownerrealThe Steam ID of the item owner
time_createdrealThe time the item was first created
time_uploadedrealThe last time the item was updated
time_added_to_user_listrealThe time that the item was subscribed to
visibilityconstant.UGCFileVisibilityThe visibility of the item (see UGCFileVisibility constant)
bannedboolWhether the item has been banned or not
accepted_for_useboolWhether the item has been accepted for use or not
tags_truncatedarrayShort version of the tags as an array
tagsarrayAn array of the tags for the item
handle_fileint64The unique file handle for the item
handle_preview_fileint64The unique handle for the image preview for the item (can be used with steam_ugc_download to download a preview image)
filenamestringThe name of the item file
file_sizerealThe size of the item file
preview_file_sizerealThe size of the preview image
urlstringThe full URL for the item
up_votesrealThe number of up-votes received
down_votesrealThe number of down-votes received
scorerealThe overall score of the item
account_id_ownerrealThe account ID from the Steam ID owner (can be used in the function steam_ugc_create_query_user)
-


-

Example:

-
var query_handle = steam_ugc_create_query_all(ugc_query_RankedByTrend, ugc_match_Items, 1);
-
-  steam_ugc_query_add_required_tag(query_handle, "RPG");
-
-  steam_ugc_query_set_return_long_description(query_handle, true);
-
-  steam_ugc_query_set_allow_cached_response(query_handle, true);
-
-  query_ID = steam_ugc_send_query(query_handle);
The above code creates a query request and stores it&#39;s handle in a local variable for future use in the rest of the functions which further define the query request before sending the query.
-
-<!-- KEYWORDS

steam_ugc_send_query ---> -

-
- - -

Back To Top

-

steam_ugc_download

-

With this function you can download a preview image for any given UGC item. The ugc_handle is the unique identifying value for the image (which you can get using the function steam_ugc_send_query), and the destination filename is the name (and local path within the Steam sandbox) that you wish to give the image file when the download is complete. - This is an asynchronous function that will return an asynchronous id and trigger the Steam Async Event when the task is finished.

-


-

Syntax:

-
steam_ugc_download(ugc_handle, dest_filename);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
ugc_handleint64The unique handle for the preview to be downloaded.
dest_filenamestringThe file name to save the preview with.
-


-

Returns:

-
Real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idrealThe asynchronous request ID
event_typestringThe string value "ugc_create_item"
resultrealThis will either be the GML constant ugc_result_success or some other real number (see theSteam docs under EResult , for more details)
original_filenamestringThis key holds the original name of the image file on the server (a string)
dest_filenamestringThis key holds the image file name you passed in (a string)
ugc_handleinteger
-


-

Extended Example:

-

In this example we first call the function and store the async ID value in a variable:

-
steam_get = steam_ugc_download(steam_handle, "\UGC\Preview_file.png");

This would then send off a file request to the Steam API, generating an async event which we would deal with as follows:

-
var event_id = async_load[? "id"];
-if event_id == steam_get
-{
-    var type = async_load[? "event_type"];
-    if type == "ugc_download"
-    {
-        sprite_delete(preview_sprite);
-        preview_sprite = sprite_add(async_load[? "dest_filename"], 0, false, false, 0, 0);
-    }
-}

The above code checks the event type and then creates a sprite from the downloaded image.

- - -



-
- -

Back To Top

-

UGCFileType

-

These constants specify the way that a shared file will be shared with the community and should be used while creating a new item with steam_ugc_create_item.

-
-

ℹ️ NOTE

-

See Steam Docs for more details.

-
- - - - - - - - - - - - - - - - - -
UGC File Type ConstantDescription
ugc_filetype_communityThis is used to create files that will be uploaded and made available to anyone in the community
ugc_filetype_microtransThis is used to describe files that are uploaded but intended only for the game to consider adding as official content
-



-
- -

Back To Top

-

UGCFileVisibility

-

These constants specify possible visibility states that a Workshop item can be in. They are used with the function steam_ugc_set_item_visibility and are an async callback parameter for the functions steam_ugc_request_item_details and steam_ugc_send_query.

-
-

ℹ️ NOTE

-

See Steam Docs for more details.

-
- - - - - - - - - - - - - - - - - - - - - -
UGC File Visibility ConstantDescription
ugc_visibility_publicSet the item to be publicly visible
ugc_visibility_friends_onlySet the item to be visible to only people on the users friends list
ugc_visibility_privateSet the item to be private
-



-
- -

Back To Top

-

UGCListSortOrder

-

These constants specify the sorting order of user published UGC lists from queries created using one of the following functions:

- -
-

ℹ️ NOTE

-

See Steam UGC Docs for more details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UGC List Sort Order ConstantDescription
ugc_sortorder_CreationOrderDescReturns items by creation date. Descending - the newest items are first
ugc_sortorder_CreationOrderAscReturns items by creation date. Ascending - the oldest items are first
ugc_sortorder_TitleAscReturns items by name
ugc_sortorder_LastUpdatedDescReturns the most recently updated items first
ugc_sortorder_SubscriptionDateDescReturns the most recently subscribed items first
ugc_sortorder_VoteScoreDescReturns the items with the more recent score updates first
ugc_sortorder_ForModerationReturns the items that have been reported for moderation
-



-
- -

Back To Top

-

UGCListType

-

These constants specify the type of published UGC list to obtain from queries created using one of the following functions:

- -
-

ℹ️ NOTE

-

See Steam UGC Docs for more details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UGC List Type ConstantDescription
ugc_list_PublishedList of files the user has published
ugc_list_VotedOnList of files the user has voted on. Includes both VotedUp and VotedDown
ugc_list_VotedUpList of files the user has voted up (restricted to the current user only)
ugc_list_VotedDownList of files the user has voted down (restricted to the current user only)
ugc_list_WillVoteLater⚠️ DEPRECATED
ugc_list_FavoritedList of files the user has favorited
ugc_list_SubscribedList of files the user has subscribed to (restricted to the current user only)
ugc_list_UsedOrPlayedList of files the user has spent time in game with
ugc_list_FollowedList of files the user is following updates for
-



-
- -

Back To Top

-

UGCMatchType

-

These constants specify the types of UGC to obtain from queries created using one of the following function:

- -
-

ℹ️ NOTE

-

See Steam UGC Docs for more details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UGC Match Type ConstantDescription
ugc_match_ItemsBoth microtransaction items and Ready-to-use items
ugc_match_Items_MtxMicrotransaction items
ugc_match_Items_ReadyToUseRegular in game items that players have uploaded
ugc_match_CollectionsShared collections of UGC
ugc_match_ArtworkArtwork which has been shared
ugc_match_VideosVideos which have been shared
ugc_match_ScreenshotsScreenshots which have been shared
ugc_match_AllGuidesBoth web guides and integrated guides
ugc_match_WebGuidesGuides that are only available on the steam community
ugc_match_IntegratedGuidesGuides that you can use within your game (like Dota 2's in game character guides)
ugc_match_UsableInGameReady-to-use items and integrated guides
ugc_match_ControllerBindingsController Bindings which have been shared
-



-
- -

Back To Top

-

UGCQueryType (Sorting & Filtering)

-

These constants specify the sorting and filtering for queries across all available UGC, and are to be used with the following functions:

- -
-

ℹ️ NOTE

-

See Steam UGC Docs for more details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UGC Query Type ConstantDescription
ugc_query_RankedByVoteSort by vote popularity all-time
ugc_query_RankedByPublicationDateSort by publication date descending
ugc_query_AcceptedForGameRankedByAcceptanceDateSort by date accepted (for mtx items)
ugc_query_RankedByTrendSort by vote popularity within the given "trend" period (set in steam_ugc_query_set_ranked_by_trend_days)
ugc_query_FavoritedByFriendsRankedByPublicationDateFilter to items the user's friends have favorited, sorted by publication date descending
ugc_query_CreatedByFriendsRankedByPublicationDateFilter to items created by friends, sorted by publication date descending
ugc_query_RankedByNumTimesReportedSort by report weight descending
ugc_query_CreatedByFollowedUsersRankedByPublicationDateFilter to items created by users that the current user has followed, sorted by publication date descending
ugc_query_NotYetRatedFiltered to the user's voting queue
ugc_query_RankedByTotalVotesAscSort by total # of votes ascending (used internally for building the user's voting queue)
ugc_query_RankedByVotesUpSort by number of votes up descending. Will use the "trend" period if specified (set in steam_ugc_query_set_ranked_by_trend_days)
ugc_query_RankedByTextSearchSort by keyword text search relevancy
-



-
-

Social

-

- -

- -

Back To Top

-

Social

-

The following set of functions are used for setting or getting social information.

-

Rich Presence

-

The following functions are provided to work with rich presence:

- -

User & Friends

-

The following functions are provided to work with user and friends data:

- -



-
- - -

Back To Top

-

steam_set_rich_presence

-

Sets a Rich Presence key/value for the current user that is automatically shared to all friends playing the same game.

-


-

Syntax:

-
steam_set_rich_presence(key, value);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
keystringThe rich presence 'key' to set
valuestringThe rich presence 'value' to associate
-


-

Returns:

-
N/A


-

Example:

-
steam_set_rich_presence("game", "MyAwesomeGame");
-steam_set_rich_presence("level", "Last");
-steam_set_rich_presence("Mood","Happy");
-
-steam_clear_rich_presence();
-

The code sample above uses sets a couple values for the local user rich presence and after that clears this values (using a call to the steam_clear_rich_presence function) meaning those will no longer show.

- - -



-
- - -

Back To Top

-

steam_set_rich_presence

-

Clears all of the current user's Rich Presence key/values.

-


-

Syntax:

-
steam_clear_rich_presence()


-

Returns:

-
N/A


-

Example:

-
steam_set_rich_presence("game", "MyAwesomeGame");
-steam_set_rich_presence("level", "Last");
-steam_set_rich_presence("Mood","Happy");
-
-steam_clear_rich_presence();
-

The code sample above uses steam_set_rich_presence to set a couple values for the local user rich presence and after that clears this values meaning those will no longer show.

- - -



-
- - -

Back To Top

-

steam_user_set_played_with

-

Adds the given user to the "recently played with" list (accessed via "Players" - "Recent games") menu in Steam overlay. - This is usually something to do on session start for all remote users.

-


-

Syntax:

-
steam_user_set_played_with(user_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
user_idint64Other player user id
-


-

Returns:

-
Bool


-

Example:

-
steam_user_set_played_with(anyFriendUserID)

This code will add the specified user id to the "recently played with" list, of the local user.

- - -



-
- - -

Back To Top

-

steam_get_friends_game_info

-

Returns an array of information about what the current user's Steam friends are playing. - Equivalent to what can be seen in Steam Friends UI.

-


-

Syntax:

-
steam_get_friends_game_info();


-

Returns:

-
array of structs
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
friendIdint64The Steam user id
gameIdrealThe Steam game id
lobbyIdint64The Steam lobby id (if hosting a lobby that is open for friends to join - otherwise 0)
namestringThe friend's user name
-


-

Example:

-
var info_arr = steam_get_friends_game_info();
-var info_num = array_length(info_arr);
-var _steam_app_id = steam_get_app_id();
-for (var i = 0; i < info_num; i++)
-{
-    var info = info_arr[i];
-    // same game!
-    if (info.gameId == _steam_app_id)
-    {
-        var lobby_id = info.lobbyId;
-        // has an open lobby!
-        if (lobby_id != 0)
-        {
-            var user_id = info.friendId;
-            var name = info.name;
-            // Use steam_lobby_join_id(lobby_id) to join the lobby when asked
-        }
-    }
-}

The above code will check all you friends to see if anyone of them is playing the same game as you are (steam_get_app_id) and check if they have an open lobbies and if so we can request to join the lobby they are in using steam_lobby_join_id.

- - -



-
- - -

Back To Top

-

steam_get_user_avatar

-

Fetches an avatar for the specified user ID. - Returns 0 if no avatar is set for the user;
- Returns -1 if the request is pending, in which case an Steam Async Event will be triggered. - Returns positive IDs if the avatar is ready, this id is to be used with the following function:

- -


-

Syntax:

-
steam_get_user_avatar(userID, avatar_size);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
userIDint64The user Steam unique identifier
avatar_sizeAvatarSizeThe size of the avatar to be requested
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "avatar_image_loaded"
successboolWhether the async action succeeded
user_idint64The associated user's ID
imagerealThe image ID that would otherwise be returned by the function
widthrealThe image width, in pixels
heightrealThe image height, in pixels **
-


-

Example:

-
var l_img = steam_get_user_avatar(steam_get_user_steam_id(), steam_user_avatar_size_large);
-
-// Check if avatar is ready
-if (l_img > 0)
-{
-    var l_dims = steam_image_get_size(l_img);
-    var buff_size = l_dims[0] * l_dims[1] * 4
-
-    var l_cols = buffer_create(buff_size, buffer_fixed, 1);
-
-    l_ok = steam_image_get_rgba(l_img, l_cols, buff_size);
-
-    if(!l_ok)
-    {
-        buffer_delete(l_cols);
-    }
-
-    var l_surf = surface_create(l_dims[0], l_dims[1]);
-    buffer_set_surface(l_cols, l_surf, 0);
-
-    l_sprite = sprite_create_from_surface(l_surf, 0, 0, l_dims[0], l_dims[1], false, false, 0, 0);
-
-    surface_free(l_surf);
-    buffer_delete(l_cols);
-}
-

In the code above we query for the current user's (steam_get_user_steam_id) avatar, this function this function will either return:

-
    -
  • the handle to the function (return value greater than zero): in this case we follow by getting size information (steam_image_get_size), creating a buffer and and getting the avatar image RBGA data into the buffer (steam_image_get_rgba) and lastely creating a sprite from said buffer.
  • -
  • no handle at all (return value equal to zero): in this case there is no avatar image for the specified used.
  • -
  • a value of -1: in this last case it measn that the request is pending and you can catch the output with a Steam Async Event, using the following code:
  • -
-
// Early exit if event type doesn't match
-if (async_load[?"event_type"] != "avatar_image_loaded") exit
-
-// Validate status
-var success = async_load[?"success"];
-if (success == 1) {
-
-    // Do what you want with the provided image handle
-}
-else {
-    // Failure
-    show_debug_message("Failed to get user avatar");
-}
-
- -



-
- - -

Back To Top

-

steam_image_get_size

-

Fetches dimensions for the said Steam image ID. - If the call succeeds, the return value is a two-element array containing width and height in pixels.

-


-

Syntax:

-
steam_image_get_size(steam_image_id);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
steam_image_idint64steam identifier of the image
-


-

Returns:

-
array


-

Example:

-
var l_img = steam_get_user_avatar(steam_get_user_steam_id(), steam_user_avatar_size_large);
-var l_dims = steam_image_get_size(l_img);
-var buff_size = l_dims[0] * l_dims[1] * 4
-var l_cols = buffer_create(buff_size, buffer_fixed, 1);
-l_ok = steam_image_get_rgba(l_img, l_cols, buff_size);
-if(!l_ok)
-    exit
-var l_surf = surface_create(l_dims[0], l_dims[1]);
-buffer_set_surface(l_cols, l_surf, 0);
-l_sprite = sprite_create_from_surface(l_surf, 0, 0, l_dims[0], l_dims[1], false, false, 0, 0);
-surface_free(l_surf);
-buffer_delete(l_cols);

The above code will show a code example.

- - -



-
- - -

Back To Top

-

steam_image_get_rgba

-

Grabs RGBA data of the specified Steam image ID into a GameMaker buffer. - Returns whether successful.

-
-

ℹ️ NOTE

-

The buffer should be appropriately sized in accordance with steam_image_get_size (width height 4).

-
-


-

Syntax:

-
steam_image_get_rgba(steam_image_id, buffer, size);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
steam_image_idint64The steam image identifier
bufferbufferThe buffer where data will be written
sizerealThe size of the buffer supplied
-


-

Returns:

-
Boolean


-

Example:

-
var l_img = steam_get_user_avatar(steam_get_user_steam_id(), steam_user_avatar_size_large);
-
-// Check if avatar is ready
-if (l_img > 0)
-{
-    var l_dims = steam_image_get_size(l_img);
-    var buff_size = l_dims[0] * l_dims[1] * 4
-
-    var l_cols = buffer_create(buff_size, buffer_fixed, 1);
-
-    l_ok = steam_image_get_rgba(l_img, l_cols, buff_size);
-
-    if(!l_ok)
-    {
-        buffer_delete(l_cols);
-    }
-
-    var l_surf = surface_create(l_dims[0], l_dims[1]);
-    buffer_set_surface(l_cols, l_surf, 0);
-
-    l_sprite = sprite_create_from_surface(l_surf, 0, 0, l_dims[0], l_dims[1], false, false, 0, 0);
-
-    surface_free(l_surf);
-    buffer_delete(l_cols);
-}
-

In the code above we query for the current user's (steam_get_user_steam_id) avatar data and place it inside a buffer (with the RGBA color format). - For a more extensive example refer to the steam_get_user_avatar function.

- - -



-
- -

Back To Top

-

steam_image_get_bgra

-

Grabs BGRA data of the specified Steam image ID into a GameMaker buffer. - Returns whether successful.

-
-

ℹ️ NOTE

-

The buffer should be appropriately sized in accordance with steam_image_get_size (width height 4).

-
-


-

Syntax:

-
steam_image_get_bgra(steam_image_id, buffer, size);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
steam_image_idint64The steam image identifier
bufferbuffer IDThe buffer where data will be written
sizerealThe size of the buffer supplied
-


-

Returns:

-
Boolean


-

Example:

-
var l_img = steam_get_user_avatar(steam_get_user_steam_id(), steam_user_avatar_size_large);
-
-// Check if avatar is ready
-if (l_img > 0)
-{
-    var l_dims = steam_image_get_size(l_img);
-    var buff_size = l_dims[0] * l_dims[1] * 4
-
-    var l_cols = buffer_create(buff_size, buffer_fixed, 1);
-
-    l_ok = steam_image_get_bgra(l_img, l_cols, buff_size);
-
-    if(!l_ok)
-    {
-        buffer_delete(l_cols);
-    }
-
-    var l_surf = surface_create(l_dims[0], l_dims[1]);
-    buffer_set_surface(l_cols, l_surf, 0);
-
-    l_sprite = sprite_create_from_surface(l_surf, 0, 0, l_dims[0], l_dims[1], false, false, 0, 0);
-
-    surface_free(l_surf);
-    buffer_delete(l_cols);
-}
-

In the code above we query for the current user's (steam_get_user_steam_id) avatar data and place it inside a buffer (with the BGRA color format). - For a more extensive example refer to the steam_get_user_avatar function.

-



-
-

Inventory

-

- - -

Back To Top

-

Inventory

-

The following functions, constants and structures allow to use the Steam Inventory Service.

-

Pricing and Consumables

-

These functions are provided for handling pricing, purchases and consumables:

- -

Inventory Management (Async Result)

-

These asynchronous functions will return a inventory result handle that can be used to get additional information (see section below):

- -

Inventory Result Information

-

These functions can be called with the inventory result handle (from previous section) to get additional information:

- -

Dynamic Properties

-

This set of functions can be used to author items dynamic properties:

- -

Constants

-

These are the constants used by this API:

- -

Structures

-

These are the structures used by this API:

- -



-
- -

Back To Top

-

steam_inventory_consume_item

-

Consumes items from a user's inventory. If the quantity of the given item goes to zero, it is permanently removed. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around ConsumeItem.

-
-


-

Syntax:

-
steam_inventory_consume_item(item_id, quantity);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
item_idint64The steam_inventory_item_id to consume.
quantityrealThe number of items in that stack to consume.
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
steam_inventory_consume_item(player.apple, 1);

The code sample above will try to consume one item (apple, steam_inventory_item_id), and trigger an async event with the task result.

-



-
- -

Back To Top

-

steam_inventory_get_item_price

-

After a successful call to steam_inventory_request_prices, you can call this method to get the pricing for a specific item definition.

-
-

✴️ EXTERNAL

-

A wrapper around GetItemPrice.

-
-


-

Syntax:

-
steam_inventory_get_item_price(item);
- - - - - - - - - - - - - - -
ArgumentkindDescription
itemrealThe steam_inventory_item_def to get the price of.
-


-

Returns:

-
int64


-

Example:

-
var price = steam_inventory_get_item_price(item);

The code sample above will return you the price for the speficied item definition. For more detailed example on using the function check steam_inventory_request_prices

-



-
- -

Back To Top

-

steam_inventory_get_items_with_prices

-

After a successful call to steam_inventory_request_prices, you can call this method to get all the prices for applicable item definitions.

-
-

✴️ EXTERNAL

-

A wrapper around GetItemsWithPrices.

-
-


-

Syntax:

-
steam_inventory_get_items_with_prices();


-

Returns:

-
array of structs
- - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item_defrealThe steam_inventory_item_def representing the item type
priceint64The price of the item definition
base_priceint64The base price of the item definition ✴️ WINDOWS ONLY
-


-

Example:

-
var array = steam_inventory_get_items_with_prices(inv_result);
-if(array_length(array) > 0)
-{
-    var item_def = array[0].item_def
-    var price = array[0].price
-    var base_price = array[0].base_price
-    show_debug_message("Found at one item that costs: " + string(price));
-}

The code above will get items with prices and if the returning array size is greater than zero (meaning there is at least one item with a configured price) it prints to the console the item's price.

-



-
- -

Back To Top

-

steam_inventory_request_eligible_promo_item_defs

-

Requests the list of "eligible" promo items that can be manually granted to the given user. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

✴️ EXTERNAL

-

A wrapper around RequestEligiblePromoItemDefinitionsIDs.

-
-


-

Syntax:

-
steam_inventory_request_eligible_promo_item_defs(user_id);
- - - - - - - - - - - - -
ArgumentDescription
user_idThe user ID of the user to request the eligible promo items for.
-


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_request_eligible_promo_item_defs"
user_idint64The user's unique identifier
item_def_countrealThe number of items
item_def_jsonstringA json array of items identifiers (must be parsed using json_parse or json_decode)
is_cached_databoolWhether the data was retrieved from the cache and not from the server
-


-

Example:

-
steam_inventory_request_eligible_promo_item_defs(user_id)

For more information on this function call please refer to the official manual.

-



-
- -

Back To Top

-

steam_inventory_request_prices

-

Request prices for all item definitions that can be purchased in the user's local currency.

-

This is an asynchronous function that will trigger the Steam Async Event when the task is finished, after which you can use the following functions:

- -
-

✴️ EXTERNAL

-

A wrapper around RequestPrices.

-
-


-

Syntax:

-
steam_inventory_request_prices();


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_request_prices"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
currencystringThe string representing the user's local currency code.
-


-

Example:

-
steam_inventory_request_prices();

The code above will request for price information. The result for this task can be caught inside the Steam Async Event with the following code:

-
// Early exit if event type doesn't match
-if (async_load[? "event_type"] != "inventory_request_prices") exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "success"])
-{
-    show_debug_message("The currenct being used is: " + async_load[? "currency"]);
-
-    var price = steam_inventory_get_item_price(global.swordId);
-}
-

The code above matches the event type and if so shows the currency being used. It also gets the price for a specific item using the steam_inventory_get_item_price function.

-



-
- -

Back To Top

-

steam_inventory_start_purchase

-

Starts the purchase process for the user, given a "shopping cart" of item definitions that the user would like to buy. - The user will be prompted in the Steam Overlay to complete the purchase in their local currency, funding their Steam Wallet if necessary, etc.

-
-

✴️ EXTERNAL

-

A wrapper around StartPurchase.

-
-


-

Syntax:

-
steam_inventory_start_purchase(array);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
arrayarray<InventoryItemCreationData>An array of structs representing items to be purchased (see InventoryItemCreationData)
-


-

Returns:

-
N/A


-

Example:

-
var arrayCreate = [
-              {item_def: item1, quantity: 3},
-              {item_def: item2, quantity: 5},
-       ]
-
-steam_inventory_start_purchase()
-

The code above will initialize a purchase intent that will be finalized in the Steam Overlay.

-



-
- -

Back To Top

-

steam_inventory_add_promo_item

-

Take an Item Definition and grants the user the promo item. Item Definitions are integer numbers ranging from 1 to 999999999. Values below the range are invalid and values above the range are reserved. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around AddPromoItem.

-
-


-

Syntax:

-
steam_inventory_add_promo_item(item_def)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
item_defint64The steam_inventory_item_def to grant the player (number between 1 and 999999999)
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
steam_inventory_add_promo_item(item)

The above code will grant the user with a specific item. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_add_promo_items

-

Takes an array of Item Definitions and grants the user multiple items. Item Definitions are integer numbers ranging from 1 to 999999999. Values below the range are invalid and values above the range are reserved. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around AddPromoItems.

-
-


-

Syntax:

-
steam_inventory_add_promo_items(item_defs)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
item_defsarrayAn array of steam_inventory_item_def to grant the user with.
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
steam_inventory_add_promo_items([item1,item2,item3])

The above code will grant the user with an multiple items specified in an array format. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_exchange_items

-

Grants one item in exchange for a set of other items. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around ExchangeItems.

-
-


-

Syntax:

-
steam_inventory_exchange_items(create_arr, destroy_arr);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
create_arrarray<InventoryItemCreationData>An array of structs representing items to be created (see InventoryItemCreationData)
destroy_arrarray<InventoryItemConsumptionData>An array of structs representing items to be consumed (see InventoryItemConsumptionData)
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
var arrayDestroy = [
-    { item_id: player.cursed_sword, quantity: 1 },
-    { item_id: player.apple, quantity: 7 },
-];
-
-var arrayCreate = [
-    { item_def: global.holy_sword, quantity: 1 },
-    { item_def: global.orange, quantity: 2 }
-];
-
-steam_inventory_exchange_items(arrayCreate, arrayDestroy);
-

Given the provided items to be destroyed and the items to be create the code above will perform an exchange removing the current items (arrayDestroy) from the inventory and adding the new (arrayCreate) in their place. The result for this task can be caught inside the Steam Async Event with the following code:

-
// Early exit if event type doesn't match
-if (async_load[? "event_type"] != "inventory_result_ready") exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "handle"] != handle) exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "success"])
-{
-    show_debug_message("Exchange was a success");
-}
-else 
-{
-    show_debug_message("Exchange failed");
-}
-
-// Don't forget to clean the ununsed handle
-steam_inventory_result_destroy(handle);
-handle = undefined;
-

The code above matches the event type and checks if the handle id matches the one that initialized the request and if so we print a debug message with the success of the task. In the end we also use a call to steam_inventory_result_destroy to make sure we dispose and free all the used memory.

-



-
- -

Back To Top

-

steam_inventory_generate_items

-

Generates specific items for the current user. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

ℹ️ NOTE

-

This is only usable by Steam accounts that belong to the publisher group for your game.

-
-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around GenerateItems.

-
-


-

Syntax:

-
steam_inventory_generate_items(create_arr);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
create_arrarray<InventoryItemCreationData>An array of structs representing items to be created (see InventoryItemCreationData)
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
var arrayCreate = [
-    {item_def: item1, quantity: 3},
-    {item_def: item2, quantity: 5},
-];
-
-steam_inventory_generate_items(arrayCreate)
-

The code above will grant the specific items to the current user. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_get_all_items

-

Starts retrieving all items in the current user's inventory. - This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetAllItems.

-
-


-

Syntax:

-
steam_inventory_get_all_items();


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-
-

✴️ OPTIONAL

-

The asynchronous event presented below is only triggered when the result is newer/fresher than the last known result. It will not trigger if the inventory hasn't changed, or if results from two overlapping calls are reversed in flight and the earlier result is already known to be stale/out-of-date. The regular callback will still be triggered immediately afterwards; this is an additional notification for your convenience.

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_full_update"
successboolWhether the async action succeeded
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
handle = steam_inventory_get_all_items();

The code above will start a query for all the items in current users inventory. The result for this task can be caught inside the Steam Async Event with the following code:

-
// Early exit if event type doesn't match
-if (async_load[? "event_type"] != "inventory_result_ready") exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "handle"] != handle) exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "success"])
-{
-    var items = steam_inventory_result_get_items(handle);
-
-    for (var i = 0; i < array_length(items); i++)
-    {
-        var item = items[i];
-        // access item data for each entry
-        //
-        // item.item_id
-        // item.item_def
-        // item.quantity
-        // item.flags
-    }
-}
-
-// Don't forget to clean the ununsed handle
-steam_inventory_result_destroy(handle);
-handle = undefined;
-

The code above matches the event type and checks if the handle id matches the one that initialized the request and if so gets the items from the result using the function steam_inventory_result_get_items and loops through them. In the end we also use a call to steam_inventory_result_destroy to make sure we dispose and free all the used memory.

-



-
- -

Back To Top

-

steam_inventory_get_items_by_id

-

Requests information about a subset of the current user's inventory.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetItemsByID.

-
-


-

Syntax:

-
steam_inventory_get_items_by_id(item_ids);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
item_idsarrayAn array of steam_inventory_item_id of items to get information of.
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
handle = steam_inventory_get_items_by_id([item1, item2])

Similar to steam_inventory_get_all_items but you can specify an array of items to query information instead of querying all of them. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_submit_update_properties

-

Submits the transaction request to modify dynamic properties on items for the current user. See StartUpdateProperties.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around SubmitUpdateProperties.

-
-


-

Syntax:

-
steam_inventory_submit_update_properties(handle);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle corresponding to the transaction request
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
var handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handle, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then multiple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_transfer_item_quantity

-

Transfer items between stacks within a user's inventory.

-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around TransferItemQuantity.

-
-


-

Syntax:

-
steam_inventory_transfer_item_quantity(source_item_id, quantity, dest_item_id);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
source_item_idint64The source steam_inventory_item_id to transfer from
quantityrealThe quantity of the item that will be transferred
dest_item_idint64The destination steam_inventory_item_id to transfer to
-


-

Returns:

-
real


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
handle = steam_inventory_transfer_item_quantity(global.apple, 2, global.oranges);

The above code will trigger a transfer between to items owned by the used the amount to be transferred in the example, the user will lose 2 apples and receive 2 oranges. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_trigger_item_drop

-

Trigger an item drop if the user has played a long enough period of time.
-
- This period can be customized in two places:

-
    -
  • At the application level within Inventory Service: Playtime Item Grants. This will automatically apply to all "playtimegenerator" items that do not specify any overrides.
  • -
  • In an individual "playtimegenerator" item definition. The settings would take precedence over any application-level settings.

    -


    - Only item definitions which are marked as "playtime item generators" can be spawned.

    -

    This is an asynchronous function that will trigger the Steam Async Event when the task is finished.

    -
  • -
-
-

⚠️ IMPORTANT

-

You must call steam_inventory_result_destroy on the returned async result ID when you are done with it.

-
-
-

✴️ EXTERNAL

-

A wrapper around TriggerItemDrop.

-
-


-

Syntax:

-
steam_inventory_trigger_item_drop(item_def);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
item_defrealThis must refer to an item definition of the type "playtimegenerator". See the inventory schema for more details.
-


-

Returns:

-
bool


-

Triggers:

-
Asynchronous Steam Event
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
event_typestringThe string value "inventory_result_ready"
successboolWhether the async action succeeded
resultInventoryResultStatusThe status code as returned by steam_inventory_result_get_status
handlerealThe associated async result ID, which can be used to tell apart what result this event is for.
-


-

Example:

-
handle = steam_inventory_trigger_item_drop(item_def)

For more information on this function call please refer to the official manual. For an example on how to use the Steam Async Event to read the callback response, refer to the function steam_inventory_get_all_items.

-



-
- -

Back To Top

-

steam_inventory_result_destroy

-

Destroys a result handle and frees all associated memory. - This handle is returned by the following functions:

- -
-

ℹ️ NOTE

-

This function can be called using an inventory result handle after the corresponding async event has been triggered.

-
-
-

✴️ EXTERNAL

-

A wrapper around DestroyResult.

-
-


-

Syntax:

-
steam_inventory_result_destroy(inv_result);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
inv_resultrealThe inventory result handle to destroy
-


-

Returns:

-
bool


-

Example:

-
// Early exit if event type doesn't match
-if (async_load[? "event_type"] != "inventory_result_ready") exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "handle"] != handle) exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "success"])
-{
-    show_debug_message("Exchange was a success");
-}
-else 
-{
-    show_debug_message("Exchange failed");
-}
-
-// Don't forget to clean the ununsed handle
-steam_inventory_result_destroy(handle);
-handle = undefined;
-

In the code above we have an example of a asynchronous callback that generates a result handle by the end of which we execute a call to steam_inventory_result_destroy to make sure we dispose and free all the used memory.

-



-
- -

Back To Top

-

steam_inventory_result_get_item_property

-

Gets the dynamic properties from an item in an inventory result set. - Property names are always composed of ASCII letters, numbers, and/or underscores.

-
-

ℹ️ NOTE

-

This function can be called using an inventory result handle after the corresponding async event has been triggered.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetResultItemProperty.

-
-


-

Syntax:

-
steam_inventory_result_get_item_property(inv_result, item_index, prop_name);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
inv_resultrealThe inventory result handle
item_indexrealPosition of the item in the result set
prop_namestringThe property name to get the value for
-


-

Returns:

-
string


-

Example:

-
handle = steam_inventory_get_all_items();

The code above will start a query for all the items in current users inventory. The result for this task can be caught inside the Steam Async Event with the following code:

-
// Early exit if event type doesn't match
-if (async_load[? "event_type"] != "inventory_result_ready") exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "handle"] != handle) exit;
-
-// Early exit if handle doesn't match
-if (async_load[? "success"])
-{
-    var items = steam_inventory_result_get_items(handle);
-
-    var status = steam_inventory_result_get_status(handle);
-    var timestamp = steam_inventory_result_get_unix_timestamp(handle);
-
-    for (var i = 0; i < array_length(items); i++)
-    {      
-        // It's also possible to get properties from each item using 
-        // prop1 = steam_inventory_result_get_item_property(handle, i, "property_name1")
-        // prop2 = steam_inventory_result_get_item_property(handle, i, "property_name2")
-    }
-}
-
-// Don't forget to clean the ununsed handle
-steam_inventory_result_destroy(handle);
-handle = undefined;
-

The code above matches the event type and checks if the handle id matches the one that initialized the request and if so gets the items from the result using the function steam_inventory_result_get_items and loops through them to get the item properties we want. In the end we also use a call to steam_inventory_result_destroy to make sure we dispose and free all the used memory.

-



-
- -

Back To Top

-

steam_inventory_result_get_items

-

Get the items associated with an inventory result handle.

-
-

ℹ️ NOTE

-

This function can be called using an inventory result handle after the corresponding async event has been triggered.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetResultItems.

-
-


-

Syntax:

-
steam_inventory_result_get_items(inv_result);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
inv_resultrealThe inventory result handle
-


-

Returns:

-
array of structs
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
item_idrealA representing the item instance
item_defrealA representing the item type
quantityint64How many of the said item there is in the slot
flagsint64This is a bit-masked collection of ESteamItemFlags
-


-

Example:

-
var array = steam_inventory_result_get_items(inv_result);
-for(var i = 0 ; i < array_lenght(array) ; i++)
-{
-     var struct = array[i]
-     var item_id = struct.item_id
-     var item_def = struct.item_def
-     var quantity = struct.quantity
-}

For a more detailed implementation sample please refer to the steam_inventory_get_all_items function.

-



-
- -

Back To Top

-

steam_inventory_result_get_status

-

Returns status code of a result.

-
-

ℹ️ NOTE

-

This function can be called using an inventory result handle after the corresponding async event has been triggered.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetResultStatus.

-
-


-

Syntax:

-
steam_inventory_result_get_status(inv_result);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
inv_resultrealThe inventory result handle
-


-

Returns:

-
InventoryResultStatus


-

Example:

-
-if(steam_inventory_result_get_status(inv_result) != steam_inventory_result_status_ok)
-     exit

For a more detailed implementation sample please refer to the steam_inventory_result_get_item_property function.

-



-
- -

Back To Top

-

steam_inventory_result_get_unix_timestamp

-

Returns a Unix timestamp for the server time at which the result was generated.

-
-

ℹ️ NOTE

-

This function can be called using an inventory result handle after the corresponding async event has been triggered.

-
-
-

✴️ EXTERNAL

-

A wrapper around GetResultTimestamp.

-
-


-

Syntax:

-
steam_inventory_result_get_unix_timestamp(inv_result);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
inv_resultrealThe inventory result handle
-


-

Returns:

-
int64


-

Example:

-
var timestamp = steam_inventory_result_get_unix_timestamp(inv_result);

For a more detailed implementation sample please refer to the steam_inventory_result_get_item_property function.

-



-
- -

Back To Top

-

steam_inventory_start_update_properties

-

Starts a transaction request to update dynamic properties on items for the current user. - Returns a steam_inventory_update_handle that can be used with the following functions:

- -
-

✴️ EXTERNAL

-

A wrapper around StartUpdateProperties.

-
-


-

Syntax:

-
steam_inventory_start_update_properties()


-

Returns:

-
int64


-

Example:

-
handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_remove_property

-

Removes a dynamic property of the given item.

-
-

✴️ EXTERNAL

-

A wrapper around RemoveProperty.

-
-


-

Syntax:

-
steam_inventory_remove_property(handle, item_id, prop_name);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle returned by steam_inventory_start_update_properties
item_idint64The steam_inventory_item_id of the item being modified
prop_namestringThe dynamic property being removed
-


-

Returns:

-
bool


-

Example:

-
var handler = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handler, item_id, "invisible", true)
-steam_inventory_set_property_float(handler, item_id, "power", 123.54)
-steam_inventory_set_property_int(handler, item_id, "uses", 5)
-steam_inventory_set_property_string(handler, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handler, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handler)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_set_property_bool

-

Sets a dynamic property for the boolean given item

-
-

✴️ EXTERNAL

-

A wrapper around SetProperty.

-
-


-

Syntax:

-
steam_inventory_set_property_bool(handle, prop_name, val);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle corresponding to the transaction request
prop_namestringThe dynamic property being added or updated.
valboolvalue being set.
-


-

Returns:

-
bool


-

Example:

-
handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handle, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_set_property_float

-

Sets a dynamic property for the float given item

-
-

✴️ EXTERNAL

-

A wrapper around SetProperty.

-
-


-

Syntax:

-
steam_inventory_set_property_float(handle, prop_name, val);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle corresponding to the transaction request
prop_namestringThe dynamic property being added or updated.
valrealvalue being set.
-


-

Returns:

-
bool


-

Example:

-
handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handle, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_set_property_int

-

Sets a dynamic property for the int given item

-
-

✴️ EXTERNAL

-

A wrapper around SetProperty.

-
-


-

Syntax:

-
steam_inventory_set_property_int(handle, prop_name, val);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle corresponding to the transaction request
prop_namestringThe dynamic property being added or updated.
valrealvalue being set.
-


-

Returns:

-
bool


-

Example:

-
handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handle, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

steam_inventory_result_get_status

-

Sets a dynamic property for the string given item

-
-

✴️ EXTERNAL

-

A wrapper around SetProperty.

-
-


-

Syntax:

-
steam_inventory_set_property_string(handle, prop_name, val);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
handlerealThe update handle corresponding to the transaction request
prop_namestringThe dynamic property being added or updated.
valstringvalue being set.
-


-

Returns:

-
bool


-

Example:

-
var handle = steam_inventory_start_update_properties()
-steam_inventory_set_property_bool(handle, item_id, "invisible", true)
-steam_inventory_set_property_float(handle, item_id, "power", 123.54)
-steam_inventory_set_property_int(handle, item_id, "uses", 5)
-steam_inventory_set_property_string(handle, item_id, "name", "Big Sword")
-...
-steam_inventory_remove_property(handle, item_id, "invisible")
-...
-steam_inventory_submit_update_properties(handle)

The code above provides a simple sample on how to set/removed some properties. - Starting with a steam_inventory_start_update_properties then mutliple calls to set/remove property functions:

- -



-
- -

Back To Top

-

InventoryResultStatus

-

These constants represent the status of an inventory result async event, and are returned by the async events of the following functions:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Inventory Result Status ConstantDescription
steam_inventory_result_status_pendingPending
steam_inventory_result_status_okOk
steam_inventory_result_status_expiredExpired
steam_inventory_result_status_invalidInvalid
steam_inventory_result_status_failFail
steam_inventory_result_status_invalid_paramIinvalid
steam_inventory_result_status_service_unavailableUnavailable
steam_inventory_result_status_limit_exceededExceeded
-


-



-
- -

Back To Top

-

InventoryItemConsumptionData

-

This struct is used as an argument when performing a call to the following functions

- - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
item_idint64A steam_inventory_item_id of an item to be consumed
quantityrealHow much of the said item is to be consumed
-



-
- -

Back To Top

-

InventoryItemCreationData

-

This struct is used as an argument when performing a call to the following functions

- - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
item_defint64A steam_inventory_item_def representing the item type
quantityrealNumber of items of type to be created
-



-
-

Networking

-

- - -

Back To Top

-

Networking

-

The following functions and constants allow you to use Steam's Networking functionality.

-

Packets IO

-

These functions are provided for handling sending and receiving packets:

- -

Session

-

The following functions allow handling P2P sessions:

- -

Constants

-

These are the constants used by this API:

- -



-
- -

Back To Top

-

steam_net_packet_get_data

-

Copies the contents of last received packet to the given buffer. Data is copied to the start of the buffer (position remains unaffected), meaning that if you reuse the same buffer, you should "rewind" it prior to reading.

-
-

ℹ️ NOTE

-

If the buffer is not big enough to fit data, it will be resized automatically (the buffer needs to be created using the using the buffer_grow type).

-
-


-

Syntax:

-
steam_net_packet_get_data(buffer)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
bufferrealThe buffer to write the incoming data to.
-


-

Returns:

-
bool


-

Example:

-
while (steam_net_packet_receive())
-{
-    steam_net_packet_get_data(inbuf);
-    buffer_seek(inbuf, buffer_seek_start, 0);
-    switch (buffer_read(inbuf, buffer_u8))
-    {
-        case 1: show_debug_message("packet ID 1"); break;
-        case 2: show_debug_message("packet ID 2"); break;
-        default: show_debug_message("unknown packet"); break;
-    }
-}

The code above will check for an incoming packet and get its data into a buffer (resizing if necessary) and reads from it.

-



-
- -

Back To Top

-

steam_net_packet_get_sender_id

-

Returns Steam ID of the user that sent the last received packet. - Can be used in conjunction with steam_net_packet_send to send something back and for just telling the senders apart.

-


-

Syntax:

-
steam_net_packet_get_sender_id();


-

Returns:

-
int64


-

Example:

-
while(steam_net_packet_receive())
-{
-    var sender = steam_net_packet_get_sender_id();
-
-    buffer_seek(outbuf, buffer_seek_start, 0);
-    buffer_write(outbuf, buffer_u8, test_network_packet.ping);
-
-    steam_net_packet_send(sender, outbuf);
-}
-

The above code will show a code example.

-



-
- -

Back To Top

-

steam_net_packet_get_size

-

Returns the size of last received packet, in bytes.

-


-

Syntax:

-
steam_net_packet_get_size();


-

Returns:

-
real


-

Example:

-
while (steam_net_packet_receive())
-{
-    var size = steam_net_packet_size();
-    show_debug_message("Received " + string(size) + " bytes.");
-}

The code above will display the size of each incoming packet.

-



-
- -

Back To Top

-

steam_net_packet_receive

-

Attempts to get the next packet from Steam API and returns whether successfully done so. - Other steam_net_ functions can then be used to get packet information/contents.

-


-

Syntax:

-
steam_net_packet_receive();


-

Returns:

-
bool


-

Example:

-
while (steam_net_packet_receive())
-{
-    // process the received packet
-}

The code above will attempt to get the next packet from Steam API, would be used every step while in lobby or with less frequency otherwise.

-



-
- -

Back To Top

-

steam_net_packet_send

-

Sends a packet to the given endpoint, returns whether successful (as opposed to incorrect arguments/invalid ID). If no packet type is passed in then default value will be used, the default value can be set using the steam_net_packet_set_type function. Returns whether or not the packet was successfully sent.

-


-

Syntax:

-
steam_net_packet_send(user_id, buffer, size, packet_type)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
user_idint64The target user to send the packet to
bufferrealBuffer that contains the raw byte array for the packet data to send
sizerealThe size of data to send (default -1, sends the entire buffer) ✴️ OPTIONAL
packet_typePacketTypeThe type of packet to be used ✴️ OPTIONAL
-


-

Returns:

-
bool


-

Example:

-
var buf = buffer_create(16, buffer_grow, 1);
-buffer_write(buf, buffer_string, "Hello!");
-steam_net_packet_send(steam_id, buf, -1);
-buffer_delete(buff);

The code sample will create a buffer and write to it, sending the total length of it to the given steam_id, the buffer is then deleted.

-



-
- -

Back To Top

-

steam_net_packet_set_type

-

Set the default connection protocol used when sending the data packets (using the steam_net_packet_send function). Returns whether or not the default protocol was successfully set.

-


-

Syntax:

-
steam_net_packet_set_type(protocol);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
protocolPacketTypeThe default connection protocol to be used
-


-

Returns:

-
bool


-

Example:

-
steam_net_packet_set_type(steam_net_packet_type_reliable)

The above code will set the current connection to use the steam_net_packet_type_reliable protocol to send data packages.

-



-
- -

Back To Top

-

steam_net_accept_p2p_session

-

Accepts a P2P session request from the specified user. Returns whether successful or not.

-


-

Syntax:

-
steam_net_accept_p2p_session(userID);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
userIDint64The User ID of the user that sent the initial packet to us.
-


-

Returns:

-
bool


-

Example:

-
if (isMyFriend(userID))
-{
-    steam_net_accept_p2p_session(userID);
-}

The code above uses a custom implemented function that will check if a given userID is a friend and if it is it will accept the P2P session.

-



-
- -

Back To Top

-

steam_net_close_p2p_session

-

Closes a P2P session with the specified user. Returns whether successful or not. - Steam will automatically close sessions after a period of inactivity, but you could also do it manually if you so desired.

-


-

Syntax:

-
steam_net_close_p2p_session(user_id)
- - - - - - - - - - - - - - -
ArgumentTypeDescription
user_idint64The user ID of the user to close the connection with.
-


-

Returns:

-
bool


-

Example:

-
if (global.chat_closed)
-{
-     steam_net_close_p2p_session(user_id)
-}

The code above check to see if a global variable (chat_closed) is true and if so, it will close the P2P session.

-



-
- -

Back To Top

-

steam_net_set_auto_accept_p2p_sessions

-

Sets whether to auto-accept session requests coming from players in the same lobby. This is enabled by default for convenience. If you disable it, you will need to handle the async event when someone uses the steam_lobby_join_id function.

-


-

Syntax:

-
steam_net_set_auto_accept_p2p_sessions(enable);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
enablebooldisable/enable auto accept sessions
-


-

Returns:

-
N/A


-

Triggers:

-
Asynchronous Steam Event (for each request, if disabled)
- - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
typestringThe string value "lobby_join_requested"
lobby_idint64The lobby unique identifier
friend_idint64The friend unique identifier
-


-

Example:

-
steam_net_set_auto_accept_p2p_sessions(false);

The code above will disable the auto accept P2P sessions functionality meaning we should deal with the requests manually. In order to do so we need to use the Steam Async Event to catch the callback:

-
if (async_load[?"event_type"] == "lobby_join_requested")
-{
-    steam_net_accept_p2p_session(async_load[?"friend_id"]);
-}



-
- -

Back To Top

-

PacketType

-

These constants specify the type of a steam packet and should be used with the function steam_net_packet_set_type.

- - - - - - - - - - - - - - - - - - - - - - - - - -
Packet Type ConstantDescription
steam_net_packet_type_unreliableEquivalent to UDP the data may or may not be delivered, will not be resent automatically.
steam_net_packet_type_unreliable_nodelaySimilar to "unreliable" type, but always sent instantly (as soon as function is called). Intended for things like streaming voice data, where you want lowest latency possible and only care about the current data.
steam_net_packet_type_reliableEquivalent to TCP, the data is warranted to be delivered in order and intact.
steam_net_packet_type_reliable_bufferSimilar to "reliable" type, but utilizes Nagle's algorithm to reduce the number of packets at cost of potential delay while the data accumulates until the sending threshold.
-



-
-

Steam Input

-

- -

- -

Back To Top

-

Input

-

The Steam Input API is designed to allow you to easily enable full support for Steam Input devices in your game. This means things such as:

-
    -
  • Ability to use proper controller-specific glyphs for input hints.
  • -
  • Allow the user to easily rebind controls however they like via the Steam Input Configurator.
  • -
  • Share input mappings with others via the Steam Workshop.
  • -
  • and many more!

    -


    -

    Before proceeding, please read this page about the Steam Input API for developers before reading this page to have a good understanding of what are Input Handles, Action Sets, Action Set Layers, Digital Actions, Analog Actions, Action Origins, the Steam Input Configurator, and bindings.

    -
  • -
-
-

ℹ️ NOTE

-

This API is designed for advanced users only, if you don't know why you need it, please use the native GML gamepad_ functions instead.

-
-

The following functions can be used to access the Steam Input from within GameMaker Studio 2

- -



-
- - -

Back To Top

-

steam_input_init

-

With this function you can initialize the Steam Input API. It will return true if initialization was successful and false otherwise. If argument explicitly_call_run_frame is true, then you must manually call steam_input_run_frame to poll for input data and async events, otherwise that will be performed by the steam_update function. After you initialize the Steam Input API, configuration events will be dispatched for any controllers connected while your game is running, they can be used to detect gamepad connection and when bindings have been updated so you need to refresh the sprites, input hints, etc.

-
-

⚠️ IMPORTANT

-

This function must be called ONLY if you REALLY wish to use the Steam Input API, or some other extensions in your project rely on Steam Input, otherwise calling it may make native GameMaker gamepad_ functions not see any controllers plugged in!

-
-


-

Syntax:

-
steam_input_init(explicitly_call_run_frame);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
explicitly_call_run_frameboolAre you going to call steam_input_run_frame manually or not?
-


-

async_load contents:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyValueDescription
event_typestringA constant string "steam_input_configuration_loaded".
app_idrealYour game's app id.
device_handlerealInput handle of the device this event refers to.
mapping_creatorrealSteam ID of the user that created the loaded input mapping or 0 if none.
major_revisionrealMajor version digit of the mapping.
minor_revisionrealMinor version digit of the mapping.
uses_steam_input_apiboolWhether this device is using the Action Set and Actions API.
uses_steam_gamepad_apiboolWhether this device is using the XInput emulation API.
-


-

Returns:

-
Bool


-

Example:

-
if (!steam_input_init(false))
-{
-    throw "Failed to initialize the Steam Input API";
-}
/// @description Async - Steam event
-if (async_load[? "event_type"] == "steam_input_configuration_loaded") {
-    // bindings refreshed, update any sprites we've fetched in some handler script
-    scr_refresh_input_hints(async_load[? "device_handle"]);
-}

The above code checks to see if the Steam Input API was initialized, and throws an exception if it wasn't, then handles "configuration loaded" async events.

- - -



-
- - -

Back To Top

-

steam_input_shutdown

-

With this function you can tell Steam that you are done using the Steam Input API. It will return true if the operation was successful and false otherwise. Usually you do not need to call this, as when your game ends Steam will automatically release Steam Input for you. After this function had returned, no other Steam Input functions must be called.

-


-

Syntax:

-
steam_input_shutdown();


-

Returns:

-
Bool


-

Example:

-
steam_input_shutdown();

The above code shuts down the Steam Input API.

- - -



-
- - -

Back To Top

-

steam_input_set_input_action_manifest_file_path

-

This function can be used to set the absolute path to the input action manifest, in case you do not wish to use the Steam Workshop for this. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_set_input_action_manifest_file_path(absolute_path);


- - - - - - - - - - - - - - - -
ArgumentTypeDescription
absolute_pathstringAbsolute path to the input action manifest file
-

Returns:

-
Bool


-

Example:

-
steam_input_set_input_action_manifest_file_path(working_directory + "manifest.vdf");

The above code sets the full path to the input action manifest file the game wants to use.

- - -



-
- - -

Back To Top

-

steam_input_run_frame

-

With this function you can poll for new input data from Steam Input if it is available, you do not need to call it manually unless you explicitly specified this when calling steam_input_init.

-


-

Syntax:

-
steam_input_run_frame();


-

Returns:

-
Bool


-

Example:

-
steam_input_run_frame();

The above code asks Steam Input to poll for new data if available.

- - -



-
- - -

Back To Top

-

steam_input_wait_for_data

-

With this function you can freeze the game until new input data had arrived, returns true if new data did arrive, or false if the timeout had expired or an error had occurred. This function is only useful for lockstep multiplayer games.

-


-

Syntax:

-
steam_input_wait_for_data(wait_forever,timeout);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
wait_foreverboolWhether to wait for data to arrive forever.
timeoutrealData arrival timeout.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_wait_for_data(true, 0);

The above code will freeze the entire game until new input data is received from Steam Input.

- - -



-
- - -

Back To Top

-

steam_input_new_data_available

-

With this function you can check if there is new input data available since last read. Returns true if there is, false otherwise.

-


-

Syntax:

-
steam_input_new_data_available();


-

Returns:

-
Bool


-

Example:

-
if (steam_input_new_data_available())
-{
-    global.data_check_flag = true;
-}

The above code checks if new data has been received since last poll, and sets a flag to true if there is.

- - -



-
- - -

Back To Top

-

steam_input_get_connected_controllers

-

With this function you can get an array of currently connected controller handles. This function returns an array of controller handles on success, and undefined on failure.

-


-

Syntax:

-
steam_input_get_connected_controllers();


-

Returns:

-
Array<Real> OR Undefined


-

Example:

-
controllers = steam_input_get_connected_controllers();
-if (is_undefined(controllers))
-{
-    throw "Unable to poll for controllers!";
-}

The above code will poll the current connected controllers array, and throw an exception if there was an error.

- - -



-
- - -

Back To Top

-

steam_input_enable_device_callbacks

-

You can use this function to enable Async - Steam device connection and disconnection events, similar to Async - System type gamepad connected and gamepad lost events. The contents of async_load are described below. Returns true if the operation was successful, and false otherwise. This can be used as an alternative to steam_input_get_connected_controllers since in that case you don't need to iterate through the entire array, which may be faster depending on how your game is coded. Both methods can be used simultaneously without issues. This function needs to be called only once and cannot be undone.

-
-

⚠️ IMPORTANT

-

Depending on the type of the controller, multiple connection or disconnection events may be sent for one handle, be sure to handle that in your code, e.g. don't show a disconnection pop-up if the controller was already lost, and don't show a connection pop-up if this controller was already connected (and is not lost).

-
-


-

Syntax:

-
steam_input_enable_device_callbacks();


-

async_load contents:

- - - - - - - - - - - - - - - - - - - - - - - - - -
KeyValueDescription
event_typeString"steam_input_device_connected" or "steam_input_device_disconnected"
disconnected_device_handleRealOnly present if event_type is "steam_input_device_disconnected"
connected_device_handleRealOnly present if event_type is "steam_input_device_connected"
-


-

Returns:

-
Bool


-

Extended Example:

-
/// @description Create event
-steam_input_enable_device_callbacks(); // enable connection events
/// @description Async - Steam event
-if (async_load[? "event_type"] == "steam_input_device_connected") {
-    scr_game_add_device(async_load[? "connected_device_handle"]); // register an input_handle
-    show_debug_message("Discovered a new input_handle!");
-}
-else if (async_load[? "event_type"] == "steam_input_device_disconnected") {
-    scr_game_remove_device(async_load[? "disconnected_device_handle"]); // de-register an input_handle
-    show_debug_message("Lost an input_handle!");
-}

The above code will enable device connection and disconnection events, then it will react to them by calling some handler function.

- - -



-
- - -

Back To Top

-

steam_input_enable_action_event_callbacks

-

This function will enable Async - Steam action events, this event will be called only when some digital or analog action will change it's state, in case of digital actions that means a button is held or released, in case of analog actions that means the analog stick had moved, or the stick type had changed. The contents of async_load are described below. This is similar to steam_input_get_digital_action_data and steam_input_get_analog_action_data, only here you don't have to poll for the actions manually, but you still need to obtain the handles via steam_input_get_digital_action_handle and steam_input_get_analog_action_handle respectively, otherwise Steam will think you don't care about these actions. This function needs to be called only once and cannot be undone.

-


-

Syntax:

-
steam_input_enable_action_event_callbacks();


-

async_load contents:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyValueDescription
event_typestring"steam_input_action_event"
controller_handleRealHandle of the controller this event is for.
action_event_typeRealA steam_input_action_event_type_ constant
action_handleRealHandle of the digital or analog action, depending on the type
activeboolWhether or not this action is currently available to be bound in the active action set. If it is not available, OR does not belong to the active action set, this will be false.
stateboolDIGITAL ACTIONS ONLY: state of the digital action, true or false.
moderealANALOG ACTIONS ONLY: A steam_input_source_mode_ constant.
xrealANALOG ACTIONS ONLY: X axis of the input
yrealANALOG ACTIONS ONLY: Y axis of the input
-


-

Returns:

-
Bool


-

Extended Example:

-
/// @description Create event
-steam_input_enable_action_event_callbacks(); // enable action input events
/// @description Async - System event
-if (async_load[? "event_type"] == "steam_input_action_event") {
-    var _controller_handle = async_load[? "controller_handle"];
-    var _action_handle = async_load[? "action_handle"];
-    var _is_action_active = async_load[? "active"];
-    if (_is_action_active) { // it's useless to try and handle an inactive action
-        if (async_load[? "action_event_type"] == steam_input_action_event_type_digital_action) {
-            var _digital_state = async_load[? "state"]; // true or false only, held or not held
-            scr_register_digital_input(_controller_handle, _action_handle, _digital_state); // some handler
-        }
-        else if (async_load[? "action_event_type"] == steam_input_action_event_type_digital_action) {
-            var _analog_mode = async_load[? "mode"]; // the user may be using a stick, or a mouse, or a touchpad...
-            var _analog_x = async_load[? "x"];
-            var _analog_y = async_load[? "y"];
-            scr_register_analog_input(_controller_handle, _action_handle, _analog_mode, _analog_x, _analog_y); // some handler
-        }
-    }
-    else {
-        show_debug_message("Action " + string(_action_handle) + " not active for con " + string(_controller_handle)); // not bound?
-    }
-}

The above code will activate action input async events, and handle them correctly.

- - -



-
- - -

Back To Top

-

steam_input_get_action_set_handle

-

This function will try to resolve an action set by name, returning the handle of that action set.

-
-

⚠️ IMPORTANT

-

Due to a bug in the Steam Input API, if the game was launched without any controllers connected, all action set and action handle resolver functions will return 0, an invalid handle, as such it is required that you try to obtain handles every frame until at least one controller gets connected and you succeed.

-
-


-

Syntax:

-
steam_input_get_action_set_handle(action_set_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
action_set_namestringThe name of the action set.
-


-

Returns:

-
Real


-

Extended Example:

-
/// @description Create event
-main_action_set = 0; // '0' is an invalid handle.
-menu_action_set = 0;
/// @description Step event
-// due to a bug in the Steam Input API, we have to try and obtain these every frame until we succeed.
-// check if any handle is invalid:
-if (main_action_set == 0 || menu_action_set == 0) {
-    // try to resolve:
-    main_action_set = steam_input_get_action_set_handle("Set_Main");
-    menu_action_set = steam_input_get_action_set_handle("Set_Menu");
-    // if we failed and the functions return 0, we will try again, on the next frame.
-}

The above code checks if any handle is 0, and if it is, it tries to obtain all handles again, until it eventually completes and all handles are valid.

- - -



-
- - -

Back To Top

-

steam_input_activate_action_set

-

With this function you can activate an action set on a specific controller, or all controllers by specifying the steam_input_handle_all_controllers constant as the controller handle. Returns true if the operation was successful, and false otherwise. This function is cheap to call and can be safely called every frame without hitting performance issues.

-


-

Syntax:

-
steam_input_activate_action_set(controller, action_set);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealInput handle of the controller.
action_setRealHandle of the action set, cannot be zero.
-


-

Returns:

-
Bool


-

Example:

-
switch (state) {
-    case game_state.menu: {
-        steam_input_activate_action_set(steam_input_handle_all_controllers, menu_action_set);
-        scr_do_menu_input();
-        break;
-    }
-
-    case game_state.play: {
-        steam_input_activate_action_set(player_controller_handle, main_action_set);
-        scr_do_gameplay_input(player_controller_handle);
-        break;
-    }
-}

The above code will activate the appropriate action set based on which state the game is currently in.

- - -



-
- - -

Back To Top

-

steam_input_get_current_action_set

-

This function will return the handle of the currently activated action set on a given controller handle, or 0 if there is no action set currently active.

-


-

Syntax:

-
steam_input_get_current_action_set(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerinput_handleHandle of the controller.
-


-

Returns:

-
Real


-

Example:

-
if (steam_input_get_current_action_set(player_handle) == 0) {
-    steam_input_activate_action_set(player_handle, menu_action_set);
-}

The above code will check to see if there is no action set activated for a controller, and if there isn't, it will activate a menu action set.

- - -



-
- - -

Back To Top

-

steam_input_activate_action_set_layer

-

This function will activate an action set layer on top of the current action set on a specified controller. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_activate_action_set_layer(controller, action_set_layer);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealHandle of the controller.
action_set_layerrealHandle of the action set layer.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_activate_action_set_layer(player_handle, action_set_layer_sniper);

The above code will activate a "sniper" action set layer on top of any currently activated action sets. Returns true if the operation was successful and false otherwise.

- - -



-
- - -

Back To Top

-

steam_input_deactivate_action_set_layer

-

This function will deactivate a specific action set layer from the specified controller. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_deactivate_action_set_layer(controller, action_set_layer);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealHandle of the controller.
action_set_layerrealHandle of the action set layer.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_deactivate_action_set_layer(player_handle, action_set_layer_sniper);

The above code will deactivate the "sniper" action set layer from the player_handle controller.

- - -



-
- - -

Back To Top

-

steam_input_deactivate_all_action_set_layers

-

This function will deactivate all action set layers on a specified controller. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_deactivate_all_action_set_layers(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealHandle of the controller.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_deactivate_all_action_set_layers(player_handle);

The above code will deactivate all action set layers on the player_handle controller.

- - -



-
- - -

Back To Top

-

steam_input_get_active_action_set_layers

-

This function will return an array of currently active action set layer handles on a specified controller. Returns an array of action set layer handles on success, and undefined on failure.

-


-

Syntax:

-
steam_input_get_active_action_set_layers(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealHandle of the controller.
-


-

Returns:

-
Array<Real> OR Undefined


-

Example:

-
var layers = steam_input_get_active_action_set_layers(player_handle);
-if (array_length(layers) > 0) {
-    steam_input_deactivate_all_action_set_layers(player_handle);
-}

The above code will retrieve all currently active action set layers for player_handle, and if there are some active, it will deactivate all action set layers.

- - -



-
- - -

Back To Top

-

steam_input_get_digital_action_handle

-

This function will resolve a digital action by name, and return that action's handle. Keep in mind that no two actions cannot have the same name, even if they are defined in different action sets, since Steam does not differentiate action names for each set.

-
-

⚠️ IMPORTANT

-

Due to a bug in the Steam Input API, if the game was launched without any controllers connected, all action set and action handle resolver functions will return 0, an invalid handle, as such it is required that you try to obtain handles every frame until at least one controller gets connected and you succeed.

-
-


-

Syntax:

-
steam_input_get_digital_action_handle(digital_action_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
digital_action_namestringName of the digital action.
-


-

Returns:

-
Real


-

Extended Example:

-
/// @description Create event
-action_shoot = 0; // '0' is an invalid handle.
-action_roll = 0;
/// @description Step event
-if (action_shoot == 0 || action_roll == 0) {
-    action_shoot = steam_input_get_digital_action_handle("DAction_Shoot");
-    action_roll = steam_input_get_digital_action_handle("DAction_Roll");
-}

The above code will try to obtain handles of digital actions shoot and roll, if it failed, it will try again on the next frame.

- - -



-
- - -

Back To Top

-

steam_input_get_digital_action_data

-

This function will return current input data for a given digital action on a given controller. It returns the digital_action_data struct on success and undefined on failure.

-


-

Syntax:

-
steam_input_get_digital_action_data(controller,action_handle);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealHandle of the controller to use.
action_handleRealHandle of the digital action to poll for.
-


-

Returns:

-
Struct OR Undefined

Struct fields: -|Name|Type|Description| -|----|----|----| -|active|Bool|Whether the action is bound to any button| -|state|Bool|Whether the action is currently held or not|

-


-

Example:

-
var _data = steam_input_get_digital_action_data(player_handle, action_shoot);
-with (objPlayer) {
-    isShooting = _data.active && _data.state;
-}

The above code will set the isShooting variable in the player object to true if the action is active and is currently held, or false otherwise.

- - -



-
- - -

Back To Top

-

steam_input_get_digital_action_origins

-

This function will retrieve an array of input origins for a specified action and controller handles. This is the function you should use when trying to obtain input hint prompts, keep in mind that it returns an array because multiple buttons can be bound to one action in the Steam Input Configurator. Also keep in mind that input hints may change mid-game as the Steam Input Configurator is accessible inside the Steam Overlay, this is why it's recommended that you update all input sprites when you get a Configuration Async - Steam event for the controller(s) you are interested in.

-


-

Syntax:

-
steam_input_get_digital_action_origins(controller, action_set, digital_action);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealHandle of the controller to use.
action_setRealHandle of the action set.
digital_actionRealHandle of the digital action inside the action set.
-


-

Returns:

-
Array<Real> OR Undefined


-

Example:

-
// this example function returns a horizontal strip of input hints as a single sprite frame
-// do not forget to use sprite_delete() when you no longer need the returned sprite.
-function scr_sprite_for_action(player_handle, action_set_handle, action_handle, is_digital_action) {
-    var _origins = is_digital_action
-        ? steam_input_get_digital_action_origins(player_handle, action_set_handle, action_handle)
-        : steam_input_get_analog_action_origins(player_handle, action_set_handle, action_handle);
-    if (is_undefined(_origins) || array_length(_origins) == 0) {
-        // something is wrong or no buttons are bound
-        return -1;
-    }
-    var _hint_count = array_length(_origins),
-        _hint_width = 32,
-        _hint_height = 32,
-        _hint_size = steam_input_glyph_size_small, // _small is 32x32 pixels
-        _hint_style = steam_input_glyph_style_dark; // prefer dark glyphs for the sake of this example
-    var _surf = surface_create(_hint_count * _hint_width, _hint_height);
-    surface_set_target(_surf);
-    draw_clear_alpha(c_black, 0);
-    for (var _h = 0; _h < _hint_count; ++_h) {
-        var _origin = _origins[_h];
-        var _path = steam_input_get_glyph_png_for_action_origin(_origin, _hint_size, _hint_style);
-        var _tempspr = sprite_add(_path, 1, false, false, 0, 0);
-        draw_sprite(_tempspr, 0, _hint_width * _h, 0);
-        sprite_delete(_tempspr);
-    }
-    surface_reset_target();
-    var _sprstrip = sprite_create_from_surface(_surf, 0, 0, surface_get_width(_surf), surface_get_height(_surf), false, false, 0, 0);
-    // you can add a call to sprite_set_offset() if you wish to auto-set the sprite origin to middle centre.
-    surface_free(_surf);
-    return _sprstrip;
-}
-
-global.shoot_sprite = scr_sprite_for_action(player_handle, main_action_set, action_shoot, true);
-draw_sprite(global.shoot_sprite, 0, 64, 64);

The above code defines an example of how to turn action origins into a sprite that you can draw in-game, for example on the GUI Layer.

- - -



-
- - -

Back To Top

-

steam_input_get_string_for_digital_action_name

-

This function will return the localized name of a digital action as specified by Steam localization settings. Keep in mind that the Steam language may be different than the OS language, and this function will always use the language settings of the Steam client, not the OS.

-


-

Syntax:

-
steam_input_get_string_for_digital_action_name(digital_action);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
digital_actionRealHandle of the digital action.
-


-

Returns:

-
string


-

Example:

-
shoot_name_loc = steam_input_get_string_for_digital_action_name(action_shoot);

The above code will get the localized name for the shoot action, and store it in the variable shoot_name_loc.

- - -



-
- - -

Back To Top

-

steam_input_get_analog_action_handle

-

This function will resolve an analog action by name, and return that action's handle. Keep in mind that no two actions cannot have the same name, even if they are defined in different action sets, since Steam does not differentiate action names for each set.

-
-

⚠️ IMPORTANT

-

Due to a bug in the Steam Input API, if the game was launched without any controllers connected, all action set and action handle resolver functions will return 0, an invalid handle, as such it is required that you try to obtain handles every frame until at least one controller gets connected and you succeed.

-
-


-

Syntax:

-
steam_input_get_analog_action_handle(analog_action_name);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
analog_action_namestringName of the analog action.
-


-

Returns:

-
Real


-

Extended Example:

-
/// @description Create event
-action_move = 0; // '0' is an invalid handle.
-action_aim = 0;
/// @description Step event
-if (action_move == 0 || action_aim == 0) {
-    action_move = steam_input_get_analog_action_handle("AAction_Move");
-    action_aim = steam_input_get_analog_action_handle("AAction_Aim");
-}

The above code will try to obtain handles of analog actions move and aim, if it failed, it will try again on the next frame.

- - -



-
- - -

Back To Top

-

steam_input_get_analog_action_data

-

This function will return current input data for a given analog action on a given controller. It returns the analog_action_data struct on success and undefined on failure.

-


-

Syntax:

-
steam_input_get_analog_action_data(controller, action_handle);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealHandle of the controller to use.
action_handleRealHandle of the analog action to poll for.
-


-

Struct Fields:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
activeBoolWhether this action is bound to any input element.
modeRealA steam_input_source_mode_ constant.
xRealX axis of the input.
yRealY axis of the input, inverted by default. See example code.
-

Returns:

-
Struct OR Undefined


-

Example:

-
var _data = steam_input_get_analog_action_data(player_handle, action_move);
-if (_data.active) {
-    with (objPlayer) {
-        x += _data.x * move_speed;
-        // in Steam Input the Y axis is in a different direction than GameMaker, so we need to invert it.
-        y += -_data.y * move_speed;
-        // you might want to use different crosshairs if the movement came from a touchpad or an analog stick.
-        last_input_mode = _data.mode;
-    }
-}

The above code will move the player object accordingly to the input data for the move analog action.

- - -



-
- - -

Back To Top

-

steam_input_get_analog_action_origins

-

This function will retrieve an array of input origins for a specified action and controller handles. This is the function you should use when trying to obtain input hint prompts, keep in mind that it returns an array because multiple buttons can be bound to one action in the Steam Input Configurator. Also keep in mind that input hints may change mid-game as the Steam Input Configurator is accessible inside the Steam Overlay, this is why it's recommended that you update all input sprites when you get a Configuration Async - Steam event for the controller(s) you are interested in.

-


-

Syntax:

-
steam_input_get_analog_action_origins(controller, action_set, action);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealHandle of the controller to use.
action_setRealHandle of the action set.
actionRealHandle of the analog action inside the action set.
-


-

Returns:

-
Array<Real> OR Undefined


-

Example:

-
// this example function returns a horizontal strip of input hints as a single sprite frame
-// do not forget to use sprite_delete() when you no longer need the returned sprite.
-function scr_sprite_for_action(player_handle, action_set_handle, action_handle, is_digital_action) {
-    var _origins = is_digital_action
-        ? steam_input_get_digital_action_origins(player_handle, action_set_handle, action_handle)
-        : steam_input_get_analog_action_origins(player_handle, action_set_handle, action_handle);
-    if (is_undefined(_origins) || array_length(_origins) == 0) {
-        // something is wrong or no buttons are bound
-        return -1;
-    }
-    var _hint_count = array_length(_origins),
-        _hint_width = 32,
-        _hint_height = 32,
-        _hint_size = steam_input_glyph_size_small, // _small is 32x32 pixels
-        _hint_style = steam_input_glyph_style_dark; // prefer dark glyphs for the sake of this example
-    var _surf = surface_create(_hint_count * _hint_width, _hint_height);
-    surface_set_target(_surf);
-    draw_clear_alpha(c_black, 0);
-    for (var _h = 0; _h < _hint_count; ++_h) {
-        var _origin = _origins[_h];
-        var _path = steam_input_get_glyph_png_for_action_origin(_origin, _hint_size, _hint_style);
-        var _tempspr = sprite_add(_path, 1, false, false, 0, 0);
-        draw_sprite(_tempspr, 0, _hint_width * _h, 0);
-        sprite_delete(_tempspr);
-    }
-    surface_reset_target();
-    var _sprstrip = sprite_create_from_surface(_surf, 0, 0, surface_get_width(_surf), surface_get_height(_surf), false, false, 0, 0);
-    // you can add a call to sprite_set_offset() if you wish to auto-set the sprite origin to middle centre.
-    surface_free(_surf);
-    return _sprstrip;
-}
-
-global.move_sprite = scr_sprite_for_action(player_handle, main_action_set, action_move, false /* not digital this time! */);
-draw_sprite(global.move_sprite, 0, 64, 64);

The above code defines an example of how to turn action origins into a sprite that you can draw in-game, for example on the GUI Layer.

- - -



-
- - -

Back To Top

-

steam_input_get_glyph_png_for_action_origin

-

This function will return a full path to a PNG file of the glyph image of an action origin. The path is automatically added into the GameMaker's filesystem sandbox list, so that you can use the returned path in sprite_add or buffer_load no matter if you have the sandbox enabled or disabled.

-


-

Syntax:

-
steam_input_get_glyph_png_for_action_origin(origin, size, flags);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
originRealAction origin to get the PNG of.
sizeRealA steam_input_glyph_size_ constant.
flagsRealA steam_input_glyph_style_ bit flags constant.
-


-

Returns:

-
string


-

Example:

-
var _path = steam_input_get_glyph_png_for_action_origin(global.shoot_origin, steam_input_glyph_size_small, steam_input_glyph_style_dark);
-global.shoot_sprite = sprite_add(_path, 1, false, false, 0, 0);

The above code will get a PNG representing an action origin and load it as a sprite. For an extended example please see the example code from steam_input_get_digital_action_origins.

- - -



-
- - -

Back To Top

-

steam_input_get_glyph_svg_for_action_origin

-

This function will return a full path to an SVG file of the glyph image of an action origin. The path is automatically added into the GameMaker's filesystem sandbox list, so that you can use the returned path in buffer_load no matter if you have the sandbox enabled or disabled. As for now GameMaker has no native capabilities to draw SVG files, but such ability may be added in the future. If you have your own SVG renderer then this function might be useful for you. Since SVGs do not have a fixed size and can be freely scaled, there is no size argument like in steam_input_get_glyph_png_for_action_origin.

-


-

Syntax:

-
steam_input_get_glyph_svg_for_action_origin(origin, flags);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
originRealAction origin to get the SVG of.
flagsRealA steam_input_glyph_style_ bit flags constant.
-


-

Returns:

-
string


-

Example:

-
var _svg_path = steam_input_get_glyph_svg_for_action_origin(global.shoot_origin, steam_input_glyph_style_dark);

The above code will get the path to an SVG representing an action origin and store it in a local variable _svg_path.

- - -



-
- - -

Back To Top

-

steam_input_get_glyph_for_action_origin_legacy

-

This function will return a full path to a PNG file of the glyph image of an action origin. The path is automatically added into the GameMaker's filesystem sandbox list, so that you can use the returned path in sprite_add or buffer_load no matter if you have the sandbox enabled or disabled. The image will be in legacy Steam Big Picture design style, if you wish to use the new Steam Deck styled glyphs (also called Knockout glyphs in Valve's documentation), please use the function steam_input_get_glyph_png_for_action_origin instead.

-


-

Syntax:

-
steam_input_get_glyph_for_action_origin_legacy(origin);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
originRealAction origin to get the PNG of.
-


-

Returns:

-
string


-

Example:

-
var _path = steam_input_get_glyph_for_action_origin_legacy(global.shoot_origin);
-global.shoot_sprite = sprite_add(_path, 1, false, false, 0, 0);

The above code will get a PNG representing an action origin and load it as a sprite.

- - -



-
- - -

Back To Top

-

steam_input_get_string_for_action_origin

-

This function will return a localized name of an action origin, for example "Y Button" if the Steam language is set to English, or "Кнопка Y" if it is set to Russian. Keep in mind that the OS language may be different from the Steam client language, and the Steam language will be used instead.

-


-

Syntax:

-
steam_input_get_string_for_action_origin(origin);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
originRealAction origin to get the localized name of.
-


-

Returns:

-
string


-

Example:

-
global.shoot_name = steam_input_get_string_for_action_origin(global.shoot_origin);

The above code will get a localized name of the shoot origin and store it in a global variable shoot_name.

- - -



-
- - -

Back To Top

-

steam_input_get_string_for_analog_action_name

-

This function will return the localized name of an analog action as specified by Steam localization settings. Keep in mind that the Steam language may be different than the OS language, and this function will always use the language settings of the Steam client, not the OS.

-


-

Syntax:

-
steam_input_get_string_for_analog_action_name(action);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
actionRealHandle of the analog action.
-


-

Returns:

-
string


-

Example:

-
move_name_loc = steam_input_get_string_for_analog_action_name(action_move);

The above code will get the localized name for the move action, and store it in the variable move_name_loc.

- - -



-
- - -

Back To Top

-

steam_input_stop_analog_action_momentum

-

This function will stop the momentum of an analog action if the input device is, for example, a trackball. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_stop_analog_action_momentum(controller,action);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealInput handle of the controller.
actionRealHandle of the analog action.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_stop_analog_action_momentum(player_handle, action_move);

The above code will stop the analog momentum of the move action.

- - -



-
- - -

Back To Top

-

steam_input_get_motion_data

-

This function will obtain raw gyroscope and accelerometer data in the controller's native format. Returns the motion_data struct on success and undefined on failure.

-


-

Syntax:

-
steam_input_get_motion_data(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerRealInput handle of the controller.
-

Struct Fields:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
rot_quat_xRealX component of the orientation quaternion.
rot_quat_yRealY component of the orientation quaternion.
rot_quat_zRealZ component of the orientation quaternion.
rot_quat_wRealW component of the orientation quaternion.
pos_accel_xRealX component of the acceleration.
pos_accel_yRealY component of the acceleration.
pos_accel_zRealZ component of the acceleration.
rot_vel_xRealX component of the angular velocity.
rot_vel_yRealY component of the angular velocity.
rot_vel_zRealZ component of the angular velocity.
-


-

Returns:

-
Struct OR Undefined


-

Example:

-
var _data = steam_input_get_motion_data(player_handle);
-if (is_undefined(_data)) {
-    exit;
-}
-var _dt = delta_time / 1000000;
-// this math will only work for the DualShock 4 controller
-x += _dt * room_width * (_data.rot_vel_y / -32767);
-y += _dt * room_height * (_data.rot_vel_x / -32767);
-image_angle = radtodeg(_dt * (_data.rot_vel_z / 32767));

The above code will rotate and move the object based on the angular velocity data of the controller.

- - -



-
- - -

Back To Top

-

steam_input_trigger_vibration

-

This function will trigger a vibration effect on the target controller. Keep in mind that due to physical differences of each controller, the motors may not be the exact same, for example on the DualShock 4 controller the left motor is bigger and faster than the right one. Returns true on success and false otherwise.

-


-

Syntax:

-
steam_input_trigger_vibration(controller,left_speed,right_speed);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
left_speedrealSpeed of the left motor from 0 to 65535.
right_speedrealSpeed of the right motor from 0 to 65535.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_trigger_vibration(player_handle, 65535 / 2, 65535 / 2);

The above code will trigger a vibration effect at half the maximum power on both motors.

- - -



-
- - -

Back To Top

-

steam_input_trigger_vibration_extended

-

This function will trigger an extended vibration effect on the target controller. Keep in mind that due to physical differences of each controller, the motors may not be the exact same, for example on the DualShock 4 controller the left motor is bigger and faster than the right one. Also keep in mind that not all controllers may support the extended vibration effects. Returns true on success and false otherwise.

-


-

Syntax:

-
steam_input_trigger_vibration_extended(controller,left_speed,right_speed,left_trigger_speed,right_trigger_speed);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
left_speedrealSpeed of the left motor from 0 to 65535.
right_speedrealSpeed of the right motor from 0 to 65535.
left_trigger_speedrealSpeed of the left trigger from 0 to 65535.
right_trigger_speedrealSpeed of the right trigger from 0 to 65535.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_trigger_vibration_extended(player_handle, 65535 / 2, 65535 / 2, 65535 / 4, 65535 / 4);

The above code will trigger a vibration effect at half the maximum power on vibration motors, and set the trigger speed for both triggers to a quarter.

- - -



-
- - -

Back To Top

-

steam_input_trigger_simple_haptic_event

-

This function will trigger a simple haptic event if the target controller supports them. Returns true on success and false on failure.

-


-

Syntax:

-
steam_input_trigger_simple_haptic_event(controller,location,intensity,gain_db,other_intensity,other_gain_db);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
locationrealA steam_input_controller_haptic_location_ constant.
intensityrealIntensity of the first motor from 0 to 255.
gain_dbrealGain in DB units, can be negative, from -127 to 128.
other_intensityrealIntensity of the second motor from 0 to 255.
other_gain_dbrealGain of the second motor in DB units, can be negative, from -127 to 128.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_trigger_simple_haptic_event(controller, steam_input_controller_haptic_location_both, 255 / 2, 0, 255 / 2, 0);

The above code will trigger a simple haptic event with half intensity and neutral db gain on both motors of the controller.

- - -



-
- - -

Back To Top

-

steam_input_set_led_color

-

This function will set or reset the color of the LED on the controller. Keep in mind that not all controllers have LEDs in them, and that the default user color of the controller differs between manufacturers, but your custom ones should always look almost the same.

-


-

Syntax:

-
steam_input_set_led_color(controller,color,flags);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
colorrealColor value to use.
flagsrealA steam_input_led_flag_ constant.
-


-

Returns:

-
Bool


-

Example:

-
// to set your own color:
-var _rainbow = make_color_hsv((get_timer() / 100000) mod (255 + 1), 255, 255); // cycle through the Hue.
-steam_input_set_led_color(controller, _rainbow, steam_input_led_flag_set_color);
-// to reset to the default color:
-steam_input_set_led_color(controller, c_black, steam_input_led_flag_restore_user_default);

The above code first sets the LED color to a custom one, then resets the color to the default one.

- - -



-
- - -

Back To Top

-

steam_input_trigger_haptic_pulse_legacy

-

This function runs a haptic pulse through the legacy API, this is only useful if the target controller is a Steam Controller. Returns true on success and false otherwise.

-


-

Syntax:

-
steam_input_trigger_haptic_pulse_legacy(controller,pad,duration_in_ms);
- - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
padrealA steam_input_steam_controller_pad_ constant.
duration_in_msrealDuration of the pulse in miliseconds.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_trigger_haptic_pulse_legacy(player_handle, steam_input_steam_controller_pad_left, 2 * 1000);

The above code runs a haptic pulse on the left motor for two seconds (2000 miliseconds).

- - -



-
- - -

Back To Top

-

steam_input_trigger_repeated_haptic_pulse_legacy

-

This function runs a repeated haptic pulse through the legacy API, this is only useful if the target controller is a Steam Controller. Returns true on success and false otherwise.

-


-

Syntax:

-
steam_input_trigger_repeated_haptic_pulse_legacy(controller,pad,duration_in_ms,offset_in_ms,repeat_times,flags);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
padrealA steam_input_steam_controller_pad_ constant.
duration_in_msrealDuration of the pulse in miliseconds.
offset_in_msrealThe offset from which to start looping in miliseconds.
repeat_timesrealHow many times to repeat the loop?
flagsrealRepeated haptic pulse flags
-


-

Returns:

-
Bool


-

Example:

-
steam_input_trigger_repeated_haptic_pulse_legacy(player_handle, steam_input_steam_controller_pad_left, 2 * 1000, 100, 2, 0);

The above code runs a repeated haptic pulse on the left motor for two seconds (2000 miliseconds), the next iterations will start at 100 miliseconds and this will repeat two times.

- - -



-
- - -

Back To Top

-

steam_input_show_binding_panel

-

This function opens the Steam Input Configurator for the target controller which allows the player to rebind controls in-game. If Steam is not running in Big Picture, a new window will be opened, otherwise the configurator will be invoked as a part of the Steam Overlay. Keep in mind that the player can open the Configurator without this function too, by pressing the "Controller Layout" button in the Steam Overlay. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_show_binding_panel(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
-


-

Returns:

-
Bool


-

Example:

-
steam_input_show_binding_panel(player_handle);

The above code opens the Steam Input Configurator for the controller handle stored in player_handle.

- - -



-
- - -

Back To Top

-

steam_input_get_input_type_for_handle

-

This function returns the type of the target controller. Useful if you want to know which features are most likely supported by the target contorller.

-


-

Syntax:

-
steam_input_get_input_type_for_handle(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
-


-

Returns:

-
real


-

Example:

-
var _input_type = steam_input_get_input_type_for_handle(player_handle);
-var _msg = "The controller type is ";
-var _typestr = "Unknown";
-switch (_input_type) {
-    case steam_input_type_steam_controller: _typestr = "Steam Controller"; break;
-    case steam_input_type_xbox_360_controller: _typestr = "Xbox 360"; break;
-    case steam_input_type_xbox_one_controller: _typestr = "Xbox One"; break;
-    case steam_input_type_generic_gamepad: _typestr = "Generic Gamepad"; break;
-    case steam_input_type_ps4_controller: _typestr = "DualShock 4"; break;
-    case steam_input_type_apple_mfi_controller: _typestr = "Apple MFi"; break;
-    case steam_input_type_android_controller: _typestr = "Android"; break;
-    case steam_input_type_switch_joycon_pair: _typestr = "Joy-Con Pair"; break;
-    case steam_input_type_switch_joycon_single: _typestr = "Single Joy-Con"; break;
-    case steam_input_type_switch_pro_controller: _typestr = "Pro Controller"; break;
-    case steam_input_type_mobile_touch: _typestr = "Mobile Touch"; break;
-    case steam_input_type_ps3_controller: _typestr = "DualShock 3"; break;
-    case steam_input_type_ps5_controller: _typestr = "DualSense"; break;
-    case steam_input_type_steam_deck_controller: _typestr = "Steam Deck"; break;
-}
-show_debug_message(_msg + _typestr);

The above code prints the type of the controller as a string to debug output.

- - -



-
- - -

Back To Top

-

steam_input_get_controller_for_gamepad_index

-

This function returns the input handle for an XInput gamepad slot, or 0 if that slot is not powered by Steam Input. That can be used to match between native GameMaker gamepad_ slots and Steam Input controllers on Windows. Since on Windows the GameMaker pad slots from 0 to 3 are XInput controllers, and from 4 to 12 are DirectInput controllers. This function only works with emulated XInput controllers.

-


-

Syntax:

-
steam_input_get_controller_for_gamepad_index(index);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
indexrealXInput slot from 0 to 3 included.
-


-

Returns:

-
real


-

Example:

-
var _slot0h = steam_input_get_controller_for_gamepad_index(0);
-if (_slot0h != 0) {
-    show_debug_message("GM slot 0 handle = " + string(_slot0h));
-}

The above code prints the controller handle for the first XInput gamepad slot if it is valid.

- - -



-
- - -

Back To Top

-

steam_input_get_controller_for_gamepad_index

-

This function is the reverse of steam_input_get_controller_for_gamepad_index, except it allows you to determine whether a Steam Input handle is being emulated as XInput as well or not. See the definition of the reverse function for more information about slots.

-


-

Syntax:

-
steam_input_get_controller_for_gamepad_index(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput handle of the controller.
-


-

Returns:

-
Real


-

Example:

-
var _slot0i = steam_input_get_gamepad_index_for_controller(player_handle);
-if (_slot0i >= 0) {
-    show_debug_message("GM slot for player is = " + string(_slot0i));
-}

The above code prints the XInput slot for the player controller if it's valid.

- - -



-
- - -

Back To Top

-

steam_input_get_string_for_xbox_origin

-

This function turns a steam_input_xbox_origin_ constant into a localized string, the language will be taken from Steam client settings. For example "A Button" if it's English or "Кнопка A" if it's Russian.

-


-

Syntax:

-
steam_input_get_string_for_xbox_origin(origin);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
originrealA steam_input_xbox_origin_ constant.
-


-

Returns:

-
string


-

Example:

-
show_debug_message("A Button is " + steam_input_get_string_for_xbox_origin(steam_input_xbox_origin_a));

The above code prints the localized name of the Xbox 360 A button origin.

- - -



-
- - -

Back To Top

-

steam_input_get_glyph_for_xbox_origin

-

This returns a path to a PNG associated with a steam_input_xbox_origin_ constant. The returned path will be automatically added into the GameMaker filesystem sandbox list so it can be used with buffer_load or sprite_add no matter whether you have sandbox enabled or not.

-


-

Syntax:

-
steam_input_get_glyph_for_xbox_origin(origin);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
originrealA steam_input_xbox_origin_ constant.
-


-

Returns:

-
string


-

Example:

-
var _path = steam_input_get_glyph_for_xbox_origin(steam_input_xbox_origin_a);
-var _sprite = sprite_add(_path, 1, false, false, 0, 0);
-// ...
-// do not forget to free the sprite when you're done:
-sprite_delete(_sprite);

The above code loads a PNG file associated with steam_input_xbox_origin_a as a sprite.

- - -



-
- - -

Back To Top

-

steam_input_get_action_origin_from_xbox_origin

-

This function returns the closest origin that maps to the steam_input_xbox_origin_ constant for the target controller. So for a DualShock 4 controller handle steam_input_xbox_origin_a will return the "cross" button origin. Useful for transposing Xbox 360 button hints into the target controller button hints without using the Actions and Action Sets.

-


-

Syntax:

-
steam_input_get_action_origin_from_xbox_origin(controller, origin);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealTarget controller handle to use.
originrealA steam_input_xbox_origin_ constant.
-


-

Returns:

-
real


-

Example:

-
// original origin:
-var _xbox_origin = steam_input_xbox_origin_y;
-// transposed origin: (ex: (Y) -> (TRIANGLE) on DS4)
-var _transposed_origin = steam_input_get_action_origin_from_xbox_origin(player_handle, _xbox_origin);
-var _path = steam_input_get_glyph_png_for_action_origin(_transposed_origin, steam_input_glyph_size_small, steam_input_glyph_style_dark);
-var _sprite = sprite_add(_path, 1, false, false, 0, 0);
-// do something with the sprite
-// ...
-// free the sprite:
-sprite_delete(_sprite);

The above code loads an input sprite of the Xbox 360 button "Y" in the target controller's style.

- - -



-
- - -

Back To Top

-

steam_input_translate_action_origin

-

This function allows to translate an action origin for a new unknown controller type into an origin that this extension will understand. This is useful if a new controller is released, it's support is added into Steam Input, the Steam client is updated, the Steam Input Configurator is updated, but your game is not, and it doesn't know about this controller. With this function you can try to obtain the closest origin that maps to that unknown-for-your-game controller origin.

-


-

Syntax:

-
steam_input_translate_action_origin(type, origin);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
typerealsteam_input_type_ you would like to map to, or steam_input_type_unknown to let Steam do a best guess.
originrealAn unknown input action origin you would like to translate.
-


-

Returns:

-
real


-

Example:

-
// do a best guess here, let's pretend we have absolutely no idea how to handle this new controller
-var _transposed_origin = steam_input_translate_action_origin(steam_input_type_unknown, global.shoot_origin);
-var _path = steam_input_get_glyph_png_for_action_origin(_transposed_origin, steam_input_glyph_size_small, steam_input_glyph_style_dark);
-var _sprite = sprite_add(_path, 1, false, false, 0, 0);
-// do something with the sprite
-// ...
-// free the sprite:
-sprite_delete(_sprite);

The above code tries to map an unknown action origin into something that this extension understands, and then loads a sprite representing that origin.

- - -



-
- - -

Back To Top

-

steam_input_get_device_binding_revision

-

This function returns the current action bindings revision as a struct, or undefined if there was an error.

-


-

Syntax:

-
steam_input_get_device_binding_revision(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput controller handle to use.
-

Struct Fields:

- - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
majorrealMajor version digit.
minorrealMinor version digit.
-


-

Returns:

-
Struct OR Undefined


-

Example:

-
var _bindvers = steam_input_get_device_binding_revision(player_handle);
-show_debug_message("Major = " + string(_bindvers.major) + ", minor = " + string(_bindvers.minor));

The above code prints the current device bindings revision into debug output.

- - -



-
- - -

Back To Top

-

steam_input_get_remote_play_session_id

-

This function returns the current Steam Remote Play session id associated with the controller, or 0 if no session is associated.

-


-

Syntax:

-
steam_input_get_remote_play_session_id(controller);
- - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerinput_handleInput controller handle to use.
-


-

Returns:

-
Real


-

Example:

-
var _sessid = steam_input_get_remote_play_session_id(player_handle);
-show_debug_message("Session ID = " + string(_sessid));

The above code prints the current Steam Remote Play session id associated with the player controller.

- - -



-
- - -

Back To Top

-

steam_input_get_session_input_configuration_settings

-

This function returns the Steam Remote Play session opted-in gamepad types bitmask. Specifically the steam_input_configuration_enable_type_ constants.

-


-

Syntax:

-
steam_input_get_session_input_configuration_settings();


-

Returns:

-
Real


-

Example:

-
var _setmask = steam_input_get_session_input_configuration_settings();
-// how to detect for opt-in:
-var _opted_into_ps = (_setmask & steam_input_configuration_enable_type_playstation) != 0;
-var _opted_into_switch = (_setmask & steam_input_configuration_enable_type_switch) != 0;
-// just print the bitmask:
-show_debug_message("Settings bit mask = " + string(_setmask));

The above code prints the current Steam Remote Play session input bitmask into the debug output.

- - -



-
- - -

Back To Top

-

steam_input_set_dualsense_trigger_effect

-

This function is for input handles of DualSense controllers only, allows to apply an adaptive trigger effect to a DualSense input handle. The format of the struct is described in the example code. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_input_set_dualsense_trigger_effect(controller, param);
- - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
controllerrealInput controller handle to use.
paramstructTrigger effect parameter struct, see the example.
-


-

Returns:

-
Bool


-

Example:

-
// please PLEASE PLEASE read the comments for each field here,
-// your struct MUST follow this format, otherwise the extension will throw an exception.
-// field comments taken from isteamdualsense.h header file from the Steamworks SDK.
-var _param = {
-    // which triggers to modify, L2, R2, or both
-    trigger_mask: steam_input_sce_pad_trigger_effect_trigger_mask_l2 | steam_input_sce_pad_trigger_effect_trigger_mask_r2,
-    // must be a valid array of 2 elements, always
-    command: [
-        // L2 data:
-        {
-            mode: steam_input_sce_pad_trigger_effect_mode_multiple_position_vibration,
-            // command_data must be a valid struct, never undefined
-            command_data: {
-                // if mode_off then no fields from command_data will be read, otherwise:
-                feedback_param: {
-                    // if mode_feedback
-                    position: 0, /*E position where the strength of target trigger start changing(0~9). */
-                    strength: 0  /*E strength that the motor arm pushes back target trigger(0~8 (0: Same as Off mode)). */
-                },
-                weapon_param: {
-                    // if mode_weapon
-                    start_position: 0, /*E position where the stiffness of trigger start changing(2~7). */
-                    end_position: 0,   /*E position where the stiffness of trigger finish changing(start_position+1~8). */
-                    strength: 0        /*E strength of gun trigger(0~8 (0: Same as Off mode)). */
-                },
-                vibration_param: {
-                    // if mode_vibration
-                    position: 0,  /*E position where the motor arm start vibrating(0~9). */
-                    amplitude: 0, /*E vibration amplitude(0~8 (0: Same as Off mode)). */
-                    frequency: 0, /*E vibration frequency(0~255[Hz] (0: Same as Off mode)). */
-                },
-                multiple_position_feedback_param: {
-                    // if mode_multiple_position_feedback
-                    /*E strength that the motor arm pushes back target trigger at position(0~8 (0: Same as Off mode)).
-                        *  strength[0] means strength of motor arm at position0.
-                        *  strength[1] means strength of motor arm at position1.
-                        *  ...
-                        * */
-                    strength: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
-                },
-                slope_feedback_param: {
-                    // if mode_slope_feedback
-                    start_position: 0, /*E position where the strength of target trigger start changing(0~end_position). */
-                    end_position: 0,   /*E position where the strength of target trigger finish changing(start_position+1~9). */
-                    start_strength: 0, /*E strength when trigger's position is start_position(1~8) */
-                    end_strength: 0    /*E strength when trigger's position is end_position(1~8) */
-                },
-                multiple_position_vibration_param: {
-                    // if mode_multiple_position_vibration
-                    frequency: 0, /*E vibration frequency(0~255 (0: Same as Off mode)) */
-                    /*E vibration amplitude at position(0~8 (0: Same as Off mode)).
-                        *  amplitude[0] means amplitude of vibration at position0.
-                        *  amplitude[1] means amplitude of vibration at position1.
-                        *  ...
-                        * */
-                    amplitude: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
-                }
-            }
-        },
-        // R2 data: even if your mask tells "only l2", you MUST still include the dummy r2 field:
-        {
-            mode: steam_input_sce_pad_trigger_effect_mode_off,
-            command_data: {
-                // MUST be present even when mode_off!!
-            }
-        }
-    ]
-};
-// apply the parameters to the dualsense controller:
-steam_input_set_dualsense_trigger_effect(player_handle, _param);

The above code demonstrates the use of DualSense adaptive trigger effects in Steam Input, along with documenting every field in the struct.

- - -



-

Steam Utilities

-

- -

- -

Back To Top

-

Utilities

-

The Steam utility functions provide access to gamepad keyboard UI and Steam Deck getters.

-

The following functions can be used to access Steam Utilities from within GameMaker Studio 2

- - - -



-
- - -

Back To Top

-

steam_show_floating_gamepad_text_input

-

With this function you can show a floating gamepad keyboard window, all input is emulated as if it is a physical keyboard, so keyboard_string or keyboard_check can be used to obtain the input. This function only works in Big Picture or on the Steam Deck. Returns true if the keyboard has been shown successfully, false otherwise.

-
-

⚠️ IMPORTANT

-

You must call steam_utils_enable_callbacks prior to calling this function if you wish to receive Async - Steam gamepad keyboard events.

-
-


-

Syntax:

-
steam_show_floating_gamepad_text_input(mode, text_field_x, text_field_y, text_field_width, text_field_height);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
moderealA steam_floating_gamepad_text_input_mode_ constant.
text_field_xrealX position of the keyboard window in display coordinates.
text_field_yrealY position of the keyboard window in display coordinates.
text_field_widthrealWidth of the keyboard window in display coordinates.
text_field_heightrealHeight of the keyboard window in display coordinates.
-


-

async_load contents:

- - - - - - - - - - - - - - - -
KeyValueDescription
event_typestringA constant string "floating_gamepad_text_input_dismissed".
-


-

Returns:

-
Bool


-

Extended Example:

-
steam_utils_enable_callbacks(); // do this somewhere once.
-// show the dialog:
-steam_show_floating_gamepad_text_input(
-    steam_floating_gamepad_text_input_mode_single_line,
-    // in Display coordinates: use window_get_ or display_get_ functions to obtain the dimensions
-    window_get_x(),
-    window_get_y()/2,
-    window_get_width(),
-    window_get_height()/2
-);
/// @description Async - Steam event
-if (async_load[? "event_type"] == "floating_gamepad_text_input_dismissed") {
-    show_debug_message("Floating gamepad keyboard UI dialog dismissed.");
-}

The above code shows a floating keyboard window in the bottom half of the window, then print a message to debug output when the dialog is dismissed.

- - -



-
- - -

Back To Top

-

steam_dismiss_floating_gamepad_text_input

-

With this function you can dismiss a floating keyboard window if it is being currently shown. Returns true if the operation was successful, false otherwise.

-


-

Syntax:

-
steam_dismiss_floating_gamepad_text_input();


-

Returns:

-
Bool


-

Example:

-
steam_dismiss_floating_gamepad_text_input();

The above code will dismiss the floating keyboard window if it is being displayed.

- - -



-
- - -

Back To Top

-

steam_show_gamepad_text_input

-

With this function you can show a full-screen old-style Big Picture Mode-only keyboard UI. This one does not emulate the physical keyboard so you must use the steam_get_entered_gamepad_text_input function inside a corresponding Async - Steam event to obtain the input. Returns true if the window is being shown successfully, false otherwise.

-
-

⚠️ IMPORTANT

-

You must call steam_utils_enable_callbacks prior to calling this function if you wish to receive Async - Steam gamepad keyboard events.

-
-


-

Syntax:

-
steam_show_gamepad_text_input(mode,lines_mode,description,chars_max,existing_text);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentTypeDescription
moderealA steam_gamepad_text_input_mode_ constant.
lines_moderealA steam_gamepad_text_input_line_mode_ constant.
descriptionstringThe description of the window.
chars_maxrealThe maximum amount of characters the player can enter.
existing_textstringSome existing text to put into the text field or an empty string.
-


-

async_load contents:

- - - - - - - - - - - - - - - - - - - - - - - - - -
KeyValueDescription
event_typestringA string "gamepad_text_input_dismissed".
submittedbooltrue if the dialog was submitted successfully and false if it was cancelled.
submitted_text_raw_byte_lengthrealRaw length of the text in bytes.
-


-

Returns:

-
Bool


-

Extended Example:

-
steam_utils_enable_callbacks(); // somewhere once.
-// show the dialog:
-steam_show_gamepad_text_input(
-    steam_gamepad_text_input_mode_normal,
-    steam_gamepad_text_input_line_mode_single_line,
-    "Some Description",
-    100, // up to 100 string characters
-    "" // no default text, can be any string, ex: "Player 1" etc
-);
/// @description Async - Steam event
-if (async_load[? "event_type"] == "gamepad_text_input_dismissed") {
-    if (async_load[? "submitted"]) {
-        var _input = steam_get_entered_gamepad_text_input();
-        show_debug_message("Old-style dialog result: " + _input);
-    }
-}

The above code will show a modal gamepad keyboard input dialog with "Some Description" as the description and an empty text field, then print the typed text.

- - -



-
- - -

Back To Top

-

steam_get_entered_gamepad_text_input

-

With this function you can obtain the result of the steam_show_gamepad_text_input input dialog. This function must only be called in the corresponding Async - Steam event.

-
-

⚠️ IMPORTANT

-

You must call steam_utils_enable_callbacks prior to calling this function if you wish to receive Async - Steam gamepad keyboard events.

-
-


-

Syntax:

-
steam_get_entered_gamepad_text_input();


-

Returns:

-
string


-

Example:

-
/// @description Async - Steam event
-if (async_load[? "event_type"] == "gamepad_text_input_dismissed") {
-    if (async_load[? "submitted"]) {
-        var _input = steam_get_entered_gamepad_text_input();
-        show_debug_message("Old-style dialog result: " + _input);
-    }
-}

The above code will activate the use of gamepad keyboard UI async events.

- - -



-
- - -

Back To Top

-

steam_utils_enable_callbacks

-

With this function you can activate the dispatch of Async - Steam events for gamepad keyboard UI. Returns true if the operation was successful and false otherwise.

-


-

Syntax:

-
steam_utils_enable_callbacks();


-

Returns:

-
Bool


-

Example:

-
steam_utils_enable_callbacks();

The above code will activate the use of gamepad keyboard UI async events.

- - -



-
- - -

Back To Top

-

steam_utils_is_steam_running_on_steam_deck

-

With this function you can check if your game is currently running on a Steam Deck, returns true if yes and false otherwise.

-


-

Syntax:

-
steam_utils_is_steam_running_on_steam_deck();


-

Returns:

-
Bool


-

Example:

-
if (steam_utils_is_steam_running_on_steam_deck()) {
-    show_debug_message("The game is running on a Steam Deck.");
-}

The above code will print a message to debug output if the game is running on the Steam Deck.

- - -



- -
-
-
- - - \ No newline at end of file diff --git a/datafiles/Welcome files.zip b/datafiles/Welcome files.zip index a75ef88bf..f2a6fe01b 100644 Binary files a/datafiles/Welcome files.zip and b/datafiles/Welcome files.zip differ diff --git a/datafiles/README.txt b/datafiles/dllcredits.txt similarity index 100% rename from datafiles/README.txt rename to datafiles/dllcredits.txt diff --git a/scripts/_node_VFX_spawner/_node_VFX_spawner.gml b/scripts/_node_VFX_spawner/_node_VFX_spawner.gml index 4cc55bc17..06860795e 100644 --- a/scripts/_node_VFX_spawner/_node_VFX_spawner.gml +++ b/scripts/_node_VFX_spawner/_node_VFX_spawner.gml @@ -99,9 +99,7 @@ function Node_VFX_Spawner_Base(_x, _y, _group = noone) : Node(_x, _y, _group) co inputs[| 30] = nodeValue("Distribution map", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone) .rejectArray() - inputs[| 31] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [] ) - .setArrayDepth(1) - .rejectArray(); + inputs[| 31] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [] ); inputs[| 32] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(100000, 999999)) .rejectArray(); diff --git a/scripts/buffer_functions/buffer_functions.gml b/scripts/buffer_functions/buffer_functions.gml index fd8e62213..6f1fa7afc 100644 --- a/scripts/buffer_functions/buffer_functions.gml +++ b/scripts/buffer_functions/buffer_functions.gml @@ -6,6 +6,9 @@ function buffer_get_color(buffer, _x, _y, w, h) { #region } #endregion function buffer_get_string(buffer, text = true, limit = 400) { #region + if(is_array(buffer)) return "[buffer array]"; + if(!buffer_exists(buffer)) return ""; + buffer_seek(buffer, buffer_seek_start, 0); var len = min(limit, buffer_get_size(buffer)); var ss = ""; diff --git a/scripts/d3d_icosphere/d3d_icosphere.gml b/scripts/d3d_icosphere/d3d_icosphere.gml index e1cb260f7..f43c37fd3 100644 --- a/scripts/d3d_icosphere/d3d_icosphere.gml +++ b/scripts/d3d_icosphere/d3d_icosphere.gml @@ -5,20 +5,28 @@ function __vec3Sub(_x = 0, _y = _x, _z = _x) : __vec3(_x, _y, _z) constructor { static smooth = function() { if(array_empty(connected)) return; - var _k = array_length(connected) / 2; + var _n = array_length(connected); + var _k = _n / 2; var beta = 3 / (5 * _k); - var _s = self.multiply(1 - _k * beta); - var _c = new __vec3(); + var _sx = x * (1 - _k * beta); + var _sy = y * (1 - _k * beta); + var _sz = z * (1 - _k * beta); + var _cx = 0; + var _cy = 0; + var _cz = 0; - for( var i = 0; i < array_length(connected); i++ ) - _c._add(connected[i]); - _c._multiply(0.5 * beta)._add(_s); - set(_c); + for( var i = 0; i < _n; i++ ) { + _cx += connected[i].x; + _cy += connected[i].y; + _cz += connected[i].z; + } + + x = _cx * 0.5 * beta + _sx; + y = _cy * 0.5 * beta + _sy; + z = _cz * 0.5 * beta + _sz; } static connectTo = function(point) { array_push(connected, point); } - - static clearConnect = function() { connected = []; } } function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() constructor { @@ -32,10 +40,10 @@ function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() cons _vhash = ds_map_create(); static getVertex = function(vertex) { - var _hash = string(vertex); - if(ds_map_exists(_vhash, _hash)) - return _vhash[? _hash]; - _vhash[? _hash] = vertex; + var h = $"[{vertex.x},{vertex.y},{vertex.z}]"; + if(ds_map_exists(_vhash, h)) + return _vhash[? h]; + _vhash[? h] = vertex; return vertex; } @@ -63,7 +71,7 @@ function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() cons new __vec3Sub(-b, -a, 0)._normalize()._multiply(radius), ] - array_foreach(icoverts, function(vert) { vert.old = true; }) + array_foreach(icoverts, function(vert) { vert.old = true; }); // Generate icosphere vertices ds_list_add(_vertices, icoverts[ 3], icoverts[ 1], icoverts[ 2]); @@ -87,7 +95,8 @@ function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() cons ds_list_add(_vertices, icoverts[ 6], icoverts[ 5], icoverts[12]); ds_list_add(_vertices, icoverts[11], icoverts[ 5], icoverts[ 9]); - for( var w = 1; w <= level; w++ ) { #region subdivide + var lv = min(level, 5); + repeat(lv) { #region subdivide ds_map_clear(_vhash); var newVertices = ds_list_create(); @@ -115,7 +124,7 @@ function __3dICOSphere(radius = 0.5, level = 2, smt = false) : __3dObject() cons if(_v.old) _v.smooth(); _v.old = true; - _v.clearConnect(); + _v.connected = []; } ds_list_destroy(_vertices); diff --git a/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml b/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml index eba1f194f..a5afdd9be 100644 --- a/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml +++ b/scripts/node_3d_mesh_extrude/node_3d_mesh_extrude.gml @@ -28,6 +28,7 @@ function Node_3D_Mesh_Extrude(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _gr var _smt = _data[in_mesh + 2]; var _updt = _data[in_mesh + 3]; var _surf = _mat.surface; + if(!is_surface(_surf)) return noone; temp_surface[0] = surface_cvt_8unorm(temp_surface[0], _surf); temp_surface[1] = surface_cvt_8unorm(temp_surface[1], _hght); diff --git a/scripts/node_iterate_inline/node_iterate_inline.gml b/scripts/node_iterate_inline/node_iterate_inline.gml index 95cc85cea..96ba36b98 100644 --- a/scripts/node_iterate_inline/node_iterate_inline.gml +++ b/scripts/node_iterate_inline/node_iterate_inline.gml @@ -22,12 +22,11 @@ function Node_Iterate_Inline(_x, _y, _group = noone) : Node_Collection_Inline(_x static getIterationCount = function() { return getInputData(0); } - static bypassConnection = function() { #region - return iterated > 0 && !is_undefined(value_buffer); + static bypassConnection = function() { return iterated > 0 && !is_undefined(value_buffer); } #endregion static bypassNextNode = function() { #region - return iterated < getIterationCount(); + return iterated < getIterationCount() - 1; } #endregion static getNextNodes = function() { #region diff --git a/scripts/node_line/node_line.gml b/scripts/node_line/node_line.gml index 883ae845a..2453c2002 100644 --- a/scripts/node_line/node_line.gml +++ b/scripts/node_line/node_line.gml @@ -235,7 +235,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons var pointAmo = 0; var wght; var _pathPng; - + if(_useDistance) { _pathStr *= _pathLength; _pathEnd *= _pathLength; @@ -261,9 +261,9 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons } } - //print($"===== {_prog_curr} / {_segLength} : {_segIndex} - {_pathLength} ====="); + // print($"===== {_prog_curr} / {_segLength} : {_segIndex} - {_pathLength} ====="); - while(_total > 0) { + while(true) { wght = 1; _segIndexPrev = _segIndex; @@ -277,7 +277,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons if(_prog_next == segmentLength) _segIndex++; var _pp = _clamp? clamp(_pathPng, 0, _pathLength) : _pathPng; - //print($"_pp = {_pp}"); + // print($"_pp = {_pp}, total = {_total}"); p = _pat.getPointDistance(_pp, i, p); @@ -326,7 +326,9 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons pointAmo++; } - if(_prog_next == _prog_curr && _segIndexPrev == _segIndex) break; + if(_total <= 0) break; + + if(_prog_next == _prog_curr && _segIndexPrev == _segIndex) { print("Terminate line not moving"); break; } else if(_prog_next > _prog_curr) { _prog_total += _prog_next - _prog_curr; _total -= _prog_next - _prog_curr; @@ -340,7 +342,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons if(_total_prev == _total && _segIndexPrev == _segIndex && ++_freeze > 16) { print("Terminate line not moving"); break; } _total_prev = _total; - if(_segIndex >= _segLengthAmo) break; + if(_segIndex >= _segLengthAmo) { print("Terminate line finish last segment"); break; } } array_resize(points, pointAmo); diff --git a/scripts/node_path_bridge/node_path_bridge.gml b/scripts/node_path_bridge/node_path_bridge.gml index 817ff84e2..675dbe2bf 100644 --- a/scripts/node_path_bridge/node_path_bridge.gml +++ b/scripts/node_path_bridge/node_path_bridge.gml @@ -109,12 +109,8 @@ function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constru var _ind = 0; var n = array_length(_la); - var _d = _dist; - for(; _ind < n; _ind++ ) { - if(_d < _la[_ind]) break; - _d -= _la[_ind]; - } + for(; _ind < n; _ind++ ) if(_dist < _la[_ind]) break; if(_ind >= n) { var _p = _a[_ind]; @@ -125,7 +121,8 @@ function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constru return out; } - var _rat = _d / _la[_ind]; + var _d = _ind == 0? _dist : _dist - _la[_ind - 1]; + var _rat = _d / (_la[_ind] - (_ind == 0? 0 : _la[_ind - 1])); var p0 = _a[_ind]; var p1 = _a[_ind + 1]; @@ -163,8 +160,10 @@ function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constru var _p = new __vec2(); var _rat; - anchors = array_create(_amo); - + anchors = array_create(_amo); + lengths = array_create(_amo); + lengthAccs = array_create(_amo); + for( var i = 0; i < _amo; i++ ) { var _a = array_create(_lines); _rat = _amo == 1? 0.5 : i / (_amo - 1); @@ -231,13 +230,13 @@ function Node_Path_Bridge(_x, _y, _group = noone) : Node(_x, _y, _group) constru oy = ny; } - array_push(_la, _ll); _l += _ll; + array_push(_la, _l); } - + lengths[i] = _l; lengthAccs[i] = _la; - + } else { var _l = 0, _la = []; var ox, oy, nx, ny;