Add Krea2 resolution selector
This commit is contained in:
@@ -349,6 +349,16 @@ resolutions and outputs `width`, `height`, and a `resolution` string. Use
|
|||||||
position inside the filtered pool. Connect `SxCP Global Seed` or Seed Locker's
|
position inside the filtered pool. Connect `SxCP Global Seed` or Seed Locker's
|
||||||
`seed_config` when the bucket choice must be reproducible.
|
`seed_config` when the bucket choice must be reproducible.
|
||||||
|
|
||||||
|
`SxCP Krea2 Resolution Selector` outputs model-friendly `width`, `height`,
|
||||||
|
`resolution`, aspect ratio, megapixel, and hosted API fields for Krea2. Use
|
||||||
|
`profile=turbo_local_2k` for local Turbo generation up to a 2K long edge, or
|
||||||
|
`profile=raw_local_1k` for RAW/local 1K limits. `profile=api_hosted_1k` keeps
|
||||||
|
the official API fields visible: `api_aspect_ratio` and `api_resolution=1K`.
|
||||||
|
The node searches for the best multiple-of-16 size for the selected aspect ratio
|
||||||
|
and megapixel preset, then clamps to the selected profile's limit. Use
|
||||||
|
`max_for_aspect` to get the highest valid size for that aspect ratio, or
|
||||||
|
`random_1_to_limit` with a seed config for reproducible random sizes.
|
||||||
|
|
||||||
`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
|
||||||
|
|||||||
+323
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -43,6 +44,27 @@ SDXL_BUCKET_RESOLUTIONS = [
|
|||||||
{"orientation": "landscape", "width": 1536, "height": 1024, "aspect": 1.50, "mp": 1.57},
|
{"orientation": "landscape", "width": 1536, "height": 1024, "aspect": 1.50, "mp": 1.57},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
KREA2_API_ASPECT_RATIOS = ["1:1", "4:3", "3:2", "16:9", "2.35:1", "4:5", "2:3", "9:16"]
|
||||||
|
KREA2_ASPECT_RATIOS = KREA2_API_ASPECT_RATIOS + ["21:9", "9:21", "3:1", "1:3", "custom", "random_api"]
|
||||||
|
KREA2_MEGAPIXEL_PRESETS = [
|
||||||
|
"max_for_aspect",
|
||||||
|
"random_1_to_limit",
|
||||||
|
"1.0MP",
|
||||||
|
"1.25MP",
|
||||||
|
"1.5MP",
|
||||||
|
"1.75MP",
|
||||||
|
"2.0MP",
|
||||||
|
"2.25MP",
|
||||||
|
"2.5MP",
|
||||||
|
"2.75MP",
|
||||||
|
"3.0MP",
|
||||||
|
"3.25MP",
|
||||||
|
"3.5MP",
|
||||||
|
"3.75MP",
|
||||||
|
"4.0MP",
|
||||||
|
"custom",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
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.",
|
||||||
@@ -236,6 +258,17 @@ NODE_INPUT_TOOLTIPS = {
|
|||||||
"bucket_index": "0=random. 1+ selects that bucket position inside the selected orientation pool and ignores seed.",
|
"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.",
|
"seed_config": "Optional seed config. The composition seed controls bucket choice, so Seed Locker can keep sizes fixed while rerolling pose/person.",
|
||||||
},
|
},
|
||||||
|
"SxCPKrea2ResolutionSelector": {
|
||||||
|
"profile": "api_hosted_1k returns official API fields; raw_local_1k and turbo_local_2k return explicit ComfyUI width/height under known local limits.",
|
||||||
|
"aspect_ratio": "Official Krea API ratios are listed first. custom uses custom_aspect_width/custom_aspect_height; random_api chooses from official ratios.",
|
||||||
|
"megapixel_preset": "Pick a target megapixel count, max_for_aspect, random_1_to_limit, or custom_megapixels.",
|
||||||
|
"round_to": "Krea2 local inference pads to multiples of 16; 32/64 are stricter bucket-friendly choices.",
|
||||||
|
"custom_max_long_edge": "Only used by custom_limit. Local Turbo documentation uses 2048 as the 2K upper edge.",
|
||||||
|
"custom_max_megapixels": "Only used by custom_limit. The selector still respects custom_max_long_edge.",
|
||||||
|
"seed": "Used only for random_api or random_1_to_limit. Connect Seed Config for deterministic workflow-wide randomness.",
|
||||||
|
"row_number": "Deterministic row offset for random ratio/megapixel choices.",
|
||||||
|
"seed_config": "Optional seed config. The composition seed controls resolution choices when connected.",
|
||||||
|
},
|
||||||
"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.",
|
||||||
@@ -1001,6 +1034,294 @@ class SxCPSDXLBucketSize:
|
|||||||
return width, height, resolution, selected_orientation, aspect, mp, selected_index, summary
|
return width, height, resolution, selected_orientation, aspect, mp, selected_index, summary
|
||||||
|
|
||||||
|
|
||||||
|
class SxCPKrea2ResolutionSelector:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"profile": (
|
||||||
|
["turbo_local_2k", "raw_local_1k", "api_hosted_1k", "custom_limit"],
|
||||||
|
{"default": "turbo_local_2k"},
|
||||||
|
),
|
||||||
|
"aspect_ratio": (KREA2_ASPECT_RATIOS, {"default": "1:1"}),
|
||||||
|
"megapixel_preset": (KREA2_MEGAPIXEL_PRESETS, {"default": "1.0MP"}),
|
||||||
|
"custom_megapixels": ("FLOAT", {"default": 1.0, "min": 0.10, "max": 16.0, "step": 0.05}),
|
||||||
|
"round_to": (["16", "32", "64"], {"default": "16"}),
|
||||||
|
"custom_aspect_width": ("FLOAT", {"default": 1.0, "min": 0.10, "max": 100.0, "step": 0.05}),
|
||||||
|
"custom_aspect_height": ("FLOAT", {"default": 1.0, "min": 0.10, "max": 100.0, "step": 0.05}),
|
||||||
|
"custom_max_long_edge": ("INT", {"default": 2048, "min": 256, "max": 8192, "step": 16}),
|
||||||
|
"custom_max_megapixels": ("FLOAT", {"default": 4.20, "min": 0.10, "max": 64.0, "step": 0.05}),
|
||||||
|
"seed": ("INT", {"default": -1, "min": -1, "max": 0xFFFFFFFF, "step": 1}),
|
||||||
|
"row_number": ("INT", {"default": 1, "min": 1, "max": 1000000, "step": 1}),
|
||||||
|
},
|
||||||
|
"optional": {
|
||||||
|
"seed_config": (SXCP_SEED_CONFIG,),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("INT", "INT", "STRING", "STRING", "STRING", "STRING", "FLOAT", "FLOAT", "STRING", "STRING", "STRING")
|
||||||
|
RETURN_NAMES = (
|
||||||
|
"width",
|
||||||
|
"height",
|
||||||
|
"resolution",
|
||||||
|
"aspect_ratio",
|
||||||
|
"api_aspect_ratio",
|
||||||
|
"api_resolution",
|
||||||
|
"megapixels",
|
||||||
|
"max_megapixels_for_aspect",
|
||||||
|
"orientation",
|
||||||
|
"summary",
|
||||||
|
"config_json",
|
||||||
|
)
|
||||||
|
FUNCTION = "select"
|
||||||
|
CATEGORY = "prompt_builder/util"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _configured_seed(seed_config):
|
||||||
|
return SxCPSDXLBucketSize._configured_bucket_seed(seed_config)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _aspect_value(aspect_ratio, custom_aspect_width, custom_aspect_height, rng):
|
||||||
|
selected = str(aspect_ratio or "1:1").strip()
|
||||||
|
if selected == "random_api":
|
||||||
|
selected = rng.choice(KREA2_API_ASPECT_RATIOS)
|
||||||
|
if selected == "custom":
|
||||||
|
width = max(0.1, float(custom_aspect_width))
|
||||||
|
height = max(0.1, float(custom_aspect_height))
|
||||||
|
return selected, width / height
|
||||||
|
try:
|
||||||
|
left, right = selected.split(":", 1)
|
||||||
|
return selected, max(0.01, float(left) / float(right))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return "1:1", 1.0
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _closest_api_aspect(ratio):
|
||||||
|
def parse(value):
|
||||||
|
left, right = value.split(":", 1)
|
||||||
|
return float(left) / float(right)
|
||||||
|
|
||||||
|
return min(KREA2_API_ASPECT_RATIOS, key=lambda item: abs(math.log(parse(item) / max(0.01, ratio))))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _continuous_limit_mp(ratio, max_long_edge, max_megapixels):
|
||||||
|
ratio = max(0.01, float(ratio))
|
||||||
|
max_long = max(16.0, float(max_long_edge))
|
||||||
|
if ratio >= 1.0:
|
||||||
|
exact_width = max_long
|
||||||
|
exact_height = max_long / ratio
|
||||||
|
else:
|
||||||
|
exact_width = max_long * ratio
|
||||||
|
exact_height = max_long
|
||||||
|
exact_mp = (exact_width * exact_height) / 1_000_000.0
|
||||||
|
return max(0.01, min(float(max_megapixels), exact_mp))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _nearby_multiples(value, multiple):
|
||||||
|
scaled = float(value) / float(multiple)
|
||||||
|
values = {
|
||||||
|
int(math.floor(scaled)) * multiple,
|
||||||
|
int(round(scaled)) * multiple,
|
||||||
|
int(math.ceil(scaled)) * multiple,
|
||||||
|
}
|
||||||
|
return {int(v) for v in values if int(v) > 0}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _candidate_sizes(cls, ratio, max_long_edge, max_megapixels, multiple):
|
||||||
|
max_long = max(multiple, int(max_long_edge) // multiple * multiple)
|
||||||
|
max_pixels = float(max_megapixels) * 1_000_000.0
|
||||||
|
candidates = set()
|
||||||
|
for width in range(multiple, max_long + 1, multiple):
|
||||||
|
for height in cls._nearby_multiples(float(width) / ratio, multiple):
|
||||||
|
candidates.add((width, height))
|
||||||
|
for height in range(multiple, max_long + 1, multiple):
|
||||||
|
for width in cls._nearby_multiples(float(height) * ratio, multiple):
|
||||||
|
candidates.add((width, height))
|
||||||
|
valid = []
|
||||||
|
for width, height in candidates:
|
||||||
|
if width < multiple or height < multiple:
|
||||||
|
continue
|
||||||
|
if max(width, height) > max_long:
|
||||||
|
continue
|
||||||
|
if width * height > max_pixels + 1:
|
||||||
|
continue
|
||||||
|
valid.append((width, height))
|
||||||
|
return valid
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _best_size(cls, ratio, target_megapixels, max_long_edge, max_megapixels, multiple):
|
||||||
|
candidates = cls._candidate_sizes(ratio, max_long_edge, max_megapixels, multiple)
|
||||||
|
if not candidates:
|
||||||
|
fallback = max(multiple, int(max_long_edge) // multiple * multiple)
|
||||||
|
return fallback, fallback, (fallback * fallback) / 1_000_000.0, 1.0
|
||||||
|
target = max((multiple * multiple) / 1_000_000.0, float(target_megapixels))
|
||||||
|
best = None
|
||||||
|
best_score = None
|
||||||
|
for width, height in candidates:
|
||||||
|
actual_mp = (width * height) / 1_000_000.0
|
||||||
|
actual_ratio = float(width) / float(height)
|
||||||
|
ratio_error = abs(math.log(actual_ratio / max(0.01, ratio)))
|
||||||
|
mp_error = abs(actual_mp - target) / max(target, 0.01)
|
||||||
|
score = ratio_error * 4.0 + mp_error
|
||||||
|
if best_score is None or score < best_score:
|
||||||
|
best = (width, height, actual_mp, actual_ratio)
|
||||||
|
best_score = score
|
||||||
|
return best
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _profile_limits(profile, custom_max_long_edge, custom_max_megapixels):
|
||||||
|
profile = str(profile or "turbo_local_2k").strip()
|
||||||
|
if profile == "raw_local_1k":
|
||||||
|
return 1024, 1.05, "Krea2 RAW local explicit size, up to 1K"
|
||||||
|
if profile == "api_hosted_1k":
|
||||||
|
return 1024, 1.05, "Krea hosted API fields, 1K only"
|
||||||
|
if profile == "custom_limit":
|
||||||
|
return max(256, int(custom_max_long_edge)), max(0.10, float(custom_max_megapixels)), "custom explicit size limit"
|
||||||
|
return 2048, 4.20, "Krea2 Turbo local explicit size, up to 2K"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _preset_megapixels(megapixel_preset):
|
||||||
|
value = str(megapixel_preset or "1.0MP").strip()
|
||||||
|
if value.endswith("MP"):
|
||||||
|
try:
|
||||||
|
return float(value[:-2])
|
||||||
|
except ValueError:
|
||||||
|
return 1.0
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def IS_CHANGED(cls, *args, **kwargs):
|
||||||
|
aspect_ratio = kwargs.get("aspect_ratio")
|
||||||
|
if aspect_ratio is None and len(args) > 1:
|
||||||
|
aspect_ratio = args[1]
|
||||||
|
megapixel_preset = kwargs.get("megapixel_preset")
|
||||||
|
if megapixel_preset is None and len(args) > 2:
|
||||||
|
megapixel_preset = args[2]
|
||||||
|
seed_value = kwargs.get("seed")
|
||||||
|
if seed_value is None and len(args) > 9:
|
||||||
|
seed_value = args[9]
|
||||||
|
seed_config = kwargs.get("seed_config", "")
|
||||||
|
if not seed_config and len(args) > 11:
|
||||||
|
seed_config = args[11]
|
||||||
|
try:
|
||||||
|
seed = int(seed_value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
seed = -1
|
||||||
|
uses_random = str(aspect_ratio) == "random_api" or str(megapixel_preset) == "random_1_to_limit"
|
||||||
|
if uses_random and seed < 0 and cls._configured_seed(seed_config) is None:
|
||||||
|
return random.random()
|
||||||
|
return tuple(args), tuple(sorted(kwargs.items()))
|
||||||
|
|
||||||
|
def select(
|
||||||
|
self,
|
||||||
|
profile,
|
||||||
|
aspect_ratio,
|
||||||
|
megapixel_preset,
|
||||||
|
custom_megapixels,
|
||||||
|
round_to,
|
||||||
|
custom_aspect_width,
|
||||||
|
custom_aspect_height,
|
||||||
|
custom_max_long_edge,
|
||||||
|
custom_max_megapixels,
|
||||||
|
seed,
|
||||||
|
row_number,
|
||||||
|
seed_config="",
|
||||||
|
):
|
||||||
|
configured_seed = self._configured_seed(seed_config)
|
||||||
|
if configured_seed is None and int(seed) < 0:
|
||||||
|
rng = random.Random(random.getrandbits(64))
|
||||||
|
seed_label = "fresh"
|
||||||
|
else:
|
||||||
|
selected_seed = configured_seed if configured_seed is not None else int(seed)
|
||||||
|
rng = random.Random(f"krea2_resolution:{selected_seed}:{int(row_number)}")
|
||||||
|
seed_label = str(selected_seed)
|
||||||
|
|
||||||
|
multiple = int(round_to) if str(round_to).isdigit() else 16
|
||||||
|
max_long_edge, max_profile_mp, profile_label = self._profile_limits(profile, custom_max_long_edge, custom_max_megapixels)
|
||||||
|
resolved_aspect, ratio = self._aspect_value(aspect_ratio, custom_aspect_width, custom_aspect_height, rng)
|
||||||
|
api_aspect_ratio = resolved_aspect if resolved_aspect in KREA2_API_ASPECT_RATIOS else self._closest_api_aspect(ratio)
|
||||||
|
|
||||||
|
continuous_max_mp = self._continuous_limit_mp(ratio, max_long_edge, max_profile_mp)
|
||||||
|
max_width, max_height, max_actual_mp, max_actual_ratio = self._best_size(
|
||||||
|
ratio, continuous_max_mp, max_long_edge, max_profile_mp, multiple
|
||||||
|
)
|
||||||
|
|
||||||
|
preset = str(megapixel_preset or "1.0MP").strip()
|
||||||
|
target_mp = self._preset_megapixels(preset)
|
||||||
|
if preset == "custom":
|
||||||
|
target_mp = max(0.10, float(custom_megapixels))
|
||||||
|
elif preset == "max_for_aspect":
|
||||||
|
target_mp = max_actual_mp
|
||||||
|
elif preset == "random_1_to_limit":
|
||||||
|
available = [self._preset_megapixels(value) for value in KREA2_MEGAPIXEL_PRESETS if value.endswith("MP")]
|
||||||
|
available = [value for value in available if value is not None and 1.0 <= value <= max_actual_mp + 0.001]
|
||||||
|
if not available:
|
||||||
|
target_mp = max_actual_mp
|
||||||
|
else:
|
||||||
|
target_mp = rng.choice(available)
|
||||||
|
if target_mp is None:
|
||||||
|
target_mp = 1.0
|
||||||
|
|
||||||
|
clamped = target_mp > max_actual_mp + 0.001
|
||||||
|
effective_target_mp = min(float(target_mp), max_actual_mp)
|
||||||
|
width, height, actual_mp, actual_ratio = self._best_size(
|
||||||
|
ratio, effective_target_mp, max_long_edge, max_profile_mp, multiple
|
||||||
|
)
|
||||||
|
orientation = "square"
|
||||||
|
if width > height:
|
||||||
|
orientation = "landscape"
|
||||||
|
elif height > width:
|
||||||
|
orientation = "portrait"
|
||||||
|
|
||||||
|
resolution = f"{width}x{height}"
|
||||||
|
api_resolution = "1K"
|
||||||
|
summary_parts = [
|
||||||
|
f"{profile_label}",
|
||||||
|
f"{resolution}",
|
||||||
|
f"{actual_mp:.2f} MP",
|
||||||
|
f"aspect {resolved_aspect} ({actual_ratio:.3f})",
|
||||||
|
f"max for aspect {max_width}x{max_height} / {max_actual_mp:.2f} MP",
|
||||||
|
f"API {api_aspect_ratio} {api_resolution}",
|
||||||
|
]
|
||||||
|
if clamped:
|
||||||
|
summary_parts.append(f"target {target_mp:.2f} MP clamped to aspect/profile limit")
|
||||||
|
if preset.startswith("random") or resolved_aspect == "random_api":
|
||||||
|
summary_parts.append(f"seed {seed_label}, row {int(row_number)}")
|
||||||
|
summary = "; ".join(summary_parts)
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"profile": profile,
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
"resolution": resolution,
|
||||||
|
"aspect_ratio": resolved_aspect,
|
||||||
|
"aspect_ratio_value": actual_ratio,
|
||||||
|
"target_megapixels": round(float(target_mp), 4),
|
||||||
|
"megapixels": round(actual_mp, 4),
|
||||||
|
"max_width_for_aspect": max_width,
|
||||||
|
"max_height_for_aspect": max_height,
|
||||||
|
"max_megapixels_for_aspect": round(max_actual_mp, 4),
|
||||||
|
"api_aspect_ratio": api_aspect_ratio,
|
||||||
|
"api_resolution": api_resolution,
|
||||||
|
"orientation": orientation,
|
||||||
|
"round_to": multiple,
|
||||||
|
"clamped": clamped,
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
resolution,
|
||||||
|
resolved_aspect,
|
||||||
|
api_aspect_ratio,
|
||||||
|
api_resolution,
|
||||||
|
round(actual_mp, 4),
|
||||||
|
round(max_actual_mp, 4),
|
||||||
|
orientation,
|
||||||
|
summary,
|
||||||
|
json.dumps(config, ensure_ascii=True, sort_keys=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SxCPCameraControl:
|
class SxCPCameraControl:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -2914,6 +3235,7 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"SxCPSeedControl": SxCPSeedControl,
|
"SxCPSeedControl": SxCPSeedControl,
|
||||||
"SxCPSeedLocker": SxCPSeedLocker,
|
"SxCPSeedLocker": SxCPSeedLocker,
|
||||||
"SxCPSDXLBucketSize": SxCPSDXLBucketSize,
|
"SxCPSDXLBucketSize": SxCPSDXLBucketSize,
|
||||||
|
"SxCPKrea2ResolutionSelector": SxCPKrea2ResolutionSelector,
|
||||||
"SxCPCameraControl": SxCPCameraControl,
|
"SxCPCameraControl": SxCPCameraControl,
|
||||||
"SxCPCameraOrbitControl": SxCPCameraOrbitControl,
|
"SxCPCameraOrbitControl": SxCPCameraOrbitControl,
|
||||||
"SxCPQwenCameraTranslator": SxCPQwenCameraTranslator,
|
"SxCPQwenCameraTranslator": SxCPQwenCameraTranslator,
|
||||||
@@ -2959,6 +3281,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"SxCPSeedControl": "SxCP Seed Control",
|
"SxCPSeedControl": "SxCP Seed Control",
|
||||||
"SxCPSeedLocker": "SxCP Seed Locker",
|
"SxCPSeedLocker": "SxCP Seed Locker",
|
||||||
"SxCPSDXLBucketSize": "SxCP SDXL Bucket Size",
|
"SxCPSDXLBucketSize": "SxCP SDXL Bucket Size",
|
||||||
|
"SxCPKrea2ResolutionSelector": "SxCP Krea2 Resolution Selector",
|
||||||
"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