Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve GDExtension Tools Integration with Editor Debug Tooling #86721

Merged
merged 1 commit into from
Jun 11, 2024

Conversation

Naros
Copy link
Contributor

@Naros Naros commented Jan 2, 2024

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

@AThousandShips
Copy link
Member

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

@Naros
Copy link
Contributor Author

Naros commented Jan 2, 2024

@AThousandShips done - godotengine/godot-proposals#8777
Will take a look at the formatting issues now.

@Naros Naros force-pushed the gde-debugger-tooling branch 2 times, most recently from f38b954 to 64e145c Compare January 2, 2024 19:47
@Naros Naros requested a review from a team as a code owner January 2, 2024 21:57
@Naros Naros force-pushed the gde-debugger-tooling branch from 5f46704 to 39ea285 Compare January 2, 2024 22:01
doc/classes/ScriptDebugger.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Show resolved Hide resolved
doc/classes/EditorDebuggerSession.xml Show resolved Hide resolved
@Naros Naros force-pushed the gde-debugger-tooling branch 3 times, most recently from 2e04278 to 8ab643d Compare January 2, 2024 22:22
@Naros
Copy link
Contributor Author

Naros commented Jan 3, 2024

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

@dsnopek
Copy link
Contributor

dsnopek commented Jan 3, 2024

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 dsnopek requested a review from Faless January 3, 2024 14:59
@Naros
Copy link
Contributor Author

Naros commented Jan 3, 2024

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.

Copy link
Member

@vnen vnen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not the most familiar with the debugger code, but this is mostly exposing what's there for extensions. Overall it looks fine to me.

@akien-mga akien-mga modified the milestones: 4.x, 4.3 Apr 18, 2024
@akien-mga
Copy link
Member

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

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

E.g.:

core_bind::EngineDebugger::insert_breakpoint

@dsnopek
Copy link
Contributor

dsnopek commented Apr 19, 2024

@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. :-)

@Naros
Copy link
Contributor Author

Naros commented Apr 19, 2024

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 Naros force-pushed the gde-debugger-tooling branch 2 times, most recently from fa019bf to 1fb8987 Compare April 19, 2024 16:48
@Faless
Copy link
Collaborator

Faless commented Apr 19, 2024

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.

@Naros
Copy link
Contributor Author

Naros commented Apr 19, 2024

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
Copy link
Contributor Author

Naros commented Apr 23, 2024

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
Copy link
Contributor Author

Naros commented Apr 25, 2024

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

@akien-mga
Copy link
Member

This should be fixed after rebasing.

@Naros Naros force-pushed the gde-debugger-tooling branch from 40ea1b0 to d1a07cd Compare April 25, 2024 10:49
@Naros
Copy link
Contributor Author

Naros commented May 3, 2024

@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.

@AThousandShips
Copy link
Member

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

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic job! 🏆 , and sorry for the long delay between reviews.

I was worried of the potential misuse of set_lines/set_depth which can potentially break debugging but I couldn't figure out a better solution, and it's better to have this than not in 4.3.

So I've approved this, but also suggested marking those methods as experimental.

Thank you for your patience and the great work.

doc/classes/EditorDebuggerSession.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Outdated Show resolved Hide resolved
doc/classes/EngineDebugger.xml Outdated Show resolved Hide resolved
@Faless
Copy link
Collaborator

Faless commented Jun 10, 2024

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?

@Naros Naros force-pushed the gde-debugger-tooling branch from d1a07cd to 03bf63e Compare June 10, 2024 23:39
@Naros
Copy link
Contributor Author

Naros commented Jun 10, 2024

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 Naros force-pushed the gde-debugger-tooling branch from 03bf63e to 893a2b4 Compare June 10, 2024 23:45
@Naros Naros force-pushed the gde-debugger-tooling branch from 893a2b4 to 8577340 Compare June 10, 2024 23:46
@akien-mga akien-mga merged commit 4308129 into godotengine:master Jun 11, 2024
16 checks passed
@akien-mga
Copy link
Member

Thanks!

@Faless
Copy link
Collaborator

Faless commented Jun 11, 2024

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 :(

@Naros
Copy link
Contributor Author

Naros commented Jun 11, 2024

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.

@Faless
Copy link
Collaborator

Faless commented Jun 11, 2024

@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 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve GDExtension Tooling with Editor Debugger Tools
6 participants