New shrink palette node.

This commit is contained in:
Tanasart 2024-10-29 10:19:31 +07:00
parent 5a96df270e
commit 38940de773
13 changed files with 239 additions and 21 deletions

View file

@ -993,6 +993,7 @@
{"name":"node_palette_extract","order":7,"path":"scripts/node_palette_extract/node_palette_extract.yy",},
{"name":"node_palette_replace","order":2,"path":"scripts/node_palette_replace/node_palette_replace.yy",},
{"name":"node_palette_shift","order":13,"path":"scripts/node_palette_shift/node_palette_shift.yy",},
{"name":"node_palette_shrink","order":15,"path":"scripts/node_palette_shrink/node_palette_shrink.yy",},
{"name":"node_palette_sort","order":9,"path":"scripts/node_palette_sort/node_palette_sort.yy",},
{"name":"node_palette","order":4,"path":"scripts/node_palette/node_palette.yy",},
{"name":"node_particle","order":11,"path":"scripts/node_particle/node_particle.yy",},
@ -2078,7 +2079,6 @@
{"name":"s_node_2d_light_shape","order":14,"path":"sprites/s_node_2d_light_shape/s_node_2d_light_shape.yy",},
{"name":"s_node_3d_affector_shape","order":13,"path":"sprites/s_node_3d_affector_shape/s_node_3d_affector_shape.yy",},
{"name":"s_node_3d_array","order":7,"path":"sprites/s_node_3d_array/s_node_3d_array.yy",},
{"name":"s_node_3d_array1035","order":20,"path":"sprites/s_node_3d_array1035/s_node_3d_array1035.yy",},
{"name":"s_node_3d_camera_set","order":24,"path":"sprites/s_node_3d_camera_set/s_node_3d_camera_set.yy",},
{"name":"s_node_3d_camera","order":13,"path":"sprites/s_node_3d_camera/s_node_3d_camera.yy",},
{"name":"s_node_3d_cone","order":9,"path":"sprites/s_node_3d_cone/s_node_3d_cone.yy",},
@ -2388,6 +2388,7 @@
{"name":"s_node_palette_extract","order":15,"path":"sprites/s_node_palette_extract/s_node_palette_extract.yy",},
{"name":"s_node_palette_replace","order":16,"path":"sprites/s_node_palette_replace/s_node_palette_replace.yy",},
{"name":"s_node_palette_shift","order":39,"path":"sprites/s_node_palette_shift/s_node_palette_shift.yy",},
{"name":"s_node_palette_shrink","order":21,"path":"sprites/s_node_palette_shrink/s_node_palette_shrink.yy",},
{"name":"s_node_palette_sort","order":17,"path":"sprites/s_node_palette_sort/s_node_palette_sort.yy",},
{"name":"s_node_palette","order":14,"path":"sprites/s_node_palette/s_node_palette.yy",},
{"name":"s_node_particle_effector","order":13,"path":"sprites/s_node_particle_effector/s_node_particle_effector.yy",},

View file

