godot引擎学习5

中文文档
https://docs.godotengine.org/zh_CN/latest/about/introduction.html

基础类

register_core_types 先调用,主要进行setup函数

1, Object类
     #define memnew(m_class) _post_initialize(new ("") m_class)
      注意,重载void *operator new(size_t p_size, const char *p_description) 第一个参数是固定的,
     Object类, Object对象提供反射和可编辑的属性,
     CustomObject* pobj = memnew(CustomObject);
     调用Object构造函数,加入 ObjectDB::add_instance当中去
     然后调用_postinitialize

    1) 绑定一个函数
    ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &CustomObject::set_volume_db);
    调用 call("set_volume_db",344.3); 
    MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
    不知道这样有什么好处?
  2)类似信号信号槽
       ADD_SIGNAL(MethodInfo("been_killed")); 后面带参数
       执行
       emit_signal(SNAME("been_killed"));
       另一个类
       pobj->connect("been_killed", callable_mp(this, &OtherObject::_bus_layout_changed));
       还要自己写一个干嘛,不是有现存的吗

     ObjectDB一个静态类
    MethodBind抽像类,主要成员:
int method_id;
    uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
    StringName name;
    StringName instance_class;
    Vector<Variant> default_arguments;
    int default_argument_count = 0;
    int argument_count = 0;
抽像方法:
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0;
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0;

class MethodBindT : public MethodBind 一个实现
void (MB_T::*method)(P...); 一个函数指针
看其构造函数:主要是指导函数指针保存
MethodBindT(void (MB_T::*p_method)(P...)) {
        method = p_method;
#ifdef DEBUG_METHODS_ENABLED
        _generate_argument_types(sizeof...(P));
#endif
        set_argument_count(sizeof...(P));
    }
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error)实现主要是用函数指针执行

创建MethodBind的一个工厂函数:
template <class T, class... P>
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
    MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
#else
    MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
#endif
    a->set_instance_class(T::get_class_static());
    return a;
}
用MethodBindT去创建一个对象

template <class N, class M>
    static MethodBind *bind_method(N p_method_name, M p_method) {
        MethodBind *bind = create_method_bind(p_method);

        return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, nullptr, 0); //use static function, much smaller binary usage
    }
N 一般为MethodDefinition,M为函数指针
看一下MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount)
直接返回p_bind对象,主要是设置一些属性


2, RefCounted类
      两个成员:
     SafeRefCount refcount;
     SafeRefCount refcount_init;  这个干什么用?

      Ref<>自动进行计数计算

      WeakRef : public RefCounted

     SceneTreeTimer : public RefCounted 
     有一个timeout的信号绑定

3, 
     Node : public Object  所有的基类 场景 物体
    
    这意味着将节点添加到场景树时,回调将使用以下顺序: _enter_tree 父母的, _enter_tree 孩子们, _ready 孩子们,最后 _ready 父级的(对于整个场景树递归)。

     Viewport : public Node
    
     Window : public Viewport

4,Resource : public RefCounted

     Script : public Resource,不能实例化

     Theme : public Resource
      用于剥皮控件的主题。控件可以单独剥皮,但对于复杂的应用程序,只创建定义所有内容的全局主题更为实际。此主题可应用于任何 Control ;控件及其子控件将自动使用它。
     主题资源也可以通过在 .theme 文件,

     StyleBox : public Resource    用于为UI绘制样式化的框,主要成员 float margin[4];  框内容的下边距,左边距,上边距
     StyleBoxEmpty : public StyleBox  空样式框(不显示任何内容)

     StyleBoxTexture : public StyleBox
     基于纹理的九片 StyleBox ,以类似于 NinePatchRect . 这个样式框执行纹理的3×3缩放,其中只有中心单元格被完全拉伸。

     StyleBoxFlat : public StyleBox
     这个样式框可以用来实现各种外观,而不需要纹理。这些属性是可自定义的:
          颜色
          边框宽度(每个边框的单独宽度)
          圆角(每个角的单独半径)
          阴影
    bg_color 样式框的背景色
    border_blend 设置边框混合(值)
     border_color  设置边框的颜色
    border_width_bottom 设置边框宽度(值)
    corner_detail 设置用于每个角点的顶点数量。值越大,角越圆,但需要更多的处理能力来计算,对于小于10的角半径,4-5应该足够。对于小于30的角半径,8-12应该足够
    shadow_color 阴影的颜色

    StyleBoxLine : public StyleBox  仅画一条直线,分垂直和水平,可指定颜色

String ResourceFormatLoaderText::get_resource_type(const String &p_path) const 

