Skip to content

Commit

Permalink
updated readme
Browse files Browse the repository at this point in the history
added disabling of rendering bindings in the release build using conditional compilation. You can keep rendering calls working by using the `FORCED_DD3D` definition.
  • Loading branch information
DmitriySalnikov committed Sep 13, 2023
1 parent 60fad14 commit f104c2b
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 81 deletions.
103 changes: 40 additions & 63 deletions addons/debug_draw_3d/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Debug drawing utility for Godot

This is an add-on for debug drawing in 3D and for some 2D overlays, which is written in `C++` and can be used with `GDScript`<!-- or `C#`-->.
This is an add-on for debug drawing in 3D and for some 2D overlays, which is written in `C++` and can be used with `GDScript` or `C#`.

Based on my previous addon, which was developed only for C# https://github.com/DmitriySalnikov/godot_debug_draw_cs, and which was inspired by Zylann's GDScript addon https://github.com/Zylann/godot_debug_draw

Expand All @@ -20,7 +20,7 @@ Your support adds motivation to develop my public projects.

## Features

3D Primitives:
3D:

* Arrow
* Billboard opaque square
Expand All @@ -36,6 +36,10 @@ Your support adds motivation to develop my public projects.
* Position 3D (3 crossing axes)
* Sphere

2D:

* **[Work in progress]**

Overlay:

* Text (with grouping and coloring)
Expand All @@ -55,13 +59,15 @@ To download, use the [Godot Asset Library](https://godotengine.org/asset-library

## Usage

1. Copy `addons/debug_draw_3d` to your `addons` folder, create it if the folder doesn't exist
1. Restart the editor
<!--
1. Rebuild the project if you use C#
1. Add `addons/debug_draw_3d/debug_draw.gd` or/and `addons/debug_draw_3d/DebugDrawCS.cs` to your project as autoload singleton
2. (Optionally) Enable the `Debug Draw 3D for Editor` plugin to enable debug drawing support inside the editor
-->
* Close editor
* Copy `addons/debug_draw_3d` to your `addons` folder, create it if the folder doesn't exist
* Launch editor

### C\#

When you start the engine for the first time, bindings for `C#` will be generated automatically. If this does not happen, you can manually generate them through the `Project - Tools - Debug Draw` menu.

![project_tools_menu](/images/project_tools_menu.png)

## Examples

Expand All @@ -76,30 +82,30 @@ func _process(delta: float) -> void:
var line_begin = Vector3(-1, sin(_time * 4), 0)
var line_end = Vector3(1, cos(_time * 4), 0)
DebugDraw.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0))
DebugDraw.draw_line(line_begin, line_end, Color(1, 1, 0))
DebugDraw.set_text("Time", _time)
DebugDraw.set_text("Frames drawn", Engine.get_frames_drawn())
DebugDraw.set_text("FPS", Engine.get_frames_per_second())
DebugDraw.set_text("delta", delta)
DebugDraw3D.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0))
DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0))
DebugDraw2D.set_text("Time", _time)
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
DebugDraw2D.set_text("delta", delta)
```

<!-- ```csharp
```csharp
public override void _Process(float delta)
{
var _time = OS.GetTicksMsec() / 1000f;
var box_pos = new Vector3(0, Mathf.Sin(_time * 4), 0);
var line_begin = new Vector3(-1, Mathf.Sin(_time * 4), 0);
var line_end = new Vector3(1, Mathf.Cos(_time * 4), 0);
DebugDrawCS.DrawBox(box_pos, new Vector3(1, 2, 1), new Color(0, 1, 0));
DebugDrawCS.DrawLine(line_begin, line_end, new Color(1, 1, 0));
DebugDrawCS.SetText("Time", _time);
DebugDrawCS.SetText("Frames drawn", Engine.GetFramesDrawn());
DebugDrawCS.SetText("FPS", Engine.GetFramesPerSecond());
DebugDrawCS.SetText("delta", delta);
var _time = Time.GetTicksMsec() / 1000.0f;
var box_pos = new Vector3(0, Mathf.Sin(_time * 4f), 0);
var line_begin = new Vector3(-1, Mathf.Sin(_time * 4f), 0);
var line_end = new Vector3(1, Mathf.Cos(_time * 4f), 0);

DebugDraw3D.DrawBox(box_pos, new Vector3(1, 2, 1), new Color(0, 1, 0));
DebugDraw3D.DrawLine(line_begin, line_end, new Color(1, 1, 0));
DebugDraw2D.SetText("Time", _time);
DebugDraw2D.SetText("Frames drawn", Engine.GetFramesDrawn());
DebugDraw2D.SetText("FPS", Engine.GetFramesPerSecond());
DebugDraw2D.SetText("delta", delta);
}
``` -->
```

![screenshot_1](/images/screenshot_1.png)

Expand All @@ -108,11 +114,14 @@ public override void _Process(float delta)
A list of all functions is available in the documentation inside the editor.
![screenshot_4](/images/screenshot_4.png)

Besides `DebugDraw`, you can also use `Dbg3`.
Besides `DebugDraw2D/3D`, you can also use `Dbg2/3`.

```gdscript
DebugDraw.draw_box_xf(Transform3D(), Color.GREEN)
DebugDraw3D.draw_box_xf(Transform3D(), Color.GREEN)
Dbg3.draw_box_xf(Transform3D(), Color.GREEN)
DebugDraw2D.set_text("delta", delta)
Dbg2.set_text("delta", delta)
```

But unfortunately at the moment `GDExtension` does not support adding documentation.
Expand All @@ -123,50 +132,18 @@ Most likely, when exporting a release version of a game, you don't want to expor

![export_features](/images/export_features.png)

<!-- ### For GDScript
I made a dummy wrapper to remove unnecessary checks and calls in GDScript after exporting the release version of the game. It contains only definitions of functions and parameters, but does not execute any code.
To use it, you need to replace the original autoload with the dummy version (`res://addons/debug_draw_3d/debug_draw_dummy.gd`) before exporting.
*note:* I previously suggested overriding autoloads via project settings, but this approach did not work correctly and was removed in godot 3.5. -->

