Added support for watermark, and regionalPrompt
This commit is contained in:
+7
-1
@@ -26,6 +26,9 @@ from .modules.vaeSearch import vaeSearch
|
||||
from .modules.referenceImages import referenceImages
|
||||
from .modules.imageInferenceInputs import imageInferenceInputs
|
||||
from .modules.imageInferenceAdvancedFeatures import RunwareImageInferenceAdvancedFeatures
|
||||
from .modules.imageWatermarkAdvancedFeature import RunwareWatermarkAdvancedFeature
|
||||
from .modules.imageRegionalPromptingAdvancedFeature import RunwareRegionalPromptingAdvancedFeature
|
||||
from .modules.imageRegionalPromptingAdvancedFeatureRegions import RunwareRegionalPromptingAdvancedFeatureRegions
|
||||
from .modules.videoInference import txt2vid
|
||||
from .modules.videoModelSearch import videoModelSearch
|
||||
from .modules.videoSettings import RunwareVideoSettings
|
||||
@@ -133,7 +136,10 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Runware IPAdapters Combine": ipAdapterCombine,
|
||||
"Runware Reference Images": referenceImages,
|
||||
"Runware Image Inference Inputs": imageInferenceInputs,
|
||||
"Runware Image Inference Advanced Features": RunwareImageInferenceAdvancedFeatures,
|
||||
"Runware Image Advanced Feature Input": RunwareImageInferenceAdvancedFeatures,
|
||||
"Runware Watermark Advanced Feature": RunwareWatermarkAdvancedFeature,
|
||||
"Runware Regional Prompting Advanced Feature": RunwareRegionalPromptingAdvancedFeature,
|
||||
"Runware Regional Prompting Advanced Feature Regions": RunwareRegionalPromptingAdvancedFeatureRegions,
|
||||
"Runware Video Inference": txt2vid,
|
||||
"Runware Video Model Search": videoModelSearch,
|
||||
"Runware Frame Images": RunwareFrameImages,
|
||||
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, videoSettingsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js";
|
||||
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, videoSettingsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js";
|
||||
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
|
||||
|
||||
const nodeInitList = [];
|
||||
@@ -80,6 +80,10 @@ app.registerExtension({
|
||||
audioInferenceToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.IMAGEINFERENCEADVANCEDFEATURES) {
|
||||
imageInferenceAdvancedFeaturesToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.WATERMARKADVANCEDFEATURE) {
|
||||
watermarkAdvancedFeatureToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.REGIONALPROMPTINGADVFEATUREREGIONS) {
|
||||
regionalPromptingRegionsToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINFERENCESPEECH) {
|
||||
audioInferenceSpeechToggleHandler(node);
|
||||
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOSETTINGS) {
|
||||
|
||||
+559
-544
File diff suppressed because it is too large
Load Diff
@@ -3871,6 +3871,137 @@ function imageInferenceAdvancedFeaturesToggleHandler(advancedFeaturesNode) {
|
||||
if (useHiresFixWidget && hiresFixWidget) toggleWidgetState(useHiresFixWidget, hiresFixWidget, "hiresFix");
|
||||
}
|
||||
|
||||
function watermarkAdvancedFeatureToggleHandler(watermarkNode) {
|
||||
if (!watermarkNode?.widgets) return;
|
||||
|
||||
function toggleWidgetState(useWidget, paramWidget, paramName) {
|
||||
if (!useWidget || !paramWidget) return;
|
||||
|
||||
function toggleEnabled() {
|
||||
const enabled = useWidget.value === true;
|
||||
|
||||
if (paramWidget.inputEl) {
|
||||
paramWidget.inputEl.disabled = !enabled;
|
||||
paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5";
|
||||
paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed";
|
||||
paramWidget.inputEl.readOnly = !enabled;
|
||||
}
|
||||
|
||||
paramWidget.disabled = !enabled;
|
||||
|
||||
if (!paramWidget.inputEl && paramName) {
|
||||
const nodeElement = watermarkNode.htmlElements?.widgetsContainer || watermarkNode.htmlElements;
|
||||
if (nodeElement) {
|
||||
const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`);
|
||||
if (input) {
|
||||
input.disabled = !enabled;
|
||||
input.style.opacity = enabled ? "1" : "0.5";
|
||||
input.style.cursor = enabled ? "text" : "not-allowed";
|
||||
input.readOnly = !enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watermarkNode.setDirtyCanvas(true);
|
||||
}
|
||||
|
||||
appendWidgetCB(useWidget, () => {
|
||||
setTimeout(toggleEnabled, 50);
|
||||
});
|
||||
|
||||
setTimeout(toggleEnabled, 100);
|
||||
}
|
||||
|
||||
const pairs = [
|
||||
["useText", "text"],
|
||||
["useImage", "image"],
|
||||
["useDisplayPosition", "displayPosition"],
|
||||
["useTiled", "tiled"],
|
||||
["useOpacity", "opacity"],
|
||||
["useFontColor", "fontColor"],
|
||||
["useBgColor", "bgColor"],
|
||||
];
|
||||
|
||||
for (const [useName, paramName] of pairs) {
|
||||
const useWidget = watermarkNode.widgets.find(w => w.name === useName);
|
||||
const paramWidget = watermarkNode.widgets.find(w => w.name === paramName);
|
||||
if (useWidget && paramWidget) {
|
||||
toggleWidgetState(useWidget, paramWidget, paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function regionalPromptingRegionsToggleHandler(regionsNode) {
|
||||
if (!regionsNode?.widgets) return;
|
||||
|
||||
function toggleWidgetState(useWidget, paramWidgets, paramNames) {
|
||||
if (!useWidget || !paramWidgets || paramWidgets.length === 0) return;
|
||||
|
||||
function toggleEnabled() {
|
||||
const enabled = useWidget.value === true;
|
||||
|
||||
for (let i = 0; i < paramWidgets.length; i++) {
|
||||
const paramWidget = paramWidgets[i];
|
||||
const paramName = paramNames[i];
|
||||
|
||||
if (!paramWidget) continue;
|
||||
|
||||
if (paramWidget.inputEl) {
|
||||
paramWidget.inputEl.disabled = !enabled;
|
||||
paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5";
|
||||
paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed";
|
||||
paramWidget.inputEl.readOnly = !enabled;
|
||||
}
|
||||
|
||||
paramWidget.disabled = !enabled;
|
||||
|
||||
if (!paramWidget.inputEl && paramName) {
|
||||
const nodeElement = regionsNode.htmlElements?.widgetsContainer || regionsNode.htmlElements;
|
||||
if (nodeElement) {
|
||||
const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`);
|
||||
if (input) {
|
||||
input.disabled = !enabled;
|
||||
input.style.opacity = enabled ? "1" : "0.5";
|
||||
input.style.cursor = enabled ? "text" : "not-allowed";
|
||||
input.readOnly = !enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
regionsNode.setDirtyCanvas(true);
|
||||
}
|
||||
|
||||
appendWidgetCB(useWidget, () => {
|
||||
setTimeout(toggleEnabled, 50);
|
||||
});
|
||||
|
||||
setTimeout(toggleEnabled, 100);
|
||||
}
|
||||
|
||||
for (let idx = 1; idx <= 4; idx++) {
|
||||
const useWidget = regionsNode.widgets.find(w => w.name === `useRegion${idx}`);
|
||||
const promptWidget = regionsNode.widgets.find(w => w.name === `region${idx}Prompt`);
|
||||
const x0Widget = regionsNode.widgets.find(w => w.name === `region${idx}_x0`);
|
||||
const y0Widget = regionsNode.widgets.find(w => w.name === `region${idx}_y0`);
|
||||
const x1Widget = regionsNode.widgets.find(w => w.name === `region${idx}_x1`);
|
||||
const y1Widget = regionsNode.widgets.find(w => w.name === `region${idx}_y1`);
|
||||
|
||||
const paramWidgets = [promptWidget, x0Widget, y0Widget, x1Widget, y1Widget];
|
||||
const paramNames = [
|
||||
`region${idx}Prompt`,
|
||||
`region${idx}_x0`,
|
||||
`region${idx}_y0`,
|
||||
`region${idx}_x1`,
|
||||
`region${idx}_y1`,
|
||||
];
|
||||
|
||||
if (useWidget) {
|
||||
toggleWidgetState(useWidget, paramWidgets, paramNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function audioInferenceInputsToggleHandler(audioInputsNode) {
|
||||
// Find widgets
|
||||
const useVideoWidget = audioInputsNode.widgets.find(w => w.name === "useVideo");
|
||||
@@ -3990,6 +4121,8 @@ export {
|
||||
useParameterToggleHandler,
|
||||
imageInferenceToggleHandler,
|
||||
imageInferenceAdvancedFeaturesToggleHandler,
|
||||
watermarkAdvancedFeatureToggleHandler,
|
||||
regionalPromptingRegionsToggleHandler,
|
||||
upscalerToggleHandler,
|
||||
videoUpscalerToggleHandler,
|
||||
audioInferenceToggleHandler,
|
||||
|
||||
@@ -195,7 +195,7 @@ class txt2img:
|
||||
"tooltip": "Connect Runware Image Inference Ultralytics node to configure Ultralytics parameters (maskBlur, maskPadding, confidence, prompts, steps, CFGScale, strength).",
|
||||
}),
|
||||
"advancedFeatures": ("RUNWAREIMAGEINFERENCEADVANCEDFEATURES", {
|
||||
"tooltip": "Connect Runware Image Inference Advanced Features for layerDiffuse (transparency) and hiresFix (two-stage high-res).",
|
||||
"tooltip": "Connect Runware Image Advanced Feature Input for layerDiffuse (transparency) and hiresFix (two-stage high-res).",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +1,80 @@
|
||||
"""
|
||||
Runware Image Inference Advanced Features Node
|
||||
Provides advancedFeatures (layerDiffuse, hiresFix) for Runware Image Inference.
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
class RunwareImageInferenceAdvancedFeatures:
|
||||
"""Runware Image Inference Advanced Features Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"useLayerDiffuse": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include layerDiffuse in advancedFeatures. When enabled, LayerDiffuse generates images with transparency (alpha) without post-processing background removal.",
|
||||
"default": False,
|
||||
}),
|
||||
"layerDiffuse": ("BOOLEAN", {
|
||||
"tooltip": "Enable LayerDiffuse technology for direct generation of images with transparency (alpha channels). Only used when 'Use Layer Diffuse' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "true",
|
||||
"label_off": "false",
|
||||
}),
|
||||
"useHiresFix": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include hiresFix in advancedFeatures. When enabled, uses a two-stage process for higher-resolution, higher-detail images.",
|
||||
"default": False,
|
||||
}),
|
||||
"hiresFix": ("BOOLEAN", {
|
||||
"tooltip": "Enable a two-stage generation: first at native resolution, then upscale and refine in a second pass. Only used when 'Use Hires Fix' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "true",
|
||||
"label_off": "false",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("RUNWAREIMAGEINFERENCEADVANCEDFEATURES",)
|
||||
RETURN_NAMES = ("advancedFeatures",)
|
||||
FUNCTION = "createAdvancedFeatures"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = "Configure advanced features for Runware Image Inference (layerDiffuse for transparency, hiresFix for two-stage high-res generation). Connect to Runware Image Inference advancedFeatures input."
|
||||
|
||||
def createAdvancedFeatures(self, **kwargs) -> tuple:
|
||||
"""Build advancedFeatures dict for the API."""
|
||||
use_layer_diffuse = kwargs.get("useLayerDiffuse", False)
|
||||
layer_diffuse = kwargs.get("layerDiffuse", False)
|
||||
use_hires_fix = kwargs.get("useHiresFix", False)
|
||||
hires_fix = kwargs.get("hiresFix", False)
|
||||
|
||||
advanced_features: Dict[str, Any] = {}
|
||||
|
||||
if use_layer_diffuse:
|
||||
advanced_features["layerDiffuse"] = bool(layer_diffuse)
|
||||
if use_hires_fix:
|
||||
advanced_features["hiresFix"] = bool(hires_fix)
|
||||
|
||||
return (advanced_features,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareImageInferenceAdvancedFeatures": RunwareImageInferenceAdvancedFeatures,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareImageInferenceAdvancedFeatures": "Runware Image Inference Advanced Features",
|
||||
}
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
class RunwareImageInferenceAdvancedFeatures:
|
||||
"""Runware Image Advanced Feature Input Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"useLayerDiffuse": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include layerDiffuse in advancedFeatures. When enabled, LayerDiffuse generates images with transparency (alpha) without post-processing background removal.",
|
||||
"default": False,
|
||||
}),
|
||||
"layerDiffuse": ("BOOLEAN", {
|
||||
"tooltip": "Enable LayerDiffuse technology for direct generation of images with transparency (alpha channels). Only used when 'Use Layer Diffuse' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "true",
|
||||
"label_off": "false",
|
||||
}),
|
||||
"useHiresFix": ("BOOLEAN", {
|
||||
"tooltip": "Enable to include hiresFix in advancedFeatures. When enabled, uses a two-stage process for higher-resolution, higher-detail images.",
|
||||
"default": False,
|
||||
}),
|
||||
"hiresFix": ("BOOLEAN", {
|
||||
"tooltip": "Enable a two-stage generation: first at native resolution, then upscale and refine in a second pass. Only used when 'Use Hires Fix' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "true",
|
||||
"label_off": "false",
|
||||
}),
|
||||
"watermark": ("RUNWAREIMAGEWATERMARKADVFEATURE", {
|
||||
"tooltip": "Connect Runware Watermark Advanced Feature to include watermark configuration in advancedFeatures.watermark.",
|
||||
}),
|
||||
"regionalPrompting": ("RUNWAREREGIONALPROMPTINGADVFEATURE", {
|
||||
"tooltip": "Connect Runware Regional Prompting Advanced Feature to configure regionalPrompting in advancedFeatures.",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("RUNWAREIMAGEINFERENCEADVANCEDFEATURES",)
|
||||
RETURN_NAMES = ("advancedFeatures",)
|
||||
FUNCTION = "createAdvancedFeatures"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = (
|
||||
"Configure advanced features for Runware Image Inference: layerDiffuse (transparency), "
|
||||
"hiresFix (two-stage high-res), watermark, and regional prompting. "
|
||||
"Connect to Runware Image Inference advancedFeatures input."
|
||||
)
|
||||
|
||||
def createAdvancedFeatures(self, watermark=None, regionalPrompting=None, **kwargs) -> tuple:
|
||||
"""Build advancedFeatures dict for the API."""
|
||||
use_layer_diffuse = kwargs.get("useLayerDiffuse", False)
|
||||
layer_diffuse = kwargs.get("layerDiffuse", False)
|
||||
use_hires_fix = kwargs.get("useHiresFix", False)
|
||||
hires_fix = kwargs.get("hiresFix", False)
|
||||
|
||||
advanced_features: Dict[str, Any] = {}
|
||||
|
||||
if use_layer_diffuse:
|
||||
advanced_features["layerDiffuse"] = bool(layer_diffuse)
|
||||
if use_hires_fix:
|
||||
advanced_features["hiresFix"] = bool(hires_fix)
|
||||
|
||||
if isinstance(watermark, dict) and watermark:
|
||||
advanced_features["watermark"] = watermark
|
||||
|
||||
if isinstance(regionalPrompting, dict) and regionalPrompting:
|
||||
advanced_features["regionalPrompting"] = regionalPrompting
|
||||
|
||||
return (advanced_features,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareImageInferenceAdvancedFeatures": RunwareImageInferenceAdvancedFeatures,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareImageInferenceAdvancedFeatures": "Runware Image Advanced Feature Input",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
from typing import Dict, Any, Tuple
|
||||
|
||||
|
||||
class RunwareRegionalPromptingAdvancedFeature:
|
||||
"""
|
||||
Runware Regional Prompting Advanced Feature Node
|
||||
|
||||
Builds the advancedFeatures.regionalPrompting configuration object:
|
||||
- injectSteps
|
||||
- backgroundPrompt
|
||||
- baseRatio
|
||||
- regions (connected from the Regions node)
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"injectSteps": ("INT", {
|
||||
"tooltip": "Steps to inject regional masks (1-100).",
|
||||
"default": 15,
|
||||
"min": 1,
|
||||
"max": 100,
|
||||
}),
|
||||
"backgroundPrompt": ("STRING", {
|
||||
"tooltip": "Background prompt applied to uncovered areas.",
|
||||
"default": "",
|
||||
}),
|
||||
"baseRatio": ("FLOAT", {
|
||||
"tooltip": "Base prompt attention weight (0.0 - 1.0).",
|
||||
"default": 0.0,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"step": 0.01,
|
||||
}),
|
||||
"regions": ("RUNWAREREGIONALPROMPTINGREGIONS", {
|
||||
"tooltip": "Connect Runware Regional Prompting Advanced Feature Regions node to define regional prompts and masks.",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES: Tuple[str] = ("RUNWAREREGIONALPROMPTINGADVFEATURE",)
|
||||
RETURN_NAMES = ("regionalPrompting",)
|
||||
FUNCTION = "createRegionalPrompting"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = (
|
||||
"Configure regional prompting advanced feature (injectSteps, backgroundPrompt, "
|
||||
"baseRatio, and regions). Connect output to Runware Image Advanced Feature Input "
|
||||
"regionalPrompting input."
|
||||
)
|
||||
|
||||
def createRegionalPrompting(self, regions=None, **kwargs) -> tuple:
|
||||
"""Build regionalPrompting dict for advancedFeatures.regionalPrompting."""
|
||||
inject_steps = int(kwargs.get("injectSteps", 15))
|
||||
base_ratio = float(kwargs.get("baseRatio", 0.2))
|
||||
background_prompt = (kwargs.get("backgroundPrompt", "") or "").strip()
|
||||
|
||||
config: Dict[str, Any] = {
|
||||
"injectSteps": inject_steps,
|
||||
"baseRatio": base_ratio,
|
||||
}
|
||||
|
||||
if background_prompt:
|
||||
config["backgroundPrompt"] = background_prompt
|
||||
|
||||
if isinstance(regions, list) and regions:
|
||||
config["regions"] = regions
|
||||
|
||||
return (config,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareRegionalPromptingAdvancedFeature": RunwareRegionalPromptingAdvancedFeature,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareRegionalPromptingAdvancedFeature": "Runware Regional Prompting Advanced Feature",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
from typing import Dict, Any, List, Tuple
|
||||
|
||||
|
||||
class RunwareRegionalPromptingAdvancedFeatureRegions:
|
||||
"""
|
||||
Runware Regional Prompting Advanced Feature Regions Node
|
||||
|
||||
Builds the advancedFeatures.regionalPrompting.regions array, with up to 4 regions.
|
||||
Each region has a prompt and a rectangular mask [x0, y0, x1, y1].
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
coords_tooltip = "Mask rectangle as [x0, y0, x1, y1] in image pixel coordinates."
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
# Region 1
|
||||
"useRegion1": ("BOOLEAN", {
|
||||
"tooltip": "Enable first regional prompt mask.",
|
||||
"default": False,
|
||||
}),
|
||||
"region1Prompt": ("STRING", {
|
||||
"tooltip": "Prompt for region 1.",
|
||||
"default": "",
|
||||
}),
|
||||
"region1_x0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region1_y0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region1_x1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region1_y1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
# Region 2
|
||||
"useRegion2": ("BOOLEAN", {
|
||||
"tooltip": "Enable second regional prompt mask.",
|
||||
"default": False,
|
||||
}),
|
||||
"region2Prompt": ("STRING", {
|
||||
"tooltip": "Prompt for region 2.",
|
||||
"default": "",
|
||||
}),
|
||||
"region2_x0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region2_y0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region2_x1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 1024,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region2_y1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
# Region 3
|
||||
"useRegion3": ("BOOLEAN", {
|
||||
"tooltip": "Enable third regional prompt mask.",
|
||||
"default": False,
|
||||
}),
|
||||
"region3Prompt": ("STRING", {
|
||||
"tooltip": "Prompt for region 3.",
|
||||
"default": "",
|
||||
}),
|
||||
"region3_x0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region3_y0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region3_x1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region3_y1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 1024,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
# Region 4
|
||||
"useRegion4": ("BOOLEAN", {
|
||||
"tooltip": "Enable fourth regional prompt mask.",
|
||||
"default": False,
|
||||
}),
|
||||
"region4Prompt": ("STRING", {
|
||||
"tooltip": "Prompt for region 4.",
|
||||
"default": "",
|
||||
}),
|
||||
"region4_x0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region4_y0": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 512,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region4_x1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 1024,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
"region4_y1": ("INT", {
|
||||
"tooltip": coords_tooltip,
|
||||
"default": 1024,
|
||||
"min": 0,
|
||||
"max": 8192,
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES: Tuple[str] = ("RUNWAREREGIONALPROMPTINGREGIONS",)
|
||||
RETURN_NAMES = ("regions",)
|
||||
FUNCTION = "createRegions"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = (
|
||||
"Configure regions array for regional prompting. Each enabled region provides "
|
||||
"a prompt and a rectangular mask [x0, y0, x1, y1]. Connect to Runware Regional "
|
||||
"Prompting Advanced Feature regions input."
|
||||
)
|
||||
|
||||
def createRegions(self, **kwargs) -> tuple:
|
||||
"""Build list of regional prompting regions."""
|
||||
regions: List[Dict[str, Any]] = []
|
||||
|
||||
for idx in range(1, 5):
|
||||
use_region = kwargs.get(f"useRegion{idx}", False)
|
||||
prompt = (kwargs.get(f"region{idx}Prompt", "") or "").strip()
|
||||
if not use_region or not prompt:
|
||||
continue
|
||||
|
||||
x0 = int(kwargs.get(f"region{idx}_x0", 0))
|
||||
y0 = int(kwargs.get(f"region{idx}_y0", 0))
|
||||
x1 = int(kwargs.get(f"region{idx}_x1", 0))
|
||||
y1 = int(kwargs.get(f"region{idx}_y1", 0))
|
||||
|
||||
mask = [x0, y0, x1, y1]
|
||||
regions.append(
|
||||
{
|
||||
"prompt": prompt,
|
||||
"mask": mask,
|
||||
}
|
||||
)
|
||||
|
||||
return (regions,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareRegionalPromptingAdvancedFeatureRegions": RunwareRegionalPromptingAdvancedFeatureRegions,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareRegionalPromptingAdvancedFeatureRegions": "Runware Regional Prompting Advanced Feature Regions",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
from typing import Dict, Any, Tuple
|
||||
|
||||
from .utils.runwareUtils import convertTensor2IMG
|
||||
|
||||
|
||||
class RunwareWatermarkAdvancedFeature:
|
||||
"""Runware Watermark Advanced Feature Node"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"useText": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set text content for the watermark (2-32 characters).",
|
||||
"default": False,
|
||||
}),
|
||||
"text": ("STRING", {
|
||||
"tooltip": "Text content for the watermark (2-32 characters). Only used when 'Use Text' is enabled.",
|
||||
"default": "",
|
||||
}),
|
||||
"useImage": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set image content for the watermark (connect an IMAGE, UUID, URL, data URI, or base64).",
|
||||
"default": False,
|
||||
}),
|
||||
"image": ("IMAGE", {
|
||||
"tooltip": "Image to use as watermark. Can be connected from a Load Image node; internally converted to a data URI/UUID when used.",
|
||||
}),
|
||||
"useDisplayPosition": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set watermark display position.",
|
||||
"default": False,
|
||||
}),
|
||||
"displayPosition": ([
|
||||
"top-left", "top-center", "top-right",
|
||||
"center-left", "center-center", "center-right",
|
||||
"bottom-left", "bottom-center", "bottom-right",
|
||||
], {
|
||||
"tooltip": "Watermark position on the image.",
|
||||
"default": "bottom-right",
|
||||
}),
|
||||
"useTiled": ("BOOLEAN", {
|
||||
"tooltip": "Enable to tile the watermark across the image at -45 degrees.",
|
||||
"default": False,
|
||||
}),
|
||||
"tiled": ("BOOLEAN", {
|
||||
"tooltip": "When enabled, distribute watermark across the image at -45 degrees. Only used when 'Use Tiled' is enabled.",
|
||||
"default": False,
|
||||
"label_on": "true",
|
||||
"label_off": "false",
|
||||
}),
|
||||
"useOpacity": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set watermark opacity (0.1 - 1.0).",
|
||||
"default": False,
|
||||
}),
|
||||
"opacity": ("FLOAT", {
|
||||
"tooltip": "Watermark opacity (0.1 - 1.0). Only used when 'Use Opacity' is enabled.",
|
||||
"default": 0.6,
|
||||
"min": 0.1,
|
||||
"max": 1.0,
|
||||
"step": 0.05,
|
||||
}),
|
||||
"useFontColor": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set watermark font color (hex).",
|
||||
"default": False,
|
||||
}),
|
||||
"fontColor": ("STRING", {
|
||||
"tooltip": "Text color in hex format (e.g. #ffffff). Only used when 'Use Font Color' is enabled.",
|
||||
"default": "#ffffff",
|
||||
}),
|
||||
"useBgColor": ("BOOLEAN", {
|
||||
"tooltip": "Enable to set watermark background color (hex).",
|
||||
"default": False,
|
||||
}),
|
||||
"bgColor": ("STRING", {
|
||||
"tooltip": "Background color in hex format (e.g. #000000 or transparent). Only used when 'Use Bg Color' is enabled.",
|
||||
"default": "transparent",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES: Tuple[str] = ("RUNWAREIMAGEWATERMARKADVFEATURE",)
|
||||
RETURN_NAMES = ("watermark",)
|
||||
FUNCTION = "createWatermark"
|
||||
CATEGORY = "Runware"
|
||||
DESCRIPTION = (
|
||||
"Configure watermark advanced feature for Runware Image Inference. "
|
||||
"You must provide exactly one of text or image. Connect output to "
|
||||
"Runware Image Advanced Feature Input watermark connection."
|
||||
)
|
||||
|
||||
def createWatermark(self, **kwargs) -> tuple:
|
||||
"""Build watermark dict for advancedFeatures.watermark."""
|
||||
use_text = kwargs.get("useText", False)
|
||||
text = (kwargs.get("text", "") or "").strip()
|
||||
use_image = kwargs.get("useImage", False)
|
||||
raw_image = kwargs.get("image", None)
|
||||
|
||||
has_text = use_text and bool(text)
|
||||
|
||||
image_str: str = ""
|
||||
if use_image and raw_image is not None:
|
||||
# If an IMAGE tensor is connected, convert it to a data URI / UUID.
|
||||
try:
|
||||
# convertTensor2IMG handles caching and returns either UUID or data URI.
|
||||
image_str = convertTensor2IMG(raw_image)
|
||||
except Exception:
|
||||
image_str = ""
|
||||
|
||||
has_image = use_image and bool(image_str)
|
||||
|
||||
if has_text == has_image:
|
||||
raise Exception(
|
||||
"Watermark configuration requires exactly one of text or image (but not both or neither)."
|
||||
)
|
||||
|
||||
use_pos = kwargs.get("useDisplayPosition", False)
|
||||
pos = kwargs.get("displayPosition", "bottom-right")
|
||||
use_tiled = kwargs.get("useTiled", False)
|
||||
tiled = bool(kwargs.get("tiled", False))
|
||||
use_opacity = kwargs.get("useOpacity", False)
|
||||
opacity = float(kwargs.get("opacity", 0.6))
|
||||
use_font = kwargs.get("useFontColor", False)
|
||||
font_color = (kwargs.get("fontColor", "#ffffff") or "").strip()
|
||||
use_bg = kwargs.get("useBgColor", False)
|
||||
bg_color = (kwargs.get("bgColor", "transparent") or "").strip()
|
||||
|
||||
watermark: Dict[str, Any] = {}
|
||||
|
||||
if has_text:
|
||||
watermark["text"] = text
|
||||
if has_image:
|
||||
watermark["image"] = image_str
|
||||
if use_pos:
|
||||
watermark["displayPosition"] = pos
|
||||
if use_tiled:
|
||||
watermark["tiled"] = tiled
|
||||
if use_opacity:
|
||||
watermark["opacity"] = opacity
|
||||
if use_font and font_color:
|
||||
watermark["fontColor"] = font_color
|
||||
if use_bg and bg_color:
|
||||
watermark["bgColor"] = bg_color
|
||||
|
||||
return (watermark,)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"RunwareWatermarkAdvancedFeature": RunwareWatermarkAdvancedFeature,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"RunwareWatermarkAdvancedFeature": "Runware Watermark Advanced Feature",
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user