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

Add a "debug" Label to display node properties in a running project #115

Open
Tracked by #7
golddotasksquestions opened this issue Sep 30, 2019 · 17 comments
Open
Tracked by #7

Comments

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 30, 2019

Describe the project you are working on:
2D action game, turn based card game.

Describe the problem or limitation you are having in your project:
Writing code in Godot is fast, but I actually spend the majority of my dev time debugging and making sure what I wrote actually works. Using print in all it's variants is great for the utmost basic things, but especially for any code running in _process() or _physics_process() printing to output is anything but optimal due to the nature of print:

  • It consumes a lot of performance in _process() or _physics_process() severely limiting the usefulness of "live" debugging with print
  • it's had to keep track of a larger number of different values that change each frame

Two alternatives:
Either print to file, has less performance issues, but requires to clutter your project with file code and is not suitable for live-debugging,
or create Label node and set_text to those values which will also require custom code that clutters your project and therefore scales really badly. Formatting this Label for comprehensive debugging takes even more time out of your valuable dev time.

Both alternative require a lot more effort than just writing print(myvalue) and therefore are a hindrance to immediate debugging.

Describe how this feature / enhancement will help you overcome this problem or limitation:
A Debug-Label node, that serves to print all values I pass as arguments would solve all these problems:

$DebugLabel.set_text(variable or property or signal, variable or property or signal, variable or property or signal, ...)

would automatically format the argument already like
argument1: value of argument1
argument2: value of argument2
argument3: value of argument3
...
Automatic text outline would guarantee legible text on all backgrounds. Arguments themselves would be displayed with 90% white and black outline, while the argument values have different colors according to what type the value is. Those colors depend on the users Godot editor theme so that they match the users script colors. For the default theme this would be strings are yellow, booleans are red, vectors or color is green, integers white.

It would provide immediate onscreen information, right at the location where I need it. It would have very little performance costs compared to print (presumably close to a simple Label) and provide all the Label Node comforts (scale, relative positioning, add it as child to the scene I want to debug, and therefore moving along relative with the parent scene)

In the roll down menu next to "Visual collision shapes" all types of debug Nodes like this DebugLable (another type could be DebugVector) could be made visible or hidden simultaneously.
Debug Nodes should always be automatically drawn on top of everything else.
The debug nodes are obviously not included in exports, or would have to be opted in to be included.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:
$DebugLabel.set_values(name, z_index, state, health, ready_to_jump, modulate, position) would result in:
debug_label
The DebugLabel boundary box is obviously just for the sake of this visualization.

Describe implementation detail for your proposal (in code), if possible:
I don't have the coding skills.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
It's a debugging improvement, so I can imagine it being used a lot.

Is there a reason why this should be core and not an add-on in the asset library?:
Because debugging is such an essential and big part of development time, efficient and easy use should not be an downloadable option, but already come with the engine on first installment.

@Jummit
Copy link

Jummit commented Sep 30, 2019

Another way of doing this could be a plugin that displays the log in the game, so you would still use simple print statements to debug, which is more convenient than $DebugLabel.text += "\nFoo Bar".

@willnationsdev
Copy link
Contributor

@Jummit I think that misses the point. The user's goal is specifically NOT to repeatedly see the same 7 parameters reprinted over and over to the console, flooding the console with information. His goal is instead to have a single place he can observe, in the world, that follows another object and which constantly displays live values for a subset of objects' data.

@golddotasksquestions
Copy link
Author

golddotasksquestions commented Sep 30, 2019

Another way of doing this could be a plugin that displays the log in the game

No, that would be something completely different as the print log can have all kinds of data.
As a plugin it would not part of the Godot vanilla. I would have needed this from the first time I started Godot.

@Jummit
Copy link

Jummit commented Sep 30, 2019

Both have their uses. My suggestion would be handy for single time events, and @golddotasksquestions one would be great for another way of observing variables other than the remote tree view (which is quite handy already tbh).

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 30, 2019

