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

Add callbacks to Main::setup() / Main::start() / Main::cleanup(), so to allow much freedom to modules. #1593

Open
AndreaCatania opened this issue Oct 2, 2020 · 5 comments

Comments

@AndreaCatania
Copy link

Describe the project you are working on:
I'm working on a game, and I'm creating various C++ modules. Couple of those modules, need to know when the engine setup is over, and so the SceneTree or other singletons are ready to be used.

Describe the problem or limitation you are having in your project:
Those modules try to connect to some events like process and so on, but since the engine is not ready, there is no way to connects to those events. Right now, from the register_MODULE_types() it's not possible to know when the engine starts.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
The idea is to add 3 callbacks to the Main class:

  • on_setup_done
  • on_start
  • on_cleanup

From the register_MODULE_types() will be possible to add callbacks in the following way:

void register_MODULE_types(){
    Main::add_callback(&my_setup_function, Main::SETUP_CALLBACK);
}

All the registered callbacks will be called when the setup/start terminates or the cleanup is started.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
Right before the Main::setup2 is done https://github.com/godotengine/godot/blob/master/main/main.cpp#L1719-L1720 the following code is executed:

for(int i = 0; i < on_setup_done_callbacks.size(); i+=1){
    on_setup_done_callbacks[i]();
}

So the modules, will be able to interact with the engine extensively.

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

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

@Xrayez
Copy link
Contributor

Xrayez commented Oct 2, 2020

This is needed because of issues like Zylann/godot_voxel#189.

Godot 4.0 adds ability to preregister_types(), but it has no corresponding preunregister_types(). Of course having Main callbacks as proposed here could also provide an extensive solution, I believe. 🙂

@Zylann
Copy link

Zylann commented Oct 8, 2020

Would this also allow my module to register a "process" callback without needing a node in the tree? I have some sort of server which needs to run an update loop like some other servers do (Physics Server, Visual Server) but I could not find a way to insert this within the main loop.

@AndreaCatania
Copy link
Author

Yes, you can obtain the SceneTree singleton (into the setup_done callback) and register the function to the process event. In this way your singleton is naturally called each frame or physics frame without the need to use a node.

@Calinou Calinou changed the title Add callbacks to Main::setup / Main::start / Main::cleanup, so to allow much freedom to modules. Add callbacks to Main::setup() / Main::start() / Main::cleanup(), so to allow much freedom to modules. Oct 8, 2020
@Xrayez
Copy link
Contributor

Xrayez commented Feb 2, 2021

I've noticed there's SceneTree::add_idle_callback() which can be used in modules, but this is only useful for flushing custom deferred calls since that's how MessageQueue flushing is currently used throughout the engine (those idle callbacks are called on _call_idle_callbacks()), you can actually see it in action in goostengine/goost#51.

I suspect that it might not be always thread-safe, so that's where we'd also like to have ability to register process callbacks as well. Due to this, I think that it may be also required to check whether you're inside physics frame with Engine.is_in_physics_frame() too if you do use SceneTree::add_idle_callback(), but I'm not 100% sure about it.

Yes, you can obtain the SceneTree singleton (into the setup_done callback) and register the function to the process event.

@AndreaCatania not sure whether I understand this correctly, do you imply that there's some other/existing mechanism already available for registering process callbacks within the engine (just like SceneTree::add_idle_callback(), or perhaps we're talking about the same thing already)?

@AndreaCatania
Copy link
Author

I've implemented this feature here: godotengine/godot#50179 @Xrayez check it, maybe it's cleaner what I meant by checking the code.

AndreaCatania added a commit to AndreaCatania/godot that referenced this issue Jul 5, 2021
This feature add a mechanism that emits a notification when a specific app lifecycle phase
is executed.
It call the callback on:
- Setup begins (`Main::setup`) LIFECYCLE_PHASE_SETUP_BEGIN
- Setup2 begins (`Main::setup2`) LIFECYCLE_PHASE_SETUP2_BEGIN
- Setup2 done (`Main::setup2`) LIFECYCLE_PHASE_SETUP2_DONE
- Start begins (`Main::start`) LIFECYCLE_PHASE_START_BEGIN
- Start done (`Main::start`) LIFECYCLE_PHASE_START_DONE
- Cleanup begins (`Main::cleanup`) LIFECYCLE_PHASE_CLEANUP_BEGIN
- Cleanup done (`Main::cleanup`) LIFECYCLE_PHASE_CLEANUP_DONE

----

To use it, it's enough to implement the function
`void MODULENAME_lifecycle_callback(int);` to `yourmodule/register_types.h` and
define the macro: `#define MODULE_MODULENAME_HAS_LIFECYCLE_CALLBACK`

For example, if we need to register a new singleton in the GLTF module, we
can write the following:
```c++
// .h

void gltf_lifecycle_callback(int p_lifecycle_phase);

// .cpp

void gltf_lifecycle_callback(int p_lifecycle_phase) {
	switch (p_lifecycle_phase) {
		case LIFECYCLE_PHASE_STARTUP_BEGIN:
			// TODO Init here the singleton.
			break;
		case LIFECYCLE_PHASE_CLEANUP_BEGIN:
			// TODO Clear here the singleton.
			break;
	}
}
```

Implements the proposal: godotengine/godot-proposals#1593
The proposal code is different than this implementation because this
code is using the adviced implementation the core dev adviced.
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

3 participants