Skip to content

fix: Texture2D without image data and streamed Texture2DArray - #391

Open
nichinichisou0609 wants to merge 2 commits into
K0lb3:masterfrom
nichinichisou0609:fix/texture-without-data
Open

nichinichisou0609 wants to merge 2 commits into
K0lb3:masterfrom
nichinichisou0609:fix/texture-without-data

Conversation

@nichinichisou0609

Copy link
Copy Markdown
Contributor

Two fixes for reading texture data; one commit each, and each commit adds a regression test that fails on its parent and passes with the fix.

  • Textures without size or stream data. A dynamic font keeps its glyph texture in a Texture2D named "Font Texture" with a width and height of 0 and no image data. Like every texture that is not streamed, it serializes m_StreamData with an empty path, offset 0 and size 0. Texture2D.get_image_data looked up a resource whenever m_StreamData was set, so reading .image of such a texture passed an empty name to get_resource_data, which opened the environment directory as a file and failed with PermissionError on Windows and IsADirectoryError on Linux. A texture with a size and no image data took the same path. get_image_from_texture2d now returns an empty image for a texture without width or height, as parse_image_data already does, without fetching any data, and get_image_data reads a resource only when m_StreamData.path names one and raises ValueError("No image data found") otherwise.
  • Streamed Texture2DArray. Texture2DArray.images read m_StreamData only when image_data was None. A streamed array serializes image_data as an empty byte string, so every streamed array failed with Texture2D has no image data. Texture2DArray now has get_image_data() with the same rules as Texture2D.get_image_data(), and images decodes the layers with the platform of the object reader instead of platform 0, as Texture2D does.

tests/test_texture.py (new) builds the objects in memory: a 0x0 texture and a 2x2 texture without data, both without loading any dependency, and a two-layer RGBA32 array stored inline, stored in a .resS registered with Environment.register_cab, and without data. The inline array passes before the change as well and is there as a baseline.

Validation on Windows x86_64, CPython 3.11.13, pytest 9.1.1, Pillow 12.3.0. The compiled path uses the UnityPyBoost extension of the 1.25.4 wheel; UnityPyBoost/ has no changes between 1.25.4 and 417d595. A "Font Texture" from a player build made with Unity 6000.3 raised PermissionError before the change and returns a 0x0 image after it.

Check Result
New tests against unmodified 417d595 4 failed, 1 passed (the inline array baseline)
Each commit's tests against its parent commit fail before, pass after, with and without the extension
Complete suite, with / without the extension 53 passed / 53 passed
ruff check and ruff format --check Passed
python -m pytest -q tests/test_texture.py
python -m pytest -q tests

A dynamic font keeps its glyph texture in a Texture2D named
"Font Texture" with a width and height of 0 and no image data. Like
every texture that is not streamed, it serializes m_StreamData with an
empty path, offset 0 and size 0. Texture2D.get_image_data looked up a
resource whenever m_StreamData was set, so reading the image of such a
texture passed an empty name to get_resource_data, which opened the
environment directory as a file and failed with PermissionError on
Windows and IsADirectoryError on Linux. A texture with a size and no
image data took the same path.

get_image_from_texture2d now returns an empty image for a texture
without width or height, as parse_image_data does, without fetching
any data. get_image_data reads a resource only when m_StreamData names
one, and raises "No image data found" otherwise.

tests/test_texture.py builds both textures in memory and checks that no
dependency is loaded.
Texture2DArray.images only read m_StreamData when image_data was None.
A streamed array serializes image_data as an empty byte string, so the
resource file was never read and every streamed array failed with
"Texture2D has no image data".

Texture2DArray now has get_image_data(), with the same rules as
Texture2D.get_image_data(): the inline data when there is any, else the
resource named by m_StreamData, else a ValueError. images uses it and
decodes the layers with the platform of the object reader instead of
platform 0, as Texture2D does.

tests/test_texture.py decodes a two-layer RGBA32 array stored inline and
the same array stored in a registered .resS resource.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant