support sorting nodes inside subgraphs
This commit is contained in:
+22
-19
@@ -79,7 +79,7 @@ const autonodes_rightclickmenu = {
|
|||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
"content": "LiteGraph.js default layout",
|
"content": "LiteGraph.js default layout",
|
||||||
"callback": () => app.graph.arrange()
|
"callback": () => (app.canvas.graph || app.graph).arrange()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"content": "Dagre.js layout",
|
"content": "Dagre.js layout",
|
||||||
@@ -97,7 +97,7 @@ const autonodes_topbarcommands = [
|
|||||||
{
|
{
|
||||||
"id": `${autonodes_id}.default`,
|
"id": `${autonodes_id}.default`,
|
||||||
"label": "LiteGraph.js default layout",
|
"label": "LiteGraph.js default layout",
|
||||||
"function": () => app.graph.arrange()
|
"function": () => (app.canvas.graph || app.graph).arrange()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": `${autonodes_id}.dagre`,
|
"id": `${autonodes_id}.dagre`,
|
||||||
@@ -144,7 +144,8 @@ app.registerExtension({
|
|||||||
* @returns {undefined} Nothing is returned.
|
* @returns {undefined} Nothing is returned.
|
||||||
*/
|
*/
|
||||||
async function dagreLayout() {
|
async function dagreLayout() {
|
||||||
popupInput(); // see definition below
|
const activeGraph = app.canvas.graph || app.graph;
|
||||||
|
popupInput(activeGraph); // see definition below
|
||||||
|
|
||||||
// setup dagre
|
// setup dagre
|
||||||
const daG = new window.dagre.graphlib
|
const daG = new window.dagre.graphlib
|
||||||
@@ -159,14 +160,14 @@ async function dagreLayout() {
|
|||||||
.setDefaultEdgeLabel(() => ({}));
|
.setDefaultEdgeLabel(() => ({}));
|
||||||
|
|
||||||
// convert litegraph to dagre
|
// convert litegraph to dagre
|
||||||
app.graph._nodes.forEach((n) => daG.setNode(
|
activeGraph._nodes.forEach((n) => daG.setNode(
|
||||||
n.id.toString(),
|
n.id.toString(),
|
||||||
{
|
{
|
||||||
"width": n.size[0],
|
"width": n.size[0],
|
||||||
"height": n.size[1],
|
"height": n.size[1],
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
app.graph.links.forEach((e) => daG.setEdge(
|
activeGraph.links.forEach((e) => daG.setEdge(
|
||||||
e.origin_id.toString(),
|
e.origin_id.toString(),
|
||||||
e.target_id.toString()
|
e.target_id.toString()
|
||||||
));
|
));
|
||||||
@@ -175,13 +176,13 @@ async function dagreLayout() {
|
|||||||
window.dagre.layout(daG);
|
window.dagre.layout(daG);
|
||||||
|
|
||||||
// retrieve nodes position
|
// retrieve nodes position
|
||||||
for (const n of app.graph._nodes) {
|
for (const n of activeGraph._nodes) {
|
||||||
const nodeLaidOut = daG.node(n.id.toString());
|
const nodeLaidOut = daG.node(n.id.toString());
|
||||||
n.pos[0] = nodeLaidOut.x;
|
n.pos[0] = nodeLaidOut.x;
|
||||||
n.pos[1] = nodeLaidOut.y;
|
n.pos[1] = nodeLaidOut.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.graph.setDirtyCanvas(true, true); // refresh after applying the layout
|
activeGraph.setDirtyCanvas(true, true); // refresh after applying the layout
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,15 +194,16 @@ async function dagreLayout() {
|
|||||||
* @returns {undefined} Nothing is returned.
|
* @returns {undefined} Nothing is returned.
|
||||||
*/
|
*/
|
||||||
async function elkLayeredLayout() {
|
async function elkLayeredLayout() {
|
||||||
popupInput(); // see definition below
|
const activeGraph = app.canvas.graph || app.graph;
|
||||||
|
popupInput(activeGraph); // see definition below
|
||||||
|
|
||||||
// convert litegraph to elk
|
// convert litegraph to elk
|
||||||
const myElkNodes = app.graph._nodes.map((n) => ({
|
const myElkNodes = activeGraph._nodes.map((n) => ({
|
||||||
"id": n.id,
|
"id": n.id,
|
||||||
"width": n.size[0],
|
"width": n.size[0],
|
||||||
"height": n.size[1],
|
"height": n.size[1],
|
||||||
}));
|
}));
|
||||||
const myElkEdges = [...app.graph.links.values()].filter(Boolean).map((e) => ({
|
const myElkEdges = [...activeGraph.links.values()].filter(Boolean).map((e) => ({
|
||||||
"id": e.id,
|
"id": e.id,
|
||||||
"sources": [ e.origin_id ],
|
"sources": [ e.origin_id ],
|
||||||
"targets": [ e.target_id ],
|
"targets": [ e.target_id ],
|
||||||
@@ -228,13 +230,13 @@ async function elkLayeredLayout() {
|
|||||||
.then((val) => {
|
.then((val) => {
|
||||||
// retrieve nodes position
|
// retrieve nodes position
|
||||||
for (const nodeLaidOut of val.children) {
|
for (const nodeLaidOut of val.children) {
|
||||||
const n = app.graph.getNodeById(nodeLaidOut.id);
|
const n = activeGraph.getNodeById(nodeLaidOut.id);
|
||||||
n.pos[0] = nodeLaidOut.x;
|
n.pos[0] = nodeLaidOut.x;
|
||||||
n.pos[1] = nodeLaidOut.y;
|
n.pos[1] = nodeLaidOut.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh after applying the layout
|
// refresh after applying the layout
|
||||||
app.graph.setDirtyCanvas(true, true);
|
activeGraph.setDirtyCanvas(true, true);
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
|
|
||||||
@@ -251,16 +253,17 @@ async function elkLayeredLayout() {
|
|||||||
* @returns {undefined} Nothing is returned.
|
* @returns {undefined} Nothing is returned.
|
||||||
*/
|
*/
|
||||||
async function colaLayout() {
|
async function colaLayout() {
|
||||||
popupInput(); // see definition below
|
const activeGraph = app.canvas.graph || app.graph;
|
||||||
|
popupInput(activeGraph); // see definition below
|
||||||
|
|
||||||
// convert litegraph to cola
|
// convert litegraph to cola
|
||||||
const myColaNodes = app.graph._nodes.map((n) => ({
|
const myColaNodes = activeGraph._nodes.map((n) => ({
|
||||||
"name": n.id.toString(),
|
"name": n.id.toString(),
|
||||||
"width": n.size[0],
|
"width": n.size[0],
|
||||||
"height": n.size[1],
|
"height": n.size[1],
|
||||||
}));
|
}));
|
||||||
const nodesMap = myColaNodes.reduce((map, obj, id) => (map[obj.name] = id, map), {}); // find index from id
|
const nodesMap = myColaNodes.reduce((map, obj, id) => (map[obj.name] = id, map), {}); // find index from id
|
||||||
const myColaLinks = [...app.graph.links.values()].filter(Boolean).map((e) => ({
|
const myColaLinks = [...activeGraph.links.values()].filter(Boolean).map((e) => ({
|
||||||
"source": nodesMap[e.origin_id.toString()],
|
"source": nodesMap[e.origin_id.toString()],
|
||||||
"target": nodesMap[e.target_id.toString()],
|
"target": nodesMap[e.target_id.toString()],
|
||||||
}));
|
}));
|
||||||
@@ -277,13 +280,13 @@ async function colaLayout() {
|
|||||||
g_cola.updateNodePositions();
|
g_cola.updateNodePositions();
|
||||||
|
|
||||||
// retrieve nodes position
|
// retrieve nodes position
|
||||||
for (const n of app.graph._nodes) {
|
for (const n of activeGraph._nodes) {
|
||||||
const nodeLaidOut = g_cola.nodes().find((el) => el.name == n.id.toString());
|
const nodeLaidOut = g_cola.nodes().find((el) => el.name == n.id.toString());
|
||||||
n.pos[0] = nodeLaidOut.x;
|
n.pos[0] = nodeLaidOut.x;
|
||||||
n.pos[1] = nodeLaidOut.y;
|
n.pos[1] = nodeLaidOut.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.graph.setDirtyCanvas(true, true);
|
activeGraph.setDirtyCanvas(true, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -294,8 +297,8 @@ async function colaLayout() {
|
|||||||
* also served as placeholder for any additional check in the future
|
* also served as placeholder for any additional check in the future
|
||||||
* @returns {undefined} Nothing is returned.
|
* @returns {undefined} Nothing is returned.
|
||||||
*/
|
*/
|
||||||
function popupInput() {
|
function popupInput(activeGraph) {
|
||||||
for (const n of app.graph._nodes) {
|
for (const n of activeGraph._nodes) {
|
||||||
if (n.type === "Reroute") {
|
if (n.type === "Reroute") {
|
||||||
app.extensionManager.toast.add({
|
app.extensionManager.toast.add({
|
||||||
severity: "warn",
|
severity: "warn",
|
||||||
|
|||||||
Reference in New Issue
Block a user