5,消息循环
     MainLoop类,管理成员 Ref<Script> initialize_script;  游戏主循环的抽象基类。
     BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
     先找到类名,然后把字符串与数值放到一个map中
      bool _idle ( float delta ) virtual
     以自上次空闲帧以来的时间作为参数调用每个空闲帧(秒)。
    如果实现,该方法必须返回布尔值。 true 结束主循环,而 false 让它进入下一帧。

    SceneTree : public MainLoop 真正工作类
    debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42));  项目设置
    bool debug_collisions_hint  设置调试冲突提示(值)
    MultiplayerAPI multiplayer  设置多人游戏(值)
    bool multiplayer_poll  设置多人投票(值)
   NetworkedMultiplayerPeer network_peer 设置网络对等(值)
   int get_frame ( ) const 返回当前帧号,即自应用程序启动以来的总帧计数。

6 setup 对系统进行了参数解析并初始化操作, 包括引擎内部对象的创建,根据参数判断是需要启动 “项目管理器”,“编辑器”,“游戏”,“场景”,“脚本”等
   setup 之后,osx/win/x11 平台还有 需要执行 Main::setup2 这里初始化了音频/AR
   消息处理函数
   LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

   对于项目管理器:
    Engine::get_singleton()->set_editor_hint(true);
    ProjectManager *pmanager = memnew(ProjectManager);
    ProgressDialog *progress_dialog = memnew(ProgressDialog);
    pmanager->add_child(progress_dialog);
   sml->get_root()->add_child(pmanager);
   DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN);

  Main::iteration()中
  主要是 SceneTree::physics_process(double p_time) 看_quit变量
            bool SceneTree::process(double p_time) 看_quit变量

7,对Timer分析一下
class Timer : public Node {
    GDCLASS(Timer, Node);

    double wait_time = 1.0;
    bool one_shot = false;
    bool autostart = false;
    bool processing = false;
    bool paused = false;

    double time_left = -1.0;

protected:
    void _notification(int p_what);
    static void _bind_methods();

public:
    enum TimerProcessCallback {
        TIMER_PROCESS_PHYSICS,
        TIMER_PROCESS_IDLE,
    };

    void set_wait_time(double p_time);
    double get_wait_time() const;

    void set_one_shot(bool p_one_shot);
    bool is_one_shot() const;

    void set_autostart(bool p_start);
    bool has_autostart() const;

    void start(double p_time = -1);
    void stop();

    void set_paused(bool p_paused);
    bool is_paused() const;

    bool is_stopped() const;

    double get_time_left() const;

    void set_timer_process_callback(TimerProcessCallback p_callback);
    TimerProcessCallback get_timer_process_callback() const;
    Timer();

private:
    TimerProcessCallback timer_process_callback = TIMER_PROCESS_IDLE;
    void _set_process(bool p_process, bool p_force = false);
};

VARIANT_ENUM_CAST(Timer::TimerProcessCallback);

宏#define GDCLASS(m_class, m_inherits) 
主要是实现mutable StringName _class_name;
String get_class()
String get_class_static()
String get_parent_class_static()
static void initialize_class()
virtual void _notificationv(int p_notification, bool p_reversed) override

#define VARIANT_ENUM_CAST(m_enum) 
定义几个静态函数,cast,convert,encode
实现main\timer.cpp

void Timer::_bind_methods() { 静态函数
    ClassDB::bind_method(D_METHOD("set_wait_time", "time_sec"), &Timer::set_wait_time);
    ClassDB::bind_method(D_METHOD("get_wait_time"), &Timer::get_wait_time);

    ClassDB::bind_method(D_METHOD("set_one_shot", "enable"), &Timer::set_one_shot);
    ClassDB::bind_method(D_METHOD("is_one_shot"), &Timer::is_one_shot);

    ClassDB::bind_method(D_METHOD("set_autostart", "enable"), &Timer::set_autostart);
    ClassDB::bind_method(D_METHOD("has_autostart"), &Timer::has_autostart);

    ClassDB::bind_method(D_METHOD("start", "time_sec"), &Timer::start, DEFVAL(-1));
    ClassDB::bind_method(D_METHOD("stop"), &Timer::stop);

    ClassDB::bind_method(D_METHOD("set_paused", "paused"), &Timer::set_paused);
    ClassDB::bind_method(D_METHOD("is_paused"), &Timer::is_paused);

    ClassDB::bind_method(D_METHOD("is_stopped"), &Timer::is_stopped);

    ClassDB::bind_method(D_METHOD("get_time_left"), &Timer::get_time_left);

    ClassDB::bind_method(D_METHOD("set_timer_process_callback", "callback"), &Timer::set_timer_process_callback);
    ClassDB::bind_method(D_METHOD("get_timer_process_callback"), &Timer::get_timer_process_callback);

    ADD_SIGNAL(MethodInfo("timeout"));

    ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_callback", "get_timer_process_callback");
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time", PROPERTY_HINT_RANGE, "0.001,4096,0.001,or_greater,exp"), "set_wait_time", "get_wait_time");
    ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot");
    ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart");
    ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paused", "is_paused");
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_left", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_time_left");

    BIND_ENUM_CONSTANT(TIMER_PROCESS_PHYSICS);
    BIND_ENUM_CONSTANT(TIMER_PROCESS_IDLE);
}
D_METHOD是一组函数,主要是MethodDefinition md对象
ClassDB::bind_method(D_METHOD("set_wait_time", "time_sec"), &Timer::set_wait_time);这样做的目的后就可以这样调用
pobj->call("set_wait_time", 344.3);
真正执行的,是这样的
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);

    if (method) {
        ret = method->call(this, p_args, p_argcount, r_error);
    } else {
        r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
    }

