171 lines
5.8 KiB
Python
171 lines
5.8 KiB
Python
# Set this to True to disable all tooltips
|
|
DISABLE_TOOLTIPS = False
|
|
|
|
if not DISABLE_TOOLTIPS:
|
|
from .tooltips import TooltipManager, apply_tooltips
|
|
from .tooltips.categories import register_all_tooltips
|
|
|
|
from comfy.utils import ProgressBar
|
|
from tqdm import tqdm
|
|
from .node_configs.node_configs import CombinedMeta
|
|
from collections import OrderedDict
|
|
import os
|
|
import folder_paths
|
|
import shutil
|
|
|
|
#NOTE: THIS IS LEGACY FOR BACKWARD COMPATIBILITY. FUNCTIONALLY REPLACED BY TOOLTIPS.
|
|
#NOTE: allows for central management and inheritance of class variables for help documentation
|
|
class RyanOnTheInside(metaclass=CombinedMeta):
|
|
@classmethod
|
|
def get_description(cls):
|
|
return ""
|
|
|
|
class ProgressMixin:
|
|
def start_progress(self, total_steps, desc="Processing"):
|
|
self.progress_bar = ProgressBar(total_steps)
|
|
self.tqdm_bar = tqdm(total=total_steps, desc=desc, leave=False)
|
|
self.current_progress = 0
|
|
self.total_steps = total_steps
|
|
|
|
def update_progress(self, step=1):
|
|
self.current_progress += step
|
|
if self.progress_bar:
|
|
self.progress_bar.update(step)
|
|
if self.tqdm_bar:
|
|
self.tqdm_bar.update(step)
|
|
|
|
def end_progress(self):
|
|
if self.tqdm_bar:
|
|
self.tqdm_bar.close()
|
|
self.progress_bar = None
|
|
self.tqdm_bar = None
|
|
self.current_progress = 0
|
|
self.total_steps = 0
|
|
|
|
try:
|
|
print("RYAN ON THE INSIDE - Custom Nodes Loaded", flush=True)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
import importlib
|
|
import logging
|
|
|
|
# Get the directory of the current file
|
|
current_dir = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
# Register the midi_files directory
|
|
midi_path = os.path.join(current_dir, "data/midi_files")
|
|
folder_paths.add_model_folder_path("midi_files", midi_path)
|
|
|
|
# Ensure the MIDI files directory exists
|
|
os.makedirs(midi_path, exist_ok=True)
|
|
|
|
# Get the path to ComfyUI's web/extensions directory
|
|
extension_path = os.path.join(os.path.dirname(folder_paths.__file__), "web", "extensions")
|
|
my_extension_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "web", "extensions")
|
|
|
|
# Create RyanOnTheInside subfolder in ComfyUI extensions
|
|
roti_extension_path = os.path.join(extension_path, "RyanOnTheInside")
|
|
os.makedirs(roti_extension_path, exist_ok=True)
|
|
|
|
# Clean up existing files in the RyanOnTheInside folder
|
|
for file in os.listdir(roti_extension_path):
|
|
os.remove(os.path.join(roti_extension_path, file))
|
|
|
|
# Copy our extension files to ComfyUI's extensions/RyanOnTheInside directory
|
|
if os.path.exists(my_extension_path):
|
|
for file in os.listdir(my_extension_path):
|
|
if file.endswith('.js'):
|
|
src = os.path.join(my_extension_path, file)
|
|
dst = os.path.join(roti_extension_path, file)
|
|
print(f"[RyanOnTheInside] Copying extension file: {file}")
|
|
shutil.copy2(src, dst)
|
|
_NODE_MODULES = [
|
|
".nodes.misc.misc_nodes",
|
|
".nodes.masks.temporal_masks",
|
|
".nodes.audio.audio_nodes",
|
|
".nodes.audio.flex_audio_visualizer",
|
|
".nodes.audio.audio_nodes_effects",
|
|
".nodes.audio.audio_compare",
|
|
".nodes.audio.audio_nodes_utility",
|
|
".nodes.audio.midi_nodes",
|
|
".nodes.audio.flex_audio",
|
|
".nodes.flex.feature_extractors",
|
|
".nodes.flex.feature_extractors_whisper",
|
|
".nodes.flex.feature_extractors_audio",
|
|
".nodes.flex.feature_extractors_midi",
|
|
".nodes.flex.feature_extractors_proximity",
|
|
".nodes.flex.visualizers",
|
|
".nodes.flex.flex_externals",
|
|
".nodes.flex.feature_modulation",
|
|
".nodes.flex.feature_combiner",
|
|
".nodes.flex.feature_pipe",
|
|
".nodes.flex.parameter_scheduling",
|
|
".nodes.masks.optical_flow_masks",
|
|
".nodes.masks.particle_system_masks",
|
|
".nodes.masks.mask_utility_nodes",
|
|
".nodes.masks.flex_masks",
|
|
".nodes.images.flex_images",
|
|
".nodes.images.image_utility_nodes",
|
|
".nodes.video.flex_video",
|
|
".nodes.depth.depth_base",
|
|
".nodes.utility_nodes",
|
|
".nodes.latents.flex_latents",
|
|
".nodes.latents.latent_frequency_blender",
|
|
".nodes.doom.doom",
|
|
".audio_latent_blend",
|
|
".external_integration",
|
|
".nodes.acestep.nodes",
|
|
]
|
|
|
|
NODE_CLASS_MAPPINGS = {}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
|
|
for _mod_path in _NODE_MODULES:
|
|
try:
|
|
_mod = importlib.import_module(_mod_path, package=__name__)
|
|
if hasattr(_mod, "NODE_CLASS_MAPPINGS"):
|
|
NODE_CLASS_MAPPINGS.update(_mod.NODE_CLASS_MAPPINGS)
|
|
if hasattr(_mod, "NODE_DISPLAY_NAME_MAPPINGS"):
|
|
NODE_DISPLAY_NAME_MAPPINGS.update(_mod.NODE_DISPLAY_NAME_MAPPINGS)
|
|
except Exception as _e:
|
|
logging.warning(f"[RyanOnTheInside] Failed to load {_mod_path}: {_e}")
|
|
|
|
WEB_DIRECTORY = "./web/js"
|
|
EXTENSION_WEB_DIRS = ["./web/extensions"]
|
|
|
|
import re
|
|
|
|
suffix = " ⚡🅡🅞🅣🅘"
|
|
|
|
for node_name in NODE_CLASS_MAPPINGS.keys():
|
|
if node_name not in NODE_DISPLAY_NAME_MAPPINGS:
|
|
# Convert camelCase or snake_case to Title Case
|
|
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))
|
|
else:
|
|
display_name = NODE_DISPLAY_NAME_MAPPINGS[node_name]
|
|
|
|
# Add the suffix if it's not already present
|
|
if not display_name.endswith(suffix):
|
|
display_name += suffix
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS[node_name] = display_name
|
|
|
|
|
|
from aiohttp import web
|
|
from server import PromptServer
|
|
from pathlib import Path
|
|
|
|
# if hasattr(PromptServer, "instance"):
|
|
# # NOTE: we add an extra static path to avoid comfy mechanism
|
|
# # that loads every script in web.
|
|
# #
|
|
# # Again credit to KJNodes and MTB nodes
|
|
# PromptServer.instance.app.add_routes(
|
|
# [web.static("/ryanontheinside_web_async", (Path(__file__).parent.absolute() / "ryanontheinside_web_async").as_posix())]
|
|
# )
|
|
# #register tooltips after all classes are initialized
|
|
if not DISABLE_TOOLTIPS:
|
|
register_all_tooltips()
|