@ -1578,6 +1578,7 @@
{"id":{"name":"node_palette_extract","path":"scripts/node_palette_extract/node_palette_extract.yy",},},
{"id":{"name":"node_palette_replace","path":"scripts/node_palette_replace/node_palette_replace.yy",},},
{"id":{"name":"node_palette_shift","path":"scripts/node_palette_shift/node_palette_shift.yy",},},
{"id":{"name":"node_palette_shrink","path":"scripts/node_palette_shrink/node_palette_shrink.yy",},},
{"id":{"name":"node_palette_sort","path":"scripts/node_palette_sort/node_palette_sort.yy",},},
{"id":{"name":"node_palette","path":"scripts/node_palette/node_palette.yy",},},
{"id":{"name":"node_particle","path":"scripts/node_particle/node_particle.yy",},},
@ -2800,7 +2801,6 @@
{"id":{"name":"s_node_2d_light","path":"sprites/s_node_2d_light/s_node_2d_light.yy",},},
{"id":{"name":"s_node_3d_affector_shape","path":"sprites/s_node_3d_affector_shape/s_node_3d_affector_shape.yy",},},
{"id":{"name":"s_node_3d_array","path":"sprites/s_node_3d_array/s_node_3d_array.yy",},},
{"id":{"name":"s_node_3d_array1035","path":"sprites/s_node_3d_array1035/s_node_3d_array1035.yy",},},
{"id":{"name":"s_node_3d_camera_set","path":"sprites/s_node_3d_camera_set/s_node_3d_camera_set.yy",},},
{"id":{"name":"s_node_3d_camera","path":"sprites/s_node_3d_camera/s_node_3d_camera.yy",},},
{"id":{"name":"s_node_3d_cone","path":"sprites/s_node_3d_cone/s_node_3d_cone.yy",},},
@ -3134,6 +3134,7 @@
{"id":{"name":"s_node_palette_extract","path":"sprites/s_node_palette_extract/s_node_palette_extract.yy",},},
{"id":{"name":"s_node_palette_replace","path":"sprites/s_node_palette_replace/s_node_palette_replace.yy",},},
{"id":{"name":"s_node_palette_shift","path":"sprites/s_node_palette_shift/s_node_palette_shift.yy",},},
{"id":{"name":"s_node_palette_shrink","path":"sprites/s_node_palette_shrink/s_node_palette_shrink.yy",},},
{"id":{"name":"s_node_palette_sort","path":"sprites/s_node_palette_sort/s_node_palette_sort.yy",},},
{"id":{"name":"s_node_palette","path":"sprites/s_node_palette/s_node_palette.yy",},},
{"id":{"name":"s_node_particle_effector","path":"sprites/s_node_particle_effector/s_node_particle_effector.yy",},},

View file

@ -43,7 +43,7 @@
VERSION = 1_18_01_0;
SAVE_VERSION = 1_18_02_0;
VERSION_STRING = MAC? "1.18.003m" : "1.18.3.007";
BUILD_NUMBER = 1_18_01_0;
BUILD_NUMBER = 1_18_03_0;
HOTKEYS = ds_map_create();
HOTKEY_CONTEXT = ds_list_create();

View file

