Files

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")