Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live-reload nodes in a running game when files from their scene_file_path are reimported #9519

Open
passivestar opened this issue Apr 14, 2024 · 13 comments

Comments

@passivestar
Copy link

passivestar commented Apr 14, 2024

Describe the project you are working on

Any project

Describe the problem or limitation you are having in your project

Level design is an iterative process and Iteration is slow when you need to restart the game every time you make a change to a glTF file. This is especially relevant when you're using an external 3d editor (like blender) as a level editor, be it either for quick blockouts or entire levels if you take advantage of custom import plugins

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Reload resources in the running game when reimport happens in editor

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

After some testing I discovered that even though glTF models aren't synced with the running game when reimport happens, if you delete the scene node and then drop it back in from the FileSystem dock it does update in-game, which means that there is already a mechanism to hot-load resources from disc in a running game

After taking a quick look at the source code it seems like all it would take is to either add a new message (i.e scene:live_reload_node) or just use the existing scene:live_remove_node and scene:live_instantiate_node messages to recreate the node when the file from its scene_file_path is reimported (Edit: it's probably better to go with a new message because it will allow more flexibility, i.e adding logic to preserve child nodes on the nodes that we're recreating)

Edit: a short video from twitter to show this proposal in action

wild.mp4

Also could consider the possibility of reloading in the running game without any message from the editor because it seems like all it needs is a file path (and the ability to watch for changes). (Edit: after some quick experiments with a plugin it seems like this wouldn't be worth the extra effort since it works pretty well when reimported through editor)

The problem is that right now for the reimport to trigger you need to give the editor focus. It can be worked around by continuously reimporting assets on timer, but it's clunky (maybe it makes sense to stop requiring window focus for asset reimport, or at least make it an editor setting?). (Edit: this is now fixed in master)

Ideally you'd only need to switch between blender and the running game to make levels

If this enhancement will not be used often, can it be worked around with a few lines of script?

I don't think so

Is there a reason why this should be core and not an add-on in the asset library?

I don't think live debugging is exposed to GDScript at all
(Edit: it is exposed and can be a plugin but this is a basic and useful feature to have alongside other existing live debugging features)

@KoBeWi
Copy link
Member

KoBeWi commented Apr 14, 2024

EditorFileSystem has resources_reimported signal, which also provides the list of reimported files. You can e.g. store it in a file and read that file in running game. There is EditorDebuggerPlugin which could probably achieve this, but personally I handle editor <-> game communication using files and it works quite well.

@passivestar
Copy link
Author

There is EditorDebuggerPlugin which could probably achieve this

Then I'm wrong about it not being exposed to GDScript. If so, we just need to answer the question of whether it should work out of the box with no plugins. I'll probably be able to tell once I try to implement it as a plugin. If it's easy then it would probably make sense to have in editor because other operations like node creation/deletion work and users will probably expect reimport to work as well (I did)

But the problem of editor needing focus for asset reimport will still need to be addressed for this workflow to be feasible

@passivestar
Copy link
Author

Tested a very barebones version of an EditorDebuggerPlugin that goes through all of the nodes of the scene and recreates those that have a scene_file_path that was reimported. Works fine, including objects with import hints, except of course for the fact that if those nodes are modified at runtime you'll lose any modifications. It's not a problem in my workflow (I don't touch imported models, any logic/state/etc goes on the parent node), but this will need to be thought through

I'm currently rescanning the filesystem on timer which isn't great, not to mention the bug that opens vscode after reimport which forced me to switch to the internal script editor to be able to record those videos. Godot also steals window focus when reimporting assets (for no apparent reason) it will even maximize the window if it's minimized, so I had to set the minimum window size to (100, 100) to be able to move it out of the way to make sure it doesn't pop up on top of blender and godot game. So even with an addon this is all very scuffed and there are a lot of problems to solve here. It will probably be best to solve one at a time starting with allowing reimports with no focus. Then we can return to this

@Calinou
Copy link
Member

Calinou commented Apr 15, 2024

Godot also steals window focus when reimporting assets (for no apparent reason) it will even maximize the window if it's minimized

I was thinking we should do away with the reimport popup progress and make it a progress bar that appears at the bottom of the editor instead (like when you save a file in LibreOffice), but importing in Godot is intentionally a blocking process. This is done so you can't end up with inconsistent scene state (which could happen if you're making changes while the editor is reimporting a resource).

We could use this approach for saving though – this would make Save on Focus Loss much more reliable.

@passivestar
Copy link
Author

I was thinking we should do away with the reimport popup progress and make it a progress bar that appears at the bottom of the editor instead (like when you save a file in LibreOffice), but importing in Godot is intentionally a blocking process

Yeah that's what I thought. so you're saying that godot gets focus and gets maximized because the popup window is shown? could we maybe delay showing the reimport popup until godot gets focus from the user?

Because even with the problem with the focus stealing aside, the popup is shown in the middle of the screen right now no matter where the editor window is, which is very intrusive. I don't think any app should do this, at the very least the popup should appear in the center of the editor window, not in the center of the screen. But if we don't show the popup at all while godot has no focus that shouldn't be a problem

@Calinou
Copy link
Member

Calinou commented Apr 15, 2024

But if we don't show the popup at all while godot has no focus that shouldn't be a problem

That was my initial thought, but if the reimport is taking a long time, you may not have focus on Godot at first but you might alt-tab to it later while it's still reimporting. In this case, you wouldn't have any visible progress feedback and Godot would appear to be frozen.

@passivestar
Copy link
Author

passivestar commented Apr 15, 2024

Maybe godot should do import non-blockingly and disable input artificially while importing? Then you can support the progressbar in the main window and a cancel button if it's ever needed

I guess user input isn't the only thing that can change things, but since the editor is basically a godot game it should be relatively easy to pause editor tools and such, right? 🤔

@clankill3r
Copy link

https://twitter.com/passivestar_/status/1779595365601124585

@seppoday
Copy link

Would that also work for 2D? For example redrawing something in Photoshop and seeing changes on game without reloading it?

@passivestar
Copy link
Author

Would that also work for 2D? For example redrawing something in Photoshop and seeing changes on game without reloading it?

I haven't done much 2d in godot but I expect this to be easier to do than 3d because you'd just be updating images instead of entire scene tree branches

@passivestar
Copy link
Author

passivestar commented Apr 17, 2024

Godot also steals window focus when reimporting assets (for no apparent reason) it will even maximize the window if it's minimized, so I had to set the minimum window size to (100, 100) to be able to move it out of the way to make sure it doesn't pop up on top of blender and godot game

Correction: When reimport happens the editor window doesn't get focus so it doesn't go over blender's window, it only gets in front of the game window. Does anyone know why this is happening and how to fix this?

Screen.Recording.mp4

Edit: opened an issue for this godotengine/godot#90940

@passivestar
Copy link
Author

passivestar commented Apr 20, 2024

Opened several issues that are related to this proposal. They are all about the resource import, but on the editor side:

godotengine/godot#90659
godotengine/godot#90937
godotengine/godot#90940
godotengine/godot#90944
godotengine/godot#90980
godotengine/godot#91600
godotengine/godot#92250

@passivestar
Copy link
Author

Related to this proposal: noticed that signals aren't synced too. Opened a proposal for that: #9675

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants