Skip to content

Commit 32c8fa5

Browse files
Merge pull request #16 from ryanontheinside/refactor/phase-3
Refactor/phase 3
2 parents 8d54b4c + 509a8eb commit 32c8fa5

File tree

109 files changed

+5197
-3699
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+5197
-3699
lines changed

__init__.py

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import os
21
import importlib
32
import inspect
3+
import os
44
import re
55
import traceback
66

@@ -11,74 +11,79 @@
1111

1212
print("\033[93m" + "[ComfyUI_RealtimeNodes] Loading nodes...")
1313

14+
1415
def load_nodes_from_directory(package_path):
1516
"""Dynamically loads nodes from Python files in a directory."""
16-
loaded_nodes = {}
17+
loaded_nodes = {}
1718
loaded_display_names = {}
18-
19+
1920
# Calculate absolute path to the package directory
20-
package_abs_path = os.path.join(os.path.dirname(__file__), *package_path.split('.'))
21-
21+
package_abs_path = os.path.join(os.path.dirname(__file__), *package_path.split("."))
22+
2223
if not os.path.isdir(package_abs_path):
2324
print(f"\033[91m" + f"[ComfyUI_RealtimeNodes] Warning: Directory not found: {package_abs_path}")
2425
return loaded_nodes, loaded_display_names
2526

2627
print(f"\033[92m" + f"[ComfyUI_RealtimeNodes] Searching for nodes in: {package_abs_path}")
2728

