fix: ✨ refactor
This commit is contained in:
+13
-20
@@ -45,19 +45,15 @@ def extract_nodes_from_source(filename):
|
||||
if isinstance(target, ast.Name) and target.id == "__nodes__":
|
||||
value = ast.get_source_segment(source_code, node.value)
|
||||
node_value = ast.parse(value).body[0].value
|
||||
if isinstance(node_value, ast.List) or isinstance(
|
||||
node_value, ast.Tuple
|
||||
):
|
||||
for element in node_value.elts:
|
||||
if isinstance(element, ast.Name):
|
||||
print(element.id)
|
||||
nodes.append(element.id)
|
||||
|
||||
if isinstance(node_value, (ast.List, ast.Tuple)):
|
||||
nodes.extend(
|
||||
element.id
|
||||
for element in node_value.elts
|
||||
if isinstance(element, ast.Name)
|
||||
)
|
||||
break
|
||||
except SyntaxError:
|
||||
log.error("Failed to parse")
|
||||
pass # File couldn't be parsed
|
||||
|
||||
return nodes
|
||||
|
||||
|
||||
@@ -240,11 +236,10 @@ if hasattr(PromptServer, "instance"):
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.debug("Debug mode set from API (/mtb/debug POST route)")
|
||||
|
||||
else:
|
||||
if "MTB_DEBUG" in os.environ:
|
||||
# del os.environ["MTB_DEBUG"]
|
||||
os.environ.pop("MTB_DEBUG")
|
||||
log.setLevel(logging.INFO)
|
||||
elif "MTB_DEBUG" in os.environ:
|
||||
# del os.environ["MTB_DEBUG"]
|
||||
os.environ.pop("MTB_DEBUG")
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
return web.json_response(
|
||||
{"message": f"Debug mode {'set' if enabled else 'unset'}"}
|
||||
@@ -258,7 +253,7 @@ if hasattr(PromptServer, "instance"):
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
html_response = f"""
|
||||
html_response = """
|
||||
<div class="flex-container menu">
|
||||
<a href="/mtb/debug">debug</a>
|
||||
<a href="/mtb/status">status</a>
|
||||
@@ -277,9 +272,7 @@ if hasattr(PromptServer, "instance"):
|
||||
from . import endpoint
|
||||
|
||||
reload(endpoint)
|
||||
enabled = False
|
||||
if "MTB_DEBUG" in os.environ:
|
||||
enabled = True
|
||||
enabled = "MTB_DEBUG" in os.environ
|
||||
# Check if the request prefers HTML content
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
# # Return an HTML page
|
||||
@@ -299,7 +292,7 @@ if hasattr(PromptServer, "instance"):
|
||||
from . import endpoint
|
||||
|
||||
if "text/html" in request.headers.get("Accept", ""):
|
||||
html_response = f"""
|
||||
html_response = """
|
||||
<h1>Actions has no get for now...</h1>
|
||||
"""
|
||||
return web.Response(
|
||||
|
||||
@@ -3,7 +3,6 @@ import re
|
||||
import os
|
||||
|
||||
base_log_level = logging.DEBUG if os.environ.get("MTB_DEBUG") else logging.INFO
|
||||
print(f"Log level: {base_log_level}")
|
||||
|
||||
|
||||
# Custom object that discards the output
|
||||
|
||||
+54
-32
@@ -5,7 +5,7 @@ import urllib.parse
|
||||
import torch
|
||||
import json
|
||||
from comfy.cli_args import args
|
||||
from ..utils import pil2tensor
|
||||
from ..utils import pil2tensor, apply_easing
|
||||
import io
|
||||
import numpy as np
|
||||
|
||||
@@ -40,7 +40,7 @@ class GetBatchFromHistory:
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = "images"
|
||||
RETURN_NAMES = ("images",)
|
||||
CATEGORY = "mtb/animation"
|
||||
FUNCTION = "load_from_history"
|
||||
|
||||
@@ -69,41 +69,32 @@ class GetBatchFromHistory:
|
||||
history = json.loads(response.read())
|
||||
|
||||
output_images = []
|
||||
for k, run in history.items():
|
||||
for o in run["outputs"]:
|
||||
for node_id in run["outputs"]:
|
||||
node_output = run["outputs"][node_id]
|
||||
if "images" in node_output:
|
||||
images_output = []
|
||||
for image in node_output["images"]:
|
||||
image_data = get_image(
|
||||
image["filename"], image["subfolder"], image["type"]
|
||||
)
|
||||
images_output.append(image_data)
|
||||
output_images.extend(images_output)
|
||||
|
||||
for run in history.values():
|
||||
for node_output in run["outputs"].values():
|
||||
if "images" in node_output:
|
||||
for image in node_output["images"]:
|
||||
image_data = get_image(
|
||||
image["filename"], image["subfolder"], image["type"]
|
||||
)
|
||||
output_images.append(image_data)
|
||||
|
||||
if not output_images:
|
||||
return (torch.zeros(0),)
|
||||
for i, image in enumerate(list(reversed(output_images))):
|
||||
if i < offset:
|
||||
continue
|
||||
if i >= offset + count:
|
||||
break
|
||||
# Decode image as tensor
|
||||
img = Image.open(image)
|
||||
log.debug(f"Image from history {i} of shape {img.size}")
|
||||
frames.append(img)
|
||||
|
||||
# Display the shape of the tensor
|
||||
# print("Tensor shape:", image_tensor.shape)
|
||||
# Directly get desired range of images
|
||||
start_index = max(len(output_images) - offset - count, 0)
|
||||
end_index = len(output_images) - offset
|
||||
selected_images = output_images[start_index:end_index]
|
||||
|
||||
frames = [Image.open(image) for image in selected_images]
|
||||
|
||||
# return (output_images,)
|
||||
if not frames:
|
||||
return (torch.zeros(0),)
|
||||
elif len(frames) != count:
|
||||
log.warning(f"Expected {count} images, got {len(frames)} instead")
|
||||
output = pil2tensor(
|
||||
list(reversed(frames)),
|
||||
)
|
||||
|
||||
output = pil2tensor(frames)
|
||||
|
||||
return (output,)
|
||||
|
||||
@@ -181,6 +172,33 @@ class FitNumber:
|
||||
"source_max": ("FLOAT", {"default": 1.0}),
|
||||
"target_min": ("FLOAT", {"default": 0.0}),
|
||||
"target_max": ("FLOAT", {"default": 1.0}),
|
||||
"easing": (
|
||||
[
|
||||
"Linear",
|
||||
"Sine In",
|
||||
"Sine Out",
|
||||
"Sine In/Out",
|
||||
"Quart In",
|
||||
"Quart Out",
|
||||
"Quart In/Out",
|
||||
"Cubic In",
|
||||
"Cubic Out",
|
||||
"Cubic In/Out",
|
||||
"Circ In",
|
||||
"Circ Out",
|
||||
"Circ In/Out",
|
||||
"Back In",
|
||||
"Back Out",
|
||||
"Back In/Out",
|
||||
"Elastic In",
|
||||
"Elastic Out",
|
||||
"Elastic In/Out",
|
||||
"Bounce In",
|
||||
"Bounce Out",
|
||||
"Bounce In/Out",
|
||||
],
|
||||
{"default": "Linear"},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,10 +214,14 @@ class FitNumber:
|
||||
source_max: float,
|
||||
target_min: float,
|
||||
target_max: float,
|
||||
easing: str,
|
||||
):
|
||||
res = target_min + (target_max - target_min) * (value - source_min) / (
|
||||
source_max - source_min
|
||||
)
|
||||
normalized_value = (value - source_min) / (source_max - source_min)
|
||||
|
||||
eased_value = apply_easing(normalized_value, easing)
|
||||
|
||||
# - Convert the eased value to the target range
|
||||
res = target_min + (target_max - target_min) * eased_value
|
||||
|
||||
if clamp:
|
||||
if target_min > target_max:
|
||||
|
||||
@@ -4,30 +4,34 @@ import torch
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import List
|
||||
from .log import log
|
||||
import signal
|
||||
from contextlib import suppress
|
||||
from queue import Queue, Empty
|
||||
import subprocess
|
||||
import threading
|
||||
import os
|
||||
import math
|
||||
|
||||
# - detect mode
|
||||
comfy_mode = None
|
||||
if os.environ.get("COLAB_GPU"):
|
||||
comfy_mode = "colab"
|
||||
elif "python_embeded" in sys.executable:
|
||||
comfy_mode = "embeded"
|
||||
elif ".venv" in sys.executable:
|
||||
comfy_mode = "venv"
|
||||
try:
|
||||
from .log import log
|
||||
except ImportError:
|
||||
try:
|
||||
from log import log
|
||||
|
||||
log.warn("Imported log without relative path")
|
||||
except ImportError:
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("comfy mtb utils")
|
||||
log.warn("[comfy mtb] You probably called the file outside a module.")
|
||||
|
||||
|
||||
# region MISC Utilities
|
||||
def hex_to_rgb(hex_color):
|
||||
hex_color = hex_color.lstrip("#")
|
||||
return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
|
||||
|
||||
|
||||
# region MISC Utilities
|
||||
def add_path(path, prepend=False):
|
||||
if isinstance(path, list):
|
||||
for p in path:
|
||||
@@ -143,7 +147,17 @@ def import_install(package_name):
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# region GLOBAL VARIABLES
|
||||
# - detect mode
|
||||
comfy_mode = None
|
||||
if os.environ.get("COLAB_GPU"):
|
||||
comfy_mode = "colab"
|
||||
elif "python_embeded" in sys.executable:
|
||||
comfy_mode = "embeded"
|
||||
elif ".venv" in sys.executable:
|
||||
comfy_mode = "venv"
|
||||
|
||||
# - Get the absolute path of the parent directory of the current script
|
||||
here = Path(__file__).parent.resolve()
|
||||
|
||||
@@ -172,8 +186,6 @@ PIL_FILTER_MAP = {
|
||||
"bicubic": Image.Resampling.BICUBIC,
|
||||
"lanczos": Image.Resampling.LANCZOS,
|
||||
}
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
@@ -260,3 +272,194 @@ def download_antelopev2():
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# region UV Utilities
|
||||
|
||||
|
||||
def create_uv_map_tensor(width=512, height=512):
|
||||
u = torch.linspace(0.0, 1.0, steps=width)
|
||||
v = torch.linspace(0.0, 1.0, steps=height)
|
||||
|
||||
U, V = torch.meshgrid(u, v)
|
||||
|
||||
uv_map = torch.zeros(height, width, 3, dtype=torch.float32)
|
||||
uv_map[:, :, 0] = U.t()
|
||||
uv_map[:, :, 1] = V.t()
|
||||
|
||||
return uv_map.unsqueeze(0)
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# region ANIMATION Utilities
|
||||
def apply_easing(value, easing_type):
|
||||
if value < 0 or value > 1:
|
||||
raise ValueError("The value should be between 0 and 1.")
|
||||
|
||||
if easing_type == "Linear":
|
||||
return value
|
||||
|
||||
# Back easing functions
|
||||
def easeInBack(t):
|
||||
s = 1.70158
|
||||
return t * t * ((s + 1) * t - s)
|
||||
|
||||
def easeOutBack(t):
|
||||
s = 1.70158
|
||||
return ((t - 1) * t * ((s + 1) * t + s)) + 1
|
||||
|
||||
def easeInOutBack(t):
|
||||
s = 1.70158 * 1.525
|
||||
if t < 0.5:
|
||||
return (t * t * (t * (s + 1) - s)) * 2
|
||||
return ((t - 2) * t * ((s + 1) * t + s) + 2) * 2
|
||||
|
||||
# Elastic easing functions
|
||||
def easeInElastic(t):
|
||||
if t == 0:
|
||||
return 0
|
||||
if t == 1:
|
||||
return 1
|
||||
p = 0.3
|
||||
s = p / 4
|
||||
return -(math.pow(2, 10 * (t - 1)) * math.sin((t - 1 - s) * (2 * math.pi) / p))
|
||||
|
||||
def easeOutElastic(t):
|
||||
if t == 0:
|
||||
return 0
|
||||
if t == 1:
|
||||
return 1
|
||||
p = 0.3
|
||||
s = p / 4
|
||||
return math.pow(2, -10 * t) * math.sin((t - s) * (2 * math.pi) / p) + 1
|
||||
|
||||
def easeInOutElastic(t):
|
||||
if t == 0:
|
||||
return 0
|
||||
if t == 1:
|
||||
return 1
|
||||
p = 0.3 * 1.5
|
||||
s = p / 4
|
||||
t = t * 2
|
||||
if t < 1:
|
||||
return -0.5 * (
|
||||
math.pow(2, 10 * (t - 1)) * math.sin((t - 1 - s) * (2 * math.pi) / p)
|
||||
)
|
||||
return (
|
||||
0.5 * math.pow(2, -10 * (t - 1)) * math.sin((t - 1 - s) * (2 * math.pi) / p)
|
||||
+ 1
|
||||
)
|
||||
|
||||
# Bounce easing functions
|
||||
def easeInBounce(t):
|
||||
return 1 - easeOutBounce(1 - t)
|
||||
|
||||
def easeOutBounce(t):
|
||||
if t < (1 / 2.75):
|
||||
return 7.5625 * t * t
|
||||
elif t < (2 / 2.75):
|
||||
t -= 1.5 / 2.75
|
||||
return 7.5625 * t * t + 0.75
|
||||
elif t < (2.5 / 2.75):
|
||||
t -= 2.25 / 2.75
|
||||
return 7.5625 * t * t + 0.9375
|
||||
else:
|
||||
t -= 2.625 / 2.75
|
||||
return 7.5625 * t * t + 0.984375
|
||||
|
||||
def easeInOutBounce(t):
|
||||
if t < 0.5:
|
||||
return easeInBounce(t * 2) * 0.5
|
||||
return easeOutBounce(t * 2 - 1) * 0.5 + 0.5
|
||||
|
||||
# Quart easing functions
|
||||
def easeInQuart(t):
|
||||
return t * t * t * t
|
||||
|
||||
def easeOutQuart(t):
|
||||
t -= 1
|
||||
return -(t**2 * t * t - 1)
|
||||
|
||||
def easeInOutQuart(t):
|
||||
t *= 2
|
||||
if t < 1:
|
||||
return 0.5 * t * t * t * t
|
||||
t -= 2
|
||||
return -0.5 * (t**2 * t * t - 2)
|
||||
|
||||
# Cubic easing functions
|
||||
def easeInCubic(t):
|
||||
return t * t * t
|
||||
|
||||
def easeOutCubic(t):
|
||||
t -= 1
|
||||
return t**2 * t + 1
|
||||
|
||||
def easeInOutCubic(t):
|
||||
t *= 2
|
||||
if t < 1:
|
||||
return 0.5 * t * t * t
|
||||
t -= 2
|
||||
return 0.5 * (t**2 * t + 2)
|
||||
|
||||
# Circ easing functions
|
||||
def easeInCirc(t):
|
||||
return -(math.sqrt(1 - t * t) - 1)
|
||||
|
||||
def easeOutCirc(t):
|
||||
t -= 1
|
||||
return math.sqrt(1 - t**2)
|
||||
|
||||
def easeInOutCirc(t):
|
||||
t *= 2
|
||||
if t < 1:
|
||||
return -0.5 * (math.sqrt(1 - t**2) - 1)
|
||||
t -= 2
|
||||
return 0.5 * (math.sqrt(1 - t**2) + 1)
|
||||
|
||||
# Sine easing functions
|
||||
def easeInSine(t):
|
||||
return -math.cos(t * (math.pi / 2)) + 1
|
||||
|
||||
def easeOutSine(t):
|
||||
return math.sin(t * (math.pi / 2))
|
||||
|
||||
def easeInOutSine(t):
|
||||
return -0.5 * (math.cos(math.pi * t) - 1)
|
||||
|
||||
easing_functions = {
|
||||
"Sine In": easeInSine,
|
||||
"Sine Out": easeOutSine,
|
||||
"Sine In/Out": easeInOutSine,
|
||||
"Quart In": easeInQuart,
|
||||
"Quart Out": easeOutQuart,
|
||||
"Quart In/Out": easeInOutQuart,
|
||||
"Cubic In": easeInCubic,
|
||||
"Cubic Out": easeOutCubic,
|
||||
"Cubic In/Out": easeInOutCubic,
|
||||
"Circ In": easeInCirc,
|
||||
"Circ Out": easeOutCirc,
|
||||
"Circ In/Out": easeInOutCirc,
|
||||
"Back In": easeInBack,
|
||||
"Back Out": easeOutBack,
|
||||
"Back In/Out": easeInOutBack,
|
||||
"Elastic In": easeInElastic,
|
||||
"Elastic Out": easeOutElastic,
|
||||
"Elastic In/Out": easeInOutElastic,
|
||||
"Bounce In": easeInBounce,
|
||||
"Bounce Out": easeOutBounce,
|
||||
"Bounce In/Out": easeInOutBounce,
|
||||
}
|
||||
|
||||
function_ease = easing_functions.get(easing_type)
|
||||
if function_ease:
|
||||
return function_ease(value)
|
||||
|
||||
log.error(f"Unknown easing type: {easing_type}")
|
||||
log.error(f"Available easing types: {list(easing_functions.keys())}")
|
||||
raise ValueError(f"Unknown easing type: {easing_type}")
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user