408 lines
12 KiB
Python
408 lines
12 KiB
Python
import random
|
|
|
|
DIRECTIONS = (
|
|
"front view",
|
|
"front-right quarter view",
|
|
"right side view",
|
|
"back-right quarter view",
|
|
"back view",
|
|
"back-left quarter view",
|
|
"left side view",
|
|
"front-left quarter view",
|
|
)
|
|
VERTICAL_ANGLES = ("low-angle", "eye-level", "elevated", "high-angle")
|
|
SHOT_SIZES = ("close-up", "medium shot", "wide shot")
|
|
|
|
EXPRESSIONS = (
|
|
"neutral", "smile", "big smile", "laughing", "smirk", "frown", "sad", "crying",
|
|
"angry", "surprised", "shocked", "scared", "disgusted", "confused", "winking", "pouting",
|
|
)
|
|
|
|
POSES = (
|
|
"standing", "sitting", "kneeling", "crouching", "lying down", "walking", "running", "jumping",
|
|
"arms crossed", "hands on hips", "arms raised", "leaning forward", "leaning back",
|
|
"looking over shoulder", "T-pose", "contrapposto",
|
|
)
|
|
|
|
LIGHTING = (
|
|
"soft natural light", "harsh sunlight", "golden hour", "blue hour", "overcast daylight",
|
|
"studio lighting", "rim lighting", "backlight", "side lighting", "top-down lighting",
|
|
"low-key lighting", "high-key lighting", "neon lighting", "candlelight", "moonlight",
|
|
"dramatic chiaroscuro",
|
|
)
|
|
|
|
CAMERA_TYPES = (
|
|
# vintage film & early imaging
|
|
"Kodak Brownie box camera",
|
|
"pinhole camera",
|
|
"Bolex 16mm film camera",
|
|
"Super 8 film camera",
|
|
"VHS camcorder",
|
|
"Sony Mavica floppy disk camera",
|
|
"Sony Handycam camcorder",
|
|
# instant
|
|
"Polaroid SX-70 instant camera",
|
|
"Polaroid 600 instant camera",
|
|
"disposable film camera",
|
|
# classic 35mm SLRs
|
|
"Canon AE-1 35mm SLR",
|
|
"Nikon F3 35mm SLR",
|
|
"Pentax K1000 35mm SLR",
|
|
"Olympus OM-1 35mm SLR",
|
|
# rangefinder & toy
|
|
"Leica M6 rangefinder",
|
|
"Lomography LC-A",
|
|
"Holga toy medium format camera",
|
|
# medium / large format film
|
|
"Hasselblad 500C/M medium format",
|
|
"large format view camera",
|
|
# modern digital stills
|
|
"Canon EOS 5D Mark IV DSLR",
|
|
"Nikon D850 DSLR",
|
|
"Sony Alpha A7 III mirrorless",
|
|
"Fujifilm X100V mirrorless",
|
|
"Leica Q2",
|
|
"Hasselblad X1D medium format digital",
|
|
# mobile
|
|
"iPhone 15 Pro smartphone",
|
|
"Samsung Galaxy smartphone camera",
|
|
# action / aerial
|
|
"GoPro Hero action camera",
|
|
"DJI Mavic drone camera",
|
|
# cinema
|
|
"Arri Alexa cinema camera",
|
|
"RED Komodo cinema camera",
|
|
"Panavision Panaflex 35mm cinema camera",
|
|
"IMAX 70mm camera",
|
|
"anamorphic lens",
|
|
# specialty / surveillance
|
|
"security CCTV camera",
|
|
"webcam",
|
|
"dashcam",
|
|
"thermal imaging camera",
|
|
"night vision camera",
|
|
)
|
|
|
|
BACKGROUNDS = (
|
|
# residential interiors
|
|
"living room",
|
|
"messy living room",
|
|
"bedroom",
|
|
"messy bedroom",
|
|
"modern kitchen",
|
|
"rustic kitchen",
|
|
"bathroom",
|
|
"home office",
|
|
"attic",
|
|
"basement",
|
|
"garage",
|
|
"dining room",
|
|
"nursery",
|
|
"walk-in closet",
|
|
"cozy reading nook",
|
|
# public / commercial interiors
|
|
"coffee shop",
|
|
"fine dining restaurant",
|
|
"dive bar",
|
|
"nightclub",
|
|
"public library",
|
|
"bookstore",
|
|
"art gallery",
|
|
"museum hall",
|
|
"hotel lobby",
|
|
"open-plan office",
|
|
"classroom",
|
|
"gym",
|
|
"hospital room",
|
|
"subway station platform",
|
|
"airport terminal",
|
|
# outdoor urban
|
|
"busy city street at night",
|
|
"narrow alleyway",
|
|
"rooftop at sunset",
|
|
"multi-level parking garage",
|
|
"suburban street",
|
|
"neon-lit Tokyo street",
|
|
# outdoor nature
|
|
"dense forest",
|
|
"tropical beach",
|
|
"desert dunes",
|
|
"snowy mountain peak",
|
|
"flower meadow",
|
|
"lakeside dock",
|
|
"waterfall clearing",
|
|
"jungle",
|
|
"autumn park",
|
|
# studio
|
|
"white seamless backdrop",
|
|
"black studio backdrop",
|
|
"gray studio backdrop",
|
|
"green screen",
|
|
)
|
|
|
|
CLOTHES = (
|
|
# formal / business
|
|
"business suit",
|
|
"three-piece suit",
|
|
"tuxedo",
|
|
"cocktail dress",
|
|
"evening gown",
|
|
"ball gown",
|
|
# casual everyday
|
|
"white t-shirt and jeans",
|
|
"hoodie and joggers",
|
|
"summer dress",
|
|
"sundress",
|
|
"cargo shorts and tank top",
|
|
# outerwear-led looks
|
|
"leather biker jacket outfit",
|
|
"noir trenchcoat look",
|
|
"denim jacket and jeans",
|
|
"peacoat ensemble",
|
|
# workwear / uniforms
|
|
"chef whites",
|
|
"doctor's scrubs",
|
|
"lab coat",
|
|
"hospital gown",
|
|
"military fatigues",
|
|
"police uniform",
|
|
"firefighter turnout gear",
|
|
"construction hi-vis",
|
|
# athletic / outdoor
|
|
"athletic tracksuit",
|
|
"yoga outfit",
|
|
"ski jumpsuit",
|
|
"hiking gear",
|
|
"swimwear",
|
|
"wetsuit",
|
|
# traditional / cultural
|
|
"kimono",
|
|
"hanbok",
|
|
"sari",
|
|
"cheongsam",
|
|
"dashiki",
|
|
"lederhosen",
|
|
"Scottish kilt outfit",
|
|
# historical eras
|
|
"medieval peasant garb",
|
|
"Victorian gown",
|
|
"1920s flapper dress",
|
|
"1950s rockabilly",
|
|
"1970s disco outfit",
|
|
"1980s power suit",
|
|
"1990s grunge",
|
|
# subculture / genre
|
|
"cyberpunk streetwear",
|
|
"gothic lolita",
|
|
"punk rock",
|
|
"steampunk attire",
|
|
"hip-hop streetwear",
|
|
"preppy",
|
|
# fantasy / costume
|
|
"wizard robes",
|
|
"knight's armor",
|
|
"superhero costume",
|
|
"vampire attire",
|
|
"pirate outfit",
|
|
"space suit",
|
|
# loungewear / sleepwear
|
|
"pajamas",
|
|
"silk robe",
|
|
"bathrobe",
|
|
)
|
|
|
|
_SEED = ("INT", {"default": 0, "min": 0, "max": 0xFFFFFFFFFFFFFFFF})
|
|
_PREVIOUS = ("STRING", {"default": "", "forceInput": True})
|
|
|
|
|
|
def _build_prompt(prefix: str, body: str, previous: str, separator: str) -> str:
|
|
own = f"{prefix}{body}"
|
|
return f"{previous}{separator}{own}" if previous else own
|
|
|
|
|
|
def _resolve(rng: random.Random, value: str, choices: tuple) -> str:
|
|
return rng.choice(choices) if value == "random" else value
|
|
|
|
|
|
class CameraAngleSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"direction": (("random", *DIRECTIONS), {"default": "front view"}),
|
|
"vertical_angle": (("random", *VERTICAL_ANGLES), {"default": "eye-level"}),
|
|
"shot_size": (("random", *SHOT_SIZES), {"default": "medium shot"}),
|
|
"prefix": ("STRING", {"default": "Change camera angle to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/camera"
|
|
|
|
def build(self, direction, vertical_angle, shot_size, prefix, separator, seed, previous_prompt=""):
|
|
rng = random.Random(seed)
|
|
direction = _resolve(rng, direction, DIRECTIONS)
|
|
vertical_angle = _resolve(rng, vertical_angle, VERTICAL_ANGLES)
|
|
shot_size = _resolve(rng, shot_size, SHOT_SIZES)
|
|
body = f"{direction} {vertical_angle} shot {shot_size}"
|
|
return (_build_prompt(prefix, body, previous_prompt, separator),)
|
|
|
|
|
|
class FacialExpressionSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"expression": (("random", *EXPRESSIONS), {"default": "neutral"}),
|
|
"prefix": ("STRING", {"default": "Change facial expression to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/character"
|
|
|
|
def build(self, expression, prefix, separator, seed, previous_prompt=""):
|
|
rng = random.Random(seed)
|
|
expression = _resolve(rng, expression, EXPRESSIONS)
|
|
return (_build_prompt(prefix, expression, previous_prompt, separator),)
|
|
|
|
|
|
class PoseSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"pose": (("random", *POSES), {"default": "standing"}),
|
|
"prefix": ("STRING", {"default": "Change pose to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/character"
|
|
|
|
def build(self, pose, prefix, separator, seed, previous_prompt=""):
|
|
rng = random.Random(seed)
|
|
pose = _resolve(rng, pose, POSES)
|
|
return (_build_prompt(prefix, pose, previous_prompt, separator),)
|
|
|
|
|
|
class LightingSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"lighting": (("random", *LIGHTING), {"default": "soft natural light"}),
|
|
"prefix": ("STRING", {"default": "Change lighting to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/scene"
|
|
|
|
def build(self, lighting, prefix, separator, seed, previous_prompt=""):
|
|
rng = random.Random(seed)
|
|
lighting = _resolve(rng, lighting, LIGHTING)
|
|
return (_build_prompt(prefix, lighting, previous_prompt, separator),)
|
|
|
|
|
|
class CameraTypeSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"camera_type": (("random", *CAMERA_TYPES), {"default": "Canon EOS 5D Mark IV DSLR"}),
|
|
"prefix": ("STRING", {"default": "Change camera type to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/camera"
|
|
|
|
def build(self, camera_type, prefix, separator, seed, previous_prompt=""):
|
|
rng = random.Random(seed)
|
|
camera_type = _resolve(rng, camera_type, CAMERA_TYPES)
|
|
return (_build_prompt(prefix, camera_type, previous_prompt, separator),)
|
|
|
|
|
|
class BackgroundChangerSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"background": (("random", *BACKGROUNDS), {"default": "living room"}),
|
|
"custom_background": ("STRING", {"default": "", "multiline": True}),
|
|
"prefix": ("STRING", {"default": "Change background to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/scene"
|
|
|
|
def build(self, background, custom_background, prefix, separator, seed, previous_prompt=""):
|
|
custom = custom_background.strip()
|
|
if custom:
|
|
body = custom
|
|
else:
|
|
rng = random.Random(seed)
|
|
body = _resolve(rng, background, BACKGROUNDS)
|
|
return (_build_prompt(prefix, body, previous_prompt, separator),)
|
|
|
|
|
|
class ClothesChangerSelector:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"clothes": (("random", *CLOTHES), {"default": "business suit"}),
|
|
"custom_clothes": ("STRING", {"default": "", "multiline": True}),
|
|
"prefix": ("STRING", {"default": "Change clothes to ", "multiline": False}),
|
|
"separator": ("STRING", {"default": ", ", "multiline": False}),
|
|
"seed": _SEED,
|
|
},
|
|
"optional": {"previous_prompt": _PREVIOUS},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("prompt",)
|
|
FUNCTION = "build"
|
|
CATEGORY = "prompt/character"
|
|
|
|
def build(self, clothes, custom_clothes, prefix, separator, seed, previous_prompt=""):
|
|
custom = custom_clothes.strip()
|
|
if custom:
|
|
body = custom
|
|
else:
|
|
rng = random.Random(seed)
|
|
body = _resolve(rng, clothes, CLOTHES)
|
|
return (_build_prompt(prefix, body, previous_prompt, separator),)
|