Add expression intensity controls
This commit is contained in:
@@ -127,6 +127,11 @@ Options:
|
||||
- `softcore_level`: `social_tease`, `lingerie_tease`, `implied_nude`, or
|
||||
`explicit_tease`.
|
||||
- `hardcore_level`: `explicit` or `hardcore`.
|
||||
- `softcore_expression_intensity`: `0.0` is mild/controlled, `0.5` is sensual,
|
||||
`1.0` strongly favors more heated softcore faces.
|
||||
- `hardcore_expression_intensity`: `0.0` is controlled, `0.5` is balanced
|
||||
hardcore, `1.0` strongly favors ahegao-style, drooling, fucked-out, climax,
|
||||
and messy orgasm expressions.
|
||||
- `platform_style`: `hybrid`, `instagram`, or `onlyfans`.
|
||||
- `continuity`: `same_creator_same_room` keeps the scene/composition aligned;
|
||||
`same_creator_new_scene` keeps the same creator descriptor but lets the
|
||||
@@ -144,6 +149,11 @@ The node keeps the original generator controls:
|
||||
- `minimal_clothing_ratio`: `-1` disables mixing; `0.0` to `1.0` mixes minimal/full clothing.
|
||||
- `ethnicity`: `any`, `asian`, `white_asian`.
|
||||
- `poses`: `standard` or `evocative`.
|
||||
- `expression_intensity`: `0.0` favors mild, neutral, controlled expressions;
|
||||
`0.5` favors balanced category expressions; `1.0` strongly favors the most
|
||||
intense expressions available in the selected category. This affects custom
|
||||
JSON categories such as `Provocative erotic clothes` and `Hardcore sexual
|
||||
poses`.
|
||||
- `standard_pose_ratio`: `-1` disables mixing; `0.0` to `1.0` mixes standard/evocative poses.
|
||||
- `backside_bias`: `0.0` to `1.0`, applies to evocative single-subject poses.
|
||||
- `figure`: `curvy`, `balanced`, `bombshell`.
|
||||
@@ -210,22 +220,36 @@ provided, the node uses a generic composer that selects subject appearance,
|
||||
scene, pose, expression, composition, and a random item from the selected
|
||||
subcategory.
|
||||
|
||||
Reusable location banks can be defined with top-level `scene_pools` in any
|
||||
`categories/*.json` file. Categories, subcategories, and items can reference
|
||||
them with `scene_pools`; referenced pools are merged with any local `scenes`.
|
||||
This keeps location expansion scalable without duplicating the same bedroom,
|
||||
selfie, mirror, creator, or group-sex locations across every subcategory.
|
||||
Reusable banks can be defined with top-level `scene_pools`,
|
||||
`expression_pools`, and `composition_pools` in any `categories/*.json` file.
|
||||
Categories, subcategories, and items can reference them with `scene_pools`,
|
||||
`expression_pools`, and `composition_pools`; referenced pools are merged with
|
||||
any local `scenes`, `expressions`, or `compositions`. This keeps expansion
|
||||
scalable without duplicating the same bedroom, selfie, mirror, creator,
|
||||
expression, camera, or group-sex framing across every subcategory.
|
||||
|
||||
Set `"inherit_scenes": false` on a subcategory or item when it should use only
|
||||
its own `scenes` and `scene_pools` instead of also inheriting parent category
|
||||
locations. This is useful for narrow subcategories such as group scenes, vehicle
|
||||
sets, outdoor-only sets, or any category where a generic parent room would be a
|
||||
bad match.
|
||||
Set `"inherit_scenes": false`, `"inherit_expressions": false`, or
|
||||
`"inherit_compositions": false` on a subcategory or item when it should use only
|
||||
its own pools instead of also inheriting parent category values. This is useful
|
||||
for narrow subcategories such as group scenes, fetish sets, outdoor-only sets,
|
||||
or any category where generic parent wording would be a bad match.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"expression_pools": {
|
||||
"creator_tease_faces": [
|
||||
"direct creator-shot eye contact",
|
||||
"heavy-lidded bedroom gaze"
|
||||
]
|
||||
},
|
||||
"composition_pools": {
|
||||
"creator_selfie_frames": [
|
||||
"handheld selfie crop from face to hips",
|
||||
"mirror selfie with phone visible and body framed clearly"
|
||||
]
|
||||
},
|
||||
"scene_pools": {
|
||||
"creator_selfie_rooms": [
|
||||
{
|
||||
@@ -241,7 +265,11 @@ Example:
|
||||
{
|
||||
"name": "Selfie set",
|
||||
"inherit_scenes": false,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"scene_pools": ["creator_selfie_rooms"],
|
||||
"expression_pools": ["creator_tease_faces"],
|
||||
"composition_pools": ["creator_selfie_frames"],
|
||||
"items": ["simple outfit prompt"]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -57,6 +57,7 @@ class SxCPPromptBuilder:
|
||||
"clothing": (["full", "minimal"], {"default": "full"}),
|
||||
"ethnicity": (["any", "asian", "white_asian"], {"default": "any"}),
|
||||
"poses": (["standard", "evocative"], {"default": "standard"}),
|
||||
"expression_intensity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"backside_bias": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"figure": (["curvy", "balanced", "bombshell"], {"default": "curvy"}),
|
||||
"no_plus_women": ("BOOLEAN", {"default": False}),
|
||||
@@ -91,6 +92,7 @@ class SxCPPromptBuilder:
|
||||
clothing,
|
||||
ethnicity,
|
||||
poses,
|
||||
expression_intensity,
|
||||
backside_bias,
|
||||
figure,
|
||||
no_plus_women,
|
||||
@@ -115,6 +117,7 @@ class SxCPPromptBuilder:
|
||||
clothing=clothing,
|
||||
ethnicity=ethnicity,
|
||||
poses=poses,
|
||||
expression_intensity=expression_intensity,
|
||||
backside_bias=backside_bias,
|
||||
figure=figure,
|
||||
no_plus_women=no_plus_women,
|
||||
@@ -359,6 +362,8 @@ class SxCPInstaOFOptions:
|
||||
"hardcore_men_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
|
||||
"softcore_level": (["social_tease", "lingerie_tease", "implied_nude", "explicit_tease"], {"default": "lingerie_tease"}),
|
||||
"hardcore_level": (["explicit", "hardcore"], {"default": "hardcore"}),
|
||||
"softcore_expression_intensity": ("FLOAT", {"default": 0.45, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"hardcore_expression_intensity": ("FLOAT", {"default": 0.85, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"platform_style": (["hybrid", "instagram", "onlyfans"], {"default": "hybrid"}),
|
||||
"continuity": (["same_creator_same_room", "same_creator_new_scene"], {"default": "same_creator_same_room"}),
|
||||
"softcore_camera_mode": (camera_mode_choices(), {"default": "handheld_selfie"}),
|
||||
@@ -379,6 +384,8 @@ class SxCPInstaOFOptions:
|
||||
hardcore_men_count,
|
||||
softcore_level,
|
||||
hardcore_level,
|
||||
softcore_expression_intensity,
|
||||
hardcore_expression_intensity,
|
||||
platform_style,
|
||||
continuity,
|
||||
softcore_camera_mode,
|
||||
@@ -392,6 +399,8 @@ class SxCPInstaOFOptions:
|
||||
hardcore_men_count=hardcore_men_count,
|
||||
softcore_level=softcore_level,
|
||||
hardcore_level=hardcore_level,
|
||||
softcore_expression_intensity=softcore_expression_intensity,
|
||||
hardcore_expression_intensity=hardcore_expression_intensity,
|
||||
platform_style=platform_style,
|
||||
continuity=continuity,
|
||||
softcore_camera_mode=softcore_camera_mode,
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
"item_label": "Clothing",
|
||||
"style": "tasteful adult fashion-editorial coloured-pencil comic illustration with casual everyday styling",
|
||||
"positive_suffix": "Use crisp clean comic linework, soft fabric texture, detailed hatching, warm natural light, and tactile textured paper.",
|
||||
"expression_pools": ["casual_observational_expressions"],
|
||||
"composition_pools": ["casual_fashion_compositions"],
|
||||
"subcategories": [
|
||||
{
|
||||
"name": "Streetwear",
|
||||
"slug": "streetwear",
|
||||
"weight": 1.0,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"scene_pools": ["casual_urban_scenes"],
|
||||
"expression_pools": ["streetwear_attitude_expressions"],
|
||||
"composition_pools": ["streetwear_phone_compositions"],
|
||||
"items": ["streetwear outfit generator"],
|
||||
"item_templates": [
|
||||
"{outerwear} layered over {top}, with {bottom}, {footwear}, and {accessory}",
|
||||
@@ -169,7 +175,11 @@
|
||||
"name": "Summer casual",
|
||||
"slug": "summer_casual",
|
||||
"weight": 1.0,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"scene_pools": ["casual_summer_scenes"],
|
||||
"expression_pools": ["summer_candid_expressions"],
|
||||
"composition_pools": ["summer_lifestyle_compositions"],
|
||||
"items": ["summer casual outfit generator"],
|
||||
"item_templates": [
|
||||
"{dress} with {footwear}, {accessory}, and {fabric_detail}",
|
||||
@@ -342,7 +352,11 @@
|
||||
"name": "Cozy lounge",
|
||||
"slug": "cozy_lounge",
|
||||
"weight": 1.0,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"scene_pools": ["casual_lounge_scenes"],
|
||||
"expression_pools": ["cozy_lounge_expressions"],
|
||||
"composition_pools": ["cozy_home_compositions"],
|
||||
"items": ["cozy lounge outfit generator"],
|
||||
"item_templates": [
|
||||
"{layer} over {top}, with {bottom}, {footwear}, and {texture_detail}",
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"positive_suffix": "Use crisp clean comic linework, detailed hatching, soft skin shading, tactile fabric texture, warm intimate lighting, and textured paper.",
|
||||
"negative_prompt": "minors, childlike appearance, schoolgirl, childlike costume, non-consensual, coercion, violence, injury, watermark",
|
||||
"scene_pools": ["softcore_creator_scenes", "mirror_scenes"],
|
||||
"expression_pools": ["softcore_creator_expressions", "erotic_inviting_expressions"],
|
||||
"composition_pools": ["softcore_creator_compositions", "boudoir_body_compositions"],
|
||||
"expressions": [
|
||||
"heavy-lidded seductive gaze",
|
||||
"direct erotic stare",
|
||||
@@ -552,7 +554,11 @@
|
||||
"name": "Fetish inspired",
|
||||
"slug": "fetish_inspired",
|
||||
"weight": 1.0,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"scene_pools": ["fetish_studio_scenes"],
|
||||
"expression_pools": ["fetish_control_expressions"],
|
||||
"composition_pools": ["fetish_studio_compositions"],
|
||||
"item_templates": [
|
||||
"{color} {material} {latex_piece} with {zipper_detail}, {boot_style}, and {glove_style}",
|
||||
"{color} {harness_style} over {breast_exposure} with {bottom_detail}, {hardware}, and {shoe_style}",
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
{
|
||||
"version": 1,
|
||||
"expression_pools": {
|
||||
"casual_observational_expressions": [
|
||||
"neutral relaxed face with direct eye contact",
|
||||
"quiet focused gaze",
|
||||
"slightly aloof editorial stare",
|
||||
"calm unsmiling expression",
|
||||
"reserved half-smile",
|
||||
"thoughtful side glance",
|
||||
"candid mid-walk look",
|
||||
"subtle skeptical eyebrow raise",
|
||||
"composed fashion-model stare",
|
||||
"soft tired morning expression",
|
||||
"mildly distracted street-photo look",
|
||||
"relaxed closed-mouth smile"
|
||||
],
|
||||
"streetwear_attitude_expressions": [
|
||||
"cool unsmiling streetwear stare",
|
||||
"confident sideways glance",
|
||||
"detached outfit-check expression",
|
||||
"small knowing smirk",
|
||||
"phone-camera look with raised brow",
|
||||
"focused city-walk expression",
|
||||
"low-key bored fashion face",
|
||||
"direct lens stare under sunglasses",
|
||||
"casual closed-mouth grin",
|
||||
"serious model-off-duty expression"
|
||||
],
|
||||
"summer_candid_expressions": [
|
||||
"squinting softly in bright sun",
|
||||
"windblown candid smile",
|
||||
"relaxed vacation gaze",
|
||||
"half-lidded warm-weather expression",
|
||||
"calm look toward the horizon",
|
||||
"soft open-air market glance",
|
||||
"subtle smile while turning away",
|
||||
"sunlit thoughtful expression",
|
||||
"quiet contented look",
|
||||
"fresh-faced candid expression"
|
||||
],
|
||||
"cozy_lounge_expressions": [
|
||||
"sleepy relaxed expression",
|
||||
"quiet morning stare",
|
||||
"soft unfocused gaze",
|
||||
"warm but tired half-smile",
|
||||
"barely awake expression",
|
||||
"peaceful closed-mouth smile",
|
||||
"intimate home-camera gaze",
|
||||
"relaxed thoughtful look",
|
||||
"softly serious window-light expression",
|
||||
"calm private-moment face"
|
||||
],
|
||||
"softcore_creator_expressions": [
|
||||
"direct creator-shot eye contact",
|
||||
"heavy-lidded bedroom gaze",
|
||||
"teasing open-mouthed breath",
|
||||
"parted lips with flushed cheeks",
|
||||
"knowing subscriber-camera stare",
|
||||
"playful tongue touching the upper lip",
|
||||
"slow inviting half-smile",
|
||||
"soft aroused gaze",
|
||||
"confident mirror-selfie stare",
|
||||
"breathy expression with relaxed jaw",
|
||||
"shameless teasing grin",
|
||||
"dreamy post-tease expression",
|
||||
"subtle lip bite",
|
||||
"intense close-camera stare",
|
||||
"flushed skin and glossy eyes",
|
||||
"smirking phone-camera expression"
|
||||
],
|
||||
"erotic_inviting_expressions": [
|
||||
"wet parted lips and heavy-lidded eyes",
|
||||
"bold lustful eye contact",
|
||||
"open-mouthed sensual gasp",
|
||||
"slow predatory smile",
|
||||
"flushed cheeks with a shameless stare",
|
||||
"soft moaning expression without a sex act",
|
||||
"inviting gaze with relaxed mouth",
|
||||
"bedroom eyes and a teasing smirk",
|
||||
"dreamy aroused expression",
|
||||
"confident erotic glare",
|
||||
"mouth slightly open with glossy lips",
|
||||
"intimate close-lens stare",
|
||||
"playful tongue-out tease",
|
||||
"commanding sensual expression",
|
||||
"heated side glance",
|
||||
"after-dark seduction face"
|
||||
],
|
||||
"fetish_control_expressions": [
|
||||
"strict dominant stare",
|
||||
"cold confident gaze",
|
||||
"smirking control expression",
|
||||
"commanding eye contact",
|
||||
"calm predatory smile",
|
||||
"unblinking fetish-studio stare",
|
||||
"chin-raised confident expression",
|
||||
"sharp side-eye under dramatic light",
|
||||
"teasingly stern face",
|
||||
"intense latex-gloss stare",
|
||||
"detached dominant expression",
|
||||
"slow controlled smile"
|
||||
],
|
||||
"hardcore_orgasm_expressions": [
|
||||
"controlled intense eye contact during sex",
|
||||
"focused adult pleasure face",
|
||||
"bitten-lip near-orgasm expression",
|
||||
"steady flushed gaze with held breath",
|
||||
"adult ahegao-style crossed eyes with tongue out",
|
||||
"drooling open-mouthed orgasm face",
|
||||
"eyes rolled upward in climax",
|
||||
"tongue out with flushed cheeks",
|
||||
"overwhelmed orgasmic grimace",
|
||||
"wide open mouth mid-moan",
|
||||
"glassy unfocused climax stare",
|
||||
"sweaty breathless face with parted lips",
|
||||
"jaw slack from intense pleasure",
|
||||
"eyes squeezed shut during orgasm",
|
||||
"wild aroused expression with messy hair",
|
||||
"near-climax trembling lips",
|
||||
"desperate open-mouth pleasure face",
|
||||
"flushed face with saliva at the lips",
|
||||
"shameless fucked-out expression",
|
||||
"dazed post-orgasm stare",
|
||||
"heavy-lidded exhausted pleasure face",
|
||||
"raw orgasmic face with wet lips"
|
||||
],
|
||||
"hardcore_messy_expressions": [
|
||||
"controlled sweaty eye contact",
|
||||
"focused heavy-breathing expression",
|
||||
"bitten-lip messy pleasure face",
|
||||
"steady post-sex stare",
|
||||
"messy drooling pleasure expression",
|
||||
"cum-smeared lips with dazed eye contact",
|
||||
"saliva-shiny tongue-out expression",
|
||||
"sweaty flushed face and open mouth",
|
||||
"mascara-smudged adult climax face",
|
||||
"fucked-out stare with slack jaw",
|
||||
"wild tongue-out expression",
|
||||
"wet lips and unfocused eyes",
|
||||
"breathless panting expression",
|
||||
"overheated flushed cheeks",
|
||||
"messy post-climax grin",
|
||||
"shaking near-orgasm expression",
|
||||
"glossy eyes and parted lips",
|
||||
"drool at the corner of the mouth",
|
||||
"intense shameless eye contact",
|
||||
"spent satisfied expression"
|
||||
],
|
||||
"hardcore_penetration_expressions": [
|
||||
"controlled eye contact during penetration",
|
||||
"focused adult pleasure face during thrusting",
|
||||
"bitten-lip concentration under penetration",
|
||||
"braced expression with held breath",
|
||||
"open-mouthed moan during penetration",
|
||||
"eyes rolled back from deep penetration",
|
||||
"bitten-lip expression under hard thrusting",
|
||||
"desperate eye contact during penetration",
|
||||
"jaw slack from deep thrusts",
|
||||
"flushed face with a strained moan",
|
||||
"adult ahegao-style penetration face",
|
||||
"breathless grimace from intense pressure",
|
||||
"fucked-out gaze while hips are pinned",
|
||||
"tongue out during hard penetration",
|
||||
"sweaty orgasm-building expression",
|
||||
"eyes squeezed shut as penetration deepens",
|
||||
"wild pleasure face during thrusting",
|
||||
"near-climax pleading stare"
|
||||
],
|
||||
"hardcore_oral_expressions": [
|
||||
"focused eye contact during oral sex",
|
||||
"controlled oral-sex expression",
|
||||
"steady gaze while mouth is close to genitals",
|
||||
"bitten-lip anticipation before oral contact",
|
||||
"wet open-mouth oral expression",
|
||||
"drooling tongue-out oral face",
|
||||
"glossy eyes while mouth is occupied",
|
||||
"messy lips during oral sex",
|
||||
"gagging-but-consensual adult oral expression",
|
||||
"hungry eye contact during oral sex",
|
||||
"saliva strings at the lips",
|
||||
"sex-drunk dazed expression",
|
||||
"tongue extended toward genitals",
|
||||
"cum-smeared mouth and heavy-lidded eyes",
|
||||
"breathless oral-sex face",
|
||||
"wide open mouth ready for oral contact",
|
||||
"wet lips pressed around a partner",
|
||||
"shameless oral-service stare"
|
||||
],
|
||||
"hardcore_anal_dp_expressions": [
|
||||
"controlled braced expression during anal sex",
|
||||
"focused eye contact while hips are held open",
|
||||
"bitten-lip pressure expression",
|
||||
"steady concentrated pleasure face",
|
||||
"overwhelmed face during anal penetration",
|
||||
"eyes rolled back from double penetration",
|
||||
"strained open-mouthed pleasure expression",
|
||||
"adult ahegao-style double-penetration face",
|
||||
"fucked-out expression between two partners",
|
||||
"breathless face under intense pressure",
|
||||
"tongue out with flushed cheeks",
|
||||
"near-orgasm grimace during anal sex",
|
||||
"wide-eyed pleasure shock",
|
||||
"sweaty clenched-jaw moan",
|
||||
"dazed expression while hips are held open",
|
||||
"desperate heavy-lidded stare",
|
||||
"open mouth and trembling lips",
|
||||
"messy post-anal climax face"
|
||||
],
|
||||
"hardcore_group_expressions": [
|
||||
"controlled aroused expressions across the group",
|
||||
"focused eye contact between several partners",
|
||||
"steady concentrated pleasure faces",
|
||||
"bitten-lip group-sex expressions",
|
||||
"multiple adults with open-mouthed orgasm faces",
|
||||
"mixed dazed and hungry faces across the group",
|
||||
"several tongue-out ahegao-style adult expressions",
|
||||
"flushed sweaty faces around the pile",
|
||||
"one partner drooling while others moan",
|
||||
"overwhelmed group-sex expressions",
|
||||
"fucked-out faces across several bodies",
|
||||
"heavy-lidded eye contact between partners",
|
||||
"wild orgasmic faces in the group",
|
||||
"messy saliva-shiny mouths across the scene",
|
||||
"shameless aroused grins and moans",
|
||||
"near-climax expressions on multiple adults",
|
||||
"spent post-orgy faces",
|
||||
"open mouths and glossy eyes across the group",
|
||||
"dazed pleasure expressions from every visible adult",
|
||||
"heated direct eye contact between participants"
|
||||
],
|
||||
"hardcore_climax_expressions": [
|
||||
"controlled post-climax stare",
|
||||
"focused breathless aftermath expression",
|
||||
"bitten-lip satisfied expression",
|
||||
"steady flushed face after orgasm",
|
||||
"eyes rolled back during climax",
|
||||
"mouth open as orgasm hits",
|
||||
"cum-smeared dazed expression",
|
||||
"tongue out with visible post-climax mess",
|
||||
"breathless post-orgasm stare",
|
||||
"spent fucked-out face",
|
||||
"shaking orgasm expression",
|
||||
"wet lips and flushed cheeks after climax",
|
||||
"heavy-lidded satisfied stare",
|
||||
"dazed expression under phone flash",
|
||||
"open-mouthed post-climax panting",
|
||||
"messy satisfied grin",
|
||||
"adult ahegao-style climax face",
|
||||
"glassy eyes and slack jaw after release"
|
||||
]
|
||||
},
|
||||
"composition_pools": {
|
||||
"casual_fashion_compositions": [
|
||||
"vertical outfit-check composition with the full silhouette readable",
|
||||
"three-quarter fashion crop with face, outfit, and shoes visible",
|
||||
"street-style editorial frame with environmental context",
|
||||
"candid phone-photo composition with natural body spacing",
|
||||
"mirror outfit-check view with the room visible",
|
||||
"full-body standing frame with no cropped shoes",
|
||||
"mid-distance lifestyle frame with relaxed negative space",
|
||||
"clean fashion catalog composition",
|
||||
"slightly low phone angle emphasizing outfit shape",
|
||||
"waist-up crop focused on layering and accessories",
|
||||
"over-the-shoulder fashion pose with background context",
|
||||
"side-profile frame showing the outfit silhouette"
|
||||
],
|
||||
"streetwear_phone_compositions": [
|
||||
"low-angle streetwear phone shot with sneakers near the foreground",
|
||||
"mirror elevator outfit-check composition",
|
||||
"crosswalk mid-step vertical frame",
|
||||
"wall-leaning full-body street portrait",
|
||||
"storefront reflection composition",
|
||||
"wide sidewalk frame with city lines behind the body",
|
||||
"seated curb-level streetwear pose",
|
||||
"phone-snapshot crop from head to shoes",
|
||||
"three-quarter frame emphasizing jacket layers",
|
||||
"rear three-quarter streetwear turn"
|
||||
],
|
||||
"summer_lifestyle_compositions": [
|
||||
"sunlit full-body summer lifestyle frame",
|
||||
"promenade walking shot with fabric movement",
|
||||
"market-stall candid composition",
|
||||
"seated low-wall frame with legs and sandals visible",
|
||||
"balcony outfit-check with plants and skyline",
|
||||
"bright high-angle phone photo",
|
||||
"soft side-profile summer silhouette",
|
||||
"beach-cafe seated composition",
|
||||
"wide resort-day frame with clear warm light",
|
||||
"close crop on face, neckline, and fabric texture"
|
||||
],
|
||||
"cozy_home_compositions": [
|
||||
"soft window-light home portrait",
|
||||
"sofa-corner seated vertical frame",
|
||||
"bedroom-floor lounge composition",
|
||||
"mirror view showing cozy layers and room context",
|
||||
"kneeling rug-level composition",
|
||||
"waist-up intimate home-camera crop",
|
||||
"full-body barefoot frame near curtains",
|
||||
"reading-nook composition with relaxed negative space",
|
||||
"overhead sofa composition",
|
||||
"side-profile lounge silhouette"
|
||||
],
|
||||
"softcore_creator_compositions": [
|
||||
"handheld selfie crop from face to hips",
|
||||
"mirror selfie with phone visible and body framed clearly",
|
||||
"phone-tripod vertical creator frame",
|
||||
"bed selfie with sheets around the body",
|
||||
"bathroom mirror crop with phone and torso visible",
|
||||
"close subscriber-view crop from thighs to face",
|
||||
"ring-light creator setup with full body visible",
|
||||
"over-the-shoulder mirror view",
|
||||
"kneeling bed-frame creator composition",
|
||||
"side-profile body curve composition",
|
||||
"low-angle phone shot emphasizing legs and hips",
|
||||
"full-body lingerie outfit-check frame",
|
||||
"tight crop on face, chest, hands, and fabric",
|
||||
"vertical story-frame creator shot"
|
||||
],
|
||||
"boudoir_body_compositions": [
|
||||
"reclining boudoir full-body composition",
|
||||
"arched-back side-profile lingerie frame",
|
||||
"mirror-view bedroom composition",
|
||||
"kneeling bed composition with face and torso visible",
|
||||
"standing center-frame boudoir poster crop",
|
||||
"seated legs-forward lingerie frame",
|
||||
"close crop on lace, skin, and facial expression",
|
||||
"over-the-shoulder rear-view boudoir frame",
|
||||
"bed-edge full-body composition",
|
||||
"soft overhead bed composition",
|
||||
"low-angle glamour frame emphasizing hips and thighs",
|
||||
"three-quarter body editorial lingerie pose"
|
||||
],
|
||||
"fetish_studio_compositions": [
|
||||
"low-angle fetish-studio dominance frame",
|
||||
"centered full-body latex poster composition",
|
||||
"mirror-wall fetish composition with hard rim light",
|
||||
"kneeling front-facing studio frame",
|
||||
"standing wide-leg dominance composition",
|
||||
"close crop on harness, expression, and hands",
|
||||
"rear three-quarter fetish silhouette",
|
||||
"glossy floor reflection composition",
|
||||
"symmetrical private-studio frame",
|
||||
"side-profile body-line composition",
|
||||
"dramatic overhead studio crop",
|
||||
"tight vertical frame with props and body centered"
|
||||
],
|
||||
"hardcore_explicit_compositions": [
|
||||
{"text": "full-body explicit sex frame with all adult bodies visible", "min_people": 2},
|
||||
{"text": "bed-level camera angle focused on genital contact and faces", "min_people": 2, "max_people": 3},
|
||||
{"text": "side-profile view showing penetration alignment clearly", "min_people": 2, "max_people": 3},
|
||||
{"text": "mirror-reflected explicit sex composition with direct and reflected views", "min_people": 2, "max_people": 3},
|
||||
{"text": "overhead view of intertwined adult bodies", "min_people": 2},
|
||||
{"text": "low-angle explicit body-contact frame", "min_people": 2},
|
||||
{"text": "close crop on hips, thighs, hands, genitals, and faces", "min_people": 2, "max_people": 3},
|
||||
{"text": "wide full-body explicit composition with readable anatomy", "min_people": 2},
|
||||
{"text": "creator-shot vertical frame with phone-camera intimacy", "min_people": 2},
|
||||
{"text": "front-facing explicit frame with body contact centered", "min_people": 2},
|
||||
{"text": "floor-level sex composition with sheets and bodies filling the frame", "min_people": 2},
|
||||
{"text": "tight subscriber-view crop with face and explicit contact visible", "min_people": 2, "max_people": 3}
|
||||
],
|
||||
"penetration_compositions": [
|
||||
{"text": "low-angle penetration view with hips near the camera", "min_people": 2, "max_people": 3},
|
||||
{"text": "side-profile penetration frame with genital contact readable", "min_people": 2, "max_people": 3},
|
||||
{"text": "bed-edge explicit penetration composition", "min_people": 2, "max_people": 3},
|
||||
{"text": "overhead penetration frame with legs and hips visible", "min_people": 2, "max_people": 3},
|
||||
{"text": "mirror-reflected penetration view", "min_people": 2, "max_people": 3},
|
||||
{"text": "close crop on penetration, hands, and orgasmic face", "min_people": 2, "max_people": 3},
|
||||
{"text": "wide full-body penetration frame", "min_people": 2, "max_people": 3},
|
||||
{"text": "rear three-quarter penetration composition", "min_people": 2, "max_people": 3},
|
||||
{"text": "kneeling penetration frame with bodies stacked vertically", "min_people": 2, "max_people": 3},
|
||||
{"text": "front-facing explicit thrusting composition", "min_people": 2, "max_people": 3}
|
||||
],
|
||||
"oral_compositions": [
|
||||
{"text": "mouth-level oral-sex close-up with eyes and hands visible", "min_people": 2, "max_people": 3},
|
||||
{"text": "kneeling oral composition with genitals and face centered", "min_people": 2, "max_people": 3},
|
||||
{"text": "front-view oral-sex frame from bed height", "min_people": 2, "max_people": 3},
|
||||
{"text": "low phone-camera angle focused on mouth contact", "min_people": 2, "max_people": 3},
|
||||
{"text": "mirror-reflected oral scene with face and body visible", "min_people": 2, "max_people": 3},
|
||||
{"text": "overhead oral-sex frame with thighs and mouth contact readable", "min_people": 2, "max_people": 3},
|
||||
{"text": "side-profile oral composition with saliva and expression visible", "min_people": 2, "max_people": 3},
|
||||
{"text": "tight crop on mouth, hands, genitals, and eyes", "min_people": 2, "max_people": 3},
|
||||
{"text": "wide full-body oral-sex composition", "min_people": 2, "max_people": 3},
|
||||
{"text": "bedside kneeling oral frame with phone-shot intimacy", "min_people": 2, "max_people": 3}
|
||||
],
|
||||
"anal_dp_compositions": [
|
||||
{"text": "rear-view anal composition with hips and face visible", "min_people": 2, "max_people": 3},
|
||||
{"text": "side-profile anal penetration frame", "min_people": 2, "max_people": 3},
|
||||
{"text": "front-and-back double-penetration composition", "min_people": 3},
|
||||
{"text": "mirror-reflected double-penetration view", "min_people": 3},
|
||||
{"text": "low-angle bent-over explicit frame", "min_people": 2, "max_people": 3},
|
||||
{"text": "bed-edge rear-entry composition", "min_people": 2, "max_people": 3},
|
||||
{"text": "close crop on hips, hands, and overwhelmed face", "min_people": 2, "max_people": 3},
|
||||
{"text": "wide frame with all penetration points visible", "min_people": 3},
|
||||
{"text": "kneeling double-contact composition", "min_people": 3},
|
||||
{"text": "overhead tangled-body anal frame", "min_people": 2, "max_people": 3}
|
||||
],
|
||||
"threesome_compositions": [
|
||||
{"text": "centered threesome composition with all three adult bodies visible", "min_people": 3, "max_people": 3},
|
||||
{"text": "front-and-back threesome frame", "min_people": 3, "max_people": 3},
|
||||
{"text": "overhead three-body composition", "min_people": 3, "max_people": 3},
|
||||
{"text": "wide bed threesome frame with faces and genitals visible", "min_people": 3, "max_people": 3},
|
||||
{"text": "mirror-wall threesome composition", "min_people": 3, "max_people": 3},
|
||||
{"text": "low mattress three-person frame", "min_people": 3, "max_people": 3},
|
||||
{"text": "side-profile threesome alignment view", "min_people": 3, "max_people": 3},
|
||||
{"text": "tight center-body crop with both partners visible", "min_people": 3, "max_people": 3},
|
||||
{"text": "floor-level three-body explicit frame", "min_people": 3, "max_people": 3},
|
||||
{"text": "standing and kneeling threesome composition", "min_people": 3, "max_people": 3}
|
||||
],
|
||||
"group_sex_compositions": [
|
||||
{"text": "wide orgy composition with every visible adult body readable", "min_people": 4},
|
||||
{"text": "overhead group-sex frame with bodies arranged in layers", "min_people": 4},
|
||||
{"text": "floor-level group pile with multiple acts visible", "min_people": 4},
|
||||
{"text": "wide mirror-wall group-sex composition", "min_people": 4},
|
||||
{"text": "multi-couch group scene with all participants in frame", "min_people": 4},
|
||||
{"text": "centered group pile with penetration and oral contact visible", "min_people": 4},
|
||||
{"text": "wide private-suite orgy frame with readable body positions", "min_people": 4},
|
||||
{"text": "high-angle group-sex composition showing the whole arrangement", "min_people": 4},
|
||||
{"text": "long vertical creator-shot group frame", "min_people": 4},
|
||||
{"text": "full-room group-sex composition with clear adult spacing", "min_people": 4}
|
||||
],
|
||||
"climax_compositions": [
|
||||
{"text": "tight post-climax crop on face, body, hands, and visible fluids", "min_people": 1},
|
||||
{"text": "phone-flash close-up of orgasm aftermath", "min_people": 1},
|
||||
{"text": "bed-level climax frame with thighs, face, and fluid detail visible", "min_people": 1},
|
||||
{"text": "mirror-reflected post-climax composition", "min_people": 1},
|
||||
{"text": "front-facing cumshot composition with body and expression centered", "min_people": 1},
|
||||
{"text": "overhead post-orgasm frame on rumpled sheets", "min_people": 1},
|
||||
{"text": "kneeling climax frame with open mouth and body visible", "min_people": 1},
|
||||
{"text": "wide aftermath composition with all adult bodies visible", "min_people": 2},
|
||||
{"text": "tight subscriber-view crop of climax expression and fluid detail", "min_people": 1},
|
||||
{"text": "side-profile post-climax body-line composition", "min_people": 1}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -11,39 +11,43 @@
|
||||
"positive_suffix": "Use clear adult anatomy, visible sexual contact, intense body language, crisp comic linework, detailed hatching, warm erotic lighting, and tactile textured paper.",
|
||||
"negative_prompt": "minors, childlike appearance, teen, schoolgirl, incest, bestiality, non-consensual, coercion, rape, violence, injury, blood, gore, watermark",
|
||||
"scene_pools": ["hardcore_private_scenes"],
|
||||
"expression_pools": ["hardcore_orgasm_expressions", "hardcore_messy_expressions"],
|
||||
"composition_pools": ["hardcore_explicit_compositions"],
|
||||
"prompt_template": "{subject_phrase}, all 21+ consenting adults: {style}. Cast: {cast_summary}. Role graph: {role_graph} Sexual pose: {item}. Setting: {scene}. Composition: {composition}. Facial expressions: {expression}. Make the scene explicit, hardcore, and anatomically clear, with visible genital contact and adult bodies only. {positive_suffix} Avoid: {negative_prompt}.",
|
||||
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, {item}, {scene}, {composition}, explicit consensual adult hardcore sex illustration",
|
||||
"expressions": [
|
||||
"open-mouthed orgasmic expression",
|
||||
"heavy-lidded lustful gaze",
|
||||
"flushed faces and parted lips",
|
||||
"intense eye contact during sex",
|
||||
"breathless pleasure expression",
|
||||
"commanding erotic stare",
|
||||
"shameless aroused grin",
|
||||
"eyes closed in climax",
|
||||
"teasing dominant smile",
|
||||
"desperate hungry gaze",
|
||||
"sweaty post-orgasmic glow",
|
||||
"bitten-lip pleasure expression",
|
||||
"wild aroused expression",
|
||||
"soft moaning expression",
|
||||
"focused intimate eye contact",
|
||||
"overwhelmed climax expression"
|
||||
"adult ahegao-style orgasm face",
|
||||
"eyes rolled back with tongue out",
|
||||
"drooling open-mouthed moan",
|
||||
"fucked-out dazed stare",
|
||||
"sweaty flushed orgasm expression",
|
||||
"jaw slack from intense pleasure",
|
||||
"messy saliva-shiny lips",
|
||||
"desperate near-climax gaze",
|
||||
"wild tongue-out arousal",
|
||||
"breathless post-orgasm face",
|
||||
"cum-smeared lips and glossy eyes",
|
||||
"open mouth and trembling lips",
|
||||
"heavy-lidded exhausted pleasure stare",
|
||||
"raw overwhelmed climax expression",
|
||||
"shameless messy aroused grin",
|
||||
"eyes squeezed shut during orgasm",
|
||||
"dazed sex-drunk expression",
|
||||
"heated direct eye contact during sex"
|
||||
],
|
||||
"compositions": [
|
||||
"full-body bed scene with all bodies visible",
|
||||
"low-angle explicit penetration view",
|
||||
"overhead view of intertwined bodies",
|
||||
"side-profile view showing genital contact",
|
||||
"mirror-view sex composition",
|
||||
"close crop on hips, thighs, and faces",
|
||||
"wide orgy composition with all participants visible",
|
||||
"centered threesome composition",
|
||||
"kneeling and standing composition",
|
||||
"reclining full-body composition",
|
||||
"full-body explicit sex frame with all adult bodies visible",
|
||||
"low-angle view focused on genital contact",
|
||||
"overhead view of intertwined adult bodies",
|
||||
"side-profile view showing penetration alignment",
|
||||
"mirror-view explicit sex composition",
|
||||
"close crop on hips, thighs, hands, genitals, and faces",
|
||||
"wide group-sex composition with all participants visible",
|
||||
"centered threesome composition with all three bodies readable",
|
||||
"kneeling and standing explicit body-contact frame",
|
||||
"reclining full-body sex composition",
|
||||
"floor-level explicit sex composition",
|
||||
"front-facing explicit pin-up composition"
|
||||
"front-facing hardcore creator-shot composition"
|
||||
],
|
||||
"scenes": [
|
||||
{
|
||||
@@ -84,8 +88,12 @@
|
||||
"name": "Penetrative sex",
|
||||
"slug": "penetrative_sex",
|
||||
"min_people": 2,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_penetrative_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||
"expression_pools": ["hardcore_penetration_expressions"],
|
||||
"composition_pools": ["penetration_compositions"],
|
||||
"item_templates": [
|
||||
"{penetration_act} in {position}, with {body_contact}, {intensity}, and {visibility}",
|
||||
"{position} while {penetration_act}, {hand_detail}, {mouth_detail}, and {visibility}",
|
||||
@@ -249,8 +257,12 @@
|
||||
"name": "Oral sex",
|
||||
"slug": "oral_sex",
|
||||
"min_people": 2,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_oral_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||
"expression_pools": ["hardcore_oral_expressions"],
|
||||
"composition_pools": ["oral_compositions"],
|
||||
"item_templates": [
|
||||
"{oral_act} in {position}, with {hand_detail}, {expression_detail}, and {visibility}",
|
||||
"{position} featuring {oral_act}, {body_contact}, {saliva_detail}, and {climax_hint}",
|
||||
@@ -382,8 +394,12 @@
|
||||
"name": "Anal and double penetration",
|
||||
"slug": "anal_double_penetration",
|
||||
"min_people": 2,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_anal_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||
"expression_pools": ["hardcore_anal_dp_expressions"],
|
||||
"composition_pools": ["anal_dp_compositions"],
|
||||
"item_templates": [
|
||||
"{anal_act} in {position}, with {leg_detail}, {hand_detail}, and {visibility}",
|
||||
"{double_act} with {body_arrangement}, {intensity}, {mouth_detail}, and {visibility}",
|
||||
@@ -587,8 +603,12 @@
|
||||
"name": "Threesomes",
|
||||
"slug": "threesomes",
|
||||
"min_people": 3,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_threesome_scenes", "hardcore_group_scenes", "hardcore_mirror_scenes"],
|
||||
"expression_pools": ["hardcore_group_expressions"],
|
||||
"composition_pools": ["threesome_compositions"],
|
||||
"item_templates": [
|
||||
"{threesome_act} with {body_arrangement}, {oral_detail}, {penetration_detail}, and {visibility}",
|
||||
"{body_arrangement} while {threesome_act}, with {hand_detail}, {mouth_detail}, and {climax_hint}",
|
||||
@@ -766,8 +786,12 @@
|
||||
"slug": "group_sex_orgy",
|
||||
"min_people": 4,
|
||||
"inherit_scenes": false,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_group_scenes"],
|
||||
"expression_pools": ["hardcore_group_expressions"],
|
||||
"composition_pools": ["group_sex_compositions"],
|
||||
"item_templates": [
|
||||
"{group_act} with {arrangement}, {contact_detail}, {fluid_detail}, and {visibility}",
|
||||
"{arrangement} featuring {group_act}, {oral_detail}, {penetration_detail}, and {intensity}",
|
||||
@@ -934,8 +958,12 @@
|
||||
"name": "Cumshot and climax",
|
||||
"slug": "cumshot_climax",
|
||||
"min_people": 1,
|
||||
"inherit_expressions": false,
|
||||
"inherit_compositions": false,
|
||||
"weight": 1.0,
|
||||
"scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||
"expression_pools": ["hardcore_climax_expressions"],
|
||||
"composition_pools": ["climax_compositions"],
|
||||
"item_templates": [
|
||||
"{climax_act} with {fluid_location}, {body_position}, {expression_detail}, and {visibility}",
|
||||
"{body_position} during {climax_act}, with {hand_detail}, {fluid_location}, and {fluid_detail}",
|
||||
|
||||
+235
-9
@@ -562,15 +562,15 @@ def load_category_library() -> list[dict[str, Any]]:
|
||||
return categories
|
||||
|
||||
|
||||
def load_scene_pool_library() -> dict[str, list[Any]]:
|
||||
def _load_named_pool_library(key: str) -> dict[str, list[Any]]:
|
||||
pools: dict[str, list[Any]] = {}
|
||||
for path in _json_files():
|
||||
data = _read_json(path)
|
||||
raw_pools = data.get("scene_pools", {})
|
||||
raw_pools = data.get(key, {})
|
||||
if not raw_pools:
|
||||
continue
|
||||
if not isinstance(raw_pools, dict):
|
||||
raise ValueError(f"scene_pools in {path} must be an object")
|
||||
raise ValueError(f"{key} in {path} must be an object")
|
||||
for name, entries in raw_pools.items():
|
||||
pool_name = str(name).strip()
|
||||
if not pool_name:
|
||||
@@ -580,6 +580,18 @@ def load_scene_pool_library() -> dict[str, list[Any]]:
|
||||
return pools
|
||||
|
||||
|
||||
def load_scene_pool_library() -> dict[str, list[Any]]:
|
||||
return _load_named_pool_library("scene_pools")
|
||||
|
||||
|
||||
def load_expression_pool_library() -> dict[str, list[Any]]:
|
||||
return _load_named_pool_library("expression_pools")
|
||||
|
||||
|
||||
def load_composition_pool_library() -> dict[str, list[Any]]:
|
||||
return _load_named_pool_library("composition_pools")
|
||||
|
||||
|
||||
def _extension_targets() -> dict[str, tuple[list[Any], bool]]:
|
||||
return {
|
||||
"women_clothes": (g.WOMEN_CLOTHES, False),
|
||||
@@ -654,6 +666,14 @@ def _ratio_or_none(value: float) -> float | None:
|
||||
return max(0.0, min(1.0, ratio))
|
||||
|
||||
|
||||
def _clamped_float(value: Any, default: float = 0.5, min_value: float = 0.0, max_value: float = 1.0) -> float:
|
||||
try:
|
||||
number = float(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return max(min_value, min(max_value, number))
|
||||
|
||||
|
||||
def build_seed_config_json(
|
||||
category_seed: int = -1,
|
||||
subcategory_seed: int = -1,
|
||||
@@ -1384,6 +1404,180 @@ def _scene_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any
|
||||
return scene_entries or fallback
|
||||
|
||||
|
||||
def _sources_with_inheritance(
|
||||
category: dict[str, Any],
|
||||
subcategory: dict[str, Any],
|
||||
item: Any,
|
||||
inherit_key: str,
|
||||
) -> tuple[Any, ...]:
|
||||
item_source = item if isinstance(item, dict) else None
|
||||
if item_source is not None and _is_false(item_source.get(inherit_key)):
|
||||
return (item_source,)
|
||||
if _is_false(subcategory.get(inherit_key)):
|
||||
return (subcategory, item_source)
|
||||
return (category, subcategory, item_source)
|
||||
|
||||
|
||||
def _configured_pool(
|
||||
category: dict[str, Any],
|
||||
subcategory: dict[str, Any],
|
||||
item: Any,
|
||||
direct_key: str,
|
||||
pool_key: str,
|
||||
pool_library: dict[str, list[Any]],
|
||||
inherit_key: str,
|
||||
) -> list[Any]:
|
||||
entries: list[Any] = []
|
||||
singular_pool_key = pool_key[:-1] if pool_key.endswith("s") else pool_key
|
||||
for source in _sources_with_inheritance(category, subcategory, item, inherit_key):
|
||||
if not isinstance(source, dict):
|
||||
continue
|
||||
if direct_key in source:
|
||||
_unique_extend(entries, _list_from(source[direct_key]))
|
||||
refs = _list_from(source.get(singular_pool_key)) + _list_from(source.get(pool_key))
|
||||
for ref in refs:
|
||||
ref_name = str(ref).strip()
|
||||
if ref_name not in pool_library:
|
||||
raise ValueError(f"Unknown {singular_pool_key} '{ref_name}'")
|
||||
_unique_extend(entries, pool_library[ref_name])
|
||||
return entries
|
||||
|
||||
|
||||
def _expression_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any) -> list[Any]:
|
||||
return _configured_pool(
|
||||
category,
|
||||
subcategory,
|
||||
item,
|
||||
"expressions",
|
||||
"expression_pools",
|
||||
load_expression_pool_library(),
|
||||
"inherit_expressions",
|
||||
) or g.EXPRESSIONS
|
||||
|
||||
|
||||
def _expression_intensity_hint(entry: Any) -> float:
|
||||
if isinstance(entry, dict):
|
||||
for key in ("expression_intensity", "intensity"):
|
||||
if key in entry:
|
||||
return _clamped_float(entry[key], 0.5)
|
||||
|
||||
text = _entry_text(entry).lower()
|
||||
high_terms = (
|
||||
"ahegao",
|
||||
"orgasm",
|
||||
"climax",
|
||||
"drool",
|
||||
"drooling",
|
||||
"tongue out",
|
||||
"eyes rolled",
|
||||
"fucked-out",
|
||||
"cum-smeared",
|
||||
"saliva",
|
||||
"gagging",
|
||||
"slack jaw",
|
||||
"jaw slack",
|
||||
"slack-jawed",
|
||||
"sex-drunk",
|
||||
"overwhelmed",
|
||||
"strained",
|
||||
"messy",
|
||||
"panting",
|
||||
"trembling",
|
||||
"shaking",
|
||||
"wide open mouth",
|
||||
"raw ",
|
||||
"wild ",
|
||||
"dazed",
|
||||
"spent",
|
||||
)
|
||||
if any(term in text for term in high_terms):
|
||||
return 0.9
|
||||
|
||||
medium_terms = (
|
||||
"seductive",
|
||||
"teasing",
|
||||
"lustful",
|
||||
"aroused",
|
||||
"bedroom",
|
||||
"dominant",
|
||||
"predatory",
|
||||
"control",
|
||||
"stern",
|
||||
"strict",
|
||||
"smirk",
|
||||
"parted lips",
|
||||
"open-mouthed",
|
||||
"heated",
|
||||
"hungry",
|
||||
"inviting",
|
||||
"sensual",
|
||||
"fetish",
|
||||
"commanding",
|
||||
"flushed",
|
||||
"moan",
|
||||
)
|
||||
if any(term in text for term in medium_terms):
|
||||
return 0.62
|
||||
|
||||
low_terms = (
|
||||
"neutral",
|
||||
"quiet",
|
||||
"calm",
|
||||
"reserved",
|
||||
"relaxed",
|
||||
"candid",
|
||||
"closed-mouth",
|
||||
"thoughtful",
|
||||
"controlled",
|
||||
"focused",
|
||||
"steady",
|
||||
"bitten-lip",
|
||||
"braced",
|
||||
"held breath",
|
||||
"concentrated",
|
||||
"aloof",
|
||||
"bored",
|
||||
"tired",
|
||||
"unfocused",
|
||||
"contented",
|
||||
"fashion",
|
||||
"soft",
|
||||
"sleepy",
|
||||
"fresh-faced",
|
||||
)
|
||||
if any(term in text for term in low_terms):
|
||||
return 0.25
|
||||
return 0.5
|
||||
|
||||
|
||||
def _expression_entries_for_intensity(entries: list[Any], expression_intensity: float) -> list[Any]:
|
||||
target = _clamped_float(expression_intensity, 0.5)
|
||||
weighted: list[Any] = []
|
||||
for entry in entries:
|
||||
entry_intensity = _expression_intensity_hint(entry)
|
||||
distance = abs(target - entry_intensity)
|
||||
if distance <= 0.18:
|
||||
intensity_weight = 4.0
|
||||
elif distance <= 0.35:
|
||||
intensity_weight = 1.4
|
||||
elif distance <= 0.55:
|
||||
intensity_weight = 0.35
|
||||
else:
|
||||
intensity_weight = 0.05
|
||||
|
||||
if isinstance(entry, dict):
|
||||
adjusted = dict(entry)
|
||||
try:
|
||||
base_weight = float(adjusted.get("weight", 1.0))
|
||||
except (TypeError, ValueError):
|
||||
base_weight = 1.0
|
||||
adjusted["weight"] = max(0.0, base_weight) * intensity_weight
|
||||
weighted.append(adjusted)
|
||||
else:
|
||||
weighted.append({"text": _entry_text(entry), "weight": intensity_weight})
|
||||
return weighted or entries
|
||||
|
||||
|
||||
def _pose_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str, poses: str) -> list[Any]:
|
||||
configured = _merged_field(category, subcategory, item, "poses")
|
||||
if configured:
|
||||
@@ -1396,9 +1590,17 @@ def _pose_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any,
|
||||
|
||||
|
||||
def _composition_pool(category: dict[str, Any], subcategory: dict[str, Any], item: Any, subject_type: str) -> list[Any]:
|
||||
configured = _merged_field(category, subcategory, item, "compositions")
|
||||
configured = _configured_pool(
|
||||
category,
|
||||
subcategory,
|
||||
item,
|
||||
"compositions",
|
||||
"composition_pools",
|
||||
load_composition_pool_library(),
|
||||
"inherit_compositions",
|
||||
)
|
||||
if configured:
|
||||
return _list_from(configured)
|
||||
return configured
|
||||
if subject_type in ("group", "configured_cast"):
|
||||
return g.GROUP_COMPOSITIONS
|
||||
if subject_type in ("layout", "scene"):
|
||||
@@ -1420,6 +1622,7 @@ def _build_custom_row(
|
||||
men_count: int,
|
||||
seed: int,
|
||||
seed_config: dict[str, int],
|
||||
expression_intensity: float,
|
||||
) -> dict[str, Any]:
|
||||
categories = load_category_library()
|
||||
category_rng = _axis_rng(seed_config, "category", seed, row_number)
|
||||
@@ -1454,12 +1657,14 @@ def _build_custom_row(
|
||||
pose = str(_merged_field(category, subcategory, item, "pose", "") or context.get("fallback_pose") or _choose_text(
|
||||
pose_rng, _compatible_entries(_pose_pool(category, subcategory, item, subject_type, poses), women_count, men_count)
|
||||
))
|
||||
expression = _choose_text(
|
||||
expression_rng,
|
||||
_compatible_entries(_list_from(_merged_field(category, subcategory, item, "expressions", g.EXPRESSIONS)), women_count, men_count),
|
||||
expression_entries = _compatible_entries(
|
||||
_expression_entries_for_intensity(_expression_pool(category, subcategory, item), expression_intensity),
|
||||
women_count,
|
||||
men_count,
|
||||
)
|
||||
expression = _choose_text(expression_rng, expression_entries)
|
||||
if subject_type in ("couple", "group") and ";" not in expression:
|
||||
expression = f"{expression}; {_choose_text(expression_rng, g.EXPRESSIONS)}"
|
||||
expression = f"{expression}; {_choose_text(expression_rng, expression_entries)}"
|
||||
composition = _choose_text(
|
||||
composition_rng,
|
||||
_compatible_entries(_composition_pool(category, subcategory, item, subject_type), women_count, men_count),
|
||||
@@ -1492,6 +1697,7 @@ def _build_custom_row(
|
||||
"scene_slug": scene_slug,
|
||||
"pose": pose,
|
||||
"expression": expression,
|
||||
"expression_intensity": expression_intensity,
|
||||
"composition": composition,
|
||||
"role_graph": role_graph,
|
||||
"positive_suffix": positive_suffix,
|
||||
@@ -1588,6 +1794,7 @@ def build_prompt(
|
||||
women_count: int = 1,
|
||||
men_count: int = 1,
|
||||
camera_config: str | dict[str, Any] | None = None,
|
||||
expression_intensity: float = 0.5,
|
||||
) -> dict[str, Any]:
|
||||
apply_pool_extensions()
|
||||
row_number = max(1, int(row_number))
|
||||
@@ -1599,6 +1806,7 @@ def build_prompt(
|
||||
figure = figure if figure in ("curvy", "balanced", "bombshell") else "curvy"
|
||||
minimal_ratio = _ratio_or_none(minimal_clothing_ratio)
|
||||
pose_ratio = _ratio_or_none(standard_pose_ratio)
|
||||
expression_intensity = _clamped_float(expression_intensity, 0.5)
|
||||
parsed_seed_config = _parse_seed_config(seed_config)
|
||||
|
||||
exact_custom_subcategory = bool(subcategory and subcategory != RANDOM_SUBCATEGORY and " / " in subcategory)
|
||||
@@ -1649,6 +1857,7 @@ def build_prompt(
|
||||
int(men_count),
|
||||
seed,
|
||||
parsed_seed_config,
|
||||
expression_intensity,
|
||||
)
|
||||
|
||||
if extra_positive.strip():
|
||||
@@ -1658,6 +1867,7 @@ def build_prompt(
|
||||
row["prompt"] = _prepend_trigger(row["prompt"], active_trigger, bool(prepend_trigger_to_prompt))
|
||||
row["negative_prompt"] = _combined_negative(row.get("negative_prompt", g.NEGATIVE_PROMPT), extra_negative)
|
||||
row["trigger"] = active_trigger
|
||||
row["expression_intensity"] = expression_intensity
|
||||
return row
|
||||
|
||||
|
||||
@@ -1700,6 +1910,8 @@ def build_insta_of_options_json(
|
||||
continuity: str = "same_creator_same_room",
|
||||
softcore_camera_mode: str = "handheld_selfie",
|
||||
hardcore_camera_mode: str = "same_as_softcore",
|
||||
softcore_expression_intensity: float = 0.45,
|
||||
hardcore_expression_intensity: float = 0.85,
|
||||
) -> str:
|
||||
return json.dumps(
|
||||
{
|
||||
@@ -1713,6 +1925,8 @@ def build_insta_of_options_json(
|
||||
"continuity": continuity,
|
||||
"softcore_camera_mode": softcore_camera_mode,
|
||||
"hardcore_camera_mode": hardcore_camera_mode,
|
||||
"softcore_expression_intensity": _clamped_float(softcore_expression_intensity, 0.45),
|
||||
"hardcore_expression_intensity": _clamped_float(hardcore_expression_intensity, 0.85),
|
||||
},
|
||||
ensure_ascii=True,
|
||||
sort_keys=True,
|
||||
@@ -1731,6 +1945,8 @@ def _parse_insta_of_options(options_json: str | dict[str, Any] | None) -> dict[s
|
||||
"continuity": "same_creator_same_room",
|
||||
"softcore_camera_mode": "handheld_selfie",
|
||||
"hardcore_camera_mode": "same_as_softcore",
|
||||
"softcore_expression_intensity": 0.45,
|
||||
"hardcore_expression_intensity": 0.85,
|
||||
}
|
||||
if not options_json:
|
||||
return defaults
|
||||
@@ -1753,6 +1969,14 @@ def _parse_insta_of_options(options_json: str | dict[str, Any] | None) -> dict[s
|
||||
parsed["softcore_camera_mode"] = parsed["softcore_camera_mode"] if parsed["softcore_camera_mode"] in CAMERA_MODE_PROMPTS else defaults["softcore_camera_mode"]
|
||||
if parsed["hardcore_camera_mode"] not in CAMERA_MODE_PROMPTS and parsed["hardcore_camera_mode"] != "same_as_softcore":
|
||||
parsed["hardcore_camera_mode"] = defaults["hardcore_camera_mode"]
|
||||
parsed["softcore_expression_intensity"] = _clamped_float(
|
||||
parsed.get("softcore_expression_intensity"),
|
||||
defaults["softcore_expression_intensity"],
|
||||
)
|
||||
parsed["hardcore_expression_intensity"] = _clamped_float(
|
||||
parsed.get("hardcore_expression_intensity"),
|
||||
defaults["hardcore_expression_intensity"],
|
||||
)
|
||||
for key in ("hardcore_women_count", "hardcore_men_count"):
|
||||
try:
|
||||
parsed[key] = max(0, min(12, int(parsed[key])))
|
||||
@@ -1845,6 +2069,7 @@ def build_insta_of_pair(
|
||||
seed_config=parsed_seed_config,
|
||||
women_count=1,
|
||||
men_count=0,
|
||||
expression_intensity=options["softcore_expression_intensity"],
|
||||
)
|
||||
hard_row = build_prompt(
|
||||
category="Hardcore sexual poses",
|
||||
@@ -1868,6 +2093,7 @@ def build_insta_of_pair(
|
||||
seed_config=parsed_seed_config,
|
||||
women_count=hard_women_count,
|
||||
men_count=hard_men_count,
|
||||
expression_intensity=options["hardcore_expression_intensity"],
|
||||
)
|
||||
|
||||
descriptor = _insta_of_descriptor(soft_row)
|
||||
|
||||
Reference in New Issue
Block a user