187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
"""
|
|
Augment - ComfyUI Custom Node Pack
|
|
Resilient loader: each node imports independently so one failure won't block the rest.
|
|
"""
|
|
|
|
import traceback
|
|
|
|
NODE_CLASS_MAPPINGS = {}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
_failed = []
|
|
|
|
|
|
def _register(module_path, imports, mappings):
|
|
"""
|
|
Try to import `imports` from `module_path` and register each into the global dicts.
|
|
|
|
imports: list of (ClassName,) — names to import from the module
|
|
mappings: dict of { "NodeID": ("ClassName", "Display Name") }
|
|
"""
|
|
try:
|
|
mod = __import__(module_path, fromlist=[c for c in imports])
|
|
except Exception as e:
|
|
for node_id, (cls_name, display) in mappings.items():
|
|
_failed.append((node_id, e))
|
|
print(f"[augment] ⚠ {node_id} unavailable: {e}")
|
|
return
|
|
|
|
for node_id, (cls_name, display) in mappings.items():
|
|
cls = getattr(mod, cls_name, None)
|
|
if cls is None:
|
|
_failed.append((node_id, f"{cls_name} not found in {module_path}"))
|
|
print(f"[augment] ⚠ {node_id} unavailable: {cls_name} not found in {module_path}")
|
|
continue
|
|
NODE_CLASS_MAPPINGS[node_id] = cls
|
|
NODE_DISPLAY_NAME_MAPPINGS[node_id] = display
|
|
|
|
|
|
# ── Executor Override (must import first to patch ComfyUI) ──
|
|
try:
|
|
__import__("custom_nodes.augment.py.executor")
|
|
except Exception as e:
|
|
print(f"[augment] ⚠ Executor patch unavailable: {e}")
|
|
|
|
# ── Image Processing & Cropping ──
|
|
_register("custom_nodes.augment.py.face_crop", ["FaceCrop"], {
|
|
"AugmentFaceCrop": ("FaceCrop", "Face Crop"),
|
|
})
|
|
|
|
_register("custom_nodes.augment.py.image_crop", ["ImageCrop"], {
|
|
"AugmentImageCrop": ("ImageCrop", "Image Crop"),
|
|
})
|
|
_register("custom_nodes.augment.py.image_place", ["ImagePlaceNode"], {
|
|
"AugmentImagePlace": ("ImagePlaceNode", "Image Place"),
|
|
})
|
|
_register("custom_nodes.augment.py.invert_image", ["InvertImageNode"], {
|
|
"AugmentInvertImage": ("InvertImageNode", "Invert Image"),
|
|
})
|
|
_register("custom_nodes.augment.py.image_rotate", ["ImageRotateNode"], {
|
|
"AugmentImageRotate": ("ImageRotateNode", "Image Rotate"),
|
|
})
|
|
_register("custom_nodes.augment.py.image_flip", ["ImageFlipNode"], {
|
|
"AugmentImageFlip": ("ImageFlipNode", "Image Flip"),
|
|
})
|
|
_register("custom_nodes.augment.py.logo_mask", ["LogoMask"], {
|
|
"AugmentLogoMask": ("LogoMask", "Logo Mask"),
|
|
})
|
|
_register("custom_nodes.augment.py.mask_bounding_box", ["MaskBoundingBox"], {
|
|
"AugmentMaskBoundingBox": ("MaskBoundingBox", "Mask Bounding Box"),
|
|
})
|
|
# ── Grid & Construction Lines ──
|
|
_register("custom_nodes.augment.py.grid", ["GridGenerator"], {
|
|
"AugmentGridGenerator": ("GridGenerator", "Grid Generator"),
|
|
})
|
|
_register("custom_nodes.augment.py.grid_coords", ["GridCoordsNode"], {
|
|
"AugmentGridCoords": ("GridCoordsNode", "Grid Coords"),
|
|
})
|
|
_register("custom_nodes.augment.py.draw_line", ["LineDrawNode"], {
|
|
"AugmentLineDraw": ("LineDrawNode", "Line Draw"),
|
|
})
|
|
_register("custom_nodes.augment.py.circle_draw", ["CircleDrawNode"], {
|
|
"AugmentCircleDraw": ("CircleDrawNode", "Circle Draw"),
|
|
})
|
|
_register("custom_nodes.augment.py.fib", ["FibonacciSpiralNode"], {
|
|
"AugmentFibonacciSpiral": ("FibonacciSpiralNode", "Fibonacci Spiral"),
|
|
})
|
|
_register("custom_nodes.augment.py.construction_lines", ["ConstructionLineOverlay"], {
|
|
"AugmentConstructionLineOverlay": ("ConstructionLineOverlay", "Construction Line Overlay"),
|
|
})
|
|
_register("custom_nodes.augment.py.edge_detect", ["ShapeEdgeDetect"], {
|
|
"AugmentShapeEdgeDetect": ("ShapeEdgeDetect", "Shape Edge Detect"),
|
|
})
|
|
|
|
# ── Color & Effects ──
|
|
_register("custom_nodes.augment.py.recolor", ["RecolorNode"], {
|
|
"AugmentRecolor": ("RecolorNode", "Recolor (Mask)"),
|
|
})
|
|
_register("custom_nodes.augment.py.blur_average", ["BlurAverageNode"], {
|
|
"AugmentBlurAverage": ("BlurAverageNode", "Blur Average (Dominant Color)"),
|
|
})
|
|
|
|
# ── Primitives ──
|
|
_register("custom_nodes.augment.py.prim_node", ["IntNode", "FloatNode", "StringNode", "BoolNode"], {
|
|
"AugmentIntPrim": ("IntNode", "Int"),
|
|
"AugmentFloatPrim": ("FloatNode", "Float"),
|
|
"AugmentStringPrim": ("StringNode", "String"),
|
|
"AugmentBoolPrim": ("BoolNode", "Bool"),
|
|
})
|
|
|
|
# ── Variables ──
|
|
_register("custom_nodes.augment.py.variables", [
|
|
"NumberVarSetNode", "NumberVarGetNode", "NumberVarIncrementNode",
|
|
"NumberVarDecrementNode", "NumberVarResetNode",
|
|
"StringVarSetNode", "StringVarGetNode", "StringVarDeleteNode",
|
|
], {
|
|
"AugmentNumberVarSet": ("NumberVarSetNode", "Variable Set (Number)"),
|
|
"AugmentNumberVarGet": ("NumberVarGetNode", "Variable Get (Number)"),
|
|
"AugmentNumberVarIncrement": ("NumberVarIncrementNode", "Variable Increment (Number)"),
|
|
"AugmentNumberVarDecrement": ("NumberVarDecrementNode", "Variable Decrement (Number)"),
|
|
"AugmentNumberVarReset": ("NumberVarResetNode", "Variable Reset (Number)"),
|
|
"AugmentStringVarSet": ("StringVarSetNode", "Variable Set (String)"),
|
|
"AugmentStringVarGet": ("StringVarGetNode", "Variable Get (String)"),
|
|
"AugmentStringVarDelete": ("StringVarDeleteNode", "Variable Delete (String)"),
|
|
})
|
|
|
|
# ── Flow Control ──
|
|
try:
|
|
from .py.trigger import make_wait_node, WAIT_TYPES
|
|
for _name, _type_str in WAIT_TYPES.items():
|
|
_cls_name = f"AugmentWait{_name}"
|
|
try:
|
|
NODE_CLASS_MAPPINGS[_cls_name] = make_wait_node(_name, _type_str)
|
|
NODE_DISPLAY_NAME_MAPPINGS[_cls_name] = f"{_name} (Improved)"
|
|
except Exception as e:
|
|
_failed.append((_cls_name, e))
|
|
print(f"[augment] ⚠ {_cls_name} unavailable: {e}")
|
|
except Exception as e:
|
|
_failed.append(("Wait nodes", e))
|
|
print(f"[augment] ⚠ Flow control nodes unavailable: {e}")
|
|
|
|
|
|
# PAID
|
|
|
|
_register("custom_nodes.augment.py.svg_tools", ["AugmentSVGToPNG", "AugmentPNGToSVG"], {
|
|
"AugmentSVGToPNG": ("AugmentSVGToPNG", "Augment SVG to PNG"),
|
|
"AugmentPNGToSVG": ("AugmentPNGToSVG", "Augment PNG to SVG"),
|
|
})
|
|
|
|
# ── Crypto & Utilities ──
|
|
_register("custom_nodes.augment.py.crypto", ["SHA256Node", "RandomNumberNode", "UUIDNode"], {
|
|
"AugmentSHA256": ("SHA256Node", "SHA-256 Hash"),
|
|
"AugmentRandomNumber": ("RandomNumberNode", "Random Number"),
|
|
"AugmentUUID": ("UUIDNode", "UUID Generator"),
|
|
})
|
|
_register("custom_nodes.augment.py.json_viewer", ["JsonViewerNode"], {
|
|
"AugmentJsonViewer": ("JsonViewerNode", "JSON Viewer"),
|
|
})
|
|
|
|
_register("custom_nodes.augment.py.json_extract", ["JsonExtractNode"], {
|
|
"AugmentJsonExtract": ("JsonExtractNode", "JSON Extract"),
|
|
})
|
|
|
|
# ── Preview & Save ──
|
|
_register("custom_nodes.augment.py.preview", ["AugmentPreviewImage", "AugmentSaveImage", "AugmentPreviewAny"], {
|
|
"AugmentPreviewImage": ("AugmentPreviewImage", "Preview Image"),
|
|
"AugmentSaveImage": ("AugmentSaveImage", "Save Image (Improved)"),
|
|
"AugmentPreviewAny": ("AugmentPreviewAny", "Preview Any"),
|
|
})
|
|
|
|
_register("custom_nodes.augment.py.load_image", ["AugmentLoadImage"], {
|
|
"AugmentLoadImage": ("AugmentLoadImage", "Load Image (Improved)"),
|
|
})
|
|
|
|
_register("custom_nodes.augment.py.switch", ["SwitchNode"], {
|
|
"AugmentSwitchNode": ("SwitchNode", "Switch Improved"),
|
|
})
|
|
|
|
# ── Summary ──
|
|
WEB_DIRECTORY = "./web/js"
|
|
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
|
|
|
if _failed:
|
|
print(f"[augment] ✓ Registered {len(NODE_CLASS_MAPPINGS)} nodes ({len(_failed)} failed)")
|
|
for node_id, err in _failed:
|
|
print(f"[augment] ✗ {node_id}: {err}")
|
|
else:
|
|
print(f"[augment] ✓ Registered {len(NODE_CLASS_MAPPINGS)} nodes")
|