fix tooltip application for dynamic inputs, feature info node
This commit is contained in:
+5
-1
@@ -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()
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user