Skip to content

Commit 70db7fc

Browse files
author
Vano
committed
README change
2 parents 65c91a0 + dbabe57 commit 70db7fc

File tree

1 file changed

+221
-88
lines changed

1 file changed

+221
-88
lines changed

README.md

Lines changed: 221 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
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
1919
libclang
2020
```bash
2121
pip 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
197329
using 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

Comments
 (0)