diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 80fe5aef0..db67de475 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -716,6 +716,7 @@ {"name":"node_cross_section","order":20,"path":"scripts/node_cross_section/node_cross_section.yy",}, {"name":"node_csv_file_read","order":8,"path":"scripts/node_csv_file_read/node_csv_file_read.yy",}, {"name":"node_csv_file_write","order":12,"path":"scripts/node_csv_file_write/node_csv_file_write.yy",}, + {"name":"node_curve_hsv","order":18,"path":"scripts/node_curve_hsv/node_curve_hsv.yy",}, {"name":"node_data","order":1,"path":"scripts/node_data/node_data.yy",}, {"name":"node_de_stray","order":1,"path":"scripts/node_de_stray/node_de_stray.yy",}, {"name":"node_delay","order":5,"path":"scripts/node_delay/node_delay.yy",}, @@ -1302,6 +1303,7 @@ {"name":"sh_corner_iterate","order":2,"path":"shaders/sh_corner_iterate/sh_corner_iterate.yy",}, {"name":"sh_cross_histogram","order":26,"path":"shaders/sh_cross_histogram/sh_cross_histogram.yy",}, {"name":"sh_cross_section","order":25,"path":"shaders/sh_cross_section/sh_cross_section.yy",}, + {"name":"sh_curve_hsv","order":54,"path":"shaders/sh_curve_hsv/sh_curve_hsv.yy",}, {"name":"sh_curve","order":3,"path":"shaders/sh_curve/sh_curve.yy",}, {"name":"sh_d3d_background","order":8,"path":"shaders/sh_d3d_background/sh_d3d_background.yy",}, {"name":"sh_d3d_extrude_extends","order":11,"path":"shaders/sh_d3d_extrude_extends/sh_d3d_extrude_extends.yy",}, @@ -1671,6 +1673,7 @@ {"name":"s_node_csv_file_write","order":30,"path":"sprites/s_node_csv_file_write/s_node_csv_file_write.yy",}, {"name":"s_node_csv_parse","order":19,"path":"sprites/s_node_csv_parse/s_node_csv_parse.yy",}, {"name":"s_node_curve_edit","order":14,"path":"sprites/s_node_curve_edit/s_node_curve_edit.yy",}, + {"name":"s_node_curve_hsv","order":63,"path":"sprites/s_node_curve_hsv/s_node_curve_hsv.yy",}, {"name":"s_node_curve","order":20,"path":"sprites/s_node_curve/s_node_curve.yy",}, {"name":"s_node_decorner","order":15,"path":"sprites/s_node_decorner/s_node_decorner.yy",}, {"name":"s_node_delay","order":7,"path":"sprites/s_node_delay/s_node_delay.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 12417286a..f605fed60 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -1128,6 +1128,7 @@ {"id":{"name":"node_cross_section","path":"scripts/node_cross_section/node_cross_section.yy",},}, {"id":{"name":"node_csv_file_read","path":"scripts/node_csv_file_read/node_csv_file_read.yy",},}, {"id":{"name":"node_csv_file_write","path":"scripts/node_csv_file_write/node_csv_file_write.yy",},}, + {"id":{"name":"node_curve_hsv","path":"scripts/node_curve_hsv/node_curve_hsv.yy",},}, {"id":{"name":"node_curve","path":"scripts/node_curve/node_curve.yy",},}, {"id":{"name":"node_data","path":"scripts/node_data/node_data.yy",},}, {"id":{"name":"node_de_corner","path":"scripts/node_de_corner/node_de_corner.yy",},}, @@ -1805,6 +1806,7 @@ {"id":{"name":"sh_corner","path":"shaders/sh_corner/sh_corner.yy",},}, {"id":{"name":"sh_cross_histogram","path":"shaders/sh_cross_histogram/sh_cross_histogram.yy",},}, {"id":{"name":"sh_cross_section","path":"shaders/sh_cross_section/sh_cross_section.yy",},}, + {"id":{"name":"sh_curve_hsv","path":"shaders/sh_curve_hsv/sh_curve_hsv.yy",},}, {"id":{"name":"sh_curve","path":"shaders/sh_curve/sh_curve.yy",},}, {"id":{"name":"sh_d3d_background","path":"shaders/sh_d3d_background/sh_d3d_background.yy",},}, {"id":{"name":"sh_d3d_default","path":"shaders/sh_d3d_default/sh_d3d_default.yy",},}, @@ -2235,6 +2237,7 @@ {"id":{"name":"s_node_csv_parse","path":"sprites/s_node_csv_parse/s_node_csv_parse.yy",},}, {"id":{"name":"s_node_curve_edit","path":"sprites/s_node_curve_edit/s_node_curve_edit.yy",},}, {"id":{"name":"s_node_curve_eval","path":"sprites/s_node_curve_eval/s_node_curve_eval.yy",},}, + {"id":{"name":"s_node_curve_hsv","path":"sprites/s_node_curve_hsv/s_node_curve_hsv.yy",},}, {"id":{"name":"s_node_curve","path":"sprites/s_node_curve/s_node_curve.yy",},}, {"id":{"name":"s_node_decorner","path":"sprites/s_node_decorner/s_node_decorner.yy",},}, {"id":{"name":"s_node_delay","path":"sprites/s_node_delay/s_node_delay.yy",},}, diff --git a/scripts/node_curve_hsv/node_color_adjustment.yy b/scripts/node_curve_hsv/node_color_adjustment.yy new file mode 100644 index 000000000..b90346cca --- /dev/null +++ b/scripts/node_curve_hsv/node_color_adjustment.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_color_adjustment", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_curve_hsv/node_color_replacement.yy b/scripts/node_curve_hsv/node_color_replacement.yy new file mode 100644 index 000000000..024aa6a80 --- /dev/null +++ b/scripts/node_curve_hsv/node_color_replacement.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_color_replacement", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_curve_hsv/node_curve_hsv.gml b/scripts/node_curve_hsv/node_curve_hsv.gml new file mode 100644 index 000000000..f66349c58 --- /dev/null +++ b/scripts/node_curve_hsv/node_curve_hsv.gml @@ -0,0 +1,63 @@ +function Node_Curve_HSV(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "HSV Curve"; + + inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| 1] = nodeValue("Hue", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_01); + + inputs[| 2] = nodeValue("Saturation", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_01); + + inputs[| 3] = nodeValue("Value", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_01); + + inputs[| 4] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| 5] = nodeValue("Mix", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 6] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true); + active_index = 6; + + inputs[| 7] = nodeValue("Channel", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0b1111) + .setDisplay(VALUE_DISPLAY.toggle, { data: array_create(4, THEME.inspector_channel) }); + + __init_mask_modifier(4); // inputs 8, 9, + + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + + input_display_list = [ 6, 7, + ["Surfaces", true], 0, 4, 5, 8, 9, + ["Curve", false], 1, 2, 3, + ]; + + attribute_surface_depth(); + + static step = function() { #region + __step_mask_modifier(); + } #endregion + + static processData = function(_outSurf, _data, _output_index, _array_index) { #region + var _hcur = _data[1]; + var _scur = _data[2]; + var _vcur = _data[3]; + + surface_set_shader(_outSurf, sh_curve_hsv); + + shader_set_f("h_curve", _hcur); + shader_set_i("h_amount", array_length(_hcur)); + + shader_set_f("s_curve", _scur); + shader_set_i("s_amount", array_length(_scur)); + + shader_set_f("v_curve", _vcur); + shader_set_i("v_amount", array_length(_vcur)); + + draw_surface_safe(_data[0]); + surface_reset_shader(); + + __process_mask_modifier(_data); + _outSurf = mask_apply(_data[0], _outSurf, _data[4], _data[5]); + _outSurf = channel_apply(_data[0], _outSurf, _data[7]); + + return _outSurf; + } #endregion +} diff --git a/scripts/node_curve_hsv/node_curve_hsv.yy b/scripts/node_curve_hsv/node_curve_hsv.yy new file mode 100644 index 000000000..1db0f04ab --- /dev/null +++ b/scripts/node_curve_hsv/node_curve_hsv.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_curve_hsv", + "isCompatibility":false, + "isDnD":false, + "name":"node_curve_hsv", + "parent":{ + "name":"colors", + "path":"folders/nodes/data/filter/colors.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_curve_hsv/node_outline.yy b/scripts/node_curve_hsv/node_outline.yy new file mode 100644 index 000000000..86468bc09 --- /dev/null +++ b/scripts/node_curve_hsv/node_outline.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_outline", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index 6b14c94f2..06160152d 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -622,6 +622,7 @@ function __initNodes() { addNodeObject(filter, "Level", s_node_level, "Node_Level", [1, Node_Level],, "Adjust brightness of an image by changing its brightness range."); addNodeObject(filter, "Level Selector", s_node_level_selector, "Node_Level_Selector", [1, Node_Level_Selector],, "Isolate part of the image that falls in the selected brightness range."); addNodeObject(filter, "Curve", s_node_curve_edit, "Node_Curve", [1, Node_Curve],, "Adjust brightness of an image using curves.").setVersion(1120); + addNodeObject(filter, "HSV Curve", s_node_curve_hsv, "Node_Curve_HSV", [1, Node_Curve_HSV],, "Adjust hsv values of an image using curves.").setVersion(11720); addNodeObject(filter, "Threshold", s_node_threshold, "Node_Threshold", [1, Node_Threshold],, "Set a threshold where pixel darker will becomes black, and brighter to white. Also works with alpha.").setVersion(1080); addNodeObject(filter, "Alpha Cutoff", s_node_alpha_cut, "Node_Alpha_Cutoff", [1, Node_Alpha_Cutoff], ["remove alpha"], "Remove pixel with low alpha value."); addNodeObject(filter, "Normalize", s_node_normalize, "Node_Normalize", [1, Node_Normalize]).setVersion(11710); diff --git a/shaders/sh_curve_hsv/sh_curve_hsv.fsh b/shaders/sh_curve_hsv/sh_curve_hsv.fsh new file mode 100644 index 000000000..a7a869e07 --- /dev/null +++ b/shaders/sh_curve_hsv/sh_curve_hsv.fsh @@ -0,0 +1,126 @@ +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +uniform float h_curve[64]; +uniform int h_amount; + +uniform float s_curve[64]; +uniform int s_amount; + +uniform float v_curve[64]; +uniform int v_amount; + +float eval_curve_segment_t(in float _y0, in float ax0, in float ay0, in float bx1, in float by1, in float _y1, in float prog) { + return _y0 * pow(1. - prog, 3.) + + ay0 * 3. * pow(1. - prog, 2.) * prog + + by1 * 3. * (1. - prog) * pow(prog, 2.) + + _y1 * pow(prog, 3.); +} + +float eval_curve_segment_x(in float _y0, in float ax0, in float ay0, in float bx1, in float by1, in float _y1, in float _x) { + float st = 0.; + float ed = 1.; + float _prec = 0.0001; + + float _xt = _x; + int _binRep = 8; + + if(_x <= 0.) return _y0; + if(_x >= 1.) return _y1; + if(_y0 == ay0 && _y0 == by1 && _y0 == _y1) return _y0; + + for(int i = 0; i < _binRep; i++) { + float _ftx = 3. * pow(1. - _xt, 2.) * _xt * ax0 + + 3. * (1. - _xt) * pow(_xt, 2.) * bx1 + + pow(_xt, 3.); + + if(abs(_ftx - _x) < _prec) + return eval_curve_segment_t(_y0, ax0, ay0, bx1, by1, _y1, _xt); + + if(_xt < _x) st = _xt; + else ed = _xt; + + _xt = (st + ed) / 2.; + } + + int _newRep = 16; + + for(int i = 0; i < _newRep; i++) { + float slope = ( 9. * ax0 - 9. * bx1 + 3.) * _xt * _xt + + (-12. * ax0 + 6. * bx1) * _xt + + 3. * ax0; + float _ftx = 3. * pow(1. - _xt, 2.) * _xt * ax0 + + 3. * (1. - _xt) * pow(_xt, 2.) * bx1 + + pow(_xt, 3.) + - _x; + + _xt -= _ftx / slope; + + if(abs(_ftx) < _prec) + break; + } + + _xt = clamp(_xt, 0., 1.); + return eval_curve_segment_t(_y0, ax0, ay0, bx1, by1, _y1, _xt); +} + +float curveEval(in float[64] curve, in int amo, in float _x) { + _x = clamp(_x, 0., 1.); + int segments = amo / 6 - 1; + + for( int i = 0; i < segments; i++ ) { + int ind = i * 6; + float _x0 = curve[ind + 2]; + float _y0 = curve[ind + 3]; + //float bx0 = _x0 + curve[ind + 0]; + //float by0 = _y0 + curve[ind + 1]; + float ax0 = _x0 + curve[ind + 4]; + float ay0 = _y0 + curve[ind + 5]; + + float _x1 = curve[ind + 6 + 2]; + float _y1 = curve[ind + 6 + 3]; + float bx1 = _x1 + curve[ind + 6 + 0]; + float by1 = _y1 + curve[ind + 6 + 1]; + //float ax1 = _x1 + curve[ind + 6 + 4]; + //float ay1 = _y1 + curve[ind + 6 + 5]; + + if(_x < _x0) continue; + if(_x > _x1) continue; + + return eval_curve_segment_x(_y0, ax0, ay0, bx1, by1, _y1, (_x - _x0) / (_x1 - _x0)); + } + + return curve[0]; +} + +#region =========================================== COLORS SPACES =========================================== + vec3 rgb2hsv(vec3 c) { #region + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 0.0000000001; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); + } #endregion + + vec3 hsv2rgb(vec3 c) { #region + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); + } #endregion + +#endregion =========================================== COLORS SPACES =========================================== + +void main() { + vec4 col = texture2D( gm_BaseTexture, v_vTexcoord ); + vec3 hsv = rgb2hsv(col.rgb); + + hsv.r = curveEval(h_curve, h_amount, hsv.r); + hsv.g = curveEval(s_curve, s_amount, hsv.g); + hsv.b = curveEval(v_curve, v_amount, hsv.b); + + vec3 rgb = hsv2rgb(hsv); + + gl_FragColor = vec4(rgb, col.a); +} diff --git a/shaders/sh_curve_hsv/sh_curve_hsv.vsh b/shaders/sh_curve_hsv/sh_curve_hsv.vsh new file mode 100644 index 000000000..3900c20f4 --- /dev/null +++ b/shaders/sh_curve_hsv/sh_curve_hsv.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_curve_hsv/sh_curve_hsv.yy b/shaders/sh_curve_hsv/sh_curve_hsv.yy new file mode 100644 index 000000000..a4d641fb8 --- /dev/null +++ b/shaders/sh_curve_hsv/sh_curve_hsv.yy @@ -0,0 +1,12 @@ +{ + "$GMShader":"", + "%Name":"sh_curve_hsv", + "name":"sh_curve_hsv", + "parent":{ + "name":"filter", + "path":"folders/shader/filter.yy", + }, + "resourceType":"GMShader", + "resourceVersion":"2.0", + "type":1, +} \ No newline at end of file diff --git a/shaders/sh_rm_primitive/sh_rm_primitive.fsh b/shaders/sh_rm_primitive/sh_rm_primitive.fsh index c861eba4e..b95c45fa6 100644 --- a/shaders/sh_rm_primitive/sh_rm_primitive.fsh +++ b/shaders/sh_rm_primitive/sh_rm_primitive.fsh @@ -462,7 +462,7 @@ float marchDensity(vec3 camera, vec3 direction) { float inst = (pos.y + objectScale) / (objectScale * 2.); inst = inst <= 0.? 0. : pow(2., 10. * inst - 10.) * 10.; - if (hit <= 0.) dens += stp * inst; + if (hit <= 0.) dens += stp; } return dens; diff --git a/sprites/s_node_curve_hsv/f2262182-4ebc-4362-bd6c-ae2591eef2f7.png b/sprites/s_node_curve_hsv/f2262182-4ebc-4362-bd6c-ae2591eef2f7.png new file mode 100644 index 000000000..68f465e54 Binary files /dev/null and b/sprites/s_node_curve_hsv/f2262182-4ebc-4362-bd6c-ae2591eef2f7.png differ diff --git a/sprites/s_node_curve_hsv/layers/f2262182-4ebc-4362-bd6c-ae2591eef2f7/42cf3477-e356-474f-bbfb-90f21d4c08aa.png b/sprites/s_node_curve_hsv/layers/f2262182-4ebc-4362-bd6c-ae2591eef2f7/42cf3477-e356-474f-bbfb-90f21d4c08aa.png new file mode 100644 index 000000000..68f465e54 Binary files /dev/null and b/sprites/s_node_curve_hsv/layers/f2262182-4ebc-4362-bd6c-ae2591eef2f7/42cf3477-e356-474f-bbfb-90f21d4c08aa.png differ diff --git a/sprites/s_node_curve_hsv/s_node_curve_hsv.yy b/sprites/s_node_curve_hsv/s_node_curve_hsv.yy new file mode 100644 index 000000000..efd07302a --- /dev/null +++ b/sprites/s_node_curve_hsv/s_node_curve_hsv.yy @@ -0,0 +1,90 @@ +{ + "$GMSprite":"", + "%Name":"s_node_curve_hsv", + "bboxMode":0, + "bbox_bottom":61, + "bbox_left":2, + "bbox_right":61, + "bbox_top":2, + "collisionKind":1, + "collisionTolerance":0, + "DynamicTexturePage":false, + "edgeFiltering":false, + "For3D":false, + "frames":[ + {"$GMSpriteFrame":"","%Name":"f2262182-4ebc-4362-bd6c-ae2591eef2f7","name":"f2262182-4ebc-4362-bd6c-ae2591eef2f7","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + ], + "gridX":0, + "gridY":0, + "height":64, + "HTile":false, + "layers":[ + {"$GMImageLayer":"","%Name":"42cf3477-e356-474f-bbfb-90f21d4c08aa","blendMode":0,"displayName":"default","isLocked":false,"name":"42cf3477-e356-474f-bbfb-90f21d4c08aa","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, + ], + "name":"s_node_curve_hsv", + "nineSlice":null, + "origin":4, + "parent":{ + "name":"filter", + "path":"folders/nodes/icons/filter.yy", + }, + "preMultiplyAlpha":false, + "resourceType":"GMSprite", + "resourceVersion":"2.0", + "sequence":{ + "$GMSequence":"", + "%Name":"s_node_curve_hsv", + "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_curve_hsv", + "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":"f2262182-4ebc-4362-bd6c-ae2591eef2f7","path":"sprites/s_node_curve_hsv/s_node_curve_hsv.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"d8c6ba74-bd54-4f89-8766-0a3cd515c00a","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