group ungroup undo

This commit is contained in:
Tanasart 2024-05-22 17:13:46 +07:00
parent 03ad6142d0
commit dcc07ba19e
11 changed files with 137 additions and 53 deletions

View file

@ -77,10 +77,20 @@ function log_clear() { #region
file_delete(path);
} #endregion
function os_type_sting() {
switch(os_type) {
case os_windows : return "Windows";
case os_macosx : return "MacOS";
case os_linux : return "Linux";
}
return "undefined";
}
function exception_print(e) { #region
if(!is_struct(e) || !struct_has(e, "longMessage")) return string(e);
var str = "\n\n========== Crash log ==========\n\n" + e.longMessage;
var str = $"\n\n========== Crash log [PXC {VERSION_STRING}] [{os_type_sting()}] ==========\n\n" + e.longMessage;
str += "\n\n========== Stack trace ==========\n\n";
for( var i = 0, n = array_length(e.stacktrace); i < n; i++ )
@ -99,13 +109,16 @@ function setException() { #region
if(!SAVING && !TESTING && !IS_CMD) SAVE_AT(PROJECT, path);
var tt = "";
tt += "\n-------------------------- OH NO --------------------------\n\n";
tt += $"\n-------------------------- Pixel Composer {VERSION_STRING} Crashed --------------------------\n";
tt += "\n" + ex.longMessage;
tt += "\n" + ex.script;
tt += "\n-------------------------- STACK TRACE --------------------------\n\n";
tt += "\n\n-------------------------- STACK TRACE --------------------------\n\n";
for( var i = 0, n = array_length(ex.stacktrace); i < n; i++ )
tt += ex.stacktrace[i] + "\n";
tt += "\n---------------------------- :( ----------------------------\n";
tt += "\n\n\n\n-------------------------- Device Info --------------------------\n";
tt += $"\nVersion: {VERSION_STRING} ({VERSION})";
tt += $"\nOperating system: {os_type_sting()} ({os_version})"
tt += "\n\n---------------------------- :( ----------------------------\n";
var path = $"{env_user()}crash_log.txt";

View file

@ -108,7 +108,29 @@ function Action(_type, _object, _data, _trigger = 0) constructor {
case ACTION_TYPE.ungroup :
obj.restore();
groupNodes(data.content, obj, false);
groupNodes(data.content, obj, false, false);
for (var i = 0, n = array_length(data.deleted); i < n; i++) {
var _dl = data.deleted[i];
var _nd = _dl.node;
var _vt = _dl.value_to;
_nd.enable();
for (var j = 0, m = ds_list_size(_nd.outputs); j < m; j++) {
var _out = _nd.outputs[| j];
var _too = _vt[j];
for (var k = 0, p = array_length(_too); k < p; k++)
_too[k].setFrom(_out);
}
}
var _connectTo = data.connectTo;
for (var i = 0, n = array_length(_connectTo); i < n; i++)
for (var j = 0, m = array_length(_connectTo[i]); j < m; j++)
_connectTo[i][j].setFrom(obj.outputs[| i]);
break;
case ACTION_TYPE.collection_loaded :

View file

@ -51,9 +51,9 @@ function groupNodes(nodeArray, _group = noone, record = true, check_connect = tr
_content[i] = _ctx_nodes[i];
}
var _io = { inputs: {}, outputs: {}, map: {} };
if(check_connect) { #region IO creation
var _io = { inputs: {}, outputs: {}, map: {} };
for(var i = 0; i < array_length(nodeArray); i++)
nodeArray[i].checkConnectGroup(_io);
@ -119,22 +119,53 @@ function groupNodes(nodeArray, _group = noone, record = true, check_connect = tr
} #endregion
function upgroupNode(collection, record = true) { #region
UNDO_HOLDING = true;
var _content = [];
UNDO_HOLDING = true;
var _content = [], _deleted = [];
var node_list = collection.getNodeList();
var _node_arr = ds_list_to_array(node_list);
var _conn_to = collection.getJunctionTos();
while(!ds_list_empty(node_list)) {
var remNode = node_list[| 0];
if(!remNode.destroy_when_upgroup)
var _cx = 0, _cy = 0;
var _nn = 0;
for (var i = 0, n = array_length(_node_arr); i < n; i++) {
var _node = _node_arr[i];
if(!_node.selectable) continue;
_cx += _node.x;
_cy += _node.y;
_nn++;
}
if(_nn) {
_cx = collection.x - _cx / _nn;
_cy = collection.y - _cy / _nn;
}
for (var i = 0, n = array_length(_node_arr); i < n; i++) {
var remNode = _node_arr[i];
remNode.x += _cx;
remNode.y += _cy;
if(remNode.destroy_when_upgroup) {
var _vto = remNode.getJunctionTos();
array_push(_deleted, { node: remNode, value_to : _vto });
} else
array_push(_content, remNode);
collection.remove(remNode);
}
collection.destroy();
UNDO_HOLDING = false;
if(record) recordAction(ACTION_TYPE.ungroup, collection, { content: _content });
if(!record) return;
recordAction(ACTION_TYPE.ungroup, collection, {
content : _content,
deleted : _deleted,
connectTo : _conn_to,
});
} #endregion
function Node_Collection(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
@ -383,21 +414,23 @@ function Node_Collection(_x, _y, _group = noone) : Node(_x, _y, _group) construc
} #endregion
static remove = function(_node) { #region
var node_list = getNodeList();
var _pos = ds_list_find_index(node_list, _node);
ds_list_delete(node_list, _pos);
var list = group == noone? PANEL_GRAPH.nodes_list : group.getNodeList();
ds_list_add(list, _node);
var _hide = _node.destroy_when_upgroup;
if(!_hide) {
var node_list = getNodeList();
var list = group == noone? PANEL_GRAPH.nodes_list : group.getNodeList();
ds_list_remove(node_list, _node);
ds_list_add(list, _node);
}
recordAction(ACTION_TYPE.group_removed, self, _node);
if(struct_has(_node, "ungroup"))
_node.ungroup();
if(struct_has(_node, "onUngroup"))
_node.onUngroup();
if(_node.destroy_when_upgroup)
_node.destroy();
else
_node.group = group;
if(_hide) _node.disable();
else _node.group = group;
will_refresh = true;
node_length = ds_list_size(nodes);

View file

@ -2004,6 +2004,15 @@ function Node(_x, _y, _group = noone) : __Node_Base(_x, _y) constructor {
static drawTools = function(_mx, _my, xx, yy, tool_size, hover, focus) { return 0; }
static getJunctionTos = function() { #region
var _vto = array_create(ds_list_size(outputs));
for (var j = 0, m = ds_list_size(outputs); j < m; j++)
_vto[j] = array_clone(outputs[| j].value_to);
return _vto;
} #endregion
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static serialize = function(scale = false, preset = false) { #region >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SERIALIZE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if(!active) return;

View file

@ -375,7 +375,7 @@ function Node_Group_Input(_x, _y, _group = noone) : Node(_x, _y, _group) constru
group.refreshNodes();
} #endregion
static ungroup = function() { #region
static onUngroup = function() { #region
var fr = inParent.value_from;
for( var i = 0; i < array_length(outputs[| 0].value_to); i++ ) {

View file

@ -122,7 +122,7 @@ function Node_Group_Output(_x, _y, _group = noone) : Node(_x, _y, _group) constr
group.refreshNodes();
} #endregion
static ungroup = function() { #region
static onUngroup = function() { #region
var fr = inputs[| 0].value_from;
for( var i = 0; i < array_length(outParent.value_to); i++ ) {

View file

@ -127,9 +127,9 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
} #endregion
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var sample = PREFERENCES.path_resolution;
var loop = getInputData(1);
var ansize = ds_list_size(inputs) - input_fix_len;
var sample = PREFERENCES.path_resolution;
var loop = getInputData(1);
var ansize = ds_list_size(inputs) - input_fix_len;
var _edited = false;
var pos = outputs[| 0].getValue();
@ -925,11 +925,15 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
var _a = [];
for(var i = input_fix_len; i < ds_list_size(inputs); i++) {
var _anc = array_clone(getInputData(i));
var _val = getInputData(i);
var _anc = array_create(7, 0);
for(var j = 0; j < 7; j++)
_anc[j] = array_safe_get(_val, j);
if(_rnd) {
_anc[0] = round(_anc[0]);
_anc[1] = round(_anc[1]);
_anc[0] = round(_val[0]);
_anc[1] = round(_val[1]);
}
array_push(_a, _anc);

View file

@ -969,7 +969,7 @@ function __initNodes() {
ds_list_add(node, "Groups");
addNodeObject(node, "Group", s_node_group, "Node_Group", [1, Node_Group]);
addNodeObject(node, "Feedback", s_node_feedback, "Node_Feedback", [1, Node_Feedback],, "Create a group that reuse output from last frame to the current one.");
addNodeObject(node, "Loop", s_node_loop, "Node_Iterate", [1, Node_Iterate], ["iterate", "for"], "Create group that reuse output as input repeatedly in one frame.");
addNodeObject(node, "Loop", s_node_loop, "Node_Iterate", [1, Node_Iterate], ["iterate", "for"], "Create group that reuse output as input repeatedly in one frame.").isDeprecated();
addNodeObject(node, "Loop Array", s_node_loop_array, "Node_Iterate_Each_Inline", [1, Node_Iterate_Each_Inline], ["iterate each", "for each", "array loop"], "Create group that iterate to each member in an array.");
addNodeObject(node, "Filter Array", s_node_filter_array, "Node_Iterate_Filter_Inline", [1, Node_Iterate_Filter_Inline],, "Filter array using condition.").setVersion(1140);

View file

@ -1,7 +1,7 @@
function Panel_History() : PanelContent() constructor {
title = __txt("History");
w = ui(400);
h = ui(480);
w = ui(400);
h = ui(480);
anchor = ANCHOR.left | ANCHOR.top;
hold = false;
@ -34,12 +34,10 @@ function Panel_History() : PanelContent() constructor {
refreshList();
onResize = function() {
PANEL_PADDING
sc_history.resize(w - ui(padding + padding), h - ui(title_height + padding));
sc_history.resize(w - padding * 2, h - padding * 2);
}
sc_history = new scrollPane(w - ui(padding + padding), h - ui(title_height + padding), function(_y, _m) {
sc_history = new scrollPane(w - padding * 2, h - padding * 2, function(_y, _m) {
draw_clear_alpha(COLORS._main_text, 0);
if((ds_list_size(redo_list) != ds_stack_size(REDO_STACK)) || (ds_list_size(undo_list) != ds_stack_size(UNDO_STACK)))
@ -153,10 +151,10 @@ function Panel_History() : PanelContent() constructor {
function drawContent(panel) {
draw_clear_alpha(COLORS.panel_bg_clear, 0);
var px = ui(padding);
var py = ui(padding);
var pw = w - ui(padding + padding);
var ph = h - ui(padding + padding);
var px = padding;
var py = padding;
var pw = w - padding * 2;
var ph = h - padding * 2;
draw_sprite_stretched(THEME.ui_panel_bg, 1, px - ui(8), py - ui(8), pw + ui(16), ph + ui(16));
sc_history.setFocusHover(pFOCUS, pHOVER);

View file

@ -119,9 +119,12 @@
function is_surface(s) { #region
INLINE
if(is_instanceof(s, dynaSurf) || is_instanceof(s, SurfaceAtlas)) return true;
if(is_numeric(s) && s > 0 && surface_exists(s)) return true;
return false;
return !is_array(s) && (
is_instanceof(s, dynaSurf) ||
is_instanceof(s, SurfaceAtlas) ||
(is_numeric(s) && s > 0 && surface_exists(s))
);
} #endregion
function surface_verify(surf, w, h, format = surface_rgba8unorm) { #region
@ -149,6 +152,7 @@
function surface_get_width_safe(s, crop = true) { #region
INLINE
if(!is_surface(s)) return 1;
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getWidth();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_width(s.getSurface()) : s.oriSurf_w;
@ -161,6 +165,7 @@
function surface_get_height_safe(s, crop = true) { #region
INLINE
if(!is_surface(s)) return 1;
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getHeight();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_height(s.getSurface()) : s.oriSurf_h;