GDExtension: how to make editor plugin.

Written

Godot's manual does not explain at all how to make an editor plugin to Godot's editor through GDExtension. The manual explains how to make a plugin through GDScript at the moment very well. The problem is that when doing a plugin this way, you have to add .cfg in INI format, which has metadata for the plugin. It is not clear how to make this INI file for the GDExtension. The thing is that you do not need it!

First, create a class that extends EditorPlugin class. You can implement metadata in this class by overriding some methods. For example, this class adds two inspector plugins for the bar counter and bar chair. We do not show the insides of these inspector plugins as they are not the point here.

#include<godot_cpp/classes/editor_plugin.hpp>
#include"PluginsModules.hpp"

using namespace godot;

/******************************************************************************
* Main editor plugin distributer. Less writing to have one let alone the      *
* memory cost.                                                                *
*                                                                             *
* Plugins have to be manually freed after use so pointers to plugins are      *
* stored.                                                                     *
******************************************************************************/
class GDExtEditorPlugin : public EditorPlugin{
	GDCLASS(GDExtEditorPlugin,EditorPlugin)

  // References to the plugins distributed by this EditorPlugins
	Ref<BarCounterInspectorPlugin> counter_inspector;
	Ref<BarChairInspectorPlugin> chair_inspector;

	public:
	/****************************************************************************
	* Required godot method registeration function.                             *
	****************************************************************************/
	static void _bind_methods();
	/****************************************************************************
	* Override to the get the plugin name metadata.                             *
	****************************************************************************/
	String _get_plugin_name() const;
	/****************************************************************************
	* Override to for Node::_enter_tree() to initialize plugins here.           *
	****************************************************************************/
	virtual void _enter_tree() override;
	/****************************************************************************
	* Override Node::_exit_tree() to deinitialize plugins here.                 *
	****************************************************************************/
	virtual void _exit_tree() override;
};
#include"GDExtEditorPlugin.hpp"

String GDExtEditorPlugin::_get_plugin_name() const{
	return String("Example plugin name");
}

void GDExtEditorPlugin::_bind_methods(){/* Since we only implemented virtuals we not need to add any methods. */}

void GDExtEditorPlugin::_enter_tree(){
  // Allocate the references before adding the plugin.
	this->counter_inspector=Ref(memnew(BarCounterInspectorPlugin));
	this->add_inspector_plugin(this->counter_inspector);
	this->chair_inspector=Ref(memnew(BarChairInspectorPlugin));
	this->add_inspector_plugin(this->chair_inspector);
}

void GDExtEditorPlugin::_exit_tree(){
  // Remove the plugins. Allocation in _enter_tree are not needed to be
  // deallocated since Ref class handles it when GDExtensionPlugin
  // deconstructor is called.
	this->remove_inspector_plugin(this->counter_inspector);
	this->remove_inspector_plugin(this->chair_inspector);
}

Then, in your initialize_module after you register the plugin class, call EditorPlugins::add_plugin_class. This registration has to be done when ModuleInitializationLevel. In the following example, STRINGIFY is a stringification preprocessing macro.

void initialize_module(ModuleInitializationLevel p_level){
	if (p_level==MODULE_INITIALIZATION_LEVEL_SCENE) {
		// Initialization normal nodes like bar counter and bar chair.
		ClassDB::register_class>BarCounter<();
		ClassDB::Register_class>BarChair<();
	}
	else if (p_level==MODULE_INITIALIZATION_LEVEL_EDITOR){
		ClassDB::register_class<BarCounterInspectorPlugin>();
		ClassDB::register_class<BarChairInspectorPlugin>();
		ClassDB::register_class<GDExtEditorPlugin>();
		EditorPlugins::add_plugin_class(STRINGIFY(GDExtEditorPlugin));
	}
}

I have not tested is EditorPlugins accessable from the Godot Script, but I assume so. Regardless, that is how EditorPlugin is added through GDExtension.