GDevelop
GDevelop copied to clipboard
Update resources used by pixi on scene editor force update
Fix #3388. #3549
@Bouh I had not seen you tagged me in the issue. I used your PR #1724 to fix this bug. @4ian I added a forced update of Pixi resources when the editor is force updated, that's to say each time the user comes back to the tab I think.
It feels ok regarding the performance: Using the Isometric starter that can feel a bit loaded, the change of tabs takes 40ms without this pixi reload, and 51ms with. Maybe I could work a bit more so that this Pixi forced update only takes place on project change.
There's also the issue of the resource not updating if we modify the file outside of GDevelop, but I'm not sure it should be part of this PR.
It feels ok regarding the performance: Using the Isometric starter that can feel a bit loaded, the change of tabs takes 40ms without this pixi reload, and 51ms with. Maybe I could work a bit more so that this Pixi forced update only takes place on project change.
The only time I have experienced this problem is when switching between projects. I don't think it is possible for two scenes to run into this problem (two different images with the same name) as they already share the same folder so duplicate names are not possible (I think).
Yep I think this would make sense to achieve this kind of "forced reloading" (or somehow "just" clear the Pixi cache) only when switching project. When switching tab, I'm a bit concerned this could put too much pressure especially for large games with a lot of objects (and global objects) 🤔
I had not noticed this TODO:
https://github.com/4ian/GDevelop/blob/master/newIDE/app/src/MainFrame/index.js#L595
I had trouble finding how to clear PIXI's cache, and all the things I tested didn't work.
PIXI.Texture.removeFromCache('NewObject-1.png');
if (
PIXI.Loader.shared.resources['NewObject-1.png'] &&
PIXI.Loader.shared.resources['NewObject-1.png'].texture &&
PIXI.Loader.shared.resources['NewObject-1.png'].texture.baseTexture
) {
PIXI.Loader.shared.resources[
'NewObject-1.png'
].texture.baseTexture.destroy(true);
PIXI.Texture.removeTextureFromCache(
PIXI.Loader.shared.resources['NewObject-1.png'].texture
);
PIXI.Loader.shared.resources['NewObject-1.png'].texture.destroy(true);
}
for (const textureUrl in PIXI.utils.BaseTextureCache) {
delete PIXI.utils.BaseTextureCache[textureUrl];
}
for (const textureUrl in PIXI.utils.TextureCache) {
delete PIXI.utils.TextureCache[textureUrl];
}
PIXI.Loader.shared.reset();
delete PIXI.Loader.shared.resources['NewObject-1.png'];
I'm a bit stuck.
Our ResourcesLoader should be cleared, Pixi too. Maybe WebGL has its own cache but it seemed to me that it corresponds to the pixi BaseTexture.
I'm also a bit unsure what the problem is. I wonder if the problem is the cache at the browser level and so PIXI is indeed reloading any resource but keeping the same files cached in memory? Might be worth testing with the cache disabled on the debugger.
When you switch projects, you can see a request for the object to the path:
.../My%20project15/NewObject-1.png?cache=1642780961091&gdUsage=img
I don't know what the cache value is used for, but it differs from the first load of the file with the same name
I also tried using electron.session.clearCache and electron.session.clearStorageData (see https://www.electronjs.org/docs/v14-x-y/api/session) but the bug is still here.
Let's try to understand the problem in the reverse order: why is your PR here working? What it is doing that we're not doing at the project opening?
If there are concerns on performance impacts on having this reload every time a tab is refreshed. What about the following two scenarios:
- On project load
- On resources tab load
As well as a button on the top bar that is literally just a "refresh all resources button" to let the user decide to do it themselves. Or if not a separate button. Maybe a menu option when clicking on the debugger/but icon?
Ideally we would have this situation:
- whenever you load a new project, we ensure resources are reloaded to avoid any mismatch.
- whenever you change a file, GDevelop automagically notice it and reload the associated resource(s).
We want to do 1., but we can't find the technical solution. Alexandre tried to do "reload on tab change", which works, but is a bit "overkill" in terms of performance. We try to get it done only when loading a project - no reason it can't be done.
For 2, it's a bit separate because it involves monitoring the file system. So indeed as a workaround, we could for now have a button (somewhere in the app) "Reload all resources (images, etc...) from disk". Not super pretty but should do the trick.
But even to do this, we need to understand why we can't properly force Pixi and the editor to reload a file rather than keeping the file with the same name they discovered in the previous project.
For 2, it's a bit separate because it involves monitoring the file system. So indeed as a workaround, we could for now have a button (somewhere in the app) "Reload all resources (images, etc...) from disk". Not super pretty but should do the trick.
I had been using chokidar and a watcher on the resource files, then updating the changed resource, it seemed like a good approach.