Skip to content

Commit b3da6aa

Browse files
committed
add image downloading page
1 parent 3f372f8 commit b3da6aa

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

tutorials/image-loading.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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

Comments
 (0)