diff --git a/blender_asset_tracer/pack/__init__.py b/blender_asset_tracer/pack/__init__.py index 583b6e3..c26a566 100644 --- a/blender_asset_tracer/pack/__init__.py +++ b/blender_asset_tracer/pack/__init__.py @@ -27,7 +27,7 @@ import threading import typing from blender_asset_tracer import trace, bpathlib, blendfile -from blender_asset_tracer.trace import result +from blender_asset_tracer.trace import file_sequence, result from . import filesystem, transfer, progress log = logging.getLogger(__name__) @@ -187,7 +187,13 @@ class Packer: raise Aborted() def exclude(self, *globs: str): - """Register glob-compatible patterns of files that should be ignored.""" + """Register glob-compatible patterns of files that should be ignored. + + Must be called before calling strategise(). + """ + if self._actions: + raise RuntimeError('%s.exclude() must be called before strategise()' % + self.__class__.__qualname__) self._exclude_globs.update(globs) def strategise(self) -> None: @@ -196,6 +202,10 @@ class Packer: Places an asset into one of these categories: - Can be copied as-is, nothing smart required. - Blend files referring to this asset need to be rewritten. + + This function does *not* expand globs. Globs are seen as single + assets, and are only evaluated when performing the actual transfer + in the execute() function. """ # The blendfile that we pack is generally not its own dependency, so @@ -219,30 +229,55 @@ class Packer: log.info('Excluding file: %s', asset_path) continue - if not asset_path.exists(): - log.warning('Missing file: %s', asset_path) - self.missing_files.add(asset_path) - self._progress_cb.missing_file(asset_path) - continue - - self._visit_asset(asset_path, usage) + if usage.is_sequence: + self._visit_sequence(asset_path, usage) + else: + self._visit_asset(asset_path, usage) self._find_new_paths() self._group_rewrites() + def _visit_sequence(self, asset_path: pathlib.Path, usage: result.BlockUsage): + assert usage.is_sequence + + for first_path in file_sequence.expand_sequence(asset_path): + if first_path.exists(): + break + else: + # At least the first file of a sequence must exist. + log.warning('Missing file: %s', asset_path) + self.missing_files.add(asset_path) + self._progress_cb.missing_file(asset_path) + return + + # Handle this sequence as an asset. + self._visit_asset(asset_path, usage) + def _visit_asset(self, asset_path: pathlib.Path, usage: result.BlockUsage): """Determine what to do with this asset. Determines where this asset will be packed, whether it needs rewriting, and records the blend file data block referring to it. """ + + # Sequences are allowed to not exist at this point. + if not usage.is_sequence and not asset_path.exists(): + log.warning('Missing file: %s', asset_path) + self.missing_files.add(asset_path) + self._progress_cb.missing_file(asset_path) + return + bfile_path = usage.block.bfile.filepath.absolute() self._progress_cb.trace_asset(asset_path) # Needing rewriting is not a per-asset thing, but a per-asset-per- # blendfile thing, since different blendfiles can refer to it in # different ways (for example with relative and absolute paths). - path_in_project = self._path_in_project(asset_path) + if usage.is_sequence: + first_path = next(file_sequence.expand_sequence(asset_path)) + else: + first_path = asset_path + path_in_project = self._path_in_project(first_path) use_as_is = usage.asset_path.is_blendfile_relative() and path_in_project needs_rewriting = not use_as_is @@ -428,11 +463,13 @@ class Packer: bfile.close() def _copy_asset_and_deps(self, asset_path: pathlib.Path, action: AssetAction): - # Copy the asset itself. - packed_path = action.new_path - read_path = action.read_from or asset_path - self._send_to_target(read_path, packed_path, - may_move=action.read_from is not None) + # Copy the asset itself, but only if it's not a sequence (sequences are + # handled below in the for-loop). + if '*' not in str(asset_path): + packed_path = action.new_path + read_path = action.read_from or asset_path + self._send_to_target(read_path, packed_path, + may_move=action.read_from is not None) # Copy its sequence dependencies. for usage in action.usages: diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000000_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000000_01.bphys new file mode 100644 index 0000000..3478db3 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000000_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000001_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000001_01.bphys new file mode 100644 index 0000000..fecdba8 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000001_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000011_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000011_01.bphys new file mode 100644 index 0000000..1b4302c Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000011_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000021_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000021_01.bphys new file mode 100644 index 0000000..aae5a29 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000021_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000031_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000031_01.bphys new file mode 100644 index 0000000..aab7049 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000031_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000041_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000041_01.bphys new file mode 100644 index 0000000..89cfc61 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000041_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000051_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000051_01.bphys new file mode 100644 index 0000000..0ddd23d Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000051_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000061_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000061_01.bphys new file mode 100644 index 0000000..d6b4128 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000061_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000071_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000071_01.bphys new file mode 100644 index 0000000..802f753 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000071_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000081_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000081_01.bphys new file mode 100644 index 0000000..a340cbd Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000081_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000091_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000091_01.bphys new file mode 100644 index 0000000..eb39bfc Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000091_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000101_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000101_01.bphys new file mode 100644 index 0000000..e376a79 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000101_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000111_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000111_01.bphys new file mode 100644 index 0000000..7e72ab2 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000111_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000121_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000121_01.bphys new file mode 100644 index 0000000..6f245ef Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000121_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000131_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000131_01.bphys new file mode 100644 index 0000000..c321669 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000131_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000141_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000141_01.bphys new file mode 100644 index 0000000..4d1bc50 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000141_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000151_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000151_01.bphys new file mode 100644 index 0000000..3c0cb12 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000151_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000161_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000161_01.bphys new file mode 100644 index 0000000..876cd36 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000161_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000171_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000171_01.bphys new file mode 100644 index 0000000..7ebef4a Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000171_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000181_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000181_01.bphys new file mode 100644 index 0000000..13bbfaf Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000181_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000191_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000191_01.bphys new file mode 100644 index 0000000..dda7aab Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000191_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000201_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000201_01.bphys new file mode 100644 index 0000000..cd2e7e3 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000201_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000211_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000211_01.bphys new file mode 100644 index 0000000..32c9be3 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000211_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000221_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000221_01.bphys new file mode 100644 index 0000000..a2e3e3c Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000221_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000231_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000231_01.bphys new file mode 100644 index 0000000..0f40ea0 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000231_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000241_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000241_01.bphys new file mode 100644 index 0000000..a9db83e Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000241_01.bphys differ diff --git a/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000250_01.bphys b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000250_01.bphys new file mode 100644 index 0000000..7677839 Binary files /dev/null and b/tests/blendfiles/T55539-particles/blendcache_particle/43756265_000250_01.bphys differ diff --git a/tests/test_pack.py b/tests/test_pack.py index 8014d5e..96b11f0 100644 --- a/tests/test_pack.py +++ b/tests/test_pack.py @@ -371,6 +371,40 @@ class ProgressTest(AbstractPackTest): cb.missing_file.assert_has_calls(expected_calls, any_order=True) self.assertEqual(len(expected_calls), cb.missing_file.call_count) + def test_particle_cache(self): + # The particle cache uses a glob to indicate which files to pack. + cb = mock.Mock(progress.Callback) + infile = self.blendfiles / 'T55539-particles/particle.blend' + with pack.Packer(infile, self.blendfiles, self.tpath) as packer: + packer.progress_cb = cb + packer.strategise() + packer.execute() + + # We should have all the *.bphys files now. + count = len(list((self.tpath / 'T55539-particles/blendcache_particle').glob('*.bphys'))) + self.assertEqual(27, count) + + # Physics files + particle.blend + pack_info.txt + self.assertGreaterEqual(cb.transfer_progress.call_count, 29, + 'transfer_progress() should be called at least once per asset') + + def test_particle_cache_with_ignore_glob(self): + cb = mock.Mock(progress.Callback) + infile = self.blendfiles / 'T55539-particles/particle.blend' + with pack.Packer(infile, self.blendfiles, self.tpath) as packer: + packer.progress_cb = cb + packer.exclude('*.bphys') + packer.strategise() + packer.execute() + + # We should have none of the *.bphys files now. + count = len(list((self.tpath / 'T55539-particles/blendcache_particle').glob('*.bphys'))) + self.assertEqual(0, count) + + # Just particle.blend + pack_info.txt + self.assertGreaterEqual(cb.transfer_progress.call_count, 2, + 'transfer_progress() should be called at least once per asset') + class AbortTest(AbstractPackTest): def test_abort_strategise(self):