Trail, scatter

This commit is contained in:
Tanasart 2023-02-21 10:48:50 +07:00
parent 0c66bc0883
commit 5d4fd62937
23 changed files with 480 additions and 106 deletions

View File

@ -200,7 +200,7 @@
{"id":{"name":"node_displacement","path":"scripts/node_displacement/node_displacement.yy",},"order":1,},
{"id":{"name":"mask_function","path":"scripts/mask_function/mask_function.yy",},"order":1,},
{"id":{"name":"text_file","path":"scripts/text_file/text_file.yy",},"order":5,},
{"id":{"name":"sh_trail_filler","path":"shaders/sh_trail_filler/sh_trail_filler.yy",},"order":49,},
{"id":{"name":"sh_trail_filler_pass1","path":"shaders/sh_trail_filler_pass1/sh_trail_filler_pass1.yy",},"order":49,},
{"id":{"name":"s_node_vfx_wind","path":"sprites/s_node_vfx_wind/s_node_vfx_wind.yy",},"order":3,},
{"id":{"name":"s_node_rigidSim_global","path":"sprites/s_node_rigidSim_global/s_node_rigidSim_global.yy",},"order":4,},
{"id":{"name":"sh_channel_G_grey","path":"shaders/sh_channel_G_grey/sh_channel_G_grey.yy",},"order":8,},
@ -257,6 +257,7 @@
{"id":{"name":"s_node_gradient_4points","path":"sprites/s_node_gradient_4points/s_node_gradient_4points.yy",},"order":2,},
{"id":{"name":"s_node_gradient_out","path":"sprites/s_node_gradient_out/s_node_gradient_out.yy",},"order":9,},
{"id":{"name":"s_node_vec3","path":"sprites/s_node_vec3/s_node_vec3.yy",},"order":8,},
{"id":{"name":"node_gradient_shift","path":"scripts/node_gradient_shift/node_gradient_shift.yy",},"order":10,},
{"id":{"name":"sh_vertex_normal_pass","path":"shaders/sh_vertex_normal_pass/sh_vertex_normal_pass.yy",},"order":5,},
{"id":{"name":"surface_valid","path":"scripts/surface_valid/surface_valid.yy",},"order":6,},
{"id":{"name":"steam_ugc_collection","path":"scripts/steam_ugc_collection/steam_ugc_collection.yy",},"order":0,},
@ -744,6 +745,7 @@
{"id":{"name":"point_direction_positive","path":"scripts/point_direction_positive/point_direction_positive.yy",},"order":4,},
{"id":{"name":"s_node_fluidSim_add_fluid","path":"sprites/s_node_fluidSim_add_fluid/s_node_fluidSim_add_fluid.yy",},"order":3,},
{"id":{"name":"node_blur_contrast","path":"scripts/node_blur_contrast/node_blur_contrast.yy",},"order":1,},
{"id":{"name":"sh_trail_filler","path":"shaders/sh_trail_filler/sh_trail_filler.yy",},"order":50,},
{"id":{"name":"s_fx_pixel","path":"sprites/s_fx_pixel/s_fx_pixel.yy",},"order":0,},
{"id":{"name":"gradients_function","path":"scripts/gradients_function/gradients_function.yy",},"order":0,},
{"id":{"name":"s_node_border","path":"sprites/s_node_border/s_node_border.yy",},"order":10,},
@ -755,6 +757,7 @@
{"id":{"name":"fd_y","path":"scripts/fd_y/fd_y.yy",},"order":5,},
{"id":{"name":"s_node_text_render","path":"sprites/s_node_text_render/s_node_text_render.yy",},"order":17,},
{"id":{"name":"__init_global","path":"scripts/__init_global/__init_global.yy",},"order":8,},
{"id":{"name":"sh_trail_filler_pass2","path":"shaders/sh_trail_filler_pass2/sh_trail_filler_pass2.yy",},"order":51,},
{"id":{"name":"s_node_color_from_rgb","path":"sprites/s_node_color_from_rgb/s_node_color_from_rgb.yy",},"order":5,},
{"id":{"name":"node_scale_algo","path":"scripts/node_scale_algo/node_scale_algo.yy",},"order":12,},
{"id":{"name":"node_alpha_hash","path":"scripts/node_alpha_hash/node_alpha_hash.yy",},"order":11,},

View File

@ -41,6 +41,8 @@ event_inherited();
if(sFOCUS && (mouse_press(mb_left) || keyboard_check_pressed(vk_enter))) {
if(exists) array_remove(array, arrayBox.data[i]);
else array_push(array, arrayBox.data[i]);
if(arrayBox.onModify) arrayBox.onModify();
}
}

