Convert http to socketio, simplify by removing push from PS.
This commit is contained in:
+1
-22
@@ -46,25 +46,4 @@ def define_http_endpoints(PromptServer, sdppp):
|
||||
print('=============error============', e)
|
||||
return web.json_response({
|
||||
'error': str(e)
|
||||
})
|
||||
|
||||
@PromptServer.instance.routes.get("/sd-ppp/checkchanges")
|
||||
async def check_changes(request):
|
||||
is_changed = False
|
||||
if sdppp.has_ps_instance():
|
||||
is_changed = await sdppp.get_ps_instance().is_ps_history_changed()
|
||||
return web.json_response({'is_changed': is_changed}, content_type='application/json')
|
||||
|
||||
@PromptServer.instance.routes.get("/sd-ppp/resetchanges")
|
||||
async def reset_changes(request):
|
||||
if sdppp.has_ps_instance():
|
||||
sdppp.get_ps_instance().reset_change_tracker()
|
||||
return web.json_response({}, content_type='application/json')
|
||||
|
||||
@PromptServer.instance.routes.get("/sd-ppp/getlayers")
|
||||
async def get_layers(request):
|
||||
layer_strs = []
|
||||
bounds_strs = []
|
||||
if sdppp.has_ps_instance():
|
||||
layer_strs, bounds_strs = sdppp.get_ps_instance().get_layers()
|
||||
return web.json_response({'layer_strs': layer_strs, 'bounds_strs': bounds_strs}, content_type='application/json')
|
||||
})
|
||||
+9
-26
@@ -20,7 +20,8 @@ def define_comfyui_nodes(sdppp):
|
||||
return np.random.rand()
|
||||
else:
|
||||
photoshopInstance = sdppp.get_ps_instance()
|
||||
id, bounds_id = self.LAYER_BOUNDS_NAME_TO_ID(layer, use_layer_bounds)
|
||||
id = photoshopInstance.layer_name_to_id(layer)
|
||||
bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
|
||||
is_changed, history_state_id = photoshopInstance.check_layer_bounds_combo_changed(id, bounds_id)
|
||||
if is_changed and history_state_id is None:
|
||||
return np.random.rand()
|
||||
@@ -33,7 +34,8 @@ def define_comfyui_nodes(sdppp):
|
||||
layer_strs = []
|
||||
bounds_strs = []
|
||||
else:
|
||||
layer_strs, bounds_strs = sdppp.get_ps_instance().get_layers()
|
||||
layer_strs = sdppp.get_ps_instance().get_base_layers()
|
||||
bounds_strs = sdppp.get_ps_instance().get_bounds_layers()
|
||||
|
||||
return {
|
||||
"required": {
|
||||
@@ -41,26 +43,6 @@ def define_comfyui_nodes(sdppp):
|
||||
"use_layer_bounds": (bounds_strs, {"default": bounds_strs[0] if len(bounds_strs) > 0 else None}),
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def LAYER_BOUNDS_NAME_TO_ID(self, layer, use_layer_bounds):
|
||||
id = 0
|
||||
if layer == '### Use canvas ###':
|
||||
id = 0
|
||||
else:
|
||||
layer_name_and_id_split = layer.split('(id:')
|
||||
id = int(layer_name_and_id_split.pop().strip()[:-1])
|
||||
bounds_id = 0
|
||||
if use_layer_bounds == '### Use canvas ###':
|
||||
bounds_id = 0
|
||||
elif use_layer_bounds == '### Use selection ###':
|
||||
bounds_id = -1
|
||||
elif use_layer_bounds == '### Same as layer ###':
|
||||
bounds_id = id
|
||||
else:
|
||||
bounds_layer_name_and_id_split = use_layer_bounds.split('(id:')
|
||||
bounds_id = int(bounds_layer_name_and_id_split.pop().strip()[:-1])
|
||||
return id, bounds_id
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "MASK", "FLOAT")
|
||||
RETURN_NAMES = ("image_out", "mask_out", "layer_opacity")
|
||||
@@ -72,7 +54,8 @@ def define_comfyui_nodes(sdppp):
|
||||
raise ValueError('Photoshop is not connected')
|
||||
photoshopInstance = sdppp.get_ps_instance()
|
||||
|
||||
id, bounds_id = self.LAYER_BOUNDS_NAME_TO_ID(layer, use_layer_bounds)
|
||||
id = photoshopInstance.layer_name_to_id(layer)
|
||||
bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
|
||||
image_id, layer_opacity = photoshopInstance.get_image_from_remote(layer_id=id, bounds_id=bounds_id)
|
||||
loadImage = LoadImage()
|
||||
(output_image, output_mask) = loadImage.load_image(image_id)
|
||||
@@ -89,8 +72,7 @@ def define_comfyui_nodes(sdppp):
|
||||
if validate_sdppp() is not True:
|
||||
layer_strs = []
|
||||
else:
|
||||
layer_strs, b = sdppp.get_ps_instance().get_layers()
|
||||
layer_strs.insert(0, '### New Layer ###')
|
||||
layer_strs = sdppp.get_ps_instance().get_set_layers()
|
||||
|
||||
return {
|
||||
"required": {
|
||||
@@ -110,7 +92,8 @@ def define_comfyui_nodes(sdppp):
|
||||
photoshopInstance = sdppp.get_ps_instance()
|
||||
|
||||
ret = cache_images(images)
|
||||
photoshopInstance.send_images_to_remote(image_ids=ret, layer_name=layer)
|
||||
layer_id = photoshopInstance.layer_name_to_id(layer)
|
||||
photoshopInstance.send_images_to_remote(image_ids=ret, layer_id=layer_id)
|
||||
|
||||
return (None,)
|
||||
|
||||
|
||||
+60
-36
@@ -1,4 +1,18 @@
|
||||
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
|
||||
@@ -10,39 +24,61 @@ class PhotoshopInstance:
|
||||
'done': False,
|
||||
'result': None
|
||||
}
|
||||
self.sdppp.onNextTick(fn, handle)
|
||||
while not handle['done']:
|
||||
self.sdppp.onNextTick(fn, handle, self.sid)
|
||||
start_time = time.time()
|
||||
while not handle['done'] and self.sdppp.check_state_true(self.sid) and time.time() - start_time < 15:
|
||||
pass
|
||||
return handle['result']
|
||||
|
||||
def get_layers(self):
|
||||
layer_strs = []
|
||||
bounds_strs = []
|
||||
|
||||
layer_strs = list(map(lambda layer: f"{layer['name']} (id:{layer['id']})", self.layers))
|
||||
layer_strs.insert(0, '### Use canvas ###')
|
||||
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
|
||||
|
||||
bounds_strs = list(layer_strs)
|
||||
bounds_strs.insert(1, '### Use selection ###')
|
||||
bounds_strs.insert(1, '### Same as layer ###')
|
||||
|
||||
return layer_strs, 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
|
||||
|
||||
# for nodes call
|
||||
def get_image_from_remote(self, layer_id, bounds_id=False):
|
||||
async def _get_image(sio):
|
||||
return await sio.call('get_image', data={'layer_id': layer_id, 'use_layer_bounds': bounds_id}, to=self.sid)
|
||||
result = self._run_in_next_server_event(_get_image)
|
||||
|
||||
if not result:
|
||||
return None, None
|
||||
history_state_id = self._update_layer_bounds_history_state_id(layer_id, bounds_id)
|
||||
self._update_history_state_id_after_internal_change(history_state_id)
|
||||
|
||||
return result['upload_name'], result['layer_opacity']
|
||||
|
||||
# for nodes call
|
||||
def send_images_to_remote(self, image_ids, layer_name=""):
|
||||
def send_images_to_remote(self, image_ids, layer_id=""):
|
||||
async def _send_images(sio):
|
||||
return await sio.call('send_images', data={'image_ids': image_ids, 'layer_name': layer_name}, to=self.sid)
|
||||
return await sio.call('send_images', data={'image_ids': image_ids, 'layer_id': layer_id}, to=self.sid)
|
||||
result = self._run_in_next_server_event(_send_images)
|
||||
self._update_history_state_id_after_internal_change()
|
||||
return result
|
||||
@@ -50,14 +86,11 @@ class PhotoshopInstance:
|
||||
# for nodes call
|
||||
def get_active_history_state_id_from_remote(self):
|
||||
async def get_active_history_state_id_from_remote(sio):
|
||||
return await sio.call('get_active_history_state_id', data={}, to=self.sid)
|
||||
res = await sio.call('get_active_history_state_id', data={}, to=self.sid)
|
||||
return res
|
||||
result = self._run_in_next_server_event(get_active_history_state_id_from_remote)
|
||||
id = result.get('history_state_id', None)
|
||||
return id
|
||||
|
||||
# for apis call
|
||||
async def async_get_active_history_state_id_from_remote(self):
|
||||
result = await self.sdppp.sio.call('get_active_history_state_id', data={}, to=self.sid)
|
||||
if result is None:
|
||||
return 0
|
||||
id = result.get('history_state_id', None)
|
||||
return id
|
||||
|
||||
@@ -65,19 +98,14 @@ class PhotoshopInstance:
|
||||
# ===
|
||||
# for api calls and initialize
|
||||
def reset_change_tracker(self):
|
||||
self.push_data = {}
|
||||
self.get_img_state_id = 0
|
||||
self.last_get_img_id = None
|
||||
self.change_tracker = {}
|
||||
self.comfyui_last_value_tracker = {}
|
||||
|
||||
# for apis calls
|
||||
async def is_ps_history_changed(self):
|
||||
push_state_id = await self.async_get_active_history_state_id_from_remote()
|
||||
if push_state_id is not None:
|
||||
return self.get_img_state_id < push_state_id
|
||||
current_id = await self.get_active_history_state_id_from_remote()
|
||||
return self.get_img_state_id != current_id
|
||||
def is_ps_history_changed(self):
|
||||
current_id = self.get_active_history_state_id_from_remote()
|
||||
return self.get_img_state_id != current_id and self.get_img_state_id < current_id
|
||||
|
||||
# for nodes calls
|
||||
def check_layer_bounds_combo_changed(self, layer, use_layer_bounds):
|
||||
@@ -85,7 +113,7 @@ class PhotoshopInstance:
|
||||
layer_bounds_history_state_id = self.change_tracker.get(layer_bounds_combo, None)
|
||||
if layer_bounds_history_state_id is None:
|
||||
return True
|
||||
latest_state_id = self._get_push_history_state_id() or self.get_active_history_state_id_from_remote()
|
||||
latest_state_id = self.get_active_history_state_id_from_remote()
|
||||
if latest_state_id > layer_bounds_history_state_id:
|
||||
return True, latest_state_id
|
||||
#didn't change, use last value
|
||||
@@ -113,8 +141,4 @@ class PhotoshopInstance:
|
||||
layer_bounds_combo = f"{layer}{use_layer_bounds}"
|
||||
latest_state_id = self.get_active_history_state_id_from_remote()
|
||||
self.change_tracker[layer_bounds_combo] = latest_state_id
|
||||
return latest_state_id
|
||||
|
||||
# for nodes call
|
||||
def _get_push_history_state_id(self):
|
||||
return self.push_data.get('history_state_id', None)
|
||||
return latest_state_id
|
||||
+45
-13
@@ -3,6 +3,7 @@ import json
|
||||
import asyncio
|
||||
from socketio import exceptions
|
||||
from .photoshop_instance import PhotoshopInstance
|
||||
empty_queue = []
|
||||
|
||||
class SDPPP:
|
||||
def __init__(self, PromptServer):
|
||||
@@ -16,18 +17,25 @@ class SDPPP:
|
||||
|
||||
self.loop = PromptServer.instance.loop
|
||||
|
||||
self.onNextTickQueue = []
|
||||
self.onNextTickQueue = {}
|
||||
|
||||
def has_ps_instance(self):
|
||||
return len(self.photoshop_instances) > 0
|
||||
|
||||
def get_ps_instance(self, sid = None):
|
||||
def get_ps_instance(self, sid = None) -> PhotoshopInstance:
|
||||
if len(self.photoshop_instances) == 0:
|
||||
return None
|
||||
if sid is None:
|
||||
sid = list(self.photoshop_instances.keys())[0]
|
||||
return self.photoshop_instances[sid]
|
||||
|
||||
def onNextTick(self, fn, handle):
|
||||
self.onNextTickQueue.append((fn, handle))
|
||||
def onNextTick(self, fn, handle, sid):
|
||||
if sid not in self.onNextTickQueue:
|
||||
self.onNextTickQueue[sid] = []
|
||||
self.onNextTickQueue[sid].append((fn, handle))
|
||||
|
||||
def check_state_true(self, sid):
|
||||
return self.state.get(sid, False)
|
||||
|
||||
def registerSocketListeners(self):
|
||||
sio = self.sio
|
||||
@@ -56,10 +64,15 @@ class SDPPP:
|
||||
while True:
|
||||
if (self.state[sid] is False):
|
||||
break
|
||||
while len(self.onNextTickQueue) > 0:
|
||||
item = self.onNextTickQueue.pop(0)
|
||||
item[1]['result'] = await item[0](self.sio)
|
||||
item[1]['done'] = True
|
||||
sid_queue = self.onNextTickQueue.get(sid, empty_queue)
|
||||
while len(sid_queue) > 0:
|
||||
try:
|
||||
item = sid_queue.pop(0)
|
||||
item[1]['result'] = await item[0](self.sio)
|
||||
except Exception as e:
|
||||
pass
|
||||
finally:
|
||||
item[1]['done'] = True
|
||||
await asyncio.sleep(0.5)
|
||||
self.loop.create_task(selfEventLoop())
|
||||
|
||||
@@ -67,25 +80,44 @@ class SDPPP:
|
||||
@sio.event
|
||||
def disconnect(sid):
|
||||
self.state[sid] = False
|
||||
self.onNextTickQueue.pop(sid, None)
|
||||
if sid in self.photoshop_instances:
|
||||
self.photoshop_instances.pop(sid, None)
|
||||
elif sid in self.comfyui_instances:
|
||||
self.comfyui_instances.pop(sid, None)
|
||||
sio.disconnect(sid)
|
||||
|
||||
# only emit by photoshop instance
|
||||
@sio.event
|
||||
async def sync_layers(sid, data):
|
||||
instance = self.get_ps_instance(sid)
|
||||
if instance is None:
|
||||
return
|
||||
instance.layers = data['layers']
|
||||
|
||||
layer_strs, bounds_strs = instance.get_layers()
|
||||
layer_strs = instance.get_base_layers()
|
||||
bounds_strs = instance.get_bounds_layers()
|
||||
set_layer_strs = instance.get_set_layers()
|
||||
for sid, instance in self.comfyui_instances.items():
|
||||
await sio.emit('sync_layers', {
|
||||
'layer_strs': layer_strs,
|
||||
'bound_strs': bounds_strs
|
||||
'bound_strs': bounds_strs,
|
||||
'set_layer_strs': set_layer_strs,
|
||||
}, to=sid)
|
||||
|
||||
@sio.event
|
||||
def push_data(sid, data):
|
||||
instance = self.get_ps_instance(sid)
|
||||
instance.push_data.update(push_data)
|
||||
def check_changes(sid):
|
||||
instance = self.get_ps_instance()
|
||||
if instance is None:
|
||||
return
|
||||
if not instance.is_ps_history_changed():
|
||||
return
|
||||
sio.emit('trigger_graph_change', to=sid)
|
||||
|
||||
@sio.event
|
||||
def reset_changes(sid):
|
||||
instance = self.get_ps_instance()
|
||||
if instance is None:
|
||||
return
|
||||
instance.reset_change_tracker()
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import socketio from './socket.io.js'
|
||||
|
||||
let layerStrs = [];
|
||||
let boundsStrs = [];
|
||||
let setLayerStrs = [];
|
||||
let socket = null;
|
||||
|
||||
console.log("[sd-ppp]", "Loading js extension");
|
||||
app.registerExtension({
|
||||
@@ -11,10 +13,9 @@ app.registerExtension({
|
||||
init() {
|
||||
},
|
||||
async setup() {
|
||||
await api.fetchApi(`/sd-ppp/resetchanges`);
|
||||
setInterval(checkChanges, 1000);
|
||||
|
||||
const socket = socketio(location.origin, {
|
||||
socket = socketio(location.origin, {
|
||||
transports: ["websocket"],
|
||||
path: '/sd-ppp/',
|
||||
query: {
|
||||
@@ -24,6 +25,7 @@ app.registerExtension({
|
||||
});
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.emit('reset_changes');
|
||||
});
|
||||
socket.on('disconnect', () => {
|
||||
});
|
||||
@@ -33,6 +35,10 @@ app.registerExtension({
|
||||
socket.on('sync_layers', (data) => {
|
||||
layerStrs = data.layer_strs;
|
||||
boundsStrs = data.bound_strs;
|
||||
setLayerStrs = data.set_layer_strs;
|
||||
});
|
||||
socket.on('trigger_graph_change', () => {
|
||||
api.dispatchEvent(new CustomEvent("graphChanged"));
|
||||
});
|
||||
},
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
@@ -51,6 +57,21 @@ app.registerExtension({
|
||||
if(onMouseEnter) await onMouseEnter.call(this, ...args);
|
||||
this_handler.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;
|
||||
}
|
||||
nodeType.prototype.onSelected = async function(...args) {
|
||||
if(onSelected) await onSelected.call(this, ...args);
|
||||
this_handler.call(this);
|
||||
}
|
||||
nodeType.prototype.onMouseEnter = async function(...args) {
|
||||
if(onMouseEnter) await onMouseEnter.call(this, ...args);
|
||||
this_handler.call(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -58,7 +79,6 @@ app.registerExtension({
|
||||
const SDPPPNodes = [
|
||||
'Get Image From Photoshop Layer',
|
||||
'Send Images To Photoshop',
|
||||
'Send Images To Photoshop Set Layer',
|
||||
]
|
||||
async function checkChanges() {
|
||||
await checkHistoryChanges();
|
||||
@@ -70,10 +90,7 @@ async function checkHistoryChanges() {
|
||||
const mode0NodeTypes = currentState.nodes.filter(node => node.mode == 0).map(node => node.type);
|
||||
const containsSDPPPNodes = mode0NodeTypes.some(nodeType => SDPPPNodes.includes(nodeType));
|
||||
if (!containsSDPPPNodes) return;
|
||||
const res = await api.fetchApi(`/sd-ppp/checkchanges`);
|
||||
const json = await res.json()
|
||||
if (!json.is_changed) return;
|
||||
api.dispatchEvent(new CustomEvent("graphChanged"));
|
||||
socket.emit('check_changes')
|
||||
} catch (e) {
|
||||
console.error("[sd-ppp]", "Failed to check changes", e);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from "react";
|
||||
import ComfyConnection from "../system/ComfyConnection";
|
||||
import HistoryChecker from "../system/HistoryChecker";
|
||||
import { storage } from "uxp";
|
||||
|
||||
export default class Main extends React.Component {
|
||||
@@ -17,14 +16,6 @@ export default class Main extends React.Component {
|
||||
isConnected: instance?.isConnected,
|
||||
comfyURL: instance ? instance.comfyURL : ''
|
||||
})
|
||||
if (instance?.isConnected) {
|
||||
const hc = HistoryChecker.createInstance();
|
||||
hc.setChangeCallback((historyId) => {
|
||||
instance.pushData({history_state_id: historyId})
|
||||
});
|
||||
} else {
|
||||
HistoryChecker.instance?.destroy();
|
||||
}
|
||||
});
|
||||
storage.secureStorage.getItem('comfyURL').then((value) => {
|
||||
if (!value) return
|
||||
|
||||
@@ -40,6 +40,7 @@ class ComfyConnection {
|
||||
this.connect();
|
||||
}
|
||||
connect() {
|
||||
console.log('connect')
|
||||
if (!this.socket) {
|
||||
this._createSocket();
|
||||
}
|
||||
@@ -52,21 +53,10 @@ class ComfyConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pushData(data) {
|
||||
if (!this.isConnected) {
|
||||
console.error('Connection not open');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.socket.emit('push_data', {
|
||||
push_data: data,
|
||||
});
|
||||
} catch (e) { console.error(e) }
|
||||
}
|
||||
|
||||
_createSocket() {
|
||||
console.log('create socket')
|
||||
const socket = this.socket = socketio(this.comfyURL, {
|
||||
autoConnect: false,
|
||||
transports: ["websocket"],
|
||||
path: '/sd-ppp/',
|
||||
query: {
|
||||
@@ -76,17 +66,22 @@ class ComfyConnection {
|
||||
});
|
||||
this.interval = setInterval(() => {
|
||||
if (!this.isConnected) return;
|
||||
const allLayers = getAllSubLayer(app.activeDocument);
|
||||
const allLayers = getAllSubLayer(app.activeDocument);
|
||||
this.socket.emit('sync_layers',
|
||||
{ layers: allLayers }
|
||||
)
|
||||
}, 3000)
|
||||
|
||||
socket.on('connect_error', (error) => {
|
||||
console.error('connect_error', error)
|
||||
if (socket.active) {
|
||||
console.error('connect_error reconnecting...')
|
||||
} else {
|
||||
console.error('connect_error disconnected')
|
||||
}
|
||||
ComfyConnection._callConnectStateChange();
|
||||
});
|
||||
socket.on('connect', () => {
|
||||
console.log('connect')
|
||||
storage.secureStorage.setItem('comfyURL', this.comfyURL);
|
||||
ComfyConnection._callConnectStateChange();
|
||||
});
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import {app, action} from "photoshop";
|
||||
|
||||
class HistoryChecker {
|
||||
static instance = null;
|
||||
static createInstance() {
|
||||
if (HistoryChecker.instance) {
|
||||
return HistoryChecker.instance;
|
||||
}
|
||||
return new HistoryChecker();
|
||||
}
|
||||
constructor() {
|
||||
HistoryChecker.instance = this;
|
||||
this.lastCheckId = -1;
|
||||
this.changeCallback = null;
|
||||
action.addNotificationListener(["historyStateChanged"], () => {
|
||||
this.checkHistoryState();
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
this.changeCallback = null;
|
||||
HistoryChecker.instance = null;
|
||||
}
|
||||
|
||||
setChangeCallback(callback) {
|
||||
this.changeCallback = callback;
|
||||
}
|
||||
|
||||
checkHistoryState() {
|
||||
const historyStates = app.activeDocument?.historyStates;
|
||||
if (!historyStates || historyStates.length == 0) return;
|
||||
const historyState = historyStates[historyStates.length - 1];
|
||||
const historyId = historyState.id;
|
||||
if (this.lastCheckId == historyId) return;
|
||||
this.lastCheckId = historyId;
|
||||
if (this.changeCallback)
|
||||
this.changeCallback(historyId);
|
||||
}
|
||||
}
|
||||
|
||||
export default HistoryChecker;
|
||||
@@ -2,6 +2,17 @@ import { app, imaging } from "photoshop";
|
||||
import { executeAsModalUntilSuccess} from '../util.js';
|
||||
import Jimp from "../library/jimp.min";
|
||||
|
||||
const SPECIAL_LAYER_USE_CANVAS = '### Use Canvas ###'
|
||||
const SPECIAL_LAYER_USE_SELECTION = '### Use Selection ###'
|
||||
const SPECIAL_LAYER_NEW_LAYER = '### New Layer ###'
|
||||
const SPECIAL_LAYER_SAME_AS_LAYER = '### Same as Layer ###'
|
||||
const 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
|
||||
}
|
||||
|
||||
function autocrop(jimp) {
|
||||
let minX = jimp.bitmap.width - 1;
|
||||
let minY = jimp.bitmap.height - 1;
|
||||
@@ -25,9 +36,8 @@ function autocrop(jimp) {
|
||||
}
|
||||
|
||||
export default async function sendImages(comfyURL, params) {
|
||||
|
||||
const imageIds = params.image_ids
|
||||
const layerName = params.layer_name
|
||||
const layerId = params.layer_id
|
||||
await Promise.all(
|
||||
imageIds.map(async imageId => {
|
||||
let layer;
|
||||
@@ -35,58 +45,72 @@ export default async function sendImages(comfyURL, params) {
|
||||
let newLayerName;
|
||||
await executeAsModalUntilSuccess(async () => {
|
||||
try {
|
||||
if (layerName && layerName != "### New Layer ###") {
|
||||
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 = ""
|
||||
console.log("imageIds.length: ", imageIds.length)
|
||||
if (imageIds.length > 1){
|
||||
imageIndexSuffix = ` ${imageIds.indexOf(imageId)}`
|
||||
index = imageIds.indexOf(imageId)
|
||||
console.log("imageIds.index: ", index)
|
||||
if (index > 0)
|
||||
imageIndexSuffix = ` ${index}`
|
||||
}
|
||||
if (imageIndexSuffix != "" && layer != null){
|
||||
const layerName = layer?.name;
|
||||
existingLayerName = layerName + imageIndexSuffix
|
||||
console.log("existingLayerName: ", existingLayerName)
|
||||
layer = await app.activeDocument.layers.find(l => l.name == existingLayerName)
|
||||
}
|
||||
existingLayerName = layerName + imageIndexSuffix
|
||||
layer = await app.activeDocument.layers.find(l => l.name == existingLayerName)
|
||||
}
|
||||
// deal with new layer or id/name not found layer
|
||||
if (!layer) {
|
||||
newLayerName = existingLayerName ?? 'Comfy Images ' + imageId
|
||||
console.log("newLayerName: ", newLayerName)
|
||||
layer = await app.activeDocument.createLayer("pixel", {
|
||||
name: newLayerName
|
||||
})
|
||||
}
|
||||
const jimp = (await Jimp.read(comfyURL + '/finished_images?id=' + imageId))
|
||||
autocrop(jimp)
|
||||
console.log("layer name ", layer.name)
|
||||
let putPixelsOptions = {
|
||||
layerID: layer.id,
|
||||
imageData: await imaging.createImageDataFromBuffer(
|
||||
jimp.bitmap.data,
|
||||
{
|
||||
width: jimp.bitmap.width,
|
||||
height: jimp.bitmap.height,
|
||||
components: 4,
|
||||
colorSpace: "RGB"
|
||||
}
|
||||
),
|
||||
replace: true,
|
||||
}
|
||||
if (!newLayerName) {
|
||||
let bounds = layer.bounds
|
||||
if (bounds.width != jimp.bitmap.width || bounds.height != jimp.bitmap.height) {
|
||||
if (bounds.width <= 1 && bounds.height <= 1) {
|
||||
bounds.left = jimp.bitmap.width / 2
|
||||
bounds.top = jimp.bitmap.height / 2
|
||||
}
|
||||
let centerBounds = {}
|
||||
centerBounds.left = bounds.left + (bounds.width - jimp.bitmap.width) / 2
|
||||
centerBounds.top = bounds.top + (bounds.height - jimp.bitmap.height) / 2
|
||||
centerBounds.right = bounds.left + jimp.bitmap.width
|
||||
centerBounds.bottom = bounds.top + jimp.bitmap.height
|
||||
centerBounds.width = jimp.bitmap.width
|
||||
centerBounds.height = jimp.bitmap.height
|
||||
bounds = centerBounds
|
||||
}
|
||||
putPixelsOptions.targetBounds = bounds
|
||||
}
|
||||
await imaging.putPixels(putPixelsOptions)
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
const jimp = (await Jimp.read(comfyURL + '/finished_images?id=' + imageId))
|
||||
autocrop(jimp)
|
||||
let putPixelsOptions = {
|
||||
layerID: layer.id,
|
||||
imageData: await imaging.createImageDataFromBuffer(
|
||||
jimp.bitmap.data,
|
||||
{
|
||||
width: jimp.bitmap.width,
|
||||
height: jimp.bitmap.height,
|
||||
components: 4,
|
||||
colorSpace: "RGB"
|
||||
}
|
||||
),
|
||||
replace: true,
|
||||
}
|
||||
if (!newLayerName) {
|
||||
let bounds = layer.bounds
|
||||
if (bounds.width != jimp.bitmap.width || bounds.height != jimp.bitmap.height) {
|
||||
let centerBounds = {}
|
||||
centerBounds.left = bounds.left + (bounds.width - jimp.bitmap.width) / 2
|
||||
centerBounds.top = bounds.top + (bounds.height - jimp.bitmap.height) / 2
|
||||
centerBounds.right = bounds.left + jimp.bitmap.width
|
||||
centerBounds.bottom = bounds.top + jimp.bitmap.height
|
||||
centerBounds.width = jimp.bitmap.width
|
||||
centerBounds.height = jimp.bitmap.height
|
||||
bounds = centerBounds
|
||||
}
|
||||
putPixelsOptions.targetBounds = bounds
|
||||
}
|
||||
await executeAsModalUntilSuccess(async () => {
|
||||
await imaging.putPixels(putPixelsOptions)
|
||||
})
|
||||
})
|
||||
)
|
||||
return {}
|
||||
|
||||
@@ -57,7 +57,7 @@ export function unTrimImageData(
|
||||
}
|
||||
|
||||
export function getAllSubLayer(layer, level = 0) {
|
||||
if (!layer.layers) return [];
|
||||
if (!layer?.layers) return [];
|
||||
return layer.layers.reduce((ret, layer) => {
|
||||
ret.push({
|
||||
name: '-'.repeat(level) + layer.name,
|
||||
|
||||
Reference in New Issue
Block a user