godot引擎学习7
编辑器进程,
进入方式
D:\godot2\bin\godot.windows.tools.32.exe --path E:\G3WorkCode\Simple --editor
E:\godot\bin\godot.windows.tools.32.exe --path E:\G4WorkProject\Simple --editor
D:\godot2\bin\godot.windows.tools.64.exe --path E:\G3WorkCode\Simple --editor
D:\godot2\bin\godot.windows.tools.64.exe --path E:\G3WorkCode\SimpleDebug --editor
1)主要类 EditorNode
进入位置 start()
bool Main::start()
EditorNode *editor_node = nullptr;
if (editor) {
editor_node = memnew(EditorNode);
sml->get_root()->add_child(editor_node);
if (_export_preset != "") {
editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only);
game_path = ""; // Do not load anything.
}
}
EditorNode : public Node
构造函数中:
ScriptServer::set_scripting_enabled(false); 这一句脚本不能运行了
EditorNode::_editor_select(int p_which) 点击2D,3D,Scripe等事件函数
****************************
EditorPlugin : public Node 基类,成员变量实现UnDo,ReDo功能
实现一些公众操作功能,主要调用其他类的函数
EditorPlugins 工厂类,实现对EditorPlugin派生类的创建
EditorPlugins::add_by_type<EditorPluginCSG>();
EditorPlugins::add_by_type<SceneExporterGLTFPlugin>();
EditorPlugins::add_by_type<GridMapEditorPlugin>();
EditorPlugins::add_by_type<NavigationMeshEditorPlugin>();
class EditorData,主要管理成员
Vector<EditorPlugin *> editor_plugins;
class EditorHistory 辅助类
EditorSelection : public Object 辅助类
对于2D项的有关类
CanvasItemEditorPlugin : public EditorPlugin
主要成员:
CanvasItemEditor *canvas_item_editor; 具体工作
EditorNode *editor; 总节点
看看构造函数:
editor = p_node;
canvas_item_editor = memnew(CanvasItemEditor(editor));
canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_main_control()->add_child(canvas_item_editor);
canvas_item_editor->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
canvas_item_editor->hide();
真正的工作类
CanvasItemEditor : public VBoxContainer 是一个垂直布局
**************************************************
add_editor_plugin(memnew(AnimationPlayerEditorPlugin(this)));
AnimationPlayerEditorPlugin节点直接作为EditorNode的子节点
2D
add_editor_plugin(memnew(CanvasItemEditorPlugin(this)));
CanvasItemEditor节点为viewport的子节点,其中scene_root为CanvasItemEditor的子节点
CanvasItemEditorPlugin作为EditorNode的子节点
3D
add_editor_plugin(memnew(Node3DEditorPlugin(this)));
SpatialEditor节点为viewport的子节点
SpatialEditorPlugin作为EditorNode的子节点
脚本
add_editor_plugin(memnew(ScriptEditorPlugin(this)));
ScriptEditor节点为viewport的子节点
ScriptEditorPlugin作为EditorNode的子节点
增加AssetLib
if (StreamPeerSSL::is_available()) {
add_editor_plugin(memnew(AssetLibraryEditorPlugin(this)));
} else {
WARN_PRINT("Asset Library not available, as it requires SSL to work.");
}
事件:
tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size()));
EditorAssetLibrary节点为viewport的子节点
AssetLibraryEditorPlugin作为EditorNode的子节点
EditorNode布局说明***
1,上面部分
左边菜单
HBoxContainer *left_menu_hb = memnew(HBoxContainer); 一个水平布局
menu_hb->add_child(left_menu_hb); ****1
file_menu = memnew(MenuButton); 场景菜单
project_menu = memnew(MenuButton); 项目菜单
tool_menu = memnew(PopupMenu);项目菜单中子菜单
debug_menu = memnew(MenuButton); 调试菜单
help_menu = memnew(MenuButton); 帮助菜单
中间菜单
menu_hb->add_spacer(); ****2
main_editor_button_vb = memnew(HBoxContainer);
menu_hb->add_child(main_editor_button_vb); ****3
右边菜单
menu_hb->add_spacer(); ***3
HBoxContainer *play_hb = memnew(HBoxContainer); 一个水平布局
menu_hb->add_child(play_hb); ****4
play_button = memnew(ToolButton); 运行
pause_button = memnew(ToolButton); 暂停
run_native = memnew(EditorRunNative);
play_custom_scene_button = memnew(ToolButton);
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
menu_hb->add_child(right_menu_hb); *****5
外部:
main_vbox = memnew(VBoxContainer); 垂直布局
main_vbox->add_child(menu_hb);
main_vbox->add_child(left_l_hsplit); 两个子节点
2,左边部分
scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data));
import_dock = memnew(ImportDock);
filesystem_dock = memnew(FileSystemDock(this));
// Scene: Top left
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock);
dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
// Import: Top left, behind Scene
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(import_dock);
dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(import_dock->get_index(), TTR("Import"));
// FileSystem: Bottom left
dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock);
dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
// 这里说一下面板选板布局
a) dock_select_popup = memnew(PopupPanel);
gui_base->add_child(dock_select_popup); 这里主布局
b) VBoxContainer *dock_vb = memnew(VBoxContainer);
dock_select_popup->add_child(dock_vb);
里面只有一个垂直布局
c) 垂直布局的元素:
dock_vb->add_child(dock_hb); 这个是一个水平布局,分别 左,title 右
dock_vb->add_child(dock_select); 这个是一个Control对象,实现
Control对象的属性:
dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
dock_select->connect("draw", this, "_dock_select_draw");
然后和TabContainer绑定
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
dock_slot[i]->set_popup(dock_select_popup);
}
3,右边部分
inspector_dock = memnew(InspectorDock(this, editor_data));
node_dock = memnew(NodeDock);
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock);
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node"));
4,中间部分说明
主体部分:
tabbar_container = memnew(HBoxContainer);水平布局
1,插入右键菜单 tabbar_container->add_child(scene_tabs_context_menu);
scene_tabs_context_menu = memnew(PopupMenu);
2,插入Tabs tabbar_container->add_child(scene_tabs);
scene_tabs = memnew(Tabs); 显示多个场景,用Tab
3,插入增加场景 tabbar_container->add_child(scene_tab_add);
scene_tab_add = memnew(ToolButton);
4,插入专注模式tabbar_container->add_child(distraction_free);
distraction_free = memnew(ToolButton);
VBoxContainer *srt = memnew(VBoxContainer); 一个垂直布局
srt->add_child(tabbar_container);
srt->add_child(scene_root_parent);
就这两个元素
而这个 scene_root_parent = memnew(PanelContainer);
里面放一个垂直布局
main_control = memnew(VBoxContainer);
scene_root_parent->add_child(main_control);
main_control就是所有EditorPlugin派生节点的父节点, 记住这个节点就好了
比如脚本模式:
script_editor = memnew(ScriptEditor(p_node));
editor->get_viewport()->add_child(script_editor);
生成的ScriptEditor就是main_control的子节点
而libary模式:
addon_library = memnew(EditorAssetLibrary);
editor->get_viewport()->add_child(addon_library);
生成的EditorAssetLibrary也是main_control的子节点
3D模式:
spatial_editor = memnew(SpatialEditor(p_node));
editor->get_viewport()->add_child(spatial_editor);
spatial_editor->hide();
生成的SpatialEditor也是main_control的子节点
2D模式:
canvas_item_editor = memnew(CanvasItemEditor(editor));
editor->get_viewport()->add_child(canvas_item_editor);
生成的CanvasItemEditor也是main_control的子节点
至于scene_root = memnew(Viewport); 这个节点,主要是2D模式下用到这个作为父节点
场景Tab卡片上鼠标移会显示:
tab_preview_panel = memnew(Panel);
tab_preview_panel->set_size(Size2(100, 100) * EDSCALE);
tab_preview_panel->hide();
tab_preview_panel->set_self_modulate(Color(0, 0, 1, 0.7));
gui_base->add_child(tab_preview_panel);
tab_preview = memnew(TextureRect);
tab_preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
tab_preview->set_size(Size2(96, 96) * EDSCALE);
tab_preview->set_position(Point2(2, 2) * EDSCALE);
tab_preview_panel->add_child(tab_preview);
事件:
scene_tabs->connect("tab_hover", this, "_scene_tab_hover");
5,底部分析
底部 由bottom_panel = memnew(PanelContainer);这个节点管理
里面存放 bottom_panel_vb = memnew(VBoxContainer);垂直布局
垂直布局存放一个水平布局
bottom_panel_hb = memnew(HBoxContainer); 水平布局,依次放四个元素
1,增加bottom_panel_hb_editors,水平布局
2,增加version_info_vbc,垂直布局(仅调整)
3,增加v_spacer ,分割线
4,增加按纽 展开底部面板
输出(日志)
log = memnew(EditorLog);
Button *output_button = add_bottom_panel_item(TTR("Output"), log); 加在了bottom_panel_hb_editors水平布局上
log->set_tool_button(output_button);
调试器:add_editor_plugin(memnew(ScriptEditorPlugin(this)));
ScriptEditor::ScriptEditor(EditorNode *p_editor)中
EditorDebuggerNode *debugger = memnew(EditorDebuggerNode);
Button *db = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Debugger"), debugger);
debugger->set_tool_button(db);
动画:由add_editor_plugin(memnew(AnimationPlayerEditorPlugin(this)));
editor = p_node;
anim_editor = memnew(AnimationPlayerEditor(editor, this));
anim_editor->set_undo_redo(EditorNode::get_undo_redo());
editor->add_bottom_panel_item(TTR("Animation"), anim_editor);
搜索
add_editor_plugin(memnew(ScriptEditorPlugin(this)));由这里触发的
ScriptEditor::ScriptEditor(EditorNode *p_editor)中
find_in_files = memnew(FindInFilesPanel);
find_in_files_button = editor->add_bottom_panel_item(TTR("Search Results"), find_in_files);
find_in_files->hide(); 按纽这里隐藏了
音频
EditorAudioBuses *EditorAudioBuses::register_editor()
EditorAudioBuses *audio_buses = memnew(EditorAudioBuses);
EditorNode::get_singleton()->add_bottom_panel_item(TTR("Audio"), audio_buses);
着色器
shader_editor = memnew(ShaderEditor(p_node));
shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("Shader"), shader_editor);
button->hide(); 这里隐藏了
//ShaderFile
shader_editor = memnew(ShaderFileEditor(p_node));
shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
button = editor->add_bottom_panel_item(TTR("ShaderFile"), shader_editor);
button->hide();
ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item)分析
bottom_panel_vb->add_child(p_item); 垂直布局增加节点
bottom_panel_hb->raise(); bottom_panel_hb这个节点就是最上面的地方的了
调用这个就是把bottom_panel_hb这个节点放在最下面
bottom_panel_hb_editors->add_child(tb); 加入一个buttton
BottomPanelItem bpi;
bpi.button = tb;
bpi.control = p_item;
bpi.name = p_text;
bottom_panel_items.push_back(bpi);
信息保存一下,切换的时候使用
raise_bottom_panel_item(AnimationPlayerEditor::singleton);动画放在后面
7,其他窗体说明:
a)对话框:
class Popup : public Control
WindowDialog : public Popup
AcceptDialog : public WindowDialog
EditorAbout : public AcceptDialog
这样的对话框不能移到父窗口外面
b) 编辑器配置文件
feature_profile_manager = memnew(EditorFeatureProfileManager);
管理导出模块
export_template_manager = memnew(ExportTemplateManager);
项目设置 由菜单点击
project_settings = memnew(ProjectSettingsEditor(&editor_data));
编辑设置
settings_config_dialog = memnew(EditorSettingsDialog);
保存/删除布局对话框
layout_dialog = memnew(EditorLayoutsDialog);
gui_base->add_child(layout_dialog);
8,几个子布局说明
1, CreateDialog创建结点对话框
背景颜色改变:
Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
style->set_bg_color(Color(255, 0, 0, 1));
add_style_override("panel", style);
2,脚本插件分析:
ScriptEditorPlugin : public EditorPlugin
主要成员:ScriptEditor *script_editor;
ScriptEditor : public PanelContainer
布局分析
TabContainer *tab_container; //里面存放的是ScriptEditorBase
ScriptEditorBase : public VBoxContainer一个抽象类
ScriptTextEditor : public ScriptEditorBase
TextEditor : public ScriptEditorBase
VisualScriptEditor : public ScriptEditorBase
有以上三种实现
如果资源是Script则用ScriptTextEditor类
如果资源是TextFile则TextEditor类
如果资源是VisualScript则用VisualScriptEditor类
ScriptTextEditor : public ScriptEditorBase
主要成员:
CodeTextEditor *code_editor;
RichTextLabel *warnings_panel;
CodeTextEditor : public VBoxContainer主要成员为:
TextEdit *text_editor;
双击gd文件,最主要调用
editor_plugin_screen->edit(current_obj);
3) 分析AssetLibrary
AssetLibraryEditorPlugin类
AssetLibraryEditorPlugin : public EditorPlugin
主要成员:
EditorAssetLibrary *addon_library;
EditorNode *editor;
EditorAssetLibrary : public PanelContainer布局分析
VBoxContainer *library_main = memnew(VBoxContainer); 垂直布局
1,增加HBoxContainer *search_hb 水平布局
LineEdit过滤条件,Timer,VSeparator,Button导入,Button插件
2,HBoxContainer *search_hb2 水平布局
Label(TTR("Sort:"),OptionButton,memnew(VSeparator),Label(TTR("Category:"),OptionButton,memnew(VSeparator),Label(TTR("Site:"),OptionButton,MenuButton支持
3,library_scroll_bg = memnew(PanelContainer);
只有一个 library_scroll = memnew(ScrollContainer);
library_scroll_bg->add_child(library_scroll);子节点
library_scroll 也只有一个子节点
PanelContainer *library_vb_border = memnew(PanelContainer);
library_vb_border 存放一个垂直布局
分别存放 1,library_loading Label
2,library_error Label
3,asset_top_page HBoxContainer
4,asset_items, GridContainer
5,asset_bottom_page HBoxContainer
其中4为内容
EditorAssetLibraryItem *item = memnew(EditorAssetLibraryItem);
asset_items->add_child(item);
4,error_hb = memnew(HBoxContainer);
5,downloads_scroll = memnew(ScrollContainer);
4)AssetLibrary请求数据流程
请求的数据类型为三种:
REQUESTING_CONFIG
REQUESTING_SEARCH
REQUESTING_ASSET
首先请求配置数据,
得到
{
"categories": [{
"id": "1",
"name": "2D Tools",
"type": "0"
}, {
"id": "2",
"name": "3D Tools",
"type": "0"
}, {
"id": "3",
"name": "Shaders",
"type": "0"
}, {
"id": "4",
"name": "Materials",
"type": "0"
}, {
"id": "5",
"name": "Tools",
"type": "0"
}, {
"id": "6",
"name": "Scripts",
"type": "0"
}, {
"id": "7",
"name": "Misc",
"type": "0"
}]
}
然后调用search,其实就是发送请求数据
https://godotengine.org/asset-library/api/asset?sort=updated&godot_version=4.0&support=official+community
得到如下数据:
"asset_id": "739",
"title": "InterpolatedCamera3D",
"author": "Calinou",
"author_id": "10",
"category": "3D Tools",
"category_id": "2",
"godot_version": "4.0",
"rating": "0",
"cost": "MIT",
"support_level": "community",
"icon_url": "https:\/\/raw.githubusercontent.com\/godot-extended-libraries\/godot-interpolated-camera3d\/master\/icon.png",
"version": "2",
"version_string": "1.1.0",
"modify_date": "2021-09-24 20:56:30"
然后开始请求icon_url的数据到本地文件
5) EditorAssetLibraryItem类的布局
6)增加场景事件
scene_tabs->connect("tab_closed", callable_mp(this, &EditorNode::_scene_tab_closed), varray(SCENE_TAB_CLOSE));
void EditorNode::_menu_option(int p_option) {
_menu_option_confirm(p_option, false);
}
调用
int EditorNode::new_scene() {
int idx = editor_data.add_edited_scene(-1); 增加一个EditedScene结构
_scene_tab_changed(idx);
editor_data.clear_editor_states();
_update_scene_tabs();
return idx;
}
关闭场景
void EditorNode::_scene_tab_closed(int p_tab, int option)
中,如果没有根结点直接关闭
Node *scene = editor_data.get_edited_scene_root(p_tab);
if (!scene) {
_discard_changes();
return;
}
加到tab中
scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon);
主要看一下EditorData类
主要成员:
Vector<EditorPlugin *> editor_plugins;
Map<String, Vector<CustomType>> custom_types;
List<PropertyData> clipboard;
UndoRedo undo_redo;
Vector<Callable> undo_redo_callbacks;
Map<StringName, Callable> move_element_functions;
Vector<EditedScene> edited_scene;
int current_edited_scene;
双击xx.tscn文件的流程
a)FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorites)中调用
if (ResourceLoader::get_resource_type(fpath) == "PackedScene") {
editor->open_request(fpath);
} else {
editor->load_resource(fpath);
}
b)进入EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported, bool p_silent_change_tab)
Error err;
Ref<PackedScene> sdata = ResourceLoader::load(lpath, "", true, &err);
产生结点:
Node *new_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_MAIN);
最终产生位置:
obj = ClassDB::instance(snames[n.type]);
script_instance值为:0x0000000000000000
Object::set_script(const RefPtr &p_script)中
script_instance = s->placeholder_instance_create(this);
用
PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this)
在EditorNode::set_edited_scene(Node *p_scene)中
if (p_scene) {
if (p_scene->get_parent() != scene_root)
scene_root->add_child(p_scene);
}
7)ScriptEditorPlugin脚本类分析
ScriptEditorPlugin : public EditorPlugin
主要成员:
ScriptEditor *script_editor;
EditorNode *editor;
构造方式:
editor = p_node;
script_editor = memnew(ScriptEditor(p_node));
editor->get_main_control()->add_child(script_editor);
ScriptEditor类
ScriptEditor : public PanelContainer
code_editor_container->add_child(tab_container);
code_editor_container->add_child(find_replace_bar);
tab_container->connect("tab_changed", callable_mp(this, &ScriptEditor::_tab_changed));
ScriptTextEditor::register_editor(); //register one for text scripts
TextEditor::register_editor();
register_editor_callback()
最后都调用
ScriptEditor::register_create_script_editor_function(create_editor); 三个函数指针放在script_editor_funcs
for (int i = script_editor_func_count - 1; i >= 0; i--) {
se = script_editor_funcs[i](p_resource);
if (se) {
break;
}
}
这里生成ScriptTextEditor对象
ScriptTextEditor : public ScriptEditorBase
ScriptEditorBase : public VBoxContainer为一个虚基类
ScriptTextEditor 的主要成员:
CodeTextEditor *code_editor = nullptr;
CodeTextEditor : public VBoxContainer
RichTextLabel *warnings_panel = nullptr;
RichTextLabel : public Control
RichTextLabel *errors_panel = nullptr;
看一看脚本数据类
Resource : public RefCounted
Script : public Resource 为一个虚基类
函数:
virtual ScriptInstance *instance_create(Object *p_this);
virtual PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this);
几个实现
GDScript : public Script
NativeScript : public Script
class ScriptInstance 为一个抽象类
几个函数:
virtual void call_multilevel(const StringName &p_method, VARIANT_ARG_LIST);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
class ScriptLanguage 为一个抽象类
几个实现
class PlaceHolderScriptInstance : public ScriptInstance 占位符的实现方法
构造函数:PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner);
此类主要是对Script进行一些操作,并没有对call_multilevel_reversed函数进行重写
实例化:script_instance = s->placeholder_instance_create(this);
PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this)
NativeScriptInstance : public ScriptInstance
class NativeScriptLanguage : public ScriptLanguage
GDScriptInstance : public ScriptInstance
class GDScriptLanguage : public ScriptLanguage
GDScriptCache::get_full_script中读脚本文件
Ref<GDScript> script = get_shallow_script(p_path);
ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());
r_error = script->load_source_code(p_path);
GDScript::reload(bool p_keep_state)中
GDScriptParser parser;
Error err = parser.parse(source, path, false); 判断脚本有没有错误
语法
GDScriptAnalyzer analyzer(&parser);
err = analyzer.analyze();
GDScriptCompiler compiler;
err = compiler.compile(&parser, this, p_keep_state);
保存脚本文件
EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path)
Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags)
if (ScriptServer::is_reload_scripts_on_save_enabled()) {
GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, false);
}
GDScript::reload(bool p_keep_state)
*********************************************************
EditorRun::run(const String &p_scene 开启另一个进程
编辑进程与调试进程的互动关系
1,调试进程关闭收到的消息
开启调试进程后,一直收到NOTIFICATION_PROCESS消息
EditorDebuggerNode::start(const String &p_uri)中调用
set_process(true);这样就可以收到_notification
EditorNode::get_singleton()->get_scene_tree_dock()->show_tab_buttons();
debugger->set_editor_remote_tree(remote_scene_tree);
debugger->start(server->take_connection());
然后ScriptEditorDebugger类也进行start,
EditorDebuggerNode管理ScriptEditorDebugger类
2,编辑进程开启服务器
EditorDebuggerNode类中成员: Ref<EditorDebuggerServer> server;
EditorDebuggerServerTCP
端口6007,127.0.0.1
最后 NetSocketPosix : public NetSocket 类进行具体操作
连接成功后,产生RemoteDebuggerPeer对象,具体RemoteDebuggerPeerTCP
由ScriptEditorDebugger管理
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp)
开启一个线程
ScriptEditorDebugger::_notification(int p_what) == 17
if (!is_session_active()) {
_stop_and_notify();
break;
};
godot引擎学习7相关推荐
- godot引擎学习5
中文文档 https://docs.godotengine.org/zh_CN/latest/about/introduction.html 基础类 register_core_types 先调用,主 ...
- godot引擎学习4
基本数据结构 1, SafeNumeric 安全数值类 原子操作 2, SafeRefCount 引用计数类,组合SafeNumeric类 3,mutable变量的值 ,某个常成员函数的调用次数时 ...
- godot引擎学习6
项目管理器结构: 主要类ProjectManager 1,CanvasItem : public Node 任何2d的基类. void _draw ( ) virtual 调用(如 ...
- godot引擎学习10
调试进入进程, 进入方式 --path E:/G4WorkProject/SimpleDebug --remote-debug tcp://127.0.0.1:6007 --allow_fo ...
- godot引擎学习9
游戏进入参数 D:\godot2\bin\godot.windows.tools.64.exe --path E:\G3WorkCode\SimpleDebug --remote-debug tcp ...
- Godot3游戏引擎入门之零一:【翻译】为什么要选择 Godot 引擎
前言 本文作为我的 Godot 系列文章的第二篇,是一篇翻译文作为 Godot 的优点说明吧,虽然文章发布于去年,但还是很有借鉴意义,翻译的不是很好请海涵! :smile: 作者简介:Rock Mil ...
- Godot引擎 4.0 文档 - 第一个 2D 游戏
本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正.英文原版页面: Your first 2D game - Godot Engine (stable) docum ...
- ue4 迁移模型_UE4虚幻引擎学习云笔记(六)-关卡设计入门-[5.地形快速入门]
[六.关卡设计入门(Level Designer Quick Start)] 19-09-29 UE4虚幻引擎学习云笔记(六)-关卡设计入门zhuanlan.zhihu.com UE4虚幻引擎学习云 ...
- velocity(vm)模板引擎学习介绍及语法
velocity模板引擎学习 velocity与freemaker.jstl并称为java web开发三大标签技术,而且velocity在codeplex上还有.net的移植版本NVelocity,( ...
最新文章
- java mysql 删除 博客园_mysql的增删改查
- [git]git相关
- Qt 断言的使用 Q_ASSERT
- python语言的单行注释以井号开头_【学习】Python语言入门
- 浅说深度学习(1):核心概念
- 为Sublime Text 3的C++编译器(g++)添加C++11标准的方法
- ERP产品销售发货判断库存功能(四十二)
- JAVA多线程----用--取钱问题1
- 【CSS3】 线性渐变
- eclipse字体大小设置教程(eclipse主窗口和控制台字体大小设置)
- 2265. 统计值等于子树平均值的节点数
- 鲲鹏920是计算机CPU吗,鲲鹏920是电脑cpu吗
- Cadence OrCAD Capture 如何批量替换元器件
- FANUC机器人的通讯方式(4)TIA博途如何添加机器人组态网络
- docker多容器操作与强制删除容器的方法步骤
- Cydia常用源推荐
- vpython_Vpython简单例子
- Java String的API方法总结
- 【DEM格式转换】转换国标DEM数据格式为通用格式
- *VWRITE 命令应该注意的事项