godot icon indicating copy to clipboard operation
godot copied to clipboard

Improve GDExtension Tools Integration with Editor Debug Tooling

Open Naros opened this issue 1 year ago • 13 comments

This PR aims to address several issues around GDExtension and Debug Tooling within the Editor.

  • Bugsquad edit, closes: https://github.com/godotengine/godot-proposals/issues/8777

Naros avatar Jan 02 '24 19:01 Naros

Please open a proposal to track this and discuss the specifics of this feature

AThousandShips avatar Jan 02 '24 19:01 AThousandShips

@AThousandShips done - https://github.com/godotengine/godot-proposals/issues/8777 Will take a look at the formatting issues now.

Naros avatar Jan 02 '24 19:01 Naros

Hi, would someone me able to tell me whether the failure is related to my change or something that pre-exists in main?

Naros avatar Jan 03 '24 10:01 Naros

Thanks!

At a high-level, I think this is a great addition, since it's making something that's possible via Godot modules also be possible via GDExtension (and addons).

I'm not really familiar with the debugger API, but for the most part, the code here looks like a thin layer over ScriptDebugger from core/debugger/script_debugger.h, which seems good to me. But it should probably be reviewed by someone more familiar with this API (@Faless?) to see if the API that's being exposed really makes sense.

dsnopek avatar Jan 03 '24 14:01 dsnopek

I'd also add that if there are other bits from SccriptDebugger that make sense to include, let me know. I basically grabbed just what I needed for the short-term but perhaps there are others that may warrant inclusion.

Naros avatar Jan 03 '24 15:01 Naros

Could you squash the commits? See PR workflow for instructions.

akien-mga avatar Apr 19 '24 08:04 akien-mga

@Faless:

Do we really want to expose ScriptDebugger as a separate class?

I feel that class exists in core mostly for historical reasons.

Does it make sense to move the exposed functions directly to EngineDebugger?

Unfortunately, you may be the person most qualified to answer the questions you pose. :-)

dsnopek avatar Apr 19 '24 15:04 dsnopek

Do we really want to expose ScriptDebugger as a separate class?

I feel that class exists in core mostly for historical reasons.

Does it make sense to move the exposed functions directly to EngineDebugger?

I have to agree with David, really entirely your call, I can certainly align those there if you'd prefer.

Naros avatar Apr 19 '24 16:04 Naros

Unfortunately, you may be the person most qualified to answer the questions you pose. :-)

I have to agree with David, really entirely your call, I can certainly align those there if you'd prefer.

Given there doesn't seem to be any objection, I will say let's do that.

It's already confusing enough to have EngineDebugger and EditorDebugger, adding a ScriptDebugger will make it even worse.

I already had plans to move more of the debugger default features to the plugin interface (while still shipping them as part of Godot), so I will take a chance there to see if we can get rid of the whole ScriptDebugger concept internally too.

Faless avatar Apr 19 '24 17:04 Faless

Sounds good, then I'll amend the PR over the weekend and ping you when its ready for a review from your side on the particulars to make sure that the direction and goals are aligned to what you have in mind 👍 @Faless

Naros avatar Apr 19 '24 17:04 Naros

Hi @Faless, I have a few questions about this work.

I was reviewing and testing my changes in a local build to make sure I hadn't missed any additions needed for this to work well for our script language plug-in, and I came across a hack I had used to integrate with the goto_script_line signal.

TypedArray<Node> nodes = editor_node->find_children("*", "EditorDebuggerNode", true, false);
if (nodes.size() == 1) {
  // Wire this signal so when user selects a frame we can handle that here.
  Node* editor_debugger_node = Object::cast_to<Node>(nodes[0]);
  editor_debugger_node->connect("goto_script_line", callable_mp(this, &OrchestratorScriptView::_goto_script_line));
}

The ScriptEditor hooks into this directly into the engine to advance the text editor position in the script view to the correct line based on the chosen breakpoint; however, as our plug-in isn't based on the ScriptEditor classes, we cannot take advantage of that callback. I want to find a reasonable way to expose this signal.

What I was considering was adding a new method on EditorDebuggerPlugin, i.e.:

