godotengine / godot-cpp

C++ bindings for the Godot script API
MIT License
1.75k stars 577 forks source link

EditorSyntaxHighlighter is missing `_create()` #1636

Open FractalDiane opened 2 weeks ago

FractalDiane commented 2 weeks ago

Godot version

4.3.stable

godot-cpp version

4.3.stable

System information

Windows 10

Issue description

Context I'm creating an editor plugin with GDExtension that involves working with .ink files, and I'm trying to create a syntax highlighter for it in pure C++. I'm creating and registering this highlighter class:

class InkSyntaxHighlighter : public EditorSyntaxHighlighter {
    GDCLASS(InkSyntaxHighlighter, EditorSyntaxHighlighter);

protected:
    static void _bind_methods();

public:
    virtual Dictionary _get_line_syntax_highlighting(std::int32_t line) const override;

    virtual String _get_name() const override { return "Ink"; }
    virtual PackedStringArray _get_supported_languages() const override { return PackedStringArray({"TextFile"}); }
};
// _enter_tree() in the EditorPlugin class

Ref<InkSyntaxHighlighter> hl = memnew(InkSyntaxHighlighter);
syntax_highlighter = hl;
ScriptEditor* script_editor = get_editor_interface()->get_script_editor();
script_editor->register_syntax_highlighter(syntax_highlighter);

However, I cannot get any part of the highlighter to actually work; it shows up as an option in the syntax highlighters list, but it just shows up as Unnamed and doesn't actually provide any highlighting. (I tried putting prints in all three functions and none of them are even called) image

What I think is the problem I looked into the Godot source code for EditorSyntaxHighlighter, and it has a method called _create which is called whenever a highlighter is instantiated. Normally, it instantiates a base EditorSyntaxHighlighter and just tries to give it whatever script the object has:

Ref<EditorSyntaxHighlighter> EditorSyntaxHighlighter::_create() const {
    Ref<EditorSyntaxHighlighter> syntax_highlighter;
    syntax_highlighter.instantiate();
    if (get_script_instance()) {
        syntax_highlighter->set_script(get_script_instance()->get_script());
    }
    return syntax_highlighter;
}

My class is a native derived class that has no script, so it seems like it's failing to find a script and just instantiating a default base EditorSyntaxHighlighter for me.

However, looking at the source code for the derived GDScriptSyntaxHighlighter class, this class overrides the _create function and just returns a ref to the derived class instead.

Ref<EditorSyntaxHighlighter> GDScriptSyntaxHighlighter::_create() const {
    Ref<GDScriptSyntaxHighlighter> syntax_highlighter;
    syntax_highlighter.instance();
    return syntax_highlighter;
}

This seems to be the solution to get a pure C++ EditorSyntaxHighlighter with no script to work; however, this _create() function is not accessible in GDExtension, so this seems to not currently be possible unless I'm missing another way of doing this.

Steps to reproduce

  1. Create a GDExtension project
  2. Create and register a class that derives from EditorSyntaxHighlighter and overrides the _get_name function
  3. Create and register an EditorPlugin class that registers this syntax highlighter
  4. Observe that the custom named defined in _get_name is not shown when selecting it in editor

Minimal reproduction project

N/A

dsnopek commented 2 weeks ago

Thanks!

This is really a Godot issue - once this is exposed there (or some other way to allow this is added), it should start working with godot-cpp.

I threw together PR https://github.com/godotengine/godot/pull/98929 which exposes the _create() virtual method. I haven't tested it, and since I don't really know this API, I'm not sure this is right approach, but hopefully this could help get things started :-)