fix tooltip application for dynamic inputs, feature info node

This commit is contained in:
ryanontheinstide
2025-01-05 20:40:33 -05:00
parent 3a87d889c2
commit f3dbb9735f
5 changed files with 67 additions and 12 deletions
+5 -1
View File
@@ -2,7 +2,6 @@ from .tooltips import TooltipManager, apply_tooltips
from .tooltips.categories import register_all_tooltips
# Register tooltips immediately after import
register_all_tooltips()
from .node_configs.node_configs import CombinedMeta
from collections import OrderedDict
@@ -78,6 +77,7 @@ from .nodes.flex.feature_extractors import(
ManualFeatureNode,
ManualFeatureFromPipe,
DrawableFeatureNode,
FeatureInfoNode,
)
from .nodes.flex.feature_extractors_audio import(
@@ -410,6 +410,7 @@ NODE_CLASS_MAPPINGS = {
"LocationFromPoint": LocationFromPoint,
"LocationTransform": LocationTransform,
"AreaFeatureNode": AreaFeatureNode,
"FeatureInfoNode": FeatureInfoNode,
"FeatureToWeightsStrategy": FeatureToWeightsStrategy,
"FeatureToSplineData": FeatureToSplineData,
@@ -593,3 +594,6 @@ if hasattr(PromptServer, "instance"):
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
register_all_tooltips()
+35 -1
View File
@@ -20,10 +20,14 @@ class FeatureExtractorBase(RyanOnTheInside, ABC):
@classmethod
def INPUT_TYPES(cls):
print(f"\n[DEBUG] Getting INPUT_TYPES for {cls.__name__}")
feature_class = cls.feature_type()
print(f"[DEBUG] Feature class: {feature_class.__name__}")
extraction_methods = feature_class.get_extraction_methods()
print(f"[DEBUG] Extraction methods: {extraction_methods}")
return {
"required": {
"extraction_method": (feature_class.get_extraction_methods(), {"default": feature_class.get_extraction_methods()[0]}),
"extraction_method": (extraction_methods, {"default": extraction_methods[0]}),
"frame_rate": ("FLOAT", {"default": 30.0, "min": 1.0, "max": 120.0, "step": 0.1}),
"frame_count": ("INT", {"default": 30, "min": 1}),
"width": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}),
@@ -392,7 +396,37 @@ class DrawableFeatureNode(FeatureExtractorBase):
return (drawable_feature,)
@apply_tooltips
class FeatureInfoNode(RyanOnTheInside):
"""
Node that extracts common information from feature inputs.
"""
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"feature": ("FEATURE",), # Accepts any feature type
}
}
RETURN_TYPES = ("STRING", "STRING", "INT", "INT", "INT", "INT")
RETURN_NAMES = ("name", "type", "frame_rate", "frame_count", "width", "height")
FUNCTION = "get_info"
CATEGORY = "Ryan/Features"
def get_info(self, feature):
"""Extract common information from the feature"""
return (
feature.name,
feature.type,
feature.frame_rate,
feature.frame_count,
feature.width if feature.width is not None else 0,
feature.height if feature.height is not None else 0
)
+2
View File
@@ -7,6 +7,7 @@ from scipy.interpolate import interp1d, make_interp_spline
class BaseFeature(ABC):
def __init__(self, name, feature_type, frame_rate, frame_count, width, height):
print(f"\n[DEBUG] Initializing BaseFeature: {name} of type {feature_type}")
self.name = name
self.type = feature_type
self.frame_rate = frame_rate
@@ -25,6 +26,7 @@ class BaseFeature(ABC):
@abstractmethod
def get_extraction_methods(cls):
"""Return a list of parameter names that can be modulated."""
print(f"\n[DEBUG] Getting extraction methods for {cls.__name__}")
return []
def get_value_at_frame(self, frame_index):
+1 -1
View File
@@ -12,7 +12,7 @@ from typing import List
import torch.nn.functional as F
from ...tooltips import apply_tooltips
@apply_tooltips
# @apply_tooltips
class FlexMaskMorph(FlexMaskBase):
@classmethod
def INPUT_TYPES(cls):
+24 -9
View File
@@ -163,10 +163,10 @@ def apply_tooltips(node_class):
@classmethod
def input_types_with_tooltips(cls):
try:
input_types = original_input_types()
if input_types is None:
input_types = original_input_types.__get__(cls, cls)()
if not isinstance(input_types, dict):
return original_input_types.__get__(cls, cls)()
except Exception:
except Exception as e:
return original_input_types.__get__(cls, cls)()
tooltips = TooltipManager.get_tooltips(cls.__name__)
@@ -174,17 +174,30 @@ def apply_tooltips(node_class):
def add_tooltip_to_config(param_name, config):
if param_name not in tooltips:
return config
tooltip = tooltips[param_name]
# Handle tuple format (type, config_dict)
if isinstance(config, tuple):
if len(config) == 2 and isinstance(config[1], dict):
if len(config) == 2:
param_type, param_config = config
param_config = param_config.copy()
param_config["tooltip"] = tooltip
return (param_type, param_config)
# If param_config is already a dict, just add the tooltip
if isinstance(param_config, dict):
param_config = param_config.copy()
param_config["tooltip"] = tooltip
return (param_type, param_config)
# If param_type is a list, this is a dropdown without config
elif isinstance(param_type, list):
return (param_type, {"tooltip": tooltip})
# If param_type is a tuple containing a method call result, preserve it
elif isinstance(param_type, tuple) and len(param_type) > 0:
return (param_type, {"tooltip": tooltip})
# Otherwise treat second element as is
return config
elif len(config) == 1:
# Handle single-element tuples that might be method call results
if isinstance(config[0], tuple):
return (config[0], {"tooltip": tooltip})
return (config[0], {"tooltip": tooltip})
return config
@@ -213,8 +226,10 @@ def apply_tooltips(node_class):
param_name: add_tooltip_to_config(param_name, config)
for param_name, config in input_types["optional"].items()
}
return input_types
# Replace the original INPUT_TYPES with our wrapped version
node_class.INPUT_TYPES = input_types_with_tooltips
return node_class