diff --git a/categories/default_categories.json b/categories/default_categories.json index adf50d9..48e464f 100644 --- a/categories/default_categories.json +++ b/categories/default_categories.json @@ -506,6 +506,324 @@ "standing in profile near soft curtains", "reclining with one arm draped over a pillow" ] + }, + { + "name": "Smart casual", + "slug": "smart_casual", + "weight": 1.0, + "inherit_expressions": false, + "inherit_compositions": false, + "scene_pools": ["casual_smart_scenes"], + "expression_pools": ["smart_casual_expressions"], + "composition_pools": ["smart_casual_compositions"], + "items": ["smart casual outfit generator"], + "item_templates": [ + "{jacket} over {top}, with {bottom}, {footwear}, and {bag}", + "{set_piece} styled with {jewelry}, {footwear}, and {color_mood}", + "{top} tucked into {bottom}, paired with {jacket}, {accessory}, and {detail}", + "{dress_piece} with {jacket}, {footwear}, {bag}, and {texture_detail}", + "{jacket} with {bottom}, {top}, {jewelry}, and {color_mood}", + "{set_piece} with {accessory}, {bag}, and {detail}", + "{top} under {layer}, with {bottom}, {footwear}, and {texture_detail}", + "{dress_piece} styled with {accessory}, {jewelry}, and {color_mood}" + ], + "item_axes": { + "accessory": [ + "thin sunglasses", + "a silk neck scarf", + "a narrow belt", + "wire-frame glasses", + "a minimalist hair clip", + "a structured watch", + "a soft leather belt", + "a neat phone case in hand" + ], + "bag": [ + "a structured tote", + "a compact leather shoulder bag", + "a slim laptop bag", + "a small satchel", + "a clean crossbody bag", + "a polished bucket bag", + "a narrow clutch", + "a minimal work tote" + ], + "bottom": [ + "tailored ankle trousers", + "wide-leg pleated trousers", + "dark straight-leg jeans", + "a satin midi skirt", + "a pencil skirt with a soft slit", + "cropped cigarette trousers", + "high-waist wool trousers", + "a clean A-line skirt" + ], + "color_mood": [ + "charcoal, ivory, and soft blue", + "navy and warm white", + "black with muted green accents", + "soft grey and pale pink", + "deep wine and cream tones", + "camel, white, and graphite", + "olive and black contrast", + "cool slate and silver details" + ], + "detail": [ + "rolled blazer sleeves", + "a clean tucked waist", + "softly structured proportions", + "a polished off-duty silhouette", + "a crisp collar line", + "subtle layered hems", + "a relaxed but tailored fit", + "neat high-waist styling" + ], + "dress_piece": [ + "ribbed knit midi dress", + "simple slip dress", + "button-front shirt dress", + "soft wrap dress", + "tailored sleeveless dress", + "clean knit column dress", + "minimal black day dress", + "belted cotton midi dress" + ], + "footwear": [ + "leather loafers", + "low block heels", + "minimal white sneakers", + "ankle boots", + "pointed flats", + "clean slingback heels", + "polished mules", + "sleek platform loafers" + ], + "jacket": [ + "soft oversized blazer", + "cropped tweed jacket", + "unstructured linen blazer", + "short trench jacket", + "boxy wool blazer", + "open cardigan blazer", + "clean leather jacket", + "tailored sleeveless vest" + ], + "jewelry": [ + "small gold hoops", + "a fine pendant necklace", + "stacked slim rings", + "pearl stud earrings", + "a narrow bracelet", + "minimal silver earrings", + "a delicate watch", + "a thin chain necklace" + ], + "layer": [ + "light trench coat", + "long knit cardigan", + "open tailored vest", + "soft cropped jacket", + "fine-gauge cardigan", + "relaxed blazer", + "short wool coat", + "silk bomber jacket" + ], + "set_piece": [ + "matching blazer and trouser set", + "knit top and midi skirt set", + "soft suit separates", + "vest and wide-trouser outfit", + "shirt-and-tailored-jean outfit", + "minimal workday co-ord", + "slip dress and blazer outfit", + "cardigan and pleated-skirt outfit" + ], + "texture_detail": [ + "smooth wool texture", + "soft satin sheen", + "crisp cotton folds", + "fine ribbed knit", + "matte crepe fabric", + "light linen slubs", + "polished leather accents", + "subtle woven texture" + ], + "top": [ + "silk camisole", + "ribbed mock-neck top", + "buttoned cotton shirt", + "soft blouse", + "fitted knit tee", + "square-neck tank", + "fine turtleneck", + "draped satin top" + ] + }, + "scenes": [ + {"slug": "coworking_lounge_window", "prompt": "coworking lounge with tall windows, warm desks, and a polished outfit-check angle"}, + {"slug": "office_elevator_mirror", "prompt": "modern office elevator lobby with brushed metal doors and a full-length mirror"}, + {"slug": "gallery_opening_corner", "prompt": "small gallery opening with white walls, framed art, and soft evening light"}, + {"slug": "wine_bar_terrace", "prompt": "quiet wine bar terrace with small tables, street lights, and relaxed after-work mood"} + ], + "poses": [ + "standing with one hand holding a structured tote", + "adjusting a blazer cuff while looking at the camera", + "leaning against a window counter with relaxed posture", + "walking through an office lobby with a confident stride", + "checking a phone while the outfit stays fully visible", + "sitting on a low chair with ankles crossed", + "turning slightly to show the jacket silhouette", + "standing near a mirror with one hand at the waist" + ] + }, + { + "name": "Athleisure", + "slug": "athleisure", + "weight": 1.0, + "inherit_expressions": false, + "inherit_compositions": false, + "scene_pools": ["casual_athleisure_scenes"], + "expression_pools": ["athleisure_focused_expressions"], + "composition_pools": ["athleisure_compositions"], + "items": ["athleisure outfit generator"], + "item_templates": [ + "{top} with {bottom}, {footwear}, {bag}, and {texture_detail}", + "{set_piece} with {layer}, {accessory}, and {color_mood}", + "{layer} over {top}, with {bottom}, {footwear}, and {detail}", + "{top} tucked into {bottom}, paired with {accessory}, {prop}, and {texture_detail}", + "{set_piece} styled with {footwear}, {bag}, and {detail}", + "{top} with {bottom}, {layer}, {accessory}, and {color_mood}", + "{layer} tied at the waist over {top}, with {bottom}, {footwear}, and {prop}", + "{set_piece} with {accessory}, {texture_detail}, and {bag}" + ], + "item_axes": { + "accessory": [ + "a baseball cap", + "thin sport sunglasses", + "a scrunchie at the wrist", + "wireless earbuds", + "a soft headband", + "a fitness watch", + "a small towel over one shoulder", + "a zippered phone armband" + ], + "bag": [ + "a compact gym bag", + "a nylon sling bag", + "a canvas tote", + "a small backpack", + "a drawstring sport bag", + "a crossbody phone pouch", + "a rolled yoga mat strap", + "a minimal duffel" + ], + "bottom": [ + "high-waist leggings", + "bike shorts", + "wide-leg track pants", + "soft joggers", + "ribbed flare leggings", + "running shorts", + "cropped yoga pants", + "sleek training tights" + ], + "color_mood": [ + "black, white, and neon green accents", + "soft grey and lavender tones", + "navy with clean white details", + "sage green and charcoal", + "warm coral and cream", + "graphite and powder blue", + "muted berry and black", + "fresh white and silver accents" + ], + "detail": [ + "a clean high-waist line", + "body-skimming stretch fit", + "visible sporty seam lines", + "cropped proportions", + "relaxed post-workout styling", + "layered athletic straps", + "sleek compression fit", + "soft draped warm-up layers" + ], + "footwear": [ + "running shoes", + "clean white trainers", + "chunky athletic sneakers", + "minimal walking shoes", + "sleek gym sneakers", + "retro trainers", + "soft slip-on sneakers", + "platform sport sneakers" + ], + "layer": [ + "cropped zip hoodie", + "oversized warm-up jacket", + "light windbreaker", + "open flannel shirt", + "soft track jacket", + "mesh training jacket", + "sleeveless puffer vest", + "relaxed crewneck sweatshirt" + ], + "prop": [ + "a stainless water bottle", + "a rolled yoga mat", + "a phone in hand", + "a towel tucked under one arm", + "a smoothie cup", + "a pair of headphones", + "a locker key band", + "a folded hoodie nearby" + ], + "set_piece": [ + "matching sports bra and legging set", + "cropped hoodie and jogger set", + "training tank and bike-short outfit", + "ribbed workout co-ord", + "track jacket and flare-legging outfit", + "running top and short set", + "yoga set with a soft wrap layer", + "monochrome athleisure set" + ], + "texture_detail": [ + "smooth stretch fabric", + "matte performance knit", + "ribbed athletic texture", + "mesh panel details", + "soft fleece trim", + "light nylon sheen", + "breathable jersey fabric", + "subtle compression seams" + ], + "top": [ + "cropped training tank", + "fitted sport tee", + "longline sports bra", + "ribbed workout top", + "sleeveless zip top", + "soft racerback tank", + "cropped crewneck sweatshirt", + "mesh-layered athletic top" + ] + }, + "scenes": [ + {"slug": "pilates_studio_mirror", "prompt": "bright pilates studio with mirrors, mats, and soft daylight"}, + {"slug": "gym_lobby_outfit_check", "prompt": "clean gym lobby with lockers, rubber flooring, and a phone outfit-check angle"}, + {"slug": "park_running_path", "prompt": "tree-lined park running path with morning light and open walking space"}, + {"slug": "rooftop_yoga_corner", "prompt": "rooftop yoga corner with mats, plants, and city skyline in warm light"} + ], + "poses": [ + "standing with one foot forward and a water bottle in hand", + "stretching one arm overhead while the outfit stays visible", + "leaning against a locker with relaxed confidence", + "walking away from a workout mat while looking back", + "sitting on a mat with one knee raised", + "adjusting earbuds before a walk", + "standing in a mirror outfit-check pose", + "tying a hoodie around the waist" + ] } ] } diff --git a/categories/expression_composition_pools.json b/categories/expression_composition_pools.json index 6c6a7dc..72bbf04 100644 --- a/categories/expression_composition_pools.json +++ b/categories/expression_composition_pools.json @@ -51,6 +51,30 @@ "softly serious window-light expression", "calm private-moment face" ], + "smart_casual_expressions": [ + "composed workday gaze", + "quiet confident half-smile", + "focused after-work expression", + "calm gallery-opening stare", + "polished phone-camera look", + "subtle professional smile", + "thoughtful side glance", + "reserved but warm expression", + "confident outfit-check stare", + "relaxed city-evening expression" + ], + "athleisure_focused_expressions": [ + "fresh post-workout expression", + "focused activewear stare", + "relaxed sporty half-smile", + "winded but composed look", + "direct mirror-check gaze", + "calm pre-workout focus", + "soft morning-run expression", + "confident athletic side glance", + "casual earbuds-in expression", + "bright outdoor training look" + ], "softcore_creator_expressions": [ "direct creator-shot eye contact", "heavy-lidded bedroom gaze", @@ -301,6 +325,30 @@ "overhead sofa composition", "side-profile lounge silhouette" ], + "smart_casual_compositions": [ + "full-body smart-casual outfit-check frame", + "polished mirror view with bag and shoes visible", + "three-quarter workday portrait with structured layers readable", + "gallery-opening vertical frame with clean negative space", + "office-lobby walking composition", + "seated lounge-chair frame with ankles and footwear visible", + "waist-up crop focused on collar, jacket, and jewelry", + "side-profile tailored silhouette frame", + "phone-snapshot crop from head to shoes", + "calm street-corner editorial composition" + ], + "athleisure_compositions": [ + "full-body activewear outfit-check frame", + "mirror gym-lobby crop with shoes and bag visible", + "standing stretch composition with full silhouette readable", + "mat-level seated athletic frame", + "walking path phone-photo composition", + "three-quarter activewear crop with seams and layers visible", + "side-profile sporty silhouette", + "low-angle trainer-focused frame", + "bright studio mirror composition", + "post-workout lifestyle frame with prop visible" + ], "softcore_creator_compositions": [ "handheld selfie crop from face to hips", "mirror selfie with phone visible and body framed clearly", diff --git a/categories/location_pools.json b/categories/location_pools.json index 92dfea9..e0845b6 100644 --- a/categories/location_pools.json +++ b/categories/location_pools.json @@ -31,6 +31,26 @@ {"slug": "hotel_morning_lounge", "prompt": "hotel room lounge chair with rumpled travel bags, curtains, and soft morning sun"}, {"slug": "studio_apartment_mirror", "prompt": "small studio apartment with a full-length mirror, neutral bedding, and warm lamp light"} ], + "casual_smart_scenes": [ + {"slug": "coworking_lounge_window", "prompt": "coworking lounge with tall windows, warm desks, and a polished outfit-check angle"}, + {"slug": "office_elevator_mirror", "prompt": "modern office elevator lobby with brushed metal doors and a full-length mirror"}, + {"slug": "gallery_opening_corner", "prompt": "small gallery opening with white walls, framed art, and soft evening light"}, + {"slug": "wine_bar_terrace", "prompt": "quiet wine bar terrace with small tables, street lights, and relaxed after-work mood"}, + {"slug": "bookstore_event_smart", "prompt": "independent bookstore event corner with display tables, warm lamps, and polished casual styling"}, + {"slug": "hotel_lobby_daywear", "prompt": "bright hotel lobby with marble floor, lounge seating, and a clean daywear portrait angle"}, + {"slug": "museum_steps_smart", "prompt": "museum entrance steps with stone walls, soft sky light, and a composed outfit-photo frame"}, + {"slug": "business_cafe_counter", "prompt": "quiet business cafe counter with laptops, plants, and a smart-casual mirror nearby"} + ], + "casual_athleisure_scenes": [ + {"slug": "pilates_studio_mirror", "prompt": "bright pilates studio with mirrors, mats, and soft daylight"}, + {"slug": "gym_lobby_outfit_check", "prompt": "clean gym lobby with lockers, rubber flooring, and a phone outfit-check angle"}, + {"slug": "park_running_path", "prompt": "tree-lined park running path with morning light and open walking space"}, + {"slug": "rooftop_yoga_corner", "prompt": "rooftop yoga corner with mats, plants, and city skyline in warm light"}, + {"slug": "locker_room_mirror_clean", "prompt": "clean locker-room mirror area with benches, soft overhead lights, and athletic outfit framing"}, + {"slug": "studio_stairwell_active", "prompt": "fitness studio stairwell with concrete steps, handrails, and bright side light"}, + {"slug": "track_side_morning", "prompt": "outdoor track edge with morning sun, lane markings, and open activewear framing"}, + {"slug": "smoothie_bar_postworkout", "prompt": "smoothie bar counter near a gym entrance with bright tiles and casual post-workout light"} + ], "softcore_creator_scenes": [ {"slug": "creator_bedroom_ring_light", "prompt": "private creator bedroom with a ring light, phone tripod, rumpled bedding, and warm lamps"}, {"slug": "onlyfans_mirror_bedroom", "prompt": "bedroom mirror selfie setup with a visible phone, messy sheets, and soft amber light"}, diff --git a/categories/sexual_poses.json b/categories/sexual_poses.json index c19bd56..b9db929 100644 --- a/categories/sexual_poses.json +++ b/categories/sexual_poses.json @@ -351,7 +351,7 @@ "face-sitting position", "sixty-nine position", "edge-of-bed oral position", - "standing blowjob position", + "standing oral position", "reclining cunnilingus position", "straddled oral position", "side-lying oral position", diff --git a/prompt_builder.py b/prompt_builder.py index 75895d6..7670a51 100644 --- a/prompt_builder.py +++ b/prompt_builder.py @@ -55,18 +55,18 @@ GENERIC_POSITIVE_SUFFIX = ( SINGLE_TEMPLATE = ( "A {subject}: {style}, {age}, {body_phrase}, {skin}, {hair}, {eyes}. " "{item_label}: {item}. Scene: {scene}. Pose: {pose}. Facial expression: {expression}. " - "Composition: vertical {composition}. {positive_suffix} Avoid: {negative_prompt}." + "Composition: {composition_prompt}. {positive_suffix} Avoid: {negative_prompt}." ) COUPLE_TEMPLATE = ( "{subject_phrase}: {style}. Ages: {age}. Body types: {body}. {item_label}: {item}. " "Scene: {scene}. Pose: {pose}. Facial expressions: {expression}. " - "Composition: vertical {composition}. {positive_suffix} Avoid: {negative_prompt}." + "Composition: {composition_prompt}. {positive_suffix} Avoid: {negative_prompt}." ) GROUP_TEMPLATE = ( "{subject_phrase}: {style}, ages {age}, diverse adult body types. {item_label}: {item}. " - "Scene: {scene}. Facial expressions: {expression}. Composition: vertical {composition}. " + "Scene: {scene}. Facial expressions: {expression}. Composition: {composition_prompt}. " "{positive_suffix} Avoid: {negative_prompt}." ) @@ -1154,6 +1154,16 @@ def _body_phrase(body: Any, figure_note: Any = "") -> str: return f"{body} figure with {figure_note}" +def _composition_prompt(composition: str) -> str: + composition = str(composition or "").strip() + if not composition: + return composition + lower = composition.lower() + if lower.startswith("vertical ") or " vertical " in lower or lower.endswith(" vertical"): + return composition + return f"vertical {composition}" + + def _appearance_for_subject( rng: random.Random, subject_type: str, @@ -1384,7 +1394,12 @@ def _role_graph( man = any_man() third = any_person({woman, man}) if people_count >= 3 else "" if "oral" in slug: - graph = f"{woman} gives oral to {man} while {man} holds her hair and hips." + if "sixty-nine" in item_text or ("blowjob" in item_text and ("cunnilingus" in item_text or "pussy" in item_text)): + graph = f"{woman} and {man} are in mutual oral contact with mouth-to-genital contact visible." + elif any(term in item_text for term in ("cunnilingus", "pussy licking", "tongue on pussy", "mouth on pussy")): + graph = f"{man} gives oral to {woman} while {woman}'s thighs are held open for the camera." + else: + graph = f"{woman} gives oral to {man} while {man} holds her hair and hips." elif "anal" in slug or "double" in slug: if "double" in item_text or "toy" in item_text: if people_count >= 3: @@ -1794,6 +1809,7 @@ def _build_custom_row( "expression": expression, "expression_intensity": expression_intensity, "composition": composition, + "composition_prompt": _composition_prompt(composition), "role_graph": role_graph, "positive_suffix": positive_suffix, "negative_prompt": negative_prompt,