Files
aodh-pack/nodes/character_reader/character_reader.py
2026-03-04 21:49:43 +00:00

134 lines
5.3 KiB
Python

import json
import os
import random
class CharacterJsonReader:
@classmethod
def INPUT_TYPES(s):
base_path = os.path.dirname(os.path.realpath(__file__))
char_dir = os.path.join(base_path, "characters")
characters = []
if os.path.exists(char_dir):
characters = sorted([f for f in os.listdir(char_dir) if f.endswith('.json')])
return {
"required": {
"character_file": (characters, ),
"selection_mode": (["manual", "sequential", "random"], {"default": "manual"}),
"repeat_count": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
}
}
@classmethod
def IS_CHANGED(s, character_file, selection_mode, repeat_count):
if selection_mode == "random" or selection_mode == "sequential":
return float("nan")
return character_file
RETURN_TYPES = (
"STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING",
"STRING", "STRING", "STRING", "STRING", "STRING", "STRING",
"STRING", "STRING", "STRING", "STRING",
"STRING", "FLOAT", "STRING", "INT", "STRING"
)
RETURN_NAMES = (
"name", "base_specs", "hair", "eyes", "expression", "hands", "arms", "torso", "pelvis", "legs", "feet", "distinguishing_marks",
"inner_layer", "outer_layer", "lower_body", "footwear", "gloves", "accessories",
"aesthetic", "primary_color", "secondary_color", "tertiary_color",
"lora_name", "lora_weight", "lora_triggers", "total_characters", "tags"
)
FUNCTION = "read_character"
CATEGORY = "AODH Pack"
def __init__(self):
self.current_index = 0
self.current_count = 0
self.last_selection = None
self.last_start_file = None
def read_character(self, character_file, selection_mode, repeat_count):
repeat_count = max(1, repeat_count)
base_path = os.path.dirname(os.path.realpath(__file__))
char_dir = os.path.join(base_path, "characters")
characters = sorted([f for f in os.listdir(char_dir) if f.endswith('.json')])
if not characters:
return ("",) * 22 + ("", 0.0, "", 0)
# Reset sequence if character_file changes
if self.last_start_file != character_file:
try:
self.current_index = characters.index(character_file)
except ValueError:
self.current_index = 0
self.current_count = 0
self.last_start_file = character_file
if selection_mode == "manual":
selected_file = character_file
elif selection_mode == "sequential":
if self.current_count >= repeat_count:
self.current_index += 1
self.current_count = 0
selected_file = characters[self.current_index % len(characters)]
self.current_count += 1
elif selection_mode == "random":
if self.current_count >= repeat_count or self.last_selection is None or self.last_selection not in characters:
# Use a local Random instance to ensure randomness regardless of global seed
rng = random.Random()
self.last_selection = rng.choice(characters)
self.current_count = 0
selected_file = self.last_selection
self.current_count += 1
else:
selected_file = character_file
file_path = os.path.join(char_dir, selected_file)
with open(file_path, 'r') as f:
data = json.load(f)
identity = data.get("identity", {})
wardrobe = data.get("wardrobe", {})
styles = data.get("styles", {})
lora = data.get("lora", {})
def get_val(obj, key, prepend_comma=True):
val = obj.get(key, "")
if val and prepend_comma and not val.startswith(","):
val = ", " + val
return val
return (
get_val(data, "character_id", prepend_comma=False),
get_val(identity, "base_specs"),
get_val(identity, "hair"),
get_val(identity, "eyes"),
get_val(identity, "expression"),
get_val(identity, "hands"),
get_val(identity, "arms"),
get_val(identity, "torso"),
get_val(identity, "pelvis"),
get_val(identity, "legs"),
get_val(identity, "feet"),
get_val(identity, "distinguishing_marks"),
get_val(wardrobe, "inner_layer"),
get_val(wardrobe, "outer_layer"),
get_val(wardrobe, "lower_body"),
get_val(wardrobe, "footwear"),
get_val(wardrobe, "gloves"),
get_val(wardrobe, "accessories"),
get_val(styles, "aesthetic"),
get_val(styles, "primary_color"),
get_val(styles, "secondary_color"),
get_val(styles, "tertiary_color"),
get_val(lora, "lora_name", prepend_comma=False),
float(lora.get("lora_weight", 0.0) if lora.get("lora_weight") else 0.0),
get_val(lora, "lora_triggers"),
len(characters),
", ".join(data.get("tags", [])) if isinstance(data.get("tags"), list) else ""
)