Appearance
Assets
Assets are requested by path and usable right away. Barton loads them in the background and fills them in when they're ready.
Loading
Assets come from an Assets& parameter, available in render and in handlers:
cpp
View render(Assets& assets) const {
const auto sunset = assets.load<Pixmap>("assets/sunset.png");
return Image { sunset, width = 240_px, height = 160_px };
}Loading never blocks the window. A handle comes back right away while the file is read on a worker thread. Assets are cached by path, so loading on every render is cheap and returns the same handle each time.
Embedded assets
For files embedded in the app's binary, Pixmap and Font load straight from bytes. Pass the bytes after the path, and the path becomes the asset's name and cache key:
cpp
std::span<const std::uint8_t> logo = embedded_logo();
const auto handle = assets.load<Pixmap>(
"logo.png",
std::vector<std::uint8_t> { logo.begin(), logo.end() }
);Barton loads its own built-in fonts this way.
Pending assets
Until an asset is ready, anything using it draws nothing and measures as zero size. An Image without a fixed size takes up no space at first. When the load finishes, Barton re-renders, and layout picks up the real size.
Giving the view a fixed width and height keeps the layout from shifting when the image arrives.
Status
Every asset is either still loading, ready, or failed. Its status is a std::variant, so Match can render something different for each:
cpp
View render(Assets& assets) const {
const auto avatar = assets.load<Pixmap>("avatars/ada.png");
return Match(assets.status(avatar),
[](Loading) {
return Text { "Loading…", color = Color::GRAY };
},
[&](const Pixmap&) {
return Image { avatar, width = 48_px, height = 48_px };
},
[](const Error& error) {
return Text { error.message(), color = Color::RED };
});
}Only the matching lambda runs. When the status changes, Barton renders again and Match picks the new branch.
Custom assets
Any type with a static read function can be loaded:
cpp
struct Level {
std::vector<Tile> tiles;
static Result<Level, Error> read(const std::string& path);
};
const auto level = assets.load<Level>("levels/forest.json");Reading happens on a worker thread, and any extra arguments to load are passed through.