- [Replace Colors] Add palette sorting.

This commit is contained in:
Tanasart 2024-04-25 15:13:43 +07:00
parent ac58c863b6
commit 2a6190e5ab
16 changed files with 847 additions and 31 deletions

View file

@ -0,0 +1,102 @@
// 2024-04-25 11:12:56
function buttonGradient(_onApply, dialog = noone) : widget() constructor {
onApply = _onApply;
parentDialog = dialog;
current_gradient = noone;
side_button = noone;
function apply(value) { #region
if(!interactable) return;
onApply(value);
} #endregion
static trigger = function() { #region
var dialog = dialogCall(o_dialog_gradient, WIN_W / 2, WIN_H / 2);
dialog.setDefault(current_gradient.clone());
dialog.onApply = apply;
dialog.interactable = interactable;
if(parentDialog)
parentDialog.addChildren(dialog);
} #endregion
static drawParam = function(params) { return draw(params.x, params.y, params.w, params.h, params.data, params.m); }
static draw = function(_x, _y, _w, _h, _gradient, _m) { #region
x = _x;
y = _y;
w = _w;
var _bs = min(_h, ui(32));
hovering = hover && point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
if(_w - _bs > ui(100) && side_button && instanceof(side_button) == "buttonClass") {
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(8);
}
var _gw = _w - ui(8);
var _gh = _h - ui(8);
current_gradient = _gradient;
if(is_array(_gradient)) {
if(array_length(_gradient) == 0) return 0;
h = ui(8) + array_length(_gradient) * _gh;
current_gradient = _gradient[0];
} else {
h = _h;
}
if(!is_instanceof(current_gradient, gradientObject))
return 0;
var click = false;
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + h);
if(ihover && hoverRect) {
draw_sprite_stretched(THEME.button_def, 1, _x, _y, _w, h);
if(mouse_press(mb_left, iactive)) {
trigger();
click = true;
}
if(mouse_click(mb_left, iactive)) {
draw_sprite_stretched(THEME.button_def, 2, _x, _y, _w, h);
draw_sprite_stretched_ext(THEME.button_def, 3, _x, _y, _w, h, COLORS._main_accent, 1);
}
} else {
draw_sprite_stretched(THEME.button_def, 0, _x, _y, _w, h);
if(mouse_press(mb_left)) deactivate();
}
if(!is_array(_gradient)) _gradient = [ _gradient ];
for( var i = 0, n = array_length(_gradient); i < n; i++ ) {
var _grad = _gradient[i];
var _gx = _x + ui(4);
var _gy = _y + ui(4) + i * _gh;
if(is_instanceof(_grad, gradientObject))
_grad.draw(_gx, _gy, _gw, _gh);
}
if(WIDGET_CURRENT == self)
draw_sprite_stretched_ext(THEME.widget_selecting, 0, _x - ui(3), _y - ui(3), _w + ui(6), h + ui(6), COLORS._main_accent, 1);
if(DRAGGING && DRAGGING.type == "Gradient" && hover && hoverRect) {
draw_sprite_stretched_ext(THEME.ui_panel_active, 0, _x, _y, _w, h, COLORS._main_value_positive, 1);
if(mouse_release(mb_left))
onApply(DRAGGING.data);
}
resetFocus();
return h;
} #endregion
static clone = function() { #region
var cln = new buttonGradient(onApply, parentDialog);
return cln;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-16 09:39:26
// 2024-04-25 11:09:44
function buttonPalette(_onApply, dialog = noone) : widget() constructor {
onApply = _onApply;
parentDialog = dialog;
@ -46,7 +46,7 @@ function buttonPalette(_onApply, dialog = noone) : widget() constructor {
if(array_length(_color) > 0 && is_array(_color[0])) {
if(array_length(_color[0]) == 0) return 0;
h = ui(12) + array_length(_color) * _ph;
h = ui(8) + array_length(_color) * _ph;
current_palette = _color[0];
} else {
h = _h;
@ -77,8 +77,7 @@ function buttonPalette(_onApply, dialog = noone) : widget() constructor {
var _px = _x + ui(4);
var _py = _y + ui(4) + i * _ph;
if(is_array(_pal))
drawPalette(_pal, _px, _py, _pw, _ph);
if(is_array(_pal)) drawPalette(_pal, _px, _py, _pw, _ph);
}
if(WIDGET_CURRENT == self)

View file

@ -1,4 +1,4 @@
// 2024-04-16 09:39:25
// 2024-04-25 11:09:41
function buttonPalette(_onApply, dialog = noone) : widget() constructor {
onApply = _onApply;
parentDialog = dialog;
@ -77,8 +77,7 @@ function buttonPalette(_onApply, dialog = noone) : widget() constructor {
var _px = _x + ui(4);
var _py = _y + ui(4) + i * _ph;
if(is_array(_pal))
drawPalette(_pal, _px, _py, _pw, _ph);
if(is_array(_pal)) drawPalette(_pal, _px, _py, _pw, _ph);
}
if(WIDGET_CURRENT == self)

View file

@ -1,4 +1,4 @@
// 2024-04-18 12:08:21
// 2024-04-25 15:00:56
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
@ -39,8 +39,8 @@
LATEST_VERSION = 11600;
VERSION = 11700;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.rc3";
BUILD_NUMBER = 11700;
VERSION_STRING = "1.17.rc4";
BUILD_NUMBER = 11704;
globalvar HOTKEYS, HOTKEY_CONTEXT;
HOTKEYS = ds_map_create();

View file

@ -1,4 +1,4 @@
// 2024-04-18 12:08:17
// 2024-04-18 12:08:21
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;

View file

@ -0,0 +1,262 @@
// 2024-04-25 15:06:31
function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Replace Colors";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setDisplay(VALUE_DISPLAY.palette);
inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setDisplay(VALUE_DISPLAY.palette)
.setVisible(false, false);
inputs[| 3] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
.setDisplay(VALUE_DISPLAY.slider);
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;
__init_mask_modifier(4); // inputs 7, 8,
selecting_index = 0;
function setColor(colr) { #region
var _to = array_clone(getInputData(2));
_to[selecting_index] = colr;
inputs[| 2].setValue(_to); // Not necessary due to array reference
} #endregion
sort_menu = [
new MenuItem("Sort Brightness", () => { sortPalette(0) }),
new MenuItem("Sort Dark", () => { sortPalette(1) }),
new MenuItem("Sort Hue", () => { sortPalette(2) }),
new MenuItem("Sort Saturation", () => { sortPalette(3) }),
new MenuItem("Sort Value", () => { sortPalette(4) }),
new MenuItem("Sort Red", () => { sortPalette(5) }),
new MenuItem("Sort Green", () => { sortPalette(6) }),
new MenuItem("Sort Blue", () => { sortPalette(7) }),
];
render_palette = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
var bx = _x;
var by = _y;
var bs = ui(24);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.refresh_16) == 2)
refreshPalette();
bx += bs + ui(4);
var jun = inputs[| 2];
var index = jun.isLeaf()? jun.is_anim : 2;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.animate_clock, index, index == 2? COLORS._main_accent : COLORS._main_icon) == 2)
jun.setAnim(!jun.is_anim);
bx += bs + ui(4);
var vis = jun.visible;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.junc_visible, vis) == 2)
jun.visible = !vis;
bx += bs + ui(4);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.sort_16) == 2)
menuCall("", mouse_mx + ui(4), mouse_my + ui(4), sort_menu);
var _from = getInputData(1);
var _to = getInputData(2);
var ss = TEXTBOX_HEIGHT;
var amo = array_length(_from);
var top = bs + ui(8);
var hh = top + (amo * (ss + ui(8)) + ui(8));
var _yy = _y + top;
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _x, _yy, _w, hh - top, COLORS.node_composite_bg_blend, 1);
for( var i = 0; i < amo; i++ ) {
var fr = array_safe_get_fast(_from, i);
var to = array_safe_get_fast(_to, i);
var _x0 = _x + ui(8);
var _y0 = _yy + ui(8) + i * (ss + ui(8));
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x0, _y0, ss, ss, COLORS._main_icon, 0.5);
draw_sprite_stretched_ext(THEME.color_picker_box, 1, _x0, _y0, ss, ss, fr, 1);
var _x1 = _x0 + ss + ui(32);
var _x2 = _x + _w - ui(8);
bx = _x2 - ui(32);
_x2 -= ui(32 + 4);
by = _y0 + ss / 2 - ui(32) / 2;
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), _m, _focus, _hover,, THEME.color_picker_dropper,, c_white) == 2) {
var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2);
dialog.selector.dropper_active = true;
dialog.selector.dropper_close = true;
dialog.selector.onApply = setColor;
dialog.onApply = setColor;
}
bx = _x2 - ui(32);
_x2 -= ui(32 + 4);
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), _m, _focus, _hover,, THEME.color_wheel,, c_white) == 2) {
var pick = instance_create(mouse_mx, mouse_my, o_dialog_color_quick_pick);
pick.onApply = setColor;
selecting_index = i;
}
_x2 -= ui(4);
var _xw = _x2 - _x1;
draw_sprite_ext(THEME.arrow, 0, (_x0 + ss + _x1) / 2, _y0 + ss / 2, 1, 1, 0, c_white, 0.5);
draw_sprite_stretched_ext(THEME.color_picker_box, 1, _x1, _y0, _xw, ss, to, 1);
if(_hover && point_in_rectangle(_m[0], _m[1], _x1, _y0, _x1 + _xw, _y0 + ss)) {
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x1, _y0, _xw, ss, COLORS._main_icon, 1);
if(mouse_press(mb_left, _focus)) {
var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2);
dialog.setDefault(to);
dialog.selector.onApply = setColor;
dialog.onApply = setColor;
selecting_index = i;
}
} else
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x1, _y0, _xw, ss, COLORS._main_icon, 0.5);
}
return hh;
}); #endregion
input_display_list = [ 6,
["Surfaces", true], 0, 4, 5, 7, 8,
["Replace", false], render_palette, 2,
//["Comparison", false], 3,
];
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
attribute_surface_depth();
attributes.auto_refresh = true;
array_push(attributeEditors, ["Auto refresh", function() { return attributes.auto_refresh; },
new checkBox(function() {
attributes.auto_refresh = !attributes.auto_refresh;
triggerRender();
})]);
static sortPalette = function(type) {
var palFrom = inputs[| 1].getValue();
var palTo = inputs[| 2].getValue();
var _map = ds_map_create();
for (var i = 0, n = array_length(palFrom); i < n; i++)
_map[? palFrom[i]] = palTo[i];
switch(type) {
case 0 : array_sort(palFrom, __sortBright); break;
case 1 : array_sort(palFrom, __sortDark); break;
case 2 : array_sort(palFrom, __sortHue); break;
case 3 : array_sort(palFrom, __sortSat); break;
case 4 : array_sort(palFrom, __sortVal); break;
case 5 : array_sort(palFrom, __sortRed); break;
case 6 : array_sort(palFrom, __sortGreen); break;
case 7 : array_sort(palFrom, __sortBlue); break;
}
for (var i = 0, n = array_length(palTo); i < n; i++)
palTo[i] = _map[? palFrom[i]]
ds_map_destroy(_map);
inputs[| 1].setValue(palFrom);
inputs[| 2].setValue(palTo);
}
static refreshPalette = function() { #region
var _surf = inputs[| 0].getValue();
inputs[| 1].setValue([]);
inputs[| 2].setValue([]);
if(!is_array(_surf))
_surf = [ _surf ];
var _pall = ds_map_create();
for( var i = 0, n = array_length(_surf); i < n; i++ ) {
var _s = _surf[i];
if(!is_surface(_s)) continue;
var ww = surface_get_width_safe(_s);
var hh = surface_get_height_safe(_s);
var c_buffer = buffer_create(ww * hh * 4, buffer_fixed, 2);
buffer_get_surface(c_buffer, _s, 0);
buffer_seek(c_buffer, buffer_seek_start, 0);
for( var i = 0; i < ww * hh; i++ ) {
var b = buffer_read(c_buffer, buffer_u32);
var c = b & ~(0b11111111 << 24);
var a = b & (0b11111111 << 24);
if(a == 0) continue;
c = make_color_rgb(color_get_red(c), color_get_green(c), color_get_blue(c));
_pall[? c] = 1;
}
buffer_delete(c_buffer);
}
var palette = ds_map_keys_to_array(_pall);
ds_map_destroy(_pall);
inputs[| 1].setValue(palette);
inputs[| 2].setValue(palette);
} #endregion
static onValueFromUpdate = function(index) { #region
if(LOADING || APPENDING || CLONING) return;
if(index == 0 && attributes.auto_refresh) refreshPalette();
} #endregion
static step = function() { #region
__step_mask_modifier();
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var fr = _data[1];
var to = _data[2];
var tr = _data[3];
var msk = _data[4];
surface_set_shader(_outSurf, sh_colours_replace);
shader_set_palette(fr, "colorFrom", "colorFromAmount");
shader_set_palette(to, "colorTo", "colorToAmount");
shader_set_i("useMask", is_surface(msk));
shader_set_surface("mask", msk);
draw_surface_safe(_data[0], 0, 0);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_data[0], _outSurf, _data[4], _data[5]);
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,262 @@
// 2024-04-25 15:06:02
function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Replace Colors";
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setDisplay(VALUE_DISPLAY.palette);
inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setDisplay(VALUE_DISPLAY.palette)
.setVisible(false, false);
inputs[| 3] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
.setDisplay(VALUE_DISPLAY.slider);
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;
__init_mask_modifier(4); // inputs 7, 8,
selecting_index = 0;
function setColor(colr) { #region
var _to = array_clone(getInputData(2));
_to[selecting_index] = colr;
inputs[| 2].setValue(_to); // Not necessary due to array reference
} #endregion
sort_menu = [
new MenuItem("Sort Brightness", () => { sortPalette(0) }),
new MenuItem("Sort Dark", () => { sortPalette(1) }),
new MenuItem("Sort Hue", () => { sortPalette(2) }),
new MenuItem("Sort Saturation", () => { sortPalette(3) }),
new MenuItem("Sort Value", () => { sortPalette(4) }),
new MenuItem("Sort Red", () => { sortPalette(5) }),
new MenuItem("Sort Green", () => { sortPalette(6) }),
new MenuItem("Sort Blue", () => { sortPalette(7) }),
];
render_palette = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
var bx = _x;
var by = _y;
var bs = ui(24);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.refresh_16) == 2)
refreshPalette();
bx += bs + ui(4);
var jun = inputs[| 2];
var index = jun.isLeaf()? jun.is_anim : 2;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.animate_clock, index, index == 2? COLORS._main_accent : COLORS._main_icon) == 2)
jun.setAnim(!jun.is_anim);
bx += bs + ui(4);
var vis = jun.visible;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.junc_visible, vis) == 2)
jun.visible = !vis;
bx += bs + ui(4);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.sort_16) == 2)
menuCall("", mouse_mx + ui(4), mouse_my + ui(4), sort_menu);
var _from = getInputData(1);
var _to = getInputData(2);
var ss = TEXTBOX_HEIGHT;
var amo = array_length(_from);
var top = bs + ui(8);
var hh = top + (amo * (ss + ui(8)) + ui(8));
var _yy = _y + top;
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _x, _yy, _w, hh - top, COLORS.node_composite_bg_blend, 1);
for( var i = 0; i < amo; i++ ) {
var fr = array_safe_get_fast(_from, i);
var to = array_safe_get_fast(_to, i);
var _x0 = _x + ui(8);
var _y0 = _yy + ui(8) + i * (ss + ui(8));
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x0, _y0, ss, ss, COLORS._main_icon, 0.5);
draw_sprite_stretched_ext(THEME.color_picker_box, 1, _x0, _y0, ss, ss, fr, 1);
var _x1 = _x0 + ss + ui(32);
var _x2 = _x + _w - ui(8);
bx = _x2 - ui(32);
_x2 -= ui(32 + 4);
by = _y0 + ss / 2 - ui(32) / 2;
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), _m, _focus, _hover,, THEME.color_picker_dropper,, c_white) == 2) {
var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2);
dialog.selector.dropper_active = true;
dialog.selector.dropper_close = true;
dialog.selector.onApply = setColor;
dialog.onApply = setColor;
}
bx = _x2 - ui(32);
_x2 -= ui(32 + 4);
if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), _m, _focus, _hover,, THEME.color_wheel,, c_white) == 2) {
var pick = instance_create(mouse_mx, mouse_my, o_dialog_color_quick_pick);
pick.onApply = setColor;
selecting_index = i;
}
_x2 -= ui(4);
var _xw = _x2 - _x1;
draw_sprite_ext(THEME.arrow, 0, (_x0 + ss + _x1) / 2, _y0 + ss / 2, 1, 1, 0, c_white, 0.5);
draw_sprite_stretched_ext(THEME.color_picker_box, 1, _x1, _y0, _xw, ss, to, 1);
if(_hover && point_in_rectangle(_m[0], _m[1], _x1, _y0, _x1 + _xw, _y0 + ss)) {
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x1, _y0, _xw, ss, COLORS._main_icon, 1);
if(mouse_press(mb_left, _focus)) {
var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2);
dialog.setDefault(to);
dialog.selector.onApply = setColor;
dialog.onApply = setColor;
selecting_index = i;
}
} else
draw_sprite_stretched_ext(THEME.color_picker_box, 0, _x1, _y0, _xw, ss, COLORS._main_icon, 0.5);
}
return hh;
}); #endregion
input_display_list = [ 6,
["Surfaces", true], 0, 4, 5, 7, 8,
["Replace", false], render_palette, 2,
//["Comparison", false], 3,
];
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
attribute_surface_depth();
attributes.auto_refresh = true;
array_push(attributeEditors, ["Auto refresh", function() { return attributes.auto_refresh; },
new checkBox(function() {
attributes.auto_refresh = !attributes.auto_refresh;
triggerRender();
})]);
static sortPalette = function(type) {
var palFrom = inputs[| 1].getValue();
var palTo = inputs[| 2].getValue();
var _map = ds_map_create();
for (var i = 0, n = array_length(palFrom); i < n; i++)
_map[? palFrom[i]] = palTo[i];
switch(type) {
case 0 : array_sort(palFrom, __sortBright); break;
case 1 : array_sort(palFrom, __sortDark); break;
case 2 : array_sort(palFrom, __sortHue); break;
case 3 : array_sort(palFrom, __sortSat); break;
case 4 : array_sort(palFrom, __sortVal); break;
case 5 : array_sort(palFrom, __sortRed); break;
case 6 : array_sort(palFrom, __sortGreen); break;
case 7 : array_sort(palFrom, __sortBlue); break;
}
for (var i = 0, n = array_length(palTo); i < n; i++)
palTo[i] = _map[? palFrom[i]]
ds_map_destroy(_map);
inputs[| 1].setValue(palFrom);
inputs[| 2].setValue(palTo);
}
static refreshPalette = function() { #region
var _surf = inputs[| 0].getValue();
inputs[| 1].setValue([]);
inputs[| 2].setValue([]);
if(!is_array(_surf))
_surf = [ _surf ];
var _pall = ds_map_create();
for( var i = 0, n = array_length(_surf); i < n; i++ ) {
var _s = _surf[i];
if(!is_surface(_s)) continue;
var ww = surface_get_width_safe(_s);
var hh = surface_get_height_safe(_s);
var c_buffer = buffer_create(ww * hh * 4, buffer_fixed, 2);
buffer_get_surface(c_buffer, _s, 0);
buffer_seek(c_buffer, buffer_seek_start, 0);
for( var i = 0; i < ww * hh; i++ ) {
var b = buffer_read(c_buffer, buffer_u32);
var c = b & ~(0b11111111 << 24);
var a = b & (0b11111111 << 24);
if(a == 0) continue;
c = make_color_rgb(color_get_red(c), color_get_green(c), color_get_blue(c));
_pall[? c] = 1;
}
buffer_delete(c_buffer);
}
var palette = ds_map_keys_to_array(_pall);
ds_map_destroy(_pall);
inputs[| 1].setValue(palette);
inputs[| 2].setValue(palette);
} #endregion
static onValueFromUpdate = function(index) { #region
if(LOADING || APPENDING || CLONING) return;
if(index == 0 && attributes.auto_refresh) refreshPalette();
} #endregion
static step = function() { #region
__step_mask_modifier();
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var fr = _data[1];
var to = _data[2];
var tr = _data[3];
var msk = _data[4];
surface_set_shader(_outSurf, sh_colours_replace);
shader_set_palette(fr, "colorFrom", "colorFromAmount");
shader_set_palette(to, "colorTo", "colorToAmount");
shader_set_i("useMask", is_surface(msk));
shader_set_surface("mask", msk);
draw_surface_safe(_data[0], 0, 0);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_data[0], _outSurf, _data[4], _data[5]);
return _outSurf;
} #endregion
}

