From c66cd6901ba0211f63b3968c3cb80d14912e7e55 Mon Sep 17 00:00:00 2001 From: shadowcz007 Date: Sat, 8 Jun 2024 16:03:10 +0800 Subject: [PATCH] appinfo add performance features Appinfo supports outputting to the background, enhancing the performance features of ComfyUI. --- web/javascript/app_mixlab.js | 24 ++- web/javascript/td_background.js | 323 ++++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+), 3 deletions(-) create mode 100644 web/javascript/td_background.js diff --git a/web/javascript/app_mixlab.js b/web/javascript/app_mixlab.js index c85f9a6..4871548 100644 --- a/web/javascript/app_mixlab.js +++ b/web/javascript/app_mixlab.js @@ -2,6 +2,8 @@ import { app } from '../../../scripts/app.js' import { $el } from '../../../scripts/ui.js' import { api } from '../../../scripts/api.js' +import { td_bg } from './td_background.js' +console.log('td_bg', td_bg) //本机安装的插件节点全集 window._nodesAll = null @@ -503,6 +505,22 @@ app.registerExtension({ } }) + //td bg + const tdBG = document.createElement('button') + tdBG.innerText = 'TDBG' + tdBG.style = style + tdBG.style.marginLeft = '12px' + + tdBG.addEventListener('click', () => { + td_bg.toggle(); + if(td_bg.running){ + tdBG.style.background = 'yellow' + }else{ + tdBG.style.background = 'transparent' + } + + }) + // author let author = document.createElement('div') // author.style=`display: flex` @@ -659,6 +677,7 @@ app.registerExtension({ btns.appendChild(btn) btns.appendChild(download) + btns.appendChild(tdBG) document.body.appendChild(widget.div) this.addCustomWidget(widget) @@ -687,9 +706,8 @@ app.registerExtension({ } const div = this.widgets.filter(w => w.div)[0].div - Array.from( - div.querySelectorAll('button'), - b => (b.style.background = 'yellow') + Array.from(div.querySelectorAll('button'), b => + b.innerText != 'TDBG' ? (b.style.background = 'yellow') : '' ) } catch (error) {} } diff --git a/web/javascript/td_background.js b/web/javascript/td_background.js new file mode 100644 index 0000000..7509183 --- /dev/null +++ b/web/javascript/td_background.js @@ -0,0 +1,323 @@ +// touchdesigner的背景效果,把appinfo的输出,选择一张图片作为背景 + +window._bg_img = null + +/** + * draws the back canvas (the one containing the background and the connections) + * @method drawBackCanvas + **/ +LGraphCanvas.prototype.drawBackCanvas = function () { + var canvas = this.bgcanvas + if ( + canvas.width != this.canvas.width || + canvas.height != this.canvas.height + ) { + canvas.width = this.canvas.width + canvas.height = this.canvas.height + } + + if (!this.bgctx) { + this.bgctx = this.bgcanvas.getContext('2d') + } + var ctx = this.bgctx + if (ctx.start) { + ctx.start() + } + + var viewport = this.viewport || [0, 0, ctx.canvas.width, ctx.canvas.height] + + //clear + if (this.clear_background) { + ctx.clearRect(viewport[0], viewport[1], viewport[2], viewport[3]) + } + + //show subgraph stack header + if (this._graph_stack && this._graph_stack.length) { + ctx.save() + var parent_graph = this._graph_stack[this._graph_stack.length - 1] + var subgraph_node = this.graph._subgraph_node + ctx.strokeStyle = subgraph_node.bgcolor + ctx.lineWidth = 10 + ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2) + ctx.lineWidth = 1 + ctx.font = '40px Arial' + ctx.textAlign = 'center' + ctx.fillStyle = subgraph_node.bgcolor || '#AAA' + var title = '' + for (var i = 1; i < this._graph_stack.length; ++i) { + title += this._graph_stack[i]._subgraph_node.getTitle() + ' >> ' + } + ctx.fillText(title + subgraph_node.getTitle(), canvas.width * 0.5, 40) + ctx.restore() + } + + var bg_already_painted = false + if (this.onRenderBackground) { + bg_already_painted = this.onRenderBackground(canvas, ctx) + } + + //reset in case of error + if (!this.viewport) { + ctx.restore() + ctx.setTransform(1, 0, 0, 1, 0, 0) + } + this.visible_links.length = 0 + + if (this.graph) { + //apply transformations + ctx.save() + this.ds.toCanvasContext(ctx) + + //render BG + if ( + this.ds.scale < 1 && + !bg_already_painted && + this.clear_background_color + ) { + ctx.fillStyle = this.clear_background_color + ctx.fillRect( + this.visible_area[0], + this.visible_area[1], + this.visible_area[2], + this.visible_area[3] + ) + } + + // 主要修改 + if (this.background_image && this.ds.scale > 0.5 && !bg_already_painted) { + if (this.zoom_modify_alpha) { + //使得 alpha 越接近0时变化越缓慢。 + let alpha = (1.0 - 0.5 / this.ds.scale) * this.editor_alpha + ctx.globalAlpha = Math.min(Math.max(0, Math.sqrt(alpha)), 1) + // console.log((1.0 - 0.5 / this.ds.scale) * this.editor_alpha) + } else { + ctx.globalAlpha = this.editor_alpha + } + ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled = false // ctx.mozImageSmoothingEnabled = + if (!this._bg_img || this._bg_img.name != this.background_image) { + this._bg_img = new Image() + this._bg_img.name = this.background_image + this._bg_img.src = this.background_image + var that = this + this._bg_img.onload = function () { + that.draw(true, true) + } + } + + var pattern = null + if (this._pattern == null && this._bg_img.width > 0) { + pattern = ctx.createPattern(this._bg_img, 'repeat') + this._pattern_img = this._bg_img + this._pattern = pattern + } else { + pattern = this._pattern + } + + if (pattern) { + ctx.fillStyle = pattern + ctx.fillRect( + this.visible_area[0], + this.visible_area[1], + this.visible_area[2], + this.visible_area[3] + ) + ctx.fillStyle = 'transparent' + } + + ctx.globalAlpha = 1.0 + ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled = true //= ctx.mozImageSmoothingEnabled + } + + //groups + if (this.graph._groups.length && !this.live_mode) { + this.drawGroups(canvas, ctx) + } + + if (this.onDrawBackground) { + this.onDrawBackground(ctx, this.visible_area) + } + if (this.onBackgroundRender) { + //LEGACY + console.error( + 'WARNING! onBackgroundRender deprecated, now is named onDrawBackground ' + ) + this.onBackgroundRender = null + } + + //DEBUG: show clipping area + //ctx.fillStyle = "red"; + //ctx.fillRect( this.visible_area[0] + 10, this.visible_area[1] + 10, this.visible_area[2] - 20, this.visible_area[3] - 20); + + //bg + if (this.render_canvas_border) { + ctx.strokeStyle = '#235' + ctx.strokeRect(0, 0, canvas.width, canvas.height) + } + + if (this.render_connections_shadows) { + ctx.shadowColor = '#000' + ctx.shadowOffsetX = 0 + ctx.shadowOffsetY = 0 + ctx.shadowBlur = 6 + } else { + ctx.shadowColor = 'rgba(0,0,0,0)' + } + + //draw connections + if (!this.live_mode) { + this.drawConnections(ctx) + } + + ctx.shadowColor = 'rgba(0,0,0,0)' + + //restore state + ctx.restore() + } + + if (ctx.finish) { + ctx.finish() + } + + this.dirty_bgcanvas = false + this.dirty_canvas = true //to force to repaint the front canvas with the bgcanvas +} + +function imgToCanvasBase64 (img) { + const canvas = document.createElement('canvas') + const ctx = canvas.getContext('2d') + canvas.width = img.width + canvas.height = img.height + ctx.drawImage(img, 0, 0) + const base64 = canvas.toDataURL('image/png') + + return base64 +} + +// 使用示例 +function convertImageToBase64 (img) { + // const img = new Image() + // img.src = 'path/to/your/image.jpg' // 替换为你的图片路径 + // console.log('convertImageToBase64',img) + try { + const base64 = imgToCanvasBase64(img) + return base64 + } catch (error) { + console.error(error) + } +} + +function getInputsAndOutputs () { + const outputs = + `PreviewImage,SaveImage,TransparentImage,VHS_VideoCombine,VideoCombine_Adv,Image Save,SaveImageAndMetadata_`.split( + ',' + ) + + let outputsId = [] + + for (let node of app.graph._nodes) { + if (outputs.includes(node.type)) { + outputsId.push(node.id) + } + } + + return outputsId +} + +function getRandomElement (arr) { + const randomIndex = Math.floor(Math.random() * arr.length) + return arr[randomIndex] +} + +async function getBG () { + var outputs = [] + + for (let id of app.graph + .getNodeById(50) + .widgets.filter(w => w.name === 'output_ids')[0] + .value.split('\n')) { + if (getInputsAndOutputs().map(Number).includes(Number(id))) { + if (app.graph.getNodeById(id).imgs && app.graph.getNodeById(id).imgs[0]) { + let b = convertImageToBase64(app.graph.getNodeById(id).imgs[0]) + // console.log(b) + outputs.push(b) + } + } + } + + var BACKGROUND_IMAGE = getRandomElement(outputs), + CLEAR_BACKGROUND_COLOR = 'rgba(0,0,0,0.9)' + + if (!window._bg_img) { + window._bg_img = app.canvas._bg_img.src + } + // let img=new Image(); + // img.src=BACKGROUND_IMAGE; + + //去掉透明度过度 + // app.canvas.zoom_modify_alpha=false; + //整体透明度 + app.canvas.editor_alpha = 1.1 + // app.canvas._pattern=ctx.createPattern(img, "no-repeat"); + app.canvas.updateBackground(BACKGROUND_IMAGE, CLEAR_BACKGROUND_COLOR) + app.canvas.draw(true, true) +} + +class BgRunner { + constructor () { + this.intervalId = null + this.running = false + } + + // 要运行的方法 + bg () { + console.log('方法bg正在运行') + getBG() + } + + // 启动bg方法每秒运行一次 + start () { + if (!this.running) { + this.intervalId = setInterval(() => this.bg(), 1500) + this.running = true + } + } + + // 停止bg方法的运行 + stop () { + if (this.running) { + clearInterval(this.intervalId) + this.intervalId = null + this.running = false + + if (window._bg_img) { + var BACKGROUND_IMAGE = window._bg_img, + CLEAR_BACKGROUND_COLOR = 'rgba(0,0,0,1)' + app.canvas.editor_alpha = 1 + + app.canvas.updateBackground(BACKGROUND_IMAGE, CLEAR_BACKGROUND_COLOR) + app.canvas.draw(true, true) + } + } + } + + // 切换start和stop + toggle () { + if (this.running) { + this.stop() + } else { + this.start() + } + } + + // 获取运行状态 + isRunning () { + return this.running + } +} + +// 示例用法 +// const runner = new BgRunner(); +// runner.start(); +// setTimeout(() => runner.stop(), 5000); + +export const td_bg = new BgRunner()