mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-29 07:40:21 +08:00
extras
This commit is contained in:
parent
aa1eb398e7
commit
666f5b96f7
@ -1,16 +1,19 @@
|
|||||||
import torch
|
import torch
|
||||||
|
|
||||||
import comfy.model_management
|
import comfy.model_management
|
||||||
import node_helpers
|
from comfy import node_helpers
|
||||||
|
|
||||||
|
|
||||||
class TextEncodeAceStepAudio:
|
class TextEncodeAceStepAudio:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required": {
|
return {"required": {
|
||||||
"clip": ("CLIP", ),
|
"clip": ("CLIP",),
|
||||||
"tags": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
"tags": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
||||||
"lyrics": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
"lyrics": ("STRING", {"multiline": True, "dynamicPrompts": True}),
|
||||||
"lyrics_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
"lyrics_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
RETURN_TYPES = ("CONDITIONING",)
|
RETURN_TYPES = ("CONDITIONING",)
|
||||||
FUNCTION = "encode"
|
FUNCTION = "encode"
|
||||||
|
|
||||||
@ -20,7 +23,7 @@ class TextEncodeAceStepAudio:
|
|||||||
tokens = clip.tokenize(tags, lyrics=lyrics)
|
tokens = clip.tokenize(tags, lyrics=lyrics)
|
||||||
conditioning = clip.encode_from_tokens_scheduled(tokens)
|
conditioning = clip.encode_from_tokens_scheduled(tokens)
|
||||||
conditioning = node_helpers.conditioning_set_values(conditioning, {"lyrics_strength": lyrics_strength})
|
conditioning = node_helpers.conditioning_set_values(conditioning, {"lyrics_strength": lyrics_strength})
|
||||||
return (conditioning, )
|
return (conditioning,)
|
||||||
|
|
||||||
|
|
||||||
class EmptyAceStepLatentAudio:
|
class EmptyAceStepLatentAudio:
|
||||||
@ -32,6 +35,7 @@ class EmptyAceStepLatentAudio:
|
|||||||
return {"required": {"seconds": ("FLOAT", {"default": 120.0, "min": 1.0, "max": 1000.0, "step": 0.1}),
|
return {"required": {"seconds": ("FLOAT", {"default": 120.0, "min": 1.0, "max": 1000.0, "step": 0.1}),
|
||||||
"batch_size": ("INT", {"default": 1, "min": 1, "max": 4096, "tooltip": "The number of latent images in the batch."}),
|
"batch_size": ("INT", {"default": 1, "min": 1, "max": 4096, "tooltip": "The number of latent images in the batch."}),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
RETURN_TYPES = ("LATENT",)
|
RETURN_TYPES = ("LATENT",)
|
||||||
FUNCTION = "generate"
|
FUNCTION = "generate"
|
||||||
|
|
||||||
@ -40,7 +44,7 @@ class EmptyAceStepLatentAudio:
|
|||||||
def generate(self, seconds, batch_size):
|
def generate(self, seconds, batch_size):
|
||||||
length = int(seconds * 44100 / 512 / 8)
|
length = int(seconds * 44100 / 512 / 8)
|
||||||
latent = torch.zeros([batch_size, 8, 16, length], device=self.device)
|
latent = torch.zeros([batch_size, 8, 16, length], device=self.device)
|
||||||
return ({"samples": latent, "type": "audio"}, )
|
return ({"samples": latent, "type": "audio"},)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import torch
|
import torch
|
||||||
|
|
||||||
|
|
||||||
def project(v0, v1):
|
def project(v0, v1):
|
||||||
v1 = torch.nn.functional.normalize(v1, dim=[-1, -2, -3])
|
v1 = torch.nn.functional.normalize(v1, dim=[-1, -2, -3])
|
||||||
v0_parallel = (v0 * v1).sum(dim=[-1, -2, -3], keepdim=True) * v1
|
v0_parallel = (v0 * v1).sum(dim=[-1, -2, -3], keepdim=True) * v1
|
||||||
v0_orthogonal = v0 - v0_parallel
|
v0_orthogonal = v0 - v0_parallel
|
||||||
return v0_parallel, v0_orthogonal
|
return v0_parallel, v0_orthogonal
|
||||||
|
|
||||||
|
|
||||||
class APG:
|
class APG:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -14,9 +16,10 @@ class APG:
|
|||||||
"model": ("MODEL",),
|
"model": ("MODEL",),
|
||||||
"eta": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01, "tooltip": "Controls the scale of the parallel guidance vector. Default CFG behavior at a setting of 1."}),
|
"eta": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01, "tooltip": "Controls the scale of the parallel guidance vector. Default CFG behavior at a setting of 1."}),
|
||||||
"norm_threshold": ("FLOAT", {"default": 5.0, "min": 0.0, "max": 50.0, "step": 0.1, "tooltip": "Normalize guidance vector to this value, normalization disable at a setting of 0."}),
|
"norm_threshold": ("FLOAT", {"default": 5.0, "min": 0.0, "max": 50.0, "step": 0.1, "tooltip": "Normalize guidance vector to this value, normalization disable at a setting of 0."}),
|
||||||
"momentum": ("FLOAT", {"default": 0.0, "min": -5.0, "max": 1.0, "step": 0.01, "tooltip":"Controls a running average of guidance during diffusion, disabled at a setting of 0."}),
|
"momentum": ("FLOAT", {"default": 0.0, "min": -5.0, "max": 1.0, "step": 0.01, "tooltip": "Controls a running average of guidance during diffusion, disabled at a setting of 0."}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("MODEL",)
|
RETURN_TYPES = ("MODEL",)
|
||||||
FUNCTION = "patch"
|
FUNCTION = "patch"
|
||||||
CATEGORY = "sampling/custom_sampling"
|
CATEGORY = "sampling/custom_sampling"
|
||||||
@ -67,6 +70,7 @@ class APG:
|
|||||||
m.set_model_sampler_pre_cfg_function(pre_cfg_function)
|
m.set_model_sampler_pre_cfg_function(pre_cfg_function)
|
||||||
return (m,)
|
return (m,)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"APG": APG,
|
"APG": APG,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,26 @@
|
|||||||
import nodes
|
|
||||||
import torch
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import torch
|
||||||
from einops import rearrange
|
from einops import rearrange
|
||||||
|
|
||||||
import comfy.model_management
|
import comfy.model_management
|
||||||
|
from comfy.nodes.common import MAX_RESOLUTION
|
||||||
|
|
||||||
|
|
||||||
MAX_RESOLUTION = nodes.MAX_RESOLUTION
|
|
||||||
|
|
||||||
CAMERA_DICT = {
|
CAMERA_DICT = {
|
||||||
"base_T_norm": 1.5,
|
"base_T_norm": 1.5,
|
||||||
"base_angle": np.pi/3,
|
"base_angle": np.pi / 3,
|
||||||
"Static": { "angle":[0., 0., 0.], "T":[0., 0., 0.]},
|
"Static": {"angle": [0., 0., 0.], "T": [0., 0., 0.]},
|
||||||
"Pan Up": { "angle":[0., 0., 0.], "T":[0., -1., 0.]},
|
"Pan Up": {"angle": [0., 0., 0.], "T": [0., -1., 0.]},
|
||||||
"Pan Down": { "angle":[0., 0., 0.], "T":[0.,1.,0.]},
|
"Pan Down": {"angle": [0., 0., 0.], "T": [0., 1., 0.]},
|
||||||
"Pan Left": { "angle":[0., 0., 0.], "T":[-1.,0.,0.]},
|
"Pan Left": {"angle": [0., 0., 0.], "T": [-1., 0., 0.]},
|
||||||
"Pan Right": { "angle":[0., 0., 0.], "T": [1.,0.,0.]},
|
"Pan Right": {"angle": [0., 0., 0.], "T": [1., 0., 0.]},
|
||||||
"Zoom In": { "angle":[0., 0., 0.], "T": [0.,0.,2.]},
|
"Zoom In": {"angle": [0., 0., 0.], "T": [0., 0., 2.]},
|
||||||
"Zoom Out": { "angle":[0., 0., 0.], "T": [0.,0.,-2.]},
|
"Zoom Out": {"angle": [0., 0., 0.], "T": [0., 0., -2.]},
|
||||||
"Anti Clockwise (ACW)": { "angle": [0., 0., -1.], "T":[0., 0., 0.]},
|
"Anti Clockwise (ACW)": {"angle": [0., 0., -1.], "T": [0., 0., 0.]},
|
||||||
"ClockWise (CW)": { "angle": [0., 0., 1.], "T":[0., 0., 0.]},
|
"ClockWise (CW)": {"angle": [0., 0., 1.], "T": [0., 0., 0.]},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def process_pose_params(cam_params, width=672, height=384, original_pose_width=1280, original_pose_height=720, device='cpu'):
|
def process_pose_params(cam_params, width=672, height=384, original_pose_width=1280, original_pose_height=720, device='cpu'):
|
||||||
|
|
||||||
def get_relative_pose(cam_params):
|
def get_relative_pose(cam_params):
|
||||||
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
||||||
"""
|
"""
|
||||||
@ -59,9 +55,9 @@ def process_pose_params(cam_params, width=672, height=384, original_pose_width=1
|
|||||||
cam_param.fy = resized_ori_h * cam_param.fy / height
|
cam_param.fy = resized_ori_h * cam_param.fy / height
|
||||||
|
|
||||||
intrinsic = np.asarray([[cam_param.fx * width,
|
intrinsic = np.asarray([[cam_param.fx * width,
|
||||||
cam_param.fy * height,
|
cam_param.fy * height,
|
||||||
cam_param.cx * width,
|
cam_param.cx * width,
|
||||||
cam_param.cy * height]
|
cam_param.cy * height]
|
||||||
for cam_param in cam_params], dtype=np.float32)
|
for cam_param in cam_params], dtype=np.float32)
|
||||||
|
|
||||||
K = torch.as_tensor(intrinsic)[None] # [1, 1, 4]
|
K = torch.as_tensor(intrinsic)[None] # [1, 1, 4]
|
||||||
@ -72,9 +68,11 @@ def process_pose_params(cam_params, width=672, height=384, original_pose_width=1
|
|||||||
plucker_embedding = rearrange(plucker_embedding, "b f c h w -> b f h w c")[0]
|
plucker_embedding = rearrange(plucker_embedding, "b f c h w -> b f h w c")[0]
|
||||||
return plucker_embedding
|
return plucker_embedding
|
||||||
|
|
||||||
|
|
||||||
class Camera(object):
|
class Camera(object):
|
||||||
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, entry):
|
def __init__(self, entry):
|
||||||
fx, fy, cx, cy = entry[1:5]
|
fx, fy, cx, cy = entry[1:5]
|
||||||
self.fx = fx
|
self.fx = fx
|
||||||
@ -85,6 +83,7 @@ class Camera(object):
|
|||||||
self.c2w_mat = c2w_mat
|
self.c2w_mat = c2w_mat
|
||||||
self.w2c_mat = np.linalg.inv(c2w_mat)
|
self.w2c_mat = np.linalg.inv(c2w_mat)
|
||||||
|
|
||||||
|
|
||||||
def ray_condition(K, c2w, H, W, device):
|
def ray_condition(K, c2w, H, W, device):
|
||||||
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
"""Copied from https://github.com/hehao13/CameraCtrl/blob/main/inference.py
|
||||||
"""
|
"""
|
||||||
@ -121,59 +120,62 @@ def ray_condition(K, c2w, H, W, device):
|
|||||||
# plucker = plucker.permute(0, 1, 4, 2, 3)
|
# plucker = plucker.permute(0, 1, 4, 2, 3)
|
||||||
return plucker
|
return plucker
|
||||||
|
|
||||||
|
|
||||||
def get_camera_motion(angle, T, speed, n=81):
|
def get_camera_motion(angle, T, speed, n=81):
|
||||||
def compute_R_form_rad_angle(angles):
|
def compute_R_form_rad_angle(angles):
|
||||||
theta_x, theta_y, theta_z = angles
|
theta_x, theta_y, theta_z = angles
|
||||||
Rx = np.array([[1, 0, 0],
|
Rx = np.array([[1, 0, 0],
|
||||||
[0, np.cos(theta_x), -np.sin(theta_x)],
|
[0, np.cos(theta_x), -np.sin(theta_x)],
|
||||||
[0, np.sin(theta_x), np.cos(theta_x)]])
|
[0, np.sin(theta_x), np.cos(theta_x)]])
|
||||||
|
|
||||||
Ry = np.array([[np.cos(theta_y), 0, np.sin(theta_y)],
|
Ry = np.array([[np.cos(theta_y), 0, np.sin(theta_y)],
|
||||||
[0, 1, 0],
|
[0, 1, 0],
|
||||||
[-np.sin(theta_y), 0, np.cos(theta_y)]])
|
[-np.sin(theta_y), 0, np.cos(theta_y)]])
|
||||||
|
|
||||||
Rz = np.array([[np.cos(theta_z), -np.sin(theta_z), 0],
|
Rz = np.array([[np.cos(theta_z), -np.sin(theta_z), 0],
|
||||||
[np.sin(theta_z), np.cos(theta_z), 0],
|
[np.sin(theta_z), np.cos(theta_z), 0],
|
||||||
[0, 0, 1]])
|
[0, 0, 1]])
|
||||||
|
|
||||||
R = np.dot(Rz, np.dot(Ry, Rx))
|
R = np.dot(Rz, np.dot(Ry, Rx))
|
||||||
return R
|
return R
|
||||||
|
|
||||||
RT = []
|
RT = []
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
_angle = (i/n)*speed*(CAMERA_DICT["base_angle"])*angle
|
_angle = (i / n) * speed * (CAMERA_DICT["base_angle"]) * angle
|
||||||
R = compute_R_form_rad_angle(_angle)
|
R = compute_R_form_rad_angle(_angle)
|
||||||
_T=(i/n)*speed*(CAMERA_DICT["base_T_norm"])*(T.reshape(3,1))
|
_T = (i / n) * speed * (CAMERA_DICT["base_T_norm"]) * (T.reshape(3, 1))
|
||||||
_RT = np.concatenate([R,_T], axis=1)
|
_RT = np.concatenate([R, _T], axis=1)
|
||||||
RT.append(_RT)
|
RT.append(_RT)
|
||||||
RT = np.stack(RT)
|
RT = np.stack(RT)
|
||||||
return RT
|
return RT
|
||||||
|
|
||||||
|
|
||||||
class WanCameraEmbedding:
|
class WanCameraEmbedding:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {
|
return {
|
||||||
"required": {
|
"required": {
|
||||||
"camera_pose":(["Static","Pan Up","Pan Down","Pan Left","Pan Right","Zoom In","Zoom Out","Anti Clockwise (ACW)", "ClockWise (CW)"],{"default":"Static"}),
|
"camera_pose": (["Static", "Pan Up", "Pan Down", "Pan Left", "Pan Right", "Zoom In", "Zoom Out", "Anti Clockwise (ACW)", "ClockWise (CW)"], {"default": "Static"}),
|
||||||
"width": ("INT", {"default": 832, "min": 16, "max": MAX_RESOLUTION, "step": 16}),
|
"width": ("INT", {"default": 832, "min": 16, "max": MAX_RESOLUTION, "step": 16}),
|
||||||
"height": ("INT", {"default": 480, "min": 16, "max": MAX_RESOLUTION, "step": 16}),
|
"height": ("INT", {"default": 480, "min": 16, "max": MAX_RESOLUTION, "step": 16}),
|
||||||
"length": ("INT", {"default": 81, "min": 1, "max": MAX_RESOLUTION, "step": 4}),
|
"length": ("INT", {"default": 81, "min": 1, "max": MAX_RESOLUTION, "step": 4}),
|
||||||
},
|
},
|
||||||
"optional":{
|
"optional": {
|
||||||
"speed":("FLOAT",{"default":1.0, "min": 0, "max": 10.0, "step": 0.1}),
|
"speed": ("FLOAT", {"default": 1.0, "min": 0, "max": 10.0, "step": 0.1}),
|
||||||
"fx":("FLOAT",{"default":0.5, "min": 0, "max": 1, "step": 0.000000001}),
|
"fx": ("FLOAT", {"default": 0.5, "min": 0, "max": 1, "step": 0.000000001}),
|
||||||
"fy":("FLOAT",{"default":0.5, "min": 0, "max": 1, "step": 0.000000001}),
|
"fy": ("FLOAT", {"default": 0.5, "min": 0, "max": 1, "step": 0.000000001}),
|
||||||
"cx":("FLOAT",{"default":0.5, "min": 0, "max": 1, "step": 0.01}),
|
"cx": ("FLOAT", {"default": 0.5, "min": 0, "max": 1, "step": 0.01}),
|
||||||
"cy":("FLOAT",{"default":0.5, "min": 0, "max": 1, "step": 0.01}),
|
"cy": ("FLOAT", {"default": 0.5, "min": 0, "max": 1, "step": 0.01}),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("WAN_CAMERA_EMBEDDING","INT","INT","INT")
|
RETURN_TYPES = ("WAN_CAMERA_EMBEDDING", "INT", "INT", "INT")
|
||||||
RETURN_NAMES = ("camera_embedding","width","height","length")
|
RETURN_NAMES = ("camera_embedding", "width", "height", "length")
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
CATEGORY = "camera"
|
CATEGORY = "camera"
|
||||||
|
|
||||||
def run(self, camera_pose, width, height, length, speed=1.0, fx=0.5, fy=0.5, cx=0.5, cy=0.5):
|
def run(self, camera_pose, width, height, length, speed=1.0, fx=0.5, fy=0.5, cx=0.5, cy=0.5):
|
||||||
"""
|
"""
|
||||||
Use Camera trajectory as extrinsic parameters to calculate Plücker embeddings (Sitzmannet al., 2021)
|
Use Camera trajectory as extrinsic parameters to calculate Plücker embeddings (Sitzmannet al., 2021)
|
||||||
Adapted from https://github.com/aigc-apps/VideoX-Fun/blob/main/comfyui/comfyui_nodes.py
|
Adapted from https://github.com/aigc-apps/VideoX-Fun/blob/main/comfyui/comfyui_nodes.py
|
||||||
@ -184,13 +186,13 @@ class WanCameraEmbedding:
|
|||||||
T = np.array(CAMERA_DICT[motion_list[0]]["T"])
|
T = np.array(CAMERA_DICT[motion_list[0]]["T"])
|
||||||
RT = get_camera_motion(angle, T, speed, length)
|
RT = get_camera_motion(angle, T, speed, length)
|
||||||
|
|
||||||
trajs=[]
|
trajs = []
|
||||||
for cp in RT.tolist():
|
for cp in RT.tolist():
|
||||||
traj=[fx,fy,cx,cy,0,0]
|
traj = [fx, fy, cx, cy, 0, 0]
|
||||||
traj.extend(cp[0])
|
traj.extend(cp[0])
|
||||||
traj.extend(cp[1])
|
traj.extend(cp[1])
|
||||||
traj.extend(cp[2])
|
traj.extend(cp[2])
|
||||||
traj.extend([0,0,0,1])
|
traj.extend([0, 0, 0, 1])
|
||||||
trajs.append(traj)
|
trajs.append(traj)
|
||||||
|
|
||||||
cam_params = np.array([[float(x) for x in pose] for pose in trajs])
|
cam_params = np.array([[float(x) for x in pose] for pose in trajs])
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import re
|
|||||||
|
|
||||||
from comfy.comfy_types.node_typing import IO
|
from comfy.comfy_types.node_typing import IO
|
||||||
|
|
||||||
|
|
||||||
class StringConcatenate():
|
class StringConcatenate():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -20,6 +21,7 @@ class StringConcatenate():
|
|||||||
def execute(self, string_a, string_b, delimiter, **kwargs):
|
def execute(self, string_a, string_b, delimiter, **kwargs):
|
||||||
return delimiter.join((string_a, string_b)),
|
return delimiter.join((string_a, string_b)),
|
||||||
|
|
||||||
|
|
||||||
class StringSubstring():
|
class StringSubstring():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -38,6 +40,7 @@ class StringSubstring():
|
|||||||
def execute(self, string, start, end, **kwargs):
|
def execute(self, string, start, end, **kwargs):
|
||||||
return string[start:end],
|
return string[start:end],
|
||||||
|
|
||||||
|
|
||||||
class StringLength():
|
class StringLength():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -57,6 +60,7 @@ class StringLength():
|
|||||||
|
|
||||||
return length,
|
return length,
|
||||||
|
|
||||||
|
|
||||||
class CaseConverter():
|
class CaseConverter():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -112,6 +116,7 @@ class StringTrim():
|
|||||||
|
|
||||||
return result,
|
return result,
|
||||||
|
|
||||||
|
|
||||||
class StringReplace():
|
class StringReplace():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -188,6 +193,7 @@ class StringCompare():
|
|||||||
elif mode == "Ends With":
|
elif mode == "Ends With":
|
||||||
return a.endswith(b),
|
return a.endswith(b),
|
||||||
|
|
||||||
|
|
||||||
class RegexMatch():
|
class RegexMatch():
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@ -299,6 +305,7 @@ class RegexExtract():
|
|||||||
|
|
||||||
class RegexReplace():
|
class RegexReplace():
|
||||||
DESCRIPTION = "Find and replace text using regex patterns."
|
DESCRIPTION = "Find and replace text using regex patterns."
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {
|
return {
|
||||||
@ -331,6 +338,7 @@ class RegexReplace():
|
|||||||
result = re.sub(regex_pattern, replace, string, count=count, flags=flags)
|
result = re.sub(regex_pattern, replace, string, count=count, flags=flags)
|
||||||
return result,
|
return result,
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"StringConcatenate": StringConcatenate,
|
"StringConcatenate": StringConcatenate,
|
||||||
"StringSubstring": StringSubstring,
|
"StringSubstring": StringSubstring,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user