@ -86,11 +86,11 @@ function Node_Grid(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons
newInput(34, nodeValueSeed(self, VALUE_TYPE.float, "Scale Seed"));
input_display_list = [
["Output", false], 0,
["Pattern", false], 1, 4, 15, 2, 13, 28, 3, 26, 27, 14,
["Shift", false], 9, 8, 16, 31, 32, 30,
["Scale", false], 29, 33, 34,
["Render", false], 10, 11, 5, 20, 6, 7, 25, 12, 24,
["Output", false], 0,
["Pattern", false], 1, 4, 15, 2, 13, 28, 3, 26, 27, 14,
["Shift", false], 9, 8, 16, 31, 32, 30,
["Scale", false], 33, 34, 29,
["Render", false], 10, 11, 5, 20, 6, 7, 25, 12, 24,
["Truchet", true, 17], 18, 19, 22, 23,
];

View file

@ -0,0 +1,202 @@
function Node_Palette_Shrink(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Shrink Palette";
setDimension(96);
newInput(0, nodeValue_Palette("Palette in", self, array_clone(DEF_PALETTE)))
.setVisible(true, true);
newInput(1, nodeValue_Enum_Button("Algorithm", self, 1, [ "Histogram", "K-mean" ]))
.rejectArray();
newInput(2, nodeValue_Int("Amount", self, 4));
newInput(3, nodeValueSeed(self, VALUE_TYPE.float));
newInput(4, nodeValue_Enum_Button("Color Space", self, 0, [ "RGB", "HSV" ]))
newOutput(0, nodeValue_Output("Palette", self, VALUE_TYPE.color, []))
.setDisplay(VALUE_DISPLAY.palette);
input_display_list = [
0, 4, 1, 2,
];
function kmean(_pal) {
_size = max(1, getInputData(2));
_space = getInputData(4);
_min = [ 1, 1, 1 ];
_max = [ 0, 0, 0 ];
var _cc, col = 0, colors = [];
for( var i = 0, n = array_length(_pal); i < n; i++ ) {
_cc = _pal[i];
switch(_space) {
case 0 : col = [ _color_get_red(_cc), _color_get_green(_cc), _color_get_blue(_cc), 0 ]; break;
case 1 : col = [ _color_get_hue(_cc), _color_get_saturation(_cc), _color_get_value(_cc), 0 ]; break;
}
array_push(colors, col);
_min[0] = min(_min[0], col[0]); _max[0] = max(_max[0], col[0]);
_min[1] = min(_min[1], col[1]); _max[1] = max(_max[1], col[1]);
_min[2] = min(_min[2], col[2]); _max[2] = max(_max[2], col[2]);
}
// random_set_seed(_seed);
// var cnt = array_create_ext(_size, () => [ random_range(_min[0], _max[0]), random_range(_min[1], _max[1]), random_range(_min[2], _max[2]), 0 ]);
var cnt = array_create_ext(_size, function(i) /*=>*/ {return [ lerp(_min[0], _max[0], i / (_size - 1)), lerp(_min[1], _max[1], i / (_size - 1)), lerp(_min[2], _max[2], i / (_size - 1)), 0 ]});
repeat(8) {
// var _cnt = array_create_ext(_size, (i) => [ cnt[i][0], cnt[i][1], cnt[i][2], 0 ]);
for( var i = 0, n = array_length(colors); i < n; i++ ) {
var ind = 0;
var dist = 999;
var _cl = colors[i];
for( var j = 0; j < _size; j++ ) {
var _cn = cnt[j];
var d = point_distance_3d(_cl[0], _cl[1], _cl[2], _cn[0], _cn[1], _cn[2]);
if(d < dist) {
dist = d;
ind = j;
}
}
colors[i][3] = ind;
}
for( var i = 0; i < _size; i++ )
cnt[i] = [ 0, 0, 0, 0 ];
for( var i = 0, n = array_length(colors); i < n; i++ ) {
var _cl = colors[i];
var _co = _cl[3];
cnt[_co][0] += _cl[0];
cnt[_co][1] += _cl[1];
cnt[_co][2] += _cl[2];
cnt[_co][3]++;
}
for( var i = 0; i < _size; i++ ) {
var _cc = cnt[i];
cnt[i][0] = _cc[3]? _cc[0] / _cc[3] : 0;
cnt[i][1] = _cc[3]? _cc[1] / _cc[3] : 0;
cnt[i][2] = _cc[3]? _cc[2] / _cc[3] : 0;
}
// var del = array_reduce(cnt, (prev, cur, i) => max(prev, point_distance_3d(cnt[i][0], cnt[i][1], cnt[i][2], cur[0], cur[1], cur[2])), 0);
// if(del < 0.001) break;
}
var palette = [];
var clr;
for( var i = 0; i < _size; i++ ) {
var closet = 0;
var dist = 999;
var _cl = cnt[i];
for( var j = 0, n = array_length(colors); j < n; j++ ) {
var _cn = colors[j];
var d = point_distance_3d(_cl[0], _cl[1], _cl[2], _cn[0], _cn[1], _cn[2]);
if(d < dist) {
dist = d;
closet = j;
}
}
var _cc = colors[closet];
switch(_space) {
case 0 : clr = make_color_rgba(_cc[0] * 255, _cc[1] * 255, _cc[2] * 255, 255); break;
case 1 : clr = make_color_hsva(_cc[0] * 255, _cc[1] * 255, _cc[2] * 255, 255); break;
}
array_push_unique(palette, clr);
}
return palette;
}
function histogram(_pal) {
var _size = max(1, getInputData(2));
var _space = getInputData(4);
var _min = [ 1, 1, 1 ];
var _max = [ 0, 0, 0 ];
var _cc, col, colors = [];
for( var i = 0, n = array_length(_pal); i < n; i++ ) {
_cc = _pal[i];
switch(_space) {
case 0 : col = [ _color_get_red(_cc), _color_get_green(_cc), _color_get_blue(_cc), 0 ]; break;
case 1 : col = [ _color_get_hue(_cc), _color_get_saturation(_cc), _color_get_value(_cc), 0 ]; break;
}
array_push(colors, col);
_min[0] = min(_min[0], col[0]); _max[0] = max(_max[0], col[0]);
_min[1] = min(_min[1], col[1]); _max[1] = max(_max[1], col[1]);
_min[2] = min(_min[2], col[2]); _max[2] = max(_max[2], col[2]);
}
var palette = array_create(_size);
var clr, _c0, _c1, _c2;
for( var i = 0, n = array_length(palette); i < n; i++ ) {
_c0 = lerp(_min[0], _max[0], i / (n - 1)) * 255;
_c1 = lerp(_min[1], _max[1], i / (n - 1)) * 255;
_c2 = lerp(_min[2], _max[2], i / (n - 1)) * 255;
switch(_space) {
case 0 : clr = make_color_rgba(_c0, _c1, _c2, 255); break;
case 1 : clr = make_color_hsva(_c0, _c1, _c2, 255); break;
}
palette[i] = clr;
}
return palette;
}
static processData = function(_outSurf, _data, _output_index, _array_index) {
var _pal = _data[0];
var _alg = _data[1];
if(!is_array(_pal)) return;
switch(_alg) {
case 0 : return histogram(_pal);
case 1 : return kmean(_pal);
}
return _pal;
}
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
var bbox = drawGetBbox(xx, yy, _s);
if(bbox.h < 1) return;
var pal = outputs[0].getValue();
if(array_empty(pal)) return;
if(!is_array(pal[0])) pal = [ pal ];
var _h = array_length(pal) * 32;
var _y = bbox.y0;
var gh = bbox.h / array_length(pal);
for( var i = 0, n = array_length(pal); i < n; i++ ) {
drawPalette(pal[i], bbox.x0, _y, bbox.w, gh);
_y += gh;
}
if(_h != min_h) will_setHeight = true;
min_h = _h;
}
}

