|
| 1 | +# Image (Down)loading |
| 2 | + |
| 3 | +If your have to display **images** in your mod that are **not included** in the mod file (for example for reducing the **size** of the mod or for showing **user-generated content**), you can use geode's `LazySprite` class. It can **also** be used for ordinary image initialization, either from a path or from raw data, which would have slight performance improvements over `CCSprite::create`, as the image is lazily read and decoded **in the background**, without freezing the game. |
| 4 | + |
| 5 | +It is **recommended** to use this API instead of implementing custom solutions that mess with `CCTextureCache`. It is not straightforward to do this correctly, and multiple mods (and Geode itself) have in the past failed to do this without memory leaks and other bugs. |
| 6 | + |
| 7 | +By default, the sprite will have a **loading circle** inside it when it's loading, which is removed once loading is finished. This can be disabled, making the sprite blank until it's loaded. |
| 8 | + |
| 9 | +## Usage |
| 10 | + |
| 11 | +Basic examples of downloading an image from a URL, loading from a file, and initializing from data, and a showcase of various options. |
| 12 | + |
| 13 | +```cpp |
| 14 | +#include <Geode/ui/LazySprite.hpp> |
| 15 | +using namespace geode::prelude; |
| 16 | + |
| 17 | +// this will be the initial size of the node (and the loading circle) |
| 18 | +CCSize nodeSize{64.f, 64.f}; |
| 19 | + |
| 20 | +auto spr1 = LazySprite::create(nodeSize); |
| 21 | +// or, if you want to disable the loading circle |
| 22 | +auto spr1 = LazySprite::create(nodeSize, false); |
| 23 | + |
| 24 | +// if you want to know when the image finished loading, you can assign a callback |
| 25 | +// do this **before** calling one of the next functions, because if the image is cached, |
| 26 | +// the callback will be called instantly, potentially before you assign it. |
| 27 | +spr1->setLoadCallback([spr1](Result<> res) { |
| 28 | + if (res) { |
| 29 | + log::info("Sprite loaded successfully!"); |
| 30 | + } else { |
| 31 | + log::error("Sprite failed to load, setting fallback: {}", res.unwrapErr()); |
| 32 | + spr1->initWithSpriteFrameName("globed-logo.png"_spr); |
| 33 | + } |
| 34 | +}); |
| 35 | + |
| 36 | +// load the image from a URL |
| 37 | +spr1->loadFromUrl("https://globed.dev/logo.png"); |
| 38 | +// or, load from a file |
| 39 | +spr1->loadFromFile(Mod::get()->getSaveDir() / "file.png"); |
| 40 | +// or, load from binary data |
| 41 | +std::vector<uint8_t> pngBytes = {0x1, 0x2, 0x3}; |
| 42 | +spr1->loadFromData(std::move(pngBytes)); |
| 43 | + |
| 44 | +// using cocos methods also works, but does not have any performance benefits: |
| 45 | +spr1->initWithFile("my-file.png"); |
| 46 | +spr1->initWithSpriteFrameName("my-texture.png"); |
| 47 | + |
| 48 | +// note: you MUST either add the sprite as a child or store it in a Ref<>, |
| 49 | +// if the sprite node gets deleted then it will stop loading and will never call your callback |
| 50 | +someMenu->addChild(spr1); |
| 51 | +``` |
| 52 | +
|
| 53 | +## Automatic resize |
| 54 | +
|
| 55 | +Once the sprite has finished loading, the content size of the `LazySprite` will be set to match the loaded image (in the same manner a `CCSprite::initWithTexture` would). If you want the sprite to be automatically scaled to the size you passed in `LazySprite::create`, you can enable autoresize: |
| 56 | +
|
| 57 | +```cpp |
| 58 | +
|
| 59 | +auto spr1 = LazySprite::create({64.f, 64.f}); |
| 60 | +spr1->setAutoResize(true); |
| 61 | +spr1->loadFromFile(Mod::get()->getSaveDir() / "file.png"); |
| 62 | +
|
| 63 | +// now, once the sprite finished loading, it should be resized to 64x64 (in cocos units) |
| 64 | +``` |
| 65 | + |
| 66 | +## Caching |
| 67 | + |
| 68 | +By default, if using `loadFromFile` or `loadFromUrl`, this class will cache the textures in `CCTextureCache` (`loadFromData` is not supported due to it being hard to pick a uniquely identifying cache key). |
| 69 | + |
| 70 | +If this is not wanted, the load functions have an extra bool argument for ignoring the cache: |
| 71 | + |
| 72 | +```cpp |
| 73 | +spr1->loadFromUrl("url", true); |
| 74 | +``` |
0 commit comments