Pixel-Composer/scripts/node_align_functions/node_align_functions.gml
2024-12-13 19:23:06 +07:00

442 lines
No EOL
11 KiB
Text

function node_halign(nodeList, alignment = fa_center) {
var amo = array_length(nodeList);
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
switch(alignment) {
case fa_left:
var x0 = 999999;
for( var i = 0; i < amo; i++ )
x0 = min(x0, nodeList[i].x);
for( var i = 0; i < amo; i++ )
nodeList[i].x = x0;
break;
case fa_center:
var xc = 0;
for( var i = 0; i < amo; i++ )
xc += nodeList[i].x + nodeList[i].w / 2;
xc /= amo;
for( var i = 0; i < amo; i++ )
nodeList[i].x = xc - nodeList[i].w / 2;
break;
case fa_right:
var x0 = -999999;
for( var i = 0; i < amo; i++ )
x0 = max(x0, nodeList[i].x + nodeList[i].w);
for( var i = 0; i < amo; i++ )
nodeList[i].x = x0 - nodeList[i].w;
break;
}
}
function node_valign(nodeList, alignment = fa_middle) {
var amo = array_length(nodeList);
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
switch(alignment) {
case fa_top:
var y0 = 999999;
for( var i = 0; i < amo; i++ )
y0 = min(y0, nodeList[i].y);
for( var i = 0; i < amo; i++ )
nodeList[i].y = y0;
break;
case fa_middle:
var yc = 0;
for( var i = 0; i < amo; i++ )
yc += nodeList[i].y + nodeList[i].h / 2;
yc /= amo;
for( var i = 0; i < amo; i++ )
nodeList[i].y = yc - nodeList[i].h / 2;
break;
case fa_bottom:
var y0 = -999999;
for( var i = 0; i < amo; i++ )
y0 = max(y0, nodeList[i].y + nodeList[i].h);
for( var i = 0; i < amo; i++ )
nodeList[i].y = y0 - nodeList[i].h;
break;
}
}
function node_hdistribute(nodeList) {
var amo = array_length(nodeList);
var nodes = ds_priority_create();
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
var x0 = 999999;
var x1 = -999999;
for( var i = 0; i < amo; i++ ) {
var _x = nodeList[i].x + nodeList[i].w / 2;
x0 = min(x0, _x);
x1 = max(x1, _x);
ds_priority_add(nodes, nodeList[i], _x);
}
var sp = (x1 - x0) / (amo - 1);
for( var i = 0; i < amo; i++ ) {
var _node = ds_priority_delete_min(nodes);
_node.x = x0 + sp * i - _node.w / 2;
}
ds_priority_destroy(nodes);
}
function node_vdistribute(nodeList) {
var amo = array_length(nodeList);
var nodes = ds_priority_create();
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
var y0 = 999999;
var y1 = -999999;
for( var i = 0; i < amo; i++ ) {
var _y = nodeList[i].y + nodeList[i].h / 2;
y0 = min(y0, _y);
y1 = max(y1, _y);
ds_priority_add(nodes, nodeList[i], _y);
}
var sp = (y1 - y0) / (amo - 1);
for( var i = 0; i < amo; i++ ) {
var _node = ds_priority_delete_min(nodes);
_node.y = y0 + sp * i - _node.h / 2;
}
ds_priority_destroy(nodes);
}
function node_hdistribute_dist(nodeList, anchor = noone, distance = 0) {
var amo = array_length(nodeList);
var nodes = ds_priority_create();
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
var x0 = 999999;
var x1 = -999999;
for( var i = 0; i < amo; i++ ) {
var _x = nodeList[i].x + nodeList[i].w / 2;
x0 = min(x0, _x);
x1 = max(x1, _x);
ds_priority_add(nodes, nodeList[i], _x);
}
var ar = array_create(ds_priority_size(nodes));
for( var i = 0; i < amo; i++ )
ar[i] = ds_priority_delete_min(nodes);
ds_priority_destroy(nodes);
if(anchor == noone) anchor = ar[0];
var an_ind = array_find(ar, anchor);
var an_ind_x = anchor.x + anchor.w + distance;
for (var i = an_ind + 1, n = array_length(ar); i < n; i++) {
ar[i].x = an_ind_x;
an_ind_x += ar[i].w + distance;
}
var an_ind_x = anchor.x - distance;
for (var i = an_ind - 1; i >= 0; i--) {
ar[i].x = an_ind_x - ar[i].w;
an_ind_x -= ar[i].w + distance;
}
}
function node_vdistribute_dist(nodeList, anchor = noone, distance = 0) {
var amo = array_length(nodeList);
var nodes = ds_priority_create();
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
var y0 = 999999;
var y1 = -999999;
for( var i = 0; i < amo; i++ ) {
var _y = nodeList[i].y + nodeList[i].h / 2;
y0 = min(y0, _y);
y1 = max(y1, _y);
ds_priority_add(nodes, nodeList[i], _y);
}
var ar = array_create(ds_priority_size(nodes));
for( var i = 0; i < amo; i++ )
ar[i] = ds_priority_delete_min(nodes);
ds_priority_destroy(nodes);
if(anchor == noone) anchor = ar[0];
var an_ind = array_find(ar, anchor);
var an_ind_y = anchor.y + anchor.h + distance;
for (var i = an_ind + 1, n = array_length(ar); i < n; i++) {
ar[i].y = an_ind_y;
an_ind_y += ar[i].h + distance;
}
var an_ind_y = anchor.y - distance;
for (var i = an_ind - 1; i >= 0; i--) {
ar[i].y = an_ind_y - ar[i].h;
an_ind_y -= ar[i].h + distance;
}
}
function node_auto_align(nodeList) {
var h_avg = 0, h_var = 0;
var v_avg = 0, v_var = 0;
var amo = array_length(nodeList);
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
for( var i = 0; i < amo; i++ ) {
var _n = nodeList[i];
var _x = _n.x;
var _y = _n.y;
h_avg += _x;
v_avg += _y;
}
h_avg /= amo;
v_avg /= amo;
for( var i = 0; i < amo; i++ ) {
var _n = nodeList[i];
h_var += sqr(_n.x - h_avg);
v_var += sqr(_n.y - v_avg);
}
if(h_var < v_var) { node_halign(nodeList); node_vdistribute(nodeList); }
else if(v_var < h_var) { node_valign(nodeList); node_hdistribute(nodeList); }
}
function node_snap_grid(nodeList, spacing = 16) {
var amo = array_length(nodeList);
for( var i = 0; i < amo; i++ ) {
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].x, "x", "node x position" ]);
recordAction(ACTION_TYPE.var_modify, nodeList[i], [ nodeList[i].y, "y", "node y position" ]);
}
for (var i = 0, n = array_length(nodeList); i < n; i++) {
var _node = nodeList[i];
_node.x = value_snap(_node.x, spacing);
_node.y = value_snap(_node.y, spacing);
}
}
////- Auto organize
function node_auto_organize_parameter() constructor {
padd_w = 32;
padd_h = 16;
snap = true;
snap_size = 16;
}
function __node_auto_organize_graph(node) {
var children = [];
var froms = node.getNodeFrom();
node.__organize_sorted = false;
for( var i = 0, n = array_length(froms); i < n; i++ )
children[i] = __node_auto_organize_graph(froms[i]);
return { node, children, w: 0, h: 0, depth: 0 };
}
function __node_auto_organize_size(node, param) {
if(array_empty(node.children)) {
if(node.node == noone) return node;
node.w = node.node.w;
node.h = node.node.h;
return node;
}
var tw = 0;
var th = 0;
for( var i = 0, n = array_length(node.children); i < n; i++ ) {
var _s = __node_auto_organize_size(node.children[i], param);
tw = max(tw, _s.node.w);
th += _s.h + param.padd_h * bool(i);
}
node.w = tw;
node.h = th;
return node;
}
function __node_auto_organize(node, param, _x = 0, _y = 0, _cap = false) {
var ch = [];
var tw = node.w;
var _sx = _x - tw - param.padd_w;
var _sy = _y;
if(param.snap) {
_sx = value_snap(_sx, param.snap_size);
_sy = value_snap(_sy, param.snap_size);
}
var miny = 0;
var maxy = 0;
for( var i = 0, n = array_length(node.children); i < n; i++ ) {
var _n = node.children[i];
__node_auto_organize(_n, param, _sx, _sy, _cap);
if(!_n.node.__organize_sorted) {
_n.node.x = _sx;
_n.node.y = _sy;
} else {
_n.node.x = min(_n.node.x, _sx);
_n.node.y = min(_n.node.y, _sy);
}
miny = i == 0? _n.node.y : min(miny, _n.node.y);
maxy = i == 0? _n.node.y + _n.node.h : max(maxy, _n.node.y + _n.node.h);
_n.node.__organize_sorted = true;
_sy += _n.h + param.padd_h;
if(param.snap) _sy = value_snap(_sy, param.snap_size);
}
if(_cap && node.node) miny = max(miny, node.node.y);
if(n) node.h = maxy - miny;
if(node.node) node.h = max(node.h, node.node.h);
}
function __node_bbox_recal(node, param) {
node.bbox = [ 0, 0, 0, 0 ];
node.h = 0;
if(node.node) node.node.__organize_sorted = false;
if(array_empty(node.children)) {
if(node.node == noone) return node;
node.bbox[0] = node.node.x;
node.bbox[1] = node.node.y;
node.bbox[2] = node.node.x + node.node.w;
node.bbox[3] = node.node.y + node.node.h;
node.h = node.bbox[3] - node.bbox[1];
return node;
}
for( var i = 0, n = array_length(node.children); i < n; i++ ) {
var _n = node.children[i];
__node_bbox_recal(_n, param);
node.bbox[0] = min(node.bbox[0], _n.bbox[0]);
node.bbox[1] = min(node.bbox[1], _n.bbox[1]);
node.bbox[2] = max(node.bbox[2], _n.bbox[2]);
node.bbox[3] = max(node.bbox[3], _n.bbox[3]);
}
if(node.node) node.bbox[1] = max(node.bbox[1], node.node.y);
node.h = node.bbox[3] - node.bbox[1];
return node;
}
function node_auto_organize(nodeList, param = new node_auto_organize_parameter()) {
if(array_empty(nodeList)) return;
var cx = 0, cy = 0;
for( var i = 0, n = array_length(nodeList); i < n; i++ ) {
var _n = nodeList[i];
cx += _n.x + _n.w / 2;
cy += _n.y + _n.h / 2;
}
cx /= n; cy /= n;
var root = { node: noone, children: [], w: 0, h: 0, depth: 0 };
for( var i = 0, n = array_length(nodeList); i < n; i++ ) {
var _n = nodeList[i];
var _nto = _n.getNodeTo();
var _isRoot = array_empty(_nto) || array_empty(array_union(_nto, nodeList));
if(_isRoot) array_push(root.children, __node_auto_organize_graph(_n));
}
array_sort(root.children, function(a, b) /*=>*/ {return a.node.y - b.node.y});
__node_auto_organize_size(root, param);
__node_auto_organize(root, param, 0, 0);
repeat(1) {
__node_bbox_recal(root, param);
__node_auto_organize(root, param, 0, 0, true);
}
var ncx = 0, ncy = 0;
for( var i = 0, n = array_length(nodeList); i < n; i++ ) {
var _n = nodeList[i];
ncx += _n.x + _n.w / 2;
ncy += _n.y + _n.h / 2;
}
ncx /= n; ncy /= n;
var dx = ncx - cx;
var dy = ncy - cy;
if(param.snap) {
dx = value_snap(dx, param.snap_size);
dy = value_snap(dy, param.snap_size);
}
for( var i = 0, n = array_length(nodeList); i < n; i++ ) {
var _n = nodeList[i];
_n.x = _n.x - dx;
_n.y = _n.y - dy;
}
PANEL_GRAPH.draw_refresh = true;
}