2829
for filename in os.listdir(package_abs_path):
29-
if filename.endswith(".py") and not filename.startswith('__'):
30+
if filename.endswith(".py") and not filename.startswith("__"):
3031
module_name = filename[:-3]
31-
full_module_path = f".{package_path}.{module_name}" # Relative import path
32-
32+
full_module_path = f".{package_path}.{module_name}" # Relative import path
33+
3334
try:
3435
module = importlib.import_module(full_module_path, package=__name__)
35-
36+
3637
# Find classes defined in the module
3738
for name, obj in inspect.getmembers(module):
3839
if inspect.isclass(obj):
3940
# Check if it's a ComfyUI node (heuristic: has INPUT_TYPES)
40-
if hasattr(obj, 'INPUT_TYPES') and callable(obj.INPUT_TYPES):
41-
# Exclude base classes/mixins if they are explicitly named or lack a CATEGORY
42-
if not name.endswith("Base") and not name.endswith("Mixin") and hasattr(obj, 'CATEGORY'):
41+
if hasattr(obj, "INPUT_TYPES") and callable(obj.INPUT_TYPES):
42+
# Exclude base classes/mixins if they are explicitly named or lack a CATEGORY
43+
if not name.endswith("Base") and not name.endswith("Mixin") and hasattr(obj, "CATEGORY"):
4344
loaded_nodes[name] = obj
44-
45+
4546
# Generate display name (similar to original logic)
46-
display_name = ' '.join(word.capitalize() for word in re.findall(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\W|$)|\d+', name))
47+
display_name = " ".join(
48+
word.capitalize() for word in re.findall(r"[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\W|$)|\d+", name)
49+
)
4750
suffix = " 🕒🅡🅣🅝"
4851
if not display_name.endswith(suffix):
4952
display_name += suffix
5053
loaded_display_names[name] = display_name
5154
print(f"\033[94m" + f"[ComfyUI_RealtimeNodes] - Loaded node: {name} -> {display_name}")
52-
55+
5356
except ImportError as e:
5457
print(f"\033[91m" + f"[ComfyUI_RealtimeNodes] Error importing module {full_module_path}: {e}")
5558
traceback.print_exc()
5659
except Exception as e:
5760
print(f"\033[91m" + f"[ComfyUI_RealtimeNodes] Error processing module {full_module_path}: {e}")
5861
traceback.print_exc()
59-
62+
6063
return loaded_nodes, loaded_display_names
6164

65+
6266
# --- Main Loading Logic ---
6367

6468
# Get base path for the node_wrappers directory
6569
base_dir_path = os.path.join(os.path.dirname(__file__), WRAPPER_DIR)
6670

71+
6772
# Recursively scan all directories and subdirectories
6873
def scan_for_modules(base_path, base_package):
6974
"""Recursively scan directories for module files"""
7075
try:
7176
for item in os.listdir(base_path):
7277
item_path = os.path.join(base_path, item)
73-
78+
7479
# Skip __pycache__ and files/dirs starting with __
75-
if item.startswith('__'):
80+
if item.startswith("__"):
7681
continue
77-
82+
7883
if os.path.isdir(item_path):
7984
# Handle subdirectory
8085
subdir_package = f"{base_package}.{item}"
81-
86+
8287
# First load .py files in this directory
8388
try:
8489
nodes, display_names = load_nodes_from_directory(subdir_package)
@@ -87,14 +92,15 @@ def scan_for_modules(base_path, base_package):
8792
except Exception as e:
8893
print(f"\033[91m" + f"[ComfyUI_RealtimeNodes] Error processing directory {subdir_package}: {e}")
8994
traceback.print_exc()
90-
95+
9196
# Then recursively process subdirectories
9297
subdir_path = os.path.join(base_path, item)
9398
scan_for_modules(subdir_path, subdir_package)
9499
except Exception as e:
95100
print(f"\033[91m" + f"[ComfyUI_RealtimeNodes] Error scanning directory {base_path}: {e}")
96101
traceback.print_exc()
97102

103+
98104
# Start recursive scanning from the base directory
99105
print(f"\033[92m" + f"[ComfyUI_RealtimeNodes] Scanning node_wrappers directory for modules...")
100106
scan_for_modules(base_dir_path, WRAPPER_DIR)
@@ -104,19 +110,19 @@ def scan_for_modules(base_path, base_package):
104110
for node_name in NODE_CLASS_MAPPINGS.keys():
105111
# Convert camelCase or snake_case to Title Case
106112
if node_name not in NODE_DISPLAY_NAME_MAPPINGS:
107-
display_name = ' '.join(word.capitalize() for word in re.findall(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\W|$)|\d+', node_name))
113+
display_name = " ".join(word.capitalize() for word in re.findall(r"[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\W|$)|\d+", node_name))
108114
else:
109115
display_name = NODE_DISPLAY_NAME_MAPPINGS[node_name]
110-
116+
111117
# Add the suffix if it's not already present
112118
if not display_name.endswith(suffix):
113119
display_name += suffix
114-
120+
115121
# Assign the final display name to the mappings
116122
NODE_DISPLAY_NAME_MAPPINGS[node_name] = display_name
117123
# --- Original Web Directory and Export ---
118-
WEB_DIRECTORY = "./web/js" # Adjusted path if needed
124+
WEB_DIRECTORY = "./web/js" # Adjusted path if needed
119125

120-
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
126+
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
121127

122-
print("\033[92m" + f"[ComfyUI_RealtimeNodes] Loaded {len(NODE_CLASS_MAPPINGS)} nodes.")
128+
print("\033[92m" + f"[ComfyUI_RealtimeNodes] Loaded {len(NODE_CLASS_MAPPINGS)} nodes.")

node_wrappers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# This file intentionally left blank
1+
# This file intentionally left blank

node_wrappers/coordinates/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,3 @@
44
This package provides node wrappers for the coordinate system functionality,
55
allowing users to convert between coordinate spaces and create coordinate objects.
66
"""
7-
8-
from .conversion_nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
9-
10-
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']

node_wrappers/coordinates/conversion_nodes.py

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
These nodes provide user-friendly interfaces for the coordinate system functionality.
55
"""
66

7-
import torch
87
import logging
9-
from typing import Union, List, Tuple
108

119
from ...src.coordinates import CoordinateSystem
1210

1311
logger = logging.getLogger(__name__)
1412

13+
1514
class CoordinateConverterNode:
1615
"""
1716
Fast coordinate conversion between different coordinate spaces.
1817
"""
18+
1919
CATEGORY = "Realtime Nodes/Coordinates"
2020
FUNCTION = "convert_coordinates"
2121
RETURN_TYPES = ("FLOAT", "FLOAT")
@@ -42,20 +42,20 @@ def convert_coordinates(self, x, y, image_for_dimensions, from_space, to_space):
4242
try:
4343
# Get dimensions from image
4444
dimensions = CoordinateSystem.get_dimensions_from_tensor(image_for_dimensions)
45-
45+
4646
# Map string inputs to CoordinateSystem constants
4747
space_map = {
4848
"pixel": CoordinateSystem.PIXEL,
4949
"normalized": CoordinateSystem.NORMALIZED,
5050
}
51-
51+
5252
from_space_const = space_map[from_space]
5353
to_space_const = space_map[to_space]
54-
54+
5555
# Convert coordinates
5656
x_out = CoordinateSystem.convert(x, dimensions[0], from_space_const, to_space_const)
5757
y_out = CoordinateSystem.convert(y, dimensions[1], from_space_const, to_space_const)
58-
58+
5959
return (x_out, y_out)
6060
except Exception as e:
6161
logger.error(f"Error in coordinate conversion: {e}")
@@ -66,6 +66,7 @@ class Point2DNode:
6666
"""
6767
Creates a 2D point with coordinate space awareness.
6868
"""
69+
6970
CATEGORY = "Realtime Nodes/Coordinates"
7071
FUNCTION = "create_point"
7172
RETURN_TYPES = ("POINT",)
@@ -80,33 +81,37 @@ def INPUT_TYPES(cls):
8081
"space": (["normalized", "pixel"],),
8182
},
8283
"optional": {
83-
"image_for_dimensions": ("IMAGE", {"tooltip": "Reference image for dimensions (required for pixel space)"}),
84-
}
84+
"image_for_dimensions": (
85+
"IMAGE",
86+
{"tooltip": "Reference image for dimensions (required for pixel space)"},
87+
),
88+
},
8589
}
8690