View File

@ -10,6 +10,10 @@ enum AREA_SCATTER {
random
}
function area_get_bbox(area) {
return [ area[0] - area[2], area[1] - area[3], area[0] + area[2], area[1] + area[3] ];
}
function area_get_random_point(area, distrib = AREA_DISTRIBUTION.area, scatter = AREA_SCATTER.random, index = 0, total = 1, _sed = 999) {
if(total == 0) return [0, 0];

View File

@ -22,7 +22,7 @@ function get_point_from_dist(distMap, attempt = 4) {
return res;
}
function get_points_from_dist(distMap, amount, seed = 0) {
function get_points_from_dist(distMap, amount, seed = 0, attempt = 8) {
if(amount < 1) return [];
if(!is_surface(distMap)) return [];
@ -34,6 +34,7 @@ function get_points_from_dist(distMap, amount, seed = 0) {
shader_set(sh_sample_points);
shader_set_uniform_f(shader_get_uniform(sh_sample_points, "dimension"),
surface_get_width(distMap) / amount, surface_get_height(distMap));
shader_set_uniform_i(shader_get_uniform(sh_sample_points, "attempt"), attempt);
shader_set_uniform_f(shader_get_uniform(sh_sample_points, "seed"), seed);
draw_surface_stretched(distMap, 0, 0, amount, 1);
@ -55,7 +56,8 @@ function get_points_from_dist(distMap, amount, seed = 0) {
else {
var _x = color_get_red(cc) / 255;
var _y = color_get_green(cc) / 255;
pos[i] = [_x, _y];
var _v = color_get_blue(cc) / 255;
pos[i] = [_x, _y, _v];
}
}

View File

@ -1,15 +1,15 @@
function draw_tooltip_text(txt) {
draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text);
var tw = string_width(txt);
var th = string_height(txt);
var tw = min(WIN_W - ui(32), string_width(txt));
var th = string_height_ext(txt, -1, tw);
var mx = min(mouse_mx + ui(16), WIN_W - (tw + ui(16)));
var my = min(mouse_my + ui(16), WIN_H - (th + ui(16)));
draw_sprite_stretched(THEME.textbox, 3, mx, my, tw + ui(16), th + ui(16));
draw_sprite_stretched(THEME.textbox, 0, mx, my, tw + ui(16), th + ui(16));
draw_text(mx + ui(8), my + ui(8), txt);
draw_text_ext(mx + ui(8), my + ui(8), txt, -1, tw);
}
function draw_tooltip_color(clr) {

View File

@ -0,0 +1,42 @@
function Node_Gradient_Shift(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) constructor {
name = "Gradient Shift";
previewable = false;
w = 96;
inputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [ new gradientKey(0, c_white) ] )
.setDisplay(VALUE_DISPLAY.gradient);
inputs[| 1] = nodeValue("Shift", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
.setDisplay(VALUE_DISPLAY.slider, [-1, 1, 0.01]);
inputs[| 2] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
outputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.output, VALUE_TYPE.color, [ new gradientKey(0, c_white) ] )
.setDisplay(VALUE_DISPLAY.gradient);
_pal = -1;
static process_data = function(_outSurf, _data, _output_index, _array_index) {
var pal = _data[0];
var sft = _data[1];
var lop = _data[2];
_outSurf = [];
for( var i = 0; i < array_length(pal); i++ ) {
var k = pal[i];
_outSurf[i] = new gradientKey(k.time + sft, k.value);
if(lop) _outSurf[i].time = frac(_outSurf[i].time);
}
return _outSurf;
}
static onDrawNode = function(xx, yy, _mx, _my, _s) {
var bbox = drawGetBbox(xx, yy, _s);
if(bbox.h < 1) return;
var grad = outputs[| 0].getValue();
draw_gradient(bbox.x0, bbox.y0, bbox.w, bbox.h, grad, inputs[| 0].extra_data[| 0]);
}
}

View File

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "node_gradient_shift",
"isDnD": false,
"isCompatibility": false,
"parent": {
"name": "color",
"path": "folders/nodes/data/value/color.yy",
},
}

View File

@ -412,6 +412,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor {
addNodeObject(color, "RGB Color", s_node_color_from_rgb, "Node_Color_RGB", [1, Node_Color_RGB]);
addNodeObject(color, "HSV Color", s_node_color_from_hsv, "Node_Color_HSV", [1, Node_Color_HSV]);
addNodeObject(color, "Gradient", s_node_gradient_out, "Node_Gradient_Out", [1, Node_Gradient_Out]);
addNodeObject(color, "Gradient Shift", s_node_gradient_out, "Node_Gradient_Shift", [1, Node_Gradient_Shift]);
addNodeObject(color, "Sampler", s_node_sampler, "Node_Sampler", [1, Node_Sampler]);
addNodeObject(color, "Color Data", s_node_color_data, "Node_Color_Data", [1, Node_Color_Data]);
addNodeObject(color, "Find pixel", s_node_pixel_find, "Node_Find_Pixel", [1, Node_Find_Pixel]).set_version(1130);

View File

@ -40,6 +40,7 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
inputs[| 14] = nodeValue("Distribution data", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setDisplay(VALUE_DISPLAY.vector);
inputs[| 14].array_depth = 1;
inputs[| 15] = nodeValue("Array", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0, @"What to do when input array of surface.
- Spread: Create Array of output each scattering single surface.
@ -48,11 +49,14 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
inputs[| 16] = nodeValue("Multiply alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
inputs[| 17] = nodeValue("Use value", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, [ "Scale" ])
.setDisplay(VALUE_DISPLAY.text_array, [ "Scale", "Rotation", "Color" ]);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [
["Surface", false], 0, 1, 15, 10,
["Scatter", false], 5, 6, 13, 14, 9, 2,
["Scatter", false], 5, 6, 13, 14, 17, 9, 2,
["Transform", false], 3, 8, 7, 4,
["Render", false], 11, 12, 16,
];
@ -60,13 +64,17 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
temp_surf = [ surface_create(1, 1), surface_create(1, 1) ];
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) {
inputs[| 5].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny);
if(process_amount > 1) return;
var _distType = current_data[6];
if(_distType < 3)
inputs[| 5].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny);
}
static onValueUpdate = function(index) {
if(index == 15) {
var _arr = inputs[| 15].getValue();
inputs[| 0].force_array = _arr;
inputs[| 0].array_depth = _arr;
doUpdate();
}
@ -75,10 +83,11 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
static step = function() {
var _dis = inputs[| 6].getValue();
var _arr = inputs[| 15].getValue();
inputs[| 0].force_array = _arr;
inputs[| 0].array_depth = _arr;
inputs[| 13].setVisible(_dis == 2, _dis == 2);
inputs[| 14].setVisible(_dis == 3, _dis == 3);
inputs[| 17].setVisible(_dis == 3);
inputs[| 9].setVisible(_dis != 2);
}
@ -108,9 +117,14 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
var _bldTyp = inputs[| 11].getExtraData();
var alpha = _data[12];
var mulpA = _data[16];
var useV = _data[17];
var _in_w, _in_h;
var vSca = array_exists(useV, "Scale");
var vRot = array_exists(useV, "Rotation");
var vCol = array_exists(useV, "Color");
var _posDist = [];
if(_dist == 2 && is_surface(_distMap))
_posDist = get_points_from_dist(_distMap, _amount);
@ -124,7 +138,8 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
var res_index = 0, bg = 0;
for(var i = 0; i < _amount; i++) {
var sp = noone, _x = 0, _y = 0;
var _v = noone;
if(_dist < 2) {
sp = area_get_random_point(_area, _dist, _scat, i, _amount, _sed); _sed += 20;
_x = sp[0];
@ -139,19 +154,29 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
sp = array_safe_get(_distData, i);
if(!is_array(sp)) continue;
_x = sp[0];
_y = sp[1];
_x = array_safe_get(sp, 0);
_y = array_safe_get(sp, 1);
_v = array_safe_get(sp, 2, noone);
}
var _scx = random_range_seed(_scale[0], _scale[1], _sed); _sed++;
var _scy = random_range_seed(_scale[2], _scale[3], _sed); _sed++;
var posS = seed + _y * _dim[0] + _x;
var _scx = random_range_seed(_scale[0], _scale[1], posS); posS++;
var _scy = random_range_seed(_scale[2], _scale[3], posS); posS++;
if(_unis) _scy = _scx;
var _r = (_pint? point_direction(_area[0], _area[1], _x, _y) : 0) + random_range_seed(_rota[0], _rota[1], _sed); _sed++;
if(vSca && _v != noone) {
_scx *= _v;
_scy *= _v;
}
var _r = (_pint? point_direction(_area[0], _area[1], _x, _y) : 0) + random_range_seed(_rota[0], _rota[1], posS); posS++;
if(vRot && _v != noone)
_r *= _v;
var surf = _inSurf;
if(is_array(_inSurf))
surf = _inSurf[irandom_seed(array_length(_inSurf) - 1, _sed)]; _sed++;
surf = _inSurf[irandom_seed(array_length(_inSurf) - 1, posS)]; posS++;
var sw = surface_get_width(surf);
var sh = surface_get_height(surf);
@ -161,12 +186,15 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
_x += p[0];
_y += p[1];
}
var clr = gradient_eval(color, random_seed(1, _sed), _bldTyp[| 0]); _sed++;
var alp = random_range_seed(alpha[0], alpha[1], _sed); _sed++;
var grSamp = random_seed(1, posS); posS++;
if(vCol && _v != noone)
grSamp *= _v;
var clr = gradient_eval(color, grSamp, _bldTyp[| 0]);
var alp = random_range_seed(alpha[0], alpha[1], posS); posS++;
draw_surface_ext_safe(surf, _x, _y, _scx, _scy, _r, clr, alp);
//print(string(_x) + ", " + string(_y))
}
BLEND_NORMAL;
surface_reset_target();
@ -176,7 +204,7 @@ function Node_Scatter(_x, _y, _group = -1) : Node_Processor(_x, _y, _group) cons
static doApplyDeserialize = function() {
var _arr = inputs[| 15].getValue();
inputs[| 0].force_array = _arr;
inputs[| 0].array_depth = _arr;
doUpdate();
}

View File

@ -6,7 +6,7 @@ function Node_Scatter_Points(_x, _y, _group = -1) : Node(_x, _y, _group) constru
w = 96;
inputs[| 0] = nodeValue("Point area", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ def_surf_size / 2, def_surf_size / 2, def_surf_size / 2, def_surf_size / 2, AREA_SHAPE.rectangle ])
.setDisplay(VALUE_DISPLAY.area);
.setDisplay(VALUE_DISPLAY.area, function() { return inputs[| 7].getValue(); });
inputs[| 1] = nodeValue("Point distribution", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
.setDisplay(VALUE_DISPLAY.enum_button, [ "Area", "Border", "Map" ])
@ -25,11 +25,21 @@ function Node_Scatter_Points(_x, _y, _group = -1) : Node(_x, _y, _group) constru
inputs[| 5] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom(99999))
.rejectArray();
input_display_list = [ 5, 0, 1, 4, 2, 3 ];
inputs[| 6] = nodeValue("Fixed position", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Fix point position, and only select point in the area.");
inputs[| 7] = nodeValue("Reference dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, def_surf_size2)
.setDisplay(VALUE_DISPLAY.vector);
input_display_list = [
["Base", false], 5, 6, 7,
["Scatter", false], 0, 1, 4, 2, 3,
];
outputs[| 0] = nodeValue("Points", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [ ])
.setDisplay(VALUE_DISPLAY.vector);
refVal = nodeValue("Reference value", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
static step = function() {
var _dist = inputs[| 1].getValue();
@ -41,26 +51,51 @@ function Node_Scatter_Points(_x, _y, _group = -1) : Node(_x, _y, _group) constru
inputs[| 0].drawOverlay(active, _x, _y, _s, _mx, _my, _snx, _sny);
}
static getPreviewValue = function() { return refVal; }
function update(frame = ANIMATOR.current_frame) {
var _area = inputs[| 0].getValue();
var _dist = inputs[| 1].getValue();
var _scat = inputs[| 2].getValue();
var _amo = inputs[| 3].getValue();
var _area = inputs[| 0].getValue();
var _dist = inputs[| 1].getValue();
var _scat = inputs[| 2].getValue();
var _amo = inputs[| 3].getValue();
var _distMap = inputs[| 4].getValue();
var _seed = inputs[| 5].getValue();
var pos;
var _seed = inputs[| 5].getValue();
var _fix = inputs[| 6].getValue();
var _fixRef = inputs[| 7].getValue();
inputs[| 7].setVisible(_fix);
var pos = [];
if(_fix) {
var ref = refVal.getValue();
ref = surface_verify(ref, _fixRef[0], _fixRef[1]);
refVal.setValue(ref);
}
var aBox = area_get_bbox(_area);
if(_dist != 2) {
pos = array_create(_amo);
for( var i = 0; i < _amo; i++ )
pos[i] = area_get_random_point(_area, _dist, _scat, i, _amo, _seed++);
pos = [];
for( var i = 0; i < _amo; i++ ) {
if(_fix) {
var p = area_get_random_point([_fixRef[0], _fixRef[1], _fixRef[0], _fixRef[1]], _dist, _scat, i, _amo, _seed++);
if(point_in_rectangle(p[0], p[1], aBox[0], aBox[1], aBox[2], aBox[3]))
array_push(pos, p);
} else
pos[i] = area_get_random_point(_area, _dist, _scat, i, _amo, _seed++);
}
} else {
pos = [];
var p = get_points_from_dist(_distMap, _amo, _seed);
var p = get_points_from_dist(_distMap, _amo, _seed, _fix? 1 : 8);
for( var i = 0; i < array_length(p); i++ ) {
if(p[i] == 0) continue;
p[i][0] = _area[0] + _area[2] * (p[i][0] * 2 - 1);
p[i][1] = _area[1] + _area[3] * (p[i][1] * 2 - 1);
if(_fix) {
p[i][0] *= _fixRef[0];
p[i][1] *= _fixRef[1];
} else {
p[i][0] = _area[0] + _area[2] * (p[i][0] * 2 - 1);
p[i][1] = _area[1] + _area[3] * (p[i][1] * 2 - 1);
}
array_push(pos, p[i]);
}

View File

@ -2,10 +2,16 @@ function Node_Trail(_x, _y, _group = -1) : Node(_x, _y, _group) constructor {
name = "Trail";
use_cache = true;
shader = sh_trail_filler;
uni_dimension = shader_get_uniform(shader, "dimension");
uni_range = shader_get_uniform(shader, "range");
uni_sam_prev = shader_get_sampler_index(shader, "prevFrame");
shader1 = sh_trail_filler_pass1;
uni_dimension = shader_get_uniform(shader1, "dimension");
uni_mode = shader_get_uniform(shader1, "mode");
uni_range = shader_get_uniform(shader1, "range");
uni_seg_st = shader_get_uniform(shader1, "segmentStart");
uni_seg_sz = shader_get_uniform(shader1, "segmentSize");
uni_sam_prev = shader_get_sampler_index(shader1, "prevFrame");
shader2 = sh_trail_filler_pass2;
uni2_dimension = shader_get_uniform(shader2, "dimension");
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0);
@ -13,14 +19,18 @@ function Node_Trail(_x, _y, _group = -1) : Node(_x, _y, _group) constructor {
inputs[| 2] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 3] = nodeValue("Max distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, -1);
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
outputs[| 1] = nodeValue("Trail UV", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
input_display_list = [
["Surface", true], 0,
["Trail settings", false], 1, 2,
["Trail settings", false], 1, 3, 2
];
output_surf = surface_create(1, 1);
temp = [ surface_create(1, 1), surface_create(1, 1), surface_create(1, 1) ];
static update = function() {
if(!inputs[| 0].value_from) return;
@ -29,24 +39,30 @@ function Node_Trail(_x, _y, _group = -1) : Node(_x, _y, _group) constructor {
var _surf = inputs[| 0].getValue();
var _life = inputs[| 1].getValue();
var _loop = inputs[| 2].getValue();
var _rang = inputs[| 3].getValue();
if(!is_surface(_surf)) return;
cacheCurrentFrame(_surf);
output_surf = surface_verify(output_surf, surface_get_width(_surf), surface_get_height(_surf));
surface_set_target(output_surf);
draw_clear_alpha(0, 0);
surface_reset_target();
for( var i = 0; i < array_length(temp); i++ ) {
temp[i] = surface_verify(temp[i], surface_get_width(_surf), surface_get_height(_surf));
surface_set_target(temp[i]);
draw_clear_alpha(0, 0);
surface_reset_target();
}
var _outSurf = outputs[| 0].getValue();
_outSurf = surface_verify(_outSurf, surface_get_width(_surf), surface_get_height(_surf));
outputs[| 0].setValue(_outSurf);
var _outUV = outputs[| 1].getValue();
_outUV = surface_verify(_outUV, surface_get_width(_surf), surface_get_height(_surf));
outputs[| 1].setValue(_outUV);
var curf = ANIMATOR.current_frame;
var frame_amo = _loop? _life : min(_life, curf);
var st_frame = curf - frame_amo;
print("=====");
for(var i = 0; i <= frame_amo; i++) {
var frame_idx = st_frame + i;
var prog = (frame_idx - (curf - _life)) / _life;
@ -57,27 +73,54 @@ function Node_Trail(_x, _y, _group = -1) : Node(_x, _y, _group) constructor {
if(!is_surface(getCacheFrame(frame_idx))) continue;
if(!is_surface(getCacheFrame(prev))) {
surface_set_target(output_surf);
surface_set_target(temp[0]);
draw_surface(getCacheFrame(frame_idx), 0, 0);
surface_reset_target();
surface_set_target(temp[2]);
draw_surface(getCacheFrame(frame_idx), 0, 0);
surface_reset_target();
continue;
}
surface_set_target(output_surf);
shader_set(sh_trail_filler);
shader_set(shader1);
shader_set_uniform_f(uni_dimension, surface_get_width(_surf), surface_get_height(_surf));
shader_set_uniform_f(uni_range, surface_get_width(_surf) / 2);
shader_set_uniform_f(uni_range, _rang? _rang : surface_get_width(_surf) / 2);
shader_set_uniform_f(uni_seg_st, (frame_amo - i) / frame_amo);
shader_set_uniform_f(uni_seg_sz, 1 / frame_amo);
texture_set_stage(uni_sam_prev, surface_get_texture(getCacheFrame(prev)));
draw_surface(getCacheFrame(frame_idx), 0, 0);
shader_set_uniform_i(uni_mode, 1);
surface_set_target(temp[0]);
draw_surface(getCacheFrame(frame_idx), 0, 0);
surface_reset_target();
shader_set_uniform_i(uni_mode, 0);
surface_set_target(temp[2]);
draw_surface(getCacheFrame(frame_idx), 0, 0);
surface_reset_target();
shader_reset();
surface_reset_target();
}
surface_set_target(temp[1]);
shader_set(shader2);
shader_set_uniform_f(uni2_dimension, surface_get_width(_surf), surface_get_height(_surf));
draw_surface(temp[0], 0, 0);
shader_reset();
surface_reset_target();
surface_set_target(_outUV);
draw_clear_alpha(0, 0);
BLEND_ALPHA;
draw_surface_safe(temp[1], 0, 0);
BLEND_NORMAL;
surface_reset_target();
surface_set_target(_outSurf);
draw_clear_alpha(0, 0);
BLEND_OVERRIDE;
draw_surface_safe(output_surf, 0, 0);
BLEND_ALPHA;
draw_surface_safe(temp[2], 0, 0);
BLEND_NORMAL;
surface_reset_target();
}

View File

@ -63,6 +63,7 @@ enum VALUE_DISPLAY {
export_format,
code,
node_title,
text_array,
//path
path_save,
@ -158,6 +159,7 @@ function typeArray(_type) {
case VALUE_DISPLAY.path_array :
case VALUE_DISPLAY.palette :
case VALUE_DISPLAY.gradient :
case VALUE_DISPLAY.text_array :
return 2;
}
return 0;
@ -319,7 +321,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
value_to = ds_list_create();
value_to_arr = [];
accept_array = true;
force_array = false;
array_depth = 0;
auto_connect = true;
setFrom_condition = -1;
@ -383,11 +385,6 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
return self;
}
static forceArray = function() {
force_array = true;
return self;
}
static rejectArray = function() {
accept_array = false;
return self;
@ -399,8 +396,8 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
}
static isAnimable = function() {
if(display_type == VALUE_DISPLAY.gradient)
return false;
if(display_type == VALUE_DISPLAY.gradient) return false;
if(display_type == VALUE_DISPLAY.text_array) return false;
return true;
}
@ -659,17 +656,29 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
});
break;
case VALUE_TYPE.text :
editWidget = new textArea(TEXTBOX_INPUT.text, function(str) {
return setValueDirect(str);
});
if(display_type == VALUE_DISPLAY.code) {
editWidget.font = f_code;
editWidget.format = TEXT_AREA_FORMAT.code;
editWidget.min_lines = 4;
switch(display_type) {
case VALUE_DISPLAY._default :
editWidget = new textArea(TEXTBOX_INPUT.text, function(str) {
return setValueDirect(str);
});
extract_node = "Node_String";
break;
case VALUE_DISPLAY.code :
editWidget = new textArea(TEXTBOX_INPUT.text, function(str) {
return setValueDirect(str);
});
editWidget.font = f_code;
editWidget.format = TEXT_AREA_FORMAT.code;
editWidget.min_lines = 4;
extract_node = "Node_String";
break;
case VALUE_DISPLAY.text_array :
editWidget = new textArrayBox(function() { return animator.values[| 0].value; }, display_data, function() { node.update(); });
break;
}
extract_node = "Node_String";
break;
case VALUE_TYPE.surface :
editWidget = new surfaceBox(function(ind) {
@ -784,8 +793,14 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
}
}
if(type == VALUE_TYPE.text)
return string_real(value);
if(type == VALUE_TYPE.text) {
switch(display_type) {
case VALUE_DISPLAY.text_array :
return value;
default:
return string_real(value);
}
}
if(typeFrom == VALUE_TYPE.integer && type == VALUE_TYPE.color)
return make_color_hsv(0, 0, value);
@ -924,22 +939,27 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
cache_array[0] = true;
if(!is_array(val)) {
if(!is_array(val)) { //Value is array
cache_array[1] = false;
return cache_array[1];
}
if(!force_array && !typeArray(display_type)) {
if(array_depth == 0 && !typeArray(display_type)) { //Value is not an array by default, and no array depth enforced
cache_array[1] = true;
return cache_array[1];
}
var ar = val;
repeat(array_depth + typeArray(display_type)) { //Recursively get the first member of subarray to check if value has depth of "array_depth" or not
if(!is_array(ar) || !array_length(ar)) { //empty array
cache_array[1] = false;
return cache_array[1];
}
if(array_length(val) > 0) {
cache_array[1] = is_array(val[0]);
return cache_array[1];
ar = ar[0];
}
cache_array[1] = false;
cache_array[1] = is_array(ar);
return cache_array[1];
}

View File

@ -459,10 +459,18 @@ function Panel_Inspector() : PanelContent() constructor {
break;
case VALUE_TYPE.text :
var _hh = 0;
if(instanceof(jun.editWidget) == "textBox")
_hh = jun.editWidget.draw(editBoxX, editBoxY, editBoxW, editBoxH, jun.showValue(), _m, jun.display_type);
else if(instanceof(jun.editWidget) == "textArea")
_hh = jun.editWidget.draw(ui(16), _hsy, w - ui(16 + 48), editBoxH, jun.showValue(), _m, jun.display_type);
switch(instanceof(jun.editWidget)) {
case "textBox":
_hh = jun.editWidget.draw(editBoxX, editBoxY, editBoxW, editBoxH, jun.showValue(), _m, jun.display_type);
break;
case "textArea":
_hh = jun.editWidget.draw(ui(16), _hsy, w - ui(16 + 48), editBoxH, jun.showValue(), _m, jun.display_type);
break;
case "textArrayBox":
_hh = jun.editWidget.draw(ui(16), editBoxY, editBoxW, editBoxH, _m, ui(16) + x, top_bar_h + y);
break;
}
widH = _hh;
break;
}

View File

@ -1,8 +1,9 @@
function textArrayBox(arraySet, data) : widget() constructor {
function textArrayBox(arraySet, data, onModify = noone) : widget() constructor {
self.getArray = arraySet;
self.arraySet = noone;
self.data = data;
self.onModify = onModify;
hide = false;
open = false;

View File

@ -4,7 +4,7 @@
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
const int attempt = 8;
uniform int attempt;
uniform float seed;
uniform vec2 dimension;
@ -22,10 +22,11 @@ void main() {
float _w = random(vec2( i, i) + v_vTexcoord.x, 8.10684 + seed);
vec4 col = texture2D( gm_BaseTexture, vec2(_x, _y) );
float br = (col.r + col.g + col.b) / 3. * col.a * _w;
float gr = (col.r + col.g + col.b) / 3.;
float br = gr * col.a * _w;
if(br > v) {
v = br;
gl_FragColor = vec4(_x, _y, 0., 1.);
gl_FragColor = vec4(_x, _y, gr, 1.);
}
}
}

View File

@ -7,6 +7,11 @@ varying vec4 v_vColour;
uniform sampler2D map;
void main() {
vec2 pos = texture2D( map, v_vTexcoord ).rg;
gl_FragColor = texture2D( gm_BaseTexture, vec2(1. - pos.x, pos.y) );
vec4 map = texture2D( map, v_vTexcoord );
vec2 pos = map.rg;
vec4 samp = texture2D( gm_BaseTexture, vec2(1. - pos.x, pos.y) );
samp.a *= map.a;
gl_FragColor = samp;
}

View File

@ -4,7 +4,7 @@
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
#define PI 3.14159265359
#define TAU 6.283185307179586
uniform sampler2D prevFrame;
uniform vec2 dimension;
@ -12,34 +12,32 @@ uniform float range;
void main() {
vec4 colCur = texture2D( gm_BaseTexture, v_vTexcoord );
vec4 colPre = texture2D( prevFrame, v_vTexcoord );
if(colCur.a > 0.) {
if(colCur.a > 0.5) {
gl_FragColor = colCur;
return;
}
gl_FragColor = vec4(0.);
float piStep = PI / 64.;
float aStep = TAU / 64.;
vec2 texel = 1. / dimension;
for(float i = 0.; i <= range; i++)
for(float j = 0.; j <= PI * 2.; j += piStep) {
vec2 shift = vec2(cos(j), sin(j)) * i / dimension;
for(float i = 1.; i <= range; i++)
for(float j = 0.; j <= TAU; j += aStep) {
vec2 shift = vec2(cos(j), sin(j)) * i * texel;
vec2 pos0 = v_vTexcoord + shift;
vec2 pos1 = v_vTexcoord - shift;
if(pos0.x < 0. || pos0.y < 0. || pos0.x > 1. || pos0.y > 1.) continue;
vec4 col0 = texture2D( prevFrame, pos0 );
if(col0.a == 0.) continue;
if(col0.a <= 0.5) continue;
vec2 norm = normalize(shift);
for(float k = 0.; k <= range; k++) {
vec2 posS = v_vTexcoord - norm * k / dimension;
vec2 norm = normalize(shift) * texel;
for(float k = 1.; k <= range; k++) {
vec2 posS = v_vTexcoord - norm * k;
if(posS.x < 0. || posS.y < 0. || posS.x > 1. || posS.y > 1.) continue;
vec4 colS = texture2D( gm_BaseTexture, posS );
if(colS.a == 0.) continue;
if(colS.a <= 0.5) continue;
gl_FragColor = colS;
return;

View File

@ -0,0 +1,69 @@
//
// Simple passthrough fragment shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
#define TAU 6.283185307179586
uniform sampler2D prevFrame;
uniform vec2 dimension;
uniform float range;
uniform float segmentStart;
uniform float segmentSize;
uniform int mode;
void main() {
gl_FragColor = vec4(0.);
vec4 colCur = texture2D( gm_BaseTexture, v_vTexcoord );
if(colCur.a > 0.5) {
if(mode == 0) gl_FragColor = colCur;
return;
}
vec2 texel = 1. / dimension;
for(float i = 0.; i <= range; i++) {
float base = 1.;
float top = 0.;
for(float j = 0.; j <= 64.; j++) {
float ang = top / base * TAU;
top += 2.;
if(top >= base) {
top = 1.;
base *= 2.;
}
vec2 shift = vec2(cos(ang), sin(ang)) * i * texel;
vec2 pos0 = v_vTexcoord + shift;
if(pos0.x < 0. || pos0.y < 0. || pos0.x > 1. || pos0.y > 1.) continue;
vec4 col0 = texture2D( gm_BaseTexture, pos0 );
if(col0.a <= 0.5) continue;
vec2 norm = normalize(shift) * texel;
int searchStage = 0;
for(float k = 0.; k <= range; k++) {
vec2 posS = v_vTexcoord - norm * k;
if(searchStage == 0 && (posS.x < 0. || posS.y < 0. || posS.x > 1. || posS.y > 1.)) continue;
vec4 colS = texture2D( prevFrame, posS );
if(mode == 0) {
if(distance(colS, col0) > 0.1) continue;
gl_FragColor = colS;
return;
} else {
if(searchStage == 0 && distance(colS, col0) < 0.1) {
searchStage = 1;
continue;
} else if(searchStage == 1 && distance(colS, col0) > 0.1) {
gl_FragColor = vec4(norm.x, norm.y, segmentStart + segmentSize * (1. - k / (k + i)), 1.);
return;
}
}
}
}
}
}

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
{
"resourceType": "GMShader",
"resourceVersion": "1.0",
"name": "sh_trail_filler_pass1",
"type": 1,
"parent": {
"name": "filter",
"path": "folders/shader/filter.yy",
},
}

View File

@ -0,0 +1,43 @@
//
// Simple passthrough fragment shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform vec2 dimension;
void main() {
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
float u = 0.;
float v = col.b;
if(col.a < 0.5) {
gl_FragColor = vec4(0.);
return;
}
float pos = 0.;
vec2 scPos = v_vTexcoord;
for( float i = 0.; i < dimension.x; i++ ) {
vec4 sm = texture2D( gm_BaseTexture, scPos );
if(sm.a < 0.5) break;
scPos.x -= sm.y;
scPos.y += sm.x;
pos++;
}
float tot = 0.;
vec2 scTot = v_vTexcoord;
for( float i = 0.; i < dimension.x; i++ ) {
vec4 sm = texture2D( gm_BaseTexture, scTot );
if(sm.a < 0.5) break;
scTot.x += sm.y;
scTot.y -= sm.x;
tot++;
}
u = pos / (pos + tot);
gl_FragColor = vec4(u, v, 0., col.a);
}

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
{
"resourceType": "GMShader",
"resourceVersion": "1.0",
"name": "sh_trail_filler_pass2",
"type": 1,
"parent": {
"name": "filter",
"path": "folders/shader/filter.yy",
},
}