Support UDIM images
This commit is contained in:
parent
4ebd535b5f
commit
843c34c3c0
@ -3,6 +3,10 @@
|
|||||||
This file logs the changes that are actually interesting to users (new features,
|
This file logs the changes that are actually interesting to users (new features,
|
||||||
changed functionality, fixed bugs).
|
changed functionality, fixed bugs).
|
||||||
|
|
||||||
|
# Version 1.11 (in development)
|
||||||
|
|
||||||
|
- Support UDIM images.
|
||||||
|
|
||||||
# Version 1.10 (2022-02-03)
|
# Version 1.10 (2022-02-03)
|
||||||
|
|
||||||
- Avoid doubly-compressing ZStandard (Blender 3) compressed files.
|
- Avoid doubly-compressing ZStandard (Blender 3) compressed files.
|
||||||
|
|||||||
@ -32,6 +32,7 @@ SEQ_TYPE_EFFECT = 8
|
|||||||
IMA_SRC_FILE = 1
|
IMA_SRC_FILE = 1
|
||||||
IMA_SRC_SEQUENCE = 2
|
IMA_SRC_SEQUENCE = 2
|
||||||
IMA_SRC_MOVIE = 3
|
IMA_SRC_MOVIE = 3
|
||||||
|
IMA_SRC_TILED = 6 # UDIM
|
||||||
|
|
||||||
# DNA_modifier_types.h
|
# DNA_modifier_types.h
|
||||||
eModifierType_Wave = 7
|
eModifierType_Wave = 7
|
||||||
|
|||||||
@ -555,7 +555,7 @@ class Packer:
|
|||||||
def _copy_asset_and_deps(self, asset_path: pathlib.Path, action: AssetAction):
|
def _copy_asset_and_deps(self, asset_path: pathlib.Path, action: AssetAction):
|
||||||
# Copy the asset itself, but only if it's not a sequence (sequences are
|
# Copy the asset itself, but only if it's not a sequence (sequences are
|
||||||
# handled below in the for-loop).
|
# handled below in the for-loop).
|
||||||
if "*" not in str(asset_path):
|
if "*" not in str(asset_path) and '<UDIM>' not in asset_path.name:
|
||||||
packed_path = action.new_path
|
packed_path = action.new_path
|
||||||
assert packed_path is not None
|
assert packed_path is not None
|
||||||
read_path = action.read_from or asset_path
|
read_path = action.read_from or asset_path
|
||||||
|
|||||||
@ -96,11 +96,13 @@ def image(block: blendfile.BlendFileBlock) -> typing.Iterator[result.BlockUsage]
|
|||||||
cdefs.IMA_SRC_FILE,
|
cdefs.IMA_SRC_FILE,
|
||||||
cdefs.IMA_SRC_SEQUENCE,
|
cdefs.IMA_SRC_SEQUENCE,
|
||||||
cdefs.IMA_SRC_MOVIE,
|
cdefs.IMA_SRC_MOVIE,
|
||||||
|
cdefs.IMA_SRC_TILED,
|
||||||
}:
|
}:
|
||||||
|
log.debug("skiping image source type %s", image_source)
|
||||||
return
|
return
|
||||||
|
|
||||||
pathname, field = block.get(b"name", return_field=True)
|
pathname, field = block.get(b"name", return_field=True)
|
||||||
is_sequence = image_source == cdefs.IMA_SRC_SEQUENCE
|
is_sequence = image_source in {cdefs.IMA_SRC_SEQUENCE, cdefs.IMA_SRC_TILED}
|
||||||
|
|
||||||
yield result.BlockUsage(block, pathname, is_sequence, path_full_field=field)
|
yield result.BlockUsage(block, pathname, is_sequence, path_full_field=field)
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,12 @@ def expand_sequence(path: pathlib.Path) -> typing.Iterator[pathlib.Path]:
|
|||||||
or the path of the first file in the sequence.
|
or the path of the first file in the sequence.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if "<UDIM>" in path.name: # UDIM tiles
|
||||||
|
# Change <UDIM> marker to a glob pattern, then let the glob case handle it.
|
||||||
|
# This assumes that all files that match the glob are actually UDIM
|
||||||
|
# tiles; this could cause some false-positives.
|
||||||
|
path = path.with_name(path.name.replace('<UDIM>', '*'))
|
||||||
|
|
||||||
if "*" in str(path): # assume it is a glob
|
if "*" in str(path): # assume it is a glob
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
@ -46,7 +52,6 @@ def expand_sequence(path: pathlib.Path) -> typing.Iterator[pathlib.Path]:
|
|||||||
for fname in sorted(glob.glob(str(path), recursive=True)):
|
for fname in sorted(glob.glob(str(path), recursive=True)):
|
||||||
yield pathlib.Path(fname)
|
yield pathlib.Path(fname)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise DoesNotExist(path)
|
raise DoesNotExist(path)
|
||||||
|
|
||||||
|
|||||||
BIN
tests/blendfiles/udim/cube_UDIM.color.1001.png
Normal file
BIN
tests/blendfiles/udim/cube_UDIM.color.1001.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 B |
BIN
tests/blendfiles/udim/cube_UDIM.color.1002.png
Normal file
BIN
tests/blendfiles/udim/cube_UDIM.color.1002.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 B |
BIN
tests/blendfiles/udim/cube_UDIM.color.1003.png
Normal file
BIN
tests/blendfiles/udim/cube_UDIM.color.1003.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 187 B |
BIN
tests/blendfiles/udim/v01_UDIM_BAT_debugging.blend
Normal file
BIN
tests/blendfiles/udim/v01_UDIM_BAT_debugging.blend
Normal file
Binary file not shown.
@ -366,6 +366,21 @@ class PackTest(AbstractPackTest):
|
|||||||
self.assertEqual(b"SQ000210.png", seq[b"name"])
|
self.assertEqual(b"SQ000210.png", seq[b"name"])
|
||||||
self.assertEqual(relpath, seq_strip[b"dir"])
|
self.assertEqual(relpath, seq_strip[b"dir"])
|
||||||
|
|
||||||
|
def test_sequence_udim(self):
|
||||||
|
# UDIM tiles are special, because the filename itself has a <UDIM>
|
||||||
|
# marker in there and thus doesn't exist itself.
|
||||||
|
ppath = self.blendfiles / "udim"
|
||||||
|
infile = ppath / "v01_UDIM_BAT_debugging.blend"
|
||||||
|
|
||||||
|
with pack.Packer(infile, ppath, self.tpath) as packer:
|
||||||
|
packer.strategise()
|
||||||
|
packer.execute()
|
||||||
|
|
||||||
|
# The UDIM files should have been copied.
|
||||||
|
self.assertTrue((self.tpath / "cube_UDIM.color.1001.png").exists())
|
||||||
|
self.assertTrue((self.tpath / "cube_UDIM.color.1002.png").exists())
|
||||||
|
self.assertTrue((self.tpath / "cube_UDIM.color.1003.png").exists())
|
||||||
|
|
||||||
def test_noop(self):
|
def test_noop(self):
|
||||||
ppath = self.blendfiles / "subdir"
|
ppath = self.blendfiles / "subdir"
|
||||||
infile = ppath / "doubly_linked_up.blend"
|
infile = ppath / "doubly_linked_up.blend"
|
||||||
|
|||||||
@ -62,7 +62,6 @@ class AssetHoldingBlocksTest(AbstractTracerTest):
|
|||||||
self.assertEqual(965, len(self.bf.blocks))
|
self.assertEqual(965, len(self.bf.blocks))
|
||||||
self.assertEqual(4, blocks_seen)
|
self.assertEqual(4, blocks_seen)
|
||||||
|
|
||||||
|
|
||||||
class DepsTest(AbstractTracerTest):
|
class DepsTest(AbstractTracerTest):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def field_name(field: dna.Field) -> typing.Optional[str]:
|
def field_name(field: dna.Field) -> typing.Optional[str]:
|
||||||
@ -189,6 +188,19 @@ class DepsTest(AbstractTracerTest):
|
|||||||
actual = list(dep.files())
|
actual = list(dep.files())
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_seq_image_udim_sequence(self):
|
||||||
|
expects = {
|
||||||
|
b"IMcube_UDIM.color": Expect(
|
||||||
|
'Image',
|
||||||
|
'name[1024]',
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
b'//cube_UDIM.color.<UDIM>.png',
|
||||||
|
True,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
self.assert_deps("udim/v01_UDIM_BAT_debugging.blend", expects)
|
||||||
|
|
||||||
def test_block_cf(self):
|
def test_block_cf(self):
|
||||||
self.assert_deps(
|
self.assert_deps(
|
||||||
"alembic-user.blend",
|
"alembic-user.blend",
|
||||||
|
|||||||
@ -20,6 +20,14 @@ class ExpandFileSequenceTest(AbstractBlendFileTest):
|
|||||||
actual = list(file_sequence.expand_sequence(path))
|
actual = list(file_sequence.expand_sequence(path))
|
||||||
self.assertEqual(self.imgseq, actual)
|
self.assertEqual(self.imgseq, actual)
|
||||||
|
|
||||||
|
def test_udim_sequence(self):
|
||||||
|
path = self.blendfiles / "udim/cube_UDIM.color.<UDIM>.png"
|
||||||
|
actual = list(file_sequence.expand_sequence(path))
|
||||||
|
imgseq = [
|
||||||
|
self.blendfiles / ("udim/cube_UDIM.color.%04d.png" % num) for num in range(1001, 1004)
|
||||||
|
]
|
||||||
|
self.assertEqual(imgseq, actual)
|
||||||
|
|
||||||
def test_nonexistent(self):
|
def test_nonexistent(self):
|
||||||
path = self.blendfiles / "nonexistant"
|
path = self.blendfiles / "nonexistant"
|
||||||
with self.assertRaises(file_sequence.DoesNotExist) as raises:
|
with self.assertRaises(file_sequence.DoesNotExist) as raises:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user