Skip to content

Commit

Permalink
Merge pull request #33 from gilzoide/global-enums
Browse files Browse the repository at this point in the history
Add global enum bindings
  • Loading branch information
gilzoide authored Oct 14, 2023
2 parents 22ca8e1 + c82f0ef commit 1a75bea
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 114 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ jobs:
uses: actions/cache@v3
with:
path: .scons-cache/
key: ${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-${{ hashfiles('.gitmodules', 'src/**.{hpp,cpp}') }}
key: ${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-${{ hashfiles('.gitmodules', 'src/**') }}
restore-keys: |
${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}
${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-
- name: Build artifact
run: |
scons platform=${{ matrix.platform }} arch=${{ matrix.arch }} target=${{ matrix.target }} ${{ join(matrix.scons-args, ' ') }}
Expand Down Expand Up @@ -85,12 +85,14 @@ jobs:
uses: actions/cache@v3
with:
path: .scons-cache/
key: ${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-${{ hashfiles('.gitmodules', 'src/**.{hpp,cpp}') }}
key: ${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-${{ hashfiles('.gitmodules', 'src/**') }}
restore-keys: |
${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}
${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.target }}-
- name: Build artifact
run: |
scons platform=${{ matrix.platform }} arch=${{ matrix.arch }} target=${{ matrix.target }}
env:
PYTHON_BIN: python3
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ build/*
*.framework
compile_commands.json
addons/lua-gdextension/LICENSE
src/generated/

# Test project files
.godot/
Expand Down
15 changes: 15 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ else: # build library
compiledb = env.CompilationDatabase("compile_commands.json")
env.Alias("compiledb", compiledb)

# Generate sources
python_bin = os.getenv("PYTHON_BIN", "python")
env.Command(
[
"src/generated/global_enums.hpp",
"src/generated/utility_functions.hpp",
],
[
"src/generate_code.py",
"lib/godot-cpp/gdextension/extension_api.json",
"lib/godot-cpp/gen/include/godot_cpp/variant/utility_functions.hpp",
],
action=python_bin + " $SOURCE",
)

# Compile with debugging symbols
if ARGUMENTS.get("debugging_symbols") == 'true':
if "-O2" in env["CCFLAGS"]:
Expand Down
2 changes: 1 addition & 1 deletion src/LuaObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class LuaObjectSubclass : public LuaObject {
}
}

const sol::reference& get_lua_object() const {
const sol::reference& get_lua_object() const override {
return lua_object;
}

Expand Down
4 changes: 4 additions & 0 deletions src/LuaState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ void LuaState::open_libraries(BitField<Library> libraries) {
if (libraries.has_flag(GODOT_CLASSES)) {
lua_state.require(module_names::classes, &luaopen_godot_classes, false);
}
if (libraries.has_flag(GODOT_ENUMS)) {
lua_state.require(module_names::enums, &luaopen_godot_enums, false);
}
}
}

Expand Down Expand Up @@ -175,6 +178,7 @@ void LuaState::_bind_methods() {
BIND_BITFIELD_FLAG(GODOT_UTILITY_FUNCTIONS);
BIND_BITFIELD_FLAG(GODOT_SINGLETONS);
BIND_BITFIELD_FLAG(GODOT_CLASSES);
BIND_BITFIELD_FLAG(GODOT_ENUMS);
BIND_BITFIELD_FLAG(GODOT);

// Methods
Expand Down
3 changes: 2 additions & 1 deletion src/LuaState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ class LuaState : public RefCounted {
GODOT_UTILITY_FUNCTIONS = 1 << 14,
GODOT_SINGLETONS = 1 << 15,
GODOT_CLASSES = 1 << 16,
GODOT_ENUMS = 1 << 17,

// all of the above
GODOT = GODOT_VARIANT | GODOT_UTILITY_FUNCTIONS | GODOT_SINGLETONS | GODOT_CLASSES,
GODOT = GODOT_VARIANT | GODOT_UTILITY_FUNCTIONS | GODOT_SINGLETONS | GODOT_CLASSES | GODOT_ENUMS,
};

LuaState();
Expand Down
65 changes: 65 additions & 0 deletions src/generate_code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import json
from os import path

SRC_DIR = path.dirname(__file__)
DEST_DIR = path.join(SRC_DIR, "generated")
API_JSON_PATH = path.join(SRC_DIR, "..", "lib", "godot-cpp", "gdextension", "extension_api.json")
GODOT_CPP_DIR = path.join(SRC_DIR, "..", "lib", "godot-cpp")
GODOT_CPP_UTILITY_FUNCTIONS = path.join(GODOT_CPP_DIR, "gen", "include", "godot_cpp", "variant", "utility_functions.hpp")
PRIMITIVE_VARIANTS = [
"bool",
"int",
"float",
]


def generate_utility_functions(utility_functions):
lines = [
"#undef register_utility_functions\n#define register_utility_functions(state)"
]
with open(GODOT_CPP_UTILITY_FUNCTIONS) as f:
godot_cpp_utility_functions = f.read()
for f in utility_functions:
name = f["name"]
if name not in godot_cpp_utility_functions:
# godot-cpp does not implement "typeof", just skip anything that is
# not mentioned in the header
continue
if f.get("is_vararg", False):
lines.append(f'\tstate.set("{name}", wrap_function(&UtilityFunctions::{name}_internal));')
elif (
f.get("return_type") not in PRIMITIVE_VARIANTS
or any(arg["type"] not in PRIMITIVE_VARIANTS for arg in f.get("arguments", []))
):
lines.append(f'\tstate.set("{name}", wrap_function(&UtilityFunctions::{name}));')
else:
lines.append(f'\tstate.set("{name}", &UtilityFunctions::{name});')
return " \\\n".join(lines) + "\n"


def generate_enums(global_enums):
lines = [
"#undef register_global_enums\n#define register_global_enums(state)"
]
for enum in global_enums:
lines.append(f"\t/* {enum['name']} */")
for value in enum["values"]:
lines.append(f'\tstate.set("{value["name"]}", {value["value"]});')
return " \\\n".join(lines) + "\n"


def main():
with open(API_JSON_PATH) as f:
api = json.load(f)

with open(path.join(DEST_DIR, "utility_functions.hpp"), "w") as f:
code = generate_utility_functions(api["utility_functions"])
f.write(code)

with open(path.join(DEST_DIR, "global_enums.hpp"), "w") as f:
code = generate_enums(api["global_enums"])
f.write(code)


if __name__ == "__main__":
main()
36 changes: 36 additions & 0 deletions src/luaopen/enums.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (C) 2023 Gil Barbosa Reis.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the “Software”), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "../generated/global_enums.hpp"
#include "../utils/module_names.hpp"

#include <sol/sol.hpp>

using namespace luagdextension;

extern "C" int luaopen_godot_enums(lua_State *L) {
sol::state_view state = L;

register_global_enums(state);

return 0;
}

1 change: 1 addition & 0 deletions src/luaopen/godot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extern "C" int luaopen_godot(lua_State *L) {
state.require(module_names::utility_functions, &luaopen_godot_utility_functions, false);
state.require(module_names::singleton_access, &luaopen_godot_singleton_access, false);
state.require(module_names::classes, &luaopen_godot_classes, false);
state.require(module_names::enums, &luaopen_godot_enums, false);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/luaopen/godot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ int luaopen_godot_variant(lua_State *L);
int luaopen_godot_utility_functions(lua_State *L);
int luaopen_godot_singleton_access(lua_State *L);
int luaopen_godot_classes(lua_State *L);
int luaopen_godot_enums(lua_State *L);

}

Expand Down
110 changes: 2 additions & 108 deletions src/luaopen/utility_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "../generated/utility_functions.hpp"
#include "../utils/function_wrapper.hpp"

// We can't call variadic templates at runtime, so we need access
Expand All @@ -35,113 +35,7 @@ using namespace luagdextension;
extern "C" int luaopen_godot_utility_functions(lua_State *L) {
sol::state_view state = L;

state.set("sin", &UtilityFunctions::sin);
state.set("cos", &UtilityFunctions::cos);
state.set("tan", &UtilityFunctions::tan);
state.set("sinh", &UtilityFunctions::sinh);
state.set("cosh", &UtilityFunctions::cosh);
state.set("tanh", &UtilityFunctions::tanh);
state.set("asin", &UtilityFunctions::asin);
state.set("acos", &UtilityFunctions::acos);
state.set("atan", &UtilityFunctions::atan);
state.set("atan2", &UtilityFunctions::atan2);
state.set("sqrt", &UtilityFunctions::sqrt);
state.set("fmod", &UtilityFunctions::fmod);
state.set("fposmod", &UtilityFunctions::fposmod);
state.set("posmod", &UtilityFunctions::posmod);
state.set("floor", wrap_function(&UtilityFunctions::floor));
state.set("floorf", &UtilityFunctions::floorf);
state.set("floori", &UtilityFunctions::floori);
state.set("ceil", wrap_function(&UtilityFunctions::ceil));
state.set("ceilf", &UtilityFunctions::ceilf);
state.set("ceili", &UtilityFunctions::ceili);
state.set("round", wrap_function(&UtilityFunctions::round));
state.set("roundf", &UtilityFunctions::roundf);
state.set("roundi", &UtilityFunctions::roundi);
state.set("abs", wrap_function(&UtilityFunctions::abs));
state.set("absf", &UtilityFunctions::absf);
state.set("absi", &UtilityFunctions::absi);
state.set("sign", wrap_function(&UtilityFunctions::sign));
state.set("signf", &UtilityFunctions::signf);
state.set("signi", &UtilityFunctions::signi);
state.set("snapped", wrap_function(&UtilityFunctions::snapped));
state.set("snappedf", &UtilityFunctions::snappedf);
state.set("snappedi", &UtilityFunctions::snappedi);
state.set("pow", &UtilityFunctions::pow);
state.set("log", &UtilityFunctions::log);
state.set("exp", &UtilityFunctions::exp);
state.set("is_nan", &UtilityFunctions::is_nan);
state.set("is_inf", &UtilityFunctions::is_inf);
state.set("is_equal_approx", &UtilityFunctions::is_equal_approx);
state.set("is_zero_approx", &UtilityFunctions::is_zero_approx);
state.set("is_finite", &UtilityFunctions::is_finite);
state.set("ease", &UtilityFunctions::ease);
state.set("step_decimals", &UtilityFunctions::step_decimals);
state.set("lerp", wrap_function(&UtilityFunctions::lerp));
state.set("lerpf", &UtilityFunctions::lerpf);
state.set("cubic_interpolate", &UtilityFunctions::cubic_interpolate);
state.set("cubic_interpolate_angle", &UtilityFunctions::cubic_interpolate_angle);
state.set("cubic_interpolate_in_time", &UtilityFunctions::cubic_interpolate_in_time);
state.set("cubic_interpolate_angle_in_time", &UtilityFunctions::cubic_interpolate_angle_in_time);
state.set("bezier_interpolate", &UtilityFunctions::bezier_interpolate);
state.set("bezier_derivative", &UtilityFunctions::bezier_derivative);
state.set("lerp_angle", &UtilityFunctions::lerp_angle);
state.set("inverse_lerp", &UtilityFunctions::inverse_lerp);
state.set("remap", &UtilityFunctions::remap);
state.set("smoothstep", &UtilityFunctions::smoothstep);
state.set("move_toward", &UtilityFunctions::move_toward);
state.set("deg_to_rad", &UtilityFunctions::deg_to_rad);
state.set("rad_to_deg", &UtilityFunctions::rad_to_deg);
state.set("linear_to_db", &UtilityFunctions::linear_to_db);
state.set("db_to_linear", &UtilityFunctions::db_to_linear);
state.set("wrap", wrap_function(&UtilityFunctions::wrap));
state.set("wrapi", &UtilityFunctions::wrapi);
state.set("wrapf", &UtilityFunctions::wrapf);
state.set("max", wrap_function(&UtilityFunctions::max_internal));
state.set("maxi", &UtilityFunctions::maxi);
state.set("maxf", &UtilityFunctions::maxf);
state.set("min", wrap_function(&UtilityFunctions::min_internal));
state.set("mini", &UtilityFunctions::mini);
state.set("minf", &UtilityFunctions::minf);
state.set("clamp", wrap_function(&UtilityFunctions::clamp));
state.set("clampi", &UtilityFunctions::clampi);
state.set("clampf", &UtilityFunctions::clampf);
state.set("nearest_po2", &UtilityFunctions::nearest_po2);
state.set("pingpong", &UtilityFunctions::pingpong);
state.set("randomize", &UtilityFunctions::randomize);
state.set("randi", &UtilityFunctions::randi);
state.set("randf", &UtilityFunctions::randf);
state.set("randi_range", &UtilityFunctions::randi_range);
state.set("randf_range", &UtilityFunctions::randf_range);
state.set("randfn", &UtilityFunctions::randfn);
state.set("seed", &UtilityFunctions::seed);
state.set("rand_from_seed", &UtilityFunctions::rand_from_seed);
state.set("weakref", wrap_function(&UtilityFunctions::weakref));
state.set("type_of", wrap_function(&UtilityFunctions::type_of));
state.set("str", wrap_function(&UtilityFunctions::str_internal));
state.set("error_string", &UtilityFunctions::error_string);
state.set("print", wrap_function(&UtilityFunctions::print_internal));
state.set("print_rich", wrap_function(&UtilityFunctions::print_rich_internal));
state.set("printerr", wrap_function(&UtilityFunctions::printerr_internal));
state.set("printt", wrap_function(&UtilityFunctions::printt_internal));
state.set("prints", wrap_function(&UtilityFunctions::prints_internal));
state.set("printraw", wrap_function(&UtilityFunctions::printraw_internal));
state.set("print_verbose", wrap_function(&UtilityFunctions::print_verbose_internal));
state.set("push_error", wrap_function(&UtilityFunctions::push_error_internal));
state.set("push_warning", wrap_function(&UtilityFunctions::push_warning_internal));
state.set("var_to_str", wrap_function(&UtilityFunctions::var_to_str));
state.set("str_to_var", wrap_function(&UtilityFunctions::str_to_var));
state.set("var_to_bytes", wrap_function(&UtilityFunctions::var_to_bytes));
state.set("bytes_to_var", wrap_function(&UtilityFunctions::bytes_to_var));
state.set("var_to_bytes_with_objects", wrap_function(&UtilityFunctions::var_to_bytes_with_objects));
state.set("bytes_to_var_with_objects", wrap_function(&UtilityFunctions::bytes_to_var_with_objects));
state.set("hash", wrap_function(&UtilityFunctions::hash));
state.set("instance_from_id", &UtilityFunctions::instance_from_id);
state.set("is_instance_id_valid", &UtilityFunctions::is_instance_id_valid);
state.set("is_instance_valid", wrap_function(&UtilityFunctions::is_instance_valid));
state.set("rid_allocate_id", &UtilityFunctions::rid_allocate_id);
state.set("rid_from_int64", &UtilityFunctions::rid_from_int64);
state.set("is_same", wrap_function(&UtilityFunctions::is_same));
register_utility_functions(state);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/utils/module_names.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ constexpr char variant[] = "godot.variant";
constexpr char utility_functions[] = "godot.utility_functions";
constexpr char singleton_access[] = "godot.singleton_access";
constexpr char classes[] = "godot.classes";
constexpr char enums[] = "godot.enums";

}

Expand Down
4 changes: 4 additions & 0 deletions test/lua_tests/global_enums.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
assert(SIDE_LEFT == 0)
assert(SIDE_TOP == 1)
assert(SIDE_RIGHT == 2)
assert(SIDE_BOTTOM == 3)

0 comments on commit 1a75bea

Please sign in to comment.