diff --git a/javascript/sdppp-comfy.js b/javascript/sdppp-comfy.js index 2a939ea..9315d7d 100644 --- a/javascript/sdppp-comfy.js +++ b/javascript/sdppp-comfy.js @@ -1,14 +1,13 @@ -(async function() { +(async function () { if (typeof gradioApp != 'undefined') return; const { app } = await import("../../../scripts/app.js") const { api } = await import("../../../scripts/api.js") const { $el } = await import('../../../scripts/ui.js') - await import('./socket.io.js') + await import('./socket.io.js') + await import('./sdppp-util.js') const socketio = globalThis.io - let layerStrs = []; - let boundsStrs = []; - let setLayerStrs = []; + let documentData = null; let socket = socketio(location.origin, { transports: ["websocket"], path: '/sd-ppp/', @@ -23,7 +22,7 @@ progress: Math.round(detail.value / detail.max * 100) }); }); - + console.log("[sd-ppp]", "Loading js extension"); const id = "Comfy.SD-PPP" app.ui.settings.addSetting({ @@ -54,8 +53,8 @@ init() { }, async setup() { - - + + socket.on('connect', () => { socket.emit('c_reset_changes'); socket.emit('c_reset_instance_name', { @@ -75,11 +74,11 @@ }); setInterval(() => { checkHistoryChanges(); - socket.emit('c_get_layers', (data) => { - layerStrs = data.layer_strs; - boundsStrs = data.bound_strs; - setLayerStrs = data.set_layer_strs; - }) + // socket.emit('c_get_layers', (data) => { + // layerStrs = data.layer_strs; + // boundsStrs = data.bound_strs; + // setLayerStrs = data.set_layer_strs; + // }) socket.emit('c_reset_instance_name', { name: document.title }) @@ -89,45 +88,80 @@ if (nodeType.comfyClass === 'Get Image From Photoshop Layer') { const onSelected = nodeType.prototype.onSelected; const onMouseEnter = nodeType.prototype.onMouseEnter; - let this_handler = function() { - this.widgets[0].options.values = layerStrs; - this.widgets[1].options.values = boundsStrs; + const onAdded = nodeType.prototype.onAdded; + const resetWidget12 = function () { + const documentName = this.widgets[0].value + this.widgets[1].options.values = !documentData[documentName] ? [] : SDPPPSpeicialIDManager.getSpecialLayerForGet().concat(documentData[documentName].layers.map(layer => layer.name)); + this.widgets[2].options.values = !documentData[documentName] ? [] : SDPPPSpeicialIDManager.getSpecialLayerForGetBounds().concat(documentData[documentName].layers.map(layer => layer.name)); + if (!this.widgets[1].value || this.widgets[1].options.values.indexOf(this.widgets[1].value) == -1) this.widgets[1].value = this.widgets[1].options.values[0] + if (!this.widgets[2].value || this.widgets[2].options.values.indexOf(this.widgets[2].value) == -1) this.widgets[2].value = this.widgets[2].options.values[0] } - nodeType.prototype.onSelected = async function(...args) { - if(onSelected) await onSelected.call(this, ...args); - this_handler.call(this); + const getAndRender = async function () { + documentData = (await new Promise(resolve => { + socket.emit('c_get_documents', resolve) + })) || {} + this.widgets[0].options.values = Object.keys(documentData); + if (!this.widgets[0].options.values.length) this.widgets[0].value = '' + if (!this.widgets[0].value || this.widgets[0].options.values.indexOf(this.widgets[0].value) == -1) this.widgets[0].value = this.widgets[0].options.values[0]; + resetWidget12.call(this); } - nodeType.prototype.onMouseEnter = async function(...args) { - if(onMouseEnter) await onMouseEnter.call(this, ...args); - this_handler.call(this); + nodeType.prototype.onSelected = async function (...args) { + if (onSelected) await onSelected.call(this, ...args); + await getAndRender.call(this); } + nodeType.prototype.onMouseEnter = async function (...args) { + if (onMouseEnter) await onMouseEnter.call(this, ...args); + await getAndRender.call(this); + } + nodeType.prototype.onAdded = async function () { + if (onAdded) await onAdded.call(this, ...args); + this.widgets[0].callback = () => { + resetWidget12.call(this); + } + } + } else if (nodeType.comfyClass === 'Send Images To Photoshop') { const onSelected = nodeType.prototype.onSelected; const onMouseEnter = nodeType.prototype.onMouseEnter; - let this_handler = function() { - this.widgets[0].options.values = setLayerStrs; + const onAdded = nodeType.prototype.onAdded; + const resetWidget1 = function () { + const documentName = this.widgets[0].value + this.widgets[1].options.values = !documentData[documentName] ? [] : SDPPPSpeicialIDManager.getSpecialLayerForSend().concat(documentData[documentName].layers.map(layer => layer.name)); + if (!this.widgets[1].value || this.widgets[1].options.values.indexOf(this.widgets[1].value) == -1) this.widgets[1].value = this.widgets[1].options.values[0] } - nodeType.prototype.onSelected = async function(...args) { - if(onSelected) await onSelected.call(this, ...args); - this_handler.call(this); + const getAndRender = async function () { + documentData = (await new Promise(resolve => { + socket.emit('c_get_documents', resolve) + })) || {} + this.widgets[0].options.values = Object.keys(documentData); + if (!this.widgets[0].options.values.length) this.widgets[0].value = '' + if (!this.widgets[0].value || this.widgets[0].options.values.indexOf(this.widgets[0].value) == -1) this.widgets[0].value = this.widgets[0].options.values[0]; + resetWidget1.call(this); } - nodeType.prototype.onMouseEnter = async function(...args) { - if(onMouseEnter) await onMouseEnter.call(this, ...args); - this_handler.call(this); + nodeType.prototype.onSelected = async function (...args) { + if (onSelected) await onSelected.call(this, ...args); + await getAndRender.call(this); } - nodeType.prototype.onDrawBackground = async function(...args) { - console.log(args); + nodeType.prototype.onMouseEnter = async function (...args) { + if (onMouseEnter) await onMouseEnter.call(this, ...args); + await getAndRender.call(this); } - + nodeType.prototype.onAdded = async function () { + if (onAdded) await onAdded.call(this, ...args); + this.widgets[0].callback = () => { + resetWidget1.call(this); + } + } + } } }); - + const SDPPPNodes = [ 'Get Image From Photoshop Layer', 'Send Images To Photoshop', ] - + async function checkHistoryChanges() { try { const currentState = app.graph.serialize(); diff --git a/javascript/sdppp-util.js b/javascript/sdppp-util.js new file mode 100644 index 0000000..c9fbd6a --- /dev/null +++ b/javascript/sdppp-util.js @@ -0,0 +1,52 @@ +(function() { + class SpeicialIDManager { + static SPECIAL_DOCUMENT_CURRENT = '### Active Document ###' + static SPECIAL_LAYER_USE_CANVAS = '### The Canvas ###' + static SPECIAL_LAYER_USE_SELECTION = '### Selection ###' + static SPECIAL_LAYER_NEW_LAYER = '### New Layer ###' + static SPECIAL_LAYER_SAME_AS_LAYER = '### Same as Layer ###' + + static getDocumentID(name) { + if (name == this.SPECIAL_DOCUMENT_CURRENT) { + return -1; + } + const split = name.split('(id:') + id = parseInt(split.pop().trim().slice(0, -1)) + return id; + } + static getLayerID(name) { + if (name == this.SPECIAL_LAYER_USE_CANVAS) + return 0; + if (name == this.SPECIAL_LAYER_USE_SELECTION) + return -1; + if (name == this.SPECIAL_LAYER_NEW_LAYER) + return -2; + if (name == this.SPECIAL_LAYER_SAME_AS_LAYER) + return -3; + const split = name.split('(id:') + id = parseInt(split.pop().trim().slice(0, -1)) + return id; + } + + + + static getSpecialLayerForGet() { + return [ + SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS + ] + } + static getSpecialLayerForGetBounds() { + return [ + SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS, + SpeicialIDManager.SPECIAL_LAYER_USE_SELECTION, + SpeicialIDManager.SPECIAL_LAYER_SAME_AS_LAYER + ] + } + static getSpecialLayerForSend() { + return [ + SpeicialIDManager.SPECIAL_LAYER_NEW_LAYER + ] + } + } + globalThis.SDPPPSpeicialIDManager = SpeicialIDManager +})(); diff --git a/photoshop/dist/index.js b/photoshop/dist/index.js index 2d0d610..9a0dc18 100644 --- a/photoshop/dist/index.js +++ b/photoshop/dist/index.js @@ -1,6 +1,49 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ +/***/ "../javascript/sdppp-util.js": +/*!***********************************!*\ + !*** ../javascript/sdppp-util.js ***! + \***********************************/ +/***/ (() => { + +(function () { + class SpeicialIDManager { + static SPECIAL_DOCUMENT_CURRENT = '### Active Document ###'; + static SPECIAL_LAYER_USE_CANVAS = '### The Canvas ###'; + static SPECIAL_LAYER_USE_SELECTION = '### Selection ###'; + static SPECIAL_LAYER_NEW_LAYER = '### New Layer ###'; + static SPECIAL_LAYER_SAME_AS_LAYER = '### Same as Layer ###'; + static getDocumentID(name) { + if (name == this.SPECIAL_DOCUMENT_CURRENT) { + return -1; + } + const split = name.split('(id:'); + return parseInt(split.pop().trim().slice(0, -1)); + } + static getLayerID(name) { + if (name == this.SPECIAL_LAYER_USE_CANVAS) return 0; + if (name == this.SPECIAL_LAYER_USE_SELECTION) return -1; + if (name == this.SPECIAL_LAYER_NEW_LAYER) return -2; + if (name == this.SPECIAL_LAYER_SAME_AS_LAYER) return -3; + const split = name.split('(id:'); + return parseInt(split.pop().trim().slice(0, -1)); + } + static getSpecialLayerForGet() { + return [SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS]; + } + static getSpecialLayerForGetBounds() { + return [SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS, SpeicialIDManager.SPECIAL_LAYER_USE_SELECTION, SpeicialIDManager.SPECIAL_LAYER_SAME_AS_LAYER]; + } + static getSpecialLayerForSend() { + return [SpeicialIDManager.SPECIAL_LAYER_NEW_LAYER]; + } + } + globalThis.SDPPPSpeicialIDManager = SpeicialIDManager; +})(); + +/***/ }), + /***/ "./src/controllers/PanelController.jsx": /*!*********************************************!*\ !*** ./src/controllers/PanelController.jsx ***! @@ -337,10 +380,6 @@ class ComfyConnection { }); this.interval = setInterval(() => { if (!this.isConnected) return; - const allLayers = (0,_util__WEBPACK_IMPORTED_MODULE_2__.getAllSubLayer)(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument); - this.socket.emit('b_sync_layers', { - layers: allLayers - }); }, 3000); this.lastErrorMessage = ''; socket.on('connect_error', error => { @@ -361,7 +400,7 @@ class ComfyConnection { console.log('disconnect'); ComfyConnection._callConnectStateChange(); }); - socket.on('get_image', async (data, callback) => { + socket.on('s_get_image', async (data, callback) => { try { const startTime = Date.now(); const result = await (0,_events_get_image__WEBPACK_IMPORTED_MODULE_5__["default"])(this.backendURL, Object.assign(data, { @@ -376,7 +415,7 @@ class ComfyConnection { }); } }); - socket.on('send_images', async (data, callback) => { + socket.on('s_send_images', async (data, callback) => { try { const result = await (0,_events_send_images__WEBPACK_IMPORTED_MODULE_4__["default"])(this.backendURL, Object.assign(data, { isComfy: this.serverType == "comfy" @@ -389,7 +428,7 @@ class ComfyConnection { }); } }); - socket.on('get_active_history_state_id', async (data, callback) => { + socket.on('s_get_active_history_state_id', async (data, callback) => { try { callback({ history_state_id: _model_js__WEBPACK_IMPORTED_MODULE_7__["default"].instance.historyStateId @@ -407,6 +446,20 @@ class ComfyConnection { socket.on('c_progress', data => { ComfyConnection._callPageInstancesChange(data); }); + socket.on('c_get_documents', (d, callback) => { + callback(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.documents.reduce((ret, document) => { + ret[document.name + ` (id:${document.id})`] = { + name: document.name + ` (id:${document.id})`, + layers: (0,_util__WEBPACK_IMPORTED_MODULE_2__.getAllSubLayer)(document) + }; + return ret; + }, { + '### Active Document ###': { + name: '### Active Document ###', + layers: (0,_util__WEBPACK_IMPORTED_MODULE_2__.getAllSubLayer)(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument) + } + })); + }); setInterval(() => { socket.emit('b_get_pages', data => { ComfyConnection._callPageInstancesChange(data); @@ -476,11 +529,11 @@ __webpack_require__.r(__webpack_exports__); function isFolder(layer) { return layer.kind == "group"; } -async function findLayer(layerID) { +async function findLayer(document, layerID) { let layer; let layerIsFolder = false; if (layerID <= 0) return [layer, layerIsFolder]; - layer = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.findInAllSubLayer)(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument, layerID); + layer = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.findInAllSubLayer)(document, layerID); if (!layer) throw new Error(`Layer(id: ${layerID}) not found`); if (!isFolder(layer)) return [layer, layerIsFolder]; @@ -498,7 +551,7 @@ async function findLayer(layerID) { } // ps returns trimmed data so need padding -function padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds) { +function padAndTrimLayerDataToDesireBounds(document, layer, pixelDataFromAPI, desireBounds) { if (pixelDataFromAPI.length == desireBounds.width * desireBounds.height * 4) { return pixelDataFromAPI; } @@ -506,16 +559,16 @@ function padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds let bounds = { left: 0, top: 0, - right: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.width, - bottom: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.height + right: document.width, + bottom: document.height }; if (layer) bounds = layer.bounds; (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.unTrimImageData)(pixelDataFromAPI, pixelDataForReturn, bounds, desireBounds); return pixelDataForReturn; } -async function getPixelsDataHelper(layer, desireBounds) { +async function getPixelsDataHelper(document, layer, desireBounds) { let options = { - documentID: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.id, + documentID: document.id, applyAlpha: false, sourceBounds: desireBounds }; @@ -534,27 +587,31 @@ async function getPixelsDataHelper(layer, desireBounds) { }); return pixelDataFromAPI; } -async function getPixelsData(layer, desireBounds) { +async function getPixelsData(document, layer, desireBounds) { // layer null = document data if (!layer) { - return await getPixelsDataHelper(null, desireBounds); + return await getPixelsDataHelper(document, null, desireBounds); } // normal layer - return await getPixelsDataHelper(layer, desireBounds); + return await getPixelsDataHelper(document, layer, desireBounds); } -function getDesiredBounds(boundsLayerID) { +function getDesiredBounds(document, boundLayerIdentify, layerIdentify) { + const boundsLayerID = boundLayerIdentify == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_LAYER_SAME_AS_LAYER ? _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getLayerID(layerIdentify) : _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getLayerID(boundLayerIdentify); const docBounds = { left: 0, top: 0, - right: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.width, - bottom: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.height, - width: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.width, - height: photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.height + right: document.width, + bottom: document.height, + width: document.width, + height: document.height }; - // if boundsLayerID == -1, use selection bounds - if (boundsLayerID == -1) { + if (boundLayerIdentify == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS) { + return docBounds; + } + // use selection bounds + if (boundLayerIdentify == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_LAYER_USE_SELECTION) { // if no selection use document bounds - const selectionBounds = photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.selection?.bounds; + const selectionBounds = document.selection?.bounds; if (!selectionBounds) return docBounds; return { left: selectionBounds.left, @@ -567,12 +624,9 @@ function getDesiredBounds(boundsLayerID) { } let boundsLayer; if (boundsLayerID > 0) { - boundsLayer = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.findInAllSubLayer)(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument, boundsLayerID); - if (!boundsLayer) throw new Error(`Bounds layer(id: ${boundsLayerID}) not found`); + boundsLayer = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.findInAllSubLayer)(document, boundsLayerID); } - // null boundsLayer = document bounds - if (!boundsLayer) return docBounds; - // empty boundsLayer = document bounds + if (!boundsLayer) throw new Error(`Bounds layer(id: ${boundsLayerID}) not found`); const boundsLayerBounds = boundsLayer.bounds; const isEmptyBoundsLayer = boundsLayerBounds.left == 0 && boundsLayerBounds.top == 0 && boundsLayerBounds.right == 0 && boundsLayerBounds.bottom == 0; if (isEmptyBoundsLayer) return docBounds; @@ -587,41 +641,33 @@ function getDesiredBounds(boundsLayerID) { }; return desireBounds; } -function arrayBufferToBase64(buffer) { - var binary = ''; - var bytes = new Uint8Array(buffer); - var len = bytes.byteLength; - for (var i = 0; i < len; i++) { - binary += String.fromCharCode(bytes[i]); - } - return window.btoa(binary); -} async function getImage(serverURL, params) { - if (!photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument) { - throw new Error('no active document'); - } - const layerID = params.layer_id; - const boundsLayerID = params.use_layer_bounds; - const desireBounds = getDesiredBounds(boundsLayerID); + const documentIdentify = params.document_identify; + let document = documentIdentify == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_DOCUMENT_CURRENT ? photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument : photoshop__WEBPACK_IMPORTED_MODULE_0__.app.documents.find(document => document.id == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getDocumentID(documentIdentify)); + if (!document) throw new Error('document not found'); + const layerIdentify = params.layer_identify; + const boundLayerIdentify = params.bound_layer_identify; + const desireBounds = getDesiredBounds(document, boundLayerIdentify, layerIdentify); let pixelDataForReturn = null; let layerOpacity = 100; + const layerID = _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getLayerID(layerIdentify); const startTime = Date.now(); await (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.executeAsModalUntilSuccess)(async executionContext => { let hostControl; let suspensionID; let layer; let isFolder = false; - const activeLayers = photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.activeLayers; + const activeLayers = document.activeLayers; try { hostControl = executionContext.hostControl; suspensionID = await hostControl.suspendHistory({ - "documentID": photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.id, + "documentID": document.id, "name": "Image To ComfyUI" }); - [layer, isFolder] = await findLayer(layerID); + [layer, isFolder] = await findLayer(document, layerID); layerOpacity = layer?.opacity ?? 100; - const pixelDataFromAPI = await getPixelsData(layer, desireBounds); - pixelDataForReturn = padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds); + const pixelDataFromAPI = await getPixelsData(document, layer, desireBounds); + pixelDataForReturn = padAndTrimLayerDataToDesireBounds(document, layer, pixelDataFromAPI, desireBounds); console.log('getPixels', Date.now() - startTime, 'ms'); } catch (e) { console.error(e); @@ -632,16 +678,16 @@ async function getImage(serverURL, params) { layer.delete(); } if (activeLayers && activeLayers.length > 0) { - for (let i = 0; i < activeLayers.length; i++) { - const visible = activeLayers[i].visible; - activeLayers[i].selected = true; - activeLayers[i].visible = visible; - } + activeLayers.forEach(layer => { + const visible = layer.visible; + layer.selected = true; + layer.visible = visible; + }); } if (hostControl && suspensionID) hostControl.resumeHistory(suspensionID); } }, { - commandName: "get content of layer " + layerID + commandName: "get content of layer " + layerIdentify }); try { // log desire size @@ -740,45 +786,55 @@ function autocrop(jimp) { } async function sendImages(comfyURL, params) { const imageIds = params.image_ids; - const layerId = params.layer_id; + const documentIdentify = params.document_identify; + const layerIdentify = params.layer_identify; + let document = documentIdentify == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_DOCUMENT_CURRENT ? photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument : photoshop__WEBPACK_IMPORTED_MODULE_0__.app.documents.find(document => document.id == _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getDocumentID(documentIdentify)); + if (!document) throw new Error('document not found'); await Promise.all(imageIds.map(async imageId => { - let layer; + let layerOrGroup; let existingLayerName; let newLayerName; + const layerId = _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.getDocumentID(layerIdentify); await (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.executeAsModalUntilSuccess)(async () => { try { - if (layerId && layerId != SPECIAL_LAYER_NAME_TO_ID[SPECIAL_LAYER_NEW_LAYER]) { - layer = await photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.layers.find(l => l.id == layerId); - // deal with multiple images - let imageIndexSuffix = ""; - if (imageIds.length > 1) { - index = imageIds.indexOf(imageId); - if (index > 0) imageIndexSuffix = ` ${index}`; - } - if (imageIndexSuffix != "" && layer != null) { - const layerName = layer?.name; - existingLayerName = layerName + imageIndexSuffix; - layer = await photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.layers.find(l => l.name == existingLayerName); - } + if (layerIdentify && layerIdentify != _util_js__WEBPACK_IMPORTED_MODULE_1__.SpeicialIDManager.SPECIAL_LAYER_NEW_LAYER) { + layerOrGroup = await document.layers.find(l => l.id == layerId); + // // deal with multiple images + // let imageIndexSuffix = "" + // if (imageIds.length > 1){ + // index = imageIds.indexOf(imageId) + // if (index > 0) + // imageIndexSuffix = ` ${index}` + // } + // if (imageIndexSuffix != "" && layerOrGroup != null){ + // const layerName = layerOrGroup?.name; + // existingLayerName = layerName + imageIndexSuffix + // layerOrGroup = await app.activeDocument.layers.find(l => l.name == existingLayerName) + // } } // deal with new layer or id/name not found layer - if (!layer || layer.kind == "group") { - newLayerName = existingLayerName ?? 'Comfy Images ' + imageId; - const activeLayers = photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.activeLayers; - const newLayer = await photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.createLayer("pixel", { + if (!layerOrGroup || layerOrGroup.kind == "group") { + newLayerName = existingLayerName ?? 'Images ' + imageId; + const activeLayers = document.activeLayers; + const newLayer = await document.createLayer("pixel", { name: newLayerName }); - if (layer) newLayer.move(layer, "placeInside");else newLayer.move(photoshop__WEBPACK_IMPORTED_MODULE_0__.app.activeDocument.layers[0], 'placeBefore'); - layer = newLayer; - activeLayers.forEach(layer => layer.selected = true); - layer.selected = false; + if (layerOrGroup) newLayer.move(layerOrGroup, "placeInside");else newLayer.move(document.layers[0], 'placeBefore'); + layerOrGroup = newLayer; + activeLayers.forEach(layerOrGroup => { + const visible = layerOrGroup.visible; + layerOrGroup.selected = true; + layerOrGroup.visible = visible; + }); + layerOrGroup.selected = false; _model_js__WEBPACK_IMPORTED_MODULE_3__["default"].instance.ignoreNextHistoryChange(); } const jimp = await _library_jimp_min__WEBPACK_IMPORTED_MODULE_2___default().read(comfyURL + '/sdppp_download?name=' + imageId); // const jimp = (await Jimp.read(comfyURL + '/finished_images?id=' + imageId)) autocrop(jimp); let putPixelsOptions = { - layerID: layer.id, + documentID: document.id, + layerID: layerOrGroup.id, imageData: await photoshop__WEBPACK_IMPORTED_MODULE_0__.imaging.createImageDataFromBuffer(jimp.bitmap.data, { width: jimp.bitmap.width, height: jimp.bitmap.height, @@ -5264,6 +5320,7 @@ class Model { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ SpeicialIDManager: () => (/* binding */ SpeicialIDManager), /* harmony export */ executeAsModalUntilSuccess: () => (/* binding */ executeAsModalUntilSuccess), /* harmony export */ findInAllSubLayer: () => (/* binding */ findInAllSubLayer), /* harmony export */ getAllSubLayer: () => (/* binding */ getAllSubLayer), @@ -5271,6 +5328,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ }); /* harmony import */ var photoshop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! photoshop */ "photoshop"); /* harmony import */ var photoshop__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(photoshop__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _javascript_sdppp_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../javascript/sdppp-util */ "../javascript/sdppp-util.js"); +/* harmony import */ var _javascript_sdppp_util__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_javascript_sdppp_util__WEBPACK_IMPORTED_MODULE_1__); + + +const SpeicialIDManager = globalThis.SDPPPSpeicialIDManager; function unTrimImageData(intersectImageDataArray, toImageDataArray, fromImageBounds, toImageBounds) { const fromLeft = fromImageBounds.left; @@ -5317,7 +5379,7 @@ function getAllSubLayer(layer, level = 0) { if (!layer?.layers) return []; return layer.layers.reduce((ret, layer) => { ret.push({ - name: '-'.repeat(level) + layer.name, + name: '-'.repeat(level) + layer.name + ` (id:${layer['id']})`, id: layer.id }); return ret.concat(getAllSubLayer(layer, level + 1)); diff --git a/photoshop/src/system/ComfyConnection.js b/photoshop/src/system/ComfyConnection.js index aaa1439..88d7dd1 100644 --- a/photoshop/src/system/ComfyConnection.js +++ b/photoshop/src/system/ComfyConnection.js @@ -87,10 +87,6 @@ class ComfyConnection { }); this.interval = setInterval(() => { if (!this.isConnected) return; - const allLayers = getAllSubLayer(app.activeDocument); - this.socket.emit('b_sync_layers', - { layers: allLayers } - ) }, 3000) this.lastErrorMessage = ''; @@ -113,7 +109,7 @@ class ComfyConnection { ComfyConnection._callConnectStateChange(); }); - socket.on('get_image', async (data, callback) => { + socket.on('s_get_image', async (data, callback) => { try { const startTime = Date.now(); const result = await getImage(this.backendURL, Object.assign(data, { isComfy: this.serverType == "comfy" })) @@ -121,13 +117,13 @@ class ComfyConnection { callback(result) } catch (e) { console.error(e); callback({ error: e.message }) } }) - socket.on('send_images', async (data, callback) => { + socket.on('s_send_images', async (data, callback) => { try { const result = await sendImages(this.backendURL, Object.assign(data, { isComfy: this.serverType == "comfy" })) callback(result) } catch (e) { console.error(e); callback({ error: e.message }) } }) - socket.on('get_active_history_state_id', async (data, callback) => { + socket.on('s_get_active_history_state_id', async (data, callback) => { try { callback({ history_state_id: Model.instance.historyStateId @@ -140,6 +136,21 @@ class ComfyConnection { socket.on('c_progress', (data) => { ComfyConnection._callPageInstancesChange(data); }) + socket.on('c_get_documents', (d, callback) => { + + callback(app.documents.reduce((ret, document) => { + ret[document.name + ` (id:${document.id})`] = { + name: document.name + ` (id:${document.id})`, + layers: getAllSubLayer(document) + } + return ret; + }, { + '### Active Document ###': { + name: '### Active Document ###', + layers: getAllSubLayer(app.activeDocument) + } + })) + }) setInterval(() => { socket.emit('b_get_pages', (data) => { ComfyConnection._callPageInstancesChange(data); diff --git a/photoshop/src/system/events/get_image.js b/photoshop/src/system/events/get_image.js index 1545bd2..d43a476 100644 --- a/photoshop/src/system/events/get_image.js +++ b/photoshop/src/system/events/get_image.js @@ -1,16 +1,16 @@ import { app, imaging } from "photoshop"; -import { executeAsModalUntilSuccess, findInAllSubLayer, unTrimImageData } from '../util.js'; +import { SpeicialIDManager, executeAsModalUntilSuccess, findInAllSubLayer, unTrimImageData } from '../util.js'; import Jimp from "../library/jimp.min"; -function isFolder(layer){ +function isFolder(layer) { return layer.kind == "group" } -async function findLayer(layerID) { +async function findLayer(document, layerID) { let layer; let layerIsFolder = false; if (layerID <= 0) return [layer, layerIsFolder]; - layer = findInAllSubLayer(app.activeDocument, layerID) + layer = findInAllSubLayer(document, layerID) if (!layer) throw new Error(`Layer(id: ${layerID}) not found`); if (!isFolder(layer)) return [layer, layerIsFolder]; @@ -28,7 +28,7 @@ async function findLayer(layerID) { } // ps returns trimmed data so need padding -function padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds) { +function padAndTrimLayerDataToDesireBounds(document, layer, pixelDataFromAPI, desireBounds) { if (pixelDataFromAPI.length == desireBounds.width * desireBounds.height * 4) { return pixelDataFromAPI; } @@ -36,22 +36,22 @@ function padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds let bounds = { left: 0, top: 0, - right: app.activeDocument.width, - bottom: app.activeDocument.height, + right: document.width, + bottom: document.height, } if (layer) bounds = layer.bounds; unTrimImageData( pixelDataFromAPI, - pixelDataForReturn, + pixelDataForReturn, bounds, desireBounds ) return pixelDataForReturn; } -async function getPixelsDataHelper(layer, desireBounds) { +async function getPixelsDataHelper(document, layer, desireBounds) { let options = { - documentID: app.activeDocument.id, + documentID: document.id, applyAlpha: false, sourceBounds: desireBounds, } @@ -69,29 +69,36 @@ async function getPixelsDataHelper(layer, desireBounds) { return pixelDataFromAPI } -async function getPixelsData(layer, desireBounds) { +async function getPixelsData(document, layer, desireBounds) { // layer null = document data if (!layer) { - return await getPixelsDataHelper(null, desireBounds); + return await getPixelsDataHelper(document, null, desireBounds); } // normal layer - return await getPixelsDataHelper(layer, desireBounds); + return await getPixelsDataHelper(document, layer, desireBounds); } -function getDesiredBounds(boundsLayerID) { +function getDesiredBounds(document, boundLayerIdentify, layerIdentify) { + const boundsLayerID = boundLayerIdentify == SpeicialIDManager.SPECIAL_LAYER_SAME_AS_LAYER ? + SpeicialIDManager.getLayerID(layerIdentify) : + SpeicialIDManager.getLayerID(boundLayerIdentify) + const docBounds = { - left: 0, - top: 0, - right: app.activeDocument.width, - bottom: app.activeDocument.height, - width: app.activeDocument.width, - height: app.activeDocument.height + left: 0, + top: 0, + right: document.width, + bottom: document.height, + width: document.width, + height: document.height }; - // if boundsLayerID == -1, use selection bounds - if (boundsLayerID == -1) { + if (boundLayerIdentify == SpeicialIDManager.SPECIAL_LAYER_USE_CANVAS) { + return docBounds; + } + // use selection bounds + if (boundLayerIdentify == SpeicialIDManager.SPECIAL_LAYER_USE_SELECTION) { // if no selection use document bounds - const selectionBounds = app.activeDocument.selection?.bounds; + const selectionBounds = document.selection?.bounds; if (!selectionBounds) return docBounds; return { left: selectionBounds.left, @@ -104,12 +111,9 @@ function getDesiredBounds(boundsLayerID) { } let boundsLayer; if (boundsLayerID > 0) { - boundsLayer = findInAllSubLayer(app.activeDocument, boundsLayerID) - if (!boundsLayer) throw new Error(`Bounds layer(id: ${boundsLayerID}) not found`); + boundsLayer = findInAllSubLayer(document, boundsLayerID) } - // null boundsLayer = document bounds - if (!boundsLayer) return docBounds; - // empty boundsLayer = document bounds + if (!boundsLayer) throw new Error(`Bounds layer(id: ${boundsLayerID}) not found`); const boundsLayerBounds = boundsLayer.bounds const isEmptyBoundsLayer = boundsLayerBounds.left == 0 && boundsLayerBounds.top == 0 && boundsLayerBounds.right == 0 && boundsLayerBounds.bottom == 0; if (isEmptyBoundsLayer) return docBounds; @@ -124,43 +128,39 @@ function getDesiredBounds(boundsLayerID) { }; return desireBounds } -function arrayBufferToBase64(buffer) { - var binary = '' - var bytes = new Uint8Array(buffer) - var len = bytes.byteLength - for (var i = 0; i < len; i++) { - binary += String.fromCharCode(bytes[i]) - } - return window.btoa(binary) -} export default async function getImage(serverURL, params) { - if (!app.activeDocument) { - throw new Error('no active document'); - } - const layerID = params.layer_id - const boundsLayerID = params.use_layer_bounds - const desireBounds = getDesiredBounds(boundsLayerID); + const documentIdentify = params.document_identify + let document = documentIdentify == SpeicialIDManager.SPECIAL_DOCUMENT_CURRENT ? + app.activeDocument : + app.documents.find(document => document.id == SpeicialIDManager.getDocumentID(documentIdentify)) + if (!document) throw new Error('document not found'); + + const layerIdentify = params.layer_identify + const boundLayerIdentify = params.bound_layer_identify + const desireBounds = getDesiredBounds(document, boundLayerIdentify, layerIdentify) + ; let pixelDataForReturn = null; let layerOpacity = 100; - + const layerID = SpeicialIDManager.getLayerID(layerIdentify); + const startTime = Date.now(); await executeAsModalUntilSuccess(async (executionContext) => { let hostControl; let suspensionID; let layer; let isFolder = false; - const activeLayers = app.activeDocument.activeLayers; + const activeLayers = document.activeLayers; try { hostControl = executionContext.hostControl; suspensionID = await hostControl.suspendHistory({ - "documentID": app.activeDocument.id, + "documentID": document.id, "name": "Image To ComfyUI" }); - [layer, isFolder] = await findLayer(layerID); + [layer, isFolder] = await findLayer(document, layerID); layerOpacity = layer?.opacity ?? 100; - const pixelDataFromAPI = await getPixelsData(layer, desireBounds) - pixelDataForReturn = padAndTrimLayerDataToDesireBounds(layer, pixelDataFromAPI, desireBounds) + const pixelDataFromAPI = await getPixelsData(document, layer, desireBounds) + pixelDataForReturn = padAndTrimLayerDataToDesireBounds(document, layer, pixelDataFromAPI, desireBounds) console.log('getPixels', Date.now() - startTime, 'ms'); } catch (e) { console.error(e); @@ -172,16 +172,16 @@ export default async function getImage(serverURL, params) { layer.delete(); } if (activeLayers && activeLayers.length > 0) { - for (let i = 0; i < activeLayers.length; i++) { - const visible = activeLayers[i].visible; - activeLayers[i].selected = true; - activeLayers[i].visible = visible; - } + activeLayers.forEach(layer => { + const visible = layer.visible; + layer.selected = true; + layer.visible = visible; + }) } if (hostControl && suspensionID) hostControl.resumeHistory(suspensionID); } - }, { commandName: "get content of layer " + layerID }) + }, { commandName: "get content of layer " + layerIdentify }) try { // log desire size @@ -197,11 +197,11 @@ export default async function getImage(serverURL, params) { image.quality(100); const file = await image.getBufferAsync(Jimp.MIME_PNG); console.log('create pngfile', Date.now() - startTime, 'ms'); - + const fd = new FormData(); const PhotoshopBlob = new Blob([file], { type: "image/png" }); - fd.append('image', PhotoshopBlob, "PhotoshopBlob.png") ; - fd.append('overwrite', "true"); + fd.append('image', PhotoshopBlob, "PhotoshopBlob.png"); + fd.append('overwrite', "true"); console.log('start upload', Date.now() - startTime, 'ms'); let endpoint = params.isComfy ? '/upload/image' : '/sdppp_upload' const promise = fetch(serverURL + endpoint, { @@ -216,15 +216,15 @@ export default async function getImage(serverURL, params) { console.log('finish upload', Date.now() - startTime, 'ms') const result = await promise console.log('upload resulted', Date.now() - startTime, 'ms') - + if (result.error) throw new Error(result.error); if (!result.name) throw new Error('No upload_name') - + return { upload_name: result.name, layer_opacity: layerOpacity, } - } catch(e) { + } catch (e) { console.error(e); throw e } diff --git a/photoshop/src/system/events/send_images.js b/photoshop/src/system/events/send_images.js index 68f7643..19da684 100644 --- a/photoshop/src/system/events/send_images.js +++ b/photoshop/src/system/events/send_images.js @@ -1,5 +1,5 @@ import { app, imaging } from "photoshop"; -import { executeAsModalUntilSuccess} from '../util.js'; +import { SpeicialIDManager, executeAsModalUntilSuccess} from '../util.js'; import Jimp from "../library/jimp.min"; import Model from "../model.js"; @@ -38,48 +38,60 @@ function autocrop(jimp) { export default async function sendImages(comfyURL, params) { const imageIds = params.image_ids - const layerId = params.layer_id + const documentIdentify = params.document_identify + const layerIdentify = params.layer_identify + + let document = documentIdentify == SpeicialIDManager.SPECIAL_DOCUMENT_CURRENT ? + app.activeDocument : + app.documents.find(document => document.id == SpeicialIDManager.getDocumentID(documentIdentify)) + if (!document) throw new Error('document not found'); await Promise.all( imageIds.map(async imageId => { - let layer; + let layerOrGroup; let existingLayerName; let newLayerName; + const layerId = SpeicialIDManager.getDocumentID(layerIdentify) await executeAsModalUntilSuccess(async () => { try { - if (layerId && layerId != SPECIAL_LAYER_NAME_TO_ID[SPECIAL_LAYER_NEW_LAYER]) { - layer = await app.activeDocument.layers.find(l => l.id == layerId) - // deal with multiple images - let imageIndexSuffix = "" - if (imageIds.length > 1){ - index = imageIds.indexOf(imageId) - if (index > 0) - imageIndexSuffix = ` ${index}` - } - if (imageIndexSuffix != "" && layer != null){ - const layerName = layer?.name; - existingLayerName = layerName + imageIndexSuffix - layer = await app.activeDocument.layers.find(l => l.name == existingLayerName) - } + if (layerIdentify && layerIdentify != SpeicialIDManager.SPECIAL_LAYER_NEW_LAYER) { + layerOrGroup = await document.layers.find(l => l.id == layerId) + // // deal with multiple images + // let imageIndexSuffix = "" + // if (imageIds.length > 1){ + // index = imageIds.indexOf(imageId) + // if (index > 0) + // imageIndexSuffix = ` ${index}` + // } + // if (imageIndexSuffix != "" && layerOrGroup != null){ + // const layerName = layerOrGroup?.name; + // existingLayerName = layerName + imageIndexSuffix + // layerOrGroup = await app.activeDocument.layers.find(l => l.name == existingLayerName) + // } } // deal with new layer or id/name not found layer - if (!layer || (layer.kind == "group")) { - newLayerName = existingLayerName ?? 'Comfy Images ' + imageId - const activeLayers = app.activeDocument.activeLayers; - const newLayer = await app.activeDocument.createLayer("pixel", { + if (!layerOrGroup || (layerOrGroup.kind == "group")) { + newLayerName = existingLayerName ?? 'Images ' + imageId + const activeLayers = document.activeLayers; + const newLayer = await document.createLayer("pixel", { name: newLayerName, }) - if (layer) newLayer.move(layer, "placeInside") - else newLayer.move(app.activeDocument.layers[0], 'placeBefore') - layer = newLayer - activeLayers.forEach(layer => layer.selected = true); - layer.selected = false; + if (layerOrGroup) newLayer.move(layerOrGroup, "placeInside") + else newLayer.move(document.layers[0], 'placeBefore') + layerOrGroup = newLayer + activeLayers.forEach(layerOrGroup => { + const visible = layerOrGroup.visible; + layerOrGroup.selected = true + layerOrGroup.visible = visible; + }); + layerOrGroup.selected = false; Model.instance.ignoreNextHistoryChange() } const jimp = (await Jimp.read(comfyURL + '/sdppp_download?name=' + imageId)) // const jimp = (await Jimp.read(comfyURL + '/finished_images?id=' + imageId)) autocrop(jimp) let putPixelsOptions = { - layerID: layer.id, + documentID: document.id, + layerID: layerOrGroup.id, imageData: await imaging.createImageDataFromBuffer( jimp.bitmap.data, { diff --git a/photoshop/src/system/util.js b/photoshop/src/system/util.js index 7851850..9c0fb76 100644 --- a/photoshop/src/system/util.js +++ b/photoshop/src/system/util.js @@ -1,9 +1,12 @@ import { core } from "photoshop"; +import '../../../javascript/sdppp-util' +const SpeicialIDManager = globalThis.SDPPPSpeicialIDManager +export { SpeicialIDManager }; export function unTrimImageData( intersectImageDataArray, toImageDataArray, - fromImageBounds, + fromImageBounds, toImageBounds ) { const fromLeft = fromImageBounds.left; @@ -60,7 +63,7 @@ export function getAllSubLayer(layer, level = 0) { if (!layer?.layers) return []; return layer.layers.reduce((ret, layer) => { ret.push({ - name: '-'.repeat(level) + layer.name, + name: '-'.repeat(level) + layer.name + ` (id:${layer['id']})`, id: layer.id }); return ret.concat(getAllSubLayer(layer, level + 1)); diff --git a/sdppp_python/apis.py b/sdppp_python/apis.py index 031051d..3fe38cc 100644 --- a/sdppp_python/apis.py +++ b/sdppp_python/apis.py @@ -65,33 +65,36 @@ def registerSDHTTPEndpoints(sdppp, app): return {'name': name} def registerSocketEvents(sdppp, sio): - # only emit by web instance + # only emit by sd webui instance @sio.event async def c_get_image(sid, data={}): if not sdppp.has_ps_instance(): return photoshopInstance = sdppp.get_ps_instance() - layer = data['layer_id'] + document = data['document'] + layer = data['layer'] use_layer_bounds = data['use_layer_bounds'] sd_elem_id = data['sd']['elem_id'] - id = photoshopInstance.layer_name_to_id(layer) - bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id) + # id = photoshopInstance.layer_name_to_id(layer) + # bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id) - upload_name, opacity = await photoshopInstance.get_image(layer_id=id, bounds_id=bounds_id) + upload_name, opacity = await photoshopInstance.get_image( + document_identify=document, layer_identify=layer, bound_layer_identify=use_layer_bounds + ) res = consumeImageCache(upload_name) addImageCache(res, sd_elem_id) return {} - # only emit by web instance + # only emit by sd webui instance @sio.event async def c_send_image(sid, data={}): if not sdppp.has_ps_instance(): return photoshopInstance = sdppp.get_ps_instance() + document = data['document'] layer = data['layer'] - layer_id = photoshopInstance.layer_name_to_id(layer) image_urls = data['sd']['image_urls'] def load_image(image_url): @@ -101,23 +104,7 @@ def registerSocketEvents(sdppp, sio): raise Exception('Invalid image url') return addImageCache(image_url) image_ids = [load_image(image_url) for image_url in image_urls] - await photoshopInstance.send_images(layer_id=layer_id, image_ids=image_ids) - - # only emit by web instance - @sio.event - async def c_get_layers(sid, data = {}): - if not sdppp.has_ps_instance(): - return {} - instance = sdppp.get_ps_instance() - - layer_strs = instance.get_base_layers() - bounds_strs = instance.get_bounds_layers() - set_layer_strs = instance.get_set_layers() - return { - 'layer_strs': layer_strs, - 'bound_strs': bounds_strs, - 'set_layer_strs': set_layer_strs, - } + await photoshopInstance.send_images(document_identify=document, layer_identify=layer, image_ids=image_ids) # only emit by photoshop instance @sio.event @@ -166,9 +153,20 @@ def registerSocketEvents(sdppp, sio): @sio.event async def c_progress(sid, data): - photoshop_sid = sdppp.get_ps_instance().sid + instance = sdppp.get_ps_instance() + if instance is None: + return + photoshop_sid = instance.sid await sio.emit('c_progress', { 'progress': data['progress'], 'sid': sid }, to=photoshop_sid) + + @sio.event + async def c_get_documents(sid, data = {}): + instance = sdppp.get_ps_instance() + if instance is None: + return {} + photoshop_sid = instance.sid + return await sio.call('c_get_documents', data, to=photoshop_sid) diff --git a/sdppp_python/comfy_nodes.py b/sdppp_python/comfy_nodes.py index e584b2e..7b23394 100644 --- a/sdppp_python/comfy_nodes.py +++ b/sdppp_python/comfy_nodes.py @@ -39,37 +39,34 @@ def define_comfyui_nodes(sdppp): class GetImageFromPhotoshopLayerNode: @classmethod - def VALIDATE_INPUTS(s, layer): + def VALIDATE_INPUTS(s): return validate_sdppp() @classmethod - def IS_CHANGED(self, layer, use_layer_bounds): + def IS_CHANGED(self, layer_or_group, use_layer_bounds): if not sdppp.has_ps_instance(): return np.random.rand() else: photoshopInstance = sdppp.get_ps_instance() - id = photoshopInstance.layer_name_to_id(layer) - bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id) - start = time.time() - is_changed, history_state_id = call_async_func_in_server_thread(photoshopInstance.check_layer_bounds_combo_changed(id, bounds_id)) + print(1) + is_changed, history_state_id = call_async_func_in_server_thread( + photoshopInstance.check_layer_bounds_combo_changed(layer, use_layer_bounds) + ) + print(2) if is_changed and history_state_id is None: return np.random.rand() - photoshopInstance.update_comfyui_last_value(id, bounds_id, history_state_id) + print(3) + photoshopInstance.update_comfyui_last_value(layer, use_layer_bounds, history_state_id) return history_state_id @classmethod def INPUT_TYPES(cls): - if validate_sdppp() is not True: - layer_strs = [] - bounds_strs = [] - else: - layer_strs = sdppp.get_ps_instance().get_base_layers() - bounds_strs = sdppp.get_ps_instance().get_bounds_layers() - return { - "required": { - "layer": (layer_strs, {"default": layer_strs[0] if len(layer_strs) > 0 else None}), - "use_layer_bounds": (bounds_strs, {"default": bounds_strs[0] if len(bounds_strs) > 0 else None}), + "required": {}, + "optional": { + "document": ([], {"default": None}), + "layer_or_group": ([], {"default": None}), + "use_layer_bounds": ([], {"default": None}), } } @@ -78,16 +75,14 @@ def define_comfyui_nodes(sdppp): FUNCTION = "get_image" CATEGORY = "Photoshop" - def get_image(self, layer, use_layer_bounds): + def get_image(self, document, layer_or_group, use_layer_bounds): if validate_sdppp() is not True: raise ValueError('Photoshop is not connected') photoshopInstance = sdppp.get_ps_instance() - id = photoshopInstance.layer_name_to_id(layer) - bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id) - - start = time.time() - image_id, layer_opacity = call_async_func_in_server_thread(photoshopInstance.get_image(layer_id=id, bounds_id=bounds_id)) + image_id, layer_opacity = call_async_func_in_server_thread( + photoshopInstance.get_image(document_identify=document, layer_identify=layer_or_group, bound_layer_identify=use_layer_bounds) + ) loadImage = LoadImage() (output_image, output_mask) = loadImage.load_image(image_id) @@ -96,20 +91,17 @@ def define_comfyui_nodes(sdppp): class SendImageToPhotoshopLayerNode: @classmethod - def VALIDATE_INPUTS(s, images): + def VALIDATE_INPUTS(s): return validate_sdppp() @classmethod def INPUT_TYPES(cls): - if validate_sdppp() is not True: - layer_strs = [] - else: - layer_strs = sdppp.get_ps_instance().get_set_layers() - return { - "required": { + "required": {}, + "optional": { "images": ("IMAGE", ), - "layer": (layer_strs, {"default": layer_strs[0] if len(layer_strs) > 0 else None}), + "document": ([], {"default": None}), + "layer_or_group": ([], {"default": None}), } } @@ -118,7 +110,7 @@ def define_comfyui_nodes(sdppp): CATEGORY = "Photoshop" OUTPUT_NODE = True - def send_image(self, images, layer): + def send_image(self, images, document, layer_or_group): if validate_sdppp() is not True: raise ValueError('Photoshop is not connected') photoshopInstance = sdppp.get_ps_instance() @@ -128,8 +120,10 @@ def define_comfyui_nodes(sdppp): i = 255. * image.cpu().numpy() img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) image_ids.append(addImageCache(img)) - layer_id = photoshopInstance.layer_name_to_id(layer) - call_async_func_in_server_thread(photoshopInstance.send_images(image_ids=image_ids, layer_id=layer_id), True) + + call_async_func_in_server_thread(photoshopInstance.send_images( + image_ids=image_ids, document_identify=document, layer_identify=layer_or_group + ), True) return (None,) @@ -174,4 +168,4 @@ def define_comfyui_nodes(sdppp): 'SendImageToPhotoshopLayerNode': SendImageToPhotoshopLayerNode, 'ImageTimesOpacity': ImageTimesOpacity, 'MaskTimesOpacity': MaskTimesOpacity, - } \ No newline at end of file + } diff --git a/sdppp_python/photoshop_instance.py b/sdppp_python/photoshop_instance.py index a18ac7e..721c89e 100644 --- a/sdppp_python/photoshop_instance.py +++ b/sdppp_python/photoshop_instance.py @@ -1,74 +1,35 @@ import time class PhotoshopInstance: - SPECIAL_LAYER_NEW_LAYER = '### New Layer ###' - SPECIAL_LAYER_USE_CANVAS = '### Use Canvas ###' - SPECIAL_LAYER_USE_SELECTION = '### Use Selection ###' - SPECIAL_LAYER_SAME_AS_LAYER = '### Same as Layer ###' - SPECIAL_LAYER_NAME_TO_ID = { - SPECIAL_LAYER_USE_CANVAS: 0, - SPECIAL_LAYER_USE_SELECTION: -1, - SPECIAL_LAYER_NEW_LAYER: -2, - SPECIAL_LAYER_SAME_AS_LAYER: -3 - } def __init__(self, sdppp, sid): self.sdppp = sdppp self.sid = sid self.layers = [] self.reset_change_tracker() - - def get_layers(self): - return list(map(lambda layer: f"{layer['name']} (id:{layer['id']})", self.layers)) - def get_base_layers(self): - raw_layer_strs = self.get_layers() - layer_strs = list(raw_layer_strs) - layer_strs.insert(0, self.SPECIAL_LAYER_USE_CANVAS) - return layer_strs - - def get_bounds_layers(self): - bounds_strs = list(self.get_layers()) - bounds_strs.insert(0, self.SPECIAL_LAYER_USE_CANVAS) - bounds_strs.insert(1, self.SPECIAL_LAYER_USE_SELECTION) - bounds_strs.insert(1, self.SPECIAL_LAYER_SAME_AS_LAYER) - return bounds_strs - - def get_set_layers(self): - raw_layer_strs = self.get_layers() - set_layer_strs = list(raw_layer_strs) - set_layer_strs.insert(0, self.SPECIAL_LAYER_NEW_LAYER) - return set_layer_strs - - def layer_name_to_id(self, layer_name, refrence_id=None): - id = 0 - if layer_name == self.SPECIAL_LAYER_SAME_AS_LAYER: - id = refrence_id - elif self.SPECIAL_LAYER_NAME_TO_ID.get(layer_name, None) is not None: - id = self.SPECIAL_LAYER_NAME_TO_ID[layer_name] - else: - layer_name_and_id_split = layer_name.split('(id:') - id = int(layer_name_and_id_split.pop().strip()[:-1]) - return id - - async def get_image(self, layer_id, bounds_id=False): - result = await self.sdppp.sio.call('get_image', data={'layer_id': layer_id, 'use_layer_bounds': bounds_id}, to=self.sid) + async def get_image(self, document_identify, layer_identify, bound_layer_identify): + result = await self.sdppp.sio.call('s_get_image', data={ + 'document_identify': document_identify, 'layer_identify': layer_identify, 'bound_layer_identify': bound_layer_identify + }, to=self.sid) if not result: return None, None if 'error' in result: raise Exception('sdppp PS side error:' + result['error']) - history_state_id = await self._update_layer_bounds_history_state_id(layer_id, bounds_id) - await self._update_history_state_id_after_internal_change(history_state_id) + # history_state_id = await self._update_layer_bounds_history_state_id(layer_id, bounds_id) + # await self._update_history_state_id_after_internal_change(history_state_id) return result['upload_name'], result['layer_opacity'] - async def send_images(self, image_ids, layer_id=""): - result = await self.sdppp.sio.call('send_images', data={'image_ids': image_ids, 'layer_id': layer_id}, to=self.sid) - await self._update_history_state_id_after_internal_change() + async def send_images(self, image_ids, document_identify, layer_identify): + result = await self.sdppp.sio.call('s_send_images', data={ + 'image_ids': image_ids, 'document_identify': document_identify, 'layer_identify': layer_identify + }, to=self.sid) + # await self._update_history_state_id_after_internal_change() return result async def get_active_history_state_id(self): - result = await self.sdppp.sio.call('get_active_history_state_id', data={}, to=self.sid) + result = await self.sdppp.sio.call('s_get_active_history_state_id', data={}, to=self.sid) if result is None: return 0 if 'error' in result: @@ -118,4 +79,4 @@ class PhotoshopInstance: layer_bounds_combo = f"{layer}{use_layer_bounds}" latest_state_id = await self.get_active_history_state_id() self.change_tracker[layer_bounds_combo] = latest_state_id - return latest_state_id \ No newline at end of file + return latest_state_id diff --git a/sdppp_python/sdppp.py b/sdppp_python/sdppp.py index c5c9ddf..8195a5d 100644 --- a/sdppp_python/sdppp.py +++ b/sdppp_python/sdppp.py @@ -44,7 +44,7 @@ class SDPPP: elif qsobj['type'] == 'photoshop': if len(self.photoshop_instances) > 0: - raise socketio.exceptions.ConnectionRefusedError('only 1 instance is allowed now') + raise socketio.exceptions.ConnectionRefusedError('only 1 instance is allowed now, or try to restart comfyUI') self.photoshop_instances[sid] = PhotoshopInstance(self, sid) elif qsobj['type'] == 'comfyui':