feat: add AODH Image Saver (Metadata), Lora Selector, Checkpoint Selector, and various node improvements
This commit is contained in:
@@ -2,19 +2,31 @@ from .character_reader import NODE_CLASS_MAPPINGS as CR_CLASS, NODE_DISPLAY_NAME
|
||||
from .resolution_reader import NODE_CLASS_MAPPINGS as RR_CLASS, NODE_DISPLAY_NAME_MAPPINGS as RR_DISPLAY
|
||||
from .reenforcer import NODE_CLASS_MAPPINGS as RE_CLASS, NODE_DISPLAY_NAME_MAPPINGS as RE_DISPLAY
|
||||
from .lora_from_string import NODE_CLASS_MAPPINGS as LFS_CLASS, NODE_DISPLAY_NAME_MAPPINGS as LFS_DISPLAY
|
||||
from .lora_selector import NODE_CLASS_MAPPINGS as LS_CLASS, NODE_DISPLAY_NAME_MAPPINGS as LS_DISPLAY
|
||||
from .checkpoint_selector import NODE_CLASS_MAPPINGS as CS_CLASS, NODE_DISPLAY_NAME_MAPPINGS as CS_DISPLAY
|
||||
from .checkpoint_from_string import NODE_CLASS_MAPPINGS as CFS_CLASS, NODE_DISPLAY_NAME_MAPPINGS as CFS_DISPLAY
|
||||
from .metadata_saver import NODE_CLASS_MAPPINGS as MS_CLASS, NODE_DISPLAY_NAME_MAPPINGS as MS_DISPLAY
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
**CR_CLASS,
|
||||
**RR_CLASS,
|
||||
**RE_CLASS,
|
||||
**LFS_CLASS
|
||||
**LFS_CLASS,
|
||||
**LS_CLASS,
|
||||
**CS_CLASS,
|
||||
**CFS_CLASS,
|
||||
**MS_CLASS
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
**CR_DISPLAY,
|
||||
**RR_DISPLAY,
|
||||
**RE_DISPLAY,
|
||||
**LFS_DISPLAY
|
||||
**LFS_DISPLAY,
|
||||
**LS_DISPLAY,
|
||||
**CS_DISPLAY,
|
||||
**CFS_DISPLAY,
|
||||
**MS_DISPLAY
|
||||
}
|
||||
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
|
||||
|
||||
@@ -30,45 +30,59 @@ class CharacterJsonReader:
|
||||
"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"
|
||||
"STRING", "FLOAT", "STRING", "INT"
|
||||
)
|
||||
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"
|
||||
"lora_name", "lora_weight", "lora_triggers", "total_characters"
|
||||
)
|
||||
|
||||
FUNCTION = "read_character"
|
||||
CATEGORY = "AODH Pack"
|
||||
|
||||
_current_index = 0
|
||||
_current_count = 0
|
||||
_last_selection = None
|
||||
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, "")
|
||||
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.__class__._current_count >= repeat_count:
|
||||
self.__class__._current_index += 1
|
||||
self.__class__._current_count = 0
|
||||
selected_file = characters[self.__class__._current_index % len(characters)]
|
||||
self.__class__._current_count += 1
|
||||
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.__class__._current_count >= repeat_count or self.__class__._last_selection is None or self.__class__._last_selection not in characters:
|
||||
self.__class__._last_selection = random.choice(characters)
|
||||
self.__class__._current_count = 0
|
||||
selected_file = self.__class__._last_selection
|
||||
self.__class__._current_count += 1
|
||||
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
|
||||
|
||||
@@ -114,4 +128,5 @@ class CharacterJsonReader:
|
||||
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),
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "black short-sleeved shirt",
|
||||
"outer_layer": "blue denim vest, Red Ribbon logo on back",
|
||||
"outer_layer": "blue denim vest, 'RR' text on back",
|
||||
"lower_body": "blue denim skirt, black leggings",
|
||||
"footwear": "brown boots",
|
||||
"gloves": "",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"character_id": "anya_forger",
|
||||
"character_id": "anya_(spy_x_family)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, small build, fair skin",
|
||||
"hair": "short pink hair, two small horns (hair ornaments)",
|
||||
|
||||
35
nodes/character_reader/characters/biwa_hayahide.json
Normal file
35
nodes/character_reader/characters/biwa_hayahide.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "biwa_hayahide_(Umamusume)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, horse ears, horse tail, tall",
|
||||
"hair": "long grey hair, wild hair",
|
||||
"eyes": "purple eyes, red framed glasses",
|
||||
"expression": "thinking",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "large breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt",
|
||||
"outer_layer": "tracen school uniform",
|
||||
"lower_body": "pleated skirt",
|
||||
"footwear": "heeled shoes",
|
||||
"gloves": "",
|
||||
"accessories": ""
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "intellectual, cool",
|
||||
"primary_color": "maroon",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "grey"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,10 @@
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "pink dress, 'Bulma' text on front",
|
||||
"lower_body": "dress",
|
||||
"footwear": "purple sneakers, white socks",
|
||||
"gloves": "purple gloves",
|
||||
"outer_layer": "black playboy bunny",
|
||||
"lower_body": "pantyhose",
|
||||
"footwear": "red high heels",
|
||||
"gloves": "detatched cuffs",
|
||||
"accessories": "red hair ribbon, dragon radar"
|
||||
},
|
||||
"styles": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"character_id": "camilla",
|
||||
"character_id": "camilla_(fire_emblem)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, curvaceous build, fair skin",
|
||||
"hair": "long wavy lavender hair, hair covering one eye",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"character_id": "chun_li",
|
||||
"identity": {
|
||||
"base_specs": "1girl, muscular build, fair skin",
|
||||
"base_specs": "1girl, muscular build, fair skin, asian",
|
||||
"hair": "black hair, hair buns",
|
||||
"eyes": "brown eyes",
|
||||
"expression": "determined smile",
|
||||
@@ -22,7 +22,7 @@
|
||||
"accessories": "white hair ribbons, spiked bracelets"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "martial arts, traditional, street fighter style",
|
||||
"aesthetic": "chinese style",
|
||||
"primary_color": "blue",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "gold"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"character_id": "ciri",
|
||||
"identity": {
|
||||
"base_specs": "1girl, athletic build, pale skin",
|
||||
"base_specs": "1girl, athletic build",
|
||||
"hair": "ashen grey hair, messy bun",
|
||||
"eyes": "emerald green eyes. mascara",
|
||||
"eyes": "emerald green eyes, mascara",
|
||||
"expression": "determined look",
|
||||
"hands": "brown nails",
|
||||
"hands": "green nails",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white blouse",
|
||||
"outer_layer": "brown leather vest, silver studs",
|
||||
"outer_layer": "",
|
||||
"lower_body": "brown leather trousers",
|
||||
"footwear": "brown leather boots",
|
||||
"gloves": "brown leather gloves",
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "delinquent_mother_flim13",
|
||||
"identity": {
|
||||
"base_specs": "1girl, milf, gyaru, tall",
|
||||
"hair": "blonde hair, long hair",
|
||||
"eyes": "sharp eyes",
|
||||
"expression": "smirk, sharp teeth",
|
||||
"hands": "painted nails",
|
||||
"arms": "",
|
||||
"torso": "very large breasts",
|
||||
"pelvis": "wide hips",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "biege sweater, cleavage",
|
||||
"outer_layer": "",
|
||||
"lower_body": "pencil skirt",
|
||||
"footwear": "high heels",
|
||||
"gloves": "",
|
||||
"accessories": "necklace, rings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "gyaru, milf, pink leopard print",
|
||||
"primary_color": "pink",
|
||||
"secondary_color": "black",
|
||||
"tertiary_color": "gold"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "Illustrious/Looks/Gyaru_mom_Flim13_IL_V1.safetensors",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/gold_city.json
Normal file
35
nodes/character_reader/characters/gold_city.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "gold_city_(Umamusume)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, horse ears, horse tail, tall",
|
||||
"hair": "blonde hair, wavy hair",
|
||||
"eyes": "blue eyes",
|
||||
"expression": "confident expression",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt",
|
||||
"outer_layer": "tracen school uniform",
|
||||
"lower_body": "pleated skirt",
|
||||
"footwear": "heeled shoes",
|
||||
"gloves": "",
|
||||
"accessories": "choker, earrings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "fashionable, model",
|
||||
"primary_color": "gold",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/gold_ship.json
Normal file
35
nodes/character_reader/characters/gold_ship.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "gold_ship_(Umamusume)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, horse ears, horse tail, tall",
|
||||
"hair": "grey hair, short hair",
|
||||
"eyes": "red eyes",
|
||||
"expression": "crazy expression, grin",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt",
|
||||
"outer_layer": "tracen school uniform",
|
||||
"lower_body": "pleated skirt",
|
||||
"footwear": "heeled shoes",
|
||||
"gloves": "",
|
||||
"accessories": "ear covers, hat"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "energetic, sporty",
|
||||
"primary_color": "red",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "gold"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/jessica_rabbit.json
Normal file
35
nodes/character_reader/characters/jessica_rabbit.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "jessica_rabbit",
|
||||
"identity": {
|
||||
"base_specs": "1girl, voluptuous build, tall,",
|
||||
"hair": "long red hair, side part, hair over one eye",
|
||||
"eyes": "green eyes, heavy makeup, purple eyeshadow",
|
||||
"expression": "seductive smile",
|
||||
"hands": "purple elbow gloves",
|
||||
"arms": "",
|
||||
"torso": "large breasts",
|
||||
"pelvis": "narrow waist",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "red lips"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "red sequin dress, strapless, high slit, backless",
|
||||
"lower_body": "side_slit,",
|
||||
"footwear": "red high heels",
|
||||
"gloves": "purple opera gloves",
|
||||
"accessories": "gold earrings, glitter"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "noir, cartoon, glamorous",
|
||||
"primary_color": "red",
|
||||
"secondary_color": "purple",
|
||||
"tertiary_color": "gold"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
"outer_layer": "white Team Rocket uniform jacket, bare stomach, red R logo",
|
||||
"lower_body": "white miniskirt",
|
||||
"footwear": "black thigh-high boots",
|
||||
"gloves": "black gloves",
|
||||
"accessories": ""
|
||||
"gloves": "black elbow gloves",
|
||||
"accessories": "green earrings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "villainous, anime, pokemon style",
|
||||
|
||||
35
nodes/character_reader/characters/jinx.json
Normal file
35
nodes/character_reader/characters/jinx.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "jinx",
|
||||
"identity": {
|
||||
"base_specs": "1girl, slender build, pale skin,",
|
||||
"hair": "long aqua hair, twin braids, very long hair, bangs",
|
||||
"eyes": "pink eyes, ",
|
||||
"expression": "crazy eyes, manic grin, crazy smile",
|
||||
"hands": "black and pink nails",
|
||||
"arms": "",
|
||||
"torso": "flat chest,",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "cloud tattoo,"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "pink and black bikini, asymmetrical_bikini ",
|
||||
"lower_body": "pink shorts, single pink stocking",
|
||||
"footwear": "combat boots",
|
||||
"gloves": "black fingerless gloves, fishnet elbow gloves,",
|
||||
"accessories": "ammo belts, choker, bullet necklace,"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "punk, chaotic,",
|
||||
"primary_color": "pink",
|
||||
"secondary_color": "black",
|
||||
"tertiary_color": "aqua"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "Illustrious/Looks/jinx_default_lol-000021.safetensors",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/kagamine_rin.json
Normal file
35
nodes/character_reader/characters/kagamine_rin.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "kagamine_rin",
|
||||
"identity": {
|
||||
"base_specs": "1girl, petite",
|
||||
"hair": "blonde hair, short hair, hair bow",
|
||||
"eyes": "blue eyes",
|
||||
"expression": "smile, energetic",
|
||||
"hands": "",
|
||||
"arms": "detached sleeves",
|
||||
"torso": "flat chest",
|
||||
"pelvis": "",
|
||||
"legs": "leg warmers",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt, sailor collar",
|
||||
"outer_layer": "",
|
||||
"lower_body": "black shorts, yellow belt",
|
||||
"footwear": "white shoes",
|
||||
"gloves": "",
|
||||
"accessories": "headset, hair bow"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "vocaloid, cyber",
|
||||
"primary_color": "yellow",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
"lower_body": "black leather shorts",
|
||||
"footwear": "black thigh-high boots",
|
||||
"gloves": "",
|
||||
"accessories": "crystal orb, silver jewelry"
|
||||
"accessories": "crystal heart, silver jewelry"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "pop star, mystical, k/da style",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"hair": "light blue hair,",
|
||||
"eyes": "yellow glowing eyes, slit pupils",
|
||||
"expression": "seductive, confident look",
|
||||
"hands": "long black claws, blue nails",
|
||||
"hands": "metal claws",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "purple markings under eyes, floating crystal cannons"
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "silver bodysuit",
|
||||
|
||||
35
nodes/character_reader/characters/komi_shouko.json
Normal file
35
nodes/character_reader/characters/komi_shouko.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "komi_shouko",
|
||||
"identity": {
|
||||
"base_specs": "1girl, slender build, pale skin, asian",
|
||||
"hair": "long dark purple hair, hime cut,",
|
||||
"eyes": "dark purple eyes,",
|
||||
"expression": "neutral expression, stoic, cat ears",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "black pantyhose",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt",
|
||||
"outer_layer": "itan private high school uniform, blazer, striped bow tie",
|
||||
"lower_body": "plaid skirt",
|
||||
"footwear": "loafers",
|
||||
"gloves": "",
|
||||
"accessories": ""
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "anime, manga, clean lines",
|
||||
"primary_color": "purple",
|
||||
"secondary_color": "magenta",
|
||||
"tertiary_color": "white"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "komi shouko, itan private high school uniform"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"character_id": "lara_croft_classic",
|
||||
"identity": {
|
||||
"base_specs": "1girl, athletic build, tan skin",
|
||||
"base_specs": "1girl, athletic build,",
|
||||
"hair": "long brown hair, single braid",
|
||||
"eyes": "brown eyes",
|
||||
"expression": "determined",
|
||||
"expression": "light smile, raised eyebrow",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "",
|
||||
"torso": "large breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
@@ -15,11 +15,11 @@
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "teal tank top, crop top",
|
||||
"outer_layer": "teal tank top,",
|
||||
"lower_body": "brown shorts",
|
||||
"footwear": "brown combat boots, red laces",
|
||||
"gloves": "black fingerless gloves",
|
||||
"accessories": "dual thigh holsters, backpack, circular sunglasses"
|
||||
"accessories": "dual thigh pistol holsters, brown leatherbackpack, red circular sunglasses"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "adventure, retro, 90s style",
|
||||
@@ -28,8 +28,8 @@
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "lara_croft_classic",
|
||||
"lora_name": "Illustrious/Looks/LaraCroft_ClassicV2_Illu_Dwnsty.safetensors",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "lara croft, classic outfit"
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/lisa_minci.json
Normal file
35
nodes/character_reader/characters/lisa_minci.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "lisa_(genshin_impact)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, tall, mature female",
|
||||
"hair": "brown hair, wavy hair, side ponytail",
|
||||
"eyes": "green eyes",
|
||||
"expression": "seductive smile",
|
||||
"hands": "",
|
||||
"arms": "detached sleeves",
|
||||
"torso": "large breasts",
|
||||
"pelvis": "wide hips",
|
||||
"legs": "black pantyhose",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "beauty mark"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "purple dress, corset",
|
||||
"outer_layer": "purple shawl",
|
||||
"lower_body": "slit skirt",
|
||||
"footwear": "black heels",
|
||||
"gloves": "purple gloves",
|
||||
"accessories": "witch hat, rose, necklace"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "genshin impact, witch, librarian",
|
||||
"primary_color": "purple",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "gold"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"character_id": "lulu (ffx)",
|
||||
"character_id": "lulu (ff10)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, curvaceous build, fair skin",
|
||||
"hair": "long black hair, complex braids, hairpins",
|
||||
"eyes": "red eyes",
|
||||
"expression": "stern expression",
|
||||
"expression": "thinking, raised eyebrow",
|
||||
"hands": "black nails",
|
||||
"arms": "",
|
||||
"torso": "large breasts",
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
"base_specs": "1girl, curvaceous build, pink skin",
|
||||
"hair": "long voluminous white hair",
|
||||
"eyes": "red eyes, black sclera",
|
||||
"expression": "playful yet menacing smile",
|
||||
"expression": "evil smile",
|
||||
"hands": "black claws, pink nails",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"torso": "large breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "pink skin, long tail, pointed ears"
|
||||
"distinguishing_marks": "pink skin, long tail, pointy ears"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "black tube top",
|
||||
"outer_layer": "",
|
||||
"lower_body": "white baggy pants",
|
||||
"lower_body": "white harem pants",
|
||||
"footwear": "black and yellow boots",
|
||||
"gloves": "",
|
||||
"accessories": "gold bracelets, gold neck ring"
|
||||
"gloves": "black sleeves",
|
||||
"accessories": "gold bracelets, gold neck ring, hoop earrings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "supernatural, anime, dragon ball style",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"character_id": "marin_kitagawa",
|
||||
"identity": {
|
||||
"base_specs": "1girl, slender build, fair skin",
|
||||
"base_specs": "1girl, slender build, fair skin, asian",
|
||||
"hair": "long blonde hair, pink tips",
|
||||
"eyes": "pink eyes (contacts)",
|
||||
"expression": "excited smile",
|
||||
|
||||
35
nodes/character_reader/characters/megurine_luka.json
Normal file
35
nodes/character_reader/characters/megurine_luka.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "megurine_luka",
|
||||
"identity": {
|
||||
"base_specs": "1girl, tall, mature female",
|
||||
"hair": "pink hair, long hair",
|
||||
"eyes": "blue eyes",
|
||||
"expression": "light smile",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "crop top, detached sleeves, gold trim",
|
||||
"lower_body": "side slit, lace-up skirt",
|
||||
"footwear": "thinghighs, lace-up boots, gold boots, gold armlet",
|
||||
"gloves": "",
|
||||
"accessories": "headset"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "vocaloid, elegant",
|
||||
"primary_color": "black",
|
||||
"secondary_color": "gold",
|
||||
"tertiary_color": "pink"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/meiko.json
Normal file
35
nodes/character_reader/characters/meiko.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "meiko",
|
||||
"identity": {
|
||||
"base_specs": "1girl, mature female",
|
||||
"hair": "brown hair, short hair",
|
||||
"eyes": "brown eyes",
|
||||
"expression": "smile, confident",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "red crop top, sleeveless",
|
||||
"outer_layer": "",
|
||||
"lower_body": "red skirt, mini skirt",
|
||||
"footwear": "brown boots",
|
||||
"gloves": "",
|
||||
"accessories": "choker"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "vocaloid, casual",
|
||||
"primary_color": "red",
|
||||
"secondary_color": "brown",
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "olivier_mira_armstrong",
|
||||
"identity": {
|
||||
"base_specs": "1girl, tall, mature female",
|
||||
"hair": "blonde hair, long hair, hair over one eye",
|
||||
"eyes": "blue eyes, sharp eyes",
|
||||
"expression": "serious",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "thick lips"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "black shirt",
|
||||
"outer_layer": "blue military coat, fur collar",
|
||||
"lower_body": "black pants",
|
||||
"footwear": "black boots",
|
||||
"gloves": "black gloves",
|
||||
"accessories": "sword"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "military, amestris uniform",
|
||||
"primary_color": "blue",
|
||||
"secondary_color": "black",
|
||||
"tertiary_color": "gold"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"hair": "long blonde hair, voluminous, crown",
|
||||
"eyes": "blue eyes, long eyelashes",
|
||||
"expression": "gentle smile",
|
||||
"hands": "pink nails",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"base_specs": "1girl, slender build, fair skin, pointed ears",
|
||||
"hair": "long blonde hair, braided, gold hair clips",
|
||||
"eyes": "green eyes",
|
||||
"expression": "determined look",
|
||||
"expression": "curious",
|
||||
"hands": "gold nails",
|
||||
"arms": "",
|
||||
"torso": "small breasts",
|
||||
|
||||
35
nodes/character_reader/characters/rice_shower.json
Normal file
35
nodes/character_reader/characters/rice_shower.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "rice_shower_(Umamusume)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, petite, horse ears, horse tail",
|
||||
"hair": "long dark brown hair, bangs, hair over one eye",
|
||||
"eyes": "purple eyes",
|
||||
"expression": "shy expression",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "small breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "white shirt",
|
||||
"outer_layer": "tracen school uniform",
|
||||
"lower_body": "pleated skirt",
|
||||
"footwear": "heeled shoes",
|
||||
"gloves": "",
|
||||
"accessories": "blue rose, hair flower, small hat, dagger"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "gothic lolita, elegant",
|
||||
"primary_color": "purple",
|
||||
"secondary_color": "blue",
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -11,25 +11,25 @@
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "blue lipstick,gerudo markings"
|
||||
"distinguishing_marks": "darkblue lipstick,"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "gerudo top, colorful sash",
|
||||
"lower_body": "gerudo pants, puffy pants",
|
||||
"footwear": "sandals",
|
||||
"outer_layer": "black top, blue sash",
|
||||
"lower_body": "black skirt, pelvic curtain,",
|
||||
"footwear": "gold high heels",
|
||||
"gloves": "",
|
||||
"accessories": "gold jewelry, crown, earrings"
|
||||
"accessories": "gold jewelry, earrings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "fantasy, desert, gerudo style",
|
||||
"primary_color": "gold",
|
||||
"secondary_color": "teal",
|
||||
"secondary_color": "black",
|
||||
"tertiary_color": "red"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "riju_botw",
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "riju, gerudo"
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,21 @@
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "black skin-tight jumpsuit, pink heart-shaped chest plate",
|
||||
"outer_layer": "black skin-tight jumpsuit, pink heart-shaped chest plate, bare shoulders, cleavage",
|
||||
"lower_body": "jumpsuit",
|
||||
"footwear": "white boots, pink heart motifs",
|
||||
"gloves": "white gloves, pink cuffs",
|
||||
"accessories": "blue eyeshadow"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "sleek, spy, sonic style",
|
||||
"aesthetic": "jewels, museum,sleek, spy, sonic style",
|
||||
"primary_color": "white",
|
||||
"secondary_color": "pink",
|
||||
"tertiary_color": "black"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_name": "Illustrious/Looks/Rouge_the_bat_v2.safetensors",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/ryouko_hakubi.json
Normal file
35
nodes/character_reader/characters/ryouko_hakubi.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "ryouko_(tenchi_muyou!)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, slim build,",
|
||||
"hair": "long teal hair, spiky, voluminous",
|
||||
"eyes": "golden eyes, cat-like pupils",
|
||||
"expression": "confident smirk",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "medium breasts",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "red gem on forehead,"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "long white dress, plunging neckline, black belt",
|
||||
"outer_layer": "black and orange long sleeve jacket with purple trim,",
|
||||
"lower_body": "side_slit,, red trousers",
|
||||
"footwear": "",
|
||||
"gloves": "red gloves",
|
||||
"accessories": "red gems, wristbands"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "90s anime, sci-fi",
|
||||
"primary_color": "teal",
|
||||
"secondary_color": "white",
|
||||
"tertiary_color": "red"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "ryouko hakubi, space pirate"
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/sarah_miller.json
Normal file
35
nodes/character_reader/characters/sarah_miller.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "sarah_miller_(the_last_of_us)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, loli, small build",
|
||||
"hair": "blonde hair, short hair",
|
||||
"eyes": "blue eyes",
|
||||
"expression": "smile",
|
||||
"hands": "",
|
||||
"arms": "",
|
||||
"torso": "flat chest",
|
||||
"pelvis": "",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "grey t-shirt, white shirt",
|
||||
"outer_layer": "",
|
||||
"lower_body": "blue jeans",
|
||||
"footwear": "sneakers",
|
||||
"gloves": "",
|
||||
"accessories": "wristwatch"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "casual, 2013 fashion",
|
||||
"primary_color": "grey",
|
||||
"secondary_color": "blue",
|
||||
"tertiary_color": "white"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
35
nodes/character_reader/characters/shantae.json
Normal file
35
nodes/character_reader/characters/shantae.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"character_id": "shantae",
|
||||
"identity": {
|
||||
"base_specs": "1girl, dark skin, pointy ears",
|
||||
"hair": "purple hair, very long hair, ponytail",
|
||||
"eyes": "blue eyes",
|
||||
"expression": "smile, energetic",
|
||||
"hands": "",
|
||||
"arms": "gold bracelets",
|
||||
"torso": "small breasts, perky breasts",
|
||||
"pelvis": "wide hips",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": ""
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "red bikini top, red harem pants, gold trim",
|
||||
"lower_body": "",
|
||||
"footwear": "gold shoes",
|
||||
"gloves": "",
|
||||
"accessories": "gold tiara, hoop earrings"
|
||||
},
|
||||
"styles": {
|
||||
"aesthetic": "genie, dancer, arabian",
|
||||
"primary_color": "red",
|
||||
"secondary_color": "gold",
|
||||
"tertiary_color": "purple"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "",
|
||||
"lora_weight": 1.0,
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
"character_id": "sucy_manbavaran",
|
||||
"identity": {
|
||||
"base_specs": "1girl, lanky build, pale skin",
|
||||
"hair": "mauve hair, hair covering one eye",
|
||||
"eyes": "droopy red eyes",
|
||||
"hair": "light purple hair, hair covering one eye",
|
||||
"eyes": "red eyes",
|
||||
"expression": "deadpan expression",
|
||||
"hands": "purple nails",
|
||||
"hands": "black nails",
|
||||
"arms": "",
|
||||
"torso": "small breasts",
|
||||
"pelvis": "",
|
||||
"pelvis": "narrow waist",
|
||||
"legs": "",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "dark circles under eyes"
|
||||
@@ -16,7 +16,7 @@
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "dark purple witch robes",
|
||||
"lower_body": "long skirt",
|
||||
"lower_body": "long skirt with frayed edges",
|
||||
"footwear": "brown boots",
|
||||
"gloves": "",
|
||||
"accessories": "pointed witch hat, potion bottle"
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
"expression": "confident",
|
||||
"hands": "gold nails",
|
||||
"arms": "muscular arms",
|
||||
"torso": "abs",
|
||||
"torso": "abs, mediumS breasts",
|
||||
"pelvis": "wide hips",
|
||||
"legs": "muscular legs",
|
||||
"feet": "",
|
||||
"distinguishing_marks": "blue lipstick, gerudo markings"
|
||||
"distinguishing_marks": "dark blue lipstick, gerudo markings"
|
||||
},
|
||||
"wardrobe": {
|
||||
"inner_layer": "",
|
||||
"outer_layer": "gold breastplate, blue champion's skirt",
|
||||
"lower_body": "",
|
||||
"outer_layer": "blue top, blue champion's skirt, green sash, green shoulder guards,",
|
||||
"lower_body": "blue skirt",
|
||||
"footwear": "gold heels",
|
||||
"gloves": "",
|
||||
"accessories": "gold jewelry, scimitar"
|
||||
@@ -28,8 +28,8 @@
|
||||
"tertiary_color": "red"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "urbosa_botw",
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "urbosa, gerudo"
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"identity": {
|
||||
"base_specs": "1girl, miqo'te, slender build, fair skin, cat ears",
|
||||
"hair": "short white hair, bangs",
|
||||
"eyes": "blind white eyes",
|
||||
"eyes": "blind, white eyes",
|
||||
"expression": "stoic expression",
|
||||
"hands": "black nails",
|
||||
"arms": "",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"character_id": "yuna_ffx",
|
||||
"character_id": "yuna_(ff10)",
|
||||
"identity": {
|
||||
"base_specs": "1girl, slender, fair skin",
|
||||
"hair": "short brown hair, bob cut",
|
||||
@@ -28,8 +28,8 @@
|
||||
"tertiary_color": "yellow"
|
||||
},
|
||||
"lora": {
|
||||
"lora_name": "yuna_ffx",
|
||||
"lora_name": "",
|
||||
"lora_weight": 0.8,
|
||||
"lora_triggers": "yuna, summoner outfit"
|
||||
"lora_triggers": ""
|
||||
}
|
||||
}
|
||||
9
nodes/checkpoint_from_string/__init__.py
Normal file
9
nodes/checkpoint_from_string/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from .checkpoint_from_string import CheckpointLoaderFromString
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"CheckpointLoaderFromString": CheckpointLoaderFromString
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"CheckpointLoaderFromString": "Checkpoint Loader (From String)"
|
||||
}
|
||||
19
nodes/checkpoint_from_string/checkpoint_from_string.py
Normal file
19
nodes/checkpoint_from_string/checkpoint_from_string.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import folder_paths
|
||||
import comfy.sd
|
||||
|
||||
class CheckpointLoaderFromString:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"ckpt_name": ("STRING", {"multiline": False, "forceInput": True}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE")
|
||||
FUNCTION = "load_checkpoint"
|
||||
CATEGORY = "AODH Pack"
|
||||
|
||||
def load_checkpoint(self, ckpt_name):
|
||||
ckpt_path = folder_paths.get_full_path_or_raise("checkpoints", ckpt_name)
|
||||
out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings"))
|
||||
return out[:3]
|
||||
9
nodes/checkpoint_selector/__init__.py
Normal file
9
nodes/checkpoint_selector/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from .checkpoint_selector import CheckpointSelector
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"CheckpointSelector": CheckpointSelector
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"CheckpointSelector": "Checkpoint Selector"
|
||||
}
|
||||
120
nodes/checkpoint_selector/checkpoint_selector.py
Normal file
120
nodes/checkpoint_selector/checkpoint_selector.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import os
|
||||
import random
|
||||
import folder_paths
|
||||
|
||||
class CheckpointSelector:
|
||||
def __init__(self):
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_folder = None
|
||||
self.last_selection = None
|
||||
self.last_manual_index = 0
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
# Find folders in 'checkpoints' paths
|
||||
checkpoint_paths = folder_paths.get_folder_paths("checkpoints")
|
||||
checkpoint_folders = []
|
||||
|
||||
for path in checkpoint_paths:
|
||||
if os.path.exists(path) and os.path.isdir(path):
|
||||
# List subdirectories
|
||||
try:
|
||||
subdirs = [d for d in os.listdir(path) if os.path.isdir(os.path.join(path, d))]
|
||||
checkpoint_folders.extend(subdirs)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Remove duplicates and sort
|
||||
checkpoint_folders = sorted(list(set(checkpoint_folders)))
|
||||
|
||||
if not checkpoint_folders:
|
||||
checkpoint_folders = ["None"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"folder": (checkpoint_folders, ),
|
||||
"mode": (["Random", "Sequential", "Manual"], {"default": "Random"}),
|
||||
"repeat_count": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
|
||||
"manual_index": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT")
|
||||
RETURN_NAMES = ("checkpoint_name", "total_checkpoints")
|
||||
FUNCTION = "select_checkpoint"
|
||||
CATEGORY = "AODH Pack"
|
||||
|
||||
def select_checkpoint(self, folder, mode, repeat_count, manual_index):
|
||||
repeat_count = max(1, repeat_count)
|
||||
if folder == "None":
|
||||
return ("", 0)
|
||||
|
||||
# Find the full path for the selected folder
|
||||
checkpoint_paths = folder_paths.get_folder_paths("checkpoints")
|
||||
target_path = None
|
||||
|
||||
for path in checkpoint_paths:
|
||||
check_path = os.path.join(path, folder)
|
||||
if os.path.exists(check_path) and os.path.isdir(check_path):
|
||||
target_path = check_path
|
||||
break
|
||||
|
||||
if not target_path:
|
||||
return ("", 0)
|
||||
|
||||
# Find checkpoint files (.safetensors, .ckpt)
|
||||
extensions = ('.safetensors', '.ckpt')
|
||||
checkpoint_files = [f for f in os.listdir(target_path) if f.lower().endswith(extensions)]
|
||||
checkpoint_files.sort()
|
||||
|
||||
count = len(checkpoint_files)
|
||||
if count == 0:
|
||||
return ("", 0)
|
||||
|
||||
selected_checkpoint = ""
|
||||
|
||||
# Reset state if folder changes
|
||||
if self.last_folder != folder:
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_selection = None
|
||||
self.last_folder = folder
|
||||
|
||||
# Reset state if manual_index changes (for Sequential mode)
|
||||
if self.last_manual_index != manual_index:
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_manual_index = manual_index
|
||||
|
||||
if mode == "Random":
|
||||
if self.current_count >= repeat_count or self.last_selection is None:
|
||||
rng = random.Random()
|
||||
self.last_selection = rng.choice(checkpoint_files)
|
||||
self.current_count = 0
|
||||
|
||||
selected_checkpoint = self.last_selection
|
||||
self.current_count += 1
|
||||
|
||||
elif mode == "Sequential":
|
||||
if self.current_count >= repeat_count:
|
||||
self.current_index += 1
|
||||
self.current_count = 0
|
||||
|
||||
selected_checkpoint = checkpoint_files[(self.current_index + manual_index) % count]
|
||||
self.current_count += 1
|
||||
|
||||
elif mode == "Manual":
|
||||
selected_checkpoint = checkpoint_files[manual_index % count]
|
||||
|
||||
# Construct the relative path for ComfyUI Checkpoint loader
|
||||
# Use forward slashes for consistency with ComfyUI paths
|
||||
full_checkpoint_name = f"{folder}/{selected_checkpoint}"
|
||||
|
||||
return (full_checkpoint_name, count)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(s, folder, mode, repeat_count, manual_index):
|
||||
if mode == "Random" or mode == "Sequential":
|
||||
return float("nan")
|
||||
return f"{folder}_{manual_index}"
|
||||
9
nodes/lora_selector/__init__.py
Normal file
9
nodes/lora_selector/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from .lora_selector import LoraSelector
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"LoraSelector": LoraSelector
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LoraSelector": "Lora Selector"
|
||||
}
|
||||
121
nodes/lora_selector/lora_selector.py
Normal file
121
nodes/lora_selector/lora_selector.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import os
|
||||
import random
|
||||
import folder_paths
|
||||
|
||||
class LoraSelector:
|
||||
def __init__(self):
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_folder = None
|
||||
self.last_selection = None
|
||||
self.last_manual_index = 0
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
# Find 'Illustrious' folders in all lora paths
|
||||
lora_paths = folder_paths.get_folder_paths("loras")
|
||||
illustrious_folders = []
|
||||
|
||||
for path in lora_paths:
|
||||
illustrious_path = os.path.join(path, "Illustrious")
|
||||
if os.path.exists(illustrious_path) and os.path.isdir(illustrious_path):
|
||||
# List subdirectories
|
||||
try:
|
||||
subdirs = [d for d in os.listdir(illustrious_path) if os.path.isdir(os.path.join(illustrious_path, d))]
|
||||
illustrious_folders.extend(subdirs)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Remove duplicates and sort
|
||||
illustrious_folders = sorted(list(set(illustrious_folders)))
|
||||
|
||||
if not illustrious_folders:
|
||||
illustrious_folders = ["None"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"folder": (illustrious_folders, ),
|
||||
"mode": (["Random", "Sequential", "Manual"], {"default": "Random"}),
|
||||
"repeat_count": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
|
||||
"manual_index": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT")
|
||||
RETURN_NAMES = ("lora_name", "total_loras")
|
||||
FUNCTION = "select_lora"
|
||||
CATEGORY = "AODH Pack"
|
||||
|
||||
def select_lora(self, folder, mode, repeat_count, manual_index):
|
||||
repeat_count = max(1, repeat_count)
|
||||
if folder == "None":
|
||||
return ("", 0)
|
||||
|
||||
# Find the full path for the selected folder
|
||||
lora_paths = folder_paths.get_folder_paths("loras")
|
||||
target_path = None
|
||||
|
||||
for path in lora_paths:
|
||||
check_path = os.path.join(path, "Illustrious", folder)
|
||||
if os.path.exists(check_path) and os.path.isdir(check_path):
|
||||
target_path = check_path
|
||||
break
|
||||
|
||||
if not target_path:
|
||||
return ("", 0)
|
||||
|
||||
# Find .safetensors files
|
||||
lora_files = [f for f in os.listdir(target_path) if f.endswith('.safetensors')]
|
||||
lora_files.sort() # Ensure consistent order
|
||||
|
||||
count = len(lora_files)
|
||||
if count == 0:
|
||||
return ("", 0)
|
||||
|
||||
selected_lora = ""
|
||||
|
||||
# Reset state if folder changes
|
||||
if self.last_folder != folder:
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_selection = None
|
||||
self.last_folder = folder
|
||||
|
||||
# Reset state if manual_index changes (for Sequential mode)
|
||||
if self.last_manual_index != manual_index:
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_manual_index = manual_index
|
||||
|
||||
if mode == "Random":
|
||||
if self.current_count >= repeat_count or self.last_selection is None:
|
||||
# Use a local Random instance to ensure randomness regardless of global seed
|
||||
rng = random.Random()
|
||||
self.last_selection = rng.choice(lora_files)
|
||||
self.current_count = 0
|
||||
|
||||
selected_lora = self.last_selection
|
||||
self.current_count += 1
|
||||
|
||||
elif mode == "Sequential":
|
||||
if self.current_count >= repeat_count:
|
||||
self.current_index += 1
|
||||
self.current_count = 0
|
||||
|
||||
selected_lora = lora_files[(self.current_index + manual_index) % count]
|
||||
self.current_count += 1
|
||||
|
||||
elif mode == "Manual":
|
||||
selected_lora = lora_files[manual_index % count]
|
||||
|
||||
# Construct the relative path for ComfyUI Lora loader
|
||||
# Use forward slashes for consistency
|
||||
full_lora_name = f"Illustrious/{folder}/{selected_lora}"
|
||||
|
||||
return (full_lora_name, count)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(s, folder, mode, repeat_count, manual_index):
|
||||
if mode == "Random" or mode == "Sequential":
|
||||
return float("nan")
|
||||
return f"{folder}_{manual_index}"
|
||||
9
nodes/metadata_saver/__init__.py
Normal file
9
nodes/metadata_saver/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from .metadata_saver import AodhMetadataImageSaver
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"AodhMetadataImageSaver": AodhMetadataImageSaver
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"AodhMetadataImageSaver": "AODH Image Saver (Metadata)"
|
||||
}
|
||||
210
nodes/metadata_saver/metadata_saver.py
Normal file
210
nodes/metadata_saver/metadata_saver.py
Normal file
@@ -0,0 +1,210 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from PIL import Image
|
||||
from PIL.PngImagePlugin import PngInfo
|
||||
import folder_paths
|
||||
import comfy.samplers
|
||||
|
||||
class AodhMetadataImageSaver:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
self.type = "output"
|
||||
self.prefix_append = ""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"images": ("IMAGE", ),
|
||||
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
|
||||
},
|
||||
"optional": {
|
||||
"save_directory": ("STRING", {"default": "%Y-%m-%d"}),
|
||||
# Generation parameters
|
||||
"positive_prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"negative_prompt": ("STRING", {"default": "", "multiline": True}),
|
||||
"checkpoint_name": ("STRING", {"default": ""}),
|
||||
"vae_name": ("STRING", {"default": ""}),
|
||||
"clip_skip": ("INT", {"default": -2}),
|
||||
"lora_name": ("STRING", {"default": ""}),
|
||||
"lora_strength": ("FLOAT", {"default": 1.0}),
|
||||
|
||||
# Sampling
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 20}),
|
||||
"cfg": ("FLOAT", {"default": 8.0}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, ),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, ),
|
||||
|
||||
# Resolution
|
||||
"width": ("INT", {"default": 512}),
|
||||
"height": ("INT", {"default": 512}),
|
||||
"upscale_factor": ("FLOAT", {"default": 1.0}),
|
||||
"upscaler_name": ("STRING", {"default": ""}),
|
||||
"hires_steps": ("INT", {"default": 10}),
|
||||
"denoise": ("FLOAT", {"default": 0.0}),
|
||||
|
||||
# Character / App Metadata
|
||||
"character_name": ("STRING", {"default": ""}),
|
||||
"tags": ("STRING", {"default": ""}),
|
||||
"rating": (["safe", "questionable", "explicit"], {"default": "safe"}),
|
||||
|
||||
# Extension
|
||||
"extension": (["png", "jpg", "webp"], {"default": "png"}),
|
||||
"include_workflow": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("images",)
|
||||
FUNCTION = "save_images"
|
||||
OUTPUT_NODE = True
|
||||
CATEGORY = "AODH Pack/Image"
|
||||
|
||||
def save_images(self, images, filename_prefix="ComfyUI", save_directory="%Y-%m-%d",
|
||||
positive_prompt="", negative_prompt="",
|
||||
checkpoint_name="", vae_name="", clip_skip=-2, lora_name="", lora_strength=1.0,
|
||||
seed=0, steps=20, cfg=8.0, sampler_name="euler", scheduler="normal",
|
||||
width=512, height=512, upscale_factor=1.0, upscaler_name="", hires_steps=10, denoise=0.0,
|
||||
character_name="", tags="", rating="safe", extension="png", include_workflow=True,
|
||||
prompt=None, extra_pnginfo=None):
|
||||
|
||||
now = datetime.now()
|
||||
if save_directory:
|
||||
# Handle date:yyyy-MM-dd format
|
||||
if "date:" in save_directory:
|
||||
def replace_date(match):
|
||||
fmt = match.group(1)
|
||||
# Convert common JS-like date formats to python strftime
|
||||
fmt = fmt.replace("yyyy", "%Y").replace("MM", "%m").replace("dd", "%d")
|
||||
fmt = fmt.replace("HH", "%H").replace("mm", "%M").replace("ss", "%S")
|
||||
return now.strftime(fmt)
|
||||
save_directory = re.sub(r"date:([\w\-\:]+)", replace_date, save_directory)
|
||||
|
||||
# Also handle direct strftime patterns if any % is present
|
||||
if "%" in save_directory:
|
||||
save_directory = now.strftime(save_directory)
|
||||
|
||||
filename_prefix = os.path.join(save_directory, filename_prefix)
|
||||
|
||||
full_output_folder, filename, counter, subfolder, filename_prefix = \
|
||||
folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0])
|
||||
|
||||
results = list()
|
||||
for image in images:
|
||||
i = 255. * image.cpu().numpy()
|
||||
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||
metadata = PngInfo()
|
||||
|
||||
# 1. Construct A1111 Parameters String
|
||||
# Format: Prompt
|
||||
# Negative prompt: ...
|
||||
# Steps: ..., Sampler: ..., CFG scale: ..., Seed: ..., Size: ...x..., Model: ..., ...
|
||||
|
||||
parameters_text = f"{positive_prompt}\nNegative prompt: {negative_prompt}\n"
|
||||
parameters_text += f"Steps: {steps}, Sampler: {sampler_name}, Schedule: {scheduler}, CFG scale: {cfg}, Seed: {seed}, "
|
||||
parameters_text += f"Size: {width}x{height}, Model: {checkpoint_name}"
|
||||
|
||||
if clip_skip != -2:
|
||||
parameters_text += f", Clip skip: {clip_skip}"
|
||||
|
||||
if upscale_factor > 1.0:
|
||||
parameters_text += f", Hires upscale: {upscale_factor}, Hires steps: {hires_steps}, Hires upscaler: {upscaler_name}, Denoising strength: {denoise}"
|
||||
|
||||
if lora_name:
|
||||
display_lora_name = Path(lora_name).name
|
||||
parameters_text += f", Lora: {display_lora_name}"
|
||||
|
||||
metadata.add_text("parameters", parameters_text)
|
||||
|
||||
# 2. Construct ComfyUI Metadata JSON (following spec)
|
||||
comfy_meta = {
|
||||
"_description": "Extended metadata specific to ComfyUI workflow",
|
||||
"workflow_name": "AODH Generator", # Could be dynamic if we parsed extra_pnginfo
|
||||
"workflow_version": "1.0.0",
|
||||
"generation": {
|
||||
"checkpoint": checkpoint_name,
|
||||
"vae": vae_name,
|
||||
"clip_skip": clip_skip,
|
||||
"lora": [{"name": Path(lora_name).name, "strength_model": lora_strength}] if lora_name else []
|
||||
},
|
||||
"sampling": {
|
||||
"sampler": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"seed": seed,
|
||||
"batch_size": images.shape[0]
|
||||
},
|
||||
"resolution": {
|
||||
"width": width,
|
||||
"height": height,
|
||||
"upscale_factor": upscale_factor,
|
||||
"upscaler": upscaler_name,
|
||||
"hires_steps": hires_steps,
|
||||
"denoise_strength": denoise
|
||||
},
|
||||
"prompt_structure": {
|
||||
"positive": {"full": positive_prompt},
|
||||
"negative": {"full": negative_prompt}
|
||||
},
|
||||
"workflow": {}
|
||||
}
|
||||
|
||||
# Embed raw workflow if available
|
||||
if include_workflow:
|
||||
if prompt is not None:
|
||||
comfy_meta["workflow"]["execution"] = prompt
|
||||
if extra_pnginfo is not None and "workflow" in extra_pnginfo:
|
||||
comfy_meta["workflow"]["nodes"] = extra_pnginfo["workflow"]
|
||||
|
||||
# 3. App Metadata
|
||||
app_meta = {
|
||||
"tags": [t.strip() for t in tags.split(",") if t.strip()],
|
||||
"character": character_name,
|
||||
"rating": rating
|
||||
}
|
||||
|
||||
# Add to main JSON
|
||||
full_metadata = {
|
||||
"parameters": parameters_text,
|
||||
"source": "comfyui",
|
||||
"comfyui": True,
|
||||
"comfyui_metadata": comfy_meta,
|
||||
"app_metadata": app_meta
|
||||
}
|
||||
|
||||
# Embed as "comment" or a specific key.
|
||||
# The spec says "A ComfyUI node should embed this metadata in the 'parameters' PNG text chunk."
|
||||
# But usually JSON goes into a separate chunk or we rely on the parser to extract it from 'parameters' if it was formatted there.
|
||||
# However, standard ComfyUI puts workflow in "workflow" and "prompt" chunks.
|
||||
# The spec implies a specific JSON structure. We'll add it as a separate text chunk "comfyui_metadata_json"
|
||||
# OR we can try to append it to parameters, but A1111 parsers might break.
|
||||
# Let's put the full JSON in a "aodh_metadata" chunk for safety,
|
||||
# and ALSO try to adhere to standard Comfy behavior by keeping workflow/prompt chunks.
|
||||
|
||||
if include_workflow:
|
||||
if prompt is not None:
|
||||
metadata.add_text("prompt", json.dumps(prompt))
|
||||
if extra_pnginfo is not None:
|
||||
for x in extra_pnginfo:
|
||||
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
||||
|
||||
# Add our custom full spec JSON
|
||||
metadata.add_text("aodh_metadata", json.dumps(full_metadata, indent=2))
|
||||
|
||||
file = f"{filename}_{counter:05}_.{extension}"
|
||||
img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4)
|
||||
results.append({
|
||||
"filename": file,
|
||||
"subfolder": subfolder,
|
||||
"type": self.type
|
||||
})
|
||||
counter += 1
|
||||
|
||||
return { "ui": { "images": results }, "result": (images,) }
|
||||
@@ -29,17 +29,20 @@ class ResolutionReader:
|
||||
return float("nan")
|
||||
return resolution
|
||||
|
||||
RETURN_TYPES = ("INT", "INT", "FLOAT")
|
||||
RETURN_NAMES = ("width", "height", "upscale")
|
||||
RETURN_TYPES = ("INT", "INT", "FLOAT", "INT")
|
||||
RETURN_NAMES = ("width", "height", "upscale", "total_resolutions")
|
||||
|
||||
FUNCTION = "read_resolution"
|
||||
CATEGORY = "AODH Pack"
|
||||
|
||||
_current_index = 0
|
||||
_current_count = 0
|
||||
_last_selection = None
|
||||
def __init__(self):
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_selection = None
|
||||
self.last_start_resolution = None
|
||||
|
||||
def read_resolution(self, resolution, selection_mode, repeat_count):
|
||||
repeat_count = max(1, repeat_count)
|
||||
base_path = os.path.dirname(os.path.realpath(__file__))
|
||||
file_path = os.path.join(base_path, "resolutions", "resolutions.txt")
|
||||
|
||||
@@ -49,22 +52,33 @@ class ResolutionReader:
|
||||
lines = [line.strip() for line in f.readlines() if line.strip()]
|
||||
|
||||
if not lines:
|
||||
return (0, 0, 0.0)
|
||||
return (0, 0, 0.0, 0)
|
||||
|
||||
# Reset sequence if resolution changes
|
||||
if self.last_start_resolution != resolution:
|
||||
try:
|
||||
self.current_index = lines.index(resolution)
|
||||
except ValueError:
|
||||
self.current_index = 0
|
||||
self.current_count = 0
|
||||
self.last_start_resolution = resolution
|
||||
|
||||
if selection_mode == "manual":
|
||||
selected_line = resolution
|
||||
elif selection_mode == "sequential":
|
||||
if self.__class__._current_count >= repeat_count:
|
||||
self.__class__._current_index += 1
|
||||
self.__class__._current_count = 0
|
||||
selected_line = lines[self.__class__._current_index % len(lines)]
|
||||
self.__class__._current_count += 1
|
||||
if self.current_count >= repeat_count:
|
||||
self.current_index += 1
|
||||
self.current_count = 0
|
||||
selected_line = lines[self.current_index % len(lines)]
|
||||
self.current_count += 1
|
||||
elif selection_mode == "random":
|
||||
if self.__class__._current_count >= repeat_count or self.__class__._last_selection is None:
|
||||
self.__class__._last_selection = random.choice(lines)
|
||||
self.__class__._current_count = 0
|
||||
selected_line = self.__class__._last_selection
|
||||
self.__class__._current_count += 1
|
||||
if self.current_count >= repeat_count or self.last_selection is None:
|
||||
# Use a local Random instance to ensure randomness regardless of global seed
|
||||
rng = random.Random()
|
||||
self.last_selection = rng.choice(lines)
|
||||
self.current_count = 0
|
||||
selected_line = self.last_selection
|
||||
self.current_count += 1
|
||||
else:
|
||||
selected_line = resolution
|
||||
|
||||
@@ -74,6 +88,6 @@ class ResolutionReader:
|
||||
width = int(parts[0])
|
||||
height = int(parts[1])
|
||||
upscale = float(parts[2])
|
||||
return (width, height, upscale)
|
||||
return (width, height, upscale, len(lines))
|
||||
except (ValueError, IndexError):
|
||||
return (0, 0, 0.0)
|
||||
return (0, 0, 0.0, len(lines))
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
1280,720,3.0
|
||||
720,1280,3.0
|
||||
1376,576,2.5
|
||||
576,1376,2.5
|
||||
1024,1024,2.0
|
||||
1280,800,2.7
|
||||
1125,750,2.0
|
||||
750,1125,2.0
|
||||
Reference in New Issue
Block a user