Extract Insta OF nodes
This commit is contained in:
+10
-194
@@ -416,6 +416,10 @@ try:
|
|||||||
NODE_CLASS_MAPPINGS as FORMATTER_NODE_CLASS_MAPPINGS,
|
NODE_CLASS_MAPPINGS as FORMATTER_NODE_CLASS_MAPPINGS,
|
||||||
NODE_DISPLAY_NAME_MAPPINGS as FORMATTER_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as FORMATTER_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
)
|
)
|
||||||
|
from .node_insta import (
|
||||||
|
NODE_CLASS_MAPPINGS as INSTA_NODE_CLASS_MAPPINGS,
|
||||||
|
NODE_DISPLAY_NAME_MAPPINGS as INSTA_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
|
)
|
||||||
from .node_profile_filter import (
|
from .node_profile_filter import (
|
||||||
NODE_CLASS_MAPPINGS as PROFILE_FILTER_NODE_CLASS_MAPPINGS,
|
NODE_CLASS_MAPPINGS as PROFILE_FILTER_NODE_CLASS_MAPPINGS,
|
||||||
NODE_DISPLAY_NAME_MAPPINGS as PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
@@ -429,15 +433,10 @@ try:
|
|||||||
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
)
|
)
|
||||||
from .prompt_builder import (
|
from .prompt_builder import (
|
||||||
build_insta_of_options_json,
|
|
||||||
build_insta_of_pair,
|
|
||||||
build_prompt,
|
build_prompt,
|
||||||
build_prompt_from_configs,
|
build_prompt_from_configs,
|
||||||
camera_detail_choices,
|
|
||||||
camera_mode_choices,
|
|
||||||
category_choices,
|
category_choices,
|
||||||
ethnicity_choices,
|
ethnicity_choices,
|
||||||
hardcore_detail_density_choices,
|
|
||||||
save_character_profile_payload,
|
save_character_profile_payload,
|
||||||
subcategory_choices,
|
subcategory_choices,
|
||||||
)
|
)
|
||||||
@@ -466,6 +465,10 @@ except ImportError:
|
|||||||
NODE_CLASS_MAPPINGS as FORMATTER_NODE_CLASS_MAPPINGS,
|
NODE_CLASS_MAPPINGS as FORMATTER_NODE_CLASS_MAPPINGS,
|
||||||
NODE_DISPLAY_NAME_MAPPINGS as FORMATTER_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as FORMATTER_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
)
|
)
|
||||||
|
from node_insta import (
|
||||||
|
NODE_CLASS_MAPPINGS as INSTA_NODE_CLASS_MAPPINGS,
|
||||||
|
NODE_DISPLAY_NAME_MAPPINGS as INSTA_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
|
)
|
||||||
from node_profile_filter import (
|
from node_profile_filter import (
|
||||||
NODE_CLASS_MAPPINGS as PROFILE_FILTER_NODE_CLASS_MAPPINGS,
|
NODE_CLASS_MAPPINGS as PROFILE_FILTER_NODE_CLASS_MAPPINGS,
|
||||||
NODE_DISPLAY_NAME_MAPPINGS as PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
@@ -479,15 +482,10 @@ except ImportError:
|
|||||||
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
|
NODE_DISPLAY_NAME_MAPPINGS as SEED_RESOLUTION_NODE_DISPLAY_NAME_MAPPINGS,
|
||||||
)
|
)
|
||||||
from prompt_builder import (
|
from prompt_builder import (
|
||||||
build_insta_of_options_json,
|
|
||||||
build_insta_of_pair,
|
|
||||||
build_prompt,
|
build_prompt,
|
||||||
build_prompt_from_configs,
|
build_prompt_from_configs,
|
||||||
camera_detail_choices,
|
|
||||||
camera_mode_choices,
|
|
||||||
category_choices,
|
category_choices,
|
||||||
ethnicity_choices,
|
ethnicity_choices,
|
||||||
hardcore_detail_density_choices,
|
|
||||||
save_character_profile_payload,
|
save_character_profile_payload,
|
||||||
subcategory_choices,
|
subcategory_choices,
|
||||||
)
|
)
|
||||||
@@ -764,186 +762,6 @@ class SxCPPromptBuilderFromConfigs:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SxCPInstaOFOptions:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(cls):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"softcore_cast": (["solo", "same_as_hardcore"], {"default": "solo"}),
|
|
||||||
"hardcore_cast": (["use_counts", "couple", "threesome", "group"], {"default": "use_counts"}),
|
|
||||||
"hardcore_women_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", "explicit_nude"], {"default": "lingerie_tease"}),
|
|
||||||
"hardcore_level": (["explicit", "hardcore"], {"default": "hardcore"}),
|
|
||||||
"softcore_expression_enabled": ("BOOLEAN", {"default": True}),
|
|
||||||
"hardcore_expression_enabled": ("BOOLEAN", {"default": True}),
|
|
||||||
"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"}),
|
|
||||||
"hardcore_clothing_continuity": (["none", "same_outfit", "partially_removed", "implied_nude", "explicit_nude"], {"default": "partially_removed"}),
|
|
||||||
"softcore_camera_mode": (["from_camera_config"] + camera_mode_choices(), {"default": "handheld_selfie"}),
|
|
||||||
"hardcore_camera_mode": (["from_camera_config", "same_as_softcore"] + camera_mode_choices(), {"default": "from_camera_config"}),
|
|
||||||
"camera_detail": (["from_camera_config"] + camera_detail_choices(), {"default": "from_camera_config"}),
|
|
||||||
"hardcore_detail_density": (hardcore_detail_density_choices(), {"default": "balanced"}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = (SXCP_INSTA_OF_OPTIONS,)
|
|
||||||
RETURN_NAMES = ("options_json",)
|
|
||||||
FUNCTION = "build"
|
|
||||||
CATEGORY = "prompt_builder"
|
|
||||||
|
|
||||||
def build(
|
|
||||||
self,
|
|
||||||
softcore_cast,
|
|
||||||
hardcore_cast,
|
|
||||||
hardcore_women_count,
|
|
||||||
hardcore_men_count,
|
|
||||||
softcore_level,
|
|
||||||
hardcore_level,
|
|
||||||
softcore_expression_enabled,
|
|
||||||
hardcore_expression_enabled,
|
|
||||||
softcore_expression_intensity,
|
|
||||||
hardcore_expression_intensity,
|
|
||||||
platform_style,
|
|
||||||
continuity,
|
|
||||||
hardcore_clothing_continuity,
|
|
||||||
softcore_camera_mode,
|
|
||||||
hardcore_camera_mode,
|
|
||||||
camera_detail,
|
|
||||||
hardcore_detail_density,
|
|
||||||
):
|
|
||||||
return (
|
|
||||||
build_insta_of_options_json(
|
|
||||||
softcore_cast=softcore_cast,
|
|
||||||
hardcore_cast=hardcore_cast,
|
|
||||||
hardcore_women_count=hardcore_women_count,
|
|
||||||
hardcore_men_count=hardcore_men_count,
|
|
||||||
softcore_level=softcore_level,
|
|
||||||
hardcore_level=hardcore_level,
|
|
||||||
softcore_expression_enabled=softcore_expression_enabled,
|
|
||||||
hardcore_expression_enabled=hardcore_expression_enabled,
|
|
||||||
softcore_expression_intensity=softcore_expression_intensity,
|
|
||||||
hardcore_expression_intensity=hardcore_expression_intensity,
|
|
||||||
platform_style=platform_style,
|
|
||||||
continuity=continuity,
|
|
||||||
hardcore_clothing_continuity=hardcore_clothing_continuity,
|
|
||||||
softcore_camera_mode=softcore_camera_mode,
|
|
||||||
hardcore_camera_mode=hardcore_camera_mode,
|
|
||||||
camera_detail=camera_detail,
|
|
||||||
hardcore_detail_density=hardcore_detail_density,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SxCPInstaOFPromptPair:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(cls):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"row_number": ("INT", {"default": 1, "min": 1, "max": 1000000, "step": 1}),
|
|
||||||
"start_index": ("INT", {"default": 41, "min": 1, "max": 1000000, "step": 1}),
|
|
||||||
"seed": ("INT", {"default": 20260614, "min": 0, "max": 0xFFFFFFFF, "step": 1}),
|
|
||||||
"ethnicity": (ethnicity_choices(), {"default": "any"}),
|
|
||||||
"figure": (["random", "curvy", "balanced", "bombshell"], {"default": "random"}),
|
|
||||||
"trigger": ("STRING", {"default": "sxcpinup_coloredpencil"}),
|
|
||||||
"prepend_trigger_to_prompt": ("BOOLEAN", {"default": True}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"seed_config": (SXCP_SEED_CONFIG,),
|
|
||||||
"options_json": (SXCP_INSTA_OF_OPTIONS,),
|
|
||||||
"filter_config": (SXCP_FILTER_CONFIG,),
|
|
||||||
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
|
||||||
"camera_config": (SXCP_CAMERA_CONFIG,),
|
|
||||||
"softcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
|
||||||
"hardcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
|
||||||
"location_config": (SXCP_LOCATION_CONFIG,),
|
|
||||||
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
|
||||||
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
|
||||||
"character_cast": (SXCP_CHARACTER_CAST,),
|
|
||||||
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
|
||||||
"extra_positive": ("STRING", {"default": "", "multiline": True}),
|
|
||||||
"extra_negative": ("STRING", {"default": "", "multiline": True}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
|
||||||
RETURN_NAMES = (
|
|
||||||
"softcore_prompt",
|
|
||||||
"hardcore_prompt",
|
|
||||||
"softcore_negative_prompt",
|
|
||||||
"hardcore_negative_prompt",
|
|
||||||
"softcore_caption",
|
|
||||||
"hardcore_caption",
|
|
||||||
"shared_descriptor",
|
|
||||||
"metadata_json",
|
|
||||||
)
|
|
||||||
FUNCTION = "build"
|
|
||||||
CATEGORY = "prompt_builder"
|
|
||||||
|
|
||||||
def build(
|
|
||||||
self,
|
|
||||||
row_number,
|
|
||||||
start_index,
|
|
||||||
seed,
|
|
||||||
ethnicity,
|
|
||||||
figure,
|
|
||||||
trigger,
|
|
||||||
prepend_trigger_to_prompt,
|
|
||||||
seed_config="",
|
|
||||||
options_json="",
|
|
||||||
filter_config="",
|
|
||||||
ethnicity_list="",
|
|
||||||
camera_config="",
|
|
||||||
softcore_camera_config="",
|
|
||||||
hardcore_camera_config="",
|
|
||||||
location_config="",
|
|
||||||
composition_config="",
|
|
||||||
character_profile="",
|
|
||||||
character_cast="",
|
|
||||||
hardcore_position_config="",
|
|
||||||
extra_positive="",
|
|
||||||
extra_negative="",
|
|
||||||
no_plus_women=False,
|
|
||||||
no_black=False,
|
|
||||||
):
|
|
||||||
row = build_insta_of_pair(
|
|
||||||
row_number=row_number,
|
|
||||||
start_index=start_index,
|
|
||||||
seed=seed,
|
|
||||||
ethnicity=ethnicity,
|
|
||||||
figure=figure,
|
|
||||||
no_plus_women=no_plus_women,
|
|
||||||
no_black=no_black,
|
|
||||||
trigger=trigger,
|
|
||||||
prepend_trigger_to_prompt=prepend_trigger_to_prompt,
|
|
||||||
seed_config=seed_config or "",
|
|
||||||
options_json=options_json or "",
|
|
||||||
filter_config=ethnicity_list or filter_config or "",
|
|
||||||
camera_config=camera_config or "",
|
|
||||||
softcore_camera_config=softcore_camera_config or "",
|
|
||||||
hardcore_camera_config=hardcore_camera_config or "",
|
|
||||||
location_config=location_config or "",
|
|
||||||
composition_config=composition_config or "",
|
|
||||||
character_profile=character_profile or "",
|
|
||||||
character_cast=character_cast or "",
|
|
||||||
hardcore_position_config=hardcore_position_config or "",
|
|
||||||
extra_positive=extra_positive or "",
|
|
||||||
extra_negative=extra_negative or "",
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
row["softcore_prompt"],
|
|
||||||
row["hardcore_prompt"],
|
|
||||||
row["softcore_negative_prompt"],
|
|
||||||
row["hardcore_negative_prompt"],
|
|
||||||
row["softcore_caption"],
|
|
||||||
row["hardcore_caption"],
|
|
||||||
row["shared_descriptor"],
|
|
||||||
json.dumps(row, ensure_ascii=True, sort_keys=True),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"SxCPPromptBuilder": SxCPPromptBuilder,
|
"SxCPPromptBuilder": SxCPPromptBuilder,
|
||||||
}
|
}
|
||||||
@@ -952,12 +770,11 @@ NODE_CLASS_MAPPINGS.update(CAMERA_NODE_CLASS_MAPPINGS)
|
|||||||
NODE_CLASS_MAPPINGS.update(CHARACTER_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(CHARACTER_NODE_CLASS_MAPPINGS)
|
||||||
NODE_CLASS_MAPPINGS.update(HARDCORE_POSITION_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(HARDCORE_POSITION_NODE_CLASS_MAPPINGS)
|
||||||
NODE_CLASS_MAPPINGS.update(FORMATTER_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(FORMATTER_NODE_CLASS_MAPPINGS)
|
||||||
|
NODE_CLASS_MAPPINGS.update(INSTA_NODE_CLASS_MAPPINGS)
|
||||||
NODE_CLASS_MAPPINGS.update(ROUTE_CONFIG_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(ROUTE_CONFIG_NODE_CLASS_MAPPINGS)
|
||||||
NODE_CLASS_MAPPINGS.update(PROFILE_FILTER_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(PROFILE_FILTER_NODE_CLASS_MAPPINGS)
|
||||||
NODE_CLASS_MAPPINGS.update({
|
NODE_CLASS_MAPPINGS.update({
|
||||||
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
"SxCPPromptBuilderFromConfigs": SxCPPromptBuilderFromConfigs,
|
||||||
"SxCPInstaOFOptions": SxCPInstaOFOptions,
|
|
||||||
"SxCPInstaOFPromptPair": SxCPInstaOFPromptPair,
|
|
||||||
})
|
})
|
||||||
NODE_CLASS_MAPPINGS.update(LOOP_NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(LOOP_NODE_CLASS_MAPPINGS)
|
||||||
_install_input_tooltips(NODE_CLASS_MAPPINGS)
|
_install_input_tooltips(NODE_CLASS_MAPPINGS)
|
||||||
@@ -970,12 +787,11 @@ NODE_DISPLAY_NAME_MAPPINGS.update(CAMERA_NODE_DISPLAY_NAME_MAPPINGS)
|
|||||||
NODE_DISPLAY_NAME_MAPPINGS.update(CHARACTER_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(CHARACTER_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(HARDCORE_POSITION_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(HARDCORE_POSITION_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(FORMATTER_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(FORMATTER_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
|
NODE_DISPLAY_NAME_MAPPINGS.update(INSTA_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(ROUTE_CONFIG_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(ROUTE_CONFIG_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(PROFILE_FILTER_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update({
|
NODE_DISPLAY_NAME_MAPPINGS.update({
|
||||||
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
"SxCPPromptBuilderFromConfigs": "SxCP Prompt Builder From Configs",
|
||||||
"SxCPInstaOFOptions": "SxCP Insta/OF Options",
|
|
||||||
"SxCPInstaOFPromptPair": "SxCP Insta/OF Prompt Pair",
|
|
||||||
})
|
})
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(LOOP_NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(LOOP_NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
|
|
||||||
|
|||||||
@@ -274,7 +274,8 @@ Improve later:
|
|||||||
|
|
||||||
Owner: `__init__.py`, `node_seed_resolution.py`, `node_camera.py`,
|
Owner: `__init__.py`, `node_seed_resolution.py`, `node_camera.py`,
|
||||||
`node_character.py`, `node_hardcore_position.py`, `node_formatter.py`,
|
`node_character.py`, `node_hardcore_position.py`, `node_formatter.py`,
|
||||||
`node_route_config.py`, `node_profile_filter.py`, `loop_nodes.py`, `web/*.js`.
|
`node_insta.py`, `node_route_config.py`, `node_profile_filter.py`,
|
||||||
|
`loop_nodes.py`, `web/*.js`.
|
||||||
|
|
||||||
Keep here:
|
Keep here:
|
||||||
|
|
||||||
@@ -288,6 +289,7 @@ Keep here:
|
|||||||
- hardcore position pool/filter node declarations in
|
- hardcore position pool/filter node declarations in
|
||||||
`node_hardcore_position.py`.
|
`node_hardcore_position.py`.
|
||||||
- caption/Krea2/SDXL formatter node declarations in `node_formatter.py`.
|
- caption/Krea2/SDXL formatter node declarations in `node_formatter.py`.
|
||||||
|
- Insta/OF options and prompt-pair node declarations in `node_insta.py`.
|
||||||
- route/category/location/composition/cast config node declarations in
|
- route/category/location/composition/cast config node declarations in
|
||||||
`node_route_config.py`.
|
`node_route_config.py`.
|
||||||
- profile/filter/ethnicity-list node declarations in `node_profile_filter.py`.
|
- profile/filter/ethnicity-list node declarations in `node_profile_filter.py`.
|
||||||
@@ -306,6 +308,8 @@ Already isolated:
|
|||||||
`__init__.py`.
|
`__init__.py`.
|
||||||
- caption naturalizer, Krea2 formatter, and SDXL formatter nodes live in
|
- caption naturalizer, Krea2 formatter, and SDXL formatter nodes live in
|
||||||
`node_formatter.py`, with registration maps imported by `__init__.py`.
|
`node_formatter.py`, with registration maps imported by `__init__.py`.
|
||||||
|
- Insta/OF options and dual prompt-pair nodes live in `node_insta.py`, with
|
||||||
|
registration maps imported by `__init__.py`.
|
||||||
- category preset, location/composition pool, location theme, and cast config
|
- category preset, location/composition pool, location theme, and cast config
|
||||||
utility nodes live in `node_route_config.py`, with registration maps imported
|
utility nodes live in `node_route_config.py`, with registration maps imported
|
||||||
by `__init__.py`.
|
by `__init__.py`.
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ When a result is wrong, first identify which layer owns the bad text:
|
|||||||
- Natural caption/training caption wrong: edit `caption_naturalizer.py`.
|
- Natural caption/training caption wrong: edit `caption_naturalizer.py`.
|
||||||
- UI/preview/loop behavior wrong: edit `__init__.py`, node family modules such
|
- UI/preview/loop behavior wrong: edit `__init__.py`, node family modules such
|
||||||
as `node_seed_resolution.py`, `node_camera.py`, `node_character.py`,
|
as `node_seed_resolution.py`, `node_camera.py`, `node_character.py`,
|
||||||
`node_hardcore_position.py`, `node_formatter.py`, `node_route_config.py`, or
|
`node_hardcore_position.py`, `node_formatter.py`, `node_insta.py`,
|
||||||
`node_profile_filter.py`, `loop_nodes.py`, or `web/*.js`.
|
`node_route_config.py`, or `node_profile_filter.py`, `loop_nodes.py`, or
|
||||||
|
`web/*.js`.
|
||||||
|
|
||||||
## High-Level Routes
|
## High-Level Routes
|
||||||
|
|
||||||
@@ -698,6 +699,7 @@ These do not own prompt pool wording, but they affect execution and review:
|
|||||||
| Character utility nodes | `node_character.py`, imported by `__init__.py` | Hair, age/body/eyes/clothing pools, manual details, character slots, and profile save/load nodes. |
|
| Character utility nodes | `node_character.py`, imported by `__init__.py` | Hair, age/body/eyes/clothing pools, manual details, character slots, and profile save/load nodes. |
|
||||||
| Hardcore position utility nodes | `node_hardcore_position.py`, imported by `__init__.py` | Position-family pool and action/filter gates for hardcore routes. |
|
| Hardcore position utility nodes | `node_hardcore_position.py`, imported by `__init__.py` | Position-family pool and action/filter gates for hardcore routes. |
|
||||||
| Formatter utility nodes | `node_formatter.py`, imported by `__init__.py` | Caption naturalizer, Krea2 formatter, and SDXL formatter node wrappers. |
|
| Formatter utility nodes | `node_formatter.py`, imported by `__init__.py` | Caption naturalizer, Krea2 formatter, and SDXL formatter node wrappers. |
|
||||||
|
| Insta/OF utility nodes | `node_insta.py`, imported by `__init__.py` | Insta/OF option config and dual prompt-pair node wrappers. |
|
||||||
| Route config utility nodes | `node_route_config.py`, imported by `__init__.py` | Category preset, location/composition pool, location theme, and cast config helpers. |
|
| Route config utility nodes | `node_route_config.py`, imported by `__init__.py` | Category preset, location/composition pool, location theme, and cast config helpers. |
|
||||||
| Profile/filter utility nodes | `node_profile_filter.py`, imported by `__init__.py` | Generation profile, advanced filter config, and ethnicity list helpers. |
|
| Profile/filter utility nodes | `node_profile_filter.py`, imported by `__init__.py` | Generation profile, advanced filter config, and ethnicity list helpers. |
|
||||||
|
|
||||||
|
|||||||
+225
@@ -0,0 +1,225 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .prompt_builder import (
|
||||||
|
build_insta_of_options_json,
|
||||||
|
build_insta_of_pair,
|
||||||
|
camera_detail_choices,
|
||||||
|
camera_mode_choices,
|
||||||
|
ethnicity_choices,
|
||||||
|
hardcore_detail_density_choices,
|
||||||
|
)
|
||||||
|
except ImportError: # Allows local smoke tests from the repository root.
|
||||||
|
from prompt_builder import (
|
||||||
|
build_insta_of_options_json,
|
||||||
|
build_insta_of_pair,
|
||||||
|
camera_detail_choices,
|
||||||
|
camera_mode_choices,
|
||||||
|
ethnicity_choices,
|
||||||
|
hardcore_detail_density_choices,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
SXCP_SEED_CONFIG = "SXCP_SEED_CONFIG"
|
||||||
|
SXCP_CAMERA_CONFIG = "SXCP_CAMERA_CONFIG"
|
||||||
|
SXCP_LOCATION_CONFIG = "SXCP_LOCATION_CONFIG"
|
||||||
|
SXCP_COMPOSITION_CONFIG = "SXCP_COMPOSITION_CONFIG"
|
||||||
|
SXCP_INSTA_OF_OPTIONS = "SXCP_INSTA_OF_OPTIONS"
|
||||||
|
SXCP_HARDCORE_POSITION_CONFIG = "SXCP_HARDCORE_POSITION_CONFIG"
|
||||||
|
SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
||||||
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
||||||
|
SXCP_ETHNICITY_LIST = "SXCP_ETHNICITY_LIST"
|
||||||
|
SXCP_FILTER_CONFIG = "SXCP_FILTER_CONFIG"
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPInstaOFOptions:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"softcore_cast": (["solo", "same_as_hardcore"], {"default": "solo"}),
|
||||||
|
"hardcore_cast": (["use_counts", "couple", "threesome", "group"], {"default": "use_counts"}),
|
||||||
|
"hardcore_women_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", "explicit_nude"], {"default": "lingerie_tease"}),
|
||||||
|
"hardcore_level": (["explicit", "hardcore"], {"default": "hardcore"}),
|
||||||
|
"softcore_expression_enabled": ("BOOLEAN", {"default": True}),
|
||||||
|
"hardcore_expression_enabled": ("BOOLEAN", {"default": True}),
|
||||||
|
"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"}),
|
||||||
|
"hardcore_clothing_continuity": (["none", "same_outfit", "partially_removed", "implied_nude", "explicit_nude"], {"default": "partially_removed"}),
|
||||||
|
"softcore_camera_mode": (["from_camera_config"] + camera_mode_choices(), {"default": "handheld_selfie"}),
|
||||||
|
"hardcore_camera_mode": (["from_camera_config", "same_as_softcore"] + camera_mode_choices(), {"default": "from_camera_config"}),
|
||||||
|
"camera_detail": (["from_camera_config"] + camera_detail_choices(), {"default": "from_camera_config"}),
|
||||||
|
"hardcore_detail_density": (hardcore_detail_density_choices(), {"default": "balanced"}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = (SXCP_INSTA_OF_OPTIONS,)
|
||||||
|
RETURN_NAMES = ("options_json",)
|
||||||
|
FUNCTION = "build"
|
||||||
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
|
def build(
|
||||||
|
self,
|
||||||
|
softcore_cast,
|
||||||
|
hardcore_cast,
|
||||||
|
hardcore_women_count,
|
||||||
|
hardcore_men_count,
|
||||||
|
softcore_level,
|
||||||
|
hardcore_level,
|
||||||
|
softcore_expression_enabled,
|
||||||
|
hardcore_expression_enabled,
|
||||||
|
softcore_expression_intensity,
|
||||||
|
hardcore_expression_intensity,
|
||||||
|
platform_style,
|
||||||
|
continuity,
|
||||||
|
hardcore_clothing_continuity,
|
||||||
|
softcore_camera_mode,
|
||||||
|
hardcore_camera_mode,
|
||||||
|
camera_detail,
|
||||||
|
hardcore_detail_density,
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
build_insta_of_options_json(
|
||||||
|
softcore_cast=softcore_cast,
|
||||||
|
hardcore_cast=hardcore_cast,
|
||||||
|
hardcore_women_count=hardcore_women_count,
|
||||||
|
hardcore_men_count=hardcore_men_count,
|
||||||
|
softcore_level=softcore_level,
|
||||||
|
hardcore_level=hardcore_level,
|
||||||
|
softcore_expression_enabled=softcore_expression_enabled,
|
||||||
|
hardcore_expression_enabled=hardcore_expression_enabled,
|
||||||
|
softcore_expression_intensity=softcore_expression_intensity,
|
||||||
|
hardcore_expression_intensity=hardcore_expression_intensity,
|
||||||
|
platform_style=platform_style,
|
||||||
|
continuity=continuity,
|
||||||
|
hardcore_clothing_continuity=hardcore_clothing_continuity,
|
||||||
|
softcore_camera_mode=softcore_camera_mode,
|
||||||
|
hardcore_camera_mode=hardcore_camera_mode,
|
||||||
|
camera_detail=camera_detail,
|
||||||
|
hardcore_detail_density=hardcore_detail_density,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPInstaOFPromptPair:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"row_number": ("INT", {"default": 1, "min": 1, "max": 1000000, "step": 1}),
|
||||||
|
"start_index": ("INT", {"default": 41, "min": 1, "max": 1000000, "step": 1}),
|
||||||
|
"seed": ("INT", {"default": 20260614, "min": 0, "max": 0xFFFFFFFF, "step": 1}),
|
||||||
|
"ethnicity": (ethnicity_choices(), {"default": "any"}),
|
||||||
|
"figure": (["random", "curvy", "balanced", "bombshell"], {"default": "random"}),
|
||||||
|
"trigger": ("STRING", {"default": "sxcpinup_coloredpencil"}),
|
||||||
|
"prepend_trigger_to_prompt": ("BOOLEAN", {"default": True}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"seed_config": (SXCP_SEED_CONFIG,),
|
||||||
|
"options_json": (SXCP_INSTA_OF_OPTIONS,),
|
||||||
|
"filter_config": (SXCP_FILTER_CONFIG,),
|
||||||
|
"ethnicity_list": (SXCP_ETHNICITY_LIST,),
|
||||||
|
"camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
|
"softcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
|
"hardcore_camera_config": (SXCP_CAMERA_CONFIG,),
|
||||||
|
"location_config": (SXCP_LOCATION_CONFIG,),
|
||||||
|
"composition_config": (SXCP_COMPOSITION_CONFIG,),
|
||||||
|
"character_profile": (SXCP_CHARACTER_PROFILE,),
|
||||||
|
"character_cast": (SXCP_CHARACTER_CAST,),
|
||||||
|
"hardcore_position_config": (SXCP_HARDCORE_POSITION_CONFIG,),
|
||||||
|
"extra_positive": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
"extra_negative": ("STRING", {"default": "", "multiline": True}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING", "STRING")
|
||||||
|
RETURN_NAMES = (
|
||||||
|
"softcore_prompt",
|
||||||
|
"hardcore_prompt",
|
||||||
|
"softcore_negative_prompt",
|
||||||
|
"hardcore_negative_prompt",
|
||||||
|
"softcore_caption",
|
||||||
|
"hardcore_caption",
|
||||||
|
"shared_descriptor",
|
||||||
|
"metadata_json",
|
||||||
|
)
|
||||||
|
FUNCTION = "build"
|
||||||
|
CATEGORY = "prompt_builder"
|
||||||
|
|
||||||
|
def build(
|
||||||
|
self,
|
||||||
|
row_number,
|
||||||
|
start_index,
|
||||||
|
seed,
|
||||||
|
ethnicity,
|
||||||
|
figure,
|
||||||
|
trigger,
|
||||||
|
prepend_trigger_to_prompt,
|
||||||
|
seed_config="",
|
||||||
|
options_json="",
|
||||||
|
filter_config="",
|
||||||
|
ethnicity_list="",
|
||||||
|
camera_config="",
|
||||||
|
softcore_camera_config="",
|
||||||
|
hardcore_camera_config="",
|
||||||
|
location_config="",
|
||||||
|
composition_config="",
|
||||||
|
character_profile="",
|
||||||
|
character_cast="",
|
||||||
|
hardcore_position_config="",
|
||||||
|
extra_positive="",
|
||||||
|
extra_negative="",
|
||||||
|
no_plus_women=False,
|
||||||
|
no_black=False,
|
||||||
|
):
|
||||||
|
row = build_insta_of_pair(
|
||||||
|
row_number=row_number,
|
||||||
|
start_index=start_index,
|
||||||
|
seed=seed,
|
||||||
|
ethnicity=ethnicity,
|
||||||
|
figure=figure,
|
||||||
|
no_plus_women=no_plus_women,
|
||||||
|
no_black=no_black,
|
||||||
|
trigger=trigger,
|
||||||
|
prepend_trigger_to_prompt=prepend_trigger_to_prompt,
|
||||||
|
seed_config=seed_config or "",
|
||||||
|
options_json=options_json or "",
|
||||||
|
filter_config=ethnicity_list or filter_config or "",
|
||||||
|
camera_config=camera_config or "",
|
||||||
|
softcore_camera_config=softcore_camera_config or "",
|
||||||
|
hardcore_camera_config=hardcore_camera_config or "",
|
||||||
|
location_config=location_config or "",
|
||||||
|
composition_config=composition_config or "",
|
||||||
|
character_profile=character_profile or "",
|
||||||
|
character_cast=character_cast or "",
|
||||||
|
hardcore_position_config=hardcore_position_config or "",
|
||||||
|
extra_positive=extra_positive or "",
|
||||||
|
extra_negative=extra_negative or "",
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
row["softcore_prompt"],
|
||||||
|
row["hardcore_prompt"],
|
||||||
|
row["softcore_negative_prompt"],
|
||||||
|
row["hardcore_negative_prompt"],
|
||||||
|
row["softcore_caption"],
|
||||||
|
row["hardcore_caption"],
|
||||||
|
row["shared_descriptor"],
|
||||||
|
json.dumps(row, ensure_ascii=True, sort_keys=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
NODE_CLASS_MAPPINGS = {
|
||||||
|
"SxCPInstaOFOptions": SxCPInstaOFOptions,
|
||||||
|
"SxCPInstaOFPromptPair": SxCPInstaOFPromptPair,
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
|
"SxCPInstaOFOptions": "SxCP Insta/OF Options",
|
||||||
|
"SxCPInstaOFPromptPair": "SxCP Insta/OF Prompt Pair",
|
||||||
|
}
|
||||||
@@ -2115,6 +2115,60 @@ def smoke_node_formatter_registration() -> None:
|
|||||||
_expect(sdxl_output[6].startswith("text("), "SDXL Formatter method changed unexpectedly")
|
_expect(sdxl_output[6].startswith("text("), "SDXL Formatter method changed unexpectedly")
|
||||||
|
|
||||||
|
|
||||||
|
def smoke_node_insta_registration() -> None:
|
||||||
|
required_nodes = [
|
||||||
|
"SxCPInstaOFOptions",
|
||||||
|
"SxCPInstaOFPromptPair",
|
||||||
|
]
|
||||||
|
for node_name in required_nodes:
|
||||||
|
_expect(node_name in sxcp_nodes.NODE_CLASS_MAPPINGS, f"{node_name} missing from node registry")
|
||||||
|
_expect(node_name in sxcp_nodes.NODE_DISPLAY_NAME_MAPPINGS, f"{node_name} missing from display registry")
|
||||||
|
|
||||||
|
options_node = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPInstaOFOptions"]
|
||||||
|
options_inputs = options_node.INPUT_TYPES().get("required") or {}
|
||||||
|
_expect("hardcore_detail_density" in options_inputs, "Insta/OF Options lost hardcore_detail_density input")
|
||||||
|
_expect("tooltip" in options_inputs["hardcore_detail_density"][1], "Insta/OF Options tooltip injection missing")
|
||||||
|
options_json = options_node().build(
|
||||||
|
"same_as_hardcore",
|
||||||
|
"couple",
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
"lingerie_tease",
|
||||||
|
"hardcore",
|
||||||
|
True,
|
||||||
|
True,
|
||||||
|
0.45,
|
||||||
|
0.85,
|
||||||
|
"hybrid",
|
||||||
|
"same_creator_same_room",
|
||||||
|
"explicit_nude",
|
||||||
|
"standard",
|
||||||
|
"standard",
|
||||||
|
"compact",
|
||||||
|
"balanced",
|
||||||
|
)[0]
|
||||||
|
parsed_options = json.loads(options_json)
|
||||||
|
_expect(parsed_options.get("softcore_cast") == "same_as_hardcore", "Insta/OF Options lost softcore cast")
|
||||||
|
_expect(parsed_options.get("hardcore_cast") == "couple", "Insta/OF Options lost hardcore cast")
|
||||||
|
_expect(parsed_options.get("hardcore_clothing_continuity") == "explicit_nude", "Insta/OF Options lost clothing continuity")
|
||||||
|
|
||||||
|
pair_output = sxcp_nodes.NODE_CLASS_MAPPINGS["SxCPInstaOFPromptPair"]().build(
|
||||||
|
1,
|
||||||
|
41,
|
||||||
|
123,
|
||||||
|
"any",
|
||||||
|
"random",
|
||||||
|
Trigger,
|
||||||
|
True,
|
||||||
|
options_json=options_json,
|
||||||
|
)
|
||||||
|
_expect_text("node_insta.softcore_prompt", pair_output[0], 20)
|
||||||
|
_expect_text("node_insta.hardcore_prompt", pair_output[1], 20)
|
||||||
|
pair = json.loads(pair_output[7])
|
||||||
|
_expect_pair(pair, "node_insta_pair")
|
||||||
|
_expect(pair.get("options", {}).get("hardcore_cast") == "couple", "Insta/OF Prompt Pair lost options metadata")
|
||||||
|
|
||||||
|
|
||||||
def smoke_node_profile_filter_registration() -> None:
|
def smoke_node_profile_filter_registration() -> None:
|
||||||
required_nodes = [
|
required_nodes = [
|
||||||
"SxCPGenerationProfile",
|
"SxCPGenerationProfile",
|
||||||
@@ -2225,6 +2279,7 @@ SMOKE_CASES: list[tuple[str, Callable[[], None]]] = [
|
|||||||
("node_character_registration", smoke_node_character_registration),
|
("node_character_registration", smoke_node_character_registration),
|
||||||
("node_hardcore_position_registration", smoke_node_hardcore_position_registration),
|
("node_hardcore_position_registration", smoke_node_hardcore_position_registration),
|
||||||
("node_formatter_registration", smoke_node_formatter_registration),
|
("node_formatter_registration", smoke_node_formatter_registration),
|
||||||
|
("node_insta_registration", smoke_node_insta_registration),
|
||||||
("node_profile_filter_registration", smoke_node_profile_filter_registration),
|
("node_profile_filter_registration", smoke_node_profile_filter_registration),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user