ADD_SIGNAL(MethodInfo("timeout")); 本类中增加一个信号
执行这个信号:emit_signal(SNAME("timeout"));
这样做相当Timer类提供一个timeout的抽像反接口,使用者只需要这样做
timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout));
就可以收到Timer的timeout事件消息,通过信号的方式可以解耦,就类与类之间的通信方式之一。
这里说明:接口一般是被调用的,是一种被动的;反接口可以通知消息一种,是主动的消息,如果Timer内部自己调用信号
信号定义与执行在同一个类中?

ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_timer_process_callback", "get_timer_process_callback");
这个控件的属性信息,可以通过面板来设置,或绑定
注意,函数一定要在前面通过ClassDB::bind_method绑定,不然没有效果
后面调用可以是这样:
StringName strName("autostart");
pobj->set(strName, Variant(1));
Variant value = pobj->get(strName);

BIND_ENUM_CONSTANT(TIMER_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(TIMER_PROCESS_IDLE);
常量与字符串的对应关系

8,增加脚本数据类型
参考ClassDB::bind_method(D_METHOD("get_ids"), &RDUniform::get_ids);

static const _bit _type_list[]

void register_variant_methods() 

method_ptrcall.h这个文件看看
是Object只需要registryclass
如果是自定义类型就要在这里加

9,消息循环
函数GetMessage不一样的是,GetMessage:从系统获取消息,将消息从系统中移除,属于阻塞函数。当系统无消息时,GetMessage会等待下一条消息。
函数PeekMesssge是以查看的方式从系统中获取消息,可以不将消息从系统中移除,是非阻塞函数;当系统无消息时,返回FALSE,继续执行后续代码。
常见消息循环
// 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
godot的消息循环
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
窗口函数
LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
如处理WM_CHAR,会记录下来
key_event_buffer[key_event_pos++] = ke;
在函数DisplayServerWindows::_process_key_events() 处理
生成InputEventKey对象,交给Input::get_singleton()->parse_input_event(k);
真正工作函数:
Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated)
交给
if (event_dispatch_function) {
        event_dispatch_function(p_event);
    }
实际上:
DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
然后给:
void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error)


Viewport::_gui_input_event(Ref<InputEvent> p_event)
if (mb->is_pressed(){
找到控件
gui.mouse_focus = gui_find_control(pos);
}else
{
   //按下鼠标松开的时候,触发 事件,
}
鼠标事件;
Input::get_singleton()->parse_input_event(mb);

bool Main::iteration()函数

11,配置定义
ProjectSettings : public Object

globals = memnew(ProjectSettings);
ProjectSettings::ProjectSettings() {
    singleton = this;
}
static ProjectSettings *get_singleton();
这种方式访问

Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed


12,第三方库说明:
BulletPhysics是一个跨平台的开源物理引擎,也是三大主流3D物理引擎之一,支持三维碰撞检测、柔体动力学和刚体动力学,多用于游戏开发和电影制作中。
embree光线追踪
enet网络库
etc2comp 图像压缩工具
freetype可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,
glad
jpeg-compressor 图像压缩和转换为JPEG格式
libogg 是一个 C++ 库,用来处理 Ogg 多流传输格式。它被设计为独立的解码器,是一个线程安全的解码器。
libpng
libOpus是一款完全开放、免版税、功能多样的音频编解码器
zstd是Facebook在2016年开源的新无损压缩算法,优点是压缩率和压缩/解压缩性能都很突出。
Xattlas是一个小型C++11库,没有外部依赖项,可以生成适合烘焙光照贴图或纹理绘制的唯一纹理坐标。
Wslay 是一个用 C 语言实现的 WebSocket 开发库。
vhacd 将 3D 曲面分解为一组"靠近"凸部件
tinyexr, 小型OpenEXR图像加载程序/保护程序库 小型OpenEXR图像库。 tinyexr 是只加载和保存 OpenEXR(.exr) 映像的小型头文件库

RecastNavigation是一款非常强大的寻路系统,被广泛的应用于各大游戏引擎中

pvrtccompressor 压缩器
PCRE(Perl Compatible Regular Expressions)是一个Perl库,使用boost::regex编译时需要3秒,而使用pcre不到1秒,PCRE是用C语言实现的,其C++实现版本是PCRE++

  godot开发 QQ 35484348

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值