fivefury 0.2.4__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fivefury-0.2.4 → fivefury-0.2.5}/PKG-INFO +2 -2
- {fivefury-0.2.4 → fivefury-0.2.5}/README.md +1 -1
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/__init__.py +160 -2
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/yft.py +3 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/geometry.py +5 -23
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/model.py +157 -6
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/assets.py +18 -9
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/core.py +1 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/io.py +4 -2
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/scan.py +1 -1
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/views.py +18 -9
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/dlc/model.py +2 -2
- fivefury-0.2.5/fivefury/dlc/xml.py +51 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/gtxd.py +44 -14
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/__init__.py +2 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/codec.py +7 -1
- fivefury-0.2.5/fivefury/rbf.py +197 -0
- fivefury-0.2.5/fivefury/vector.py +150 -0
- {fivefury-0.2.4/fivefury/dlc → fivefury-0.2.5/fivefury}/xml.py +107 -17
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/prepare.py +10 -32
- fivefury-0.2.5/fivefury/yft/__init__.py +91 -0
- fivefury-0.2.5/fivefury/yft/constants.py +47 -0
- fivefury-0.2.5/fivefury/yft/corpus.py +66 -0
- fivefury-0.2.5/fivefury/yft/drawable_reader.py +48 -0
- fivefury-0.2.5/fivefury/yft/drawables.py +26 -0
- fivefury-0.2.5/fivefury/yft/fields_reader.py +84 -0
- fivefury-0.2.5/fivefury/yft/fragment.py +309 -0
- fivefury-0.2.5/fivefury/yft/io_helpers.py +91 -0
- fivefury-0.2.5/fivefury/yft/model.py +66 -0
- fivefury-0.2.5/fivefury/yft/physics.py +805 -0
- fivefury-0.2.5/fivefury/yft/physics_authoring.py +259 -0
- fivefury-0.2.5/fivefury/yft/physics_reader.py +680 -0
- fivefury-0.2.5/fivefury/yft/physics_writer.py +407 -0
- fivefury-0.2.5/fivefury/yft/pointers.py +66 -0
- fivefury-0.2.5/fivefury/yft/reader.py +175 -0
- fivefury-0.2.5/fivefury/yft/stats.py +20 -0
- fivefury-0.2.5/fivefury/yft/validation.py +331 -0
- fivefury-0.2.5/fivefury/yft/writer.py +406 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/timecycle.py +6 -13
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/utils.py +4 -24
- fivefury-0.2.5/fivefury/ymf/__init__.py +47 -0
- fivefury-0.2.5/fivefury/ymf/builder.py +284 -0
- fivefury-0.2.5/fivefury/ymf/enums.py +45 -0
- fivefury-0.2.5/fivefury/ymf/model.py +440 -0
- fivefury-0.2.5/fivefury/ymf/pso.py +269 -0
- fivefury-0.2.5/fivefury/ymf/resource.py +114 -0
- fivefury-0.2.5/fivefury/ymf/schema.py +119 -0
- fivefury-0.2.5/fivefury/ymf/utils.py +60 -0
- fivefury-0.2.5/fivefury/ymt/__init__.py +328 -0
- fivefury-0.2.5/fivefury/ymt/ped_metadata.py +131 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymt/ped_variation.py +37 -18
- fivefury-0.2.5/fivefury/ymt/scenario.py +139 -0
- fivefury-0.2.5/fivefury/ymt/streaming.py +133 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/model.py +2 -2
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/lod.py +2 -7
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury.egg-info/PKG-INFO +2 -2
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury.egg-info/SOURCES.txt +34 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/pyproject.toml +1 -1
- fivefury-0.2.5/tests/test_gtxd.py +252 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_pso.py +6 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ybn.py +25 -0
- fivefury-0.2.5/tests/test_yft.py +412 -0
- fivefury-0.2.5/tests/test_ymf.py +175 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ymt_ped_variation.py +40 -0
- fivefury-0.2.4/fivefury/ymf/__init__.py +0 -24
- fivefury-0.2.4/fivefury/ymt/__init__.py +0 -44
- {fivefury-0.2.4 → fivefury-0.2.5}/MANIFEST.in +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/_native.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/base.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/ydd.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/ydr.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/assets/ypt.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/audio.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/constants.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/conversion.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/crypto.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/io.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/awc/structures.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/binary.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/materials.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/bounds/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/kinds.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cache/paths.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/colors.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/common.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/crypto/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/crypto/backends.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/crypto/keys.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/analysis.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/dsl.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/events.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/flags.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/lights.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/names.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/payloads.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/pso.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/base.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/bindings.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/core.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/event_api.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/io.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/shared.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/subtitles.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/timeline.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/scene/validation.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/schema.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/write.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/cut/xml.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/data/lut.dat +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/data/magic.dat +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/data/ng.dat +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/dlc/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/dlc/enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/dlc/highlevel.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/game_target.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/gamefile.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/gxt2.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/hashing.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/backed.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/builder.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/read.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/resource.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/meta/utils.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/metahash.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/schema.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/pso/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rel/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rel/enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rel/io.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rel/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/resolver.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/resource.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/resource_textures.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rpf/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rpf/convert.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rpf/entries.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/rpf/utils.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/texture.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ybn/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/cutscene.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/sequence_channels.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/sequence_codec.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/sequence_tracks.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/sequences.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ycd/write.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydd/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydd/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydd/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydd/rigging.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydd/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/Shaders.xml +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/ShadersGen9Conversion.xml +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/_helpers.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/assimp.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/build_types.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/builder.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/collision.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/gen9.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/gen9_shader_enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/gen9_shader_info.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/materials.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/read_joints.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/read_lights.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/read_materials.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/read_skeleton.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/rigging.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/shader_enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/shader_info.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/shaders.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_buffers.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_drawable.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_geometry.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_joints.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_lights.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_materials.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_models.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ydr/write_skeleton.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/audit.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/constants.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/instructions.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/ped.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/yed/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/base.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/blocks.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/cargens.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/entities.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/enums.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/extension_defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/extensions.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/grass.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/io.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/lights.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/occluders.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/packing.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ymap/surfaces.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/heightmaps.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/network.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/regions.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynd/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynv/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynv/assimp.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynv/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynv/reader.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ynv/writer.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytd/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytd/defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytd/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/__init__.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/archetypes.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/asset_types.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/base_archetype.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/extension_defs.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/extensions.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/flags.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/helpers.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/mlo.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/model.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury/ytyp/timed_archetype.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury.egg-info/dependency_links.txt +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury.egg-info/requires.txt +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/fivefury.egg-info/top_level.txt +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/bounds_algorithms.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/bounds_algorithms.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/bounds_python.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/bounds_python.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/bounds_types.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/crypto_magic.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/crypto_magic.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_bindings.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_bindings.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_bounds.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_crypto.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_index.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_module.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_resource.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/py_rpf.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/resource_layout.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/resource_layout.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_archive.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_archive.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_crypto.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_index.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_index.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_read.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_scan.cpp +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/native/rpf_scan.h +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/setup.cfg +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/setup.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_awc.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_cut.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_cut_dsl.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_cut_no_template.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_cut_ycd.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_dlc.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_gxt2.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_hashing.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_high_level_api_consistency.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_meta_rpf_contracts.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_rel.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ycd.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ycd_cutscene_builder.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ydd.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ydr.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ydr_builder.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ydr_rigging.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ydr_shaders.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_yed.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ymt_ymf.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ynd.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ynv.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ynv_assimp.py +0 -0
- {fivefury-0.2.4 → fivefury-0.2.5}/tests/test_ytyp_flags.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fivefury
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Python library for GTA V asset workflows including YMAP, YTYP, RPF, YTD and GameFileCache utilities.
|
|
5
5
|
Author: Codex
|
|
6
6
|
License-Expression: MIT
|
|
@@ -77,7 +77,7 @@ Support levels:
|
|
|
77
77
|
|
|
78
78
|
| Format | Current behavior |
|
|
79
79
|
| --- | --- |
|
|
80
|
-
| `YFT` |
|
|
80
|
+
| `YFT` | Fragment reading/writing for common, damaged, extra and cloth drawables, including geometry, materials, LOD meshes, bounding sphere metadata, fragment flags, physics LODs, physics groups, physics children, child entity drawables, per-child breaking/inertia data, damping constants, damping archetypes, articulated body metadata, link attachments, group and child event references, editable composite bounds, mass/inertia helpers, glass/cloth/vehicle semantic queries, corpus scanning, validation, declarative physics helpers, geometry summaries and embedded texture dictionaries. |
|
|
81
81
|
| `YPT` | Resource texture dictionaries can be discovered/extracted from particle dictionaries, but full particle authoring is not implemented. |
|
|
82
82
|
| `AWC` | Audio wave containers can be read/written structurally, opened through `GameFileCache`, exported back to WAV for PCM/ADPCM streams, and built from mono or multichannel 16-bit PCM inputs decoded through `miniaudio` (`.wav`, `.mp3`, `.ogg`, `.flac`). Playback metadata lives in `.rel` banks. |
|
|
83
83
|
| `REL` | Audio metadata banks can be read/written structurally, opened through `GameFileCache`, and round-tripped with unknown entries preserved. `dat10.rel` modular synth presets/synths, `dat16.rel` curves, `dat22.rel` categories, and common `dat54.rel` sound graph entries have typed models, including simple AWC-backed sounds, wrappers, sequential/multitrack/streaming child lists, randomized variations, modular synth sounds, automation/MIDI sounds, note maps, variable-curve and conditional routing, directional/kinetic routing, variable blocks, math operations, parameter transforms, fluctuators, external streams, sound sets, sound-set lists, and sound-hash lists. Other REL item families currently stay as raw entries. |
|
|
@@ -67,7 +67,7 @@ Support levels:
|
|
|
67
67
|
|
|
68
68
|
| Format | Current behavior |
|
|
69
69
|
| --- | --- |
|
|
70
|
-
| `YFT` |
|
|
70
|
+
| `YFT` | Fragment reading/writing for common, damaged, extra and cloth drawables, including geometry, materials, LOD meshes, bounding sphere metadata, fragment flags, physics LODs, physics groups, physics children, child entity drawables, per-child breaking/inertia data, damping constants, damping archetypes, articulated body metadata, link attachments, group and child event references, editable composite bounds, mass/inertia helpers, glass/cloth/vehicle semantic queries, corpus scanning, validation, declarative physics helpers, geometry summaries and embedded texture dictionaries. |
|
|
71
71
|
| `YPT` | Resource texture dictionaries can be discovered/extracted from particle dictionaries, but full particle authoring is not implemented. |
|
|
72
72
|
| `AWC` | Audio wave containers can be read/written structurally, opened through `GameFileCache`, exported back to WAV for PCM/ADPCM streams, and built from mono or multichannel 16-bit PCM inputs decoded through `miniaudio` (`.wav`, `.mp3`, `.ogg`, `.flac`). Playback metadata lives in `.rel` banks. |
|
|
73
73
|
| `REL` | Audio metadata banks can be read/written structurally, opened through `GameFileCache`, and round-tripped with unknown entries preserved. `dat10.rel` modular synth presets/synths, `dat16.rel` curves, `dat22.rel` categories, and common `dat54.rel` sound graph entries have typed models, including simple AWC-backed sounds, wrappers, sequential/multitrack/streaming child lists, randomized variations, modular synth sounds, automation/MIDI sounds, note maps, variable-curve and conditional routing, directional/kinetic routing, variable blocks, math operations, parameter transforms, fluctuators, external streams, sound sets, sound-set lists, and sound-hash lists. Other REL item families currently stay as raw entries. |
|
|
@@ -280,7 +280,7 @@ from .gxt2 import (
|
|
|
280
280
|
save_gxt2,
|
|
281
281
|
save_gxt2_text,
|
|
282
282
|
)
|
|
283
|
-
from .gtxd import Gtxd, TxdRelationship, create_gtxd, read_gtxd, save_gtxd
|
|
283
|
+
from .gtxd import Gtxd, TxdRelationship, create_gtxd, is_gtxd_rbf, read_gtxd, read_gtxd_bytes, save_gtxd
|
|
284
284
|
from .hashing import jenk_hash
|
|
285
285
|
from .metahash import HashString, MetaHash
|
|
286
286
|
from .meta import Meta, read_meta
|
|
@@ -476,6 +476,52 @@ from .ydd import (
|
|
|
476
476
|
rig_ydd_to_bones_radially,
|
|
477
477
|
save_ydd,
|
|
478
478
|
)
|
|
479
|
+
from .yft import (
|
|
480
|
+
Yft,
|
|
481
|
+
YftArticulatedBodyType,
|
|
482
|
+
YftDrawable,
|
|
483
|
+
YftDrawableMatch,
|
|
484
|
+
YftFragmentFlag,
|
|
485
|
+
YftFragmentPointers,
|
|
486
|
+
YftFragmentState,
|
|
487
|
+
YftGeometryStats,
|
|
488
|
+
YftCorpusEntry,
|
|
489
|
+
DEFAULT_DAMPING_CONSTANTS,
|
|
490
|
+
IDENTITY_MATRIX34,
|
|
491
|
+
YftPhysicsChild,
|
|
492
|
+
YftPhysicsChildFlag,
|
|
493
|
+
YftPhysicsDampArchetype,
|
|
494
|
+
YftPhysicsDamping,
|
|
495
|
+
YftPhysicsDampingKind,
|
|
496
|
+
YftPhysicsEntity,
|
|
497
|
+
YftPhysicsEventRefs,
|
|
498
|
+
YftPhysicsGroup,
|
|
499
|
+
YftPhysicsGroupEventRefs,
|
|
500
|
+
YftPhysicsGroupFlag,
|
|
501
|
+
YftPhysicsInertia,
|
|
502
|
+
YftPhysicsJointType,
|
|
503
|
+
YftPhysicsLod,
|
|
504
|
+
YftPhysicsLodPointers,
|
|
505
|
+
YftPhysicsReference,
|
|
506
|
+
YftRawField,
|
|
507
|
+
YftValidationIssue,
|
|
508
|
+
YftValidationSeverity,
|
|
509
|
+
assert_valid_yft,
|
|
510
|
+
bound_inertia,
|
|
511
|
+
bound_mass,
|
|
512
|
+
box_inertia,
|
|
513
|
+
build_yft_bytes,
|
|
514
|
+
create_yft,
|
|
515
|
+
default_articulated_body_type,
|
|
516
|
+
default_damp_archetype,
|
|
517
|
+
iter_yft_paths,
|
|
518
|
+
normalize_physics_lod,
|
|
519
|
+
read_yft,
|
|
520
|
+
save_yft,
|
|
521
|
+
scan_yft_corpus,
|
|
522
|
+
simple_physics_bound,
|
|
523
|
+
validate_yft,
|
|
524
|
+
)
|
|
479
525
|
from .ymap import (
|
|
480
526
|
AngleMode,
|
|
481
527
|
Block,
|
|
@@ -646,11 +692,44 @@ from .yed import (
|
|
|
646
692
|
validate_yed,
|
|
647
693
|
)
|
|
648
694
|
from .ytd import Texture, TextureFormat, Ytd, read_ytd, save_ytd
|
|
649
|
-
from .ymf import
|
|
695
|
+
from .ymf import (
|
|
696
|
+
HdTxdAssetBinding,
|
|
697
|
+
ImapDependencies,
|
|
698
|
+
ImapDependency,
|
|
699
|
+
InteriorBoundsFile,
|
|
700
|
+
ItypDependencies,
|
|
701
|
+
ManifestFlags,
|
|
702
|
+
MapDataGroup,
|
|
703
|
+
PackFileMetaData,
|
|
704
|
+
PackFileMetaDataAssetType,
|
|
705
|
+
PackFileMetaDataImapGroupType,
|
|
706
|
+
Ymf,
|
|
707
|
+
YmfRelationship,
|
|
708
|
+
YmfRelationshipType,
|
|
709
|
+
build_ymf_for_ymaps,
|
|
710
|
+
build_ymf_manifest_for_ymaps,
|
|
711
|
+
build_ymf,
|
|
712
|
+
create_ymf_for_ymaps,
|
|
713
|
+
iter_ymf_relationships,
|
|
714
|
+
read_ymf,
|
|
715
|
+
read_ymf_xml,
|
|
716
|
+
save_ymf,
|
|
717
|
+
)
|
|
650
718
|
from .ymt import (
|
|
651
719
|
PedComponent,
|
|
652
720
|
PedDrawableVariation,
|
|
653
721
|
Ymt,
|
|
722
|
+
YmtAabb,
|
|
723
|
+
YmtContentType,
|
|
724
|
+
YmtFormat,
|
|
725
|
+
YmtPedInitData,
|
|
726
|
+
YmtPedMetadata,
|
|
727
|
+
YmtScenarioPointGroup,
|
|
728
|
+
YmtScenarioPointManifest,
|
|
729
|
+
YmtScenarioPointRegionDef,
|
|
730
|
+
YmtStreamingRequestCommonSet,
|
|
731
|
+
YmtStreamingRequestFrame,
|
|
732
|
+
YmtStreamingRequestRecord,
|
|
654
733
|
coerce_ped_component,
|
|
655
734
|
iter_ped_drawables,
|
|
656
735
|
ped_drawable_file_stem,
|
|
@@ -1187,6 +1266,50 @@ __all__ = [
|
|
|
1187
1266
|
"YedTrackFormat",
|
|
1188
1267
|
"YedPedExpressionBinding",
|
|
1189
1268
|
"YedValidationIssue",
|
|
1269
|
+
"Yft",
|
|
1270
|
+
"YftArticulatedBodyType",
|
|
1271
|
+
"YftDrawable",
|
|
1272
|
+
"YftDrawableMatch",
|
|
1273
|
+
"YftFragmentFlag",
|
|
1274
|
+
"YftFragmentPointers",
|
|
1275
|
+
"YftFragmentState",
|
|
1276
|
+
"YftGeometryStats",
|
|
1277
|
+
"YftCorpusEntry",
|
|
1278
|
+
"DEFAULT_DAMPING_CONSTANTS",
|
|
1279
|
+
"IDENTITY_MATRIX34",
|
|
1280
|
+
"YftPhysicsChild",
|
|
1281
|
+
"YftPhysicsChildFlag",
|
|
1282
|
+
"YftPhysicsDampArchetype",
|
|
1283
|
+
"YftPhysicsDamping",
|
|
1284
|
+
"YftPhysicsDampingKind",
|
|
1285
|
+
"YftPhysicsEntity",
|
|
1286
|
+
"YftPhysicsEventRefs",
|
|
1287
|
+
"YftPhysicsGroup",
|
|
1288
|
+
"YftPhysicsGroupEventRefs",
|
|
1289
|
+
"YftPhysicsGroupFlag",
|
|
1290
|
+
"YftPhysicsInertia",
|
|
1291
|
+
"YftPhysicsJointType",
|
|
1292
|
+
"YftPhysicsLod",
|
|
1293
|
+
"YftPhysicsLodPointers",
|
|
1294
|
+
"YftPhysicsReference",
|
|
1295
|
+
"YftRawField",
|
|
1296
|
+
"YftValidationIssue",
|
|
1297
|
+
"YftValidationSeverity",
|
|
1298
|
+
"assert_valid_yft",
|
|
1299
|
+
"bound_inertia",
|
|
1300
|
+
"bound_mass",
|
|
1301
|
+
"box_inertia",
|
|
1302
|
+
"build_yft_bytes",
|
|
1303
|
+
"create_yft",
|
|
1304
|
+
"default_articulated_body_type",
|
|
1305
|
+
"default_damp_archetype",
|
|
1306
|
+
"iter_yft_paths",
|
|
1307
|
+
"normalize_physics_lod",
|
|
1308
|
+
"read_yft",
|
|
1309
|
+
"save_yft",
|
|
1310
|
+
"scan_yft_corpus",
|
|
1311
|
+
"simple_physics_bound",
|
|
1312
|
+
"validate_yft",
|
|
1190
1313
|
"assimp_to_ynvs",
|
|
1191
1314
|
"build_junction_heightmap",
|
|
1192
1315
|
"get_ynd_area_bounds",
|
|
@@ -1206,8 +1329,29 @@ __all__ = [
|
|
|
1206
1329
|
"YmapLodLightType",
|
|
1207
1330
|
"YmapMloInstanceFlags",
|
|
1208
1331
|
"YmapPriorityLevel",
|
|
1332
|
+
"HdTxdAssetBinding",
|
|
1333
|
+
"ImapDependencies",
|
|
1334
|
+
"ImapDependency",
|
|
1335
|
+
"InteriorBoundsFile",
|
|
1336
|
+
"ItypDependencies",
|
|
1337
|
+
"ManifestFlags",
|
|
1338
|
+
"MapDataGroup",
|
|
1339
|
+
"PackFileMetaData",
|
|
1340
|
+
"PackFileMetaDataAssetType",
|
|
1341
|
+
"PackFileMetaDataImapGroupType",
|
|
1209
1342
|
"Ymf",
|
|
1343
|
+
"YmfRelationship",
|
|
1344
|
+
"YmfRelationshipType",
|
|
1210
1345
|
"Ymt",
|
|
1346
|
+
"YmtAabb",
|
|
1347
|
+
"YmtPedInitData",
|
|
1348
|
+
"YmtPedMetadata",
|
|
1349
|
+
"YmtScenarioPointGroup",
|
|
1350
|
+
"YmtScenarioPointManifest",
|
|
1351
|
+
"YmtScenarioPointRegionDef",
|
|
1352
|
+
"YmtStreamingRequestCommonSet",
|
|
1353
|
+
"YmtStreamingRequestFrame",
|
|
1354
|
+
"YmtStreamingRequestRecord",
|
|
1211
1355
|
"ContainerLodDef",
|
|
1212
1356
|
"YddAsset",
|
|
1213
1357
|
"Ytd",
|
|
@@ -1229,6 +1373,9 @@ __all__ = [
|
|
|
1229
1373
|
"build_dlc_extra_title_update_data_xml",
|
|
1230
1374
|
"build_dlc_list_xml",
|
|
1231
1375
|
"build_dlc_setup_xml",
|
|
1376
|
+
"build_ymf",
|
|
1377
|
+
"build_ymf_for_ymaps",
|
|
1378
|
+
"build_ymf_manifest_for_ymaps",
|
|
1232
1379
|
"create_dlc_folder_metadata",
|
|
1233
1380
|
"create_dlc_list_for_packs",
|
|
1234
1381
|
"create_dlc_patch_manifest",
|
|
@@ -1238,6 +1385,7 @@ __all__ = [
|
|
|
1238
1385
|
"clear_hash_resolver",
|
|
1239
1386
|
"clear_game_crypto",
|
|
1240
1387
|
"create_rpf",
|
|
1388
|
+
"create_ymf_for_ymaps",
|
|
1241
1389
|
"create_ydd",
|
|
1242
1390
|
"create_ydr",
|
|
1243
1391
|
"convert_audio_to_awc",
|
|
@@ -1282,7 +1430,9 @@ __all__ = [
|
|
|
1282
1430
|
"read_dlc_list",
|
|
1283
1431
|
"read_dlc_pack",
|
|
1284
1432
|
"read_dlc_setup",
|
|
1433
|
+
"is_gtxd_rbf",
|
|
1285
1434
|
"read_gtxd",
|
|
1435
|
+
"read_gtxd_bytes",
|
|
1286
1436
|
"read_gxt2",
|
|
1287
1437
|
"read_gxt2_text",
|
|
1288
1438
|
"read_ycd",
|
|
@@ -1291,6 +1441,8 @@ __all__ = [
|
|
|
1291
1441
|
"read_yed",
|
|
1292
1442
|
"read_shader_library",
|
|
1293
1443
|
"read_ydr",
|
|
1444
|
+
"read_yft",
|
|
1445
|
+
"save_yft",
|
|
1294
1446
|
"rig_body_folder_jiggle_bones",
|
|
1295
1447
|
"rig_mesh_to_bones_radially",
|
|
1296
1448
|
"rig_ydd_to_bones_radially",
|
|
@@ -1314,11 +1466,15 @@ __all__ = [
|
|
|
1314
1466
|
"read_ynv",
|
|
1315
1467
|
"read_ymap",
|
|
1316
1468
|
"read_ymf",
|
|
1469
|
+
"read_ymf_xml",
|
|
1317
1470
|
"read_ymt",
|
|
1318
1471
|
"read_ytd",
|
|
1319
1472
|
"read_ytyp",
|
|
1473
|
+
"YmtContentType",
|
|
1474
|
+
"YmtFormat",
|
|
1320
1475
|
"infer_dlc_content_from_folder",
|
|
1321
1476
|
"iter_ped_drawables",
|
|
1477
|
+
"iter_ymf_relationships",
|
|
1322
1478
|
"iter_dlc_content_candidates",
|
|
1323
1479
|
"register_name",
|
|
1324
1480
|
"register_names",
|
|
@@ -1381,4 +1537,6 @@ __all__ = [
|
|
|
1381
1537
|
"create_ycd_uv_clip",
|
|
1382
1538
|
"get_ycd_track_format",
|
|
1383
1539
|
"parse_ycd_uv_clip_binding",
|
|
1540
|
+
"assert_valid_yft",
|
|
1541
|
+
"validate_yft",
|
|
1384
1542
|
]
|
|
@@ -29,6 +29,9 @@ class YftAsset(ResourceTextureAsset):
|
|
|
29
29
|
main_drawable_pointer = _u64(self.system_data, 0x30)
|
|
30
30
|
yield from emit("drawable", main_drawable_pointer)
|
|
31
31
|
|
|
32
|
+
damaged_drawable_pointer = _u64(self.system_data, 0x50)
|
|
33
|
+
yield from emit("damaged", damaged_drawable_pointer)
|
|
34
|
+
|
|
32
35
|
drawable_array_pointer = _u64(self.system_data, 0x38)
|
|
33
36
|
drawable_array_count = _u32(self.system_data, 0x48)
|
|
34
37
|
for index, drawable_pointer in enumerate(
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
-
from math import sqrt
|
|
5
|
-
|
|
6
4
|
from .. import _native as _native_backend
|
|
5
|
+
from ..vector import aabb_center, aabb_from_points, vec_cross, vec_length, vec_sub
|
|
7
6
|
from .model import (
|
|
8
7
|
BoundAabb,
|
|
9
8
|
BoundBVH,
|
|
@@ -35,14 +34,7 @@ class BoundTriangleChunk:
|
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def _triangle_area_python(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3) -> float:
|
|
38
|
-
|
|
39
|
-
edge2 = (vertex2[0] - vertex0[0], vertex2[1] - vertex0[1], vertex2[2] - vertex0[2])
|
|
40
|
-
cross = (
|
|
41
|
-
(edge1[1] * edge2[2]) - (edge1[2] * edge2[1]),
|
|
42
|
-
(edge1[2] * edge2[0]) - (edge1[0] * edge2[2]),
|
|
43
|
-
(edge1[0] * edge2[1]) - (edge1[1] * edge2[0]),
|
|
44
|
-
)
|
|
45
|
-
return 0.5 * sqrt((cross[0] * cross[0]) + (cross[1] * cross[1]) + (cross[2] * cross[2]))
|
|
37
|
+
return 0.5 * vec_length(vec_cross(vec_sub(vertex1, vertex0), vec_sub(vertex2, vertex0)))
|
|
46
38
|
|
|
47
39
|
|
|
48
40
|
def triangle_area(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3) -> float:
|
|
@@ -54,10 +46,7 @@ def triangle_area(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3) -> float
|
|
|
54
46
|
def _bounds_from_vertices_python(vertices: list[Vector3]) -> tuple[Vector3, Vector3]:
|
|
55
47
|
if not vertices:
|
|
56
48
|
raise ValueError("At least one vertex is required")
|
|
57
|
-
return (
|
|
58
|
-
(min(vertex[0] for vertex in vertices), min(vertex[1] for vertex in vertices), min(vertex[2] for vertex in vertices)),
|
|
59
|
-
(max(vertex[0] for vertex in vertices), max(vertex[1] for vertex in vertices), max(vertex[2] for vertex in vertices)),
|
|
60
|
-
)
|
|
49
|
+
return aabb_from_points(vertices)
|
|
61
50
|
|
|
62
51
|
|
|
63
52
|
def bounds_from_vertices(vertices: list[Vector3]) -> tuple[Vector3, Vector3]:
|
|
@@ -67,19 +56,12 @@ def bounds_from_vertices(vertices: list[Vector3]) -> tuple[Vector3, Vector3]:
|
|
|
67
56
|
|
|
68
57
|
|
|
69
58
|
def center_from_bounds(minimum: Vector3, maximum: Vector3) -> Vector3:
|
|
70
|
-
return (
|
|
59
|
+
return aabb_center(minimum, maximum)
|
|
71
60
|
|
|
72
61
|
|
|
73
62
|
def _sphere_radius_from_vertices_python(center: Vector3, vertices: list[Vector3]) -> float:
|
|
74
63
|
return max(
|
|
75
|
-
(
|
|
76
|
-
sqrt(
|
|
77
|
-
((vertex[0] - center[0]) ** 2)
|
|
78
|
-
+ ((vertex[1] - center[1]) ** 2)
|
|
79
|
-
+ ((vertex[2] - center[2]) ** 2)
|
|
80
|
-
)
|
|
81
|
-
for vertex in vertices
|
|
82
|
-
),
|
|
64
|
+
(vec_length(vec_sub(vertex, center)) for vertex in vertices),
|
|
83
65
|
default=0.0,
|
|
84
66
|
)
|
|
85
67
|
|
|
@@ -8,6 +8,7 @@ from typing import Iterator
|
|
|
8
8
|
|
|
9
9
|
from .. import _native as _native_backend
|
|
10
10
|
from ..resource import ResourcePagesInfo
|
|
11
|
+
from ..vector import aabb_center, aabb_from_center_size, vec_add, vec_scale, vec_sub
|
|
11
12
|
from .materials import BoundMaterialType, coerce_bound_material_index, get_bound_material_type
|
|
12
13
|
|
|
13
14
|
|
|
@@ -57,9 +58,7 @@ def _merge_bounds(bounds: list[BoundAabb], fallback: BoundAabb) -> BoundAabb:
|
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
def _aabb_from_center_size(center: tuple[float, float, float], size: tuple[float, float, float]) -> BoundAabb:
|
|
60
|
-
|
|
61
|
-
minimum = tuple(float(center[axis]) - half_size[axis] for axis in range(3))
|
|
62
|
-
maximum = tuple(float(center[axis]) + half_size[axis] for axis in range(3))
|
|
61
|
+
minimum, maximum = aabb_from_center_size(center, size)
|
|
63
62
|
return BoundAabb(minimum, maximum)
|
|
64
63
|
|
|
65
64
|
|
|
@@ -159,6 +158,46 @@ def _sphere_radius_from_bounds(bounds: BoundAabb, center: tuple[float, float, fl
|
|
|
159
158
|
)
|
|
160
159
|
|
|
161
160
|
|
|
161
|
+
def _box_volume_distribution(size: tuple[float, float, float]) -> tuple[float, float, float]:
|
|
162
|
+
x, y, z = (abs(float(axis)) for axis in size)
|
|
163
|
+
return (((y * y) + (z * z)) / 12.0, ((x * x) + (z * z)) / 12.0, ((x * x) + (y * y)) / 12.0)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _sphere_volume_distribution(radius: float) -> tuple[float, float, float]:
|
|
167
|
+
value = 0.4 * float(radius) * float(radius)
|
|
168
|
+
return (value, value, value)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _cylinder_volume_distribution(radius: float, length: float) -> tuple[float, float, float]:
|
|
172
|
+
radius2 = float(radius) * float(radius)
|
|
173
|
+
central = (radius2 * 0.25) + ((float(length) * float(length)) / 12.0)
|
|
174
|
+
radial = radius2 * 0.5
|
|
175
|
+
return (central, radial, central)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _capsule_volume_distribution(radius: float, length: float) -> tuple[float, float, float]:
|
|
179
|
+
radius = float(radius)
|
|
180
|
+
length = float(length)
|
|
181
|
+
denominator = length + (4.0 / 3.0) * radius
|
|
182
|
+
if denominator <= 0.0:
|
|
183
|
+
return (0.0, 0.0, 0.0)
|
|
184
|
+
inverse = 1.0 / denominator
|
|
185
|
+
radius2 = radius * radius
|
|
186
|
+
radial = 0.5 * radius2 * (length + 1.0666666666667 * radius) * inverse
|
|
187
|
+
length2 = length * length
|
|
188
|
+
central = (
|
|
189
|
+
(1.0 / 3.0)
|
|
190
|
+
* (
|
|
191
|
+
0.25 * length * length2
|
|
192
|
+
+ radius * length2
|
|
193
|
+
+ 2.25 * length * radius2
|
|
194
|
+
+ 1.6 * radius * radius2
|
|
195
|
+
)
|
|
196
|
+
* inverse
|
|
197
|
+
)
|
|
198
|
+
return (central, radial, central)
|
|
199
|
+
|
|
200
|
+
|
|
162
201
|
@dataclasses.dataclass(slots=True)
|
|
163
202
|
class BoundCompositeFlags:
|
|
164
203
|
flags1: BoundCompositeFlag = BoundCompositeFlag.NONE
|
|
@@ -629,19 +668,37 @@ class Bound:
|
|
|
629
668
|
def geometry_count(self) -> int:
|
|
630
669
|
return len(self.geometries)
|
|
631
670
|
|
|
632
|
-
@property
|
|
671
|
+
@property
|
|
633
672
|
def leaf_bounds(self) -> list[Bound]:
|
|
634
673
|
return [bound for bound in self.walk() if not isinstance(bound, BoundComposite)]
|
|
635
674
|
|
|
675
|
+
def compute_volume(self) -> float:
|
|
676
|
+
if self.volume > 0.0 and math.isfinite(self.volume):
|
|
677
|
+
return float(self.volume)
|
|
678
|
+
return abs(self.width * self.depth * self.height)
|
|
679
|
+
|
|
680
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
681
|
+
if any(abs(value) > 0.0 for value in self.angular_inertia):
|
|
682
|
+
return tuple(float(value) for value in self.angular_inertia)
|
|
683
|
+
return _box_volume_distribution(self.dimensions)
|
|
684
|
+
|
|
685
|
+
def compute_angular_inertia(self, mass: float) -> tuple[float, float, float]:
|
|
686
|
+
distribution = self.compute_volume_distribution()
|
|
687
|
+
return tuple(float(value) * float(mass) for value in distribution)
|
|
688
|
+
|
|
636
689
|
def build(self) -> "Bound":
|
|
637
690
|
normalized = _normalize_aabb(self.bounds)
|
|
638
691
|
self.box_min = normalized.minimum
|
|
639
692
|
self.box_max = normalized.maximum
|
|
640
693
|
self.box_center = tuple((normalized.minimum[axis] + normalized.maximum[axis]) * 0.5 for axis in range(3))
|
|
694
|
+
if self.sphere_center == (0.0, 0.0, 0.0) and self.box_center != (0.0, 0.0, 0.0):
|
|
695
|
+
self.sphere_center = self.box_center
|
|
641
696
|
self.flags = BoundFlag(int(self.flags))
|
|
642
697
|
self.part_index = int(self.part_index) & 0xFFFF
|
|
643
698
|
self.material_index = coerce_bound_material_index(self.material_index)
|
|
644
699
|
self.ref_count = int(self.ref_count)
|
|
700
|
+
self.volume = self.compute_volume()
|
|
701
|
+
self.angular_inertia = self.compute_volume_distribution()
|
|
645
702
|
return self
|
|
646
703
|
|
|
647
704
|
def validate(self) -> list[str]:
|
|
@@ -699,9 +756,18 @@ class BoundSphere(Bound):
|
|
|
699
756
|
def diameter(self) -> float:
|
|
700
757
|
return self.radius * 2.0
|
|
701
758
|
|
|
759
|
+
def compute_volume(self) -> float:
|
|
760
|
+
return (4.0 / 3.0) * math.pi * (self.radius ** 3)
|
|
761
|
+
|
|
762
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
763
|
+
return _sphere_volume_distribution(self.radius)
|
|
764
|
+
|
|
702
765
|
|
|
703
766
|
@dataclasses.dataclass(slots=True)
|
|
704
767
|
class BoundBox(Bound):
|
|
768
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
769
|
+
return _box_volume_distribution(self.dimensions)
|
|
770
|
+
|
|
705
771
|
@classmethod
|
|
706
772
|
def from_bounds(
|
|
707
773
|
cls,
|
|
@@ -777,6 +843,13 @@ class BoundCapsule(Bound):
|
|
|
777
843
|
def total_height(self) -> float:
|
|
778
844
|
return self.shaft_length + (self.radius * 2.0)
|
|
779
845
|
|
|
846
|
+
def compute_volume(self) -> float:
|
|
847
|
+
radius = self.radius
|
|
848
|
+
return math.pi * radius * radius * (self.shaft_length + (4.0 / 3.0) * radius)
|
|
849
|
+
|
|
850
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
851
|
+
return _capsule_volume_distribution(self.radius, self.shaft_length)
|
|
852
|
+
|
|
780
853
|
|
|
781
854
|
@dataclasses.dataclass(slots=True)
|
|
782
855
|
class BoundDisc(Bound):
|
|
@@ -846,6 +919,12 @@ class BoundDisc(Bound):
|
|
|
846
919
|
def thickness(self) -> float:
|
|
847
920
|
return self.half_thickness * 2.0
|
|
848
921
|
|
|
922
|
+
def compute_volume(self) -> float:
|
|
923
|
+
return math.pi * self.radius * self.radius * self.thickness
|
|
924
|
+
|
|
925
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
926
|
+
return _cylinder_volume_distribution(self.radius, self.thickness)
|
|
927
|
+
|
|
849
928
|
|
|
850
929
|
@dataclasses.dataclass(slots=True)
|
|
851
930
|
class BoundCylinder(Bound):
|
|
@@ -910,6 +989,12 @@ class BoundCylinder(Bound):
|
|
|
910
989
|
def height(self) -> float:
|
|
911
990
|
return self.half_height * 2.0
|
|
912
991
|
|
|
992
|
+
def compute_volume(self) -> float:
|
|
993
|
+
return math.pi * self.radius * self.radius * self.height
|
|
994
|
+
|
|
995
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
996
|
+
return _cylinder_volume_distribution(self.radius, self.height)
|
|
997
|
+
|
|
913
998
|
|
|
914
999
|
@dataclasses.dataclass(slots=True)
|
|
915
1000
|
class BoundCloth(Bound):
|
|
@@ -1121,6 +1206,70 @@ class BoundComposite(Bound):
|
|
|
1121
1206
|
self.children.append(child)
|
|
1122
1207
|
return child
|
|
1123
1208
|
|
|
1209
|
+
def compute_volume(self) -> float:
|
|
1210
|
+
if self.children:
|
|
1211
|
+
return sum(child.bound.compute_volume() for child in self.children)
|
|
1212
|
+
return super().compute_volume()
|
|
1213
|
+
|
|
1214
|
+
def compute_center_of_gravity(
|
|
1215
|
+
self,
|
|
1216
|
+
masses: list[float] | tuple[float, ...] | None = None,
|
|
1217
|
+
) -> tuple[float, float, float]:
|
|
1218
|
+
weighted = (0.0, 0.0, 0.0)
|
|
1219
|
+
total_weight = 0.0
|
|
1220
|
+
for index, child in enumerate(self.children):
|
|
1221
|
+
weight = (
|
|
1222
|
+
float(masses[index])
|
|
1223
|
+
if masses is not None and index < len(masses)
|
|
1224
|
+
else child.bound.compute_volume()
|
|
1225
|
+
)
|
|
1226
|
+
if weight <= 0.0:
|
|
1227
|
+
continue
|
|
1228
|
+
child_center = _transform_point(child.bound.sphere_center, child.transform)
|
|
1229
|
+
weighted = vec_add(weighted, vec_scale(child_center, weight))
|
|
1230
|
+
total_weight += weight
|
|
1231
|
+
return vec_scale(weighted, 1.0 / total_weight) if total_weight > 0.0 else (0.0, 0.0, 0.0)
|
|
1232
|
+
|
|
1233
|
+
def compute_composite_angular_inertia(
|
|
1234
|
+
self,
|
|
1235
|
+
mass: float,
|
|
1236
|
+
*,
|
|
1237
|
+
masses: list[float] | tuple[float, ...] | None = None,
|
|
1238
|
+
inertias: list[tuple[float, float, float]] | tuple[tuple[float, float, float], ...] | None = None,
|
|
1239
|
+
) -> tuple[float, float, float]:
|
|
1240
|
+
total_mass = float(mass)
|
|
1241
|
+
total_volume = self.compute_volume()
|
|
1242
|
+
density = total_mass / total_volume if total_volume > 0.0 else 0.0
|
|
1243
|
+
center_of_gravity = self.compute_center_of_gravity(masses)
|
|
1244
|
+
total = (0.0, 0.0, 0.0)
|
|
1245
|
+
for index, child in enumerate(self.children):
|
|
1246
|
+
part_mass = (
|
|
1247
|
+
float(masses[index])
|
|
1248
|
+
if masses is not None and index < len(masses)
|
|
1249
|
+
else density * child.bound.compute_volume()
|
|
1250
|
+
)
|
|
1251
|
+
if inertias is not None and index < len(inertias):
|
|
1252
|
+
part_inertia = inertias[index]
|
|
1253
|
+
else:
|
|
1254
|
+
part_inertia = child.bound.compute_angular_inertia(part_mass)
|
|
1255
|
+
offset = vec_sub(_transform_point(child.bound.sphere_center, child.transform), center_of_gravity)
|
|
1256
|
+
parallel_axis = (
|
|
1257
|
+
part_mass * ((offset[1] * offset[1]) + (offset[2] * offset[2])),
|
|
1258
|
+
part_mass * ((offset[0] * offset[0]) + (offset[2] * offset[2])),
|
|
1259
|
+
part_mass * ((offset[0] * offset[0]) + (offset[1] * offset[1])),
|
|
1260
|
+
)
|
|
1261
|
+
total = vec_add(total, vec_add(part_inertia, parallel_axis))
|
|
1262
|
+
return total
|
|
1263
|
+
|
|
1264
|
+
def compute_volume_distribution(self) -> tuple[float, float, float]:
|
|
1265
|
+
volume = self.compute_volume()
|
|
1266
|
+
if volume <= 0.0:
|
|
1267
|
+
return (0.0, 0.0, 0.0)
|
|
1268
|
+
return vec_scale(self.compute_composite_angular_inertia(volume), 1.0 / volume)
|
|
1269
|
+
|
|
1270
|
+
def compute_angular_inertia(self, mass: float) -> tuple[float, float, float]:
|
|
1271
|
+
return self.compute_composite_angular_inertia(mass)
|
|
1272
|
+
|
|
1124
1273
|
def build(self) -> "BoundComposite":
|
|
1125
1274
|
super().build()
|
|
1126
1275
|
for child in self.children:
|
|
@@ -1133,12 +1282,14 @@ class BoundComposite(Bound):
|
|
|
1133
1282
|
for child in self.children
|
|
1134
1283
|
]
|
|
1135
1284
|
overall = _merge_bounds(transformed_bounds, self.bounds)
|
|
1136
|
-
center =
|
|
1285
|
+
center = aabb_center(overall.minimum, overall.maximum)
|
|
1137
1286
|
self.box_min = overall.minimum
|
|
1138
1287
|
self.box_max = overall.maximum
|
|
1139
1288
|
self.box_center = center
|
|
1140
|
-
self.sphere_center =
|
|
1289
|
+
self.sphere_center = self.compute_center_of_gravity()
|
|
1141
1290
|
self.sphere_radius = _sphere_radius_from_bounds(overall, center)
|
|
1291
|
+
self.volume = self.compute_volume()
|
|
1292
|
+
self.angular_inertia = self.compute_volume_distribution()
|
|
1142
1293
|
if len(self.children) <= 5:
|
|
1143
1294
|
self.bvh = None
|
|
1144
1295
|
else:
|
|
@@ -154,11 +154,11 @@ class GameFileCacheAssetMixin:
|
|
|
154
154
|
def list_ymap_entity_assets(self, query: Any, *, include_supporting: bool = True) -> list["AssetRecord"]:
|
|
155
155
|
return list(self.iter_ymap_entity_assets(query, include_supporting=include_supporting))
|
|
156
156
|
|
|
157
|
-
def extract_ymap_assets(
|
|
158
|
-
self,
|
|
159
|
-
query: Any,
|
|
160
|
-
destination: str | Path,
|
|
161
|
-
*,
|
|
157
|
+
def extract_ymap_assets(
|
|
158
|
+
self,
|
|
159
|
+
query: Any,
|
|
160
|
+
destination: str | Path,
|
|
161
|
+
*,
|
|
162
162
|
include_supporting: bool = True,
|
|
163
163
|
logical: bool = False,
|
|
164
164
|
) -> list[Path]:
|
|
@@ -168,10 +168,19 @@ class GameFileCacheAssetMixin:
|
|
|
168
168
|
for asset in self.iter_ymap_entity_assets(query, include_supporting=include_supporting):
|
|
169
169
|
result = self.extract_asset(asset, output_dir / asset.name, logical=logical)
|
|
170
170
|
if result is not None:
|
|
171
|
-
extracted.append(result)
|
|
172
|
-
return extracted
|
|
173
|
-
|
|
174
|
-
def
|
|
171
|
+
extracted.append(result)
|
|
172
|
+
return extracted
|
|
173
|
+
|
|
174
|
+
def create_ymf_for_ymaps(self, ymaps: Any | None = None, **kwargs: Any) -> Any:
|
|
175
|
+
from ..ymf import create_ymf_for_ymaps
|
|
176
|
+
|
|
177
|
+
sources = None if ymaps is None else (ymaps if isinstance(ymaps, (list, tuple, set)) else [ymaps])
|
|
178
|
+
return create_ymf_for_ymaps(sources, cache=self, **kwargs)
|
|
179
|
+
|
|
180
|
+
def build_ymf_for_ymaps(self, ymaps: Any | None = None, **kwargs: Any) -> Any:
|
|
181
|
+
return self.create_ymf_for_ymaps(ymaps, **kwargs)
|
|
182
|
+
|
|
183
|
+
def _coerce_ytd(self, value: Any) -> Ytd | None:
|
|
175
184
|
if isinstance(value, Ytd):
|
|
176
185
|
return value
|
|
177
186
|
if hasattr(value, "textures") and hasattr(value, "to_bytes"):
|
|
@@ -21,6 +21,7 @@ from ..ybn import read_ybn
|
|
|
21
21
|
from ..ydd import read_ydd
|
|
22
22
|
from ..yed import read_yed
|
|
23
23
|
from ..ydr import read_ydr
|
|
24
|
+
from ..yft import read_yft
|
|
24
25
|
from ..ynd import read_ynd
|
|
25
26
|
from ..ynv import read_ynv
|
|
26
27
|
from ..ytd import read_ytd
|
|
@@ -70,6 +71,7 @@ def _decode_payload(path: str, data: bytes, *, raw: bytes | None = None) -> tupl
|
|
|
70
71
|
resource_decoders = {
|
|
71
72
|
".ydr": (GameFileType.YDR, lambda payload: read_ydr(payload, path=path)),
|
|
72
73
|
".ydd": (GameFileType.YDD, lambda payload: read_ydd(payload, path=path)),
|
|
74
|
+
".yft": (GameFileType.YFT, lambda payload: read_yft(payload, path=path)),
|
|
73
75
|
".ytd": (GameFileType.YTD, read_ytd),
|
|
74
76
|
".ycd": (GameFileType.YCD, lambda payload: read_ycd(payload, path=path)),
|
|
75
77
|
".yed": (GameFileType.YED, lambda payload: read_yed(payload, path=path)),
|
|
@@ -225,7 +227,7 @@ class GameFileCacheIOMixin:
|
|
|
225
227
|
self._log(f"read file {asset.path}")
|
|
226
228
|
logical_native = self._logical_archive_bytes_from_standalone(asset, standalone_native)
|
|
227
229
|
ext = Path(asset.path).suffix.lower()
|
|
228
|
-
raw_source = standalone_native if ext in {".ytd", ".ydr", ".ydd", ".ycd", ".yed", ".ybn", ".ynd", ".ynv"} else stored_native
|
|
230
|
+
raw_source = standalone_native if ext in {".ytd", ".ydr", ".ydd", ".yft", ".ycd", ".yed", ".ybn", ".ynd", ".ynv"} else stored_native
|
|
229
231
|
parsed, kind = _decode_payload(asset.path, logical_native, raw=raw_source)
|
|
230
232
|
entry = asset.entry if isinstance(asset.entry, RpfFileEntry) else None
|
|
231
233
|
archive = asset.archive if isinstance(asset.archive, RpfArchive) else None
|
|
@@ -249,7 +251,7 @@ class GameFileCacheIOMixin:
|
|
|
249
251
|
stored = entry.read(logical=False)
|
|
250
252
|
logical = entry.read(logical=True)
|
|
251
253
|
raw_source = None
|
|
252
|
-
if asset.path.lower().endswith((".ytd", ".ydr", ".ydd", ".ycd", ".yed", ".ybn", ".ynd", ".ynv")):
|
|
254
|
+
if asset.path.lower().endswith((".ytd", ".ydr", ".ydd", ".yft", ".ycd", ".yed", ".ybn", ".ynd", ".ynv")):
|
|
253
255
|
raw_source = entry._archive.read_entry_standalone(entry)
|
|
254
256
|
parsed, kind = _decode_payload(asset.path, logical, raw=raw_source)
|
|
255
257
|
game_file = GameFile(
|