GDevelop icon indicating copy to clipboard operation
GDevelop copied to clipboard

Update resources used by pixi on scene editor force update

Open AlexandreSi opened this issue 3 years ago • 10 comments

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.

AlexandreSi avatar Jan 20 '22 16:01 AlexandreSi

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).

tristanbob avatar Jan 20 '22 21:01 tristanbob

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) 🤔

4ian avatar Jan 20 '22 22:01 4ian

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.

AlexandreSi avatar Jan 21 '22 14:01 AlexandreSi

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.

4ian avatar Jan 21 '22 15:01 4ian

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

AlexandreSi avatar Jan 21 '22 16:01 AlexandreSi

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.

AlexandreSi avatar Jan 24 '22 14:01 AlexandreSi

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?

4ian avatar Jan 24 '22 19:01 4ian

If there are concerns on performance impacts on having this reload every time a tab is refreshed. What about the following two scenarios:

  1. On project load
  2. 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?

Silver-Streak avatar Jan 25 '22 14:01 Silver-Streak

Ideally we would have this situation:

  1. whenever you load a new project, we ensure resources are reloaded to avoid any mismatch.
  2. 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.

4ian avatar Jan 25 '22 15:01 4ian

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.

Bouh avatar Jan 25 '22 17:01 Bouh