diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 7b3a5b2ea..8929c2f43 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -176,6 +176,7 @@ {"name":"find_boundary","order":7,"path":"folders/shader/misc/find_boundary.yy",}, {"name":"MK effects","order":12,"path":"folders/shader/MK effects.yy",}, {"name":"Flag","order":3,"path":"folders/shader/MK effects/Flag.yy",}, + {"name":"Fracture","order":5,"path":"folders/shader/MK effects/Fracture.yy",}, {"name":"Tile","order":4,"path":"folders/shader/MK effects/Tile.yy",}, {"name":"noise","order":19,"path":"folders/shader/noise.yy",}, {"name":"pixel_builder","order":13,"path":"folders/shader/pixel_builder.yy",}, @@ -1849,6 +1850,7 @@ {"name":"s_node_mk_flag","order":5,"path":"sprites/s_node_mk_flag/s_node_mk_flag.yy",}, {"name":"s_node_mk_flare","order":11,"path":"sprites/s_node_mk_flare/s_node_mk_flare.yy",}, {"name":"s_node_mk_flip_grid","order":2,"path":"sprites/s_node_mk_flip_grid/s_node_mk_flip_grid.yy",}, + {"name":"s_node_mk_fracture","order":13,"path":"sprites/s_node_mk_fracture/s_node_mk_fracture.yy",}, {"name":"s_node_mk_grid_flip","order":18,"path":"sprites/s_node_mk_grid_flip/s_node_mk_grid_flip.yy",}, {"name":"s_node_mk_rain_type","order":7,"path":"sprites/s_node_mk_rain_type/s_node_mk_rain_type.yy",}, {"name":"s_node_mk_rain","order":4,"path":"sprites/s_node_mk_rain/s_node_mk_rain.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 0306f2abb..951db59aa 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -298,6 +298,7 @@ {"$GMFolder":"","%Name":"find_boundary","folderPath":"folders/shader/misc/find_boundary.yy","name":"find_boundary","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"MK effects","folderPath":"folders/shader/MK effects.yy","name":"MK effects","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Flag","folderPath":"folders/shader/MK effects/Flag.yy","name":"Flag","resourceType":"GMFolder","resourceVersion":"2.0",}, + {"$GMFolder":"","%Name":"Fracture","folderPath":"folders/shader/MK effects/Fracture.yy","name":"Fracture","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Tile","folderPath":"folders/shader/MK effects/Tile.yy","name":"Tile","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"noise","folderPath":"folders/shader/noise.yy","name":"noise","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"pixel_builder","folderPath":"folders/shader/pixel_builder.yy","name":"pixel_builder","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -1960,6 +1961,7 @@ {"id":{"name":"sh_mk_flag_mrt","path":"shaders/sh_mk_flag_mrt/sh_mk_flag_mrt.yy",},}, {"id":{"name":"sh_mk_flag_shade","path":"shaders/sh_mk_flag_shade/sh_mk_flag_shade.yy",},}, {"id":{"name":"sh_mk_flipGrid","path":"shaders/sh_mk_flipGrid/sh_mk_flipGrid.yy",},}, + {"id":{"name":"sh_mk_fracture","path":"shaders/sh_mk_fracture/sh_mk_fracture.yy",},}, {"id":{"name":"sh_mk_saber_glow","path":"shaders/sh_mk_saber_glow/sh_mk_saber_glow.yy",},}, {"id":{"name":"sh_mk_tile18_edge_b","path":"shaders/sh_mk_tile18_edge_b/sh_mk_tile18_edge_b.yy",},}, {"id":{"name":"sh_mk_tile18_edge_l","path":"shaders/sh_mk_tile18_edge_l/sh_mk_tile18_edge_l.yy",},}, @@ -2409,6 +2411,7 @@ {"id":{"name":"s_node_mk_flag","path":"sprites/s_node_mk_flag/s_node_mk_flag.yy",},}, {"id":{"name":"s_node_mk_flare","path":"sprites/s_node_mk_flare/s_node_mk_flare.yy",},}, {"id":{"name":"s_node_mk_flip_grid","path":"sprites/s_node_mk_flip_grid/s_node_mk_flip_grid.yy",},}, + {"id":{"name":"s_node_mk_fracture","path":"sprites/s_node_mk_fracture/s_node_mk_fracture.yy",},}, {"id":{"name":"s_node_mk_grid_flip","path":"sprites/s_node_mk_grid_flip/s_node_mk_grid_flip.yy",},}, {"id":{"name":"s_node_mk_rain_type","path":"sprites/s_node_mk_rain_type/s_node_mk_rain_type.yy",},}, {"id":{"name":"s_node_mk_rain","path":"sprites/s_node_mk_rain/s_node_mk_rain.yy",},}, diff --git a/scripts/node_mk_fracture/node_mk_fracture.gml b/scripts/node_mk_fracture/node_mk_fracture.gml index 1a68d9769..fa788eba0 100644 --- a/scripts/node_mk_fracture/node_mk_fracture.gml +++ b/scripts/node_mk_fracture/node_mk_fracture.gml @@ -6,8 +6,45 @@ function Node_MK_Fracture(_x, _y, _group = noone) : Node_Processor(_x, _y, _grou inputs[| 1] = nodeValue("Subdivision", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [ 4, 4 ]) .setDisplay(VALUE_DISPLAY.vector); + inputs[| 2] = nodeValue("Progress", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5) + .setDisplay(VALUE_DISPLAY.slider) + .setMappable(3); + + inputs[| 3] = nodeValueMap("Progress map", self); + + inputs[| 4] = nodeValue("Movement", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ]) + .setDisplay(VALUE_DISPLAY.vector) + .setMappable(9, true); + + inputs[| 5] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 180) + .setDisplay(VALUE_DISPLAY.rotation) + .setMappable(10); + + inputs[| 6] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 7] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1.) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 8] = nodeValue("Gravity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.); + + inputs[| 9] = nodeValueMap("Movement map", self); + + inputs[| 10] = nodeValueMap("Rotation map", self); + + inputs[| 11] = nodeValue("Brick Shift", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 12] = nodeValue("Skew", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.) + .setDisplay(VALUE_DISPLAY.slider, { range : [ -1, 1, 0.01 ] }); + + inputs[| 13] = nodeValue("Brick Axis", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) + .setDisplay(VALUE_DISPLAY.enum_button, [ "X", "Y" ]); + input_display_list = [ new Inspector_Sprite(s_MKFX), 0, - ["Fracture", false], 1, + ["Fracture", false], 1, 2, 13, 11, 12, + ["Physics", false], 3, 4, 9, 8, 5, 10, 6, + ["Render", false], 7, ]; outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); @@ -16,14 +53,32 @@ function Node_MK_Fracture(_x, _y, _group = noone) : Node_Processor(_x, _y, _grou } #endregion + static step = function() { #region + inputs[| 2].mappableStep(); + inputs[| 4].mappableStep(); + } #endregion + static processData = function(_outSurf, _data, _output_index, _array_index) { var _surf = _data[0]; + var _dim = surface_get_dimension(_surf); - surface_set_target(_outSurf); + surface_set_shader(_outSurf, sh_mk_fracture); DRAW_CLEAR + shader_set_f("dimension", _dim); + shader_set_f("subdivision", _data[ 1]); + shader_set_f_map("progress", _data[ 2], _data[3], inputs[| 2]); + shader_set_f_map("movement", _data[ 4], _data[9], inputs[| 4]); + shader_set_f("gravity", _data[ 8]); + shader_set_f("rotation", _data[ 5], _data[10], inputs[| 5]); + shader_set_f("scale", _data[ 6]); + shader_set_f("alpha", _data[ 7]); + shader_set_i("axis", _data[13]); + shader_set_f("brickShift", _data[11]); + shader_set_f("skew", _data[12]); - surface_reset_target(); + draw_surface_safe(_surf); + surface_reset_shader(); return _outSurf; } diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index 7797f5d76..ad6d3f2d8 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -777,7 +777,7 @@ function __initNodes() { addNodeObject(generator, "MK Blinker", s_node_mk_blinker, "Node_MK_Blinker", [1, Node_MK_Blinker]).setVersion(11630); addNodeObject(generator, "MK Lens Flare", s_node_mk_flare, "Node_MK_Flare", [1, Node_MK_Flare]).setVersion(11630); addNodeObject(generator, "MK Delay Machine", s_node_mk_delay_machine, "Node_MK_Delay_Machine", [1, Node_MK_Delay_Machine]).setVersion(11680); - /**/ addNodeObject(generator, "MK Fracture", s_node_mk_delay_machine, "Node_MK_Fracture", [1, Node_MK_Fracture]).setVersion(11740); + addNodeObject(generator, "MK Fracture", s_node_mk_fracture, "Node_MK_Fracture", [1, Node_MK_Fracture]).patreonExtra(); //addNodeObject(generator, "MK Sparkle", s_node_mk_sparkle, "Node_MK_Sparkle", [1, Node_MK_Sparkle]).patreonExtra(); #endregion diff --git a/scripts/node_value/node_value.gml b/scripts/node_value/node_value.gml index 9823be294..9f721c7b8 100644 --- a/scripts/node_value/node_value.gml +++ b/scripts/node_value/node_value.gml @@ -359,16 +359,20 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru } } setDropKey(); #endregion - static setMappable = function(index) { #region + mappedJunc = noone; + mapped_vec4 = false; + + static setMappable = function(index, vec4 = false) { #region attributes.mapped = false; attributes.map_index = index; + mapped_vec4 = vec4; mapButton = button(function() { attributes.mapped = !attributes.mapped; var val = getValue(); if( attributes.mapped) - setValue([0, 0]); + setValue(mapped_vec4? [ 0, 0, 0, 0 ] : [ 0, 0 ]); if(!attributes.mapped) setValue(def_val); @@ -386,7 +390,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru break; default : - mapWidget = new rangeBox(TEXTBOX_INPUT.number, function(index, val) { return setValueDirect(val, index); }); + mapWidget = vec4? + new vectorRangeBox(4, TEXTBOX_INPUT.number, function(index, val) { return setValueDirect(val, index); }) : + new rangeBox(TEXTBOX_INPUT.number, function(index, val) { return setValueDirect(val, index); }); mapWidget.side_button = mapButton; break; } diff --git a/scripts/vectorRangeBox/vectorRangeBox.gml b/scripts/vectorRangeBox/vectorRangeBox.gml index 595496999..f27183f43 100644 --- a/scripts/vectorRangeBox/vectorRangeBox.gml +++ b/scripts/vectorRangeBox/vectorRangeBox.gml @@ -73,6 +73,8 @@ function vectorRangeBox(_size, _type, _onModify, _unit = noone) : widget() const y = _y; w = _w; + _data = array_verify(_data, size); + if(struct_has(_display_data, "linked")) linked = _display_data.linked; var _hh = linked? _h : _h * 2 + ui(4); h = h == 0? _hh : lerp_float(h, _hh, 5); @@ -82,9 +84,15 @@ function vectorRangeBox(_size, _type, _onModify, _unit = noone) : widget() const var _bs = min(_h, ui(32)); if((_w - _bs) / 2 > ui(64)) { + if(side_button) { + side_button.setFocusHover(active, hover); + side_button.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m, THEME.button_hide); + _w -= _bs + ui(4); + } + var bx = _x; var by = _y + _h / 2 - _bs / 2; - + if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, active, hover, tooltip, THEME.value_link, linked, _icon_blend) == 2) { linked = !linked; _display_data.linked = linked; diff --git a/shaders/sh_mk_fracture/sh_mk_fracture.fsh b/shaders/sh_mk_fracture/sh_mk_fracture.fsh new file mode 100644 index 000000000..ff90c1617 --- /dev/null +++ b/shaders/sh_mk_fracture/sh_mk_fracture.fsh @@ -0,0 +1,123 @@ +#define TAU 6.28318530718 +#define MAX_RANGE 3. + +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +uniform vec2 dimension; +uniform vec2 subdivision; + +uniform vec2 progress; +uniform int progressUseSurf; +uniform sampler2D progressSurf; + +uniform vec4 movement; +uniform int movementUseSurf; +uniform sampler2D movementSurf; + +uniform vec2 rotation; +uniform int rotationUseSurf; +uniform sampler2D rotationSurf; + +uniform float gravity; +uniform float scale; +uniform float alpha; + +uniform int axis; +uniform float brickShift; +uniform float skew; + +vec2 random2( vec2 p ) { return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453); } + +vec2 cellID(in vec2 coord) { + vec2 idx = floor(coord * subdivision); + vec2 prg = (coord - idx / subdivision) * subdivision; + vec2 rng = (random2(vec2((axis == 0? idx.y : idx.x) + 100.)) - .5) * 2.; + + if(axis == 0) { + coord.x += mod(idx.y, 2.) * brickShift / subdivision.x; + coord.x += (prg.y - .5) * 2. / subdivision.x * skew * 0.5 * rng.x; + } else { + coord.y += mod(idx.x, 2.) * brickShift / subdivision.x; + coord.y += (prg.x - .5) * 2. / subdivision.y * skew * 0.5 * rng.y; + } + + vec2 cel = floor(coord * subdivision) / subdivision + .5 / subdivision; + return cel; +} + +vec4 uvInFrag(in vec2 coord, in vec2 fragID) { + vec2 fragUV = coord - fragID; + + float pro = progress.x; + if(progressUseSurf == 1) { + vec4 _vMap = texture2D( progressSurf, fragID ); + pro = mix(progress.x, progress.y, (_vMap.r + _vMap.g + _vMap.b) / 3.); + } + + vec2 mvm = movement.xy; + if(movementUseSurf == 1) { + vec4 _vMap = texture2D( movementSurf, fragID ); + mvm = mix(movement.xz, movement.yw, (_vMap.r + _vMap.g + _vMap.b) / 3.); + } + + float rta = rotation.x; + if(rotationUseSurf == 1) { + vec4 _vMap = texture2D( rotationSurf, fragID ); + rta = mix(rotation.x, rotation.y, (_vMap.r + _vMap.g + _vMap.b) / 3.); + } + + float sca = mix(1., scale, pro); + float ang = pro * radians(rta); + mat2 rot = mat2(cos(ang), -sin(ang), sin(ang), cos(ang)); + + vec2 mov = mvm / dimension; + float grv = gravity; + vec2 pos = mov * pro; + pos.y += grv * pro * pro; + + vec2 uv = fragID + (fragUV - pos) / sca * rot; + vec2 newID = cellID(uv); + + return vec4( + uv, + pro, + float(newID == fragID) + ); +} + +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; +} + +void main() { + gl_FragColor = vec4(0.); + // gl_FragColor = vec4(cellID(v_vTexcoord), 0., 1.); return; + + vec2 fragSize = 1. / subdivision; + + for(float i = -MAX_RANGE; i <= MAX_RANGE; i++) + for(float j = -MAX_RANGE; j <= MAX_RANGE * 2.; j++) { + + vec2 tx = v_vTexcoord + fragSize * vec2(j, i); + vec2 cl = cellID(tx); + + vec4 uv = uvInFrag(v_vTexcoord, cl); + if(uv.w == 0.) continue; + if(uv.x < 0. || uv.x > 1. || uv.y < 0. || uv.y > 1.) continue; + + float pro = uv.z; + float alp = mix(1., alpha, pro); + + vec4 c = texture2D( gm_BaseTexture, uv.xy ); + c.a *= alp; + + gl_FragColor = blend(gl_FragColor, c); + } +} diff --git a/shaders/sh_mk_fracture/sh_mk_fracture.vsh b/shaders/sh_mk_fracture/sh_mk_fracture.vsh new file mode 100644 index 000000000..3900c20f4 --- /dev/null +++ b/shaders/sh_mk_fracture/sh_mk_fracture.vsh @@ -0,0 +1,19 @@ +// +// Simple passthrough vertex shader +// +attribute vec3 in_Position; // (x,y,z) +//attribute vec3 in_Normal; // (x,y,z) unused in this shader. +attribute vec4 in_Colour; // (r,g,b,a) +attribute vec2 in_TextureCoord; // (u,v) + +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +void main() +{ + vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); + gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; + + v_vColour = in_Colour; + v_vTexcoord = in_TextureCoord; +} diff --git a/shaders/sh_mk_fracture/sh_mk_fracture.yy b/shaders/sh_mk_fracture/sh_mk_fracture.yy new file mode 100644 index 000000000..93a9edec8 --- /dev/null +++ b/shaders/sh_mk_fracture/sh_mk_fracture.yy @@ -0,0 +1,12 @@ +{ + "$GMShader":"", + "%Name":"sh_mk_fracture", + "name":"sh_mk_fracture", + "parent":{ + "name":"Fracture", + "path":"folders/shader/MK effects/Fracture.yy", + }, + "resourceType":"GMShader", + "resourceVersion":"2.0", + "type":1, +} \ No newline at end of file diff --git a/sprites/s_node_mk_fracture/90716b26-87d1-490d-8ab7-be720b3c6302.png b/sprites/s_node_mk_fracture/90716b26-87d1-490d-8ab7-be720b3c6302.png new file mode 100644 index 000000000..006849080 Binary files /dev/null and b/sprites/s_node_mk_fracture/90716b26-87d1-490d-8ab7-be720b3c6302.png differ diff --git a/sprites/s_node_mk_fracture/layers/90716b26-87d1-490d-8ab7-be720b3c6302/33c79fa7-5597-4204-b624-2831678ab60c.png b/sprites/s_node_mk_fracture/layers/90716b26-87d1-490d-8ab7-be720b3c6302/33c79fa7-5597-4204-b624-2831678ab60c.png new file mode 100644 index 000000000..006849080 Binary files /dev/null and b/sprites/s_node_mk_fracture/layers/90716b26-87d1-490d-8ab7-be720b3c6302/33c79fa7-5597-4204-b624-2831678ab60c.png differ diff --git a/sprites/s_node_mk_fracture/s_node_mk_fracture.yy b/sprites/s_node_mk_fracture/s_node_mk_fracture.yy new file mode 100644 index 000000000..cbb24cbfb --- /dev/null +++ b/sprites/s_node_mk_fracture/s_node_mk_fracture.yy @@ -0,0 +1,90 @@ +{ + "$GMSprite":"", + "%Name":"s_node_mk_fracture", + "bboxMode":0, + "bbox_bottom":63, + "bbox_left":0, + "bbox_right":63, + "bbox_top":0, + "collisionKind":1, + "collisionTolerance":0, + "DynamicTexturePage":false, + "edgeFiltering":false, + "For3D":false, + "frames":[ + {"$GMSpriteFrame":"","%Name":"90716b26-87d1-490d-8ab7-be720b3c6302","name":"90716b26-87d1-490d-8ab7-be720b3c6302","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + ], + "gridX":0, + "gridY":0, + "height":64, + "HTile":false, + "layers":[ + {"$GMImageLayer":"","%Name":"33c79fa7-5597-4204-b624-2831678ab60c","blendMode":0,"displayName":"default","isLocked":false,"name":"33c79fa7-5597-4204-b624-2831678ab60c","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, + ], + "name":"s_node_mk_fracture", + "nineSlice":null, + "origin":4, + "parent":{ + "name":"MK effects", + "path":"folders/nodes/icons/MK effects.yy", + }, + "preMultiplyAlpha":false, + "resourceType":"GMSprite", + "resourceVersion":"2.0", + "sequence":{ + "$GMSequence":"", + "%Name":"s_node_mk_fracture", + "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_mk_fracture", + "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":"90716b26-87d1-490d-8ab7-be720b3c6302","path":"sprites/s_node_mk_fracture/s_node_mk_fracture.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"434accbf-3f1a-407b-92f7-96b1112ee2a5","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