1+ ** [ Documentation] ( https://github.com/IvanInventor/godot-cppscript/wiki ) | [ Usage example] ( #usage-example ) **
2+
13# godot-cpp-script
24
3- Python script that implements various C++ macros to automate binding code generation. Used as SCons custom builder besides default library builder . Works similar to [ Unreal Header Tool] ( https://docs.unrealengine.com/5.3/en-US/unreal-header-tool-for-unreal-engine/ ) .
5+ Python script that uses various C++ macros and templates to automate binding code generation and provide short and readable godot-cpp-specific compile error messages. With simple configuration, can attach to existing SCons/CMake build tool . Works similar to [ Unreal Header Tool] ( https://docs.unrealengine.com/5.3/en-US/unreal-header-tool-for-unreal-engine/ ) .
46
5- [ Example project] ( https://github.com/IvanInventor/godot-cppscript-example )
7+ [ Example project] ( https://github.com/IvanInventor/godot-cppscript-example )
68
79[ Keywords description] ( https://github.com/IvanInventor/godot-cppscript-example/blob/master/src/example.hpp ) (read comments)
810
@@ -13,64 +15,191 @@ Python script that implements various C++ macros to automate binding code genera
1315
1416[ Requirements] ( https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html#building-for-target-platforms ) from official guide for your OS
1517
16-
17-
1818#### Python dependencies
1919libclang
2020``` bash
2121pip install libclang
2222```
23- ## Installation
23+
24+ ## Installation as project submodule
2425
2526### Recommended project layout
2627```
27- / project directory
28- ├── project godot project root (res://)
29- ├── bin compiled binaries
30- ├── cppscript submodule
31- └── src C++ source files
28+ / project root
29+ ├── project godot project root (res://)
30+ ├── bin compiled binaries
31+ ├── external submodules
32+ │ ├── cppscript
33+ │ └── godot-cpp
34+ └── src C++ source files
3235 ```
33- ### As project submodule
3436
35- - From root of your project (git initialized)
37+ #
38+ ### Installation
39+
40+ #### From zero
41+ Install template from [ here] ( https://github.com/IvanInventor/godot-cppscript-template ) .
42+
43+ #### To existing project
44+ - From root of your project
3645``` bash
37- git submodule add https://github.com/IvanInventor/godot-cpp-script cppscript
38- git submodule update --recursive -- init cppscript
46+ git submodule add https://github.com/IvanInventor/godot-cppscript external/ cppscript
47+ git submodule update --init external/ cppscript
3948```
40- - Checkout your version of godot
41- - For stable releases: checkout one of [ tags] ( https://github.com/godotengine/godot-cpp/tags )
49+ - Copy and modify some files (library_name = 'scripts')
50+ - By script
51+ - With cmake
4252 ``` bash
43- cd cppscript/godot-cpp/
44- git checkout < tag>
53+ # Usage:
54+ # cmake -P external/cppscript/cppscript-configure.cmake <library_name> <src_dir> <project_dir>
55+ cmake -P external/cppscript/cppscript-configure.cmake scripts src/ project/
4556 ```
46- - For custom builds (from [guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/gdextension_cpp_example.html#building-the-c-bindings)):
57+ OR
58+ - With Python
4759 ` ` ` bash
48- # switch to branch corresponding to godot version
49- # Godot 4.1.3 -> 4.1
50- cd cppscript/godot-cpp/
51- git pull origin 4.1
52- git switch 4.1
53- # Generate custom bindings
54- ./your_godot_executable --dump-extension-api
55- mv extension_api.json gdextension/extension_api.json
60+ # Usage:
61+ # python3 external/cppscript/cppscript-configure.cmake <library_name> <src_dir> <project_dir>
62+ python3 external/cppscript/cppscript-configure.cmake scripts src/ project/
5663 ` ` `
64+ OR
65+ - By hand, replacing ` @LIBRARY_NAME@` in files with you library name
66+ - [templates/scripts.gdextension.in](/templates/scripts.gdextension.in) -> project/< library_name> .gdextension
67+ - [templates/register_types.cpp.in](/templates/register_types.cpp.in) -> src/register_types.cpp
68+ - [templates/register_types.h.in](/templates/register_types.h.in) -> src/register_types.h
69+
70+ - Create cppscript target in your build script
71+ - SCons
72+ ` ` ` python
73+ # import module
74+ import sys
75+ sys.path.append(' external/cppscript' )
76+ from cppscript import create_cppscript_target
77+ from cppscript import GlobRecursive # Optional
78+
79+ # ...
80+
81+ # Get list of headers (*.hpp only)
82+ scripts = GlobRecursive('src', '*.hpp')
83+
84+ # Create target, returns generated .cpp files list
85+ generated = create_cppscript_target(
86+ env, # SCons env, env.Clone() for different projects
87+ scripts, # Header files to parse
88+
89+ # CppScript config
90+ {
91+ # Name of header to be included to enable cppscript
92+ # (Prefer name unique to your project)
93+ 'header_name' : 'cppscript.h',
94+
95+ # Path to C++ header files
96+ 'header_dir' : 'src',
97+
98+ # Path to generated object files
99+ 'gen_dir' : ".gen",
100+
101+ # Generate bindings to public methods automatically
102+ # or require GMETHOD() before methods
103+ 'auto_methods' : True,
104+
105+ # Optional
106+
107+ ## C++ defines (TOOLS_ENABLED, DEBUG_METHODS etc.)
108+ ## Enable, if you conditionally enable classes/members
109+ ## based on definitions
110+ #'compile_defs' : env['CPPDEFINES'],
111+ #
112+ ## Include paths
113+ ## (Try to avoid godot-cpp headers paths,
114+ ## it slows parsing drastically)
115+ #'include_paths' : env['CPPPATH']
116+ }
117+ )
118+
119+ # Your project's target generation
120+ # You only need to modify it
121+ if env["platform"] == "macos":
122+ library = env.SharedLibrary(
123+ "bin/lib{}.{}.{}.framework/lib{}.{}.{}".format(
124+ library_name, env["platform"], env["target"], library_name, env["platform"], env["target"]
125+ ),
126+ # source=sources
127+ source=sources + generated, # Add generated source files to target
128+ )
129+ else:
130+ library = env.SharedLibrary(
131+ "bin/lib{}{}{}".format(library_name, env["suffix"], env["SHLIBSUFFIX"]),
132+ # source=sources
133+ source=sources + generated, # Add generated source files to target
134+ )
135+
136+ # Rebuild after headers change
137+ env.Depends(library[0].sources, generated)
138+ ` ` `
139+
140+ - Cmake
141+ ` ` ` cmake
142+ # Include module
143+ list(APPEND CMAKE_MODULE_PATH " ${CMAKE_CURRENT_SOURCE_DIR} /external/cppscript" )
144+ include(godot-cppscript)
145+
146+ # Get header files (.hpp only)
147+ file(GLOB_RECURSE CPPSCRIPT_HEADERS src/* .hpp)
148+
149+ # Call function to configure your target
150+ create_cppscript_target(
151+ # Name of your main target
152+ ${PROJECT_NAME}
153+
154+ # Header files to parse
155+ " ${CPPSCRIPT_HEADERS} "
156+
157+ # Name of header to be included to enable cppscript
158+ # (Prefer name unique to your project)
159+ cppscript.h
160+
161+ # FULL PATH to C++ header files
162+ ${CMAKE_CURRENT_SOURCE_DIR} /src
163+
164+ # FULL PATH to generated object files
165+ ${CMAKE_CURRENT_SOURCE_DIR} /.gen
166+
167+ # Generate bindings to public methods automatically
168+ # or require GMETHOD() before methods
169+ ON
170+
171+ # Optional
172+
173+ # C++ defines (TOOLS_ENABLED, DEBUG_METHODS etc.)
174+ # Enable, if you conditionally enable classes/members
175+ # based on definitions
176+ " " # $<TARGET_PROPERTY:godot-cpp,COMPILE_DEFINITIONS>
177+
178+ # Include paths
179+ # (Try to avoid godot-cpp headers paths,
180+ # it slows parsing drastically)
181+ " " # $<TARGET_PROPERTY:${PROJECT_NAME},INCLUDE_DIRECTORIES>
182+ )
183+
184+ ` ` `
185+
186+ # # Usage example
187+
188+ # ### Header syntax (read comments)
189+ ` ` ` cpp
190+ # include <godot_cpp/classes/control.hpp>
191+ # include <godot_cpp/classes/image.hpp>
192+ # include <godot_cpp/classes/input_event_key.hpp>
193+ # include <godot_cpp/classes/tile_map.hpp>
194+ # include <godot_cpp/classes/tile_set.hpp>
195+ # include <godot_cpp/classes/viewport.hpp>
57196
58- - Copy [scripts.gdextension](/scripts.gdextension) file to godot project (rename library name in file and filename if needed)
59- # # Build project
60- From cppscript/
61- ` ` ` bash
62- scons
63- ` ` `
64- or
65- ` ` ` bash
66- scons build_library=false
67- ` ` `
68- after building library for your target once (saves couple of seconds)
197+ // Include cppscript header (prefer custom name)
198+ # include <cppscript.h>
69199
70- # # All working features
71- # ### Example class in header (read comments)
72- ` ` ` cpp
73- class Example : public Control {
200+ using namespace godot;
201+
202+ class ExampleForRepo : public Control {
74203
75204 // Signals
76205 GSIGNAL(example_signal, float typed_arg, untyped_arg);
@@ -135,24 +264,24 @@ public:
135264 GIGNORE ();
136265 int ignore_method ();
137266
138- GIGNORE ();
267+ GIGNORE ();
139268 enum ignore_enum {
140269 ONE,
141270 TWO,
142- }
271+ } ;
143272
144- GIGNORE ();
273+ GIGNORE ();
145274 enum {
146- IGNORE_CONSTANT = 42,
147- }
275+ IGNORE_CONSTANT = 42,
276+ } ;
148277
149278 // Vararg method
150279 GVARARG(String named_arg, unnamed_arg);
151280 Variant varargs_func_example(const Variant ** args, GDExtensionInt arg_count, GDExtensionCallError & error);
152281
153282 // Default argument values
154283 int def_args(int p_a = 100, int p_b = 200);
155- int def_args_string(String s = String(" default" )); // Workaround for String
284+ int def_args_string(String s = String(" default" )); // Workaround for String
156285
157286 // RPC method
158287 GRPC(authority, reliable, call_local);
@@ -185,44 +314,47 @@ public:
185314 // basic class GCLASS(name, base_name)
186315 // virtual class GVIRTUAL_CLASS(name, base_name)
187316 // abstract class GABSTRACT_CLASS(name, base_name)
188- GCLASS(Example , Control);
317+ GCLASS(ExampleForRepo , Control);
189318};
319+
190320```
191321#### Generated code
192322```cpp
323+ /*-- GENERATED FILE - DO NOT EDIT --*/
324+
193325#include <cppscript_bindings.h>
194326
195- #include <exampleinrepo. hpp>
327+ #include "../src/example_for_repo. hpp"
196328
197329using namespace godot;
198330
199- // Example : Control
200-
201- void Example ::_bind_methods() {
202- Method<&Example ::set_custom_position>::bind(D_METHOD("set_custom_position", "pos"));
203- Method<&Example ::get_custom_position>::bind(D_METHOD("get_custom_position"));
204- Method<&Example ::simple_func>::bind(D_METHOD("simple_func"));
205- Method<&Example ::simple_const_func>::bind(D_METHOD("simple_const_func"));
206- Method<&Example ::image_ref_func>::bind(D_METHOD("image_ref_func", "p_image"));
207- Method<&Example ::image_const_ref_func>::bind(D_METHOD("image_const_ref_func", "p_image"));
208- Method<&Example ::return_something>::bind(D_METHOD("return_something", "base"));
209- Method<&Example ::return_something_const>::bind(D_METHOD("return_something_const"));
210- Method<&Example ::def_args>::bind(D_METHOD("def_args", "p_a", "p_b"), DEFVAL(100), DEFVAL(200));
211- Method<&Example ::def_args_string>::bind(D_METHOD("def_args_string", "s"), DEFVAL(String("default")));
212- Method<&Example ::rpc_example>::bind(D_METHOD("rpc_example", "p_value"));
213- Method<&Example ::rpc_example2>::bind(D_METHOD("rpc_example2"));
214- Method<&Example ::register_this>::bind(D_METHOD("register_this"));
215- Method<&Example ::virtual_example>::bind(D_METHOD("virtual_example"));
216- Method<&Example ::get_float_auto>::bind(D_METHOD("get_float_auto"));
217- Method<&Example ::set_float_auto>::bind(D_METHOD("set_float_auto", "value"));
218- Method<&Example ::get_float_hint>::bind(D_METHOD("get_float_hint"));
219- Method<&Example ::set_float_hint>::bind(D_METHOD("set_float_hint", "value"));
220-
221-
222- StaticMethod<&Example ::test_static>::bind(get_class_static(), D_METHOD("test_static", "p_a", "p_b"));
223-
224-
225- Method<&Example ::varargs_func_example>::bind_vararg("varargs_func_example"
331+ // ExampleForRepo : Control
332+
333+ void ExampleForRepo ::_bind_methods() {
334+ Method<&ExampleForRepo ::set_custom_position>::bind(D_METHOD("set_custom_position", "pos"));
335+ Method<&ExampleForRepo ::get_custom_position>::bind(D_METHOD("get_custom_position"));
336+ Method<&ExampleForRepo ::simple_func>::bind(D_METHOD("simple_func"));
337+ Method<&ExampleForRepo ::simple_const_func>::bind(D_METHOD("simple_const_func"));
338+ Method<&ExampleForRepo ::image_ref_func>::bind(D_METHOD("image_ref_func", "p_image"));
339+ Method<&ExampleForRepo ::image_const_ref_func>::bind(D_METHOD("image_const_ref_func", "p_image"));
340+ Method<&ExampleForRepo ::return_something>::bind(D_METHOD("return_something", "base"));
341+ Method<&ExampleForRepo ::return_something_const>::bind(D_METHOD("return_something_const"));
342+ Method<&ExampleForRepo ::def_args>::bind(D_METHOD("def_args", "p_a", "p_b"), DEFVAL(100), DEFVAL(200));
343+ Method<&ExampleForRepo ::def_args_string>::bind(D_METHOD("def_args_string", "s"), DEFVAL(String("default")));
344+ Method<&ExampleForRepo ::rpc_example>::bind(D_METHOD("rpc_example", "p_value"));
345+ Method<&ExampleForRepo ::rpc_example2>::bind(D_METHOD("rpc_example2"));
346+ Method<&ExampleForRepo ::register_this>::bind(D_METHOD("register_this"));
347+ Method<&ExampleForRepo ::virtual_example>::bind(D_METHOD("virtual_example"));
348+ Method<&ExampleForRepo ::get_float_auto>::bind(D_METHOD("get_float_auto"));
349+ Method<&ExampleForRepo ::set_float_auto>::bind(D_METHOD("set_float_auto", "value"));
350+ Method<&ExampleForRepo ::get_float_hint>::bind(D_METHOD("get_float_hint"));
351+ Method<&ExampleForRepo ::set_float_hint>::bind(D_METHOD("set_float_hint", "value"));
352+
353+
354+ StaticMethod<&ExampleForRepo ::test_static>::bind(get_class_static(), D_METHOD("test_static", "p_a", "p_b"));
355+
356+
357+ Method<&ExampleForRepo ::varargs_func_example>::bind_vararg("varargs_func_example"
226358 ,MakePropertyInfo<String>("named_arg")
227359 ,MakePropertyInfo<Variant>("unnamed_arg")
228360 );
@@ -253,8 +385,7 @@ void Example::_bind_methods() {
253385 BIND_CONSTANT(CONSTANT_WITHOUT_ENUM);
254386}
255387
256- // Call this in _ready() to configure RPC for your node
257- void Example::_rpc_config() {
388+ void ExampleForRepo::_rpc_config() {
258389 {
259390 Dictionary opts;
260391 opts["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
@@ -273,14 +404,16 @@ void Example::_rpc_config() {
273404 }
274405}
275406
276- // Expands into setter/getter definitions
277- GENERATE_GETTER(Example::get_float_auto, Example::float_auto);
278- GENERATE_SETTER(Example::set_float_auto, Example::float_auto);
279- GENERATE_GETTER(Example::get_float_hint, Example::float_hint);
280- GENERATE_SETTER(Example::set_float_hint, Example::float_hint);
407+ GENERATE_GETTER(ExampleForRepo::get_float_auto, ExampleForRepo::float_auto);
408+ GENERATE_SETTER(ExampleForRepo::set_float_auto, ExampleForRepo::float_auto);
409+ GENERATE_GETTER(ExampleForRepo::get_float_hint, ExampleForRepo::float_hint);
410+ GENERATE_SETTER(ExampleForRepo::set_float_hint, ExampleForRepo::float_hint);
411+
412+ VARIANT_ENUM_CAST(ExampleForRepo::Constants);
413+ VARIANT_BITFIELD_CAST(ExampleForRepo::Flags);
281414
282- // godot-cpp macros to register enums/bitfields
283- // and be able to use them as method arguments
284- VARIANT_ENUM_CAST(Example::Constants);
285- VARIANT_BITFIELD_CAST(Example::Flags);
286415```
416+
417+
418+
419+
0 commit comments