Creating a Custom Module in Godot


While on vacation I have been looking at the process of extending the Godot Game engine using C++.  Due to the vacation, this isn’t a proper tutorial, I may do one later on when I have access to video, etc…  There is pretty solid documentation of the process in this post on the Godot wiki beyond that however there is a huge lack of information.  So the following is mostly trial and error.


I worked entirely in Visual Studio for this example and am working from the most recent source from Github.  If you have trouble working in Visual Studio with Godot, be sure to check out this post.


We are going to have to create several files in the modules folder, but don’t worry many can be copy/pasted from an existing module.  I created a new module called modTest inside the modules folder, and the contents end up looking like:




Many I coped directly from gridmap, but I will show the entire contents below.

def can_build(platform):    return True          def configure(env):    pass      



Import('env')    env.add_source_files(env.modules_sources,"*.cpp")    



void register_modtest_types();  void unregister_modtest_types();  



#include "register_types.h"  #include "object_type_db.h"  #include "modtest.h"  #include "modtest_editor.h"    #define TOOLS_ENABLED 1    void register_modtest_types() {    ObjectTypeDB::register_type<ModTest>();    #ifdef TOOLS_ENABLED    EditorPlugins::add_by_type<modtest_editor_plugin>();  #endif  }        void unregister_modtest_types() {      }  



#ifndef MODTEST_H  #define MODTEST_H    #include "scene/2d/node_2d.h"    class ModTest : public Node2D {    OBJ_TYPE(ModTest, Node2D);  };    #endif  



#include "modtest.h"  



#pragma once    #include "tools/editor/editor_plugin.h"  #include "tools/editor/editor_node.h"  #include "tools/editor/pane_drag.h"      class ModtestEditor : public VBoxContainer {    OBJ_TYPE(ModtestEditor, VBoxContainer);    public:    ModtestEditor(){}    ModtestEditor(EditorNode * p_editor);      private:    VBoxContainer * container;    Label* label;    EditorNode* _editor;  };          class modtest_editor_plugin : public EditorPlugin  {    OBJ_TYPE(modtest_editor_plugin, EditorPlugin);    public:    modtest_editor_plugin(EditorNode *p_editor);    ~modtest_editor_plugin();      virtual void make_visible(bool isVisible);    virtual void edit(Object *p_node);    virtual bool handles(Object *p_node) const;    private:    EditorNode * _editor;    ModtestEditor* modtestEditor;  };    



#include "modtest_editor.h"  #include "tools/editor/plugins/canvas_item_editor_plugin.h"  #include "tools/editor/editor_settings.h"    #include "scene/main/viewport.h"    #include <iostream>      ModtestEditor::ModtestEditor(EditorNode* p_editor){    std::cout << "New Modtest Editor" << std::endl;      this->set_size(Size2(600, 600));    label = new Label();    label->set_text("Hello World");    this->add_child(label);      //p_editor->add_child(this);    p_editor->get_scene_root()->add_child(this);    _editor = p_editor;        this->hide();  }      // **************************** PLUGIN BEGIN ********************************************    modtest_editor_plugin::modtest_editor_plugin(EditorNode * p_editor)  {    _editor = p_editor;    modtestEditor = memnew(ModtestEditor(_editor));        std::cout << "Editor" << std::endl;      }      modtest_editor_plugin::~modtest_editor_plugin()  {  }      void modtest_editor_plugin::make_visible(bool isVisible){    std::cout << "Make visible" << std::endl;    if (isVisible){      std::cout << "Showing" << std::endl;      modtestEditor->show();    }    else{      std::cout << "Hiding" << std::endl;      modtestEditor->hide();    }  }    void modtest_editor_plugin::edit(Object *p_object) {    std::cout << "Edit" << std::endl;  }    bool modtest_editor_plugin::handles(Object *p_object) const {      return p_object->is_type("ModTest");  }  

So that was a mountain of examples, but nothing particularly complicated.


The SCSub and files simply tell the Scons build system how to build your module, both of them can be copied in unchanged from the gridmap module.  It’s only if your module doesn’t build for every platform or you need to do something other than compile all the included cpp files that you need to alter either of these files.


Next up are the register_types cpp and h files, which registers your type with Godot.  ModTest is a simple Node2D extension type, it can be registered using ObjectTypeDB::register_type().  Additionally we have an editor we want to show when editing our new type, that is registered using EditorPlugins::add_by_type() .  The TOOLS_ENABLED means that you are building Godot with full tooling support, as opposed to building just a game (without the editor in the generated binary).


Our extension is completely pointless.  It’s inherited from Node2D and well, that’s about it.  Obviously you would add functionality as you go.  The simple fact it inherits from Node2D makes it available in Godot as a Node:



Next we register an editor and a plugin for our ModTest type.  The ModtestEditor class is going to be the editor displayed within Godot.  It’s a simple VBoxContainer.  In this case all we do is add a label with the text Hello World then add it to the editor using the passed in pointer to the EditorNode.  This is generally where the majority of logic will go.


Next up is the modtest_editor_plugin which inherits EditorPlugin.  This class is loaded with Godot by the call EditorPlugins::add_by_type<modtest_editor_plugin>().  The important call is modtest_editor_plugin::handles(), which attaches the editor to the type it edits.  In the constructor, we create an instance of our editor.  The make_visible() method is called each time the editor is needed, or no longer needed and toggles the visibility of our editor.


As you add or select a node of ModTest type, the editor will automatically be shown:



Obviously this is a barebones example.  As I implement a more detailed example I will share the results.

Programming CPP

Scroll to Top