View file

@ -0,0 +1,77 @@
// 2024-04-25 11:36:54
function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Palette to Gradient";
setDimension(96);
inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE))
.setDisplay(VALUE_DISPLAY.palette)
.setVisible(true, true);
inputs[| 1] = nodeValue("Custom positions", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 2] = nodeValue("Positions", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [], "Array of number indicating color position (0 - 1).")
.setVisible(true, true);
inputs[| 2].array_depth = 1;
inputs[| 3] = nodeValue("Interpolation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, [ "None", "RGB", "HSV", "OKLAB", "sRGB" ]);
outputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.output, VALUE_TYPE.gradient, new gradientObject(c_white) )
_pal = -1;
static step = function() { #region
var usePos = array_safe_get_fast(current_data, 1);
inputs[| 2].setVisible(usePos, usePos);
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var pal = _data[0];
var pos_use = _data[1];
var _pos = _data[2];
var type = _data[3];
var grad = new gradientObject();
var len = min(128, array_length(pal));
grad.keys = array_create(len);
var _stp = type == GRADIENT_INTER.none? 1 / (len - 1) : 1 / len;
for( var i = 0; i < len; i++ ) {
var clr = pal[i];
var pos = pos_use? array_safe_get_fast(_pos, i, 0) : i * _stp;
grad.keys[i] = new gradientKey(pos, clr);
}
switch(type) {
case 0 : grad.type = GRADIENT_INTER.none; break;
case 1 : grad.type = GRADIENT_INTER.smooth; break;
case 2 : grad.type = GRADIENT_INTER.hue; break;
case 3 : grad.type = GRADIENT_INTER.oklab; break;
case 4 : grad.type = GRADIENT_INTER.srgb; break;
}
return grad;
} #endregion
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
var bbox = drawGetBbox(xx, yy, _s);
if(bbox.h < 1) return;
var grad = outputs[| 0].getValue();
if(!is_array(grad)) grad = [ grad ];
var _h = array_length(grad) * 32;
var _y = bbox.y0;
var gh = bbox.h / array_length(grad);
for( var i = 0, n = array_length(grad); i < n; i++ ) {
grad[i].draw(bbox.x0, _y, bbox.w, gh);
_y += gh;
}
if(_h != min_h) will_setHeight = true;
min_h = _h;
} #endregion
}

