Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac5bb32bb8 | ||
|
|
43dded2f42 | ||
|
|
a93b8687ac | ||
|
|
eb2d3762a5 | ||
|
|
6afc4c38e7 | ||
|
|
b1a061fe47 | ||
|
|
2c262f722b | ||
|
|
894d9e5a0b | ||
|
|
48736ca845 | ||
|
|
a33961fdab | ||
|
|
62a704fc14 | ||
|
|
d5e37ff797 | ||
|
|
bdade789ee | ||
|
|
1aef2b8e43 | ||
|
|
cb1e98abf1 | ||
|
|
891daeb438 | ||
|
|
d9712b0e04 | ||
|
|
92711dc762 | ||
|
|
6f256423af | ||
|
|
47c23d5a19 |
@@ -57,6 +57,7 @@ NODE_CONFIG = {
|
|||||||
"ImageUpscaleWithModelBatched": {"class": ImageUpscaleWithModelBatched, "name": "Image Upscale With Model Batched"},
|
"ImageUpscaleWithModelBatched": {"class": ImageUpscaleWithModelBatched, "name": "Image Upscale With Model Batched"},
|
||||||
"InsertImagesToBatchIndexed": {"class": InsertImagesToBatchIndexed, "name": "Insert Images To Batch Indexed"},
|
"InsertImagesToBatchIndexed": {"class": InsertImagesToBatchIndexed, "name": "Insert Images To Batch Indexed"},
|
||||||
"MergeImageChannels": {"class": MergeImageChannels, "name": "Merge Image Channels"},
|
"MergeImageChannels": {"class": MergeImageChannels, "name": "Merge Image Channels"},
|
||||||
|
"PreviewAnimation": {"class": PreviewAnimation, "name": "Preview Animation"},
|
||||||
"RemapImageRange": {"class": RemapImageRange, "name": "Remap Image Range"},
|
"RemapImageRange": {"class": RemapImageRange, "name": "Remap Image Range"},
|
||||||
"ReverseImageBatch": {"class": ReverseImageBatch, "name": "Reverse Image Batch"},
|
"ReverseImageBatch": {"class": ReverseImageBatch, "name": "Reverse Image Batch"},
|
||||||
"ReplaceImagesInBatch": {"class": ReplaceImagesInBatch, "name": "Replace Images In Batch"},
|
"ReplaceImagesInBatch": {"class": ReplaceImagesInBatch, "name": "Replace Images In Batch"},
|
||||||
|
|||||||
@@ -146,11 +146,12 @@ class SplineEditor:
|
|||||||
"optional": {
|
"optional": {
|
||||||
"min_value": ("FLOAT", {"default": 0.0, "min": -10000.0, "max": 10000.0, "step": 0.01}),
|
"min_value": ("FLOAT", {"default": 0.0, "min": -10000.0, "max": 10000.0, "step": 0.01}),
|
||||||
"max_value": ("FLOAT", {"default": 1.0, "min": -10000.0, "max": 10000.0, "step": 0.01}),
|
"max_value": ("FLOAT", {"default": 1.0, "min": -10000.0, "max": 10000.0, "step": 0.01}),
|
||||||
|
"editor_link": ("EDITORLINK",),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("MASK", "STRING", "FLOAT", "INT")
|
RETURN_TYPES = ("MASK", "STRING", "FLOAT", "INT", "EDITORLINK",)
|
||||||
RETURN_NAMES = ("mask", "coord_str", "float", "count")
|
RETURN_NAMES = ("mask", "coord_str", "float", "count", "editor_link",)
|
||||||
FUNCTION = "splinedata"
|
FUNCTION = "splinedata"
|
||||||
CATEGORY = "KJNodes/weights"
|
CATEGORY = "KJNodes/weights"
|
||||||
DESCRIPTION = """
|
DESCRIPTION = """
|
||||||
@@ -192,7 +193,7 @@ output types:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def splinedata(self, mask_width, mask_height, coordinates, float_output_type, interpolation,
|
def splinedata(self, mask_width, mask_height, coordinates, float_output_type, interpolation,
|
||||||
points_to_sample, sampling_method, points_store, tension, repeat_output, min_value=0.0, max_value=1.0):
|
points_to_sample, sampling_method, points_store, tension, repeat_output, min_value=0.0, max_value=1.0, editor_link=None):
|
||||||
|
|
||||||
coordinates = json.loads(coordinates)
|
coordinates = json.loads(coordinates)
|
||||||
for coord in coordinates:
|
for coord in coordinates:
|
||||||
@@ -221,7 +222,7 @@ output types:
|
|||||||
masks_out = torch.stack(mask_tensors)
|
masks_out = torch.stack(mask_tensors)
|
||||||
masks_out = masks_out.repeat(repeat_output, 1, 1, 1)
|
masks_out = masks_out.repeat(repeat_output, 1, 1, 1)
|
||||||
masks_out = masks_out.mean(dim=-1)
|
masks_out = masks_out.mean(dim=-1)
|
||||||
return (masks_out, str(coordinates), out_floats, len(out_floats))
|
return (masks_out, str(coordinates), out_floats, len(out_floats), editor_link,)
|
||||||
|
|
||||||
class CreateShapeMaskOnPath:
|
class CreateShapeMaskOnPath:
|
||||||
|
|
||||||
|
|||||||
@@ -1074,3 +1074,87 @@ with the **inputcount** and clicking update.
|
|||||||
new_image = kwargs[f"image_{c + 1}"]
|
new_image = kwargs[f"image_{c + 1}"]
|
||||||
image, = image_batch_node.batch(image, new_image)
|
image, = image_batch_node.batch(image, new_image)
|
||||||
return (image,)
|
return (image,)
|
||||||
|
|
||||||
|
class PreviewAnimation:
|
||||||
|
def __init__(self):
|
||||||
|
self.output_dir = folder_paths.get_temp_directory()
|
||||||
|
self.type = "temp"
|
||||||
|
self.prefix_append = "_temp_" + ''.join(random.choice("abcdefghijklmnopqrstupvxyz") for x in range(5))
|
||||||
|
self.compress_level = 1
|
||||||
|
|
||||||
|
methods = {"default": 4, "fastest": 0, "slowest": 6}
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
return {"required":
|
||||||
|
{
|
||||||
|
"fps": ("FLOAT", {"default": 8.0, "min": 0.01, "max": 1000.0, "step": 0.01}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"images": ("IMAGE", ),
|
||||||
|
"masks": ("MASK", ),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ()
|
||||||
|
FUNCTION = "preview"
|
||||||
|
OUTPUT_NODE = True
|
||||||
|
CATEGORY = "KJNodes/image"
|
||||||
|
|
||||||
|
def preview(self, fps, images=None, masks=None):
|
||||||
|
filename_prefix = "AnimPreview"
|
||||||
|
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.output_dir)
|
||||||
|
results = list()
|
||||||
|
|
||||||
|
pil_images = []
|
||||||
|
|
||||||
|
if images is not None and masks is not None:
|
||||||
|
for image in images:
|
||||||
|
i = 255. * image.cpu().numpy()
|
||||||
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||||
|
pil_images.append(img)
|
||||||
|
for mask in masks:
|
||||||
|
if pil_images:
|
||||||
|
mask_np = mask.cpu().numpy()
|
||||||
|
mask_np = np.clip(mask_np * 255, 0, 255).astype(np.uint8) # Convert to values between 0 and 255
|
||||||
|
mask_img = Image.fromarray(mask_np, mode='L')
|
||||||
|
img = pil_images.pop(0) # Remove and get the first image
|
||||||
|
img = img.convert("RGBA") # Convert base image to RGBA
|
||||||
|
|
||||||
|
# Create a new RGBA image based on the grayscale mask
|
||||||
|
rgba_mask_img = Image.new("RGBA", img.size, (255, 255, 255, 255))
|
||||||
|
rgba_mask_img.putalpha(mask_img) # Use the mask image as the alpha channel
|
||||||
|
|
||||||
|
# Composite the RGBA mask onto the base image
|
||||||
|
composited_img = Image.alpha_composite(img, rgba_mask_img)
|
||||||
|
pil_images.append(composited_img) # Add the composited image back
|
||||||
|
|
||||||
|
elif images is not None and masks is None:
|
||||||
|
for image in images:
|
||||||
|
i = 255. * image.cpu().numpy()
|
||||||
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||||
|
pil_images.append(img)
|
||||||
|
|
||||||
|
elif masks is not None and images is None:
|
||||||
|
for mask in masks:
|
||||||
|
mask_np = 255. * mask.cpu().numpy()
|
||||||
|
mask_img = Image.fromarray(np.clip(mask_np, 0, 255).astype(np.uint8))
|
||||||
|
pil_images.append(mask_img)
|
||||||
|
else:
|
||||||
|
print("PreviewAnimation: No images or masks provided")
|
||||||
|
return { "ui": { "images": results, "animated": (None,), "text": "empty" }}
|
||||||
|
|
||||||
|
num_frames = len(pil_images)
|
||||||
|
|
||||||
|
c = len(pil_images)
|
||||||
|
for i in range(0, c, num_frames):
|
||||||
|
file = f"{filename}_{counter:05}_.webp"
|
||||||
|
pil_images[i].save(os.path.join(full_output_folder, file), save_all=True, duration=int(1000.0/fps), append_images=pil_images[i + 1:i + num_frames], lossless=False, quality=80, method=4)
|
||||||
|
results.append({
|
||||||
|
"filename": file,
|
||||||
|
"subfolder": subfolder,
|
||||||
|
"type": self.type
|
||||||
|
})
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
animated = num_frames != 1
|
||||||
|
return { "ui": { "images": results, "animated": (animated,), "text": [f"{num_frames}x{pil_images[0].size[0]}x{pil_images[0].size[1]}"] } }
|
||||||
@@ -113,6 +113,24 @@ app.registerExtension({
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "PreviewAnimation":
|
||||||
|
const onPreviewAnimationConnectInput = nodeType.prototype.onConnectInput;
|
||||||
|
nodeType.prototype.onConnectInput = function (targetSlot, type, output, originNode, originSlot) {
|
||||||
|
const v = onPreviewAnimationConnectInput?.(this, arguments);
|
||||||
|
targetSlot.title = "Preview Animation"
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
const onPreviewAnimationExecuted = nodeType.prototype.onExecuted;
|
||||||
|
nodeType.prototype.onExecuted = function(message) {
|
||||||
|
const r = onPreviewAnimationExecuted? onPreviewAnimationExecuted.apply(this,arguments): undefined
|
||||||
|
let values = message["text"].toString();
|
||||||
|
console.log(this)
|
||||||
|
this.title = "Preview Animation " + values
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case "VRAM_Debug":
|
case "VRAM_Debug":
|
||||||
const onVRAM_DebugConnectInput = nodeType.prototype.onConnectInput;
|
const onVRAM_DebugConnectInput = nodeType.prototype.onConnectInput;
|
||||||
nodeType.prototype.onConnectInput = function (targetSlot, type, output, originNode, originSlot) {
|
nodeType.prototype.onConnectInput = function (targetSlot, type, output, originNode, originSlot) {
|
||||||
|
|||||||
+115
-13
@@ -176,26 +176,40 @@ app.registerExtension({
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.body.appendChild( this.contextMenu);
|
document.body.appendChild( this.contextMenu);
|
||||||
|
this.editor = new SplineEditor(this);
|
||||||
|
|
||||||
this.addWidget("button", "New spline", null, () => {
|
this.addWidget("button", "New spline", null, () => {
|
||||||
if (!this.properties || !("points" in this.properties)) {
|
if (!this.properties || !("points" in this.properties)) {
|
||||||
createSplineEditor(this)
|
|
||||||
|
this.editor.createEditor(false);
|
||||||
this.addProperty("points", this.constructor.type, "string");
|
this.addProperty("points", this.constructor.type, "string");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
createSplineEditor(this, true)
|
this.editor.createEditor(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setSize([550, 920]);
|
this.setSize([550, 950]);
|
||||||
this.resizable = false;
|
this.resizable = false;
|
||||||
this.splineEditor.parentEl = document.createElement("div");
|
this.splineEditor.parentEl = document.createElement("div");
|
||||||
this.splineEditor.parentEl.className = "spline-editor";
|
this.splineEditor.parentEl.className = "spline-editor";
|
||||||
this.splineEditor.parentEl.id = `spline-editor-${this.uuid}`
|
this.splineEditor.parentEl.id = `spline-editor-${this.uuid}`
|
||||||
element.appendChild(this.splineEditor.parentEl);
|
element.appendChild(this.splineEditor.parentEl);
|
||||||
|
console.log(this)
|
||||||
chainCallback(this, "onConfigure", function() {
|
chainCallback(this, "onGraphConfigured", function() {
|
||||||
createSplineEditor(this);
|
this.editor.createEditor();
|
||||||
|
});
|
||||||
|
chainCallback(this, "onConnectInput", function(targetSlot, type, output, originNode, originSlot) {
|
||||||
|
// console.log("INPUT CONNECTED")
|
||||||
|
// console.log(targetSlot, type, output, originNode, originSlot)
|
||||||
|
// console.log("ORIGINNODE: ",originNode)
|
||||||
|
this.editor.syncEditors(originNode, "input");
|
||||||
|
});
|
||||||
|
chainCallback(this, "onConnectOutput", function(slot, type, input, target_node, target_slot) {
|
||||||
|
// console.log("OUTPUT CONNECTED")
|
||||||
|
// console.log(slot, type, input, target_node, target_slot)
|
||||||
|
// console.log("TARGETNODE: ",target_node)
|
||||||
|
this.editor.syncEditors(target_node, "output");
|
||||||
});
|
});
|
||||||
|
|
||||||
}); // onAfterGraphConfigured
|
}); // onAfterGraphConfigured
|
||||||
@@ -203,8 +217,14 @@ app.registerExtension({
|
|||||||
} //before register
|
} //before register
|
||||||
})//register
|
})//register
|
||||||
|
|
||||||
|
class SplineEditor {
|
||||||
function createSplineEditor(context, reset=false) {
|
constructor(context) {
|
||||||
|
this.context = context;
|
||||||
|
this.vis = null;
|
||||||
|
this.extraLineLayers = {};
|
||||||
|
}
|
||||||
|
createEditor(reset=false) {
|
||||||
|
var context = this.context
|
||||||
console.log("creatingSplineEditor")
|
console.log("creatingSplineEditor")
|
||||||
|
|
||||||
// context menu
|
// context menu
|
||||||
@@ -332,6 +352,7 @@ function createSplineEditor(context, reset=false) {
|
|||||||
if (coordWidget) {
|
if (coordWidget) {
|
||||||
coordWidget.value = coordsString;
|
coordWidget.value = coordsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
vis.render();
|
vis.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,14 +369,17 @@ function createSplineEditor(context, reset=false) {
|
|||||||
const samplingMethodWidget = context.widgets.find(w => w.name === "sampling_method");
|
const samplingMethodWidget = context.widgets.find(w => w.name === "sampling_method");
|
||||||
const widthWidget = context.widgets.find(w => w.name === "mask_width");
|
const widthWidget = context.widgets.find(w => w.name === "mask_width");
|
||||||
const heightWidget = context.widgets.find(w => w.name === "mask_height");
|
const heightWidget = context.widgets.find(w => w.name === "mask_height");
|
||||||
//const segmentedWidget = context.widgets.find(w => w.name === "segmented");
|
|
||||||
|
|
||||||
|
let linkedInputEditorPointsToSample = null
|
||||||
|
let linkedOutputEditorPointsToSample = null
|
||||||
|
|
||||||
|
var points_to_sample = pointsWidget.value
|
||||||
var interpolation = interpolationWidget.value
|
var interpolation = interpolationWidget.value
|
||||||
var tension = tensionWidget.value
|
var tension = tensionWidget.value
|
||||||
var points_to_sample = pointsWidget.value
|
|
||||||
var rangeMin = minValueWidget.value
|
var rangeMin = minValueWidget.value
|
||||||
var rangeMax = maxValueWidget.value
|
var rangeMax = maxValueWidget.value
|
||||||
var pointsLayer = null;
|
var pointsLayer = null;
|
||||||
|
var extraLineLayer = null;
|
||||||
var samplingMethod = samplingMethodWidget.value
|
var samplingMethod = samplingMethodWidget.value
|
||||||
|
|
||||||
if (samplingMethod == "path") {
|
if (samplingMethod == "path") {
|
||||||
@@ -378,7 +402,21 @@ function createSplineEditor(context, reset=false) {
|
|||||||
updatePath();
|
updatePath();
|
||||||
}
|
}
|
||||||
pointsWidget.callback = () => {
|
pointsWidget.callback = () => {
|
||||||
|
let linkedInputEditor = context.getInputNode(0)
|
||||||
|
let linkedOutputEditor = context.getOutputNodes(4)
|
||||||
|
if (linkedOutputEditor != null) {
|
||||||
|
linkedOutputEditorPointsToSample = linkedOutputEditor[0].widgets.find(w => w.name === "points_to_sample")
|
||||||
|
linkedOutputEditorPointsToSample.value = pointsWidget.value
|
||||||
points_to_sample = pointsWidget.value
|
points_to_sample = pointsWidget.value
|
||||||
|
}
|
||||||
|
if (linkedInputEditor != null) {
|
||||||
|
linkedInputEditorPointsToSample = linkedInputEditor.widgets.find(w => w.name === "points_to_sample")
|
||||||
|
linkedInputEditorPointsToSample.value = pointsWidget.value
|
||||||
|
points_to_sample = pointsWidget.value
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
points_to_sample = pointsWidget.value
|
||||||
|
}
|
||||||
updatePath();
|
updatePath();
|
||||||
}
|
}
|
||||||
minValueWidget.callback = () => {
|
minValueWidget.callback = () => {
|
||||||
@@ -414,9 +452,12 @@ function createSplineEditor(context, reset=false) {
|
|||||||
var h = heightWidget.value;
|
var h = heightWidget.value;
|
||||||
var i = 3;
|
var i = 3;
|
||||||
let points = [];
|
let points = [];
|
||||||
|
let splineColor = null;
|
||||||
|
|
||||||
if (!reset && pointsStoreWidget.value != "") {
|
if (!reset && pointsStoreWidget.value != "") {
|
||||||
points = JSON.parse(pointsStoreWidget.value);
|
points = JSON.parse(pointsStoreWidget.value);
|
||||||
|
splineColor = context.properties.spline_color["color"]
|
||||||
|
console.log(splineColor["color"])
|
||||||
} else {
|
} else {
|
||||||
points = pv.range(1, 4).map((i, index) => {
|
points = pv.range(1, 4).map((i, index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
@@ -433,7 +474,20 @@ function createSplineEditor(context, reset=false) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
pointsStoreWidget.value = JSON.stringify(points);
|
pointsStoreWidget.value = JSON.stringify(points)
|
||||||
|
|
||||||
|
context.properties.points = JSON.stringify(points)
|
||||||
|
if (!splineColor) {
|
||||||
|
let colors = pv.Colors.category10().range()
|
||||||
|
splineColor = colors[Math.floor(Math.random() * pv.Colors.category10().range().length)]
|
||||||
|
context.addProperty("spline_color", splineColor, pv.Colors)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
splineColor = context.properties.spline_color
|
||||||
|
console.log(splineColor["color"])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var vis = new pv.Panel()
|
var vis = new pv.Panel()
|
||||||
@@ -502,7 +556,7 @@ function createSplineEditor(context, reset=false) {
|
|||||||
.interpolate(() => interpolation)
|
.interpolate(() => interpolation)
|
||||||
.tension(() => tension)
|
.tension(() => tension)
|
||||||
.segmented(() => false)
|
.segmented(() => false)
|
||||||
.strokeStyle(pv.Colors.category10().by(pv.index))
|
.strokeStyle(splineColor)
|
||||||
.lineWidth(3)
|
.lineWidth(3)
|
||||||
|
|
||||||
vis.add(pv.Dot)
|
vis.add(pv.Dot)
|
||||||
@@ -556,7 +610,13 @@ function createSplineEditor(context, reset=false) {
|
|||||||
})
|
})
|
||||||
.event("dragend", function() {
|
.event("dragend", function() {
|
||||||
if (this.pathElements !== null) {
|
if (this.pathElements !== null) {
|
||||||
|
context.editor.syncEditors(context.getInputNode(0))
|
||||||
|
let outputEditor = context.getOutputNodes(4);
|
||||||
|
if (outputEditor !== null){
|
||||||
|
context.editor.syncEditors(outputEditor[0]) }
|
||||||
updatePath();
|
updatePath();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
})
|
})
|
||||||
@@ -607,9 +667,51 @@ function createSplineEditor(context, reset=false) {
|
|||||||
svgElement.style['position'] = "relative"
|
svgElement.style['position'] = "relative"
|
||||||
context.splineEditor.element.appendChild(svgElement);
|
context.splineEditor.element.appendChild(svgElement);
|
||||||
var pathElements = svgElement.getElementsByTagName('path'); // Get all path elements
|
var pathElements = svgElement.getElementsByTagName('path'); // Get all path elements
|
||||||
|
|
||||||
updatePath();
|
updatePath();
|
||||||
|
this.vis = vis
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncEditors(node, connectionType) {
|
||||||
|
if (node == null) return
|
||||||
|
let linkedEditor = node
|
||||||
|
|
||||||
|
if (linkedEditor != null) {
|
||||||
|
let linkedPointsWidget = linkedEditor.widgets.find(w => w.name === "points_store")
|
||||||
|
let linkedCoords = JSON.parse(linkedPointsWidget.value)
|
||||||
|
|
||||||
|
// Initialize linkedNodes if it doesn't already exist
|
||||||
|
if (!node.hasOwnProperty("linkedNodes")) {
|
||||||
|
node["linkedNodes"] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
node["linkedNodes"][this.context.id] = linkedCoords;
|
||||||
|
|
||||||
|
if (Array.isArray(linkedCoords)) {
|
||||||
|
// Check if a layer for this node ID already exists
|
||||||
|
if (!this.extraLineLayers.hasOwnProperty(node.id)) {
|
||||||
|
// Create a new layer for this node ID if it doesn't exist
|
||||||
|
this.extraLineLayers[node.id] = this.vis.add(pv.Line)
|
||||||
|
.data(linkedCoords)
|
||||||
|
.left(d => d.x)
|
||||||
|
.top(d => d.y)
|
||||||
|
.interpolate(() => node.widgets.find(w => w.name === "interpolation").value)
|
||||||
|
.tension(() => node.widgets.find(w => w.name === "tension").value)
|
||||||
|
.segmented(() => false)
|
||||||
|
.strokeStyle(node.properties.spline_color["color"])
|
||||||
|
.lineWidth(3);
|
||||||
|
} else {
|
||||||
|
// If the layer already exists, update its data
|
||||||
|
this.extraLineLayers[node.id].data(linkedCoords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.vis.render()
|
||||||
|
}
|
||||||
|
}//syncEditors
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
function samplePoints(svgPathElement, numSamples, samplingMethod, width) {
|
function samplePoints(svgPathElement, numSamples, samplingMethod, width) {
|
||||||
var svgWidth = width; // Fixed width of the SVG element
|
var svgWidth = width; // Fixed width of the SVG element
|
||||||
var pathLength = svgPathElement.getTotalLength();
|
var pathLength = svgPathElement.getTotalLength();
|
||||||
@@ -683,7 +785,7 @@ function findPointAtX(svgPathElement, targetX, pathLength) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//from melmass
|
//from melmass
|
||||||
export function hideWidgetForGood(node, widget, suffix = '') {
|
function hideWidgetForGood(node, widget, suffix = '') {
|
||||||
widget.origType = widget.type
|
widget.origType = widget.type
|
||||||
widget.origComputeSize = widget.computeSize
|
widget.origComputeSize = widget.computeSize
|
||||||
widget.origSerializeValue = widget.serializeValue
|
widget.origSerializeValue = widget.serializeValue
|
||||||
|
|||||||
Reference in New Issue
Block a user