adds batch support for sequence controls
This commit is contained in:
@@ -17,11 +17,21 @@ class SequenceControlBase(ControlNodeBase):
|
||||
["forward", "reverse", "pingpong", "random"],
|
||||
{"default": "forward", "tooltip": "How to move through the sequence"},
|
||||
),
|
||||
"batch_size": (
|
||||
"INT",
|
||||
{
|
||||
"default": 1,
|
||||
"min": 1,
|
||||
"max": 1000,
|
||||
"step": 1,
|
||||
"tooltip": "Number of values to generate in batch",
|
||||
},
|
||||
),
|
||||
}
|
||||
)
|
||||
return inputs
|
||||
|
||||
def update_sequence_base(self, values: list, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
||||
def update_sequence_base(self, values: list, steps_per_item: int, sequence_mode: str, batch_size: int = 1, always_execute: bool = True):
|
||||
# Initialize or get state
|
||||
state = self.get_state(
|
||||
{
|
||||
@@ -32,8 +42,41 @@ class SequenceControlBase(ControlNodeBase):
|
||||
)
|
||||
|
||||
if not values:
|
||||
return (values[0] if values else None,)
|
||||
if batch_size > 1:
|
||||
return ([None] * batch_size,)
|
||||
return (None,)
|
||||
|
||||
# Fast path for batch_size=1 (real-time case)
|
||||
if batch_size == 1:
|
||||
# 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"]],)
|
||||
|
||||
# Batch processing path
|
||||
# Update step counter
|
||||
state["step_counter"] += 1
|
||||
|
||||
@@ -54,14 +97,35 @@ class SequenceControlBase(ControlNodeBase):
|
||||
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"]],)
|
||||
# Generate batch of values from current position
|
||||
batch_values = []
|
||||
for i in range(batch_size):
|
||||
if sequence_mode == "forward":
|
||||
idx = (state["current_index"] + i) % len(values)
|
||||
elif sequence_mode == "reverse":
|
||||
idx = (state["current_index"] - i) % len(values)
|
||||
elif sequence_mode == "pingpong":
|
||||
# For pingpong, we need to bounce when we hit the ends
|
||||
direction = state["direction"]
|
||||
idx = state["current_index"]
|
||||
for j in range(i):
|
||||
idx += direction
|
||||
if idx >= len(values) or idx < 0:
|
||||
direction *= -1
|
||||
idx += 2 * direction # Move two steps to correct direction
|
||||
idx = max(0, min(idx, len(values) - 1)) # Safety bounds check
|
||||
elif sequence_mode == "random":
|
||||
import random
|
||||
idx = random.randint(0, len(values) - 1)
|
||||
|
||||
batch_values.append(values[idx])
|
||||
|
||||
return (batch_values,)
|
||||
|
||||
|
||||
class FloatSequence(SequenceControlBase):
|
||||
@@ -77,10 +141,10 @@ class FloatSequence(SequenceControlBase):
|
||||
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):
|
||||
def update(self, values: str, steps_per_item: int, sequence_mode: str, batch_size: int = 1, 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)
|
||||
return self.update_sequence_base(float_values, steps_per_item, sequence_mode, batch_size, always_execute)
|
||||
|
||||
|
||||
class IntSequence(SequenceControlBase):
|
||||
@@ -96,10 +160,10 @@ class IntSequence(SequenceControlBase):
|
||||
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):
|
||||
def update(self, values: str, steps_per_item: int, sequence_mode: str, batch_size: int = 1, 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)
|
||||
return self.update_sequence_base(int_values, steps_per_item, sequence_mode, batch_size, always_execute)
|
||||
|
||||
|
||||
class StringSequence(SequenceControlBase):
|
||||
@@ -122,7 +186,7 @@ class StringSequence(SequenceControlBase):
|
||||
)
|
||||
return inputs
|
||||
|
||||
def update(self, values: str, steps_per_item: int, sequence_mode: str, always_execute: bool = True):
|
||||
def update(self, values: str, steps_per_item: int, sequence_mode: str, batch_size: int = 1, 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)
|
||||
return self.update_sequence_base(string_values, steps_per_item, sequence_mode, batch_size, always_execute)
|
||||
|
||||
Reference in New Issue
Block a user