View file

@ -0,0 +1,77 @@
// 2024-04-25 11:17:40
function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Palette to Gradient";
setDimension(96);
inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE))
.setDisplay(VALUE_DISPLAY.palette)
.setVisible(true, true);
inputs[| 1] = nodeValue("Custom positions", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
inputs[| 2] = nodeValue("Positions", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [], "Array of number indicating color position (0 - 1).")
.setVisible(true, true);
inputs[| 2].array_depth = 1;
inputs[| 3] = nodeValue("Interpolation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, [ "None", "RGB", "HSV", "OKLAB", "sRGB" ]);
outputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.output, VALUE_TYPE.gradient, new gradientObject(c_white) )
_pal = -1;
static step = function() { #region
var usePos = array_safe_get_fast(current_data, 1);
inputs[| 2].setVisible(usePos, usePos);
} #endregion
static processData = function(_outSurf, _data, _output_index, _array_index) { #region
var pal = _data[0];
var pos_use = _data[1];
var _pos = _data[2];
var type = _data[3];
var grad = new gradientObject();
var len = min(128, array_length(pal));
grad.keys = array_create(len);
var _stp = type == GRADIENT_INTER.none? 1 / (len - 1) : 1 / len;
for( var i = 0; i < len; i++ ) {
var clr = pal[i];
var pos = pos_use? array_safe_get_fast(_pos, i, 0) : i * _stp;
grad.keys[i] = new gradientKey(pos, clr);
}
switch(type) {
case 0 : grad.type = GRADIENT_INTER.none; break;
case 1 : grad.type = GRADIENT_INTER.smooth; break;
case 2 : grad.type = GRADIENT_INTER.hue; break;
case 3 : grad.type = GRADIENT_INTER.oklab; break;
case 4 : grad.type = GRADIENT_INTER.srgb; break;
}
return grad;
} #endregion
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
var bbox = drawGetBbox(xx, yy, _s);
if(bbox.h < 1) return;
var grad = outputs[| 0].getValue();
if(!is_array(grad)) grad = [ grad ];
var _h = array_length(grad) * 32;
var _y = bbox.y0;
var gh = bbox.h / array_length(grad);
for( var i = 0, n = array_length(grad); i < n; i++ ) {
grad[i].draw(bbox.x0, _y, bbox.w, gh);
_y += gh;
}
if(_h != min_h) will_setHeight = true;
min_h = _h;
} #endregion
}

