mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
897 lines
25 KiB
JavaScript
Executable File
897 lines
25 KiB
JavaScript
Executable File
(function(global) {
|
|
var LiteGraph = global.LiteGraph;
|
|
|
|
function GraphicsPlot() {
|
|
this.addInput("A", "Number");
|
|
this.addInput("B", "Number");
|
|
this.addInput("C", "Number");
|
|
this.addInput("D", "Number");
|
|
|
|
this.values = [[], [], [], []];
|
|
this.properties = { scale: 2 };
|
|
}
|
|
|
|
GraphicsPlot.title = "Plot";
|
|
GraphicsPlot.desc = "Plots data over time";
|
|
GraphicsPlot.colors = ["#FFF", "#F99", "#9F9", "#99F"];
|
|
|
|
GraphicsPlot.prototype.onExecute = function(ctx) {
|
|
if (this.flags.collapsed) {
|
|
return;
|
|
}
|
|
|
|
var size = this.size;
|
|
|
|
for (var i = 0; i < 4; ++i) {
|
|
var v = this.getInputData(i);
|
|
if (v == null) {
|
|
continue;
|
|
}
|
|
var values = this.values[i];
|
|
values.push(v);
|
|
if (values.length > size[0]) {
|
|
values.shift();
|
|
}
|
|
}
|
|
};
|
|
|
|
GraphicsPlot.prototype.onDrawBackground = function(ctx) {
|
|
if (this.flags.collapsed) {
|
|
return;
|
|
}
|
|
|
|
var size = this.size;
|
|
|
|
var scale = (0.5 * size[1]) / this.properties.scale;
|
|
var colors = GraphicsPlot.colors;
|
|
var offset = size[1] * 0.5;
|
|
|
|
ctx.fillStyle = "#000";
|
|
ctx.fillRect(0, 0, size[0], size[1]);
|
|
ctx.strokeStyle = "#555";
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, offset);
|
|
ctx.lineTo(size[0], offset);
|
|
ctx.stroke();
|
|
|
|
if (this.inputs) {
|
|
for (var i = 0; i < 4; ++i) {
|
|
var values = this.values[i];
|
|
if (!this.inputs[i] || !this.inputs[i].link) {
|
|
continue;
|
|
}
|
|
ctx.strokeStyle = colors[i];
|
|
ctx.beginPath();
|
|
var v = values[0] * scale * -1 + offset;
|
|
ctx.moveTo(0, Math.clamp(v, 0, size[1]));
|
|
for (var j = 1; j < values.length && j < size[0]; ++j) {
|
|
var v = values[j] * scale * -1 + offset;
|
|
ctx.lineTo(j, Math.clamp(v, 0, size[1]));
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/plot", GraphicsPlot);
|
|
|
|
function GraphicsImage() {
|
|
this.addOutput("frame", "image");
|
|
this.properties = { url: "" };
|
|
}
|
|
|
|
GraphicsImage.title = "Image";
|
|
GraphicsImage.desc = "Image loader";
|
|
GraphicsImage.widgets = [{ name: "load", text: "Load", type: "button" }];
|
|
|
|
GraphicsImage.supported_extensions = ["jpg", "jpeg", "png", "gif"];
|
|
|
|
GraphicsImage.prototype.onAdded = function() {
|
|
if (this.properties["url"] != "" && this.img == null) {
|
|
this.loadImage(this.properties["url"]);
|
|
}
|
|
};
|
|
|
|
GraphicsImage.prototype.onDrawBackground = function(ctx) {
|
|
if (this.flags.collapsed) {
|
|
return;
|
|
}
|
|
if (this.img && this.size[0] > 5 && this.size[1] > 5 && this.img.width) {
|
|
ctx.drawImage(this.img, 0, 0, this.size[0], this.size[1]);
|
|
}
|
|
};
|
|
|
|
GraphicsImage.prototype.onExecute = function() {
|
|
if (!this.img) {
|
|
this.boxcolor = "#000";
|
|
}
|
|
if (this.img && this.img.width) {
|
|
this.setOutputData(0, this.img);
|
|
} else {
|
|
this.setOutputData(0, null);
|
|
}
|
|
if (this.img && this.img.dirty) {
|
|
this.img.dirty = false;
|
|
}
|
|
};
|
|
|
|
GraphicsImage.prototype.onPropertyChanged = function(name, value) {
|
|
this.properties[name] = value;
|
|
if (name == "url" && value != "") {
|
|
this.loadImage(value);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
GraphicsImage.prototype.loadImage = function(url, callback) {
|
|
if (url == "") {
|
|
this.img = null;
|
|
return;
|
|
}
|
|
|
|
this.img = document.createElement("img");
|
|
|
|
if (url.substr(0, 4) == "http" && LiteGraph.proxy) {
|
|
url = LiteGraph.proxy + url.substr(url.indexOf(":") + 3);
|
|
}
|
|
|
|
this.img.src = url;
|
|
this.boxcolor = "#F95";
|
|
var that = this;
|
|
this.img.onload = function() {
|
|
if (callback) {
|
|
callback(this);
|
|
}
|
|
console.log( "Image loaded, size: " + that.img.width + "x" + that.img.height );
|
|
this.dirty = true;
|
|
that.boxcolor = "#9F9";
|
|
that.setDirtyCanvas(true);
|
|
};
|
|
this.img.onerror = function() {
|
|
console.log("error loading the image:" + url);
|
|
}
|
|
};
|
|
|
|
GraphicsImage.prototype.onWidget = function(e, widget) {
|
|
if (widget.name == "load") {
|
|
this.loadImage(this.properties["url"]);
|
|
}
|
|
};
|
|
|
|
GraphicsImage.prototype.onDropFile = function(file) {
|
|
var that = this;
|
|
if (this._url) {
|
|
URL.revokeObjectURL(this._url);
|
|
}
|
|
this._url = URL.createObjectURL(file);
|
|
this.properties.url = this._url;
|
|
this.loadImage(this._url, function(img) {
|
|
that.size[1] = (img.height / img.width) * that.size[0];
|
|
});
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/image", GraphicsImage);
|
|
|
|
function ColorPalette() {
|
|
this.addInput("f", "number");
|
|
this.addOutput("Color", "color");
|
|
this.properties = {
|
|
colorA: "#444444",
|
|
colorB: "#44AAFF",
|
|
colorC: "#44FFAA",
|
|
colorD: "#FFFFFF"
|
|
};
|
|
}
|
|
|
|
ColorPalette.title = "Palette";
|
|
ColorPalette.desc = "Generates a color";
|
|
|
|
ColorPalette.prototype.onExecute = function() {
|
|
var c = [];
|
|
|
|
if (this.properties.colorA != null) {
|
|
c.push(hex2num(this.properties.colorA));
|
|
}
|
|
if (this.properties.colorB != null) {
|
|
c.push(hex2num(this.properties.colorB));
|
|
}
|
|
if (this.properties.colorC != null) {
|
|
c.push(hex2num(this.properties.colorC));
|
|
}
|
|
if (this.properties.colorD != null) {
|
|
c.push(hex2num(this.properties.colorD));
|
|
}
|
|
|
|
var f = this.getInputData(0);
|
|
if (f == null) {
|
|
f = 0.5;
|
|
}
|
|
if (f > 1.0) {
|
|
f = 1.0;
|
|
} else if (f < 0.0) {
|
|
f = 0.0;
|
|
}
|
|
|
|
if (c.length == 0) {
|
|
return;
|
|
}
|
|
|
|
var result = [0, 0, 0];
|
|
if (f == 0) {
|
|
result = c[0];
|
|
} else if (f == 1) {
|
|
result = c[c.length - 1];
|
|
} else {
|
|
var pos = (c.length - 1) * f;
|
|
var c1 = c[Math.floor(pos)];
|
|
var c2 = c[Math.floor(pos) + 1];
|
|
var t = pos - Math.floor(pos);
|
|
result[0] = c1[0] * (1 - t) + c2[0] * t;
|
|
result[1] = c1[1] * (1 - t) + c2[1] * t;
|
|
result[2] = c1[2] * (1 - t) + c2[2] * t;
|
|
}
|
|
|
|
/*
|
|
c[0] = 1.0 - Math.abs( Math.sin( 0.1 * reModular.getTime() * Math.PI) );
|
|
c[1] = Math.abs( Math.sin( 0.07 * reModular.getTime() * Math.PI) );
|
|
c[2] = Math.abs( Math.sin( 0.01 * reModular.getTime() * Math.PI) );
|
|
*/
|
|
|
|
for (var i in result) {
|
|
result[i] /= 255;
|
|
}
|
|
|
|
this.boxcolor = colorToString(result);
|
|
this.setOutputData(0, result);
|
|
};
|
|
|
|
LiteGraph.registerNodeType("color/palette", ColorPalette);
|
|
|
|
function ImageFrame() {
|
|
this.addInput("", "image,canvas");
|
|
this.size = [200, 200];
|
|
}
|
|
|
|
ImageFrame.title = "Frame";
|
|
ImageFrame.desc = "Frame viewerew";
|
|
ImageFrame.widgets = [
|
|
{ name: "resize", text: "Resize box", type: "button" },
|
|
{ name: "view", text: "View Image", type: "button" }
|
|
];
|
|
|
|
ImageFrame.prototype.onDrawBackground = function(ctx) {
|
|
if (this.frame && !this.flags.collapsed) {
|
|
ctx.drawImage(this.frame, 0, 0, this.size[0], this.size[1]);
|
|
}
|
|
};
|
|
|
|
ImageFrame.prototype.onExecute = function() {
|
|
this.frame = this.getInputData(0);
|
|
this.setDirtyCanvas(true);
|
|
};
|
|
|
|
ImageFrame.prototype.onWidget = function(e, widget) {
|
|
if (widget.name == "resize" && this.frame) {
|
|
var width = this.frame.width;
|
|
var height = this.frame.height;
|
|
|
|
if (!width && this.frame.videoWidth != null) {
|
|
width = this.frame.videoWidth;
|
|
height = this.frame.videoHeight;
|
|
}
|
|
|
|
if (width && height) {
|
|
this.size = [width, height];
|
|
}
|
|
this.setDirtyCanvas(true, true);
|
|
} else if (widget.name == "view") {
|
|
this.show();
|
|
}
|
|
};
|
|
|
|
ImageFrame.prototype.show = function() {
|
|
//var str = this.canvas.toDataURL("image/png");
|
|
if (showElement && this.frame) {
|
|
showElement(this.frame);
|
|
}
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/frame", ImageFrame);
|
|
|
|
function ImageFade() {
|
|
this.addInputs([
|
|
["img1", "image"],
|
|
["img2", "image"],
|
|
["fade", "number"]
|
|
]);
|
|
this.addOutput("", "image");
|
|
this.properties = { fade: 0.5, width: 512, height: 512 };
|
|
}
|
|
|
|
ImageFade.title = "Image fade";
|
|
ImageFade.desc = "Fades between images";
|
|
ImageFade.widgets = [
|
|
{ name: "resizeA", text: "Resize to A", type: "button" },
|
|
{ name: "resizeB", text: "Resize to B", type: "button" }
|
|
];
|
|
|
|
ImageFade.prototype.onAdded = function() {
|
|
this.createCanvas();
|
|
var ctx = this.canvas.getContext("2d");
|
|
ctx.fillStyle = "#000";
|
|
ctx.fillRect(0, 0, this.properties["width"], this.properties["height"]);
|
|
};
|
|
|
|
ImageFade.prototype.createCanvas = function() {
|
|
this.canvas = document.createElement("canvas");
|
|
this.canvas.width = this.properties["width"];
|
|
this.canvas.height = this.properties["height"];
|
|
};
|
|
|
|
ImageFade.prototype.onExecute = function() {
|
|
var ctx = this.canvas.getContext("2d");
|
|
this.canvas.width = this.canvas.width;
|
|
|
|
var A = this.getInputData(0);
|
|
if (A != null) {
|
|
ctx.drawImage(A, 0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
|
|
var fade = this.getInputData(2);
|
|
if (fade == null) {
|
|
fade = this.properties["fade"];
|
|
} else {
|
|
this.properties["fade"] = fade;
|
|
}
|
|
|
|
ctx.globalAlpha = fade;
|
|
var B = this.getInputData(1);
|
|
if (B != null) {
|
|
ctx.drawImage(B, 0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
ctx.globalAlpha = 1.0;
|
|
|
|
this.setOutputData(0, this.canvas);
|
|
this.setDirtyCanvas(true);
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/imagefade", ImageFade);
|
|
|
|
function ImageCrop() {
|
|
this.addInput("", "image");
|
|
this.addOutput("", "image");
|
|
this.properties = { width: 256, height: 256, x: 0, y: 0, scale: 1.0 };
|
|
this.size = [50, 20];
|
|
}
|
|
|
|
ImageCrop.title = "Crop";
|
|
ImageCrop.desc = "Crop Image";
|
|
|
|
ImageCrop.prototype.onAdded = function() {
|
|
this.createCanvas();
|
|
};
|
|
|
|
ImageCrop.prototype.createCanvas = function() {
|
|
this.canvas = document.createElement("canvas");
|
|
this.canvas.width = this.properties["width"];
|
|
this.canvas.height = this.properties["height"];
|
|
};
|
|
|
|
ImageCrop.prototype.onExecute = function() {
|
|
var input = this.getInputData(0);
|
|
if (!input) {
|
|
return;
|
|
}
|
|
|
|
if (input.width) {
|
|
var ctx = this.canvas.getContext("2d");
|
|
|
|
ctx.drawImage(
|
|
input,
|
|
-this.properties["x"],
|
|
-this.properties["y"],
|
|
input.width * this.properties["scale"],
|
|
input.height * this.properties["scale"]
|
|
);
|
|
this.setOutputData(0, this.canvas);
|
|
} else {
|
|
this.setOutputData(0, null);
|
|
}
|
|
};
|
|
|
|
ImageCrop.prototype.onDrawBackground = function(ctx) {
|
|
if (this.flags.collapsed) {
|
|
return;
|
|
}
|
|
if (this.canvas) {
|
|
ctx.drawImage(
|
|
this.canvas,
|
|
0,
|
|
0,
|
|
this.canvas.width,
|
|
this.canvas.height,
|
|
0,
|
|
0,
|
|
this.size[0],
|
|
this.size[1]
|
|
);
|
|
}
|
|
};
|
|
|
|
ImageCrop.prototype.onPropertyChanged = function(name, value) {
|
|
this.properties[name] = value;
|
|
|
|
if (name == "scale") {
|
|
this.properties[name] = parseFloat(value);
|
|
if (this.properties[name] == 0) {
|
|
console.error("Error in scale");
|
|
this.properties[name] = 1.0;
|
|
}
|
|
} else {
|
|
this.properties[name] = parseInt(value);
|
|
}
|
|
|
|
this.createCanvas();
|
|
|
|
return true;
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/cropImage", ImageCrop);
|
|
|
|
//CANVAS stuff
|
|
|
|
function CanvasNode() {
|
|
this.addInput("clear", LiteGraph.ACTION);
|
|
this.addOutput("", "canvas");
|
|
this.properties = { width: 512, height: 512, autoclear: true };
|
|
|
|
this.canvas = document.createElement("canvas");
|
|
this.ctx = this.canvas.getContext("2d");
|
|
}
|
|
|
|
CanvasNode.title = "Canvas";
|
|
CanvasNode.desc = "Canvas to render stuff";
|
|
|
|
CanvasNode.prototype.onExecute = function() {
|
|
var canvas = this.canvas;
|
|
var w = this.properties.width | 0;
|
|
var h = this.properties.height | 0;
|
|
if (canvas.width != w) {
|
|
canvas.width = w;
|
|
}
|
|
if (canvas.height != h) {
|
|
canvas.height = h;
|
|
}
|
|
|
|
if (this.properties.autoclear) {
|
|
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
}
|
|
this.setOutputData(0, canvas);
|
|
};
|
|
|
|
CanvasNode.prototype.onAction = function(action, param) {
|
|
if (action == "clear") {
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/canvas", CanvasNode);
|
|
|
|
function DrawImageNode() {
|
|
this.addInput("canvas", "canvas");
|
|
this.addInput("img", "image,canvas");
|
|
this.addInput("x", "number");
|
|
this.addInput("y", "number");
|
|
this.properties = { x: 0, y: 0, opacity: 1 };
|
|
}
|
|
|
|
DrawImageNode.title = "DrawImage";
|
|
DrawImageNode.desc = "Draws image into a canvas";
|
|
|
|
DrawImageNode.prototype.onExecute = function() {
|
|
var canvas = this.getInputData(0);
|
|
if (!canvas) {
|
|
return;
|
|
}
|
|
|
|
var img = this.getInputOrProperty("img");
|
|
if (!img) {
|
|
return;
|
|
}
|
|
|
|
var x = this.getInputOrProperty("x");
|
|
var y = this.getInputOrProperty("y");
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.drawImage(img, x, y);
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/drawImage", DrawImageNode);
|
|
|
|
function DrawRectangleNode() {
|
|
this.addInput("canvas", "canvas");
|
|
this.addInput("x", "number");
|
|
this.addInput("y", "number");
|
|
this.addInput("w", "number");
|
|
this.addInput("h", "number");
|
|
this.properties = {
|
|
x: 0,
|
|
y: 0,
|
|
w: 10,
|
|
h: 10,
|
|
color: "white",
|
|
opacity: 1
|
|
};
|
|
}
|
|
|
|
DrawRectangleNode.title = "DrawRectangle";
|
|
DrawRectangleNode.desc = "Draws rectangle in canvas";
|
|
|
|
DrawRectangleNode.prototype.onExecute = function() {
|
|
var canvas = this.getInputData(0);
|
|
if (!canvas) {
|
|
return;
|
|
}
|
|
|
|
var x = this.getInputOrProperty("x");
|
|
var y = this.getInputOrProperty("y");
|
|
var w = this.getInputOrProperty("w");
|
|
var h = this.getInputOrProperty("h");
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.fillRect(x, y, w, h);
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/drawRectangle", DrawRectangleNode);
|
|
|
|
function ImageVideo() {
|
|
this.addInput("t", "number");
|
|
this.addOutputs([["frame", "image"], ["t", "number"], ["d", "number"]]);
|
|
this.properties = { url: "", use_proxy: true };
|
|
}
|
|
|
|
ImageVideo.title = "Video";
|
|
ImageVideo.desc = "Video playback";
|
|
ImageVideo.widgets = [
|
|
{ name: "play", text: "PLAY", type: "minibutton" },
|
|
{ name: "stop", text: "STOP", type: "minibutton" },
|
|
{ name: "demo", text: "Demo video", type: "button" },
|
|
{ name: "mute", text: "Mute video", type: "button" }
|
|
];
|
|
|
|
ImageVideo.prototype.onExecute = function() {
|
|
if (!this.properties.url) {
|
|
return;
|
|
}
|
|
|
|
if (this.properties.url != this._video_url) {
|
|
this.loadVideo(this.properties.url);
|
|
}
|
|
|
|
if (!this._video || this._video.width == 0) {
|
|
return;
|
|
}
|
|
|
|
var t = this.getInputData(0);
|
|
if (t && t >= 0 && t <= 1.0) {
|
|
this._video.currentTime = t * this._video.duration;
|
|
this._video.pause();
|
|
}
|
|
|
|
this._video.dirty = true;
|
|
this.setOutputData(0, this._video);
|
|
this.setOutputData(1, this._video.currentTime);
|
|
this.setOutputData(2, this._video.duration);
|
|
this.setDirtyCanvas(true);
|
|
};
|
|
|
|
ImageVideo.prototype.onStart = function() {
|
|
this.play();
|
|
};
|
|
|
|
ImageVideo.prototype.onStop = function() {
|
|
this.stop();
|
|
};
|
|
|
|
ImageVideo.prototype.loadVideo = function(url) {
|
|
this._video_url = url;
|
|
|
|
var pos = url.substr(0,10).indexOf(":");
|
|
var protocol = "";
|
|
if(pos != -1)
|
|
protocol = url.substr(0,pos);
|
|
|
|
var host = "";
|
|
if(protocol)
|
|
{
|
|
host = url.substr(0,url.indexOf("/",protocol.length + 3));
|
|
host = host.substr(protocol.length+3);
|
|
}
|
|
|
|
if (
|
|
this.properties.use_proxy &&
|
|
protocol &&
|
|
LiteGraph.proxy &&
|
|
host != location.host
|
|
) {
|
|
url = LiteGraph.proxy + url.substr(url.indexOf(":") + 3);
|
|
}
|
|
|
|
this._video = document.createElement("video");
|
|
this._video.src = url;
|
|
this._video.type = "type=video/mp4";
|
|
|
|
this._video.muted = true;
|
|
this._video.autoplay = true;
|
|
|
|
var that = this;
|
|
this._video.addEventListener("loadedmetadata", function(e) {
|
|
//onload
|
|
console.log("Duration: " + this.duration + " seconds");
|
|
console.log("Size: " + this.videoWidth + "," + this.videoHeight);
|
|
that.setDirtyCanvas(true);
|
|
this.width = this.videoWidth;
|
|
this.height = this.videoHeight;
|
|
});
|
|
this._video.addEventListener("progress", function(e) {
|
|
//onload
|
|
console.log("video loading...");
|
|
});
|
|
this._video.addEventListener("error", function(e) {
|
|
console.error("Error loading video: " + this.src);
|
|
if (this.error) {
|
|
switch (this.error.code) {
|
|
case this.error.MEDIA_ERR_ABORTED:
|
|
console.error("You stopped the video.");
|
|
break;
|
|
case this.error.MEDIA_ERR_NETWORK:
|
|
console.error("Network error - please try again later.");
|
|
break;
|
|
case this.error.MEDIA_ERR_DECODE:
|
|
console.error("Video is broken..");
|
|
break;
|
|
case this.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
|
|
console.error("Sorry, your browser can't play this video.");
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
|
|
this._video.addEventListener("ended", function(e) {
|
|
console.log("Video Ended.");
|
|
this.play(); //loop
|
|
});
|
|
|
|
//document.body.appendChild(this.video);
|
|
};
|
|
|
|
ImageVideo.prototype.onPropertyChanged = function(name, value) {
|
|
this.properties[name] = value;
|
|
if (name == "url" && value != "") {
|
|
this.loadVideo(value);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
ImageVideo.prototype.play = function() {
|
|
if (this._video && this._video.videoWidth ) { //is loaded
|
|
this._video.play();
|
|
}
|
|
};
|
|
|
|
ImageVideo.prototype.playPause = function() {
|
|
if (!this._video) {
|
|
return;
|
|
}
|
|
if (this._video.paused) {
|
|
this.play();
|
|
} else {
|
|
this.pause();
|
|
}
|
|
};
|
|
|
|
ImageVideo.prototype.stop = function() {
|
|
if (!this._video) {
|
|
return;
|
|
}
|
|
this._video.pause();
|
|
this._video.currentTime = 0;
|
|
};
|
|
|
|
ImageVideo.prototype.pause = function() {
|
|
if (!this._video) {
|
|
return;
|
|
}
|
|
console.log("Video paused");
|
|
this._video.pause();
|
|
};
|
|
|
|
ImageVideo.prototype.onWidget = function(e, widget) {
|
|
/*
|
|
if(widget.name == "demo")
|
|
{
|
|
this.loadVideo();
|
|
}
|
|
else if(widget.name == "play")
|
|
{
|
|
if(this._video)
|
|
this.playPause();
|
|
}
|
|
if(widget.name == "stop")
|
|
{
|
|
this.stop();
|
|
}
|
|
else if(widget.name == "mute")
|
|
{
|
|
if(this._video)
|
|
this._video.muted = !this._video.muted;
|
|
}
|
|
*/
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/video", ImageVideo);
|
|
|
|
// Texture Webcam *****************************************
|
|
function ImageWebcam() {
|
|
this.addOutput("Webcam", "image");
|
|
this.properties = { facingMode: "user" };
|
|
this.boxcolor = "black";
|
|
this.frame = 0;
|
|
}
|
|
|
|
ImageWebcam.title = "Webcam";
|
|
ImageWebcam.desc = "Webcam image";
|
|
ImageWebcam.is_webcam_open = false;
|
|
|
|
ImageWebcam.prototype.openStream = function() {
|
|
if (!navigator.getUserMedia) {
|
|
//console.log('getUserMedia() is not supported in your browser, use chrome and enable WebRTC from about://flags');
|
|
return;
|
|
}
|
|
|
|
this._waiting_confirmation = true;
|
|
|
|
// Not showing vendor prefixes.
|
|
var constraints = {
|
|
audio: false,
|
|
video: { facingMode: this.properties.facingMode }
|
|
};
|
|
navigator.mediaDevices
|
|
.getUserMedia(constraints)
|
|
.then(this.streamReady.bind(this))
|
|
.catch(onFailSoHard);
|
|
|
|
var that = this;
|
|
function onFailSoHard(e) {
|
|
console.log("Webcam rejected", e);
|
|
that._webcam_stream = false;
|
|
ImageWebcam.is_webcam_open = false;
|
|
that.boxcolor = "red";
|
|
that.trigger("stream_error");
|
|
}
|
|
};
|
|
|
|
ImageWebcam.prototype.closeStream = function() {
|
|
if (this._webcam_stream) {
|
|
var tracks = this._webcam_stream.getTracks();
|
|
if (tracks.length) {
|
|
for (var i = 0; i < tracks.length; ++i) {
|
|
tracks[i].stop();
|
|
}
|
|
}
|
|
ImageWebcam.is_webcam_open = false;
|
|
this._webcam_stream = null;
|
|
this._video = null;
|
|
this.boxcolor = "black";
|
|
this.trigger("stream_closed");
|
|
}
|
|
};
|
|
|
|
ImageWebcam.prototype.onPropertyChanged = function(name, value) {
|
|
if (name == "facingMode") {
|
|
this.properties.facingMode = value;
|
|
this.closeStream();
|
|
this.openStream();
|
|
}
|
|
};
|
|
|
|
ImageWebcam.prototype.onRemoved = function() {
|
|
this.closeStream();
|
|
};
|
|
|
|
ImageWebcam.prototype.streamReady = function(localMediaStream) {
|
|
this._webcam_stream = localMediaStream;
|
|
//this._waiting_confirmation = false;
|
|
this.boxcolor = "green";
|
|
|
|
var video = this._video;
|
|
if (!video) {
|
|
video = document.createElement("video");
|
|
video.autoplay = true;
|
|
video.srcObject = localMediaStream;
|
|
this._video = video;
|
|
//document.body.appendChild( video ); //debug
|
|
//when video info is loaded (size and so)
|
|
video.onloadedmetadata = function(e) {
|
|
// Ready to go. Do some stuff.
|
|
console.log(e);
|
|
ImageWebcam.is_webcam_open = true;
|
|
};
|
|
}
|
|
|
|
this.trigger("stream_ready", video);
|
|
};
|
|
|
|
ImageWebcam.prototype.onExecute = function() {
|
|
if (this._webcam_stream == null && !this._waiting_confirmation) {
|
|
this.openStream();
|
|
}
|
|
|
|
if (!this._video || !this._video.videoWidth) {
|
|
return;
|
|
}
|
|
|
|
this._video.frame = ++this.frame;
|
|
this._video.width = this._video.videoWidth;
|
|
this._video.height = this._video.videoHeight;
|
|
this.setOutputData(0, this._video);
|
|
for (var i = 1; i < this.outputs.length; ++i) {
|
|
if (!this.outputs[i]) {
|
|
continue;
|
|
}
|
|
switch (this.outputs[i].name) {
|
|
case "width":
|
|
this.setOutputData(i, this._video.videoWidth);
|
|
break;
|
|
case "height":
|
|
this.setOutputData(i, this._video.videoHeight);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
ImageWebcam.prototype.getExtraMenuOptions = function(graphcanvas) {
|
|
var that = this;
|
|
var txt = !that.properties.show ? "Show Frame" : "Hide Frame";
|
|
return [
|
|
{
|
|
content: txt,
|
|
callback: function() {
|
|
that.properties.show = !that.properties.show;
|
|
}
|
|
}
|
|
];
|
|
};
|
|
|
|
ImageWebcam.prototype.onDrawBackground = function(ctx) {
|
|
if (
|
|
this.flags.collapsed ||
|
|
this.size[1] <= 20 ||
|
|
!this.properties.show
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (!this._video) {
|
|
return;
|
|
}
|
|
|
|
//render to graph canvas
|
|
ctx.save();
|
|
ctx.drawImage(this._video, 0, 0, this.size[0], this.size[1]);
|
|
ctx.restore();
|
|
};
|
|
|
|
ImageWebcam.prototype.onGetOutputs = function() {
|
|
return [
|
|
["width", "number"],
|
|
["height", "number"],
|
|
["stream_ready", LiteGraph.EVENT],
|
|
["stream_closed", LiteGraph.EVENT],
|
|
["stream_error", LiteGraph.EVENT]
|
|
];
|
|
};
|
|
|
|
LiteGraph.registerNodeType("graphics/webcam", ImageWebcam);
|
|
})(this);
|