godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

Add header builders script for `env.GLSL_HEADER` and SVG icons

Open aaronfranke opened this issue 5 months ago • 0 comments

Sometimes it is desired to have non-C++ files compiled into C++ code and available for use there. For example, you may want GLSL files available as Strings to be used at runtime. For example, you may want SVG files available as Strings to allow generating multiple sizes at runtime (important for the editor to be able to display things at any scale).

Each of these functionalities is already available when using a Godot engine module:

  • For GLSL, you can use Godot's provided glsl_builders.py to generate these. This is exposed with env.GLSL_HEADER, meaning you call into it in a SConscript or SCsub like env.GLSL_HEADER("path/to/some_file.glsl") and it will generate a file some_file.glsl.gen.h with inline constexpr const char *some_file_shader_glsl = ... in it.
    • With GDExtension, without this PR, this has to be done manually.
  • For SVG icons, Godot has two duplicated functions to generate editor icons and default theme icons. Icon generation happens "automatically", so modules do not need to call into it.
    • With GDExtension, the [icons] in the .gdextension file provides icons for classes. This fulfills the most common use case, however...
    • ...sometimes you need an icon that isn't tied to a class. Such icons are automatically available in modules.
      • With GDExtension, without this PR, this has to be done manually.

This PR adds a new file to the tools folder called header_builders.py which mimics the basic functionality of Godot's functions for GLSL header builders and SVG icon header builders. The GLSL header is used exactly like it is in the engine, with env.GLSL_HEADER("path/to/some_file.glsl"). This is registered in godotcpp.py with "GLSL_HEADER": Builder(.

As for the SVG icon builders, the engine does not provide an API for modules because it's supposed to be handled automatically, and so the function isn't needed in modules. Therefore, if the user needs non-class resizable SVG icons at runtime, calling into this function can be left as a godot-cpp-specific part of a user's buildsystem code, like this:

import header_builders
target_file_path = "../../editor/icons/editor_4d_icons.gen.h"
icon_sources = Glob("icons/4D.svg") + Glob("icons/Node4D.svg")
header_builders.make_svg_icons_action([target_file_path], icon_sources, env)

Note that the code in this PR cannot simply be an exact copy of the engine functions. Those functions have many dependencies on other functions which are not necessary in GDExtension, such as the code to generate the copyright headers. The code in this PR is a lot simpler. Also, the code in this PR is much more generalized. The GLSL code in Godot is hard-coded for GLSL, but the function in this PR can be used for non-GLSL as well. As for the SVG icons, the code in the engine is duplicated for editor icons and default theme icons, and each is hard-coded for each of those, while the code in this PR will work with any destination file.

The motivation behind this PR is the needs of the Godot 4D module/extension, but this benefits all extensions.

aaronfranke avatar Jun 07 '25 04:06 aaronfranke