View file

@ -0,0 +1,13 @@
{
"$GMScript":"v1",
"%Name":"node_palette_shrink",
"isCompatibility":false,
"isDnD":false,
"name":"node_palette_shrink",
"parent":{
"name":"color",
"path":"folders/nodes/data/value/color.yy",
},
"resourceType":"GMScript",
"resourceVersion":"2.0",
}

View file

@ -1013,6 +1013,7 @@ function __initNodes() {
ds_list_add(color, "Palettes");
addNodeObject(color, "Palette", s_node_palette, "Node_Palette", [1, Node_Palette],, "Create palette value. Note that palette is simple an array of colors.");
addNodeObject(color, "Sort Palette", s_node_palette_sort, "Node_Palette_Sort", [1, Node_Palette_Sort],, "Sort palette with specified order.").setVersion(1130);
addNodeObject(color, "Shrink Palette", s_node_palette_shrink, "Node_Palette_Shrink", [1, Node_Palette_Shrink],, "Reduce palette size by collapsing similiar colors.").setVersion(1_18_03_0);
addNodeObject(color, "Palette Extract", s_node_palette_extract, "Node_Palette_Extract", [1, Node_Palette_Extract],, "Extract palette from an image.").setVersion(1100);
addNodeObject(color, "Palette Replace", s_node_palette_replace, "Node_Palette_Replace", [1, Node_Palette_Replace],, "Replace colors in a palette with new one.").setVersion(1120);

View file

@ -257,7 +257,7 @@ void main() {
float cell = floor(_pos[antiAxis] * sca[antiAxis]);
float _sec = mod(cell, 2.);
float _shft = (_sec * secShift) + (_sec * shf);
float _shft = (_sec * secShift) + (cell * shf);
float _rdsh = randShift * (random(randShiftSeed / 1000. + vec2(cell / dimension.x)) * 2. - 1.);
_shft += _rdsh;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

View file

@ -1,27 +1,27 @@
{
"$GMSprite":"",
"%Name":"s_node_3d_array1035",
"%Name":"s_node_palette_shrink",
"bboxMode":0,
"bbox_bottom":57,
"bbox_left":0,
"bbox_right":63,
"bbox_top":6,
"bbox_bottom":63,
"bbox_left":2,
"bbox_right":61,
"bbox_top":0,
"collisionKind":1,
"collisionTolerance":0,
"DynamicTexturePage":false,
"edgeFiltering":false,
"For3D":false,
"frames":[
{"$GMSpriteFrame":"","%Name":"65e38a62-f610-4cf8-822a-16c39c40241a","name":"65e38a62-f610-4cf8-822a-16c39c40241a","resourceType":"GMSpriteFrame","resourceVersion":"2.0",},
{"$GMSpriteFrame":"","%Name":"6d55c407-53fa-405a-8406-9f2fe7e6f1d6","name":"6d55c407-53fa-405a-8406-9f2fe7e6f1d6","resourceType":"GMSpriteFrame","resourceVersion":"2.0",},
],
"gridX":0,
"gridY":0,
"height":64,
"HTile":false,
"layers":[
{"$GMImageLayer":"","%Name":"0b2cfd8a-b4f0-4322-8524-ba881a77392f","blendMode":0,"displayName":"default","isLocked":false,"name":"0b2cfd8a-b4f0-4322-8524-ba881a77392f","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,},
{"$GMImageLayer":"","%Name":"a39948a6-973c-4432-854a-7fe33b64f6d5","blendMode":0,"displayName":"default","isLocked":false,"name":"a39948a6-973c-4432-854a-7fe33b64f6d5","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,},
],
"name":"s_node_3d_array1035",
"name":"s_node_palette_shrink",
"nineSlice":null,
"origin":4,
"parent":{
@ -33,7 +33,7 @@
"resourceVersion":"2.0",
"sequence":{
"$GMSequence":"",
"%Name":"s_node_3d_array1035",
"%Name":"s_node_palette_shrink",
"autoRecord":true,
"backdropHeight":768,
"backdropImageOpacity":0.5,
@ -57,7 +57,7 @@
"resourceType":"KeyframeStore<MomentsEventKeyframe>",
"resourceVersion":"2.0",
},
"name":"s_node_3d_array1035",
"name":"s_node_palette_shrink",
"playback":1,
"playbackSpeed":30.0,
"playbackSpeedType":0,
@ -69,8 +69,8 @@
"tracks":[
{"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore<SpriteFrameKeyframe>":"","Keyframes":[
{"$Keyframe<SpriteFrameKeyframe>":"","Channels":{
"0":{"$SpriteFrameKeyframe":"","Id":{"name":"65e38a62-f610-4cf8-822a-16c39c40241a","path":"sprites/s_node_3d_array1035/s_node_3d_array1035.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",},
},"Disabled":false,"id":"77fe217e-7a99-4a4e-8e78-2eff8f9c7275","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"2.0","Stretch":false,},
"0":{"$SpriteFrameKeyframe":"","Id":{"name":"6d55c407-53fa-405a-8406-9f2fe7e6f1d6","path":"sprites/s_node_palette_shrink/s_node_palette_shrink.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",},
},"Disabled":false,"id":"57db72d8-daf6-4ee1-8118-1f2e8a2f903d","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe<SpriteFrameKeyframe>","resourceVersion":"2.0","Stretch":false,},
],"resourceType":"KeyframeStore<SpriteFrameKeyframe>","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,},
],
"visibleRange":null,