From c18d458b508194912c343743baeefc563d820720 Mon Sep 17 00:00:00 2001 From: Tanasart Date: Sun, 19 May 2024 20:11:45 +0700 Subject: [PATCH] palette mixer --- PixelComposer.resource_order | 2 + PixelComposer.yyp | 2 + .../o_dialog_add_multiple_images/Draw_64.gml | 4 +- objects/o_dialog_menubox/Create_0.gml | 2 +- objects/o_main/Create_0.gml | 4 +- objects/o_pie_menu/Create_0.gml | 4 + objects/o_pie_menu/Draw_64.gml | 27 +- scripts/buttonPalette/buttonPalette.gml | 8 +- .../node_cross_section/node_cross_section.gml | 21 + .../node_cross_section/node_cross_section.yy | 13 + scripts/panel_color/panel_color.gml | 6 +- .../panel_file_explorer.gml | 90 +++- scripts/panel_function/panel_function.gml | 9 +- scripts/panel_graph/panel_graph.gml | 10 +- scripts/panel_menu/panel_menu.gml | 2 + .../panel_palette_mixer.gml | 423 ++++++++++++++++++ .../panel_palette_mixer.yy | 13 + scripts/preferences/preferences.gml | 2 + 18 files changed, 599 insertions(+), 43 deletions(-) create mode 100644 scripts/node_cross_section/node_cross_section.gml create mode 100644 scripts/node_cross_section/node_cross_section.yy create mode 100644 scripts/panel_palette_mixer/panel_palette_mixer.gml create mode 100644 scripts/panel_palette_mixer/panel_palette_mixer.yy diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index aaf7c5b15..5773dd044 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -1101,6 +1101,7 @@ {"name":"panel_node_data_gen","order":7,"path":"scripts/panel_node_data_gen/panel_node_data_gen.yy",}, {"name":"panel_nodes","order":2,"path":"scripts/panel_nodes/panel_nodes.yy",}, {"name":"panel_notification","order":2,"path":"scripts/panel_notification/panel_notification.yy",}, + {"name":"panel_palette_mixer","order":3,"path":"scripts/panel_palette_mixer/panel_palette_mixer.yy",}, {"name":"panel_patreon","order":2,"path":"scripts/panel_patreon/panel_patreon.yy",}, {"name":"panel_preview_3d_setting","order":2,"path":"scripts/panel_preview_3d_setting/panel_preview_3d_setting.yy",}, {"name":"panel_preview_grid_setting","order":4,"path":"scripts/panel_preview_grid_setting/panel_preview_grid_setting.yy",}, @@ -1144,6 +1145,7 @@ {"name":"safe_operation","order":6,"path":"scripts/safe_operation/safe_operation.yy",}, {"name":"sample_projects","order":6,"path":"scripts/sample_projects/sample_projects.yy",}, {"name":"save_function","order":1,"path":"scripts/save_function/save_function.yy",}, + {"name":"node_cross_section","order":20,"path":"scripts/node_cross_section/node_cross_section.yy",}, {"name":"scrollBox","order":2,"path":"scripts/scrollBox/scrollBox.yy",}, {"name":"scrollPane","order":3,"path":"scripts/scrollPane/scrollPane.yy",}, {"name":"shell_functions","order":20,"path":"scripts/shell_functions/shell_functions.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index a0d98de25..898e95b23 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -1569,6 +1569,7 @@ {"id":{"name":"panel_node_data_gen","path":"scripts/panel_node_data_gen/panel_node_data_gen.yy",},}, {"id":{"name":"panel_nodes","path":"scripts/panel_nodes/panel_nodes.yy",},}, {"id":{"name":"panel_notification","path":"scripts/panel_notification/panel_notification.yy",},}, + {"id":{"name":"panel_palette_mixer","path":"scripts/panel_palette_mixer/panel_palette_mixer.yy",},}, {"id":{"name":"panel_palette","path":"scripts/panel_palette/panel_palette.yy",},}, {"id":{"name":"panel_patreon","path":"scripts/panel_patreon/panel_patreon.yy",},}, {"id":{"name":"panel_preview_3d_setting","path":"scripts/panel_preview_3d_setting/panel_preview_3d_setting.yy",},}, @@ -1620,6 +1621,7 @@ {"id":{"name":"safe_operation","path":"scripts/safe_operation/safe_operation.yy",},}, {"id":{"name":"sample_projects","path":"scripts/sample_projects/sample_projects.yy",},}, {"id":{"name":"save_function","path":"scripts/save_function/save_function.yy",},}, + {"id":{"name":"node_cross_section","path":"scripts/node_cross_section/node_cross_section.yy",},}, {"id":{"name":"scrollBox","path":"scripts/scrollBox/scrollBox.yy",},}, {"id":{"name":"scrollPane","path":"scripts/scrollPane/scrollPane.yy",},}, {"id":{"name":"shader_functions","path":"scripts/shader_functions/shader_functions.yy",},}, diff --git a/objects/o_dialog_add_multiple_images/Draw_64.gml b/objects/o_dialog_add_multiple_images/Draw_64.gml index 3c61b1040..5655e87ee 100644 --- a/objects/o_dialog_add_multiple_images/Draw_64.gml +++ b/objects/o_dialog_add_multiple_images/Draw_64.gml @@ -23,8 +23,8 @@ if !ready exit; PANEL_GRAPH.stepBegin(); - var nx = (PANEL_GRAPH.w / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_x; - var ny = (PANEL_GRAPH.h / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_y; + var nx = PANEL_GRAPH.graph_cx; + var ny = PANEL_GRAPH.graph_cy; draw_sprite_stretched(THEME.node_bg, 0, xx, yy, grid_size, grid_size); if(sHOVER && point_in_rectangle(mouse_mx, mouse_my, xx, yy, xx + grid_width, yy + grid_size)) { diff --git a/objects/o_dialog_menubox/Create_0.gml b/objects/o_dialog_menubox/Create_0.gml index 3c864c098..9c7686930 100644 --- a/objects/o_dialog_menubox/Create_0.gml +++ b/objects/o_dialog_menubox/Create_0.gml @@ -11,7 +11,7 @@ event_inherited(); alarm[0] = -1; menu = 1; - hght = ui(32); + hght = ui(36); tooltips = []; show_icon = false; diff --git a/objects/o_main/Create_0.gml b/objects/o_main/Create_0.gml index a84e905ff..9533dbb72 100644 --- a/objects/o_main/Create_0.gml +++ b/objects/o_main/Create_0.gml @@ -137,8 +137,8 @@ if(!is_array(path)) path = [ path ]; if(array_length(path) == 0) return; - _x = _x == undefined? (PANEL_GRAPH.w / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_x : _x; - _y = _y == undefined? (PANEL_GRAPH.h / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_y : _y; + _x = _x == undefined? PANEL_GRAPH.graph_cx : _x; + _y = _y == undefined? PANEL_GRAPH.graph_cy : _y; var type = "others"; diff --git a/objects/o_pie_menu/Create_0.gml b/objects/o_pie_menu/Create_0.gml index 02c907dbe..2539543b6 100644 --- a/objects/o_pie_menu/Create_0.gml +++ b/objects/o_pie_menu/Create_0.gml @@ -13,6 +13,10 @@ active = true; anim_prog = 0; + mouse_tx = mouse_mx; + mouse_ty = mouse_my; + mouse_ta = 0.5; + function setMenu(menu) { menus = menu; } diff --git a/objects/o_pie_menu/Draw_64.gml b/objects/o_pie_menu/Draw_64.gml index 391e98811..9c5122b13 100644 --- a/objects/o_pie_menu/Draw_64.gml +++ b/objects/o_pie_menu/Draw_64.gml @@ -12,14 +12,27 @@ var amo = array_length(menus); var _r = 360 / amo; + draw_set_color(COLORS._main_icon); + draw_set_alpha(mouse_ta); + draw_line_round(x, y, mouse_tx, mouse_ty, 4); + draw_set_alpha(1); + + mouse_tx = mouse_mx; + mouse_ty = mouse_my; + mouse_ta = 0.3; + + var _sel = point_distance(x, y, mouse_mx, mouse_my) > rad; + var _ang = point_direction(x, y, mouse_mx, mouse_my); + for( var i = 0; i < amo; i++ ) { var _menuItem = menus[i]; var label = _menuItem.name; var _ba = i * _r; - var _bx = x + lengthdir_x(rad, _ba); - var _by = y + lengthdir_y(rad, _ba); + var _dff = clamp((_r - abs(angle_difference(_ang, _ba))) / (_r), 0., 1.); + var _bx = x + lengthdir_x(rad + _dff * 16, _ba); + var _by = y + lengthdir_y(rad + _dff * 16, _ba); var _spr = _menuItem.spr; @@ -35,7 +48,13 @@ draw_sprite_stretched(THEME.menu_bg, 0, _bx0, _by0, _spw, _sph); - if(point_in_rectangle(mouse_mx, mouse_my, _bx0, _by0, _bx1, _by1)) { + var _hov = _sel && abs(angle_difference(_ang, _ba)) < _r / 2; + + if(_hov/*point_in_rectangle(mouse_mx, mouse_my, _bx0, _by0, _bx1, _by1)*/) { + mouse_tx = _bx; + mouse_ty = _by; + mouse_ta = 1; + draw_sprite_stretched_ext(THEME.textbox, 3, _bx0, _by0, _spw, _sph, COLORS.dialog_menubox_highlight, 0.75); if(mouse_release(mb_left)) { var _dat = { @@ -68,7 +87,7 @@ var tx = _bx0 + ui(16) + (_spr != noone) * ui(32); var aa = _menuItem.active * 0.75 + 0.25; - draw_set_text(f_p0, fa_left, fa_center, COLORS._main_text); + draw_set_text(f_p0, fa_left, fa_center, _hov? COLORS._main_text_accent : COLORS._main_text); draw_set_alpha(aa * anim_prog); draw_text(tx, _by0 + _sph / 2, label); draw_set_alpha(1); diff --git a/scripts/buttonPalette/buttonPalette.gml b/scripts/buttonPalette/buttonPalette.gml index 636e0519d..206527c32 100644 --- a/scripts/buttonPalette/buttonPalette.gml +++ b/scripts/buttonPalette/buttonPalette.gml @@ -138,8 +138,9 @@ function drawPaletteGrid(_pal, _x, _y, _w, _gs = 24, c_color = -1) { #region var amo = array_length(_pal); var col = floor(_w / _gs); var row = ceil(amo / col); - var cx = -1, cy = -1; + var cx = -1, cy = -1; var _pd = ui(5); + var _h = row * _gs; for(var i = 0; i < array_length(_pal); i++) { draw_set_color(_pal[i]); @@ -148,13 +149,14 @@ function drawPaletteGrid(_pal, _x, _y, _w, _gs = 24, c_color = -1) { #region draw_rectangle(_x0, _y0 + 1, _x0 + _gs, _y0 + _gs, false); - if(color_diff(c_color, _pal[i]) <= 0) { + if(c_color >= 0 && color_diff(c_color, _pal[i]) <= 0) { cx = _x0; cy = _y0; } } - if(cx == -1) return; + if(cx == -1) return _h; draw_sprite_stretched_ext(THEME.palette_selecting, 0, cx - _pd, cy + 1 - _pd, _gs + _pd * 2, _gs + _pd * 2); + return _h; } #endregion \ No newline at end of file diff --git a/scripts/node_cross_section/node_cross_section.gml b/scripts/node_cross_section/node_cross_section.gml new file mode 100644 index 000000000..a1c0414fd --- /dev/null +++ b/scripts/node_cross_section/node_cross_section.gml @@ -0,0 +1,21 @@ +function Node_Cross_Section(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Cross Section"; + + inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone ); + + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone ); + + input_display_list = [ + ["Surfaces", false], 0, + ]; + + attribute_surface_depth(); + + static processData = function(_outSurf, _data, _output_index, _array_index) { + var _surf = _data[0]; + + + + return _outSurf; + } +} \ No newline at end of file diff --git a/scripts/node_cross_section/node_cross_section.yy b/scripts/node_cross_section/node_cross_section.yy new file mode 100644 index 000000000..8711ebe3f --- /dev/null +++ b/scripts/node_cross_section/node_cross_section.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_cross_section", + "isCompatibility":false, + "isDnD":false, + "name":"node_cross_section", + "parent":{ + "name":"generator", + "path":"folders/nodes/data/generator.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/panel_color/panel_color.gml b/scripts/panel_color/panel_color.gml index ea8ee0583..63e47441c 100644 --- a/scripts/panel_color/panel_color.gml +++ b/scripts/panel_color/panel_color.gml @@ -103,12 +103,14 @@ function Panel_Color() : PanelContent() constructor { } if(show_hex) { - var alp_w = w - ui(padding * 2); var alp_h = ui(20); + var alp_w = w - ui(padding * 2) - alp_h - ui(padding); - var alp_x = ui(padding); + var alp_x = alp_h + ui(padding * 2); var alp_y = _y1 - alp_h; + draw_sprite_stretched_ext(s_ui_base_white, 0, ui(padding), alp_y, alp_h, alp_h, CURRENT_COLOR, show_alpha); + hex_tb.setFocusHover(pFOCUS, pHOVER); hex_tb.setFont(f_p2); diff --git a/scripts/panel_file_explorer/panel_file_explorer.gml b/scripts/panel_file_explorer/panel_file_explorer.gml index 36b02d75c..5c507dca7 100644 --- a/scripts/panel_file_explorer/panel_file_explorer.gml +++ b/scripts/panel_file_explorer/panel_file_explorer.gml @@ -185,8 +185,9 @@ function Panel_File_Explorer() : PanelContent() constructor { tb_root = new textBox(TEXTBOX_INPUT.text, function(val) { setRoot(val); }); - file_selectings = []; - file_hovering = noone; + file_selectings = []; + file_hovering = noone; + context_hovering = noone; file_dragging = false; file_drag_mx = 0; @@ -202,20 +203,15 @@ function Panel_File_Explorer() : PanelContent() constructor { #region menu __menu_file_selecting = noone; + __menu_cnxt_selecting = noone; menu_file_image = [ menuItem("Add as node", function() { - var _graph_x = (PANEL_GRAPH.w / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_x; - var _graph_y = (PANEL_GRAPH.h / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_y; - - Node_create_Image_path(_graph_x, _graph_y, __menu_file_selecting.path); + Node_create_Image_path(PANEL_GRAPH.graph_cx, PANEL_GRAPH.graph_cy, __menu_file_selecting.path); }), menuItem("Add as canvas", function() { - var _graph_x = (PANEL_GRAPH.w / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_x; - var _graph_y = (PANEL_GRAPH.h / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_y; - - nodeBuild("Node_Canvas", _graph_x, _graph_y).loadImagePath(__menu_file_selecting.path); + nodeBuild("Node_Canvas", PANEL_GRAPH.graph_cx, PANEL_GRAPH.graph_cy).loadImagePath(__menu_file_selecting.path); }), menuItem("Copy path", function() { clipboard_set_text(__menu_file_selecting.path); }, THEME.copy), @@ -227,7 +223,34 @@ function Panel_File_Explorer() : PanelContent() constructor { menuItem("Copy path", function() { clipboard_set_text(__menu_file_selecting.path); }, THEME.copy), ]; - menu_general = [ menuItem("Refresh", function() { if(rootFile) rootFile.getContent() }), ]; + menu_general = [ + menuItem("New Canvas", function() { + var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); + dia.onModify = function (txt) { + var _s = surface_create(DEF_SURF_W, DEF_SURF_H); + surface_clear(_s); + surface_save(_s, txt); + surface_free(_s); + + nodeBuild("Node_Canvas", PANEL_GRAPH.graph_cx, PANEL_GRAPH.graph_cy).loadImagePath(txt); + __menu_cnxt_selecting.getContent(); + }; + dia.path = __menu_cnxt_selecting.path + "/"; + }, THEME.new_file), + + menuItem("New Folder", function() { + var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); + dia.name = "New Folder"; + dia.onModify = function (txt) { + directory_create(txt); + __menu_cnxt_selecting.getContent(); + }; + dia.path = __menu_cnxt_selecting.path + "/"; + }, THEME.folder), + + -1, + menuItem("Refresh", function() { if(rootFile) rootFile.getContent() }), + ]; #endregion function onFocusBegin() { PANEL_FILE = self; } @@ -237,13 +260,16 @@ function Panel_File_Explorer() : PanelContent() constructor { if(frame_dragging) file_selectings = []; - file_hovering = noone; - draggable = true; + file_hovering = noone; + context_hovering = noone; + draggable = true; var _h = drawDir(rootFile, 0, _y, contentPane.surface_w, _m); if(frame_dragging) draw_sprite_stretched_points_clamp(THEME.ui_selection, 0, frame_drag_mx, frame_drag_my, _m[0], _m[1], COLORS._main_accent); - + if(context_hovering == noone) + context_hovering = rootFile; + if(draggable && mouse_press(mb_left, pFOCUS)) { if(file_hovering == noone) { file_selectings = []; @@ -284,6 +310,8 @@ function Panel_File_Explorer() : PanelContent() constructor { if(mouse_release(mb_left)) frame_dragging = false; if(pFOCUS && mouse_press(mb_right)) { + __menu_cnxt_selecting = context_hovering; + if(file_hovering == noone || is_instanceof(file_hovering, ExpDir)) menuCall("",,, menu_general); } @@ -329,11 +357,18 @@ function Panel_File_Explorer() : PanelContent() constructor { file_dragging = false; path_dragging = -1; - } else if(key_mod_press(CTRL)) { + } else if(keyboard_check_pressed(vk_control)) { + __menu_file_selecting = file_selectings[0]; - pieMenuCall("", mouse_mx, mouse_my, [ + if(path_is_image(__menu_file_selecting.path)) + pieMenuCall("",,, menu_file_image); - ]); + else if(path_is_project(__menu_file_selecting.path)) + pieMenuCall("",,, menu_file_project); + + file_dragging = false; + path_dragging = -1; + } } @@ -358,8 +393,8 @@ function Panel_File_Explorer() : PanelContent() constructor { draw_set_text(f_p2, fa_left, fa_top, COLORS._main_text); var _ith = line_get_height() + ui(4); - var _graph_x = (PANEL_GRAPH.w / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_x; - var _graph_y = (PANEL_GRAPH.h / 2) / PANEL_GRAPH.graph_s - PANEL_GRAPH.graph_y; + var _graph_x = PANEL_GRAPH.graph_cx; + var _graph_y = PANEL_GRAPH.graph_cy; for (var i = 0, n = array_length(dirObject.directories); i < n; i++) { draw_set_text(f_p2, fa_left, fa_top, COLORS._main_text); @@ -523,12 +558,11 @@ function Panel_File_Explorer() : PanelContent() constructor { var _title_heigh = ui(24); draw_set_text(f_p3, fa_center, fa_bottom, COLORS._main_text); + var _amo = array_length(dirObject.files); var _col = floor(_w / (_grid_width + _grid_spac)); _grid_width = (_w - (_col - 1) * _grid_spac) / _col; - for (var i = 0, n = array_length(dirObject.files); i < n; i++) { - var _fil = dirObject.files[i]; - + for (var i = 0; i < _amo; i++) { var _cind = i % _col; var _rind = floor(i / _col); @@ -537,6 +571,12 @@ function Panel_File_Explorer() : PanelContent() constructor { var _pw = _grid_width; var _ph = _grid_height + _title_heigh; + // if(i == _amo - 1) { + // draw_sprite_ext(THEME.add, 0, _px + _grid_width / 2, _py + _grid_height / 2, 1, 1, 0, COLORS._main_value_positive, 1); + // continue; + // } + + var _fil = dirObject.files[i]; if(frame_dragging && rectangle_in_rectangle(_px, _py, _px + _pw, _py + _ph, frame_drag_mx, frame_drag_my, _m[0], _m[1])) array_push(file_selectings, _fil); @@ -591,10 +631,12 @@ function Panel_File_Explorer() : PanelContent() constructor { } - var n = array_length(dirObject.files); - _h += ceil(n / _col) * (_grid_height + _title_heigh + _grid_spac); + _h += ceil(_amo / _col) * (_grid_height + _title_heigh + _grid_spac); } + if(context_hovering == noone && pHOVER && point_in_rectangle(_m[0], _m[1], 0, _y, _w, _y + _h)) + context_hovering = dirObject; + return _h; } diff --git a/scripts/panel_function/panel_function.gml b/scripts/panel_function/panel_function.gml index a33285ec0..02f1b07f4 100644 --- a/scripts/panel_function/panel_function.gml +++ b/scripts/panel_function/panel_function.gml @@ -65,10 +65,11 @@ case "Panel_Node_Align" : return new Panel_Node_Align(); case "Panel_File_Explorer" : var p = (create || findPanel(name))? new Panel_File_Explorer() : PANEL_FILE; PANEL_FILE = p; return p; - case "Panel_Color" : return new Panel_Color(); - case "Panel_Palette" : return new Panel_Palette(); - case "Panel_Gradient" : return new Panel_Gradient(); - case "Panel_Console" : return new Panel_Console(); + case "Panel_Color" : return new Panel_Color(); + case "Panel_Palette" : return new Panel_Palette(); + case "Panel_Palette_Mixer" : return new Panel_Palette_Mixer(); + case "Panel_Gradient" : return new Panel_Gradient(); + case "Panel_Console" : return new Panel_Console(); } return noone; diff --git a/scripts/panel_graph/panel_graph.gml b/scripts/panel_graph/panel_graph.gml index 5871b5f80..e15827678 100644 --- a/scripts/panel_graph/panel_graph.gml +++ b/scripts/panel_graph/panel_graph.gml @@ -166,6 +166,11 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor { #endregion #region ---- position ---- + graph_x = 0; + graph_y = 0; + graph_cx = 0; + graph_cy = 0; + scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0 ]; graph_s = 1; graph_s_to = graph_s; @@ -1824,11 +1829,14 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor { context_frame_ey = context_frame_sy + 16; } #endregion - function drawContent(panel) { #region MAIN DRAW + function drawContent(panel) { #region ======================================= MAIN DRAW ======================================= if(!project.active) return; dragGraph(); + graph_cx = (w / 2) / graph_s - graph_x; + graph_cy = (h / 2) / graph_s - graph_y; + var context = getCurrentContext(); if(context != noone) title_raw += " > " + (context.renamed? context.display_name : context.name); diff --git a/scripts/panel_menu/panel_menu.gml b/scripts/panel_menu/panel_menu.gml index 599c5e777..9504017b7 100644 --- a/scripts/panel_menu/panel_menu.gml +++ b/scripts/panel_menu/panel_menu.gml @@ -224,6 +224,8 @@ function Panel_Menu() : PanelContent() constructor { menuItem(__txt("Color"), function() { panelAdd("Panel_Color", true) }, noone, ["", "Color Panel"], function() { return findPanel("Panel_Color") != noone; } ), menuItem(__txt("Palettes"), function() { panelAdd("Panel_Palette", true) }, noone, ["", "Palettes Panel"], function() { return findPanel("Panel_Palette") != noone; } ), menuItem(__txt("Gradients"), function() { panelAdd("Panel_Gradient", true) }, noone, ["", "Gradients Panel"], function() { return findPanel("Panel_Gradient") != noone; } ), + -1, + menuItem(__txt("Palette Mixer"), function() { panelAdd("Panel_Palette_Mixer", true) }, noone, ["", "Palette Mixer Panel"], function() { return findPanel("Panel_Palette_Mixer") != noone; } ), ]); } ).setIsShelf(), ]], diff --git a/scripts/panel_palette_mixer/panel_palette_mixer.gml b/scripts/panel_palette_mixer/panel_palette_mixer.gml new file mode 100644 index 000000000..cef6edb18 --- /dev/null +++ b/scripts/panel_palette_mixer/panel_palette_mixer.gml @@ -0,0 +1,423 @@ +function Panel_Palette_Mixer() : PanelContent() constructor { + title = __txt("Palettes Mixer"); + padding = ui(8); + auto_pin = true; + + w = ui(320); + h = ui(400); + + content = surface_create(1, 1); + var _def = load_palette_mixer(); + palette_data = _def != noone? _def : { + nodes: [ + { color : cola(c_black), x : -64, y : 0 }, + { color : cola(c_white), x : 64, y : 0 }, + ], + connections: [ + [ 0, 1 ], + ], + }; + + palette = []; + + var _mx = 0, _my = 0; + for (var i = 0, n = array_length(palette_data.nodes); i < n; i++) { + var _node = palette_data.nodes[i]; + _mx += _node.x; + _my += _node.y; + } + + mixer_x = n? -_mx / n : 0; + mixer_y = n? -_my / n : 0; + mixer_s = 1; + + mixer_dragging = false; + mixer_drag_mx = 0; + mixer_drag_my = 0; + mixer_drag_sx = 0; + mixer_drag_sy = 0; + + node_size = ui(PREFERENCES.panel_menu_palette_node_size); + node_hovering = noone; + node_dragging = noone; + node_drag_mx = 0; + node_drag_my = 0; + node_drag_sx = 0; + node_drag_sy = 0; + node_selecting = noone; + + conn_hovering = noone; + connection_drag = noone; + + pr_palette = ds_priority_create(); + + function setColor(clr) { + if(node_selecting == noone) return; + node_selecting.color = clr; + CURRENT_COLOR = clr; + } + + function drawContent(panel) { + draw_clear_alpha(COLORS.panel_bg_clear, 0); + + var _palettes = palette_data.nodes; + var _connections = palette_data.connections; + + #region palette + var pal_s = ui(16); + var pal_w = w - padding - padding; + + var col = floor(pal_w / pal_s); + var row = ceil(array_length(_palettes) / col); + + var pal_h = pal_s * row; + var pal_x = padding; + var pal_y = h - padding - pal_h; + + draw_sprite_stretched(THEME.button_def, 0, pal_x - ui(8), pal_y - ui(8), pal_w + ui(16), pal_h + ui(16)); + + ds_priority_clear(pr_palette); + for (var i = 0, n = array_length(_palettes); i < n; i++) + ds_priority_add(pr_palette, _palettes[i], _palettes[i].y * 10000 + _palettes[i].x); + + palette = []; + for (var i = 0, n = array_length(_palettes); i < n; i++) { + var pal = ds_priority_delete_min(pr_palette); + palette[i] = pal.color; + } + + var _pw = pal_s; + var _ph = pal_s; + var amo = array_length(palette); + var col = floor(pal_w / _pw); + var row = ceil(amo / col); + var cx = -1, cy = -1; + var _pd = ui(5); + var _h = row * _ph; + _pw = pal_w / col; + + for(var i = 0; i < array_length(palette); i++) { + draw_set_color(palette[i]); + var _x0 = pal_x + safe_mod(i, col) * _pw; + var _y0 = pal_y + floor(i / col) * _ph; + + draw_rectangle(_x0, _y0 + 1, _x0 + _pw, _y0 + _ph, false); + + if(node_selecting) { + if(color_diff(node_selecting.color, palette[i]) < 0.01) { + cx = _x0; cy = _y0; + } + + } else if(color_diff(CURRENT_COLOR, palette[i]) < 0.01) { + cx = _x0; cy = _y0; + } + + if(pHOVER && point_in_rectangle(mx, my, _x0, _y0 + 1, _x0 + _pw, _y0 + _ph)) { + if(mouse_press(mb_left)) { + node_selecting = noone; + CURRENT_COLOR = palette[i]; + + DRAGGING = { + type: "Color", + data: palette[i] + } + MESSAGE = DRAGGING; + } + } + } + + if(cx) draw_sprite_stretched_ext(THEME.palette_selecting, 0, cx - _pd, cy + 1 - _pd, _pw + _pd * 2, _ph + _pd * 2); + #endregion + + var px = padding; + var py = padding; + var pw = w - padding - padding; + var ph = h - padding - padding - pal_h - ui(16); + if(in_dialog) ph -= ui(4); + + draw_sprite_stretched(THEME.ui_panel_bg, 1, px - ui(8), py - ui(8), pw + ui(16), ph + ui(16)); + + content = surface_verify(content, pw, ph); + + var _mx_x = pw / 2 + mixer_x; + var _mx_y = ph / 2 + mixer_y; + + var _msx = (mx - px); + var _msy = (my - py); + + var _mmx = mx - px - _mx_x; + var _mmy = my - py - _mx_y; + + #region draw mixer + surface_set_target(content) + DRAW_CLEAR + + var _gs = node_size; + var _gs2 = _gs / 2; + var _ind = noone; + var _hov = node_hovering; + var _con_hover = conn_hovering; + var _con_rat = 0; + var _pHover = pHOVER && point_in_rectangle(mx, my, px, py, px + pw, py + ph); + + node_hovering = noone; + conn_hovering = noone; + + for (var i = 0, n = array_length(_connections); i < n; i++) { + var conn = _connections[i]; + + var _fr = _palettes[conn[0]]; + var _to = _palettes[conn[1]]; + + var _frx = round(_mx_x + _fr.x); + var _fry = round(_mx_y + _fr.y); + var _tox = round(_mx_x + _to.x); + var _toy = round(_mx_y + _to.y); + + var _hv = _hov == noone && _con_hover == i; + draw_line_width_color(_frx, _fry, _tox, _toy, _hv? 8 : 4, _fr.color, _to.color); + + if(distance_to_line(_msx, _msy, _frx, _fry, _tox, _toy) < 6) { + conn_hovering = i; + + var _d0 = point_distance(_frx, _fry, _msx, _msy); + var _d1 = point_distance(_tox, _toy, _msx, _msy); + _con_rat = _d0 / (_d0 + _d1); + } + } + + if(connection_drag >= 0) { + var _fr = _palettes[connection_drag]; + + var _frx = round(_mx_x + _fr.x); + var _fry = round(_mx_y + _fr.y); + + if(_hov) { + var _tox = round(_mx_x + _hov.x); + var _toy = round(_mx_y + _hov.y); + draw_line_width_color(_frx, _fry, _tox, _toy, 8, _fr.color, _hov.color); + + } else + draw_line_width_color(_frx, _fry, _msx, _msy, 8, _fr.color, _fr.color); + } + + for (var i = 0, n = array_length(_palettes); i < n; i++) { + var pal = _palettes[i]; + + var _c = pal.color; + var _px = round(_mx_x + pal.x); + var _py = round(_mx_y + pal.y); + var _hv = _pHover && point_in_rectangle(_msx, _msy, _px - _gs2, _py - _gs2, _px + _gs2, _py + _gs2); + + draw_sprite_stretched(THEME.button_def, _hov == pal, _px - _gs2, _py - _gs2, _gs, _gs); + draw_sprite_stretched_ext(THEME.menu_button_mask, 0, _px - _gs2 + 2, _py - _gs2 + 2, _gs - 4, _gs - 4, _c, 1); + + BLEND_ADD + draw_sprite_stretched_ext(THEME.button_def, 3, _px - _gs2 + 2, _py - _gs2 + 2, _gs - 4, _gs - 4, c_white, 0.25); + BLEND_NORMAL + + if(pal == node_selecting) + draw_sprite_stretched_ext(THEME.button_def, 3, _px - _gs2, _py - _gs2, _gs, _gs, COLORS._main_accent, 1); + + if(_hv) { + node_hovering = pal; + _ind = i; + } + } + + if(node_hovering) { + if(mouse_press(mb_left)) { + node_selecting = node_hovering; + node_dragging = node_hovering; + node_drag_mx = mx; + node_drag_my = my; + node_drag_sx = node_hovering.x; + node_drag_sy = node_hovering.y; + + CURRENT_COLOR = node_hovering.color; + } + + if(DOUBLE_CLICK) { + node_selecting = node_hovering; + + var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2); + dialog.selector.onApply = setColor; + dialog.onApply = setColor; + dialog.setDefault(node_selecting.color); + + save_palette_mixer(palette_data); + } + + if(mouse_press(mb_right)) + connection_drag = _ind; + + } else if(conn_hovering != noone) { + + if(DOUBLE_CLICK) { + var conn = palette_data.connections[conn_hovering]; + var _fr = _palettes[conn[0]]; + var _to = _palettes[conn[1]]; + + var _cc = merge_color(_fr.color, _to.color, _con_rat); + var _node = { + color : _cc, + x : lerp(_fr.x, _to.x, _con_rat), + y : lerp(_fr.y, _to.y, _con_rat) + }; + + var _idx = array_length(palette_data.nodes); + array_push(palette_data.nodes, _node); + + array_delete(palette_data.connections, conn_hovering, 1); + array_push( palette_data.connections, [ conn[0], _idx ]); + array_push( palette_data.connections, [ _idx, conn[1] ]); + + node_selecting = _node; + + save_palette_mixer(palette_data); + } + + } else { + if(_pHover && mouse_press(mb_left)) + node_selecting = noone; + + if(_pHover && DOUBLE_CLICK) { + var _node = { color : cola(c_black), x : value_snap(_mmx, 8), y : value_snap(_mmy, 8) }; + array_push(palette_data.nodes, _node); + node_selecting = _node; + + var dialog = dialogCall(o_dialog_color_selector, WIN_W / 2, WIN_H / 2); + dialog.selector.onApply = setColor; + dialog.onApply = setColor; + dialog.setDefault(node_selecting.color); + + save_palette_mixer(palette_data); + } + } + + if(connection_drag >= 0) { + if(mouse_release(mb_right)) { + if(_ind == noone) { + var _pal = _palettes[connection_drag]; + var _node = { color : _pal.color, x : value_snap(_mmx, 8), y : value_snap(_mmy, 8) }; + array_push(palette_data.nodes, _node); + + var _conn = [ connection_drag, array_length(palette_data.nodes) - 1 ]; + array_push(palette_data.connections, _conn); + + } else { + var _exist = noone; + var _conn = [ connection_drag, _ind ]; + + for (var i = 0, n = array_length(_connections); i < n; i++) { + var conn = _connections[i]; + if(array_equals(_conn, conn) || array_equals(_conn, [ conn[1], conn[0] ])) + _exist = i; + } + + if(_exist == noone) array_push(palette_data.connections, _conn); + else array_delete(palette_data.connections, _exist, 1); + + save_palette_mixer(palette_data); + } + + connection_drag = noone; + } + } + + if(node_dragging) { + node_dragging.x = value_snap(node_drag_sx + (mx - node_drag_mx), 8); + node_dragging.y = value_snap(node_drag_sy + (my - node_drag_my), 8); + + if(mouse_release(mb_left)) { + node_dragging = false; + save_palette_mixer(palette_data); + } + } + + if(node_selecting) { + node_selecting.color = CURRENT_COLOR; + + if(keyboard_check_pressed(vk_delete)) { + var _delId = array_find(_palettes, node_selecting); + + array_delete(_palettes, _delId, 1); + + for (var i = array_length(_connections) - 1; i >= 0; i--) { + var conn = _connections[i]; + + if(conn[0] == _delId || conn[1] == _delId) + array_delete(palette_data.connections, i, 1); + else { + if(conn[0] > _delId) palette_data.connections[i][0]--; + if(conn[1] > _delId) palette_data.connections[i][1]--; + } + } + + save_palette_mixer(palette_data); + } + } + + if(_pHover && DRAGGING && DRAGGING.type == "Color") { + if(mouse_release(mb_left)) { + var _node = { color : DRAGGING.data, x : value_snap(_mmx, 8), y : value_snap(_mmy, 8) }; + array_push(palette_data.nodes, _node); + + DRAGGING = noone; + + save_palette_mixer(palette_data); + } + } + surface_reset_target(); + #endregion + + draw_surface(content, px, py); + + if(_pHover && mouse_press(mb_middle)) { + mixer_dragging = true; + mixer_drag_mx = mx; + mixer_drag_my = my; + mixer_drag_sx = mixer_x; + mixer_drag_sy = mixer_y; + } + + if(mixer_dragging) { + mixer_x = round(mixer_drag_sx + (mx - mixer_drag_mx)); + mixer_y = round(mixer_drag_sy + (my - mixer_drag_my)); + + if(mouse_release(mb_middle)) + mixer_dragging = false; + } + + draw_set_text(f_p2, fa_right, fa_bottom, COLORS._main_text_sub); + if(node_hovering) + draw_text(px + pw, py + ph + ui(4), $"Node #{color_get_hex(node_hovering.color)}"); + + else if(conn_hovering >= 0) { + var conn = palette_data.connections[conn_hovering]; + var _fr = _palettes[conn[0]]; + var _to = _palettes[conn[1]]; + + draw_text(px + pw, py + ph + ui(4), $"Connection #{color_get_hex(_fr.color)} - #{color_get_hex(_to.color)} [{round(_con_rat * 100)}%]"); + } + } +} + +function save_palette_mixer(data) { + var _dirr = $"{DIRECTORY}/Palettes/Mixer"; + directory_verify(_dirr); + + var _path = _dirr + "/current.json"; + + json_save_struct(_path, data); +} + +function load_palette_mixer() { + var _dirr = $"{DIRECTORY}/Palettes/Mixer"; + directory_verify(_dirr); + + var _path = _dirr + "/current.json"; + if(!file_exists(_path)) return noone; + + return json_load_struct(_path); +} \ No newline at end of file diff --git a/scripts/panel_palette_mixer/panel_palette_mixer.yy b/scripts/panel_palette_mixer/panel_palette_mixer.yy new file mode 100644 index 000000000..a6eeebd7f --- /dev/null +++ b/scripts/panel_palette_mixer/panel_palette_mixer.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"panel_palette_mixer", + "isCompatibility":false, + "isDnD":false, + "name":"panel_palette_mixer", + "parent":{ + "name":"colors", + "path":"folders/panels/colors.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/preferences/preferences.gml b/scripts/preferences/preferences.gml index 866268af3..8b0717368 100644 --- a/scripts/preferences/preferences.gml +++ b/scripts/preferences/preferences.gml @@ -76,6 +76,8 @@ PREFERENCES.panel_menu_resource_monitor = false; PREFERENCES.panel_menu_right_control = os_type == os_windows; + PREFERENCES.panel_menu_palette_node_size = 20; + PREFERENCES.inspector_focus_on_double_click = true; PREFERENCES.inspector_view_default = 1;