572 lines
26 KiB
JavaScript
572 lines
26 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
|
|
app.registerExtension({
|
|
name: "RaykoStudio.LoadImagesFromDir",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeData.name !== "RSLoadImagesFromDir") return;
|
|
|
|
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
|
|
|
nodeType.prototype.onNodeCreated = function() {
|
|
const result = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
|
|
const node = this;
|
|
|
|
node.data = {
|
|
folder_path: "",
|
|
filter_type: "*.png",
|
|
start_index: 1,
|
|
end_index: 1,
|
|
custom_filter: "*.png"
|
|
};
|
|
|
|
const filters = ["*.*", "*.png", "*.jpg", "*.jpeg", "*.webp", "*.bmp", "*.gif", "custom"];
|
|
|
|
const NODE_WIDTH = 260;
|
|
node.targetWidth = NODE_WIDTH;
|
|
|
|
const MIN_HEIGHT_NORMAL = 255;
|
|
const MIN_HEIGHT_CUSTOM = 280;
|
|
|
|
node.setSize([NODE_WIDTH, MIN_HEIGHT_NORMAL]);
|
|
node.min_size = [NODE_WIDTH, MIN_HEIGHT_NORMAL];
|
|
|
|
const wNodeData = node.widgets?.find(w => w.name === "node_data");
|
|
const wPath = node.widgets?.find(w => w.name === "folder_path");
|
|
const wFilter = node.widgets?.find(w => w.name === "filter_type");
|
|
const wStart = node.widgets?.find(w => w.name === "start_index");
|
|
const wEnd = node.widgets?.find(w => w.name === "end_index");
|
|
const wCustom = node.widgets?.find(w => w.name === "custom_filter");
|
|
|
|
[wNodeData, wPath, wFilter, wStart, wEnd, wCustom].forEach(w => {
|
|
if (w) {
|
|
w.hidden = true;
|
|
if (w.element) w.element.style.display = "none";
|
|
}
|
|
});
|
|
|
|
if (wNodeData) {
|
|
try {
|
|
const savedData = JSON.parse(wNodeData.value || "{}");
|
|
if (savedData && typeof savedData === 'object') {
|
|
node.data = { ...node.data, ...savedData };
|
|
}
|
|
} catch (e) {}
|
|
|
|
wNodeData.serializeValue = () => {
|
|
node.syncData();
|
|
return JSON.stringify(node.data);
|
|
};
|
|
}
|
|
|
|
node.uiElements = [];
|
|
node.dropdownMenu = null;
|
|
node.customModal = null;
|
|
|
|
node.syncData = function() {
|
|
if (wPath) wPath.value = node.data.folder_path;
|
|
if (wFilter) wFilter.value = node.data.filter_type;
|
|
if (wStart) wStart.value = parseInt(node.data.start_index);
|
|
if (wEnd) wEnd.value = parseInt(node.data.end_index);
|
|
if (wCustom) wCustom.value = node.data.custom_filter;
|
|
|
|
if (wNodeData) {
|
|
wNodeData.value = JSON.stringify(node.data);
|
|
}
|
|
|
|
if (node.graph) {
|
|
node.graph.changeTracker?.dispatchEvent(new Event("change"));
|
|
}
|
|
};
|
|
|
|
const updateNodeSize = () => {
|
|
const targetHeight = node.data.filter_type === "custom" ? MIN_HEIGHT_CUSTOM : MIN_HEIGHT_NORMAL;
|
|
node.min_size = [NODE_WIDTH, targetHeight];
|
|
|
|
if (Math.abs(node.size[1] - targetHeight) > 1) {
|
|
node.setSize([node.size[0], targetHeight]);
|
|
node.setDirtyCanvas(true, true);
|
|
}
|
|
};
|
|
|
|
node.onResize = function() {
|
|
const minHeight = this.data.filter_type === "custom" ? MIN_HEIGHT_CUSTOM : MIN_HEIGHT_NORMAL;
|
|
if (this.size[0] < NODE_WIDTH) {
|
|
this.size[0] = NODE_WIDTH;
|
|
}
|
|
if (this.size[1] < minHeight) {
|
|
this.size[1] = minHeight;
|
|
}
|
|
this.setDirtyCanvas(true, true);
|
|
};
|
|
|
|
const onConfigure = node.onConfigure;
|
|
node.onConfigure = function(o) {
|
|
if (onConfigure) onConfigure.apply(this, arguments);
|
|
if (wNodeData && wNodeData.value) {
|
|
try {
|
|
const restoredData = JSON.parse(wNodeData.value);
|
|
if (restoredData) {
|
|
node.data = { ...node.data, ...restoredData };
|
|
node.syncData();
|
|
updateNodeSize();
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
};
|
|
|
|
const closeDropdown = (e) => {
|
|
if (node.dropdownMenu && !node.dropdownMenu.contains(e.target)) {
|
|
node.dropdownMenu.remove();
|
|
node.dropdownMenu = null;
|
|
}
|
|
};
|
|
|
|
const showCustomPrompt = (title, defaultValue, callback) => {
|
|
if (node.customModal) {
|
|
node.customModal.remove();
|
|
node.customModal = null;
|
|
}
|
|
|
|
const backdrop = document.createElement("div");
|
|
backdrop.style.cssText = `
|
|
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
background: rgba(0, 0, 0, 0.5); z-index: 10002;
|
|
display: flex; align-items: center; justify-content: center;
|
|
`;
|
|
|
|
const modal = document.createElement("div");
|
|
modal.style.cssText = `
|
|
background: #1a1a1a; border: 1px solid #444; border-radius: 3px;
|
|
padding: 16px; min-width: 320px; max-width: 500px;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.7);
|
|
font-family: sans-serif; font-size: 12px; color: #ddd;
|
|
`;
|
|
|
|
const titleEl = document.createElement("div");
|
|
titleEl.textContent = title;
|
|
titleEl.style.cssText = `
|
|
margin-bottom: 12px; font-size: 13px; color: #fff; font-weight: bold;
|
|
`;
|
|
modal.appendChild(titleEl);
|
|
|
|
const input = document.createElement("input");
|
|
input.type = "text";
|
|
input.value = defaultValue || "";
|
|
input.style.cssText = `
|
|
width: 100%; box-sizing: border-box; padding: 8px 10px;
|
|
background: #222; border: 1px solid #666; border-radius: 3px;
|
|
color: #fff; font-size: 12px; outline: none;
|
|
font-family: monospace;
|
|
`;
|
|
input.onfocus = () => { input.style.borderColor = "#2196F3"; };
|
|
input.onblur = () => { input.style.borderColor = "#666"; };
|
|
modal.appendChild(input);
|
|
|
|
const btnContainer = document.createElement("div");
|
|
btnContainer.style.cssText = `
|
|
display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px;
|
|
`;
|
|
|
|
const btnPaste = document.createElement("div");
|
|
btnPaste.setAttribute("role", "button");
|
|
btnPaste.setAttribute("tabindex", "0");
|
|
btnPaste.textContent = " Paste";
|
|
btnPaste.style.cssText = `
|
|
padding: 6px 16px; background: #2a2a2a; border: 1px solid #888;
|
|
border-radius: 3px; color: #ddd; font-size: 12px; cursor: pointer;
|
|
font-family: sans-serif; min-width: 80px; transition: all 0.2s;
|
|
user-select: none; -moz-user-select: none;
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
`;
|
|
btnPaste.onmousedown = (e) => e.preventDefault();
|
|
btnPaste.onmouseup = (e) => e.preventDefault();
|
|
btnPaste.oncontextmenu = (e) => e.preventDefault();
|
|
btnPaste.onmouseover = () => { if (!btnPaste.disabled) btnPaste.style.background = "#3a3a3a"; };
|
|
btnPaste.onmouseout = () => { if (!btnPaste.disabled) btnPaste.style.background = "#2a2a2a"; };
|
|
|
|
btnPaste.onclick = async (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
btnPaste.disabled = true;
|
|
btnPaste.style.opacity = "0.7";
|
|
btnPaste.style.cursor = "wait";
|
|
btnPaste.textContent = "⏳ ...";
|
|
|
|
try {
|
|
const text = await navigator.clipboard.readText();
|
|
if (text) {
|
|
input.value = text;
|
|
input.focus();
|
|
btnPaste.textContent = "✅ Done";
|
|
btnPaste.style.borderColor = "#4CAF50";
|
|
btnPaste.style.color = "#4CAF50";
|
|
}
|
|
} catch (err) {
|
|
btnPaste.textContent = "⌨️ Ctrl+V";
|
|
btnPaste.style.borderColor = "#FF9800";
|
|
btnPaste.style.color = "#FF9800";
|
|
input.focus();
|
|
input.select();
|
|
}
|
|
|
|
setTimeout(() => {
|
|
btnPaste.disabled = false;
|
|
btnPaste.style.opacity = "1";
|
|
btnPaste.style.cursor = "pointer";
|
|
btnPaste.textContent = " Paste";
|
|
btnPaste.style.borderColor = "#888";
|
|
btnPaste.style.color = "#ddd";
|
|
btnPaste.style.background = "#2a2a2a";
|
|
}, 600);
|
|
};
|
|
|
|
const btnCancel = document.createElement("button");
|
|
btnCancel.textContent = "Cancel";
|
|
btnCancel.style.cssText = `
|
|
padding: 6px 16px; background: #2a2a2a; border: 1px solid #888;
|
|
border-radius: 3px; color: #ddd; font-size: 12px; cursor: pointer;
|
|
font-family: sans-serif;
|
|
`;
|
|
btnCancel.onmouseover = () => { btnCancel.style.background = "#3a3a3a"; };
|
|
btnCancel.onmouseout = () => { btnCancel.style.background = "#2a2a2a"; };
|
|
|
|
const btnOk = document.createElement("button");
|
|
btnOk.textContent = "OK";
|
|
btnOk.style.cssText = `
|
|
padding: 6px 16px; background: #2196F3; border: 1px solid #2196F3;
|
|
border-radius: 3px; color: #fff; font-size: 12px; cursor: pointer;
|
|
font-family: sans-serif; font-weight: bold;
|
|
`;
|
|
btnOk.onmouseover = () => { btnOk.style.background = "#1976D2"; };
|
|
btnOk.onmouseout = () => { btnOk.style.background = "#2196F3"; };
|
|
|
|
btnContainer.appendChild(btnPaste);
|
|
btnContainer.appendChild(btnCancel);
|
|
btnContainer.appendChild(btnOk);
|
|
modal.appendChild(btnContainer);
|
|
backdrop.appendChild(modal);
|
|
document.body.appendChild(backdrop);
|
|
|
|
node.customModal = backdrop;
|
|
|
|
const close = (result) => {
|
|
backdrop.remove();
|
|
node.customModal = null;
|
|
document.removeEventListener("keydown", keyHandler);
|
|
if (callback) callback(result);
|
|
};
|
|
|
|
const confirm = () => close(input.value);
|
|
const cancel = () => close(null);
|
|
|
|
btnOk.onclick = (e) => { e.stopPropagation(); confirm(); };
|
|
btnCancel.onclick = (e) => { e.stopPropagation(); cancel(); };
|
|
backdrop.onclick = (e) => {
|
|
if (e.target === backdrop) cancel();
|
|
};
|
|
|
|
const keyHandler = (e) => {
|
|
if (e.key === "Enter") {
|
|
e.preventDefault();
|
|
confirm();
|
|
} else if (e.key === "Escape") {
|
|
e.preventDefault();
|
|
cancel();
|
|
}
|
|
};
|
|
document.addEventListener("keydown", keyHandler);
|
|
|
|
setTimeout(() => {
|
|
input.focus();
|
|
input.select();
|
|
}, 10);
|
|
};
|
|
|
|
const truncatePath = (ctx, path, maxWidth) => {
|
|
if (!path) return "Folder not selected";
|
|
const ellipsis = "...";
|
|
if (ctx.measureText(path).width <= maxWidth) {
|
|
return path;
|
|
}
|
|
let truncated = path;
|
|
while (truncated.length > 0 && ctx.measureText(ellipsis + truncated).width > maxWidth) {
|
|
truncated = truncated.substring(1);
|
|
}
|
|
return ellipsis + truncated;
|
|
};
|
|
|
|
const drawRoundedRect = (ctx, x, y, w, h, r) => {
|
|
if (ctx.roundRect) {
|
|
ctx.beginPath();
|
|
ctx.roundRect(x, y, w, h, r);
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
} else {
|
|
ctx.beginPath();
|
|
ctx.moveTo(x + r, y);
|
|
ctx.lineTo(x + w - r, y);
|
|
ctx.arcTo(x + w, y, x + w, y + r, r);
|
|
ctx.lineTo(x + w, y + h - r);
|
|
ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
|
|
ctx.lineTo(x + r, y + h);
|
|
ctx.arcTo(x, y + h, x, y + h - r, r);
|
|
ctx.lineTo(x, y + r);
|
|
ctx.arcTo(x, y, x + r, y, r);
|
|
ctx.closePath();
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
}
|
|
};
|
|
|
|
node.onDrawForeground = function(ctx) {
|
|
if (this.flags.collapsed) return;
|
|
|
|
ctx.save(); // ← ДОБАВЛЕНО
|
|
|
|
try {
|
|
const [w, h] = this.size;
|
|
const padding = 10;
|
|
const rowHeight = 23;
|
|
const borderRadius = 3;
|
|
let currentY = 35 + 60;
|
|
|
|
ctx.font = "12px sans-serif";
|
|
ctx.textBaseline = "middle";
|
|
|
|
const pathDisplayHeight = 20;
|
|
ctx.fillStyle = "#1a1a1a";
|
|
ctx.strokeStyle = "#333";
|
|
drawRoundedRect(ctx, padding, currentY, w - padding * 2, pathDisplayHeight, borderRadius);
|
|
|
|
const pathText = node.data.folder_path || "Folder not selected";
|
|
const displayPath = truncatePath(ctx, pathText, w - padding * 2 - 10);
|
|
ctx.fillStyle = node.data.folder_path ? "#aaa" : "#666";
|
|
ctx.textAlign = "left";
|
|
ctx.fillText(displayPath, padding + 5, currentY + pathDisplayHeight / 2);
|
|
currentY += pathDisplayHeight + 7;
|
|
|
|
ctx.fillStyle = "#2a2a2a";
|
|
ctx.strokeStyle = "#2196F3";
|
|
drawRoundedRect(ctx, padding, currentY, w - padding * 2, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#2196F3";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText("📁 Select folder", w / 2, currentY + rowHeight / 2);
|
|
this.uiElements.push({ type: "btn_folder", x: padding, y: currentY, w: w - padding * 2, h: rowHeight });
|
|
currentY += rowHeight + 7;
|
|
|
|
const filterLabel = `▼ ${node.data.filter_type}`;
|
|
ctx.fillStyle = "#2a2a2a";
|
|
ctx.strokeStyle = "#4CAF50";
|
|
drawRoundedRect(ctx, padding, currentY, w - padding * 2, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#4CAF50";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText(filterLabel, w / 2, currentY + rowHeight / 2);
|
|
this.uiElements.push({ type: "btn_filter", x: padding, y: currentY, w: w - padding * 2, h: rowHeight });
|
|
currentY += rowHeight + 7;
|
|
|
|
const drawNumberInput = (label, value, yPos, dataType) => {
|
|
const labelW = 40;
|
|
const btnW = 20;
|
|
const gap = 4;
|
|
const totalW = w - padding * 2;
|
|
const valW = totalW - labelW - (btnW * 2) - (gap * 2);
|
|
|
|
ctx.fillStyle = "#aaa";
|
|
ctx.textAlign = "left";
|
|
ctx.fillText(label, padding, yPos + rowHeight / 2);
|
|
|
|
const btnX1 = padding + labelW + gap;
|
|
ctx.fillStyle = "#333";
|
|
ctx.strokeStyle = "#888";
|
|
drawRoundedRect(ctx, btnX1, yPos, btnW, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#fff";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText("-", btnX1 + btnW / 2, yPos + rowHeight / 2);
|
|
|
|
const valX = btnX1 + btnW + gap;
|
|
ctx.fillStyle = "#222";
|
|
ctx.strokeStyle = "#666";
|
|
drawRoundedRect(ctx, valX, yPos, valW, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#fff";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText(String(value), valX + valW / 2, yPos + rowHeight / 2);
|
|
|
|
const btnX2 = valX + valW + gap;
|
|
ctx.fillStyle = "#333";
|
|
ctx.strokeStyle = "#888";
|
|
drawRoundedRect(ctx, btnX2, yPos, btnW, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#fff";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText("+", btnX2 + btnW / 2, yPos + rowHeight / 2);
|
|
|
|
this.uiElements.push({ type: `btn_${dataType}_minus`, x: btnX1, y: yPos, w: btnW, h: rowHeight });
|
|
this.uiElements.push({ type: `val_${dataType}`, x: valX, y: yPos, w: valW, h: rowHeight });
|
|
this.uiElements.push({ type: `btn_${dataType}_plus`, x: btnX2, y: yPos, w: btnW, h: rowHeight });
|
|
};
|
|
|
|
drawNumberInput("Start:", node.data.start_index, currentY, "start");
|
|
currentY += rowHeight + 5;
|
|
|
|
drawNumberInput("End:", node.data.end_index, currentY, "end");
|
|
currentY += rowHeight + 12;
|
|
|
|
if (node.data.filter_type === "custom") {
|
|
ctx.fillStyle = "#aaa";
|
|
ctx.textAlign = "left";
|
|
ctx.fillText("Custom:", padding, currentY + rowHeight / 2);
|
|
|
|
const custValW = w - padding * 2 - 45;
|
|
const custX = padding + 45;
|
|
|
|
ctx.fillStyle = "#222";
|
|
ctx.strokeStyle = "#FF9800";
|
|
drawRoundedRect(ctx, custX, currentY, custValW, rowHeight, borderRadius);
|
|
ctx.fillStyle = "#FF9800";
|
|
ctx.textAlign = "left";
|
|
ctx.fillText(node.data.custom_filter, custX + 5, currentY + rowHeight / 2);
|
|
|
|
this.uiElements.push({ type: "val_custom", x: custX, y: currentY, w: custValW, h: rowHeight });
|
|
}
|
|
} finally {
|
|
ctx.restore(); // ← ДОБАВЛЕНО
|
|
}
|
|
};
|
|
|
|
node.onMouseDown = function(event, pos) {
|
|
const [x, y] = pos;
|
|
this.uiElements = [];
|
|
this.onDrawForeground(app.canvas.ctx);
|
|
|
|
for (const el of this.uiElements) {
|
|
if (x >= el.x && x <= el.x + el.w && y >= el.y && y <= el.y + el.h) {
|
|
if (el.type === "btn_folder") {
|
|
showCustomPrompt("Enter folder path", this.data.folder_path, (result) => {
|
|
if (result !== null) {
|
|
this.data.folder_path = result.trim();
|
|
node.syncData();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (el.type === "btn_filter") {
|
|
if (this.dropdownMenu) this.dropdownMenu.remove();
|
|
|
|
const menu = document.createElement("div");
|
|
menu.style.cssText = `
|
|
position: fixed; background: #1a1a1a; border: 1px solid #444;
|
|
border-radius: 3px; max-height: 255px; overflow-y: auto;
|
|
z-index: 10001; box-shadow: 0 4px 20px rgba(0,0,0,0.5); min-width: 150px;
|
|
`;
|
|
|
|
filters.forEach(f => {
|
|
const item = document.createElement("div");
|
|
item.textContent = f;
|
|
item.style.cssText = `
|
|
padding: 8px 12px; cursor: pointer; color: #ddd; font-size: 12px;
|
|
border-bottom: 1px solid #333;
|
|
background: ${f === this.data.filter_type ? '#333' : '#1a1a1a'};
|
|
`;
|
|
item.onmouseover = () => item.style.background = "#444";
|
|
item.onmouseout = () => item.style.background = f === this.data.filter_type ? '#333' : "#1a1a1a";
|
|
item.onclick = (e) => {
|
|
e.stopPropagation();
|
|
this.data.filter_type = f;
|
|
node.syncData();
|
|
updateNodeSize();
|
|
menu.remove();
|
|
this.dropdownMenu = null;
|
|
};
|
|
menu.appendChild(item);
|
|
});
|
|
|
|
const canvasRect = app.canvas.canvas.getBoundingClientRect();
|
|
const ds = app.canvas.ds;
|
|
const nodeScreenX = canvasRect.left + ((this.pos[0] + ds.offset[0]) * ds.scale);
|
|
const nodeScreenY = canvasRect.top + ((this.pos[1] + ds.offset[1]) * ds.scale);
|
|
|
|
menu.style.left = (nodeScreenX + el.x) + "px";
|
|
menu.style.top = (nodeScreenY + el.y + el.h + 5) + "px";
|
|
|
|
document.body.appendChild(menu);
|
|
this.dropdownMenu = menu;
|
|
setTimeout(() => document.addEventListener("mousedown", closeDropdown), 100);
|
|
return true;
|
|
}
|
|
|
|
if (el.type === "btn_start_minus") {
|
|
this.data.start_index = Math.max(1, parseInt(this.data.start_index) - 1);
|
|
node.syncData();
|
|
return true;
|
|
}
|
|
if (el.type === "btn_start_plus") {
|
|
this.data.start_index = parseInt(this.data.start_index) + 1;
|
|
node.syncData();
|
|
return true;
|
|
}
|
|
if (el.type === "val_start") {
|
|
showCustomPrompt("Start index (min 1)", String(this.data.start_index), (result) => {
|
|
if (result !== null) {
|
|
this.data.start_index = Math.max(1, parseInt(result) || 1);
|
|
node.syncData();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (el.type === "btn_end_minus") {
|
|
this.data.end_index = Math.max(1, parseInt(this.data.end_index) - 1);
|
|
node.syncData();
|
|
return true;
|
|
}
|
|
if (el.type === "btn_end_plus") {
|
|
this.data.end_index = parseInt(this.data.end_index) + 1;
|
|
node.syncData();
|
|
return true;
|
|
}
|
|
if (el.type === "val_end") {
|
|
showCustomPrompt("End index", String(this.data.end_index), (result) => {
|
|
if (result !== null) {
|
|
this.data.end_index = Math.max(1, parseInt(result) || 1);
|
|
node.syncData();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (el.type === "val_custom") {
|
|
showCustomPrompt("Custom filter (e.g. *_mask.png)", this.data.custom_filter, (result) => {
|
|
if (result !== null) {
|
|
this.data.custom_filter = result.trim() || "*.png";
|
|
node.syncData();
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
const originalOnRemoved = node.onRemoved;
|
|
node.onRemoved = function() {
|
|
if (this.dropdownMenu) {
|
|
this.dropdownMenu.remove();
|
|
this.dropdownMenu = null;
|
|
}
|
|
if (this.customModal) {
|
|
this.customModal.remove();
|
|
this.customModal = null;
|
|
}
|
|
document.removeEventListener("mousedown", closeDropdown);
|
|
if (originalOnRemoved) originalOnRemoved.apply(this, arguments);
|
|
};
|
|
|
|
node.syncData();
|
|
updateNodeSize();
|
|
|
|
return result;
|
|
};
|
|
}
|
|
}); |