131 lines
4.8 KiB
Python
131 lines
4.8 KiB
Python
from ..base.control_base import ControlNodeBase
|
|
|
|
class SequenceControlBase(ControlNodeBase):
|
|
"""Base class for sequence-based controls"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
inputs = super().INPUT_TYPES()
|
|
inputs["required"].update({
|
|
"steps_per_item": ("INT", {
|
|
"default": 30,
|
|
"min": 1,
|
|
"max": 1000,
|
|
"step": 1,
|
|
"tooltip": "Number of frames to show each item"
|
|
}),
|
|
"sequence_mode": (["forward", "reverse", "pingpong", "random"], {
|
|
"default": "forward",
|
|
"tooltip": "How to move through the sequence"
|
|
})
|
|
})
|
|
return inputs
|
|
|
|
def update_sequence_base(self, values: list, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
|
# Initialize or get state
|
|
state = self.get_state({
|
|
"current_index": 0,
|
|
"step_counter": 0,
|
|
"direction": 1 # 1 for forward, -1 for reverse (used in pingpong)
|
|
})
|
|
|
|
if not values:
|
|
return (values[0] if values else None,)
|
|
|
|
# Update step counter
|
|
state["step_counter"] += 1
|
|
|
|
# Check if we should move to next item
|
|
if state["step_counter"] >= steps_per_item:
|
|
state["step_counter"] = 0
|
|
|
|
# Update index based on sequence mode
|
|
if sequence_mode == "forward":
|
|
state["current_index"] = (state["current_index"] + 1) % len(values)
|
|
elif sequence_mode == "reverse":
|
|
state["current_index"] = (state["current_index"] - 1) % len(values)
|
|
elif sequence_mode == "pingpong":
|
|
next_index = state["current_index"] + state["direction"]
|
|
if next_index >= len(values) or next_index < 0:
|
|
state["direction"] *= -1 # Reverse direction
|
|
next_index = state["current_index"] + state["direction"]
|
|
state["current_index"] = next_index
|
|
elif sequence_mode == "random":
|
|
import random
|
|
state["current_index"] = random.randint(0, len(values) - 1)
|
|
|
|
# Save state
|
|
self.set_state(state)
|
|
|
|
# Return current value
|
|
return (values[state["current_index"]],)
|
|
|
|
class FloatSequence(SequenceControlBase):
|
|
"""Cycles through a sequence of float values"""
|
|
|
|
RETURN_TYPES = ("FLOAT",)
|
|
FUNCTION = "update"
|
|
CATEGORY = "real-time/control/sequence"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
inputs = super().INPUT_TYPES()
|
|
inputs["required"].update({
|
|
"values": ("STRING", {
|
|
"default": "0.0, 0.5, 1.0",
|
|
"tooltip": "List of float values (comma separated)"
|
|
})
|
|
})
|
|
return inputs
|
|
|
|
def update(self, values: str, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
|
# Parse comma-separated float values
|
|
float_values = [float(v.strip()) for v in values.split(',') if v.strip()]
|
|
return self.update_sequence_base(float_values, steps_per_item, sequence_mode, always_execute)
|
|
|
|
class IntSequence(SequenceControlBase):
|
|
"""Cycles through a sequence of integer values"""
|
|
|
|
RETURN_TYPES = ("INT",)
|
|
FUNCTION = "update"
|
|
CATEGORY = "real-time/control/sequence"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
inputs = super().INPUT_TYPES()
|
|
inputs["required"].update({
|
|
"values": ("STRING", {
|
|
"default": "0, 5, 10",
|
|
"tooltip": "List of integer values (comma separated)"
|
|
})
|
|
})
|
|
return inputs
|
|
|
|
def update(self, values: str, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
|
# Parse comma-separated integer values
|
|
int_values = [int(v.strip()) for v in values.split(',') if v.strip()]
|
|
return self.update_sequence_base(int_values, steps_per_item, sequence_mode, always_execute)
|
|
|
|
class StringSequence(SequenceControlBase):
|
|
"""Cycles through a sequence of strings"""
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
FUNCTION = "update"
|
|
CATEGORY = "real-time/control/sequence"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
inputs = super().INPUT_TYPES()
|
|
inputs["required"].update({
|
|
"values": ("STRING", {
|
|
"multiline": True,
|
|
"default": "first\nsecond\nthird",
|
|
"tooltip": "List of strings (one per line)"
|
|
})
|
|
})
|
|
return inputs
|
|
|
|
def update(self, values: str, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
|
# Split into string values
|
|
string_values = [v.strip() for v in values.split('\n') if v.strip()]
|
|
return self.update_sequence_base(string_values, steps_per_item, sequence_mode, always_execute) |