<!-- ### For C\#
Just switch to the `release` build and all calls to this library will be removed. -->

<!-- ### For Native Libraries
In order to not export native libraries in the release build, you need to specify an exclusion filter.
To do this, select the profile in the `Export` menu, go to the `Resources` tab and add this line `addons/debug_draw_3d/libs/*` to the `Filters to exclude...`. If necessary, separate the previous values with a comma.
![export filter](/images/export_filter.png)
There are also additional parameters in the project settings to disable debug rendering in certain conditions.
![proj settings](/images/additional_proj_settings.png) -->

<!-- ### Remark
It will not be possible to completely get rid of this library in the release build in this way. Since empty functions can still be called, which can slow down code execution very slightly. To avoid this, you need to get rid of the calls of these functions in your code.
In `GDScript`, for example, you can use `if`'s before calling debugging functions so that they are not called in the release build. And in `C#`, conditional compilation (`#if DEBUG`) can be used so that calls to debugging functions occur only in the debug assembly. -->

## Known issues and limitations

Enabling occlusion culing can lower fps instead of increasing it. At the moment I do not know how to speed up the calculation of the visibility of objects.

The text in the keys and values of a text group cannot contain multi-line strings.

The entire text overlay can only be placed in one corner, unlike DataGraphs.
The entire text overlay can only be placed in one corner, unlike `DataGraphs`.

