Setup.py build not importing data files correctly

I followed this beginner tutorial to make a game, and after finishing it I’ve ended up with a lot of data files in subfolders.

After a bit of fiddling, and following setuptools documentation, I ended up with this file structure:

Screenshot 2022-12-05 at 5.17.14 pm

(In case it’s not clear, the Python files and the Assets folder are in Source)

In my game scripts, I get each resource with a path name that starts with “Assets”, like this:

loader.loadTexture("Assets/UI/UIButton.png")

This works fine when running python Source/Game.py. But after I build the game with bdist_apps, the data files are placed under Source/Assets, so the game can’t find those files anymore and will crash if I try to load them.

Here’s my setup.py file (I’m not using the TOML file right now):

from setuptools import setup, find_packages

setup(
    name="Panda-chan and the Endless Horde",
    include_package_data=True,
    options={
        "build_apps": {
            "include_patterns": [
                "**/*.png",
                "**/*.ogg",
                "**/*.txt",
                "**/*.egg",
                "Fonts/*"
            ],
            "gui_apps": {
                "Panda-chan and the Endless Horde": "Source/Game.py"
            },
            "plugins": [
                "pandagl",
                "p3openal_audio"
            ],
            "platforms": [
                "manylinux2010_x86_64",
                "macosx_10_9_x86_64",
                "win_amd64"
            ],
            "log_filename": "$HOME/PandaChanAndHorde/output.log",
            "log_append": False
        }
    }
)

And my MANIFEST.in file:

include Source/Assets/Fonts/*
include Source/Assets/Models/*
include Source/Assets/Music/*
include Source/Assets/Sounds/*
include Source/Assets/UI/*

What kind of file structure and build configuration do I need to get consistent file paths?

build_apps doesn’t use your MANIFEST.in file, so I suggest you remove it. It just uses include_patterns.

Perhaps @Thaumaturge can comment on how the game from the tutorial is intended to be built? It would be possible to use a model-path setting in a .prc file to indicate where the assets should be loaded relative to. Perhaps it was intended that your setup.py goes inside the Source directory?

In short, the tutorial is set up with the assumption that the relative paths between assets and executable is the same as the relative paths between assets and source code. Thus it doesn’t include any sort of handling for this sort of rearrangement of directory-structure.

(Largely because I’ll confess that I don’t know how handle such a rearrangement myself.)

Offhand, and admittedly without testing it, I would imagine that the addition of “Source/Assets” to the model-path should do the trick, indeed.

I think just Source needs to be added to the model-path to make this work, since the path loaded is “Assets/…”

2 Likes

Ah, right, I missed that change–you are likely right indeed. (The tutorial as written doesn’t have an “Assets” folder, and thus doesn’t reference it; I was looking at the tutorial’s code for my post above, not the code in the first post.)

What is a “model-path” and how do I change it?

In short, it’s a location (or set of locations) at which Panda should search for model-files. It’s generally set in a “prc” configuration-file, I believe.

(It may also work with a call to “loadPrcFileData” placed before your Panda-related importations.)

See this manual page for a bit more, and this “how-to” document (linked from the aforementioned manual page) for a lot more! And you should also be able to check the “prc” config-file that should have come with your installation of Panda (“Config.prc”, in the “etc” sub-folder) for an example of how the model-path is set.

1 Like

After a bit more fiddling, I got it working. Here’s my newest folder structure:

.
├── Source
│   ├── Fonts
│   ├── Models
│   ├── Music
│   ├── Sounds
│   ├── UI
│   ├── Game.py
│   ├── GameObject.py
├── requirements.txt
└── setup.py

I also added this to the top of Game.py (which is the entry point):

from panda3d.core import loadPrcFileData
loadPrcFileData("", "model-path ./Source/")

I probably could have used ./Source/Assets/ with my old folder structure.

My setup.py file also has these patterns under build_apps (crucially, egg.pz files are now included, all the PandaChan models that I downloaded were egg.pz):

"include_patterns": [
    "**/*.png",
    "**/*.ogg",
    "**/*.txt",
    "**/*.egg",
    "**/*.egg.pz",
    "**/*.ttf"
],
1 Like

One suggestion: use $MAIN_DIR/Source instead of ./Source, so that it will continue to work even if you invoke the main executable from a different working directory.

2 Likes