godot游戏引擎的启动
启动的入口代码在:platform/windows/godot_windows.cpp
WinMain()->main()
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
godot_hinstance = hInstance;
return main(0, nullptr);
}
main()->_main()
int main(int argc, char **argv) {
// override the arguments for the test handler / if symbol is provided
// TEST_MAIN_OVERRIDE
// _argc and _argv are ignored
// we are going to use the WideChar version of them instead
#ifdef CRASH_HANDLER_EXCEPTION
__try {
return _main();
} __except (CrashHandlerException(GetExceptionInformation())) {
return 1;
}
#else
return _main();
#endif
}
_main()->Main类
int _main() {
result = widechar_main(argc, wc_argv);
}
int widechar_main(int argc, wchar_t **argv) {
OS_Windows os(nullptr);
setlocale(LC_CTYPE, "");
char **argv_utf8 = new char *[argc];
for (int i = 0; i < argc; ++i) {
argv_utf8[i] = wc_to_utf8(argv[i]);
}
TEST_MAIN_PARAM_OVERRIDE(argc, argv_utf8)
Error err = Main::setup(argv_utf8[0], argc - 1, &argv_utf8[1]);
if (err != OK) {
for (int i = 0; i < argc; ++i) {
delete[] argv_utf8[i];
}
delete[] argv_utf8;
if (err == ERR_HELP) { // Returned by --help and --version, so success.
return 0;
}
return 255;
}
if (Main::start()) {
os.run();
}
Main::cleanup();
for (int i = 0; i < argc; ++i) {
delete[] argv_utf8[i];
}
delete[] argv_utf8;
return os.get_exit_code();
}
Main类的关键函数和启动时调用
/* 引擎初始化
*
* 由若干个methods组成,这些methonds会被平台特定 main(argc, argv)所调用.
* 为了完整的理解引擎初始化, 需要从平台的main开始,看他是怎样调用 Main class' methods的.
*
* 典型的初始化过程分3步构成 (其中setup2这步可以由setup自动触发,也可以在平台的main中手动触发).
*
* - setup(execpath, argc, argv, p_second_phase) 是所有平台的主入口点,
* 负责所有底层singletons and core types 的初始化,并且解析cmd参数并进行配置。
* 如果 p_second_phase 为 true, 将会接下来执行 setup2() (default behavior). 这个过程在某些平台(Android, iOS, UWP)
* 是disabled,在他们自己运行时触发。
*
* - setup2(p_main_tid_override) registers high level servers and singletons, displays the
* boot splash, then registers higher level types (scene, editor, etc.).
*
* - start()是最后一步,也是cmd工具开始运行的地方,main loop 最终被创建,系统的设置也放入执行,这里也是editor node创建的地方.
* 如果需要 start()会处理命令行参数的子参数, 这个很麻烦需要setup()进行全局的解析。
*/
Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {}