Add SDXL bucket size node
This commit is contained in:
@@ -9,6 +9,7 @@ The node is registered as:
|
|||||||
- `prompt_builder / SxCP Global Seed`
|
- `prompt_builder / SxCP Global Seed`
|
||||||
- `prompt_builder / SxCP Seed Control`
|
- `prompt_builder / SxCP Seed Control`
|
||||||
- `prompt_builder / SxCP Seed Locker`
|
- `prompt_builder / SxCP Seed Locker`
|
||||||
|
- `prompt_builder / util / SxCP SDXL Bucket Size`
|
||||||
- `prompt_builder / SxCP Camera Control`
|
- `prompt_builder / SxCP Camera Control`
|
||||||
- `prompt_builder / SxCP Camera Orbit Control`
|
- `prompt_builder / SxCP Camera Orbit Control`
|
||||||
- `prompt_builder / SxCP Qwen Camera Translator`
|
- `prompt_builder / SxCP Qwen Camera Translator`
|
||||||
@@ -309,6 +310,13 @@ you like, choose one `reroll_axis`, and connect its `seed_config`. All other
|
|||||||
axes stay frozen to `base_seed`; the rerolled axis follows `reroll_seed`, or the
|
axes stay frozen to `base_seed`; the rerolled axis follows `reroll_seed`, or the
|
||||||
main prompt seed when `reroll_seed=-1`.
|
main prompt seed when `reroll_seed=-1`.
|
||||||
|
|
||||||
|
`SxCP SDXL Bucket Size` randomly selects one of the built-in SDXL bucket
|
||||||
|
resolutions and outputs `width`, `height`, and a `resolution` string. Use
|
||||||
|
`orientation` to restrict the pool to portrait, square, or landscape. Leave
|
||||||
|
`bucket_index=0` for random selection, or set `bucket_index` to pick a specific
|
||||||
|
position inside the filtered pool. Connect `SxCP Global Seed` or Seed Locker's
|
||||||
|
`seed_config` when the bucket choice must be reproducible.
|
||||||
|
|
||||||
`SxCP Camera Control` and `SxCP Camera Orbit Control` output `camera_config`,
|
`SxCP Camera Control` and `SxCP Camera Orbit Control` output `camera_config`,
|
||||||
which can be connected to the prompt builder or the Insta/OF pair node. They
|
which can be connected to the prompt builder or the Insta/OF pair node. They
|
||||||
make camera/framing first-class instead of relying on a weak phrase inside the
|
make camera/framing first-class instead of relying on a weak phrase inside the
|
||||||
|
|||||||
+123
@@ -27,6 +27,20 @@ SXCP_CHARACTER_CAST = "SXCP_CHARACTER_CAST"
|
|||||||
SXCP_CHARACTER_SLOT = "SXCP_CHARACTER_SLOT"
|
SXCP_CHARACTER_SLOT = "SXCP_CHARACTER_SLOT"
|
||||||
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
SXCP_CHARACTER_PROFILE = "SXCP_CHARACTER_PROFILE"
|
||||||
|
|
||||||
|
SDXL_BUCKET_RESOLUTIONS = [
|
||||||
|
{"orientation": "portrait", "width": 896, "height": 1792, "aspect": 0.50, "mp": 1.61},
|
||||||
|
{"orientation": "portrait", "width": 960, "height": 1664, "aspect": 0.58, "mp": 1.60},
|
||||||
|
{"orientation": "portrait", "width": 1024, "height": 1600, "aspect": 0.64, "mp": 1.64},
|
||||||
|
{"orientation": "portrait", "width": 1088, "height": 1472, "aspect": 0.74, "mp": 1.60},
|
||||||
|
{"orientation": "portrait", "width": 1152, "height": 1408, "aspect": 0.82, "mp": 1.62},
|
||||||
|
{"orientation": "portrait", "width": 1216, "height": 1344, "aspect": 0.90, "mp": 1.63},
|
||||||
|
{"orientation": "square", "width": 1280, "height": 1280, "aspect": 1.00, "mp": 1.64},
|
||||||
|
{"orientation": "landscape", "width": 1344, "height": 1216, "aspect": 1.11, "mp": 1.63},
|
||||||
|
{"orientation": "landscape", "width": 1408, "height": 1152, "aspect": 1.22, "mp": 1.62},
|
||||||
|
{"orientation": "landscape", "width": 1472, "height": 1088, "aspect": 1.35, "mp": 1.60},
|
||||||
|
{"orientation": "landscape", "width": 1536, "height": 1024, "aspect": 1.50, "mp": 1.57},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
COMMON_INPUT_TOOLTIPS = {
|
COMMON_INPUT_TOOLTIPS = {
|
||||||
"row_number": "Generation row to use. Changing it advances the deterministic selection without changing the main seed.",
|
"row_number": "Generation row to use. Changing it advances the deterministic selection without changing the main seed.",
|
||||||
@@ -63,6 +77,8 @@ COMMON_INPUT_TOOLTIPS = {
|
|||||||
"extra_negative": "Extra negative text appended after the generated negative prompt.",
|
"extra_negative": "Extra negative text appended after the generated negative prompt.",
|
||||||
"trigger": "Training or style trigger token.",
|
"trigger": "Training or style trigger token.",
|
||||||
"prepend_trigger_to_prompt": "If enabled, put the trigger token at the start of generated prompts.",
|
"prepend_trigger_to_prompt": "If enabled, put the trigger token at the start of generated prompts.",
|
||||||
|
"bucket_index": "0 picks a random bucket. 1+ picks that position inside the selected orientation pool.",
|
||||||
|
"megapixels": "Approximate megapixel count for the selected bucket.",
|
||||||
"enabled": "Enable this node's effect while keeping it wired in the graph.",
|
"enabled": "Enable this node's effect while keeping it wired in the graph.",
|
||||||
"combine_mode": "replace starts a new pool/config; add merges selected values into the incoming config.",
|
"combine_mode": "replace starts a new pool/config; add merges selected values into the incoming config.",
|
||||||
"manual": "Manual character details config. Non-empty manual fields override generated slot details.",
|
"manual": "Manual character details config. Non-empty manual fields override generated slot details.",
|
||||||
@@ -187,6 +203,13 @@ NODE_INPUT_TOOLTIPS = {
|
|||||||
"SxCPSeedLocker": {
|
"SxCPSeedLocker": {
|
||||||
"reroll_axis": "Choose the one axis to change while the rest stays locked. Use pose for sexual pose, scene for location, person for appearance.",
|
"reroll_axis": "Choose the one axis to change while the rest stays locked. Use pose for sexual pose, scene for location, person for appearance.",
|
||||||
},
|
},
|
||||||
|
"SxCPSDXLBucketSize": {
|
||||||
|
"orientation": "Bucket orientation filter. any uses the full table; portrait/square/landscape restrict random selection.",
|
||||||
|
"seed": "Fixed bucket seed. Use -1 for a fresh random bucket each queue, or connect Global Seed for reproducible sizes.",
|
||||||
|
"row_number": "Deterministic row offset for the bucket. With a fixed seed, changing this advances the bucket choice.",
|
||||||
|
"bucket_index": "0=random. 1+ selects that bucket position inside the selected orientation pool and ignores seed.",
|
||||||
|
"seed_config": "Optional seed config. The composition seed controls bucket choice, so Seed Locker can keep sizes fixed while rerolling pose/person.",
|
||||||
|
},
|
||||||
"SxCPCameraControl": {
|
"SxCPCameraControl": {
|
||||||
"camera_mode": "Camera style preset. Use from_camera_config in Insta/OF options to consume this.",
|
"camera_mode": "Camera style preset. Use from_camera_config in Insta/OF options to consume this.",
|
||||||
"priority": "locked makes the camera wording strict; soft_hint allows the model more freedom.",
|
"priority": "locked makes the camera wording strict; soft_hint allows the model more freedom.",
|
||||||
@@ -817,6 +840,104 @@ class SxCPSeedLocker:
|
|||||||
return config, summary
|
return config, summary
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPSDXLBucketSize:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"orientation": (["any", "portrait", "square", "landscape"], {"default": "any"}),
|
||||||
|
"seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF, "step": 1}),
|
||||||
|
"row_number": ("INT", {"default": 1, "min": 1, "max": 1000000, "step": 1}),
|
||||||
|
"bucket_index": ("INT", {"default": 0, "min": 0, "max": len(SDXL_BUCKET_RESOLUTIONS), "step": 1}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"seed_config": (SXCP_SEED_CONFIG,),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("INT", "INT", "STRING", "STRING", "FLOAT", "FLOAT", "INT", "STRING")
|
||||||
|
RETURN_NAMES = ("width", "height", "resolution", "orientation", "aspect", "megapixels", "bucket_index", "summary")
|
||||||
|
FUNCTION = "build"
|
||||||
|
CATEGORY = "prompt_builder/util"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _configured_bucket_seed(seed_config):
|
||||||
|
if not seed_config:
|
||||||
|
return None
|
||||||
|
if isinstance(seed_config, dict):
|
||||||
|
raw = seed_config
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
raw = json.loads(str(seed_config))
|
||||||
|
except (TypeError, ValueError, json.JSONDecodeError):
|
||||||
|
return None
|
||||||
|
if not isinstance(raw, dict):
|
||||||
|
return None
|
||||||
|
for key in ("composition_seed", "content_seed", "seed", "global_seed"):
|
||||||
|
try:
|
||||||
|
value = int(raw.get(key))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
continue
|
||||||
|
if value >= 0:
|
||||||
|
return value
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def IS_CHANGED(cls, *args, **kwargs):
|
||||||
|
seed_value = kwargs.get("seed")
|
||||||
|
if seed_value is None and len(args) > 1:
|
||||||
|
seed_value = args[1]
|
||||||
|
bucket_index = kwargs.get("bucket_index")
|
||||||
|
if bucket_index is None and len(args) > 3:
|
||||||
|
bucket_index = args[3]
|
||||||
|
seed_config = kwargs.get("seed_config", "")
|
||||||
|
if not seed_config and len(args) > 4:
|
||||||
|
seed_config = args[4]
|
||||||
|
try:
|
||||||
|
seed = int(seed_value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
seed = -1
|
||||||
|
try:
|
||||||
|
index = int(bucket_index)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
index = 0
|
||||||
|
if index <= 0 and seed < 0 and cls._configured_bucket_seed(seed_config) is None:
|
||||||
|
return random.random()
|
||||||
|
return tuple(args), tuple(sorted(kwargs.items()))
|
||||||
|
|
||||||
|
def build(self, orientation, seed, row_number, bucket_index, seed_config=""):
|
||||||
|
orientation = str(orientation or "any").strip().lower()
|
||||||
|
pool = [
|
||||||
|
(index + 1, bucket)
|
||||||
|
for index, bucket in enumerate(SDXL_BUCKET_RESOLUTIONS)
|
||||||
|
if orientation == "any" or bucket["orientation"] == orientation
|
||||||
|
]
|
||||||
|
if not pool:
|
||||||
|
pool = list(enumerate(SDXL_BUCKET_RESOLUTIONS, start=1))
|
||||||
|
if int(bucket_index) > 0:
|
||||||
|
pool_position = max(1, min(len(pool), int(bucket_index))) - 1
|
||||||
|
else:
|
||||||
|
configured_seed = self._configured_bucket_seed(seed_config)
|
||||||
|
if configured_seed is None and int(seed) < 0:
|
||||||
|
rng = random.Random(random.getrandbits(64))
|
||||||
|
else:
|
||||||
|
bucket_seed = configured_seed if configured_seed is not None else int(seed)
|
||||||
|
rng = random.Random(f"sdxl_bucket:{bucket_seed}:{int(row_number)}:{orientation}")
|
||||||
|
pool_position = rng.randrange(len(pool))
|
||||||
|
selected_index, selected = pool[pool_position]
|
||||||
|
width = int(selected["width"])
|
||||||
|
height = int(selected["height"])
|
||||||
|
selected_orientation = str(selected["orientation"])
|
||||||
|
aspect = float(selected["aspect"])
|
||||||
|
mp = float(selected["mp"])
|
||||||
|
resolution = f"{width}x{height}"
|
||||||
|
summary = (
|
||||||
|
f"{selected_orientation} bucket {pool_position + 1}/{len(pool)} "
|
||||||
|
f"(table {selected_index}): {resolution}, aspect {aspect:.2f}, {mp:.2f} MP"
|
||||||
|
)
|
||||||
|
return width, height, resolution, selected_orientation, aspect, mp, selected_index, summary
|
||||||
|
|
||||||
|
|
||||||
class SxCPCameraControl:
|
class SxCPCameraControl:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -2475,6 +2596,7 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"SxCPGlobalSeed": SxCPGlobalSeed,
|
"SxCPGlobalSeed": SxCPGlobalSeed,
|
||||||
"SxCPSeedControl": SxCPSeedControl,
|
"SxCPSeedControl": SxCPSeedControl,
|
||||||
"SxCPSeedLocker": SxCPSeedLocker,
|
"SxCPSeedLocker": SxCPSeedLocker,
|
||||||
|
"SxCPSDXLBucketSize": SxCPSDXLBucketSize,
|
||||||
"SxCPCameraControl": SxCPCameraControl,
|
"SxCPCameraControl": SxCPCameraControl,
|
||||||
"SxCPCameraOrbitControl": SxCPCameraOrbitControl,
|
"SxCPCameraOrbitControl": SxCPCameraOrbitControl,
|
||||||
"SxCPQwenCameraTranslator": SxCPQwenCameraTranslator,
|
"SxCPQwenCameraTranslator": SxCPQwenCameraTranslator,
|
||||||
@@ -2515,6 +2637,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"SxCPGlobalSeed": "SxCP Global Seed",
|
"SxCPGlobalSeed": "SxCP Global Seed",
|
||||||
"SxCPSeedControl": "SxCP Seed Control",
|
"SxCPSeedControl": "SxCP Seed Control",
|
||||||
"SxCPSeedLocker": "SxCP Seed Locker",
|
"SxCPSeedLocker": "SxCP Seed Locker",
|
||||||
|
"SxCPSDXLBucketSize": "SxCP SDXL Bucket Size",
|
||||||
"SxCPCameraControl": "SxCP Camera Control",
|
"SxCPCameraControl": "SxCP Camera Control",
|
||||||
"SxCPCameraOrbitControl": "SxCP Camera Orbit Control",
|
"SxCPCameraOrbitControl": "SxCP Camera Orbit Control",
|
||||||
"SxCPQwenCameraTranslator": "SxCP Qwen Camera Translator",
|
"SxCPQwenCameraTranslator": "SxCP Qwen Camera Translator",
|
||||||
|
|||||||
Reference in New Issue
Block a user