Just for some insight on how something like this might be implemented:

  1. Create a type that extends Label.
  2. Define a set of configurable Theme values used to color-code each Variant value type.
  3. Define a property that specifies the target object for it to render properties about. We'll call this the "target".
  4. Export a NodePath. When assigned a non-empty value, the NodePath populates the "target" property with a Node.
  5. Define a string enum PropertyInfo that, when exported, would generate a dropdown of the property names that have been defined for the target.
  6. Export an Array of the above PropertyInfos so that users can specify a subset of properties for which they would like to render values.
  7. During the draw notification of the DebugLabel, iterate over the target object's property list, filter it based on the exported subset of properties from the Array, switch on the Variant type of the PropertyInfo to determine the color to use from the Theme, and use font->draw_char(...) to render the value beside the name of the field.

^ Could even be prototyped in script code since, afaik, all of the requisite features can be done from script (unless something about the new Theme values can't be done from script? Don't know. Haven't messed with those much). It just wouldn't be terribly useful as a non-embedded part of the engine.

Edit: you could also simplify the design even further by making it a ReferenceRect instead with a child GridContainer (columns set to 2) and then just using Labels for all of the children, color-coding the text of the right-side labels. That would make it more responsive and evenly spaced.

@clayjohn
Copy link
Member

In this reddit thread a user was able to implement this feature in GDScript in under an hour.

I think we need a better reason for inclusion in core than "it would be useful". Especially for something that is so quick and easy to implement in GDScript. Keep in mind there needs to be a compelling reason why this should be in core and not be made into an addon. This feature could likely be made into a short script that could be found on the asset library (i'm guessing it would even be short enough to include in a tweet).

In my opinion, something like this is better suited to be part of the API proposed in #112

@willnationsdev
Copy link
Contributor

@clayjohn That's fair. Curious how, with #112, you would specify that debug text for properties should be rendered at a specific location and track. Suppose you'd have to write it in _process or something?

@golddotasksquestions
Copy link
Author

golddotasksquestions commented Sep 30, 2019

It's not fair at all. Only because clayohn or others can code themselves a tool within one hour to make all kinds of magic happen, does not mean everyone else who uses the engine can, nor does it mean that this is an approach that fosters faster developing, prototyping or debugging.

Addons means horrible discoverability, means unreliable documentation (because no integration in to official documentation), means not available for first time users, means everyone works with a different Godot (hard time to reproduce bugs, hard time to follow tutorials)
Why you want to cast features that are obviously wanted and would be incredible useful for everyone using Godot to an external plugin/addon is beyond me.
If you want to keep the codebase just the size it currently is, I would suggest to start kicking out features which are used less widely compared to the proposed features or are simply redundant, instead of arguing against the inclusion of features that are actually asked for and needed.

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 30, 2019

@golddotasksquestions

He wasn't saying we shouldn't have this feature. He is saying there is already another feature proposal that supersedes the currently proposed one, i.e. we could code a Debug Singleton of some sort that would wrap all of this functionality and more. He wasn't saying this wouldn't be useful. He was saying that there is already a broader and potentially more user-friendly platform by which this feature could be delivered to users.

Edit: If you wrapped the creation of this GUI element behind a Debug singleton, and you really wanted to create a node-based draggable CanvasItem to display the information, rather than a code-based singleton method call, then it would be trivial to write a Node2D script to do this once the Debug singleton is written. With the singleton approach, all of the logic for doing it is kept within a single class and could potentially have other debug utilities combined into the API as well. Maybe at that point, it would be a good idea to, for usability purposes, also add the trivial DebugLabel that simply calls into its API? That'd be for the core devs to decide. I think at that point though it would be worth the usability gains to throw it in there, assuming most of its implementation is kept in the Debug class itself.

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 30, 2019

I would imagine something akin to this:

extends Node
export(NodePath) var _path_target := @".."
func _ready() -> void:
    var target = get_node(_path_target)
    assert(target)
    # params: parent node, offset, object to target, properties on target to display
    var id = Debug.property_label_new(target, Vector2(20, 0), target, ["num", "text"])
    # ...
    Debug.property_label_set_visibility(id, false)
    Debug.property_label_free(id)

Of course, the more we find Debug to be useful, and the more complex the customization of its generated elements becomes, the more reason there would be to perhaps segregate the more complex elements from the Debug singleton and turn them into their own node. And if need be, we could still control its debug-related behavior with the Debug singleton, e.g. "toggle off all debug renderings."

@girng
Copy link

girng commented Oct 1, 2019

I don't have performance issues with print, and I'm running on an i7 2600, with a 144hz monitor. Sometimes printing stuff in _process. I also personally would not really use this because of visual clutter, as there is so much going on in my scenes already. However, I'm not saying it's a bad idea, just not for me.

The 7-step development process to create something like this (@willnationsdev's post above) is a testament at how powerful the current gdscript/node system is,

@nezvers
Copy link

nezvers commented Oct 1, 2019

@Jummit I think that misses the point. The user's goal is specifically NOT to repeatedly see the same 7 parameters reprinted over and over to the console, flooding the console with information. His goal is instead to have a single place he can observe, in the world, that follows another object and which constantly displays live values for a subset of objects' data.

Defold has nice debugging print - if it's printing the same value, then it doesn't write new line but instead indicates call count next to the line.

@Xrayez
Copy link
Contributor

Xrayez commented Oct 1, 2019

For a more complete solution, I think this could be done as part of GodotVisualDebugger (if not already).

Also see it being promoted at GodotCon: Visual Debugger for the Godot community. 😛

I think we need a better reason for inclusion in core than "it would be useful"

It can be kept outside core indeed, but people would not want to spend considerable amount of time to setup Godot to match their needs, this is where all the battle comes which would have to be resolved somehow in the future.

@golddotasksquestions
Copy link
Author

golddotasksquestions commented Oct 1, 2019

@Xrayez
I watched this GonCon talk in it's entirety already. I had no idea what to do with it afterwards or how to use it.
The point of this particular proposal right here is to discuss an integrated solution to display variables and properties of nodes within the project while it is running in a pre-formated way that is as straight forward and accessible and need as little explanation as print()

Plus, while learning to use Godot engine, users make a large number of small test projects. At least I do. Adding this massive singleton (and learning it's use and application) every time if all you want it to do is to display some variables, properties or vectors in game is total overkill, and going through that ordeal compared to a build-in one line solution is also a hindrance to fast testing and prototyping.

@Xrayez
Copy link
Contributor

Xrayez commented Oct 1, 2019

Yeah I think it's still work-in-progress and seems like the development has staled...

I'd support this being useful for debugging networking properties at runtime, because there's no way to debug stuff visually while running several instances of the game (windows) at localhost, so I have to basically rewrite a lot of built-in editor debugging functionality.

@Xrayez
Copy link
Contributor

Xrayez commented Dec 8, 2019

I've implemented the most general-purpose debug label node I could think of in godot-extended-libraries/godot-next#49. The color coding is not implemented yet, see implementation description and the test project.

Note that implementing this as a script is only a step forward, it doesn't mean that the issue can be closed, I do think this is essential debugging stuff, but indeed #112 may be a more general-purpose solution.

@ghost
Copy link

ghost commented Apr 17, 2020

I would think that a more robust solution that could be be more suitable as something built-in, would be a way to create an instance of the Inspector and attach it to any control node during a running game.

It's API would allow it to point it at any resource during runtime, and you could navigate it just as you do in the editor.

You could then write a small bit of wrapper to use it like any other widget. Instance it, put it in a popup, and have your script send it what to watch.

This though would be useful only in cases of running the application after it's built, as the live editing will suffice during development.

@Calinou Calinou changed the title Debug Label Add a "debug" Label to display node properties in a running project Nov 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants