Resolution Master is renamed Latent Size: the old name belongs to another
node pack. The node id AUSBOSS_NODES_Resolution is unchanged, so saved
workflows and API graphs load and run as before. Workflows only store a
title that differs from the default, so they pick up the new name; a saved
title that starts with "Resolution Master 🆎" gets the new name in its
place on load. The example, its thumbnail and the README image follow.
- Latent Size can be resized: wider stretches the chips, fields and size
picks, and taller gives the stage the room. It opens at 340 x 531 as
before and goes down to 320, where the size row tightens so W, H and MP
stay whole.
- LoRA Loader: gear -> Long names, end (the default, as before) or middle,
which keeps the checkpoint number at the end of a name in view. The
picker opens wide enough for long names and shortens the folder first.
- The frontend adds 104 px to a DOM panel's minWidth before using it as
the node's floor (LGraphNode.computeSize), so a node that opened
narrower jumped wider the moment its corner was touched: the LoRA Loader
could not go under 424. fillNodeHeight gains exactMinWidth, which
measures that padding and takes it back off, and holdVueNodeMinWidth
lends the floor to Nodes 2.0, whose corner drag reads the node's inline
min-width instead. Both nodes use them; the other panels keep their old
floors for now.
- README: the workflow-tools image shows Latent Size alone; the Seed card
is gone.
70 lines
2.8 KiB
Python
70 lines
2.8 KiB
Python
"""Latent Size 🆎 backend: clamping and the latent output."""
|
|
|
|
import sys
|
|
import unittest
|
|
from unittest.mock import patch
|
|
from types import SimpleNamespace
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from nodes.node_resolution import (
|
|
DIM_MAX,
|
|
DIM_MIN,
|
|
LATENT_FAMILIES,
|
|
clamp_dimension,
|
|
latent_shape,
|
|
)
|
|
|
|
from nodes import node_resolution
|
|
ResolutionNode = getattr(node_resolution, "AusBossResolution", getattr(node_resolution, "AusBossLabResolution", None))
|
|
|
|
|
|
class TestClampDimension(unittest.TestCase):
|
|
def test_passthrough_and_clamp(self):
|
|
self.assertEqual(clamp_dimension(1344), 1344)
|
|
self.assertEqual(clamp_dimension(5), DIM_MIN)
|
|
self.assertEqual(clamp_dimension(999999), DIM_MAX)
|
|
|
|
def test_junk_falls_back(self):
|
|
self.assertEqual(clamp_dimension("wide"), 1024)
|
|
self.assertEqual(clamp_dimension(None), 1024)
|
|
self.assertEqual(clamp_dimension(float("inf")), 1024)
|
|
|
|
|
|
class TestLatentShape(unittest.TestCase):
|
|
def test_families_match_the_core_empty_latent_nodes(self):
|
|
# EmptySD3LatentImage: [b, 16, h//8, w//8]; EmptyLatentImage: [b, 4, h//8, w//8];
|
|
# EmptyFlux2LatentImage: [b, 128, h//16, w//16].
|
|
self.assertEqual(latent_shape(1024, 768, "16ch", 1), (1, 16, 96, 128))
|
|
self.assertEqual(latent_shape(1024, 768, "4ch", 2), (2, 4, 96, 128))
|
|
self.assertEqual(latent_shape(1024, 768, "128ch", 1), (1, 128, 48, 64))
|
|
|
|
def test_unknown_family_and_bad_batch_fall_back(self):
|
|
self.assertEqual(latent_shape(512, 512, "nope", "x"), (1, 16, 64, 64))
|
|
self.assertEqual(latent_shape(512, 512, "16ch", 999), (64, 16, 64, 64))
|
|
|
|
def test_combo_options_are_the_family_labels(self):
|
|
options = ResolutionNode.INPUT_TYPES()["optional"]["latent"][0]
|
|
self.assertEqual(options, list(LATENT_FAMILIES))
|
|
|
|
|
|
class TestResolve(unittest.TestCase):
|
|
def test_typed_values_survive_exactly_and_the_latent_follows(self):
|
|
# Snap governs gestures; the backend never re-snaps 1920x1080.
|
|
fake_torch = SimpleNamespace(zeros=lambda shape, **kwargs: SimpleNamespace(shape=tuple(shape)))
|
|
with patch("nodes.node_resolution.torch", fake_torch), patch("nodes.node_resolution.model_management", None):
|
|
width, height, latent = ResolutionNode().resolve(1920, 1080)
|
|
self.assertEqual((width, height), (1920, 1080))
|
|
samples = latent["samples"]
|
|
shape = tuple(samples.shape) if samples is not None else latent["shape"]
|
|
self.assertEqual(shape, (1, 16, 135, 240))
|
|
|
|
def test_outputs_are_width_height_latent(self):
|
|
self.assertEqual(ResolutionNode.RETURN_NAMES, ("width", "height", "latent"))
|
|
self.assertEqual(ResolutionNode.RETURN_TYPES, ("INT", "INT", "LATENT"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|