Add expression intensity controls
This commit is contained in:
@@ -127,6 +127,11 @@ Options:
|
|||||||
- `softcore_level`: `social_tease`, `lingerie_tease`, `implied_nude`, or
|
- `softcore_level`: `social_tease`, `lingerie_tease`, `implied_nude`, or
|
||||||
`explicit_tease`.
|
`explicit_tease`.
|
||||||
- `hardcore_level`: `explicit` or `hardcore`.
|
- `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`.
|
- `platform_style`: `hybrid`, `instagram`, or `onlyfans`.
|
||||||
- `continuity`: `same_creator_same_room` keeps the scene/composition aligned;
|
- `continuity`: `same_creator_same_room` keeps the scene/composition aligned;
|
||||||
`same_creator_new_scene` keeps the same creator descriptor but lets the
|
`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.
|
- `minimal_clothing_ratio`: `-1` disables mixing; `0.0` to `1.0` mixes minimal/full clothing.
|
||||||
- `ethnicity`: `any`, `asian`, `white_asian`.
|
- `ethnicity`: `any`, `asian`, `white_asian`.
|
||||||
- `poses`: `standard` or `evocative`.
|
- `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.
|
- `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.
|
- `backside_bias`: `0.0` to `1.0`, applies to evocative single-subject poses.
|
||||||
- `figure`: `curvy`, `balanced`, `bombshell`.
|
- `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
|
scene, pose, expression, composition, and a random item from the selected
|
||||||
subcategory.
|
subcategory.
|
||||||
|
|
||||||
Reusable location banks can be defined with top-level `scene_pools` in any
|
Reusable banks can be defined with top-level `scene_pools`,
|
||||||
`categories/*.json` file. Categories, subcategories, and items can reference
|
`expression_pools`, and `composition_pools` in any `categories/*.json` file.
|
||||||
them with `scene_pools`; referenced pools are merged with any local `scenes`.
|
Categories, subcategories, and items can reference them with `scene_pools`,
|
||||||
This keeps location expansion scalable without duplicating the same bedroom,
|
`expression_pools`, and `composition_pools`; referenced pools are merged with
|
||||||
selfie, mirror, creator, or group-sex locations across every subcategory.
|
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
|
Set `"inherit_scenes": false`, `"inherit_expressions": false`, or
|
||||||
its own `scenes` and `scene_pools` instead of also inheriting parent category
|
`"inherit_compositions": false` on a subcategory or item when it should use only
|
||||||
locations. This is useful for narrow subcategories such as group scenes, vehicle
|
its own pools instead of also inheriting parent category values. This is useful
|
||||||
sets, outdoor-only sets, or any category where a generic parent room would be a
|
for narrow subcategories such as group scenes, fetish sets, outdoor-only sets,
|
||||||
bad match.
|
or any category where generic parent wording would be a bad match.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```json
|
```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": {
|
"scene_pools": {
|
||||||
"creator_selfie_rooms": [
|
"creator_selfie_rooms": [
|
||||||
{
|
{
|
||||||
@@ -241,7 +265,11 @@ Example:
|
|||||||
{
|
{
|
||||||
"name": "Selfie set",
|
"name": "Selfie set",
|
||||||
"inherit_scenes": false,
|
"inherit_scenes": false,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"scene_pools": ["creator_selfie_rooms"],
|
"scene_pools": ["creator_selfie_rooms"],
|
||||||
|
"expression_pools": ["creator_tease_faces"],
|
||||||
|
"composition_pools": ["creator_selfie_frames"],
|
||||||
"items": ["simple outfit prompt"]
|
"items": ["simple outfit prompt"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class SxCPPromptBuilder:
|
|||||||
"clothing": (["full", "minimal"], {"default": "full"}),
|
"clothing": (["full", "minimal"], {"default": "full"}),
|
||||||
"ethnicity": (["any", "asian", "white_asian"], {"default": "any"}),
|
"ethnicity": (["any", "asian", "white_asian"], {"default": "any"}),
|
||||||
"poses": (["standard", "evocative"], {"default": "standard"}),
|
"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}),
|
"backside_bias": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||||
"figure": (["curvy", "balanced", "bombshell"], {"default": "curvy"}),
|
"figure": (["curvy", "balanced", "bombshell"], {"default": "curvy"}),
|
||||||
"no_plus_women": ("BOOLEAN", {"default": False}),
|
"no_plus_women": ("BOOLEAN", {"default": False}),
|
||||||
@@ -91,6 +92,7 @@ class SxCPPromptBuilder:
|
|||||||
clothing,
|
clothing,
|
||||||
ethnicity,
|
ethnicity,
|
||||||
poses,
|
poses,
|
||||||
|
expression_intensity,
|
||||||
backside_bias,
|
backside_bias,
|
||||||
figure,
|
figure,
|
||||||
no_plus_women,
|
no_plus_women,
|
||||||
@@ -115,6 +117,7 @@ class SxCPPromptBuilder:
|
|||||||
clothing=clothing,
|
clothing=clothing,
|
||||||
ethnicity=ethnicity,
|
ethnicity=ethnicity,
|
||||||
poses=poses,
|
poses=poses,
|
||||||
|
expression_intensity=expression_intensity,
|
||||||
backside_bias=backside_bias,
|
backside_bias=backside_bias,
|
||||||
figure=figure,
|
figure=figure,
|
||||||
no_plus_women=no_plus_women,
|
no_plus_women=no_plus_women,
|
||||||
@@ -359,6 +362,8 @@ class SxCPInstaOFOptions:
|
|||||||
"hardcore_men_count": ("INT", {"default": 1, "min": 0, "max": 12, "step": 1}),
|
"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"}),
|
"softcore_level": (["social_tease", "lingerie_tease", "implied_nude", "explicit_tease"], {"default": "lingerie_tease"}),
|
||||||
"hardcore_level": (["explicit", "hardcore"], {"default": "hardcore"}),
|
"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"}),
|
"platform_style": (["hybrid", "instagram", "onlyfans"], {"default": "hybrid"}),
|
||||||
"continuity": (["same_creator_same_room", "same_creator_new_scene"], {"default": "same_creator_same_room"}),
|
"continuity": (["same_creator_same_room", "same_creator_new_scene"], {"default": "same_creator_same_room"}),
|
||||||
"softcore_camera_mode": (camera_mode_choices(), {"default": "handheld_selfie"}),
|
"softcore_camera_mode": (camera_mode_choices(), {"default": "handheld_selfie"}),
|
||||||
@@ -379,6 +384,8 @@ class SxCPInstaOFOptions:
|
|||||||
hardcore_men_count,
|
hardcore_men_count,
|
||||||
softcore_level,
|
softcore_level,
|
||||||
hardcore_level,
|
hardcore_level,
|
||||||
|
softcore_expression_intensity,
|
||||||
|
hardcore_expression_intensity,
|
||||||
platform_style,
|
platform_style,
|
||||||
continuity,
|
continuity,
|
||||||
softcore_camera_mode,
|
softcore_camera_mode,
|
||||||
@@ -392,6 +399,8 @@ class SxCPInstaOFOptions:
|
|||||||
hardcore_men_count=hardcore_men_count,
|
hardcore_men_count=hardcore_men_count,
|
||||||
softcore_level=softcore_level,
|
softcore_level=softcore_level,
|
||||||
hardcore_level=hardcore_level,
|
hardcore_level=hardcore_level,
|
||||||
|
softcore_expression_intensity=softcore_expression_intensity,
|
||||||
|
hardcore_expression_intensity=hardcore_expression_intensity,
|
||||||
platform_style=platform_style,
|
platform_style=platform_style,
|
||||||
continuity=continuity,
|
continuity=continuity,
|
||||||
softcore_camera_mode=softcore_camera_mode,
|
softcore_camera_mode=softcore_camera_mode,
|
||||||
|
|||||||
@@ -9,12 +9,18 @@
|
|||||||
"item_label": "Clothing",
|
"item_label": "Clothing",
|
||||||
"style": "tasteful adult fashion-editorial coloured-pencil comic illustration with casual everyday styling",
|
"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.",
|
"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": [
|
"subcategories": [
|
||||||
{
|
{
|
||||||
"name": "Streetwear",
|
"name": "Streetwear",
|
||||||
"slug": "streetwear",
|
"slug": "streetwear",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"scene_pools": ["casual_urban_scenes"],
|
"scene_pools": ["casual_urban_scenes"],
|
||||||
|
"expression_pools": ["streetwear_attitude_expressions"],
|
||||||
|
"composition_pools": ["streetwear_phone_compositions"],
|
||||||
"items": ["streetwear outfit generator"],
|
"items": ["streetwear outfit generator"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{outerwear} layered over {top}, with {bottom}, {footwear}, and {accessory}",
|
"{outerwear} layered over {top}, with {bottom}, {footwear}, and {accessory}",
|
||||||
@@ -169,7 +175,11 @@
|
|||||||
"name": "Summer casual",
|
"name": "Summer casual",
|
||||||
"slug": "summer_casual",
|
"slug": "summer_casual",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"scene_pools": ["casual_summer_scenes"],
|
"scene_pools": ["casual_summer_scenes"],
|
||||||
|
"expression_pools": ["summer_candid_expressions"],
|
||||||
|
"composition_pools": ["summer_lifestyle_compositions"],
|
||||||
"items": ["summer casual outfit generator"],
|
"items": ["summer casual outfit generator"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{dress} with {footwear}, {accessory}, and {fabric_detail}",
|
"{dress} with {footwear}, {accessory}, and {fabric_detail}",
|
||||||
@@ -342,7 +352,11 @@
|
|||||||
"name": "Cozy lounge",
|
"name": "Cozy lounge",
|
||||||
"slug": "cozy_lounge",
|
"slug": "cozy_lounge",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"scene_pools": ["casual_lounge_scenes"],
|
"scene_pools": ["casual_lounge_scenes"],
|
||||||
|
"expression_pools": ["cozy_lounge_expressions"],
|
||||||
|
"composition_pools": ["cozy_home_compositions"],
|
||||||
"items": ["cozy lounge outfit generator"],
|
"items": ["cozy lounge outfit generator"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{layer} over {top}, with {bottom}, {footwear}, and {texture_detail}",
|
"{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.",
|
"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",
|
"negative_prompt": "minors, childlike appearance, schoolgirl, childlike costume, non-consensual, coercion, violence, injury, watermark",
|
||||||
"scene_pools": ["softcore_creator_scenes", "mirror_scenes"],
|
"scene_pools": ["softcore_creator_scenes", "mirror_scenes"],
|
||||||
|
"expression_pools": ["softcore_creator_expressions", "erotic_inviting_expressions"],
|
||||||
|
"composition_pools": ["softcore_creator_compositions", "boudoir_body_compositions"],
|
||||||
"expressions": [
|
"expressions": [
|
||||||
"heavy-lidded seductive gaze",
|
"heavy-lidded seductive gaze",
|
||||||
"direct erotic stare",
|
"direct erotic stare",
|
||||||
@@ -552,7 +554,11 @@
|
|||||||
"name": "Fetish inspired",
|
"name": "Fetish inspired",
|
||||||
"slug": "fetish_inspired",
|
"slug": "fetish_inspired",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"scene_pools": ["fetish_studio_scenes"],
|
"scene_pools": ["fetish_studio_scenes"],
|
||||||
|
"expression_pools": ["fetish_control_expressions"],
|
||||||
|
"composition_pools": ["fetish_studio_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{color} {material} {latex_piece} with {zipper_detail}, {boot_style}, and {glove_style}",
|
"{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}",
|
"{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.",
|
"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",
|
"negative_prompt": "minors, childlike appearance, teen, schoolgirl, incest, bestiality, non-consensual, coercion, rape, violence, injury, blood, gore, watermark",
|
||||||
"scene_pools": ["hardcore_private_scenes"],
|
"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}.",
|
"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",
|
"caption_template": "{trigger}, {scene_kind}, {cast_summary}, {role_graph}, {item}, {scene}, {composition}, explicit consensual adult hardcore sex illustration",
|
||||||
"expressions": [
|
"expressions": [
|
||||||
"open-mouthed orgasmic expression",
|
"adult ahegao-style orgasm face",
|
||||||
"heavy-lidded lustful gaze",
|
"eyes rolled back with tongue out",
|
||||||
"flushed faces and parted lips",
|
"drooling open-mouthed moan",
|
||||||
"intense eye contact during sex",
|
"fucked-out dazed stare",
|
||||||
"breathless pleasure expression",
|
"sweaty flushed orgasm expression",
|
||||||
"commanding erotic stare",
|
"jaw slack from intense pleasure",
|
||||||
"shameless aroused grin",
|
"messy saliva-shiny lips",
|
||||||
"eyes closed in climax",
|
"desperate near-climax gaze",
|
||||||
"teasing dominant smile",
|
"wild tongue-out arousal",
|
||||||
"desperate hungry gaze",
|
"breathless post-orgasm face",
|
||||||
"sweaty post-orgasmic glow",
|
"cum-smeared lips and glossy eyes",
|
||||||
"bitten-lip pleasure expression",
|
"open mouth and trembling lips",
|
||||||
"wild aroused expression",
|
"heavy-lidded exhausted pleasure stare",
|
||||||
"soft moaning expression",
|
"raw overwhelmed climax expression",
|
||||||
"focused intimate eye contact",
|
"shameless messy aroused grin",
|
||||||
"overwhelmed climax expression"
|
"eyes squeezed shut during orgasm",
|
||||||
|
"dazed sex-drunk expression",
|
||||||
|
"heated direct eye contact during sex"
|
||||||
],
|
],
|
||||||
"compositions": [
|
"compositions": [
|
||||||
"full-body bed scene with all bodies visible",
|
"full-body explicit sex frame with all adult bodies visible",
|
||||||
"low-angle explicit penetration view",
|
"low-angle view focused on genital contact",
|
||||||
"overhead view of intertwined bodies",
|
"overhead view of intertwined adult bodies",
|
||||||
"side-profile view showing genital contact",
|
"side-profile view showing penetration alignment",
|
||||||
"mirror-view sex composition",
|
"mirror-view explicit sex composition",
|
||||||
"close crop on hips, thighs, and faces",
|
"close crop on hips, thighs, hands, genitals, and faces",
|
||||||
"wide orgy composition with all participants visible",
|
"wide group-sex composition with all participants visible",
|
||||||
"centered threesome composition",
|
"centered threesome composition with all three bodies readable",
|
||||||
"kneeling and standing composition",
|
"kneeling and standing explicit body-contact frame",
|
||||||
"reclining full-body composition",
|
"reclining full-body sex composition",
|
||||||
"floor-level explicit sex composition",
|
"floor-level explicit sex composition",
|
||||||
"front-facing explicit pin-up composition"
|
"front-facing hardcore creator-shot composition"
|
||||||
],
|
],
|
||||||
"scenes": [
|
"scenes": [
|
||||||
{
|
{
|
||||||
@@ -84,8 +88,12 @@
|
|||||||
"name": "Penetrative sex",
|
"name": "Penetrative sex",
|
||||||
"slug": "penetrative_sex",
|
"slug": "penetrative_sex",
|
||||||
"min_people": 2,
|
"min_people": 2,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_penetrative_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_penetrative_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
|
"expression_pools": ["hardcore_penetration_expressions"],
|
||||||
|
"composition_pools": ["penetration_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{penetration_act} in {position}, with {body_contact}, {intensity}, and {visibility}",
|
"{penetration_act} in {position}, with {body_contact}, {intensity}, and {visibility}",
|
||||||
"{position} while {penetration_act}, {hand_detail}, {mouth_detail}, and {visibility}",
|
"{position} while {penetration_act}, {hand_detail}, {mouth_detail}, and {visibility}",
|
||||||
@@ -249,8 +257,12 @@
|
|||||||
"name": "Oral sex",
|
"name": "Oral sex",
|
||||||
"slug": "oral_sex",
|
"slug": "oral_sex",
|
||||||
"min_people": 2,
|
"min_people": 2,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_oral_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_oral_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
|
"expression_pools": ["hardcore_oral_expressions"],
|
||||||
|
"composition_pools": ["oral_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{oral_act} in {position}, with {hand_detail}, {expression_detail}, and {visibility}",
|
"{oral_act} in {position}, with {hand_detail}, {expression_detail}, and {visibility}",
|
||||||
"{position} featuring {oral_act}, {body_contact}, {saliva_detail}, and {climax_hint}",
|
"{position} featuring {oral_act}, {body_contact}, {saliva_detail}, and {climax_hint}",
|
||||||
@@ -382,8 +394,12 @@
|
|||||||
"name": "Anal and double penetration",
|
"name": "Anal and double penetration",
|
||||||
"slug": "anal_double_penetration",
|
"slug": "anal_double_penetration",
|
||||||
"min_people": 2,
|
"min_people": 2,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_anal_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_anal_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
|
"expression_pools": ["hardcore_anal_dp_expressions"],
|
||||||
|
"composition_pools": ["anal_dp_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{anal_act} in {position}, with {leg_detail}, {hand_detail}, and {visibility}",
|
"{anal_act} in {position}, with {leg_detail}, {hand_detail}, and {visibility}",
|
||||||
"{double_act} with {body_arrangement}, {intensity}, {mouth_detail}, and {visibility}",
|
"{double_act} with {body_arrangement}, {intensity}, {mouth_detail}, and {visibility}",
|
||||||
@@ -587,8 +603,12 @@
|
|||||||
"name": "Threesomes",
|
"name": "Threesomes",
|
||||||
"slug": "threesomes",
|
"slug": "threesomes",
|
||||||
"min_people": 3,
|
"min_people": 3,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_threesome_scenes", "hardcore_group_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_threesome_scenes", "hardcore_group_scenes", "hardcore_mirror_scenes"],
|
||||||
|
"expression_pools": ["hardcore_group_expressions"],
|
||||||
|
"composition_pools": ["threesome_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{threesome_act} with {body_arrangement}, {oral_detail}, {penetration_detail}, and {visibility}",
|
"{threesome_act} with {body_arrangement}, {oral_detail}, {penetration_detail}, and {visibility}",
|
||||||
"{body_arrangement} while {threesome_act}, with {hand_detail}, {mouth_detail}, and {climax_hint}",
|
"{body_arrangement} while {threesome_act}, with {hand_detail}, {mouth_detail}, and {climax_hint}",
|
||||||
@@ -766,8 +786,12 @@
|
|||||||
"slug": "group_sex_orgy",
|
"slug": "group_sex_orgy",
|
||||||
"min_people": 4,
|
"min_people": 4,
|
||||||
"inherit_scenes": false,
|
"inherit_scenes": false,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_group_scenes"],
|
"scene_pools": ["hardcore_group_scenes"],
|
||||||
|
"expression_pools": ["hardcore_group_expressions"],
|
||||||
|
"composition_pools": ["group_sex_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{group_act} with {arrangement}, {contact_detail}, {fluid_detail}, and {visibility}",
|
"{group_act} with {arrangement}, {contact_detail}, {fluid_detail}, and {visibility}",
|
||||||
"{arrangement} featuring {group_act}, {oral_detail}, {penetration_detail}, and {intensity}",
|
"{arrangement} featuring {group_act}, {oral_detail}, {penetration_detail}, and {intensity}",
|
||||||
@@ -934,8 +958,12 @@
|
|||||||
"name": "Cumshot and climax",
|
"name": "Cumshot and climax",
|
||||||
"slug": "cumshot_climax",
|
"slug": "cumshot_climax",
|
||||||
"min_people": 1,
|
"min_people": 1,
|
||||||
|
"inherit_expressions": false,
|
||||||
|
"inherit_compositions": false,
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
"scene_pools": ["hardcore_climax_scenes", "hardcore_bed_scenes", "hardcore_mirror_scenes"],
|
||||||
|
"expression_pools": ["hardcore_climax_expressions"],
|
||||||
|
"composition_pools": ["climax_compositions"],
|
||||||
"item_templates": [
|
"item_templates": [
|
||||||
"{climax_act} with {fluid_location}, {body_position}, {expression_detail}, and {visibility}",
|
"{climax_act} with {fluid_location}, {body_position}, {expression_detail}, and {visibility}",
|
||||||
"{body_position} during {climax_act}, with {hand_detail}, {fluid_location}, and {fluid_detail}",
|
"{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
|
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]] = {}
|
pools: dict[str, list[Any]] = {}
|
||||||
for path in _json_files():
|
for path in _json_files():
|
||||||
data = _read_json(path)
|
data = _read_json(path)
|
||||||
raw_pools = data.get("scene_pools", {})
|
raw_pools = data.get(key, {})
|
||||||
if not raw_pools:
|
if not raw_pools:
|
||||||
continue
|
continue
|
||||||
if not isinstance(raw_pools, dict):
|
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():
|
for name, entries in raw_pools.items():
|
||||||
pool_name = str(name).strip()
|
pool_name = str(name).strip()
|
||||||
if not pool_name:
|
if not pool_name:
|
||||||
@@ -580,6 +580,18 @@ def load_scene_pool_library() -> dict[str, list[Any]]:
|
|||||||
return pools
|
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]]:
|
def _extension_targets() -> dict[str, tuple[list[Any], bool]]:
|
||||||
return {
|
return {
|
||||||
"women_clothes": (g.WOMEN_CLOTHES, False),
|
"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))
|
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(
|
def build_seed_config_json(
|
||||||
category_seed: int = -1,
|
category_seed: int = -1,
|
||||||
subcategory_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
|
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]:
|
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")
|
configured = _merged_field(category, subcategory, item, "poses")
|
||||||
if configured:
|
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]:
|
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:
|
if configured:
|
||||||
return _list_from(configured)
|
return configured
|
||||||
if subject_type in ("group", "configured_cast"):
|
if subject_type in ("group", "configured_cast"):
|
||||||
return g.GROUP_COMPOSITIONS
|
return g.GROUP_COMPOSITIONS
|
||||||
if subject_type in ("layout", "scene"):
|
if subject_type in ("layout", "scene"):
|
||||||
@@ -1420,6 +1622,7 @@ def _build_custom_row(
|
|||||||
men_count: int,
|
men_count: int,
|
||||||
seed: int,
|
seed: int,
|
||||||
seed_config: dict[str, int],
|
seed_config: dict[str, int],
|
||||||
|
expression_intensity: float,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
categories = load_category_library()
|
categories = load_category_library()
|
||||||
category_rng = _axis_rng(seed_config, "category", seed, row_number)
|
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 = 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)
|
pose_rng, _compatible_entries(_pose_pool(category, subcategory, item, subject_type, poses), women_count, men_count)
|
||||||
))
|
))
|
||||||
expression = _choose_text(
|
expression_entries = _compatible_entries(
|
||||||
expression_rng,
|
_expression_entries_for_intensity(_expression_pool(category, subcategory, item), expression_intensity),
|
||||||
_compatible_entries(_list_from(_merged_field(category, subcategory, item, "expressions", g.EXPRESSIONS)), women_count, men_count),
|
women_count,
|
||||||
|
men_count,
|
||||||
)
|
)
|
||||||
|
expression = _choose_text(expression_rng, expression_entries)
|
||||||
if subject_type in ("couple", "group") and ";" not in expression:
|
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 = _choose_text(
|
||||||
composition_rng,
|
composition_rng,
|
||||||
_compatible_entries(_composition_pool(category, subcategory, item, subject_type), women_count, men_count),
|
_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,
|
"scene_slug": scene_slug,
|
||||||
"pose": pose,
|
"pose": pose,
|
||||||
"expression": expression,
|
"expression": expression,
|
||||||
|
"expression_intensity": expression_intensity,
|
||||||
"composition": composition,
|
"composition": composition,
|
||||||
"role_graph": role_graph,
|
"role_graph": role_graph,
|
||||||
"positive_suffix": positive_suffix,
|
"positive_suffix": positive_suffix,
|
||||||
@@ -1588,6 +1794,7 @@ def build_prompt(
|
|||||||
women_count: int = 1,
|
women_count: int = 1,
|
||||||
men_count: int = 1,
|
men_count: int = 1,
|
||||||
camera_config: str | dict[str, Any] | None = None,
|
camera_config: str | dict[str, Any] | None = None,
|
||||||
|
expression_intensity: float = 0.5,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
apply_pool_extensions()
|
apply_pool_extensions()
|
||||||
row_number = max(1, int(row_number))
|
row_number = max(1, int(row_number))
|
||||||
@@ -1599,6 +1806,7 @@ def build_prompt(
|
|||||||
figure = figure if figure in ("curvy", "balanced", "bombshell") else "curvy"
|
figure = figure if figure in ("curvy", "balanced", "bombshell") else "curvy"
|
||||||
minimal_ratio = _ratio_or_none(minimal_clothing_ratio)
|
minimal_ratio = _ratio_or_none(minimal_clothing_ratio)
|
||||||
pose_ratio = _ratio_or_none(standard_pose_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)
|
parsed_seed_config = _parse_seed_config(seed_config)
|
||||||
|
|
||||||
exact_custom_subcategory = bool(subcategory and subcategory != RANDOM_SUBCATEGORY and " / " in subcategory)
|
exact_custom_subcategory = bool(subcategory and subcategory != RANDOM_SUBCATEGORY and " / " in subcategory)
|
||||||
@@ -1649,6 +1857,7 @@ def build_prompt(
|
|||||||
int(men_count),
|
int(men_count),
|
||||||
seed,
|
seed,
|
||||||
parsed_seed_config,
|
parsed_seed_config,
|
||||||
|
expression_intensity,
|
||||||
)
|
)
|
||||||
|
|
||||||
if extra_positive.strip():
|
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["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["negative_prompt"] = _combined_negative(row.get("negative_prompt", g.NEGATIVE_PROMPT), extra_negative)
|
||||||
row["trigger"] = active_trigger
|
row["trigger"] = active_trigger
|
||||||
|
row["expression_intensity"] = expression_intensity
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
|
||||||
@@ -1700,6 +1910,8 @@ def build_insta_of_options_json(
|
|||||||
continuity: str = "same_creator_same_room",
|
continuity: str = "same_creator_same_room",
|
||||||
softcore_camera_mode: str = "handheld_selfie",
|
softcore_camera_mode: str = "handheld_selfie",
|
||||||
hardcore_camera_mode: str = "same_as_softcore",
|
hardcore_camera_mode: str = "same_as_softcore",
|
||||||
|
softcore_expression_intensity: float = 0.45,
|
||||||
|
hardcore_expression_intensity: float = 0.85,
|
||||||
) -> str:
|
) -> str:
|
||||||
return json.dumps(
|
return json.dumps(
|
||||||
{
|
{
|
||||||
@@ -1713,6 +1925,8 @@ def build_insta_of_options_json(
|
|||||||
"continuity": continuity,
|
"continuity": continuity,
|
||||||
"softcore_camera_mode": softcore_camera_mode,
|
"softcore_camera_mode": softcore_camera_mode,
|
||||||
"hardcore_camera_mode": hardcore_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,
|
ensure_ascii=True,
|
||||||
sort_keys=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",
|
"continuity": "same_creator_same_room",
|
||||||
"softcore_camera_mode": "handheld_selfie",
|
"softcore_camera_mode": "handheld_selfie",
|
||||||
"hardcore_camera_mode": "same_as_softcore",
|
"hardcore_camera_mode": "same_as_softcore",
|
||||||
|
"softcore_expression_intensity": 0.45,
|
||||||
|
"hardcore_expression_intensity": 0.85,
|
||||||
}
|
}
|
||||||
if not options_json:
|
if not options_json:
|
||||||
return defaults
|
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"]
|
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":
|
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["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"):
|
for key in ("hardcore_women_count", "hardcore_men_count"):
|
||||||
try:
|
try:
|
||||||
parsed[key] = max(0, min(12, int(parsed[key])))
|
parsed[key] = max(0, min(12, int(parsed[key])))
|
||||||
@@ -1845,6 +2069,7 @@ def build_insta_of_pair(
|
|||||||
seed_config=parsed_seed_config,
|
seed_config=parsed_seed_config,
|
||||||
women_count=1,
|
women_count=1,
|
||||||
men_count=0,
|
men_count=0,
|
||||||
|
expression_intensity=options["softcore_expression_intensity"],
|
||||||
)
|
)
|
||||||
hard_row = build_prompt(
|
hard_row = build_prompt(
|
||||||
category="Hardcore sexual poses",
|
category="Hardcore sexual poses",
|
||||||
@@ -1868,6 +2093,7 @@ def build_insta_of_pair(
|
|||||||
seed_config=parsed_seed_config,
|
seed_config=parsed_seed_config,
|
||||||
women_count=hard_women_count,
|
women_count=hard_women_count,
|
||||||
men_count=hard_men_count,
|
men_count=hard_men_count,
|
||||||
|
expression_intensity=options["hardcore_expression_intensity"],
|
||||||
)
|
)
|
||||||
|
|
||||||
descriptor = _insta_of_descriptor(soft_row)
|
descriptor = _insta_of_descriptor(soft_row)
|
||||||
|
|||||||
Reference in New Issue
Block a user