View file

@ -1,4 +1,4 @@
// 2024-04-20 09:44:05
// 2024-04-25 11:08:24
function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Palette";
setDimension(96);

View file

@ -1,4 +1,4 @@
// 2024-04-20 09:23:40
// 2024-04-20 09:44:05
function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Palette";
setDimension(96);
@ -6,16 +6,6 @@ function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) c
inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE))
.setDisplay(VALUE_DISPLAY.palette);
var p = "";
var pl = inputs[| 0].animator.values[| 0].value;
for (var i = 0, n = array_length(pl); i < n; i++) p += number_to_hex(pl[i]) + ", ";
print(p);
var p = "";
var pl = DEF_PALETTE;
for (var i = 0, n = array_length(pl); i < n; i++) p += number_to_hex(pl[i]) + ", ";
print(p);
inputs[| 1] = nodeValue("Trim range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ])
.setDisplay(VALUE_DISPLAY.slider_range);

Binary file not shown.

View file

@ -44,7 +44,7 @@ function buttonGradient(_onApply, dialog = noone) : widget() constructor {
if(is_array(_gradient)) {
if(array_length(_gradient) == 0) return 0;
h = ui(12) + array_length(_gradient) * _gh;
h = ui(8) + array_length(_gradient) * _gh;
current_gradient = _gradient[0];
} else {
h = _h;

View file

@ -45,7 +45,7 @@ function buttonPalette(_onApply, dialog = noone) : widget() constructor {
if(array_length(_color) > 0 && is_array(_color[0])) {
if(array_length(_color[0]) == 0) return 0;
h = ui(12) + array_length(_color) * _ph;
h = ui(8) + array_length(_color) * _ph;
current_palette = _color[0];
} else {
h = _h;
@ -76,8 +76,7 @@ function buttonPalette(_onApply, dialog = noone) : widget() constructor {
var _px = _x + ui(4);
var _py = _y + ui(4) + i * _ph;
if(is_array(_pal))
drawPalette(_pal, _px, _py, _pw, _ph);
if(is_array(_pal)) drawPalette(_pal, _px, _py, _pw, _ph);
}
if(WIDGET_CURRENT == self)

View file

@ -31,6 +31,19 @@ function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _g
inputs[| 2].setValue(_to); // Not necessary due to array reference
} #endregion
sort_menu = [
new MenuItem("Sort Brightness", function() /*=>*/ { sortPalette(0) }),
new MenuItem("Sort Dark", function() /*=>*/ { sortPalette(1) }),
new MenuItem("Sort Hue", function() /*=>*/ { sortPalette(2) }),
new MenuItem("Sort Saturation", function() /*=>*/ { sortPalette(3) }),
new MenuItem("Sort Value", function() /*=>*/ { sortPalette(4) }),
new MenuItem("Sort Red", function() /*=>*/ { sortPalette(5) }),
new MenuItem("Sort Green", function() /*=>*/ { sortPalette(6) }),
new MenuItem("Sort Blue", function() /*=>*/ { sortPalette(7) }),
];
render_palette = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
var bx = _x;
var by = _y;
@ -50,6 +63,10 @@ function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _g
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.junc_visible, vis) == 2)
jun.visible = !vis;
bx += bs + ui(4);
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover,, THEME.sort_16) == 2)
menuCall("", mouse_mx + ui(4), mouse_my + ui(4), sort_menu);
var _from = getInputData(1);
var _to = getInputData(2);
@ -136,6 +153,36 @@ function Node_Colors_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _g
attributes.auto_refresh = !attributes.auto_refresh;
triggerRender();
})]);
static sortPalette = function(type) {
var palFrom = inputs[| 1].getValue();
var palTo = inputs[| 2].getValue();
var _map = ds_map_create();
for (var i = 0, n = array_length(palFrom); i < n; i++)
_map[? palFrom[i]] = palTo[i];
switch(type) {
case 0 : array_sort(palFrom, __sortBright); break;
case 1 : array_sort(palFrom, __sortDark); break;
case 2 : array_sort(palFrom, __sortHue); break;
case 3 : array_sort(palFrom, __sortSat); break;
case 4 : array_sort(palFrom, __sortVal); break;
case 5 : array_sort(palFrom, __sortRed); break;
case 6 : array_sort(palFrom, __sortGreen); break;
case 7 : array_sort(palFrom, __sortBlue); break;
}
for (var i = 0, n = array_length(palTo); i < n; i++)
palTo[i] = _map[? palFrom[i]]
ds_map_destroy(_map);
inputs[| 1].setValue(palFrom);
inputs[| 2].setValue(palTo);
}
static refreshPalette = function() { #region
var _surf = inputs[| 0].getValue();

View file

@ -1,6 +1,6 @@
function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Palette to Gradient";
w = 96;
setDimension(96);
inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE))
.setDisplay(VALUE_DISPLAY.palette)
@ -12,8 +12,8 @@ function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y,
.setVisible(true, true);
inputs[| 2].array_depth = 1;
inputs[| 3] = nodeValue("Color Space", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, [ "Hard", "RGB", "HSV", "OKLAB", "sRGB" ]);
inputs[| 3] = nodeValue("Interpolation", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1)
.setDisplay(VALUE_DISPLAY.enum_button, [ "None", "RGB", "HSV", "OKLAB", "sRGB" ]);
outputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.output, VALUE_TYPE.gradient, new gradientObject(c_white) )
@ -34,9 +34,11 @@ function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y,
var len = min(128, array_length(pal));
grad.keys = array_create(len);
var _stp = type == GRADIENT_INTER.none? 1 / (len - 1) : 1 / len;
for( var i = 0; i < len; i++ ) {
var clr = pal[i];
var pos = pos_use? array_safe_get_fast(_pos, i, 0) : i / (len - 1);
var pos = pos_use? array_safe_get_fast(_pos, i, 0) : i * _stp;
grad.keys[i] = new gradientKey(pos, clr);
}