[Frustum of Camera3D does not take into account the window size from ProjectSettings](https://github.com/godotengine/godot/issues/70362).

**The version for Godot 4.0 requires explicitly specifying the exact data types, otherwise errors may occur.**

**The C# binding is not ready yet.**

## More screenshots

`DebugDrawDemoScene.tscn` in editor
Expand Down
Binary file removed images/additional_proj_settings.png
Binary file not shown.
Binary file modified images/export_features.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed images/export_filter.png
Binary file not shown.
Binary file added images/project_tools_menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/screenshot_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/screenshot_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/screenshot_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/3d/debug_draw_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,9 @@ void DebugDraw3D::draw_ray(const Vector3 &origin, const Vector3 &direction, cons
void DebugDraw3D::draw_line_path(const PackedVector3Array &path, const Color &color, const real_t &duration) {
CHECK_BEFORE_CALL();
if (path.size() < 2) {
PRINT_ERROR("Line path must contains at least 2 points. " + String::num_int64(path.size()) + " is not enough.");
if (path.size() == 1) {
PRINT_ERROR("Line path must contains at least 2 points.");
}
return;
}

Expand Down
75 changes: 60 additions & 15 deletions src/editor/generate_csharp_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,33 @@ GODOT_WARNING_RESTORE()

// add auto-braces
#define TAB() auto tab_##__LINE__ = tab()
#define IFDEF(cond) auto ifdef_##__LINE__ = ifdef(cond)
#define DD3D_ENABLED_STR "DEBUG || FORCED_DD3D"
#define IFDEF_DD3D_ENABLED() auto ifdef_##__LINE__ = ifdef(DD3D_ENABLED_STR)
#define IFELSE() line("#else", 0)

GenerateCSharpBindingsPlugin::IndentGuard::IndentGuard(GenerateCSharpBindingsPlugin *_owner) {
owner = _owner;
owner->line("{");
owner->indent += " ";
owner->indent += owner->indent_template;
}

GenerateCSharpBindingsPlugin::IndentGuard::~IndentGuard() {
owner->indent = owner->indent.substr(0, owner->indent.length() - 4);
owner->line("}");
if (owner) {
owner->indent = owner->indent.substr(0, owner->indent.length() - owner->indent_template.length());
owner->line("}");
}
}

GenerateCSharpBindingsPlugin::IfDefGuard::IfDefGuard(GenerateCSharpBindingsPlugin *_owner, const String &ifdef_condition) {
owner = _owner;
owner->line(FMT_STR("#if {0}", ifdef_condition), 0);
}

GenerateCSharpBindingsPlugin::IfDefGuard::~IfDefGuard() {
if (owner) {
owner->line("#endif", 0);
}
}

bool GenerateCSharpBindingsPlugin::is_need_to_update() {
Expand Down Expand Up @@ -86,7 +103,6 @@ void GenerateCSharpBindingsPlugin::generate() {

line("using Godot;");
line("using System;");
line("using System.Collections.Generic;");

is_shift_pressed = true;

Expand Down Expand Up @@ -296,16 +312,19 @@ void GenerateCSharpBindingsPlugin::generate_wrapper(const StringName &cls, bool
line("Instance = _instance;");
}

line();
line("public void Dispose()");
{
TAB();
line("Instance.Dispose();");
line("Instance = null;");
}
} else {
line();
line(FMT_STR("public {0}(GodotObject _instance) : base (_instance) {}", cls));
}

line();
line(FMT_STR("public {0}() : this((GodotObject)ClassDB.Instantiate(\"{0}\")) { }", cls));
}
line();
Expand Down Expand Up @@ -401,17 +420,34 @@ void GenerateCSharpBindingsPlugin::generate_method(const StringName &cls, const
call_args = ", " + call_args;
}

if (!return_data.is_void) {
String int_convert = return_data.is_enum ? "(long)" : "";
{
auto method_body = [&]() {
if (!return_data.is_void) {
String int_convert = return_data.is_enum ? "(long)" : "";

if (is_need_wrapper) {
line(FMT_STR("return ({0})_DebugDrawUtils_.CreateWrapperFromObject((GodotObject)Instance?.Call(__{1}{2}));", return_data.type_name, name, call_args));
} else {
line(FMT_STR("return ({0})({1}Instance?.Call(__{2}{3}));", return_data.type_name, int_convert, name, call_args));
}
} else {
line(FMT_STR("Instance?.Call(__{0}{1});", name, call_args));
}
};

// TODO replace by factory
if (is_need_wrapper) {
line(FMT_STR("return ({0})_DebugDrawUtils_.CreateWrapperFromObject((GodotObject)Instance?.Call(__{1}{2}));", return_data.type_name, name, call_args));
if (is_property) {
method_body();
} else {
line(FMT_STR("return ({0})({1}Instance?.Call(__{2}{3}));", return_data.type_name, int_convert, name, call_args));
IFDEF_DD3D_ENABLED();

method_body();
if (!return_data.is_void) {
IFELSE();
line("return default;");
} else {
// Nothing to do
}
}
} else {
line(FMT_STR("Instance?.Call(__{0}{1});", name, call_args));
}
}
line();
Expand Down Expand Up @@ -781,8 +817,12 @@ String GenerateCSharpBindingsPlugin::arguments_string_call(const TypedArray<Dict
return String(", ").join(arg_strs);
}

void GenerateCSharpBindingsPlugin::line(const String &str) {
opened_file->store_string(indent);
void GenerateCSharpBindingsPlugin::line(const String &str, int indent_override) {
if (indent_override < 0) {
opened_file->store_string(indent);
} else {
opened_file->store_string(indent_template.repeat(indent_override));
}
opened_file->store_string(str);
opened_file->store_8('\n');
}
Expand Down Expand Up @@ -813,5 +853,10 @@ GenerateCSharpBindingsPlugin::IndentGuard GenerateCSharpBindingsPlugin::tab() {
return IndentGuard(this);
}

GenerateCSharpBindingsPlugin::IfDefGuard GenerateCSharpBindingsPlugin::ifdef(const String &ifdef_cond) {
return IfDefGuard(this, ifdef_cond);
}

#undef TAB
#endif
#undef IFDEF
#endif
17 changes: 15 additions & 2 deletions src/editor/generate_csharp_bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@ using namespace godot;

class GenerateCSharpBindingsPlugin {
class IndentGuard {
GenerateCSharpBindingsPlugin *owner;
GenerateCSharpBindingsPlugin *owner = nullptr;

public:
IndentGuard(){};
IndentGuard(GenerateCSharpBindingsPlugin *_owner);
~IndentGuard();
};

class IfDefGuard {
GenerateCSharpBindingsPlugin *owner = nullptr;

public:
IfDefGuard(){};
IfDefGuard(GenerateCSharpBindingsPlugin *_owner, const String &ifdef_condition);

~IfDefGuard();
};

struct PropertyMethods {
String type_name;
String set;
Expand Down Expand Up @@ -82,6 +93,7 @@ class GenerateCSharpBindingsPlugin {

String output_directory = "res://addons/debug_draw_3d/csharp";
String api_file_name = "DebugDrawGeneratedAPI.cs";
String indent_template = " ";
String indent;
Ref<FileAccess> opened_file;
Ref<FileAccess> opened_log_file;
Expand Down Expand Up @@ -155,10 +167,11 @@ class GenerateCSharpBindingsPlugin {
DefaultData arguments_get_formatted_value(const ArgumentData &arg_data, const Variant &def_val);
String arguments_string_decl(const TypedArray<Dictionary> &args, bool with_defaults, std::vector<DefaultData> def_args_data = {});
String arguments_string_call(const TypedArray<Dictionary> &args, const std::vector<DefaultData> &def_remap);
void line(const String &str = "");
void line(const String &str = "", int indent_override = -1);
void log(const String &str = "", const int &indent = 0);
void log_warning(const String &str = "", const int &indent = 0);
IndentGuard tab();
IfDefGuard ifdef(const String &ifdef_cond);
};

#endif

0 comments on commit f104c2b

Please sign in to comment.