8791
def create_point(self, x, y, space, image_for_dimensions=None):
8892
"""Create a Point object."""
8993
from ...src.coordinates import Point
90-
94+
9195
space_map = {
9296
"pixel": CoordinateSystem.PIXEL,
9397
"normalized": CoordinateSystem.NORMALIZED,
9498
}
95-
99+
96100
space_const = space_map[space]
97-
101+
98102
# Validate dimensions if using pixel space
99103
if space == "pixel" and image_for_dimensions is None:
100104
logger.warning("Pixel space selected but no image provided for dimensions. Using normalized space.")
101105
space_const = CoordinateSystem.NORMALIZED
102-
106+
103107
return (Point(x, y, None, space_const),)
104108

105109

106110
class PointListNode:
107111
"""
108112
Creates a list of points from coordinate lists.
109113
"""
114+
110115
CATEGORY = "Realtime Nodes/Coordinates"
111116
FUNCTION = "create_point_list"
112117
RETURN_TYPES = ("POINT_LIST",)
@@ -116,40 +121,52 @@ class PointListNode:
116121
def INPUT_TYPES(cls):
117122
return {
118123
"required": {
119-
"x_coords": ("FLOAT", {"default": [0.25, 0.5, 0.75], "forceInput": True, "tooltip": "List of X coordinates"}),
120-
"y_coords": ("FLOAT", {"default": [0.25, 0.5, 0.75], "forceInput": True, "tooltip": "List of Y coordinates"}),
124+
"x_coords": (
125+
"FLOAT",
126+
{"default": [0.25, 0.5, 0.75], "forceInput": True, "tooltip": "List of X coordinates"},
127+
),
128+
"y_coords": (
129+
"FLOAT",
130+
{"default": [0.25, 0.5, 0.75], "forceInput": True, "tooltip": "List of Y coordinates"},
131+
),
121132
"space": (["normalized", "pixel"],),
122133
},
123134
"optional": {
124-
"z_coords": ("FLOAT", {"default": None, "forceInput": True, "tooltip": "List of Z coordinates (optional)"}),
125-
"image_for_dimensions": ("IMAGE", {"tooltip": "Reference image for dimensions (required for pixel space)"}),
126-
}
135+
"z_coords": (
136+
"FLOAT",
137+
{"default": None, "forceInput": True, "tooltip": "List of Z coordinates (optional)"},
138+
),
139+
"image_for_dimensions": (
140+
"IMAGE",
141+
{"tooltip": "Reference image for dimensions (required for pixel space)"},
142+
),
143+
},
127144
}
128145

129146
def create_point_list(self, x_coords, y_coords, space, z_coords=None, image_for_dimensions=None):
130147
"""Create a PointList object."""
131148
from ...src.coordinates import PointList
132-
149+
133150
space_map = {
134151
"pixel": CoordinateSystem.PIXEL,
135152
"normalized": CoordinateSystem.NORMALIZED,
136153
}
137-
154+
138155
space_const = space_map[space]
139-
156+
140157
# Validate dimensions if using pixel space
141158
if space == "pixel" and image_for_dimensions is None:
142159
logger.warning("Pixel space selected but no image provided for dimensions. Using normalized space.")
143160
space_const = CoordinateSystem.NORMALIZED
144-
161+
145162
# Ensure inputs are lists
146163
if not isinstance(x_coords, list):
147164
x_coords = [x_coords]
148165
if not isinstance(y_coords, list):
149166
y_coords = [y_coords]
150167
if z_coords is not None and not isinstance(z_coords, list):
151168
z_coords = [z_coords]
152-
169+
153170
return (PointList.from_coordinates(x_coords, y_coords, z_coords, space_const),)
154171

155172

@@ -165,4 +182,4 @@ def create_point_list(self, x_coords, y_coords, space, z_coords=None, image_for_
165182
"CoordinateConverter": "Coordinate Converter",
166183
"Point2D": "Create 2D Point",
167184
"PointList": "Create Point List",
168-
}
185+
}

0 commit comments

Comments
 (0)