Spaces:
Sleeping
Sleeping
File size: 6,764 Bytes
b7cb53b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | """
DGG NWN Custom Nodes for ComfyUI
Specialized nodes for Neverwinter Nights character enhancement workflow.
"""
class NWNCharacterEnhancePrompt:
"""
Generate optimized prompts for NWN character enhancement.
Automatically creates prompt/negative prompt pairs based on character archetype.
"""
CHARACTER_PRESETS = {
"paladin_female": {
"base": "female paladin warrior, ornate silver plate armor with golden trim",
"features": "noble elven features, determined expression, flowing hair",
},
"paladin_male": {
"base": "male paladin warrior, heavy plate armor with holy symbols",
"features": "strong jawline, short hair, battle-worn face",
},
"mage_female": {
"base": "female arcane mage, flowing magical robes with arcane patterns",
"features": "intelligent eyes, mysterious aura, elegant features",
},
"mage_male": {
"base": "male wizard, elaborate robes with mystical symbols",
"features": "wise expression, aged features, long beard",
},
"rogue_female": {
"base": "female rogue assassin, dark leather armor with hidden blades",
"features": "cunning eyes, agile build, sharp features",
},
"rogue_male": {
"base": "male thief, practical leather gear with pouches",
"features": "shadowy expression, quick reflexes, scarred face",
},
"warrior_female": {
"base": "female barbarian warrior, fur-lined armor with battle damage",
"features": "fierce expression, muscular build, war paint",
},
"warrior_male": {
"base": "male fighter, practical plate mail with sword and shield",
"features": "battle-hardened face, strong build, short cropped hair",
},
}
QUALITY_SUFFIXES = {
"ultra": "masterpiece, best quality, ultra detailed, 8k uhd, ray tracing, photorealistic",
"high": "high quality, detailed, 4k, professional lighting, realistic",
"medium": "good quality, detailed, sharp focus",
}
NEGATIVE_BASE = "low quality, blurry, pixelated, low poly, cartoonish, anime style, deformed, bad anatomy, extra limbs, watermark, signature, text"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"character_class": (["paladin", "mage", "rogue", "warrior"],),
"gender": (["female", "male"],),
"race": (["human", "elf", "dwarf", "halfling", "half-elf", "half-orc"],),
"quality": (["ultra", "high", "medium"],),
"custom_details": ("STRING", {"default": "", "multiline": True}),
}
}
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("positive_prompt", "negative_prompt")
FUNCTION = "generate_prompt"
CATEGORY = "DGG/NWN"
def generate_prompt(self, character_class, gender, race, quality, custom_details):
# Get preset
preset_key = f"{character_class}_{gender}"
preset = self.CHARACTER_PRESETS.get(preset_key, self.CHARACTER_PRESETS["warrior_male"])
# Build prompt
race_desc = f"{race} " if race != "human" else ""
positive = f"photorealistic {race_desc}{preset['base']}, {preset['features']}"
if custom_details.strip():
positive += f", {custom_details.strip()}"
positive += f", {self.QUALITY_SUFFIXES[quality]}"
negative = self.NEGATIVE_BASE
return (positive, negative)
class NWNImagePreprocess:
"""
Preprocess NWN screenshots for better enhancement results.
- Removes UI elements
- Normalizes lighting
- Isolates character
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
"remove_background": ("BOOLEAN", {"default": True}),
"normalize_lighting": ("BOOLEAN", {"default": True}),
"upscale_first": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "preprocess"
CATEGORY = "DGG/NWN"
def preprocess(self, image, remove_background, normalize_lighting, upscale_first):
import torch
import numpy as np
# Convert to numpy
if isinstance(image, torch.Tensor):
img_np = image.cpu().numpy()
if img_np.ndim == 4:
img_np = img_np[0] # Remove batch dimension
else:
img_np = np.array(image)
# Normalize to 0-1 if needed
if img_np.max() > 1.0:
img_np = img_np / 255.0
if normalize_lighting:
# Simple contrast normalization
for c in range(3):
channel = img_np[:, :, c]
min_val = channel.min()
max_val = channel.max()
if max_val > min_val:
img_np[:, :, c] = (channel - min_val) / (max_val - min_val)
# Convert back to tensor
result = torch.from_numpy(img_np).unsqueeze(0)
return (result,)
class NWNBatchProcessor:
"""
Process multiple NWN character images in batch.
Useful for generating front/side/back views consistently.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"prompt_template": ("STRING", {"default": "photorealistic fantasy character, {view} view"}),
"views": ("STRING", {"default": "front,side,back"}),
}
}
RETURN_TYPES = ("IMAGE", "STRING")
RETURN_NAMES = ("images", "view_prompts")
FUNCTION = "process_batch"
CATEGORY = "DGG/NWN"
def process_batch(self, images, prompt_template, views):
view_list = [v.strip() for v in views.split(",")]
prompts = [prompt_template.format(view=v) for v in view_list]
return (images, "\n".join(prompts))
# Node mappings for ComfyUI
NODE_CLASS_MAPPINGS = {
"NWNCharacterEnhancePrompt": NWNCharacterEnhancePrompt,
"NWNImagePreprocess": NWNImagePreprocess,
"NWNBatchProcessor": NWNBatchProcessor,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"NWNCharacterEnhancePrompt": "🎮 NWN Character Prompt",
"NWNImagePreprocess": "🎮 NWN Image Preprocess",
"NWNBatchProcessor": "🎮 NWN Batch Processor",
}
|