From 60d2f729f9c492b6c376334eebc22965dbf8543e Mon Sep 17 00:00:00 2001 From: Julien Samama Date: Wed, 23 Jan 2019 17:33:56 +0100 Subject: [PATCH] Feature request InfiniteAmmoInc#70 resizing nodes * Allows node resizing by dragging the bottom right corner of a node. It forces it's shape to be a square. I've added this limitation because it would require too much work on the maths of the connection arrows otherwise. * Save to file in json, xml and yarn format. Twine doesn't handle resizing, so the size is not saved in the twee and tw2 format. * Loading a file also handle the size if it finds it in json, xml and yarn format. * Had to change a little the math of the arrows because the size was hardcoded. I've tried opening saved files containing the new 'size' option, and old versions of Yarn (the one linked in the build section of the readme) handled it correctly, ignoring the 'size' option and parsing the rest of the file correctly. And old saved files without the new 'size' option are also read correctly, the 'size' option is optional when loading. Note: the dragging box was already here in the html, but it was commented out because it was incomplete. The author who added it was planning to add a 'toggle expand' feature but apparently never did. I reused his 'resize' box and removed the few lines of code related to the 'toggle expand' feature. --- app/css/style.css | 2 ++ app/index.html | 2 +- app/js/classes/app.js | 20 +++++++++++++------ app/js/classes/data.js | 23 ++++++++++++++++++++++ app/js/classes/node.js | 44 ++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/app/css/style.css b/app/css/style.css index 5c4294b..c58ab7a 100644 --- a/app/css/style.css +++ b/app/css/style.css @@ -323,6 +323,8 @@ a:hover { color: #000;} position: absolute; width: 200px; height: 200px; + min-width: 200px; + min-height: 200px; background: #fff; border-radius: 2px; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.5); diff --git a/app/index.html b/app/index.html index 05e3dc5..d24c2a1 100644 --- a/app/index.html +++ b/app/index.html @@ -135,7 +135,7 @@
- +
diff --git a/app/js/classes/app.js b/app/js/classes/app.js index 9d296eb..dcb11e7 100644 --- a/app/js/classes/app.js +++ b/app/js/classes/app.js @@ -1220,17 +1220,25 @@ var App = function(name, version) { y: (toY - fromY) / distance }; - var dist = - 110 + 160 * (1 - Math.max(Math.abs(normal.x), Math.abs(normal.y))); + const margin = 10; + // Get the size of the 2 nodes. It's a square, so width and height are the same. + let sizeFrom = node.tempWidth / 2 + margin; + let sizeTo = linked.tempWidth / 2 + margin; + // Get the length from the center of the node to it's corner. + let diagonalFrom = Math.sqrt(node.tempWidth * node.tempWidth + node.tempHeight * node.tempHeight) / 2 + margin; + let diagonalTo = Math.sqrt(linked.tempWidth * linked.tempWidth + linked.tempHeight * linked.tempHeight) / 2 + margin; + + let distFrom = sizeFrom + diagonalFrom * (1 - Math.max(Math.abs(normal.x), Math.abs(normal.y))); + let distTo = sizeTo + diagonalTo * (1 - Math.max(Math.abs(normal.x), Math.abs(normal.y))); // get from / to var from = { - x: fromX + normal.x * dist * scale, - y: fromY + normal.y * dist * scale + x: fromX + normal.x * distFrom * scale, + y: fromY + normal.y * distFrom * scale }; var to = { - x: toX - normal.x * dist * scale, - y: toY - normal.y * dist * scale + x: toX - normal.x * distTo * scale, + y: toY - normal.y * distTo * scale }; self.context.strokeStyle = diff --git a/app/js/classes/data.js b/app/js/classes/data.js index a0e4619..1bc90c7 100644 --- a/app/js/classes/data.js +++ b/app/js/classes/data.js @@ -158,6 +158,10 @@ var data = { if (obj == null) obj = {}; var xy = lines[i].substr(9, lines[i].length - 9).split(","); obj.position = { x: Number(xy[0].trim()), y: Number(xy[1].trim()) }; + } else if (lines[i].indexOf("size:") > -1) { + if (obj == null) obj = {}; + let size = lines[i].substr(5, lines[i].length - 5).split(","); + obj.size = { width: Number(size[0].trim()), height: Number(size[1].trim()) }; } else if (lines[i].indexOf("colorID:") > -1) { if (obj == null) obj = {}; obj.colorID = Number( @@ -273,6 +277,12 @@ var data = { node.y(object.position.y); avgY += object.position.y; } + if (object.size != undefined && object.size.width != undefined) { + node.width(object.size.width); + } + if (object.size != undefined && object.size.height != undefined) { + node.height(object.size.height); + } if (object.colorID != undefined) node.colorID(object.colorID); } @@ -297,6 +307,7 @@ var data = { tags: nodes[i].tags(), body: nodes[i].body(), position: { x: nodes[i].x(), y: nodes[i].y() }, + size: { width: nodes[i].width(), height: nodes[i].height() }, colorID: nodes[i].colorID() }); } @@ -314,6 +325,12 @@ var data = { "," + content[i].position.y + "\n"; + output += + "size: " + + content[i].size.width + + "," + + content[i].size.height + + "\n"; output += "---\n"; output += content[i].body; var body = content[i].body; @@ -351,6 +368,12 @@ var data = { '" y="' + content[i].position.y + '">\n'; + output += + '\t\t\n'; output += "\t\t" + content[i].colorID + "\n"; output += "\t\n"; } diff --git a/app/js/classes/node.js b/app/js/classes/node.js index bb8e28b..c408f26 100644 --- a/app/js/classes/node.js +++ b/app/js/classes/node.js @@ -1,6 +1,4 @@ var globalNodeIndex = 0; -const NodeExpandWidth = 300; -const NodeExpandHeight = 150; const ClipNodeTextLength = 1024; const bbcode = require('bbcode') @@ -23,6 +21,7 @@ var Node = function() this.colorID = ko.observable(0); this.checked = false; this.selected = false; + this.resizeHandle = null; // clipped values for display this.clippedTags = ko.computed(function() @@ -110,6 +109,9 @@ var Node = function() app.updateArrowsThrottled(); } ); + + self.resizeHandle = $(self.element).children(".resize")[0]; + self.drag(); $(self.element).on("dblclick", function() @@ -159,6 +161,20 @@ var Node = function() $(self.element).css({y:Math.floor(inY)}); return Math.floor((new WebKitCSSMatrix(self.style.webkitTransform)).m42); } + + this.width = function(inWidth) + { + if (inWidth != undefined) + $(self.element).width(Math.floor(inWidth)); + return Math.floor($(self.element).width()); + } + + this.height = function(inHeight) + { + if (inHeight != undefined) + $(self.element).height(Math.floor(inHeight)); + return Math.floor($(self.element).height()); + } this.resetDoubleClick = function() { @@ -230,6 +246,7 @@ var Node = function() { var dragging = false; var groupDragging = false; + var resizing = false; var offset = [0, 0]; var moved = false; @@ -275,6 +292,28 @@ var Node = function() //app.refresh(); app.updateArrowsThrottled(); } + else if (resizing) + { + const scale = self.getScale(); + const mouseX = (e.pageX / scale); + const mouseY = (e.pageY / scale); + const nodeX = $(self.element).offset().left / scale; + const nodeY = $(self.element).offset().top / scale; + const width = mouseX - nodeX; + const height = mouseY - nodeY; + const size = Math.max(width, height); + + // resize + self.width(size); + self.height(size); + + app.updateArrowsThrottled(); + } + }); + + $(self.resizeHandle).on("mousedown", function(e) { + resizing = true; + e.stopPropagation(); }); $(self.element).on("mousedown", function (e) @@ -314,6 +353,7 @@ var Node = function() dragging = false; groupDragging = false; moved = false; + resizing = false; app.updateArrowsThrottled(); });