void goto_script_line(const Ref<Script>& p_script, int p_line);

Then, inside EditorDebuggerNode::_error_selected and _text_editor_stack_goto where, we emit the goto_script_line signal that we iterate the registered debugger plugins and dispatch to this new method, allowing the plug-in an opportunity to react. There may be other alternatives for this, but it seemed like the most likely candidate.

~~The last task I have open is to check how GDScript integrates with the Breakpoints bottom panel. I want my script tooling to add the breakpoints to that panel, much like how the gutter breakpoints work in GDScript. If you have any pointers, I'd be grateful for the advice. I should have that worked out tomorrow with any last questions before this is ready.~~

So it seems EditorDebuggerSession::set_breakpoint is what I want to add/remove breakpoints. I have a question about usage. Is it safe then for my EditorDebuggerPlugin to cache the EditorDebuggerSession or its ID (as I think there should only be one active), and then from my code, I can call into the debugger plugin, use the session ID to set/unset the breakpoint then, right? I tested this and it seems to work, but just unsure about there being only one session.

In addition, I also need a way to react to breakpoint_set_in_tree and breakpoints_cleared_in_tree, which are signals that are also emitted by the EditorDebuggerNode, when the user uses the context-menu on the breakpoints in the panel. Again, delegate these to the Plugin or should we consider a different way?

Naros avatar Apr 23 '24 01:04 Naros

The build failures seem to be unrelated as master seems to be unstable atm.

Naros avatar Apr 25 '24 03:04 Naros

This should be fixed after rebasing.

akien-mga avatar Apr 25 '24 10:04 akien-mga

@akien-mga @Faless is it possible to still get this into 4.3? It would be super helpful for us to have debugger support in the editor and this is a blocker for that.

Naros avatar May 03 '24 22:05 Naros

It's marked for 4.3 so unless that is changed it's still planned for 4.3, wait and see

AThousandShips avatar May 04 '24 08:05 AThousandShips

Is it safe then for my EditorDebuggerPlugin to cache the EditorDebuggerSession or its ID (as I think there should only be one active),

The ID is a bit of an implementation detail, but it's indeed the "tab number". In general, it should be fine caching between then signals EditorDebuggerSession.started and EditorDebuggerSession.stopped.

I also need a way to react to breakpoint_set_in_tree and breakpoints_cleared_in_tree, which are signals that are also emitted by the EditorDebuggerNode, when the user uses the context-menu on the breakpoints in the panel. Again, delegate these to the Plugin or should we consider a different way?

I think indeed those signals could be exposed via the EditorDebuggerPlugin given they are "global" (i.e. are relevant to all sessions).

Maybe goto_script_line could also be exposed this way?

Faless avatar Jun 10 '24 10:06 Faless

Thanks for the feedback @Faless, I've addressed your recommendations with the documentation and I've added the 3 methods as virtual methods on the EditorDebuggerPlugin interface. Assuming the build succeeds, let me know if there is anything else you would like to see for this.

Naros avatar Jun 10 '24 23:06 Naros

Thanks!

akien-mga avatar Jun 11 '24 08:06 akien-mga

I've added the 3 methods as virtual methods on the EditorDebuggerPlugin interface.

Oh no... as I mentioned in my comment, those should probably have been signals not virtual methods :(

Faless avatar Jun 11 '24 18:06 Faless

I've added the 3 methods as virtual methods on the EditorDebuggerPlugin interface.

Oh no... as I mentioned in my comment, those should probably have been signals not virtual methods :(

No worries, I can send another PR to follow-up on this if that's acceptable @Faless @akien-mga, just lmk.

Naros avatar Jun 11 '24 18:06 Naros

@Naros I'll let you know in case, it's not the end of the world indeed, just a bit weird, we usually prefer virtual methods for things that needs overriding and either are frequently called (they're faster than signals), or when we need to receive a return (which is not the case for those function).

At the same time, the plugin aims to be "self-contained", so the virtual method can make sense, and might not be worth changing.

Sorry for the noise, I think in the end we'll leave it as it is now :sweat_smile:

Faless avatar Jun 11 '24 18:06 Faless