diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 14d16f5b5..d87408a08 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -57,7 +57,7 @@ {"name":"drawer","order":11,"path":"folders/nodes/data/generator/drawer.yy",}, {"name":"noise","order":14,"path":"folders/nodes/data/generator/noise.yy",}, {"name":"pattern","order":15,"path":"folders/nodes/data/generator/pattern.yy",}, - {"name":"ray march","order":21,"path":"folders/nodes/data/generator/ray march.yy",}, + {"name":"raymarching","order":13,"path":"folders/nodes/data/3D/raymarching.yy",}, {"name":"regions","order":19,"path":"folders/nodes/data/generator/regions.yy",}, {"name":"group","order":18,"path":"folders/nodes/data/group.yy",}, {"name":"io","order":19,"path":"folders/nodes/data/io.yy",}, @@ -166,11 +166,11 @@ {"name":"blinker","order":19,"path":"folders/shader/generator/blinker.yy",}, {"name":"cell","order":20,"path":"folders/shader/generator/cell.yy",}, {"name":"grid","order":18,"path":"folders/shader/generator/grid.yy",}, - {"name":"texture repeat","order":28,"path":"folders/shader/generator/texture repeat.yy",}, {"name":"interpret","order":17,"path":"folders/shader/generator/interpret.yy",}, {"name":"random_shape","order":21,"path":"folders/shader/generator/random_shape.yy",}, {"name":"reaction_diffusion","order":22,"path":"folders/shader/generator/reaction_diffusion.yy",}, {"name":"region","order":23,"path":"folders/shader/generator/region.yy",}, + {"name":"texture repeat","order":28,"path":"folders/shader/generator/texture repeat.yy",}, {"name":"vector_mapper","order":24,"path":"folders/shader/generator/vector_mapper.yy",}, {"name":"mask","order":10,"path":"folders/shader/mask.yy",}, {"name":"misc","order":11,"path":"folders/shader/misc.yy",}, @@ -346,6 +346,7 @@ {"name":"__path","order":1,"path":"scripts/__path/__path.yy",}, {"name":"__pbBox","order":3,"path":"scripts/__pbBox/__pbBox.yy",}, {"name":"__polygon","order":2,"path":"scripts/__polygon/__polygon.yy",}, + {"name":"__raymarching","order":4,"path":"scripts/__raymarching/__raymarching.yy",}, {"name":"__rectangle","order":7,"path":"scripts/__rectangle/__rectangle.yy",}, {"name":"__shapes","order":3,"path":"scripts/__shapes/__shapes.yy",}, {"name":"__sliderRange","order":3,"path":"scripts/__sliderRange/__sliderRange.yy",}, @@ -1002,6 +1003,7 @@ {"name":"node_rigid_variable","order":11,"path":"scripts/node_rigid_variable/node_rigid_variable.yy",}, {"name":"node_rigid_wall","order":12,"path":"scripts/node_rigid_wall/node_rigid_wall.yy",}, {"name":"node_rim","order":22,"path":"scripts/node_rim/node_rim.yy",}, + {"name":"node_rm_combine","order":3,"path":"scripts/node_rm_combine/node_rm_combine.yy",}, {"name":"node_rm_primitive","order":1,"path":"scripts/node_rm_primitive/node_rm_primitive.yy",}, {"name":"node_rm_terrain","order":2,"path":"scripts/node_rm_terrain/node_rm_terrain.yy",}, {"name":"node_sampler","order":3,"path":"scripts/node_sampler/node_sampler.yy",}, @@ -1971,6 +1973,7 @@ {"name":"s_node_rigidSim_render_output","order":10,"path":"sprites/s_node_rigidSim_render_output/s_node_rigidSim_render_output.yy",}, {"name":"s_node_rigidSim_renderer","order":1,"path":"sprites/s_node_rigidSim_renderer/s_node_rigidSim_renderer.yy",}, {"name":"s_node_rigidSim_wall","order":11,"path":"sprites/s_node_rigidSim_wall/s_node_rigidSim_wall.yy",}, + {"name":"s_node_rm_combine","order":26,"path":"sprites/s_node_rm_combine/s_node_rm_combine.yy",}, {"name":"s_node_rm_primitive","order":51,"path":"sprites/s_node_rm_primitive/s_node_rm_primitive.yy",}, {"name":"s_node_rm_terrain","order":52,"path":"sprites/s_node_rm_terrain/s_node_rm_terrain.yy",}, {"name":"s_node_sampler","order":19,"path":"sprites/s_node_sampler/s_node_sampler.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 7d1af578d..5a4922923 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -155,7 +155,7 @@ {"$GMFolder":"","%Name":"drawer","folderPath":"folders/nodes/data/generator/drawer.yy","name":"drawer","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"noise","folderPath":"folders/nodes/data/generator/noise.yy","name":"noise","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"pattern","folderPath":"folders/nodes/data/generator/pattern.yy","name":"pattern","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"ray march","folderPath":"folders/nodes/data/generator/ray march.yy","name":"ray march","resourceType":"GMFolder","resourceVersion":"2.0",}, + {"$GMFolder":"","%Name":"raymarching","folderPath":"folders/nodes/data/3D/raymarching.yy","name":"raymarching","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"regions","folderPath":"folders/nodes/data/generator/regions.yy","name":"regions","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"group","folderPath":"folders/nodes/data/group.yy","name":"group","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"io","folderPath":"folders/nodes/data/io.yy","name":"io","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -288,11 +288,11 @@ {"$GMFolder":"","%Name":"blinker","folderPath":"folders/shader/generator/blinker.yy","name":"blinker","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"cell","folderPath":"folders/shader/generator/cell.yy","name":"cell","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"grid","folderPath":"folders/shader/generator/grid.yy","name":"grid","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"texture repeat","folderPath":"folders/shader/generator/texture repeat.yy","name":"texture repeat","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"interpret","folderPath":"folders/shader/generator/interpret.yy","name":"interpret","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"random_shape","folderPath":"folders/shader/generator/random_shape.yy","name":"random_shape","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"reaction_diffusion","folderPath":"folders/shader/generator/reaction_diffusion.yy","name":"reaction_diffusion","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"region","folderPath":"folders/shader/generator/region.yy","name":"region","resourceType":"GMFolder","resourceVersion":"2.0",}, + {"$GMFolder":"","%Name":"texture repeat","folderPath":"folders/shader/generator/texture repeat.yy","name":"texture repeat","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"vector_mapper","folderPath":"folders/shader/generator/vector_mapper.yy","name":"vector_mapper","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"mask","folderPath":"folders/shader/mask.yy","name":"mask","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"misc","folderPath":"folders/shader/misc.yy","name":"misc","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -670,6 +670,7 @@ {"id":{"name":"__path","path":"scripts/__path/__path.yy",},}, {"id":{"name":"__pbBox","path":"scripts/__pbBox/__pbBox.yy",},}, {"id":{"name":"__polygon","path":"scripts/__polygon/__polygon.yy",},}, + {"id":{"name":"__raymarching","path":"scripts/__raymarching/__raymarching.yy",},}, {"id":{"name":"__rectangle","path":"scripts/__rectangle/__rectangle.yy",},}, {"id":{"name":"__shapes","path":"scripts/__shapes/__shapes.yy",},}, {"id":{"name":"__sliderRange","path":"scripts/__sliderRange/__sliderRange.yy",},}, @@ -1431,6 +1432,7 @@ {"id":{"name":"node_rigid_variable","path":"scripts/node_rigid_variable/node_rigid_variable.yy",},}, {"id":{"name":"node_rigid_wall","path":"scripts/node_rigid_wall/node_rigid_wall.yy",},}, {"id":{"name":"node_rim","path":"scripts/node_rim/node_rim.yy",},}, + {"id":{"name":"node_rm_combine","path":"scripts/node_rm_combine/node_rm_combine.yy",},}, {"id":{"name":"node_rm_primitive","path":"scripts/node_rm_primitive/node_rm_primitive.yy",},}, {"id":{"name":"node_rm_terrain","path":"scripts/node_rm_terrain/node_rm_terrain.yy",},}, {"id":{"name":"node_sampler","path":"scripts/node_sampler/node_sampler.yy",},}, @@ -2537,6 +2539,7 @@ {"id":{"name":"s_node_rigidSim_renderer","path":"sprites/s_node_rigidSim_renderer/s_node_rigidSim_renderer.yy",},}, {"id":{"name":"s_node_rigidSim_wall","path":"sprites/s_node_rigidSim_wall/s_node_rigidSim_wall.yy",},}, {"id":{"name":"s_node_rigidSim","path":"sprites/s_node_rigidSim/s_node_rigidSim.yy",},}, + {"id":{"name":"s_node_rm_combine","path":"sprites/s_node_rm_combine/s_node_rm_combine.yy",},}, {"id":{"name":"s_node_rm_primitive","path":"sprites/s_node_rm_primitive/s_node_rm_primitive.yy",},}, {"id":{"name":"s_node_rm_terrain","path":"sprites/s_node_rm_terrain/s_node_rm_terrain.yy",},}, {"id":{"name":"s_node_sampler","path":"sprites/s_node_sampler/s_node_sampler.yy",},}, diff --git a/scripts/__3D/__3D.gml b/scripts/__3D/__3D.gml index 792ef13b6..9e39cec23 100644 --- a/scripts/__3D/__3D.gml +++ b/scripts/__3D/__3D.gml @@ -571,8 +571,8 @@ enum CAMERA_PROJ { shader_set(shader); shader_set_uniform_f_array_safe(uniVertex_lightFor, lightFor); - shader_set_uniform_f_array_safe(uniLightAmb, colorArrayFromReal(_aclr)); - shader_set_uniform_f_array_safe(uniLightClr, colorArrayFromReal(_lclr)); + shader_set_uniform_f_array_safe(uniLightAmb, colorToArray(_aclr)); + shader_set_uniform_f_array_safe(uniLightClr, colorToArray(_lclr)); shader_set_uniform_f(uniLightInt, _lint); shader_set_uniform_i(uniLightNrm, use_normal); diff --git a/scripts/__raymarching/__raymarching.gml b/scripts/__raymarching/__raymarching.gml new file mode 100644 index 000000000..f7c0ae858 --- /dev/null +++ b/scripts/__raymarching/__raymarching.gml @@ -0,0 +1,195 @@ +function RM_Object() constructor { + id = UUID_generate(); + shapeAmount = 0; + + shape = []; + size = []; + radius = []; + thickness = []; + crop = []; + angle = []; + height = []; + radRange = []; + sizeUni = []; + elongate = []; + rounded = []; + corner = []; + size2D = []; + sides = []; + + waveAmp = []; + waveInt = []; + waveShift = []; + + twistAxis = []; + twistAmount = []; + + position = []; + rotation = []; + objectScale = []; + + tileSize = []; + tileAmount = []; + + diffuseColor = []; + reflective = []; + + volumetric = []; + volumeDensity = []; + + texture = []; + useTexture = []; + textureScale = []; + triplanar = []; + + opmap = -1; + + uniformKeys = [ "shape", "size", "radius", "thickness", "crop", "angle", "height", "radRange", "sizeUni", "elongate", "rounded", "corner", "size2D", "sides", + "waveAmp", "waveInt", "waveShift", + "twistAxis", "twistAmount", + "position", "rotation", "objectScale", + "tileSize", "tileAmount", + "diffuseColor", "reflective", + "volumetric", "volumeDensity", + "texture", "useTexture", "textureScale", "triplanar" + ]; + textureAtl = noone; + + static setTexture = function(textureAtlas) { + var tx = 1024; + + surface_set_shader(textureAtlas); + for (var i = 0; i < shapeAmount; i++) + draw_surface_stretched_safe(texture[i], tx * (i % 8), tx * floor(i / 8), tx, tx); + surface_reset_shader(); + + textureAtl = textureAtlas; + } + + static apply = function() { + // print(self); + + shader_set_i("shapeAmount", shapeAmount); + if(shapeAmount <= 0) return; + + shader_set_i("operations", opmap); + shader_set_i("opLength", array_safe_length(opmap)); + + shader_set_i("shape", shape); + shader_set_f("size", size); + shader_set_f("radius", radius); + shader_set_f("thickness", thickness); + shader_set_f("crop", crop); + shader_set_f("angle", angle); + shader_set_f("height", height); + shader_set_f("radRange", radRange); + shader_set_f("sizeUni", sizeUni); + shader_set_f("elongate", elongate); + shader_set_f("rounded", rounded); + shader_set_f("corner", corner); + shader_set_f("size2D", size2D); + shader_set_i("sides", sides); + + shader_set_f("waveAmp", waveAmp); + shader_set_f("waveInt", waveInt); + shader_set_f("waveShift", waveShift); + + shader_set_i("twistAxis", twistAxis); + shader_set_f("twistAmount", twistAmount); + + shader_set_f("position", position); + shader_set_f("rotation", rotation); + shader_set_f("objectScale", objectScale); + + shader_set_f("tileSize", tileSize); + shader_set_f("tileAmount", tileAmount); + + shader_set_f("diffuseColor", diffuseColor); + shader_set_f("reflective", reflective); + + shader_set_i("volumetric", volumetric); + shader_set_f("volumeDensity", volumeDensity); + + /////////////////////////////////////////////////////////////// + + shader_set_surface("texture1", textureAtl); + shader_set_i("useTexture", useTexture); + shader_set_f("textureScale", textureScale); + shader_set_f("triplanar", triplanar); + } +} + +function RM_Operation(type, left, right) : RM_Object() constructor { + + self.type = type; + self.left = left; + self.right = right; + + static reset = function() { + + for (var i = 0, n = array_length(uniformKeys); i < n; i++) + self[$ uniformKeys[i]] = []; + } + + static add = function(rmObject) { + + for (var i = 0, n = array_length(uniformKeys); i < n; i++) + array_append(self[$ uniformKeys[i]], rmObject[$ uniformKeys[i]]); + } + + static __flatten = function(node) { + if(is_instanceof(node, RM_Shape)) + return node; + + var _op = node.type; + var _l = node.left; + var _r = node.right; + + var _arr = [ ]; + + array_append(_arr, __flatten(_l)); + array_append(_arr, __flatten(_r)); + array_push(_arr, _op); + + return _arr; + } + + static flatten = function() { + var _arr = __flatten(self); + var _nodes = []; + + for (var i = 0, n = array_length(_arr); i < n; i++) { + var _a = _arr[i]; + + if(!is_struct(_a)) continue; + if(array_exists(_nodes, _a)) continue; + + _a.flatten_index = array_length(_nodes); + array_push(_nodes, _a); + } + + opmap = []; + for (var i = 0, n = array_length(_arr); i < n; i++) { + var _a = _arr[i]; + + if(is_string(_a)) { + switch(_a) { + case "combine" : array_push(opmap, 100); break; + } + } else if(is_struct(_a)) + array_push(opmap, _a.flatten_index); + } + + // print(opmap); + shapeAmount = array_length(_nodes); + + reset(); + for (var i = 0, n = array_length(_nodes); i < n; i++) + add(_nodes[i]); + } + +} + +function RM_Shape() : RM_Object() constructor { + +} \ No newline at end of file diff --git a/scripts/__raymarching/__raymarching.yy b/scripts/__raymarching/__raymarching.yy new file mode 100644 index 000000000..1e9f4d812 --- /dev/null +++ b/scripts/__raymarching/__raymarching.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"__raymarching", + "isCompatibility":false, + "isDnD":false, + "name":"__raymarching", + "parent":{ + "name":"raymarching", + "path":"folders/nodes/data/3D/raymarching.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/array_functions/array_functions.gml b/scripts/array_functions/array_functions.gml index ab8c8c40e..a02cb28c5 100644 --- a/scripts/array_functions/array_functions.gml +++ b/scripts/array_functions/array_functions.gml @@ -187,8 +187,8 @@ function array_insert_unique(arr, ind, val) { #region function array_append(arr, arr0) { #region INLINE - if(!is_array(arr)) return arr; - if(!is_array(arr0)) return arr; + if(!is_array(arr)) return arr; + if(!is_array(arr0)) { array_push(arr, arr0); return arr; } for( var i = 0, n = array_length(arr0); i < n; i++ ) array_push(arr, arr0[i]); diff --git a/scripts/color_function/color_function.gml b/scripts/color_function/color_function.gml index 0b1e364b0..0104c5b35 100644 --- a/scripts/color_function/color_function.gml +++ b/scripts/color_function/color_function.gml @@ -53,8 +53,9 @@ return make_color_rgb(r, g, b); } #endregion - function colorArrayFromReal(clr) { #region + function colorToArray(clr, alpha = false) { #region INLINE + if(alpha) return [ _color_get_red(clr), _color_get_green(clr), _color_get_blue(clr), _color_get_alpha(clr) ]; return [ _color_get_red(clr), _color_get_green(clr), _color_get_blue(clr) ]; } #endregion diff --git a/scripts/globals/globals.gml b/scripts/globals/globals.gml index 45801576e..86270587b 100644 --- a/scripts/globals/globals.gml +++ b/scripts/globals/globals.gml @@ -38,7 +38,7 @@ LATEST_VERSION = 11700; VERSION = 11740; SAVE_VERSION = 11700; - VERSION_STRING = "1.17.4.002"; + VERSION_STRING = "1.17.4.003"; BUILD_NUMBER = 11740; globalvar HOTKEYS, HOTKEY_CONTEXT; diff --git a/scripts/node_gradient_points/node_gradient_points.gml b/scripts/node_gradient_points/node_gradient_points.gml index c1f1c4852..2caf60615 100644 --- a/scripts/node_gradient_points/node_gradient_points.gml +++ b/scripts/node_gradient_points/node_gradient_points.gml @@ -96,9 +96,9 @@ function Node_Gradient_Points(_x, _y, _group = noone) : Node_Processor(_x, _y, _ if(_usePal) { for( var i = 0; i < 4; i++ ) - colArr = array_append(colArr, colorArrayFromReal(array_safe_get_fast(_pal, i, c_black))); + colArr = array_append(colArr, colorToArray(array_safe_get_fast(_pal, i, c_black))); } else - colArr = array_merge(colorArrayFromReal(_1col), colorArrayFromReal(_2col), colorArrayFromReal(_3col), colorArrayFromReal(_4col)) + colArr = array_merge(colorToArray(_1col), colorToArray(_2col), colorToArray(_3col), colorToArray(_4col)) surface_set_shader(_outSurf, sh_gradient_points); diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index eb9d8693b..486eaae09 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -741,7 +741,7 @@ function __initNodes() { addNodeObject(generator, "Random Tile", s_node_random_tile, "Node_Random_Tile", [1, Node_Random_Tile],, "Generate Random tile pattern.").patreonExtra(); addNodeObject(generator, "Quasicrystal", s_node_quasicircle, "Node_Quasicrystal", [1, Node_Quasicrystal]).setVersion(11660); addNodeObject(generator, "Pixel Sampler", s_node_pixel_sampler, "Node_Pixel_Sampler", [1, Node_Pixel_Sampler]).setVersion(11730); - + ds_list_add(generator, "Populate"); addNodeObject(generator, "Repeat", s_node_repeat, "Node_Repeat", [1, Node_Repeat],, "Repeat image multiple times linearly, or in grid pattern.").setVersion(1100); addNodeObject(generator, "Scatter", s_node_scatter, "Node_Scatter", [1, Node_Scatter],, "Scatter image randomly multiple times."); @@ -765,6 +765,7 @@ function __initNodes() { ds_list_add(generator, "Ray Marching"); addNodeObject(generator, "RM Primitive", s_node_rm_primitive, "Node_RM_Primitive", [1, Node_RM_Primitive], ["ray marching"]).setVersion(11720); addNodeObject(generator, "RM Terrain", s_node_rm_terrain, "Node_RM_Terrain", [1, Node_RM_Terrain], ["ray marching"]).setVersion(11720); + addNodeObject(generator, "RM Combine", s_node_rm_combine, "Node_RM_Combine", [1, Node_RM_Combine], ["ray marching"]).setVersion(11740); ds_list_add(generator, "MK Effects"); addNodeObject(generator, "MK Rain", s_node_mk_rain, "Node_MK_Rain", [1, Node_MK_Rain]).setVersion(11600); diff --git a/scripts/node_rm_combine/node_rm_combine.gml b/scripts/node_rm_combine/node_rm_combine.gml new file mode 100644 index 000000000..3dfed472f --- /dev/null +++ b/scripts/node_rm_combine/node_rm_combine.gml @@ -0,0 +1,120 @@ +function Node_RM_Combine(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "RM Combine"; + batch_output = true; + + inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF) + .setDisplay(VALUE_DISPLAY.vector); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + inputs[| 1] = nodeValue("Projection", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .setDisplay(VALUE_DISPLAY.enum_button, [ "Perspective", "Orthographic" ]) + .setVisible(false, false); + + inputs[| 2] = nodeValue("FOV", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 30) + .setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 90, 1 ] }); + + inputs[| 3] = nodeValue("Ortho Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 5.) + + inputs[| 4] = nodeValue("View Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 3, 6 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 5] = nodeValue("Depth", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 6] = nodeValue("Draw BG", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true); + + inputs[| 7] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_black); + + inputs[| 8] = nodeValue("Ambient Level", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.2) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 9] = nodeValue("Light Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ -.5, -.5, 1 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 10] = nodeValue("Environment", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, false); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + inputs[| 11] = nodeValue("Shape 1", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {}) + .setVisible(true, true); + + inputs[| 12] = nodeValue("Shape 2", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {}) + .setVisible(true, true); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + + outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone); + + input_display_list = [ 0, + ["Camera", false], 1, 2, 3, 4, 5, + ["Render", false], 6, 7, 8, 10, 9, + ["Shapes", false], 11, 12, + ] + + temp_surface = [ 0, 0 ]; + + static processData = function(_outSurf, _data, _output_index, _array_index = 0) { + var _dim = _data[0]; + + var _pro = _data[1]; + var _fov = _data[2]; + var _ort = _data[3]; + var _vrn = _data[4]; + var _dep = _data[5]; + + var _bgd = _data[6]; + var _bgc = _data[7]; + var _amb = _data[8]; + var _lig = _data[9]; + var _env = _data[10]; + + var _sh0 = _data[11]; + var _sh1 = _data[12]; + + if(!is_instanceof(_sh0, RM_Object)) return [ _outSurf, noone ]; + if(!is_instanceof(_sh1, RM_Object)) return [ _outSurf, noone ]; + + _outSurf = surface_verify(_outSurf, _dim[0], _dim[1]); + + for (var i = 0, n = array_length(temp_surface); i < n; i++) + temp_surface[i] = surface_verify(temp_surface[i], 8192, 8192); + + var tx = 1024; + surface_set_shader(temp_surface[0]); + draw_surface_stretched_safe(_env, tx * 0, tx * 0, tx, tx); + surface_reset_shader(); + + var object = new RM_Operation("combine", _sh0, _sh1); + object.flatten(); + object.setTexture(temp_surface[1]); + + gpu_set_texfilter(true); + surface_set_shader(_outSurf, sh_rm_primitive); + + shader_set_surface($"texture0", temp_surface[0]); + + shader_set_i("ortho", _pro); + shader_set_f("fov", _fov); + shader_set_f("orthoScale", _ort); + shader_set_f("viewRange", _vrn); + shader_set_f("depthInt", _dep); + + shader_set_i("drawBg", _bgd); + shader_set_color("background", _bgc); + shader_set_f("ambientIntns", _amb); + shader_set_f("lightPosition", _lig); + + shader_set_i("useEnv", is_surface(_env)); + + object.apply(); + + draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1]); + surface_reset_shader(); + gpu_set_texfilter(false); + + return [ _outSurf, object ]; + } +} \ No newline at end of file diff --git a/scripts/node_rm_combine/node_rm_combine.yy b/scripts/node_rm_combine/node_rm_combine.yy new file mode 100644 index 000000000..f96420a42 --- /dev/null +++ b/scripts/node_rm_combine/node_rm_combine.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_rm_combine", + "isCompatibility":false, + "isDnD":false, + "name":"node_rm_combine", + "parent":{ + "name":"raymarching", + "path":"folders/nodes/data/3D/raymarching.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_rm_primitive/node_rm_primitive.gml b/scripts/node_rm_primitive/node_rm_primitive.gml index 3a2deefd5..337f2d611 100644 --- a/scripts/node_rm_primitive/node_rm_primitive.gml +++ b/scripts/node_rm_primitive/node_rm_primitive.gml @@ -1,15 +1,16 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "RM Primitive"; + batch_output = true; inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF) .setDisplay(VALUE_DISPLAY.vector); shape_types = [ - "Plane", "Box", "Box Frame", + "Plane", "Box", "Box Frame", "Box Round", -1, "Sphere", "Ellipse", "Cut Sphere", "Cut Hollow Sphere", "Torus", "Capped Torus", -1, - "Cylinder", "Capsule", "Cone", "Capped Cone", "Round Cone", "3D Arc", + "Cylinder", "Prism", "Capsule", "Cone", "Capped Cone", "Round Cone", "3D Arc", -1, "Octahedron", "Pyramid", ]; @@ -102,8 +103,8 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro inputs[| 26] = nodeValue("Height", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, .5) .setDisplay(VALUE_DISPLAY.slider); - inputs[| 27] = nodeValue("Radius Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, .7) - .setDisplay(VALUE_DISPLAY.slider); + inputs[| 27] = nodeValue("Radius Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ .7, .1 ]) + .setDisplay(VALUE_DISPLAY.slider_range); inputs[| 28] = nodeValue("Uniform Size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) .setDisplay(VALUE_DISPLAY.slider); @@ -136,21 +137,34 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro inputs[| 38] = nodeValue("Texture Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1.); + inputs[| 39] = nodeValue("Corner", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0.25, 0.25, 0.25, 0.25 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 40] = nodeValue("2D Size", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0.5, 0.5 ]) + .setDisplay(VALUE_DISPLAY.vector); + + inputs[| 41] = nodeValue("Side", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 3); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + outputs[| 0] = nodeValue("Surface Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + outputs[| 1] = nodeValue("Shape Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, noone); + input_display_list = [ 0, - ["Primitive", false], 1, 21, 22, 23, 24, 25, 26, 27, 28, + ["Primitive", false], 1, 21, 22, 23, 24, 25, 26, 27, 28, 39, 40, 41, ["Modify", false], 12, 11, ["Deform", true], 15, 16, 17, 18, 19, - ["Transform", false], 2, 3, 4, - ["Material", false], 9, 36, 35, 37, 38, - ["Camera", false], 13, 14, 5, 6, - ["Render", false], 31, 30, 34, 10, 7, 8, + ["Transform", false], 2, 3, 4, + ["Material", false], 9, 36, 35, 37, 38, + ["Camera", false], 13, 14, 5, 6, + ["Render", false], 31, 30, 34, 10, 7, 8, ["Tile", false], 20, 29, ["Volumetric", true, 32], 33, ]; - temp_surface = [ 0, 0, 0, 0 ]; + temp_surface = [ 0, 0 ]; + object = new RM_Shape(); static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {} @@ -166,6 +180,9 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro inputs[| 26].setVisible(false); inputs[| 27].setVisible(false); inputs[| 28].setVisible(false); + inputs[| 39].setVisible(false); + inputs[| 40].setVisible(false); + inputs[| 41].setVisible(false); var _shape = shape_types[_shp]; switch(_shape) { // Size @@ -191,11 +208,13 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro switch(_shape) { // Thickness case "Box Frame" : + case "Box Round" : case "Torus" : case "Cut Hollow Sphere" : case "Capped Torus" : case "Terrain" : case "Extrude" : + case "Prism" : inputs[| 23].setVisible(true); break; } @@ -241,6 +260,24 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro break; } + switch(_shape) { // Corner + case "Box Round" : + inputs[| 39].setVisible(true); + break; + } + + switch(_shape) { // Size 2D + case "Box Round" : + inputs[| 40].setVisible(true); + break; + } + + switch(_shape) { // Sides + case "Prism" : + inputs[| 41].setVisible(true); + break; + } + inputs[| 5].setVisible(_ort == 0); inputs[| 14].setVisible(_ort == 1); } @@ -293,6 +330,9 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro var _text = _data[36]; var _triS = _data[37]; var _texs = _data[38]; + var _corn = _data[39]; + var _sz2d = _data[40]; + var _side = _data[41]; _outSurf = surface_verify(_outSurf, _dim[0], _dim[1]); @@ -302,96 +342,105 @@ function Node_RM_Primitive(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro var tx = 1024; surface_set_shader(temp_surface[0]); draw_surface_stretched_safe(bgEnv, tx * 0, tx * 0, tx, tx); - draw_surface_stretched_safe(_text, tx * 1, tx * 0, tx, tx); surface_reset_shader(); - gpu_set_texfilter(true); + var _shape = shape_types[_shp]; + var _shpI = 0; + switch(_shape) { + case "Plane" : _shpI = 100; break; + case "Box" : _shpI = 101; break; + case "Box Frame" : _shpI = 102; break; + case "Box Round" : _shpI = 103; break; + + case "Sphere" : _shpI = 200; break; + case "Ellipse" : _shpI = 201; break; + case "Cut Sphere" : _shpI = 202; break; + case "Cut Hollow Sphere" : _shpI = 203; _crop = _crop / pi * 2.15; break; + case "Torus" : _shpI = 204; break; + case "Capped Torus" : _shpI = 205; break; + + case "Cylinder" : _shpI = 300; break; + case "Capsule" : _shpI = 301; break; + case "Cone" : _shpI = 302; break; + case "Capped Cone" : _shpI = 303; break; + case "Round Cone" : _shpI = 304; break; + case "3D Arc" : _shpI = 305; break; + case "Prism" : _shpI = 306; break; + + case "Octahedron" : _shpI = 400; break; + case "Pyramid" : _shpI = 401; break; + } + + object.operations = -1; + object.shapeAmount = 1; + + object.shape = _shpI; + object.size = _size; + object.radius = _rad ; + object.thickness = _thk ; + object.crop = _crop; + object.angle = degtorad(_angl); + object.height = _heig; + object.radRange = _radR; + object.sizeUni = _sizz; + object.elongate = _elon; + object.rounded = _rond; + object.corner = _corn; + object.size2D = _sz2d; + object.sides = _side; + + object.waveAmp = _wavA; + object.waveInt = _wavI; + object.waveShift = _wavS; + + object.twistAxis = _twsX; + object.twistAmount = _twsA; + + object.position = _pos; + object.rotation = _rot; + object.objectScale = _sca; + + object.tileSize = _tile; + object.tileAmount = _tilA; + + object.diffuseColor = colorToArray(_amb, true); + object.reflective = _refl; + + object.volumetric = _vol; + object.volumeDensity = _vden; + + object.texture = [ _text ]; + object.useTexture = is_surface(_text); + object.textureScale = _texs; + object.triplanar = _triS; + + object.setTexture(temp_surface[1]); + + gpu_set_texfilter(true); surface_set_shader(_outSurf, sh_rm_primitive); - var _shape = shape_types[_shp]; - var _shpI = 0; - - switch(_shape) { - case "Plane" : _shpI = 100; break; - case "Box" : _shpI = 101; break; - case "Box Frame" : _shpI = 102; break; - - case "Sphere" : _shpI = 200; break; - case "Ellipse" : _shpI = 201; break; - case "Cut Sphere" : _shpI = 202; break; - case "Cut Hollow Sphere" : _shpI = 203; _crop = _crop / pi * 2.15; break; - case "Torus" : _shpI = 204; break; - case "Capped Torus" : _shpI = 205; break; - - case "Cylinder" : _shpI = 300; break; - case "Capsule" : _shpI = 301; break; - case "Cone" : _shpI = 302; break; - case "Capped Cone" : _shpI = 303; break; - case "Round Cone" : _shpI = 304; break; - case "3D Arc" : _shpI = 305; break; - - case "Octahedron" : _shpI = 400; break; - case "Pyramid" : _shpI = 401; break; - } - - for (var i = 0, n = array_length(temp_surface); i < n; i++) - shader_set_surface($"texture{i}", temp_surface[i]); - - shader_set_f("time", CURRENT_FRAME / TOTAL_FRAMES); - - shader_set_i("shape", _shpI); - shader_set_f("size", _size); - shader_set_f("radius", _rad); - shader_set_f("thickness", _thk); - shader_set_f("crop", _crop); - shader_set_f("angle", degtorad(_angl)); - shader_set_f("height", _heig); - shader_set_f("radRange", _radR); - shader_set_f("sizeUni", _sizz); - shader_set_f("elongate", _elon); - shader_set_f("rounded", _rond); - - shader_set_f("waveAmp", _wavA); - shader_set_f("waveInt", _wavI); - shader_set_f("waveShift", _wavS); - - shader_set_i("twistAxis", _twsX); - shader_set_f("twistAmount", _twsA); - - shader_set_f("position", _pos); - shader_set_f("rotation", _rot); - shader_set_f("objectScale", _sca); + shader_set_surface($"texture0", temp_surface[0]); shader_set_i("ortho", _ort); shader_set_f("fov", _fov); shader_set_f("orthoScale", _ortS); shader_set_f("viewRange", _rng); shader_set_f("depthInt", _dpi); - shader_set_f("tileSize", _tile); - shader_set_f("tileAmount", _tilA); shader_set_i("drawBg", _bgd); shader_set_color("background", _bgc); shader_set_f("ambientIntns", _ambI); shader_set_f("lightPosition", _lPos); - shader_set_color("ambient", _amb); - shader_set_f("reflective", _refl); - - shader_set_i("volumetric", _vol); - shader_set_f("volumeDensity", _vden); - shader_set_f("triplanar", _triS); - shader_set_f("textureScale", _texs); - shader_set_i("useEnv", is_surface(bgEnv)); - shader_set_i("useTexture", is_surface(_text)); + + object.apply(); draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1]); surface_reset_shader(); - gpu_set_texfilter(false); - return _outSurf; + return [ _outSurf, object ]; } } diff --git a/scripts/node_rm_primitive/node_rm_primitive.yy b/scripts/node_rm_primitive/node_rm_primitive.yy index ad982df32..e269c4b92 100644 --- a/scripts/node_rm_primitive/node_rm_primitive.yy +++ b/scripts/node_rm_primitive/node_rm_primitive.yy @@ -5,8 +5,8 @@ "isDnD":false, "name":"node_rm_primitive", "parent":{ - "name":"ray march", - "path":"folders/nodes/data/generator/ray march.yy", + "name":"raymarching", + "path":"folders/nodes/data/3D/raymarching.yy", }, "resourceType":"GMScript", "resourceVersion":"2.0", diff --git a/scripts/node_rm_terrain/node_rm_terrain.yy b/scripts/node_rm_terrain/node_rm_terrain.yy index 7126f0427..4bd49a72f 100644 --- a/scripts/node_rm_terrain/node_rm_terrain.yy +++ b/scripts/node_rm_terrain/node_rm_terrain.yy @@ -5,8 +5,8 @@ "isDnD":false, "name":"node_rm_terrain", "parent":{ - "name":"ray march", - "path":"folders/nodes/data/generator/ray march.yy", + "name":"raymarching", + "path":"folders/nodes/data/3D/raymarching.yy", }, "resourceType":"GMScript", "resourceVersion":"2.0", diff --git a/shaders/sh_rm_primitive/sh_rm_primitive.fsh b/shaders/sh_rm_primitive/sh_rm_primitive.fsh index 338289e78..78948a82a 100644 --- a/shaders/sh_rm_primitive/sh_rm_primitive.fsh +++ b/shaders/sh_rm_primitive/sh_rm_primitive.fsh @@ -1,6 +1,9 @@ //Inigo Quilez //Oh where would I be without you. +#define MAX_SHAPES 16 +#define MAX_OP 32 + varying vec2 v_vTexcoord; varying vec4 v_vColour; @@ -18,54 +21,65 @@ uniform sampler2D texture1; uniform sampler2D texture2; uniform sampler2D texture3; -uniform float time; +uniform int operations[MAX_OP]; +uniform int opLength; -uniform int shape; -uniform vec3 size; -uniform float radius; -uniform float thickness; -uniform float crop; -uniform float angle; -uniform float height; -uniform vec2 radRange; -uniform float sizeUni; -uniform vec3 elongate; -uniform float rounded; +/////////////////////////////////////////////////////////////////// -uniform vec3 waveAmp; -uniform vec3 waveInt; -uniform vec3 waveShift; +uniform int shapeAmount; +uniform int shape[MAX_SHAPES] ; +uniform vec3 size[MAX_SHAPES] ; +uniform float radius[MAX_SHAPES] ; +uniform float thickness[MAX_SHAPES] ; +uniform float crop[MAX_SHAPES] ; +uniform float angle[MAX_SHAPES] ; +uniform float height[MAX_SHAPES] ; +uniform vec2 radRange[MAX_SHAPES] ; +uniform float sizeUni[MAX_SHAPES] ; +uniform vec3 elongate[MAX_SHAPES] ; +uniform float rounded[MAX_SHAPES] ; +uniform vec4 corner[MAX_SHAPES] ; +uniform vec2 size2D[MAX_SHAPES] ; +uniform int sides[MAX_SHAPES] ; -uniform int twistAxis; -uniform float twistAmount; +uniform vec3 waveAmp[MAX_SHAPES] ; +uniform vec3 waveInt[MAX_SHAPES] ; +uniform vec3 waveShift[MAX_SHAPES] ; -uniform vec3 position; -uniform vec3 rotation; -uniform float objectScale; +uniform int twistAxis[MAX_SHAPES] ; +uniform float twistAmount[MAX_SHAPES] ; + +uniform vec3 position[MAX_SHAPES] ; +uniform vec3 rotation[MAX_SHAPES] ; +uniform float objectScale[MAX_SHAPES] ; + +uniform vec3 tileSize[MAX_SHAPES] ; +uniform vec3 tileAmount[MAX_SHAPES] ; + +uniform vec4 diffuseColor[MAX_SHAPES] ; +uniform float reflective[MAX_SHAPES] ; + +uniform int volumetric[MAX_SHAPES] ; +uniform float volumeDensity[MAX_SHAPES] ; + +uniform int useTexture[MAX_SHAPES] ; +uniform float textureScale[MAX_SHAPES] ; +uniform float triplanar[MAX_SHAPES] ; + +/////////////////////////////////////////////////////////////////// uniform int ortho; uniform float fov; uniform float orthoScale; uniform vec2 viewRange; uniform float depthInt; -uniform vec3 tileSize; -uniform vec3 tileAmount; uniform int drawBg; uniform vec4 background; uniform float ambientIntns; uniform vec3 lightPosition; -uniform vec4 ambient; -uniform float reflective; - uniform int useEnv; -uniform int useTexture; -uniform float textureScale; -uniform float triplanar; - -uniform int volumetric; -uniform float volumeDensity; mat3 rotMatrix, irotMatrix; @@ -152,7 +166,33 @@ mat3 rotMatrix, irotMatrix; #endregion -#region ////========== Primitives =========== +#region ////======== 2D Primitives ========== + + float sdRoundedBox( in vec2 p, in vec2 b, in vec4 r ) { + r.xy = (p.x > 0.0)? r.xy : r.zw; + r.x = (p.y > 0.0)? r.x : r.y; + vec2 q = abs(p) - b + r.x; + return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x; + } + + float sdRegularPolygon(in vec2 p, in float r, in int n ) { + // these 4 lines can be precomputed for a given shape + float an = 3.141593 / float(n); + vec2 acs = vec2(cos(an), sin(an)); + + // reduce to first sector + float bn = mod(atan(p.x, p.y), 2.0 * an) - an; + p = length(p) * vec2(cos(bn), abs(sin(bn))); + + // line sdf + p -= r * acs; + p.y += clamp( -p.y, 0.0, r * acs.y); + return length(p) * sign(p.x); + } + +#endregion + +#region ////======== 3D Primitives ========== float sdPlane( vec3 p, vec3 n, float h ) { return dot(p,n) + h; @@ -327,35 +367,40 @@ mat3 rotMatrix, irotMatrix; #region ////============ Modify ============= vec4 opElongate( in vec3 p, in vec3 h ) { - vec3 q = abs(p)-h; - return vec4( max(q,0.0), min(max(q.x,max(q.y,q.z)),0.0) ); + vec3 q = abs(p) - h; + return vec4( max(q, 0.0), min(max(q.x, max(q.y, q.z)), 0.0) ); } - vec3 wave(vec3 p) { - p.x += sin(p.y * waveAmp.y + waveShift.x * PI * 2.) * waveInt.x + - sin(p.z * waveAmp.z + waveShift.x * PI * 2.) * waveInt.x; - p.y += sin(p.x * waveAmp.x + waveShift.y * PI * 2.) * waveInt.y + - sin(p.z * waveAmp.z + waveShift.y * PI * 2.) * waveInt.y; - p.z += sin(p.y * waveAmp.y + waveShift.z * PI * 2.) * waveInt.z + - sin(p.x * waveAmp.x + waveShift.z * PI * 2.) * waveInt.z; + float opExtrusion( in vec3 p, in float h, in float df2d ) { + vec2 w = vec2( df2d, abs(p.z) - h ); + return min(max(w.x, w.y), 0.0) + length(max(w, 0.0)); + } + + vec3 wave(int index, vec3 p) { + p.x += sin(p.y * waveAmp[index].y + waveShift[index].x * PI * 2.) * waveInt[index].x + + sin(p.z * waveAmp[index].z + waveShift[index].x * PI * 2.) * waveInt[index].x; + p.y += sin(p.x * waveAmp[index].x + waveShift[index].y * PI * 2.) * waveInt[index].y + + sin(p.z * waveAmp[index].z + waveShift[index].y * PI * 2.) * waveInt[index].y; + p.z += sin(p.y * waveAmp[index].y + waveShift[index].z * PI * 2.) * waveInt[index].z + + sin(p.x * waveAmp[index].x + waveShift[index].z * PI * 2.) * waveInt[index].z; return p; } - vec3 twist(vec3 p) { + vec3 twist(int index, vec3 p) { - float c = cos(twistAmount * p[twistAxis]); - float s = sin(twistAmount * p[twistAxis]); + float c = cos(twistAmount[index] * p[twistAxis[index]]); + float s = sin(twistAmount[index] * p[twistAxis[index]]); mat2 m = mat2(c, -s, s, c); - if(twistAxis == 0) { + if(twistAxis[index] == 0) { vec2 q = m * p.yz; return vec3(p.x, q); - } else if(twistAxis == 1) { + } else if(twistAxis[index] == 1) { vec2 q = m * p.xz; return vec3(q.x, p.y, q.y); - } else if(twistAxis == 2) { + } else if(twistAxis[index] == 2) { vec2 q = m * p.xy; return vec3(q, p.z); @@ -364,6 +409,21 @@ mat3 rotMatrix, irotMatrix; return p; } + float opSmoothUnion( float d1, float d2, float k ) { + float h = clamp( 0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0 ); + return mix( d2, d1, h ) - k * h * (1.0 - h); + } + + float opSmoothSubtraction( float d1, float d2, float k ) { + float h = clamp( 0.5 - 0.5 * (d2 + d1) / k, 0.0, 1.0 ); + return mix( d2, -d1, h ) + k * h * (1.0 - h); + } + + float opSmoothIntersection( float d1, float d2, float k ) { + float h = clamp( 0.5 - 0.5 * (d2 - d1) / k, 0.0, 1.0 ); + return mix( d2, d1, h ) + k * h * (1.0 - h); + } + #endregion #region ////=========== View Mod ============ @@ -371,10 +431,10 @@ mat3 rotMatrix, irotMatrix; float round(float v) { return fract(v) >= 0.5? ceil(v) : floor(v); } vec3 round(vec3 v) { return vec3(round(v.x), round(v.y), round(v.z)); } - vec3 tilePosition(vec3 p) { - if(tileAmount == vec3(0.)) - return p - tileSize * round(p / tileSize); - return p - tileSize * clamp(round(p / tileSize), -tileAmount, tileAmount); + vec3 tilePosition(int index, vec3 p) { + if(tileAmount[index] == vec3(0.)) + return p - tileSize[index] * round(p / tileSize[index]); + return p - tileSize[index] * clamp(round(p / tileSize[index]), -tileAmount[index], tileAmount[index]); } #endregion @@ -397,67 +457,81 @@ mat3 rotMatrix, irotMatrix; ////========= Ray Marching ========== -float sceneSDF(vec3 p) { +float sceneSDF(int index, vec3 p) { float d; - p = wave(p); + mat3 rx = rotateX(rotation[index].x); + mat3 ry = rotateY(rotation[index].y); + mat3 rz = rotateZ(rotation[index].z); + rotMatrix = rx * ry * rz; + irotMatrix = inverse(rotMatrix); - if(tileSize != vec3(0.)) - p = tilePosition(p); + p /= objectScale[index]; + p -= position[index]; + p = irotMatrix * p; + + p = wave(index, p); - p = twist(p); + if(tileSize[index] != vec3(0.)) + p = tilePosition(index, p); + + p = twist(index, p); vec4 el = vec4(0.); - if(elongate != vec3(0.)) { - el = opElongate(p, elongate); + if(elongate[index] != vec3(0.)) { + el = opElongate(p, elongate[index]); p = el.xyz; } - if(shape == 100) d = sdPlane(p, vec3(0., -1., 0.), 0.); - else if(shape == 101) d = sdBox(p, size / 2.); - else if(shape == 102) d = sdBoxFrame(p, size / 2., thickness); + int shp = shape[index]; - else if(shape == 200) d = sdSphere(p, radius); - else if(shape == 201) d = sdEllipsoid(p, size / 2.); - else if(shape == 202) d = sdCutSphere(p, radius, crop); - else if(shape == 203) d = sdCutHollowSphere(p, radius, crop, thickness); - else if(shape == 204) d = sdTorus(p, vec2(radius, thickness)); - else if(shape == 205) d = sdCappedTorus(p, angle, radius, thickness); + if(shp == 100) d = sdPlane( p, vec3(0., -1., 0.), 0.); + else if(shp == 101) d = sdBox( p, size[index] / 2.); + else if(shp == 102) d = sdBoxFrame( p, size[index] / 2., thickness[index]); + else if(shp == 103) d = opExtrusion( p, thickness[index], sdRoundedBox(p.xy, size2D[index], corner[index])); - else if(shape == 300) d = sdCappedCylinder(p, height, radius); - else if(shape == 301) d = sdCapsule(p, vec3(-height, 0., 0.), vec3(height, 0., 0.), radius); - else if(shape == 302) d = sdCone(p, angle, height); - else if(shape == 303) d = sdCappedCone(p, height, radRange.x, radRange.y); - else if(shape == 304) d = sdRoundCone(p, height, radRange.x, radRange.y); - else if(shape == 305) d = sdSolidAngle(p, angle, radius); + else if(shp == 200) d = sdSphere( p, radius[index]); + else if(shp == 201) d = sdEllipsoid( p, size[index] / 2.); + else if(shp == 202) d = sdCutSphere( p, radius[index], crop[index]); + else if(shp == 203) d = sdCutHollowSphere( p, radius[index], crop[index], thickness[index]); + else if(shp == 204) d = sdTorus( p, vec2(radius[index], thickness[index])); + else if(shp == 205) d = sdCappedTorus( p, angle[index], radius[index], thickness[index]); - else if(shape == 400) d = sdOctahedron(p, sizeUni); - else if(shape == 401) d = sdPyramid(p, sizeUni); + else if(shp == 300) d = sdCappedCylinder( p, height[index], radius[index]); + else if(shp == 301) d = sdCapsule( p, vec3(-height[index], 0., 0.), vec3(height[index], 0., 0.), radius[index]); + else if(shp == 302) d = sdCone( p, angle[index], height[index]); + else if(shp == 303) d = sdCappedCone( p, height[index], radRange[index].x, radRange[index].y); + else if(shp == 304) d = sdRoundCone( p, height[index], radRange[index].x, radRange[index].y); + else if(shp == 305) d = sdSolidAngle( p, angle[index], radius[index]); + else if(shp == 306) d = opExtrusion( p, thickness[index], sdRegularPolygon(p.xy, 0.5, sides[index])); - if(elongate != vec3(0.)) { + else if(shp == 400) d = sdOctahedron( p, sizeUni[index]); + else if(shp == 401) d = sdPyramid( p, sizeUni[index]); + + if(elongate[index] != vec3(0.)) { d += el.w; } - d -= rounded; - d *= objectScale; + d -= rounded[index]; + d *= objectScale[index]; return d; } -vec3 normal(vec3 p) { +vec3 normal(int index, vec3 p) { return normalize(vec3( - sceneSDF(vec3(p.x + EPSILON, p.y, p.z)) - sceneSDF(vec3(p.x - EPSILON, p.y, p.z)), - sceneSDF(vec3(p.x, p.y + EPSILON, p.z)) - sceneSDF(vec3(p.x, p.y - EPSILON, p.z)), - sceneSDF(vec3(p.x, p.y, p.z + EPSILON)) - sceneSDF(vec3(p.x, p.y, p.z - EPSILON)) + sceneSDF(index, vec3(p.x + EPSILON, p.y, p.z)) - sceneSDF(index, vec3(p.x - EPSILON, p.y, p.z)), + sceneSDF(index, vec3(p.x, p.y + EPSILON, p.z)) - sceneSDF(index, vec3(p.x, p.y - EPSILON, p.z)), + sceneSDF(index, vec3(p.x, p.y, p.z + EPSILON)) - sceneSDF(index, vec3(p.x, p.y, p.z - EPSILON)) )); } -float march(vec3 camera, vec3 direction) { +float march(int index, vec3 camera, vec3 direction) { float depth = viewRange.x; for (int i = 0; i < MAX_MARCHING_STEPS; i++) { - float dist = sceneSDF(camera + depth * direction); + float dist = sceneSDF(index, camera + depth * direction); if (dist < EPSILON) return depth; @@ -469,16 +543,16 @@ float march(vec3 camera, vec3 direction) { return viewRange.y; } -float marchDensity(vec3 camera, vec3 direction) { +float marchDensity(int index, vec3 camera, vec3 direction) { float st = 1. / float(MAX_MARCHING_STEPS); float dens = 0.; - float stp = volumeDensity == 0. ? 0. : pow(2., 10. * volumeDensity * 0.5 - 10.); + float stp = volumeDensity[index] == 0. ? 0. : pow(2., 10. * volumeDensity[index] * 0.5 - 10.); for (int i = 0; i <= MAX_MARCHING_STEPS; i++) { float depth = mix(viewRange.x, viewRange.y, float(i) * st); vec3 pos = camera + depth * direction; - float hit = sceneSDF(pos); - float inst = (pos.y + objectScale) / (objectScale * 2.); + float hit = sceneSDF(index, pos); + float inst = (pos.y + objectScale[index]) / (objectScale[index] * 2.); inst = inst <= 0.? 0. : pow(2., 10. * inst - 10.) * 10.; if (hit <= 0.) dens += stp; @@ -487,81 +561,170 @@ float marchDensity(vec3 camera, vec3 direction) { return dens; } -void main() { +vec4 scene(int index, out float depth, out vec3 coll, out vec3 norm) { + depth = 0.; - mat3 rx = rotateX(rotation.x); - mat3 ry = rotateY(rotation.y); - mat3 rz = rotateZ(rotation.z); - rotMatrix = rx * ry * rz; - irotMatrix = inverse(rotMatrix); - float dz = 1. / tan(radians(fov) / 2.); vec3 dir = normalize(vec3((v_vTexcoord - .5) * 2., -dz)); vec3 eye = vec3(0., 0., 5.); - dir = normalize(irotMatrix * dir) / objectScale; - eye = irotMatrix * eye; - eye /= objectScale; - eye -= position; - - vec4 bg = background; - if(useEnv == 1) { - float edz = 1. / tan(radians(fov * 2.) / 2.); - vec3 edir = normalize(vec3((v_vTexcoord - .5) * 2., -edz)); - edir = normalize(irotMatrix * edir) / objectScale; - - vec2 envUV = equirectangularUv(edir); - vec4 endC = sampleTexture(0, envUV); - bg = endC; + if(volumetric[index] == 1) { + float _dens = clamp(marchDensity(index, eye, dir), 0., 1.); + return diffuseColor[index] * _dens; } - gl_FragColor = drawBg == 1? bg : vec4(0.); - - if(volumetric == 1) { - float _dens = clamp(marchDensity(eye, dir), 0., 1.); - gl_FragColor = mix(background, ambient, _dens); - return; - } - - float dist = march(eye, dir); - vec3 coll = eye + dir * dist; - vec3 wcoll = irotMatrix * coll; - vec3 norm = normal(coll); + depth = march(index, eye, dir); + coll = eye + dir * depth; + norm = normal(index, coll); - if(dist > viewRange.y - EPSILON) // Not hitting anything. - return; + if(depth > viewRange.y - EPSILON) // Not hitting anything. + return vec4(0.); - vec3 c = useTexture == 1? boxmap(1, coll * textureScale, norm, triplanar).rgb * ambient.rgb : ambient.rgb; + vec3 c = useTexture[index] == 1? + boxmap(int(TEXTURE_S) + index, coll * textureScale[index], norm, triplanar[index]).rgb * diffuseColor[index].rgb : + diffuseColor[index].rgb; /////////////////////////////////////////////////////////// - float distNorm = (dist - viewRange.x) / (viewRange.y - viewRange.x); + float distNorm = (depth - viewRange.x) / (viewRange.y - viewRange.x); distNorm = 1. - distNorm; distNorm = smoothstep(.0, .3, distNorm); - c = mix(background.rgb, c, mix(1., distNorm, depthInt)); + c = mix(c * background.rgb, c, mix(1., distNorm, depthInt)); /////////////////////////////////////////////////////////// - vec3 ref = reflect(dir, norm); - if(useEnv == 1) { - vec4 refC = sampleTexture(0, equirectangularUv(ref)) - + sampleTexture(0, equirectangularUv(ref + vec3( 0.01, 0., 0.))) * 0.5 - + sampleTexture(0, equirectangularUv(ref + vec3(-0.01, 0., 0.))) * 0.5 - + sampleTexture(0, equirectangularUv(ref + vec3(0., 0.01, 0.))) * 0.5 - + sampleTexture(0, equirectangularUv(ref + vec3(0., -0.01, 0.))) * 0.5 - + sampleTexture(0, equirectangularUv(ref + vec3(0., 0., 0.01))) * 0.5 - + sampleTexture(0, equirectangularUv(ref + vec3(0., 0., -0.01))) * 0.5; - refC /= 4.; - - c = mix(c, c * refC.rgb, reflective); + vec3 ref = reflect(dir, norm); + vec4 refC = sampleTexture(0, equirectangularUv(ref)); + c = mix(c, c * refC.rgb, reflective[index]); } /////////////////////////////////////////////////////////// vec3 light = normalize(lightPosition); float lamo = min(1., max(0., dot(norm, light)) + ambientIntns); - c = mix(background.rgb, c, lamo); + c = mix(c * background.rgb, c, lamo); - gl_FragColor = vec4(c, 1.); + return vec4(c, 1.); +} + +vec4 sceneBlend(float depth, vec4 color, vec3 norm) { + if(depth > viewRange.y - EPSILON) // Not hitting anything. + return vec4(0.); + + vec3 c = color.rgb; + + /////////////////////////////////////////////////////////// + + float distNorm = (depth - viewRange.x) / (viewRange.y - viewRange.x); + distNorm = 1. - distNorm; + distNorm = smoothstep(.0, .3, distNorm); + c = mix(c * background.rgb, c, mix(1., distNorm, depthInt)); + + vec3 light = normalize(lightPosition); + float lamo = min(1., max(0., dot(norm, light)) + ambientIntns); + c = mix(c * background.rgb, c, lamo); + + return vec4(c, 1.); +} + +vec4 blend(in vec4 bg, in vec4 fg) { + float al = fg.a + bg.a * (1. - fg.a); + if(al == 0.) return bg; + + vec4 res = ((fg * fg.a) + (bg * bg.a * (1. - fg.a))) / al; + res.a = al; + + return res; +} + +vec4 operate() { + vec4 color[MAX_OP]; + vec3 colis[MAX_OP]; + vec3 norml[MAX_OP]; + float depth[MAX_OP]; + + int top = 0; + int opr = 0; + + float d1, d2, dm, rt; + vec3 n1, n2, cl; + vec4 c1, c2; + float yy = viewRange.y - EPSILON; + + for(int i = 0; i < opLength; i++) { + opr = operations[i]; + + if(opr < 100) { + color[top] = scene(opr, d1, cl, n1); + depth[top] = d1; + colis[top] = cl; + norml[top] = n1; + top++; + + } else { + top--; + c1 = color[top]; + d1 = depth[top]; + n1 = norml[top]; + + top--; + c2 = color[top]; + d2 = depth[top]; + n2 = norml[top]; + + if(opr == 100) { + if(d1 < yy || d2 < yy) { + + if(d1 < d2) { + color[top] = c1; + depth[top] = d1; + norml[top] = n1; + } else { + color[top] = c2; + depth[top] = d2; + norml[top] = n2; + } + + } else { + + color[top] = vec4(0.); + depth[top] = 0.; + norml[top] = vec3(0.); + + } + + top++; + } + } + } + + return color[0]; +} + +void main() { + + vec4 bg = background; + if(useEnv == 1) { + float edz = 1. / tan(radians(fov * 2.) / 2.); + vec3 edir = normalize(vec3((v_vTexcoord - .5) * 2., -edz)); + //edir = normalize(irotMatrix * edir) / objectScale[index]; + + vec2 envUV = equirectangularUv(edir); + vec4 endC = sampleTexture(0, envUV); + bg = endC; + } + + vec4 result = drawBg == 1? bg : vec4(0.); + float d; + vec3 c, n; + + if(operations[0] == -1) + result = blend(result, scene(0, d, c, n)); + else + result = blend(result, operate()); + + ////////////////////////////////////////////////// + + gl_FragColor = result; } \ No newline at end of file diff --git a/sprites/s_node_rm_combine/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96.png b/sprites/s_node_rm_combine/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96.png new file mode 100644 index 000000000..175d10e55 Binary files /dev/null and b/sprites/s_node_rm_combine/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96.png differ diff --git a/sprites/s_node_rm_combine/layers/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96/37957189-91ab-49cb-b8e0-ce22fdb9b0c2.png b/sprites/s_node_rm_combine/layers/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96/37957189-91ab-49cb-b8e0-ce22fdb9b0c2.png new file mode 100644 index 000000000..6bec8568d Binary files /dev/null and b/sprites/s_node_rm_combine/layers/f98e82e8-b6b4-45a9-ba89-baaf12d9ca96/37957189-91ab-49cb-b8e0-ce22fdb9b0c2.png differ diff --git a/sprites/s_node_rm_combine/s_node_rm_combine.yy b/sprites/s_node_rm_combine/s_node_rm_combine.yy new file mode 100644 index 000000000..6e9293881 --- /dev/null +++ b/sprites/s_node_rm_combine/s_node_rm_combine.yy @@ -0,0 +1,90 @@ +{ + "$GMSprite":"", + "%Name":"s_node_rm_combine", + "bboxMode":0, + "bbox_bottom":62, + "bbox_left":2, + "bbox_right":60, + "bbox_top":3, + "collisionKind":1, + "collisionTolerance":0, + "DynamicTexturePage":false, + "edgeFiltering":false, + "For3D":false, + "frames":[ + {"$GMSpriteFrame":"","%Name":"f98e82e8-b6b4-45a9-ba89-baaf12d9ca96","name":"f98e82e8-b6b4-45a9-ba89-baaf12d9ca96","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + ], + "gridX":0, + "gridY":0, + "height":64, + "HTile":false, + "layers":[ + {"$GMImageLayer":"","%Name":"37957189-91ab-49cb-b8e0-ce22fdb9b0c2","blendMode":0,"displayName":"default","isLocked":false,"name":"37957189-91ab-49cb-b8e0-ce22fdb9b0c2","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, + ], + "name":"s_node_rm_combine", + "nineSlice":null, + "origin":4, + "parent":{ + "name":"3D", + "path":"folders/nodes/icons/3D.yy", + }, + "preMultiplyAlpha":false, + "resourceType":"GMSprite", + "resourceVersion":"2.0", + "sequence":{ + "$GMSequence":"", + "%Name":"s_node_rm_combine", + "autoRecord":true, + "backdropHeight":768, + "backdropImageOpacity":0.5, + "backdropImagePath":"", + "backdropWidth":1366, + "backdropXOffset":0.0, + "backdropYOffset":0.0, + "events":{ + "$KeyframeStore":"", + "Keyframes":[], + "resourceType":"KeyframeStore", + "resourceVersion":"2.0", + }, + "eventStubScript":null, + "eventToFunction":{}, + "length":1.0, + "lockOrigin":false, + "moments":{ + "$KeyframeStore":"", + "Keyframes":[], + "resourceType":"KeyframeStore", + "resourceVersion":"2.0", + }, + "name":"s_node_rm_combine", + "playback":1, + "playbackSpeed":30.0, + "playbackSpeedType":0, + "resourceType":"GMSequence", + "resourceVersion":"2.0", + "showBackdrop":true, + "showBackdropImage":false, + "timeUnits":1, + "tracks":[ + {"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore":"","Keyframes":[ + {"$Keyframe":"","Channels":{ + "0":{"$SpriteFrameKeyframe":"","Id":{"name":"f98e82e8-b6b4-45a9-ba89-baaf12d9ca96","path":"sprites/s_node_rm_combine/s_node_rm_combine.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"4e0e75a6-eac6-4ea3-bcb4-b6500b531b73","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + ],"resourceType":"KeyframeStore","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, + ], + "visibleRange":null, + "volume":1.0, + "xorigin":32, + "yorigin":32, + }, + "swatchColours":null, + "swfPrecision":0.5, + "textureGroupId":{ + "name":"Default", + "path":"texturegroups/Default", + }, + "type":0, + "VTile":false, + "width":64, +} \ No newline at end of file diff --git a/sprites/s_node_shape_3d/193adda1-e9c3-42e9-88f0-4335a4a2885f.png b/sprites/s_node_shape_3d/193adda1-e9c3-42e9-88f0-4335a4a2885f.png new file mode 100644 index 000000000..8e68f28a0 Binary files /dev/null and b/sprites/s_node_shape_3d/193adda1-e9c3-42e9-88f0-4335a4a2885f.png differ diff --git a/sprites/s_node_shape_3d/2ea21084-4785-418a-a413-2b896df41ff7.png b/sprites/s_node_shape_3d/2ea21084-4785-418a-a413-2b896df41ff7.png new file mode 100644 index 000000000..0039e9897 Binary files /dev/null and b/sprites/s_node_shape_3d/2ea21084-4785-418a-a413-2b896df41ff7.png differ diff --git a/sprites/s_node_shape_3d/layers/193adda1-e9c3-42e9-88f0-4335a4a2885f/b966fb12-3a24-4f05-8084-a475027ecd2c.png b/sprites/s_node_shape_3d/layers/193adda1-e9c3-42e9-88f0-4335a4a2885f/b966fb12-3a24-4f05-8084-a475027ecd2c.png new file mode 100644 index 000000000..8e68f28a0 Binary files /dev/null and b/sprites/s_node_shape_3d/layers/193adda1-e9c3-42e9-88f0-4335a4a2885f/b966fb12-3a24-4f05-8084-a475027ecd2c.png differ diff --git a/sprites/s_node_shape_3d/layers/2ea21084-4785-418a-a413-2b896df41ff7/b966fb12-3a24-4f05-8084-a475027ecd2c.png b/sprites/s_node_shape_3d/layers/2ea21084-4785-418a-a413-2b896df41ff7/b966fb12-3a24-4f05-8084-a475027ecd2c.png new file mode 100644 index 000000000..0039e9897 Binary files /dev/null and b/sprites/s_node_shape_3d/layers/2ea21084-4785-418a-a413-2b896df41ff7/b966fb12-3a24-4f05-8084-a475027ecd2c.png differ diff --git a/sprites/s_node_shape_3d/s_node_shape_3d.yy b/sprites/s_node_shape_3d/s_node_shape_3d.yy index f1224b7e8..7de4ca1de 100644 --- a/sprites/s_node_shape_3d/s_node_shape_3d.yy +++ b/sprites/s_node_shape_3d/s_node_shape_3d.yy @@ -15,6 +15,7 @@ {"$GMSpriteFrame":"","%Name":"4bb74abc-c433-4d95-90b8-6d432203f2cd","name":"4bb74abc-c433-4d95-90b8-6d432203f2cd","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"788d0a63-e4df-49ea-b9e1-498a0cef9940","name":"788d0a63-e4df-49ea-b9e1-498a0cef9940","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"d63e2d22-1c1d-4d1e-9894-773d9bcc75bf","name":"d63e2d22-1c1d-4d1e-9894-773d9bcc75bf","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + {"$GMSpriteFrame":"","%Name":"2ea21084-4785-418a-a413-2b896df41ff7","name":"2ea21084-4785-418a-a413-2b896df41ff7","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"f8ceda58-3651-4496-8acc-d0031209c85f","name":"f8ceda58-3651-4496-8acc-d0031209c85f","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"a67f4783-975c-4385-800c-bda14bc788aa","name":"a67f4783-975c-4385-800c-bda14bc788aa","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"fbeb2617-f75b-4d4d-8652-159e2cd0677e","name":"fbeb2617-f75b-4d4d-8652-159e2cd0677e","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, @@ -22,6 +23,7 @@ {"$GMSpriteFrame":"","%Name":"a9144d25-0a29-4a41-af37-91fa66dcfbd8","name":"a9144d25-0a29-4a41-af37-91fa66dcfbd8","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"55e17775-8c99-4c34-afba-32ff17aea0cd","name":"55e17775-8c99-4c34-afba-32ff17aea0cd","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"91e98279-4857-4edb-ad31-965ed879434f","name":"91e98279-4857-4edb-ad31-965ed879434f","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + {"$GMSpriteFrame":"","%Name":"193adda1-e9c3-42e9-88f0-4335a4a2885f","name":"193adda1-e9c3-42e9-88f0-4335a4a2885f","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"77a94bee-9795-42c2-b8d8-fa8feb667cc0","name":"77a94bee-9795-42c2-b8d8-fa8feb667cc0","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"5cc8219a-02e5-4b49-89f9-41ee24b035bb","name":"5cc8219a-02e5-4b49-89f9-41ee24b035bb","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, {"$GMSpriteFrame":"","%Name":"8f00908e-92e2-474b-9d0c-8b2fb8dba4ff","name":"8f00908e-92e2-474b-9d0c-8b2fb8dba4ff","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, @@ -65,7 +67,7 @@ }, "eventStubScript":null, "eventToFunction":{}, - "length":17.0, + "length":19.0, "lockOrigin":false, "moments":{ "$KeyframeStore":"", @@ -93,48 +95,54 @@ {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"d63e2d22-1c1d-4d1e-9894-773d9bcc75bf","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, },"Disabled":false,"id":"01d746c2-9f2e-4827-bdca-8d666a0bdafb","IsCreationKey":false,"Key":2.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + {"$Keyframe":"","Channels":{ + "0":{"$SpriteFrameKeyframe":"","Id":{"name":"2ea21084-4785-418a-a413-2b896df41ff7","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"966893bb-f205-4359-b56a-cfeb6af18996","IsCreationKey":false,"Key":3.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"f8ceda58-3651-4496-8acc-d0031209c85f","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"cd773a0c-d83e-4137-8641-ce60b984a397","IsCreationKey":false,"Key":3.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"cd773a0c-d83e-4137-8641-ce60b984a397","IsCreationKey":false,"Key":4.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"a67f4783-975c-4385-800c-bda14bc788aa","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"973d9998-69d3-404a-9cb8-b58045f5c85e","IsCreationKey":false,"Key":4.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"973d9998-69d3-404a-9cb8-b58045f5c85e","IsCreationKey":false,"Key":5.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"fbeb2617-f75b-4d4d-8652-159e2cd0677e","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"065ed05a-9605-4af3-b699-411314780dd9","IsCreationKey":false,"Key":5.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"065ed05a-9605-4af3-b699-411314780dd9","IsCreationKey":false,"Key":6.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"3c36db85-d4c1-4eac-8539-0152ee45e89c","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"8942bd33-2f9c-4364-b560-379aea9087e1","IsCreationKey":false,"Key":6.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"8942bd33-2f9c-4364-b560-379aea9087e1","IsCreationKey":false,"Key":7.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"a9144d25-0a29-4a41-af37-91fa66dcfbd8","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"dbe39012-01eb-417f-b8d9-de7de7e3cc79","IsCreationKey":false,"Key":7.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"dbe39012-01eb-417f-b8d9-de7de7e3cc79","IsCreationKey":false,"Key":8.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"55e17775-8c99-4c34-afba-32ff17aea0cd","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"5a803cfc-b354-4e3c-ae22-732d2c0831b0","IsCreationKey":false,"Key":8.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"5a803cfc-b354-4e3c-ae22-732d2c0831b0","IsCreationKey":false,"Key":9.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"91e98279-4857-4edb-ad31-965ed879434f","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"128c27fa-31bf-49b4-9f01-8211419db89a","IsCreationKey":false,"Key":9.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"128c27fa-31bf-49b4-9f01-8211419db89a","IsCreationKey":false,"Key":10.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + {"$Keyframe":"","Channels":{ + "0":{"$SpriteFrameKeyframe":"","Id":{"name":"193adda1-e9c3-42e9-88f0-4335a4a2885f","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"43c020f4-7a49-45b8-8119-4262664f7f7f","IsCreationKey":false,"Key":11.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"77a94bee-9795-42c2-b8d8-fa8feb667cc0","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"802c6cbf-5e03-463e-8a6f-285fb6a9b498","IsCreationKey":false,"Key":10.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"802c6cbf-5e03-463e-8a6f-285fb6a9b498","IsCreationKey":false,"Key":12.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"5cc8219a-02e5-4b49-89f9-41ee24b035bb","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"a7b050d2-5107-422c-bc16-c73bd17414bd","IsCreationKey":false,"Key":11.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"a7b050d2-5107-422c-bc16-c73bd17414bd","IsCreationKey":false,"Key":13.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"8f00908e-92e2-474b-9d0c-8b2fb8dba4ff","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"b41afe65-df8a-4c93-a239-da4965713fba","IsCreationKey":false,"Key":12.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"b41afe65-df8a-4c93-a239-da4965713fba","IsCreationKey":false,"Key":14.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"16bfc80e-e29e-4d4e-85bc-db11d8be1e35","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"cf14bd6d-4ac0-466e-ad27-4af436999f18","IsCreationKey":false,"Key":13.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"cf14bd6d-4ac0-466e-ad27-4af436999f18","IsCreationKey":false,"Key":15.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"53ff437f-736a-41e3-b500-bc9e840439d0","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"36d7040b-a1cc-4ce4-935a-805894d9d303","IsCreationKey":false,"Key":14.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"36d7040b-a1cc-4ce4-935a-805894d9d303","IsCreationKey":false,"Key":16.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"0da22937-fff4-452f-a8d6-3e8b57726d6e","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"b6642d24-2c86-4b2b-bceb-5d9f6a4c287c","IsCreationKey":false,"Key":15.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"b6642d24-2c86-4b2b-bceb-5d9f6a4c287c","IsCreationKey":false,"Key":17.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, {"$Keyframe":"","Channels":{ "0":{"$SpriteFrameKeyframe":"","Id":{"name":"1c600a42-babc-45aa-ba0b-00dad6ef1e04","path":"sprites/s_node_shape_3d/s_node_shape_3d.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, - },"Disabled":false,"id":"14b14ac0-8cf2-4f3f-aa4f-441b9aec23d8","IsCreationKey":false,"Key":16.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + },"Disabled":false,"id":"14b14ac0-8cf2-4f3f-aa4f-441b9aec23d8","IsCreationKey":false,"Key":18.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, ],"resourceType":"KeyframeStore","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, ], "visibleRange":null,