Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisgoringe committed Nov 27, 2024
2 parents 441594c + e1c07a0 commit 040e570
Show file tree
Hide file tree
Showing 18 changed files with 483 additions and 219 deletions.
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ If you unpin the image, you will find a handle at the bottom right of the image

## Other things to explore

### Batches

![image](images/batch.png)

If you have a batch of images, you can click through them on the preview using the control in the top right corner.

### Mask Editor

ctrl-click on an image in the controller to bring up a context menu, from which you can launch the mask editor.

### Selectively hide widgets

ctrl-click on the title of a nodeblock and you can hide/show specific widgets. Note that hide/show is specific to the controller,
so you can have the same node showing different widgets on different controllers if you want!

### Hover and zoom

If the magnifying glass in the top control is active ![image](images/top.png) then when you move you mouse over a node in
Expand Down Expand Up @@ -146,22 +161,22 @@ You can also move it around by dragging the header.

Controllers will snap to each other and move around together. To break them apart, move the controller on the right or bottom.

## Supporting Custom Nodes

Custom nodes which do not add specialised widgets will generally work. Some custom nodes with custom widgets are also supported:

- [trung0246](https://github.com/Trung0246/ComfyUI-0246) switch

## Known Limitations

### Custom widgets

At present only standard Comfy widgets are supported. We'll be working to bring some of the more popular custom node widgets to the controller
in future releases, probably starting with rgthree's Power Lora Loader.
At present only standard Comfy widgets and some custom ones are supported. We'll be working to bring more of the more popular custom node widgets to the controller
in future releases.


# The road ahead...

Future features will depend on community feedback, but the aim for the 1.5 release is to include

- Support for some popular custom node widgets
- Support for batches of images
- Open the mask editor directly from the controller on an image load node

For more details of what's under consideration, take a look at the [issues list](https://github.com/chrisgoringe/cg-controller/issues),
and feel free to add your ideas there, or
jump into the discussion [here](https://github.com/chrisgoringe/cg-controller/discussions).
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = "1.4.1"
VERSION = "1.5"
WEB_DIRECTORY = "./js"

NODE_CLASS_MAPPINGS= {}
Expand Down
Binary file added images/batch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 29 additions & 20 deletions js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
export const VERSION = "1.4.1"

export class SettingIds {
static KEYBOARD_TOGGLE = "Controller.options.keyboard"
static CONTROL_AFTER_GENERATE = "Controller.options.control_after_generate"
static SCROLL_MOVES_SLIDERS = "Controller.options.scroll_moves_slider"
static SCROLL_REVERSED = "Controller.options.scroll_reversed_for_slider"
static EDIT_SLIDERS = "Controller.options.edit_slider"
static DEBUG_LEVEL = "Controller.debug.level"
static FONT_SIZE = "Controller.options.font_size"
static TOOLTIPS = "Controller.options.tooltips"
static DEFAULT_APPLY_TO_SIMILAR = "Controller.options.default_apply_to_similar"
static SHOW_SCROLLBARS = "Controller.options.show_scrollbars"
static SHOW_IN_FOCUS_MODE = "Controller.options.show_in_focus_mode"
static KEYBOARD_TOGGLE = "Controller.Display.keyboard"
static CONTROL_AFTER_GENERATE = "Controller.Display.control_after_generate"
static SCROLL_MOVES_SLIDERS = "Controller.Sliders.scroll_moves_slider"
static SCROLL_REVERSED = "Controller.Sliders.scroll_reversed_for_slider"
static EDIT_SLIDERS = "Controller.Sliders.edit_slider"
static DEBUG_LEVEL = "Controller.Debug.level"
static FONT_SIZE = "Controller.Display.font_size"
static TOOLTIPS = "Controller.Display.tooltips"
static DEFAULT_APPLY_TO_SIMILAR = "Controller.Sliders.default_apply_to_similar"
static SHOW_SCROLLBARS = "Controller.Display.show_scrollbars"
static SHOW_IN_FOCUS_MODE = "Controller.Display.show_in_focus_mode"
}

export class SettingNames {
static KEYBOARD_TOGGLE = "Toggle controller visibility:"
static FONT_SIZE = "Controller font base size:"
static CONTROL_AFTER_GENERATE = "Show control after generate"
static FONT_SIZE = "Base font size:"
static CONTROL_AFTER_GENERATE = "Show 'control before/after generate'"
static TOOLTIPS = "Show tooltips"
static DEFAULT_APPLY_TO_SIMILAR = "Default apply to similar"
static SHOW_IN_FOCUS_MODE = "Show controllers in focus mode"
Expand All @@ -32,15 +32,17 @@ export class SettingNames {
export class Generic {
static NEVER = "Never"
static ALWAYS = "Always"
static SHIFT = "When shift key pressed"
static CTRL = "When ctrl key pressed"
static SHIFT = "shift key"
static CTRL = "ctrl key"
static OFF = "Off"
static THIN = "Thing"
static THIN = "Thin"
static NORMAL = "Normal"
static D0 = "Only show errors"
static D1 = "Normal debugging"
static D2 = "Extra information"
static D3 = "Maximum information"
static D0 = "Minimal"
static D1 = "Normal"
static D2 = "Extra"
static D3 = "Verbose"
static SHOW = "Show"
static HIDE = "Hide"
}

export class Tooltips {
Expand All @@ -63,6 +65,10 @@ export class InclusionOptions {
}

export class Timings { // ms
static GENERIC_SHORT_DELAY = 20
static GENERIC_LONGER_DELAY = 1000
static GENERIC_MUCH_LONGER_DELAY = 5000
static PERIODIC_CHECK = 1000
static DRAG_PAUSE_OVER_BACKGROUND = 500
static SLIDER_ACTIVE_DELAY = 300
static UPDATE_EXCEPTION_WAITTIME = 10000
Expand Down Expand Up @@ -94,6 +100,9 @@ export class Texts {
4 : "Group bypassed.</br>Click to activate",
9 : "Some nodes muted or bypassed.</br>Click to activate"
}
static REMOVE = "Remove from controllers"
static EDIT_WV = "Edit widget visibility"
static IMAGE_WIDGET_NAME = "image viewer"
}

export const BASE_PATH = "extensions/cg-controller"
Expand Down
25 changes: 25 additions & 0 deletions js/context_menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { app } from "../../scripts/app.js"

var context_menu

function autoclose(e) {
if (context_menu?.root?.contains(e.target)) return
close_context_menu()
}

export function close_context_menu() {
context_menu?.close()
context_menu = null
}

function _open_context_menu(e, title, values) {
close_context_menu()
const options = {
"title":title,
"event":e,
}
context_menu = LiteGraph.ContextMenu(values, options, app.canvas.getCanvasWindow())
}
export function open_context_menu(e, title, values) { setTimeout(_open_context_menu, 10, e, title, values) }

window.addEventListener('click',autoclose)
30 changes: 29 additions & 1 deletion js/controller.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
--second-back-color: #222222;
--third-back-color: #353535;

--overlay-background: #ffffff66;
--overlay-background: #ffffff99;
--overlay-foreground: #353535;

--mute-button-color:#ff6e6e;
Expand Down Expand Up @@ -576,6 +576,34 @@ i {
font-size: 80%;
}

.overlay_paging {
display:flex;
padding-bottom: 1px;
bottom: unset;
top: 2.5em;
}

.overlay_paging_icon {
font-family: 'primeicons';
min-width: 1em;
}
.overlay_paging_text {
text-align: center;
min-width: 2.5em;
padding: 0px 4px;
position: relative;
top: -1px;
}
.overlay_paging_icon:before {

}
.overlay_paging_icon.prev:before {
content: "\e928";
}
.overlay_paging_icon.next:before {
content: "\e92a";
}

.tooltip {
position: relative;
display: inline-block;
Expand Down
55 changes: 36 additions & 19 deletions js/controller.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { app } from "../../scripts/app.js"
import { api } from "../../scripts/api.js"
import { ControllerPanel } from "./controller_panel.js"
import { create, defineProperty, mouse_change } from "./utilities.js"
import { add_controls } from "./controller_controls.js"
import { create, mouse_change, send_graph_changed } from "./utilities.js"
import { OPTIONS } from "./options.js"
import { add_control_panel_options, NodeInclusionManager, } from "./node_inclusion.js"
import { OnChangeController, UpdateController } from "./update_controller.js"
import { Debug } from "./debug.js"
import { BASE_PATH } from "./constants.js"
import { BASE_PATH, SettingIds } from "./constants.js"
import { ImageManager } from "./image_manager.js"
import { global_settings } from "./settings.js"
import { NodeBlock } from "./nodeblock.js"
import { FancySlider } from "./input_slider.js"
import { SnapManager, WindowResizeManager } from "./snap_manager.js"
import { WindowResizeManager } from "./snap_manager.js"
import { Highlighter } from "./highlighter.js"
import { GroupManager } from "./groups.js"

Expand All @@ -35,7 +34,7 @@ function on_setup() {
NodeInclusionManager.node_change_callback = UpdateController.make_request
GroupManager.change_callback = ControllerPanel.on_group_details_change

api.addEventListener('graphCleared', ControllerPanel.graph_cleared)
api.addEventListener('graphCleared', ControllerPanel.on_graphCleared)

api.addEventListener('executed', ImageManager.on_executed)
api.addEventListener('execution_start', ImageManager.on_execution_start)
Expand All @@ -56,6 +55,17 @@ function on_setup() {
ControllerPanel.handle_mouse_move(e)
FancySlider.handle_mouse_move(e)
})
window.addEventListener('keypress', (e) => {
if (e.target.tagName=="CANVAS" || e.target.tagName=="BODY") {
const keysetting = app.ui.settings.getSettingValue(SettingIds.KEYBOARD_TOGGLE, "C")
if (keysetting==e.key) {
ControllerPanel.toggle()
e.preventDefault()
e.stopImmediatePropagation()
return false
}
}
})


const original_getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions;
Expand All @@ -78,6 +88,7 @@ function on_setup() {

app.registerExtension({
name: "cg.controller",
settings: OPTIONS,

async beforeConfigureGraph() {
UpdateController.configuring(true)
Expand All @@ -89,6 +100,7 @@ app.registerExtension({
try {
ImageManager.init()
ControllerPanel.new_workflow()
send_graph_changed(true)
} catch (e) {
console.error(e)
}
Expand All @@ -107,25 +119,18 @@ app.registerExtension({
on_setup()
} catch (e) { Debug.error("on setup", e) }

// add to the canvas menu, and keyboard shortcuts
try {
add_controls()
} catch (e) { Debug.error("add controls", e) }

try {
const on_change = app.graph.on_change
app.graph.on_change = function () {
const onAfterChange = app.graph.onAfterChange
app.graph.onAfterChange = function () {
try {
on_change?.apply(this,arguments)
OnChangeController.on_change()
onAfterChange?.apply(this,arguments)
OnChangeController.on_change('graph.onAfterChange')
} catch (e) {
Debug.error("on==_change", e)
Debug.error("onAfterChange", e)
}
}
Debug.trivia("*** in setup, ADDED on_change")
} catch (e) {
Debug.error("ADDING on_change", e)
console.error(e)
Debug.error("ADDING onAfterChange", e)
}

const draw = app.canvas.onDrawForeground;
Expand Down Expand Up @@ -205,7 +210,19 @@ app.registerExtension({
nodeType.prototype.onInputAdded = function () {
onInputAdded?.apply(this,arguments)
ControllerPanel.node_change(this.id)
app.graph.afterChange()
}
const onOutputRemoved = nodeType.prototype.onOutputRemoved
nodeType.prototype.onOutputRemoved = function () {
onOutputRemoved?.apply(this,arguments)
ControllerPanel.node_change(this.id)
}
const onOutputAdded = nodeType.prototype.onOutputAdded
nodeType.prototype.onOutputAdded = function () {
onOutputAdded?.apply(this,arguments)
ControllerPanel.node_change(this.id)
}

const onModeChange = nodeType.prototype.onModeChange
nodeType.prototype.onModeChange = function () {
onModeChange?.apply(this,arguments)
Expand Down
18 changes: 13 additions & 5 deletions js/controller_panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export class ControllerPanel extends HTMLDivElement {
if (changes.removed) {
this.settings.groups = this.settings.groups.filter((g)=>g!=oldname)
}
this.settings.groups = Array.from(new Set(this.settings.groups))
UpdateController.make_request('group change', Timings.GROUP_CHANGE_DELAY, false, this)
}
}
Expand Down Expand Up @@ -153,8 +154,12 @@ export class ControllerPanel extends HTMLDivElement {
Debug.trivia(`ControllerPanel.on_executing ${node_id}`)
Object.values(ControllerPanel.instances).forEach((cp)=>{
Object.values(cp.node_blocks).forEach((nb)=>{
nb.on_progress()
classSet(nb, 'active', nb.node.id==node_id)
try {
nb.on_progress()
classSet(nb, 'active', nb.node.id==node_id)
} catch (e) {
Debug.error(`on_executing: controller ${cp.index}, node ${node_id}`, e)
}
})
})
}
Expand Down Expand Up @@ -216,7 +221,7 @@ export class ControllerPanel extends HTMLDivElement {
ControllerPanel.update_buttons()
}

static graph_cleared() {
static on_graphCleared() {
UpdateController.make_request("graph_cleared")
}

Expand Down Expand Up @@ -340,6 +345,9 @@ export class ControllerPanel extends HTMLDivElement {
}

static node_change(node_id, moreinfo) {
setTimeout(ControllerPanel._node_change, Timings.GENERIC_SHORT_DELAY, node_id, moreinfo)
}
static _node_change(node_id, moreinfo) {
Object.values(ControllerPanel.instances).forEach((cp)=>{cp._node_change(node_id, moreinfo)})
}

Expand Down Expand Up @@ -686,7 +694,7 @@ export class ControllerPanel extends HTMLDivElement {
tab.addEventListener('mouseup', (e) => {
if (this.mouse_down_on == tab && Math.abs(this.mouse_down_at_x - e.x) < 2 && Math.abs(this.mouse_down_at_y - e.y) < 2) {
if (this.settings.collapsed) {
this.settings.collapsed = false;
this.settings.collapsed = false
UpdateController.make_single_request('uncollapse', this)
} else {
if (this.settings.group_choice == nm) {
Expand Down Expand Up @@ -778,7 +786,7 @@ export class ControllerPanel extends HTMLDivElement {
e.preventDefault();
e.stopPropagation();
if (app.canvas.read_only) return
this.settings.collapsed = (!this.settings.collapsed)
this.settings.collapsed = !this.settings.collapsed
UpdateController.make_single_request('collapse', this)
})
classSet(this.minimise_button, 'hidden', this.settings.collapsed)
Expand Down
Loading

0 comments on commit 040e570

Please sign in to comment.