From f9406aa9a990ab69dc626a20781e20b921bb026a Mon Sep 17 00:00:00 2001 From: PoliEcho Date: Thu, 13 Feb 2025 15:26:50 +0100 Subject: [PATCH] why doesn't this work :( --- extern/godot-cpp | 2 +- project/icon.svg.import | 2 +- project/main.tscn | 9 + ...te.gdextension => naval-swarm.gdextension} | 0 project/project.godot | 1 + src/api/extension_interface.cpp | 89 -------- src/api/extension_interface.hpp | 18 -- src/core/assert.hpp | 47 ---- src/core/attributes.hpp | 19 -- src/core/concepts.hpp | 40 ---- src/core/constants.hpp | 80 ------- src/core/function_traits.hpp | 121 ---------- src/entity/camera.cpp | 14 -- src/entity/camera.hpp | 20 -- src/entity/character/character.cpp | 134 ----------- src/entity/character/character.hpp | 87 ------- src/entity/character/enemy.cpp | 17 -- src/entity/character/enemy.hpp | 21 -- src/entity/character/player.cpp | 22 -- src/entity/character/player.hpp | 22 -- .../controller/character_controller.cpp | 61 ----- .../controller/character_controller.hpp | 48 ---- src/entity/controller/enemy_controller.cpp | 16 -- src/entity/controller/enemy_controller.hpp | 29 --- src/entity/controller/player_controller.cpp | 106 --------- src/entity/controller/player_controller.hpp | 25 -- src/entity/level.cpp | 133 ----------- src/entity/level.hpp | 56 ----- src/entity/projectile/projectile.cpp | 95 -------- src/entity/projectile/projectile.hpp | 65 ------ src/entity/projectile/projectile_spawner.cpp | 45 ---- src/entity/projectile/projectile_spawner.hpp | 48 ---- src/main.cpp | 73 ++---- src/main.hpp | 42 ++-- src/singletons/console.hpp | 117 ---------- src/ui/main_dialog.cpp | 57 ----- src/ui/main_dialog.hpp | 29 --- src/util/bind.hpp | 216 ------------------ src/util/conversions.hpp | 71 ------ src/util/debug.hpp | 54 ----- src/util/engine.cpp | 57 ----- src/util/engine.hpp | 27 --- src/util/input.cpp | 51 ----- src/util/input.hpp | 35 --- src/util/io.hpp | 134 ----------- src/util/os.hpp | 14 -- src/util/scene.hpp | 177 -------------- src/util/variant.hpp | 20 -- 48 files changed, 43 insertions(+), 2623 deletions(-) create mode 100644 project/main.tscn rename project/{roguelite.gdextension => naval-swarm.gdextension} (100%) delete mode 100644 src/api/extension_interface.cpp delete mode 100644 src/api/extension_interface.hpp delete mode 100644 src/core/assert.hpp delete mode 100644 src/core/attributes.hpp delete mode 100644 src/core/concepts.hpp delete mode 100644 src/core/constants.hpp delete mode 100644 src/core/function_traits.hpp delete mode 100644 src/entity/camera.cpp delete mode 100644 src/entity/camera.hpp delete mode 100644 src/entity/character/character.cpp delete mode 100644 src/entity/character/character.hpp delete mode 100644 src/entity/character/enemy.cpp delete mode 100644 src/entity/character/enemy.hpp delete mode 100644 src/entity/character/player.cpp delete mode 100644 src/entity/character/player.hpp delete mode 100644 src/entity/controller/character_controller.cpp delete mode 100644 src/entity/controller/character_controller.hpp delete mode 100644 src/entity/controller/enemy_controller.cpp delete mode 100644 src/entity/controller/enemy_controller.hpp delete mode 100644 src/entity/controller/player_controller.cpp delete mode 100644 src/entity/controller/player_controller.hpp delete mode 100644 src/entity/level.cpp delete mode 100644 src/entity/level.hpp delete mode 100644 src/entity/projectile/projectile.cpp delete mode 100644 src/entity/projectile/projectile.hpp delete mode 100644 src/entity/projectile/projectile_spawner.cpp delete mode 100644 src/entity/projectile/projectile_spawner.hpp delete mode 100644 src/singletons/console.hpp delete mode 100644 src/ui/main_dialog.cpp delete mode 100644 src/ui/main_dialog.hpp delete mode 100644 src/util/bind.hpp delete mode 100644 src/util/conversions.hpp delete mode 100644 src/util/debug.hpp delete mode 100644 src/util/engine.cpp delete mode 100644 src/util/engine.hpp delete mode 100644 src/util/input.cpp delete mode 100644 src/util/input.hpp delete mode 100644 src/util/io.hpp delete mode 100644 src/util/os.hpp delete mode 100644 src/util/scene.hpp delete mode 100644 src/util/variant.hpp diff --git a/extern/godot-cpp b/extern/godot-cpp index 56571dc..f3a1a2f 160000 --- a/extern/godot-cpp +++ b/extern/godot-cpp @@ -1 +1 @@ -Subproject commit 56571dc584ee7d14919996c6d58fb5b35e64af63 +Subproject commit f3a1a2fd458dfaf4de08c906f22a2fe9e924b16f diff --git a/project/icon.svg.import b/project/icon.svg.import index cadae86..fa3ddce 100644 --- a/project/icon.svg.import +++ b/project/icon.svg.import @@ -2,7 +2,7 @@ importer="texture" type="CompressedTexture2D" -uid="uid://dw7fcik6u7kkn" +uid="uid://dmcjlguuq8xqt" path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" metadata={ "vram_texture": false diff --git a/project/main.tscn b/project/main.tscn new file mode 100644 index 0000000..c941aeb --- /dev/null +++ b/project/main.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://beuvt3vhjibjt"] + +[ext_resource type="Texture2D" uid="uid://dmcjlguuq8xqt" path="res://icon.svg" id="1_lodlx"] + +[node name="Main" type="Node"] + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_lodlx") +centered = false diff --git a/project/roguelite.gdextension b/project/naval-swarm.gdextension similarity index 100% rename from project/roguelite.gdextension rename to project/naval-swarm.gdextension diff --git a/project/project.godot b/project/project.godot index d7ae337..f83b96b 100644 --- a/project/project.godot +++ b/project/project.godot @@ -11,5 +11,6 @@ config_version=5 [application] config/name="Naval Swarm" +run/main_scene="res://main.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://icon.svg" diff --git a/src/api/extension_interface.cpp b/src/api/extension_interface.cpp deleted file mode 100644 index 3075fe2..0000000 --- a/src/api/extension_interface.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "api/extension_interface.hpp" -#include "entity/camera.hpp" -#include "entity/character/character.hpp" -#include "entity/character/enemy.hpp" -#include "entity/character/player.hpp" -#include "entity/controller/character_controller.hpp" -#include "entity/controller/enemy_controller.hpp" -#include "entity/controller/player_controller.hpp" -#include "entity/level.hpp" -#include "entity/projectile/projectile_spawner.hpp" -#include "main.hpp" -#include "singletons/console.hpp" -#include "ui/main_dialog.hpp" -#include "util/engine.hpp" - -namespace rl -{ - static inline console* console_singleton{ nullptr }; - - void initialize_static_objects() - { - console_singleton = memnew(console); - rl::engine::get()->register_singleton("Console", console::get()); - } - - void teardown_static_objects() - { - rl::engine::get()->unregister_singleton("Console"); - memdelete(console_singleton); - } - - void initialize_extension_module(godot::ModuleInitializationLevel init_level) - { - if (init_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE) - return; - - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - - godot::ClassDB::register_abstract_class(); - godot::ClassDB::register_class(true); - godot::ClassDB::register_class(); - - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - godot::ClassDB::register_class(); - - godot::ClassDB::register_class(); - - initialize_static_objects(); - } - - void uninitialize_extension_module(godot::ModuleInitializationLevel init_level) - { - if (init_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE) - return; - - teardown_static_objects(); - } - - extern "C" - { - GDExtensionBool GDE_EXPORT extension_library_init(GDExtensionInterfaceGetProcAddress addr, - GDExtensionClassLibraryPtr lib, - GDExtensionInitialization* init) - { - const auto init_level = godot::MODULE_INITIALIZATION_LEVEL_SCENE; - godot::GDExtensionBinding::InitObject init_obj(addr, lib, init); - - init_obj.register_initializer(initialize_extension_module); - init_obj.register_terminator(uninitialize_extension_module); - init_obj.set_minimum_library_initialization_level(init_level); - - return init_obj.init(); - } - } -} diff --git a/src/api/extension_interface.hpp b/src/api/extension_interface.hpp deleted file mode 100644 index 380b76a..0000000 --- a/src/api/extension_interface.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -namespace godot -{ - void initialize_static_objects(); - void teardown_static_objects(); - void initialize_extension_module(ModuleInitializationLevel init_level); - void uninitialize_extension_module(ModuleInitializationLevel init_level); - - extern "C" - { - GDExtensionBool GDE_EXPORT extension_library_init(GDExtensionInterfaceGetProcAddress addr, - GDExtensionClassLibraryPtr lib, - GDExtensionInitialization* init); - } -} diff --git a/src/core/assert.hpp b/src/core/assert.hpp deleted file mode 100644 index ca6d558..0000000 --- a/src/core/assert.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include - -#include - -#ifndef NDEBUG - // - // In debug mode, checks the passed in condition and outputs - // detailed information to stederr, including a custom error - // message when the condition evaluates to false. - // - #define assertion(condition, message) \ - do \ - { \ - if (!(condition)) [[unlikely]] \ - { \ - ::godot::_err_print_error(__FUNCTION__, __FILE__, __LINE__, \ - message " => condition: (" #condition ")"); \ - ::godot::_err_flush_stdout(); \ - GENERATE_TRAP(); \ - } \ - } \ - while (false) - - #define error_msg(message) \ - do \ - { \ - ::godot::_err_print_error(__FUNCTION__, __FILE__, __LINE__, message); \ - ::godot::_err_flush_stdout(); \ - GENERATE_TRAP(); \ - } \ - while (false) - - #define runtime_assert(condition) assertion(condition, "validation check failed") - -#else -// -// In release mode the macro does nothing ((void)0), including -// the execution of the condition so don't define the expression -// as anything that would be considered program logis. -// - #define assertion(condition, message) static_cast(0) - #define error_msg(message) static_cast(0) - #define runtime_assert(condition) static_cast(0) -#endif diff --git a/src/core/attributes.hpp b/src/core/attributes.hpp deleted file mode 100644 index 0a8e7fa..0000000 --- a/src/core/attributes.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -namespace rl::inline utils -{ - -#if defined(_MSC_VER) - // MSVC doesn't have a clean way to ignore custom - // attributes within a namespace like clang or gcc - #define property - #define signal_slot -#elif defined(__GNUG__) || defined(__clang__) - // these macros are used to define custom attributes to label godot signal callbacks - // and node properties. they don't do anything other than making it easier to spot - // these functions when reading the code or searching for them in an IDE. - #define property __attribute__((rl("property"))) - #define signal_slot __attribute__((rl("signal_slot"))) -#endif - -} diff --git a/src/core/concepts.hpp b/src/core/concepts.hpp deleted file mode 100644 index a7cff22..0000000 --- a/src/core/concepts.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace godot -{ - template - struct GetTypeInfo; - class Variant; - class Object; -} - -namespace rl::inline utils -{ - template - concept CompileTimeStr = std::same_as || - std::same_as || - std::same_as; - - template - concept GDObjectDerived = - std::derived_from>, godot::Object> || - std::same_as>, godot::Object>; - - template - concept VariantConstructable = requires(const T& t) { static_cast(t); }; - - template - concept VariantConvertable = requires(T t) { static_cast(t); }; - - template - concept VariantCompatible = - VariantConstructable> && - VariantConvertable> && requires { - godot::GetTypeInfo>, void>::VARIANT_TYPE; - }; -} diff --git a/src/core/constants.hpp b/src/core/constants.hpp deleted file mode 100644 index e44a0a8..0000000 --- a/src/core/constants.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include -#include - -namespace rl::inline constants -{ - namespace name - { - namespace level - { - constexpr inline auto level1{ "Level1" }; - constexpr inline auto physics_box{ "PhysicsBox" }; - } - - namespace dialog - { - constexpr inline auto console{ "ConsolePanel" }; - constexpr inline auto canvas_layer{ "MainCanvasLayer" }; - - } - - namespace character - { - constexpr inline auto player{ "Player" }; - constexpr inline auto enemy{ "Enemy" }; - constexpr inline auto firing_pt{ "FiringPoint" }; - } - - } - - namespace event - { - constexpr inline auto position_changed{ "position_changed" }; - constexpr inline auto entered_area{ "entered_area" }; - constexpr inline auto exited_area{ "exited_area" }; - constexpr inline auto spawn_projectile{ "spawn_projectile" }; - constexpr inline auto character_move{ "character_move" }; - constexpr inline auto character_rotate{ "character_rotate" }; - constexpr inline auto character_shoot{ "character_shoot" }; - constexpr inline auto body_entered{ "body_entered" }; - constexpr inline auto body_exited{ "body_exited" }; - constexpr inline auto signal_example{ "custom_signal_example" }; - } - - enum class LayerID : uint32_t { - Player = 0x00000001, - NPCs = 0x00000002, - Projectiles = 0x00000004, - Walls = 0x00000008, - DamageZones = 0x00000010, - DeathZones = 0x00000020, - PhysicsObjects = 0x00000040, - Layer08 = 0x00000080, - Layer09 = 0x00000100, - Layer10 = 0x00000200, - Layer11 = 0x00000400, - Layer12 = 0x00000800, - Layer13 = 0x00001000, - Layer14 = 0x00002000, - Layer15 = 0x00004000, - Layer16 = 0x00008000, - }; - - namespace path - - { - namespace scene - { - constexpr inline auto Level1{ "res://scenes/levels/level1.tscn" }; - constexpr inline auto Player{ "res://scenes/characters/player.tscn" }; - constexpr inline auto Bullet{ "res://scenes/projectiles/bullet.tscn" }; - } - - namespace ui - { - constexpr inline auto MainDialog{ "res://scenes/ui/main_dialog.tscn" }; - } - } -} diff --git a/src/core/function_traits.hpp b/src/core/function_traits.hpp deleted file mode 100644 index 7229602..0000000 --- a/src/core/function_traits.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#if defined(__GNUG__) - #define stdcall __attribute__((stdcall)) -#elif defined(__clang__) - #define stdcall __stdcall -#elif defined(_MSC_VER) - #define stdcall __cdecl -#endif - -namespace rl::inline utils -{ - namespace detail - { - template - void to_arg_vec_impl(std::vector& s, H&& h) - { - s.push_back(typeid(decltype(h)).name()); - } - - template - void to_arg_vec_impl(std::vector& s, H&& h, T&&... t) - { - s.push_back(typeid(decltype(h)).name()); - to_arg_vec_impl(s, std::forward(t)...); - } - - template - std::vector to_arg_vec(const std::tuple& tup, - std::integer_sequence) - { - std::vector result = {}; - to_arg_vec_impl(result, std::get(tup)...); - return result; - } - - template - std::vector to_arg_vec(const std::tuple& tup) - { - static constexpr size_t arg_count = sizeof...(TupleTypes); - return to_arg_vec(tup, std::make_index_sequence()); - } - - template - auto arg_vec_to_tuple(const std::vector& v, std::index_sequence) - { - return std::make_tuple(v[Indexes]...); - } - - template - auto arg_vec_to_tuple(const std::vector& v) - { - return arg_vec_to_tuple(v, std::make_index_sequence()); - } - } - - template - struct function_traits; - - // non-const member function - template - struct function_traits - { - using return_type = TRet; - using class_type = TClass; - using arg_types = std::tuple; - using arg_types_nocvref = std::tuple...>; - inline static const std::string_view class_name{ typeid(class_type).name() }; - static constexpr size_t arg_count = sizeof...(TArgs); - }; - - // const member function - template - struct function_traits - : public function_traits - { - using class_type = const TClass; - }; - - // functor / lambda - template - struct function_traits - : public function_traits::operator())> - { - inline static const std::string_view class_name{}; - }; - - // leaves function signature untouched if - // __stdcall or __cdecl isn't specified - template - struct remove_callingconv - { - using type = TFunction; - }; - - // strips __stdcall or __cdecl out of - // lambdas function/lambda type signatures - template - struct remove_callingconv - { - using type = TRet(TArgs...); - }; - - // strips __stdcall or __cdecl out of - // noexcept function/lambda type signatures - template - struct remove_callingconv - { - using type = TRet(TArgs...) noexcept; - }; -} diff --git a/src/entity/camera.cpp b/src/entity/camera.cpp deleted file mode 100644 index 9ba7099..0000000 --- a/src/entity/camera.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include "entity/camera.hpp" - -namespace rl -{ - Camera::Camera() - { - this->set_name("PlayerCamera"); - this->set_margin_drawing_enabled(true); - auto anchor{ AnchorMode::ANCHOR_MODE_DRAG_CENTER }; - this->set_anchor_mode(anchor); - } -} diff --git a/src/entity/camera.hpp b/src/entity/camera.hpp deleted file mode 100644 index 4df6475..0000000 --- a/src/entity/camera.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -namespace rl -{ - class Camera : public godot::Camera2D - { - GDCLASS(Camera, godot::Camera2D); - - public: - Camera(); - ~Camera() = default; - - protected: - static void _bind_methods() - { - } - }; -} diff --git a/src/entity/character/character.cpp b/src/entity/character/character.cpp deleted file mode 100644 index 2a9074d..0000000 --- a/src/entity/character/character.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/assert.hpp" -#include "core/concepts.hpp" -#include "core/constants.hpp" -#include "entity/camera.hpp" -#include "entity/character/character.hpp" -#include "entity/controller/character_controller.hpp" -#include "util/bind.hpp" -#include "util/engine.hpp" -#include "util/input.hpp" -#include "util/io.hpp" -#include "util/scene.hpp" - -namespace rl -{ - Character::Character() - { - this->set_motion_mode(MotionMode::MOTION_MODE_FLOATING); - } - - void Character::_ready() - { - this->add_child(m_camera); - this->add_child(m_character_controller); - - m_firing_point = gdcast( - this->find_child(name::character::firing_pt, true, false)); - - runtime_assert(m_firing_point != nullptr); - if (!engine::editor_active()) - runtime_assert(m_character_controller != nullptr); - - if (m_character_controller != nullptr) - { - signal::connect(m_character_controller) <=> - signal_callback(this, on_character_movement); - - signal::connect(m_character_controller) <=> - signal_callback(this, on_character_rotate); - - signal::connect(m_character_controller) <=> - signal_callback(this, on_character_shoot); - } - } - - void Character::set_controller(CharacterController* controller) - { - m_character_controller = controller; - runtime_assert(m_character_controller != nullptr); - } - - CharacterController* Character::get_controller() const - { - return m_character_controller; - } - - [[signal_slot]] - void Character::on_character_movement(godot::Vector2 movement_velocity, double delta_time) - { - double increment = m_movement_friction * delta_time; - godot::Vector2 velocity{ this->get_velocity().lerp(movement_velocity, increment) }; - velocity = velocity.clamp({ -1.0, -1.0 }, { 1.0, 1.0 }); - this->translate(velocity * this->get_movement_speed() * delta_time); - this->set_velocity(velocity); - this->move_and_slide(); - } - - [[signal_slot]] - void Character::on_character_rotate(double rotation_angle, double delta_time) - { - const double smoothed_angle = godot::Math::lerp_angle( - static_cast(this->get_rotation()), rotation_angle, m_rotation_speed * delta_time); - this->set_rotation(smoothed_angle); - } - - [[signal_slot]] - void Character::on_character_shoot() - { - // TODO: fix this - this->emit_signal(event::spawn_projectile, m_firing_point); - } - - [[property]] - double Character::get_movement_speed() const - { - return m_movement_speed; - } - - [[property]] - void Character::set_movement_speed(const double move_speed) - { - m_movement_speed = move_speed; - } - - [[property]] - double Character::get_movement_friction() const - { - return m_movement_friction; - } - - [[property]] - void Character::set_movement_friction(const double move_friction) - { - m_movement_friction = move_friction; - } - - [[property]] - double Character::get_rotation_speed() const - { - return m_rotation_speed; - } - - [[property]] - void Character::set_rotation_speed(const double rotation_speed) - { - m_rotation_speed = rotation_speed; - } -} diff --git a/src/entity/character/character.hpp b/src/entity/character/character.hpp deleted file mode 100644 index e99f262..0000000 --- a/src/entity/character/character.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include - -#include - -#include "core/attributes.hpp" -#include "core/constants.hpp" -#include "entity/camera.hpp" -#include "singletons/console.hpp" -#include "util/bind.hpp" - -namespace godot -{ - class Marker2D; - class Object; - struct Vector2; -} - -namespace rl -{ - class CharacterController; -} - -namespace rl -{ - class Character : public godot::CharacterBody2D - { - GDCLASS(Character, godot::CharacterBody2D); - - public: - Character(); - virtual ~Character() = default; - - virtual void _ready() override; - - public: - CharacterController* get_controller() const; - void set_controller(CharacterController* controller); - - protected: - [[property]] double get_movement_speed() const; - [[property]] double get_movement_friction() const; - [[property]] double get_rotation_speed() const; - - [[property]] void set_movement_speed(const double move_speed); - [[property]] void set_movement_friction(const double move_friction); - [[property]] void set_rotation_speed(const double rotation_speed); - - [[signal_slot]] void on_character_shoot(); - [[signal_slot]] void on_character_rotate(double rotation_angle, double delta_time); - [[signal_slot]] void on_character_movement(godot::Vector2 movement_velocity, - double delta_time); - - protected: - static void _bind_methods() - { - bind_member_function(Character, on_character_movement); - bind_member_function(Character, on_character_rotate); - bind_member_function(Character, on_character_shoot); - - bind_property(Character, movement_speed, double); - bind_property(Character, movement_friction, double); - bind_property(Character, rotation_speed, double); - - signal_binding::add(); - signal_binding::add(); - } - - protected: - // Rate of acceleration/deceleration (unit/s/s) - double m_movement_friction{ 5.0 }; - // Rate of rotational acceleration/deceleration (unit/s/s) - double m_rotation_speed{ 10.0 }; - // target movement speed (units/s) - double m_movement_speed{ 500.0 }; - // target facing angle (radians) - double m_rotation_angle{ 0.0 }; - - // the player character camera - Camera* m_camera{ memnew(Camera) }; - // handles all input related player controls - CharacterController* m_character_controller{ nullptr }; - // marker identifying location where to spwwn projectiles - godot::Marker2D* m_firing_point{ nullptr }; - }; -} diff --git a/src/entity/character/enemy.cpp b/src/entity/character/enemy.cpp deleted file mode 100644 index 47ab03b..0000000 --- a/src/entity/character/enemy.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "core/constants.hpp" -#include "entity/character/character.hpp" -#include "entity/character/enemy.hpp" -#include "util/scene.hpp" - -namespace rl -{ - Enemy::Enemy() - : Character() - { - scene::node::set_unique_name(this, name::character::enemy); - } - - void Enemy::_bind_methods() - { - } -} diff --git a/src/entity/character/enemy.hpp b/src/entity/character/enemy.hpp deleted file mode 100644 index ef701d6..0000000 --- a/src/entity/character/enemy.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "core/constants.hpp" -#include "entity/character/character.hpp" -#include "util/bind.hpp" - -namespace rl -{ - class Enemy : public Character - { - GDCLASS(Enemy, Character); - - public: - Enemy(); - - using Character::_ready; - - protected: - static void _bind_methods(); - }; -} diff --git a/src/entity/character/player.cpp b/src/entity/character/player.cpp deleted file mode 100644 index 9cca021..0000000 --- a/src/entity/character/player.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "core/constants.hpp" -#include "entity/character/character.hpp" -#include "entity/character/player.hpp" -#include "util/scene.hpp" - -namespace rl -{ - Player::Player() - : Character() - { - scene::node::set_unique_name(this, name::character::player); - } - - void Player::_ready() - { - Character::_ready(); - } - - void Player::_bind_methods() - { - } -} diff --git a/src/entity/character/player.hpp b/src/entity/character/player.hpp deleted file mode 100644 index a4c9505..0000000 --- a/src/entity/character/player.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "core/constants.hpp" -#include "entity/character/character.hpp" -#include "util/bind.hpp" - -namespace rl -{ - class Player : public Character - { - GDCLASS(Player, Character); - - public: - Player(); - ~Player() = default; - - void _ready() override; - - protected: - static void _bind_methods(); - }; -} diff --git a/src/entity/controller/character_controller.cpp b/src/entity/controller/character_controller.cpp deleted file mode 100644 index 0fe8e1a..0000000 --- a/src/entity/controller/character_controller.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include - -#include "core/assert.hpp" -#include "core/constants.hpp" -#include "entity/controller/character_controller.hpp" -#include "singletons/console.hpp" -#include "util/bind.hpp" -#include "util/engine.hpp" -#include "util/input.hpp" -#include "util/io.hpp" - -namespace rl -{ - void CharacterController::_process(double delta_time) - { - if (engine::editor_active()) - return; - - godot::Input* input_handler{ input::get() }; - if (input_handler != nullptr) - { - this->process_movement_input(input_handler, delta_time); - this->process_rotation_input(input_handler, delta_time); - this->process_action_input(input_handler, delta_time); - - m_elapsed_time += delta_time; - if (m_elapsed_time > 1.0) - { - m_elapsed_time = 0.0; - this->emit_signal(event::position_changed, this->get_parent(), - this->get_global_position()); - } - } - } - - void CharacterController::process_action_input(godot::Input* const input, double delta_time) - { - error_msg("process_action_input() not implemented in derived class"); - } - - void CharacterController::process_movement_input(godot::Input* const input, double delta_time) - { - error_msg("process_movement_input() not implemented in derived class"); - } - - void CharacterController::process_rotation_input(godot::Input* const input, double delta_time) - { - error_msg("process_rotation_input() not implemented in derived class"); - } - - void CharacterController::_bind_methods() - { - signal_binding::add(); - signal_binding::add(); - signal_binding::add(); - signal_binding::add(); - } -} diff --git a/src/entity/controller/character_controller.hpp b/src/entity/controller/character_controller.hpp deleted file mode 100644 index db2c32c..0000000 --- a/src/entity/controller/character_controller.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -#include "core/concepts.hpp" -#include "core/constants.hpp" -#include "util/bind.hpp" - -namespace rl -{ - class CharacterController : public godot::Node2D - { - GDCLASS(CharacterController, godot::Node2D); - - public: - enum class InputMode { - MouseAndKeyboard, - Controller, - AI - }; - - public: - CharacterController() = default; - virtual ~CharacterController() = default; - - void _process(double delta_time) override; - - virtual void process_action_input(godot::Input* const input, double delta_time); - virtual void process_movement_input(godot::Input* const input, double delta_time); - virtual void process_rotation_input(godot::Input* const input, double delta_time); - - protected: - static void _bind_methods(); - - protected: - // the active input mode for character controls - InputMode m_input_mode{ InputMode::MouseAndKeyboard }; - // target rotation - double m_rotation_angle{ 0.0 }; - // elapsed runtime (seconds) - double m_elapsed_time{ 0.0 }; - }; -} diff --git a/src/entity/controller/enemy_controller.cpp b/src/entity/controller/enemy_controller.cpp deleted file mode 100644 index cdb5ed1..0000000 --- a/src/entity/controller/enemy_controller.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "entity/controller/enemy_controller.hpp" - -namespace rl -{ - void EnemyController::process_action_input(godot::Input* const input, double delta_time) - { - } - - void EnemyController::process_movement_input(godot::Input* const input, double delta_time) - { - } - - void EnemyController::process_rotation_input(godot::Input* const input, double delta_time) - { - } -} diff --git a/src/entity/controller/enemy_controller.hpp b/src/entity/controller/enemy_controller.hpp deleted file mode 100644 index c145348..0000000 --- a/src/entity/controller/enemy_controller.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "entity/controller/character_controller.hpp" - -namespace godot -{ - class Input; -} - -namespace rl -{ - class EnemyController : public CharacterController - { - GDCLASS(EnemyController, CharacterController); - - public: - EnemyController() = default; - ~EnemyController() = default; - - void process_action_input(godot::Input* const input, double delta_time) override; - void process_movement_input(godot::Input* const input, double delta_time) override; - void process_rotation_input(godot::Input* const input, double delta_time) override; - - protected: - static void _bind_methods() - { - } - }; -} diff --git a/src/entity/controller/player_controller.cpp b/src/entity/controller/player_controller.cpp deleted file mode 100644 index 63811fe..0000000 --- a/src/entity/controller/player_controller.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include - -#include "core/constants.hpp" -#include "entity/controller/player_controller.hpp" -#include "singletons/console.hpp" -#include "util/engine.hpp" -#include "util/input.hpp" -#include "util/io.hpp" - -namespace rl -{ - void PlayerController::process_action_input(godot::Input* const input, double delta_time) - { - if (input->is_action_pressed("shoot")) - this->emit_signal(event::character_shoot); - } - - void PlayerController::process_movement_input(godot::Input* const input, double delta_time) - { - auto velocity{ input->get_vector(input::action::move_left, input::action::move_right, - input::action::move_up, input::action::move_down) }; - this->emit_signal(event::character_move, velocity, delta_time); - } - - // void PlayerController::_notification(int notification) - // { - // switch (notification) - // { - // case NOTIFICATION_PREDELETE: - // [[fallthrough]]; - // case NOTIFICATION_UNPARENTED: - // { - // console::get()->clear_context(); - // console::get()->stop_logging(); - // break; - // } - // default: - // break; - // } - - // auto console{ console::get() }; - // console->print("PlayerController: {}", notification); - // CharacterController::_notification(notification); - // } - - PlayerController::InputMode PlayerController::get_input_mode(godot::Input* const input) - { - switch (m_input_mode) - { - default: - [[fallthrough]]; - case InputMode::MouseAndKeyboard: - { - bool controller_input_detected{ input->is_action_pressed("controller_any") }; - if (controller_input_detected) - m_input_mode = InputMode::Controller; - break; - } - case InputMode::Controller: - { - godot::Vector2 mouse_velocity{ input->get_last_mouse_velocity() }; - if (!mouse_velocity.is_zero_approx()) - m_input_mode = InputMode::MouseAndKeyboard; - break; - } - } - - return m_input_mode; - } - - void PlayerController::process_rotation_input(godot::Input* const input, double delta_time) - { - switch (this->get_input_mode(input)) - { - default: - [[fallthrough]]; - case InputMode::MouseAndKeyboard: - { - godot::Vector2 rotation_dir{ this->get_global_mouse_position() - - this->get_global_position() }; - - m_rotation_angle = rotation_dir.angle() + godot::Math::deg_to_rad(90.0); - break; - } - case InputMode::Controller: - { - godot::TypedArray controllers{ input->get_connected_joypads() }; - if (controllers.is_empty()) - log::warning("InputMode = Controller, but no controllers detected"); - else - { - godot::Vector2 target_rotation{ input->get_vector("rotate_left", "rotate_right", - "rotate_up", "rotate_down") }; - if (!target_rotation.is_zero_approx()) - m_rotation_angle = godot::Vector2(0, 0).angle_to_point(target_rotation) + - godot::Math::deg_to_rad(90.0); - } - break; - } - } - - this->emit_signal(event::character_rotate, m_rotation_angle, delta_time); - } -} diff --git a/src/entity/controller/player_controller.hpp b/src/entity/controller/player_controller.hpp deleted file mode 100644 index f352595..0000000 --- a/src/entity/controller/player_controller.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "entity/controller/character_controller.hpp" - -namespace rl -{ - class PlayerController : public CharacterController - { - GDCLASS(PlayerController, CharacterController); - - public: - PlayerController() = default; - ~PlayerController() = default; - - void process_action_input(godot::Input* const input, double delta_time) override; - void process_movement_input(godot::Input* const input, double delta_time) override; - void process_rotation_input(godot::Input* const input, double delta_time) override; - InputMode get_input_mode(godot::Input* const input); - - protected: - static void _bind_methods() - { - } - }; -} diff --git a/src/entity/level.cpp b/src/entity/level.cpp deleted file mode 100644 index 7d98c5b..0000000 --- a/src/entity/level.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include -#include -#include - -#include "entity/character/character.hpp" -#include "entity/controller/player_controller.hpp" -#include "entity/level.hpp" -#include "singletons/console.hpp" -#include "util/bind.hpp" -#include "util/conversions.hpp" -#include "util/debug.hpp" -#include "util/engine.hpp" -#include "util/input.hpp" -#include "util/io.hpp" - -namespace rl -{ - Level::Level() - { - scene::node::set_unique_name(this, name::level::level1); - this->activate(true); - } - - void Level::_ready() - { - godot::Node* box{ this->find_child(name::level::physics_box) }; - m_physics_box = gdcast(box); - - resource::preload::packed_scene player_scene{ path::scene::Player }; - m_player = player_scene.instantiate(); - m_player->set_controller(memnew(PlayerController)); - - this->add_child(m_player); - this->add_child(m_projectile_spawner); - - PlayerController* controller{ gdcast(m_player->get_controller()) }; - if (controller != nullptr) - { - signal::connect(controller) <=> - signal_callback(this, on_character_position_changed); - - signal::connect(m_player) <=> - signal_callback(this, on_player_spawn_projectile); - } - } - - void Level::_process(double delta_time) - { - if (engine::editor_active()) - return; - - if (this->active() && input::cursor_visible()) [[unlikely]] - input::hide_cursor(); - else if (!this->active() && !input::cursor_visible()) [[unlikely]] - input::show_cursor(); - - this->queue_redraw(); - } - - void Level::_draw() - { - if (this->active()) [[likely]] - { - godot::Point2 mouse_pos{ this->get_global_mouse_position() }; - this->draw_circle(mouse_pos, 5, { "DARK_CYAN" }); - } - } - - void Level::activate(bool active) - { - m_active = active; - } - - bool Level::active() const - { - return m_active; - } - - [[signal_slot]] - void Level::on_physics_box_entered(godot::Node* node) const - { - console::get()->print("{} > {}", io::yellow("projectile"), to(node->get_name())); - } - - [[signal_slot]] - void Level::on_physics_box_exited(godot::Node* node) const - { - console::get()->print("{} < {}", io::red("projectile"), to(node->get_name())); - } - - [[signal_slot]] - void Level::on_player_spawn_projectile(godot::Node* obj) - { - Projectile* projectile{ m_projectile_spawner->spawn_projectile() }; - if (projectile != nullptr) - { - godot::Marker2D* firing_pt{ gdcast(obj) }; - if (firing_pt != nullptr) - { - projectile->set_position(firing_pt->get_global_position()); - projectile->set_rotation(firing_pt->get_global_rotation()); - - signal::connect(projectile) <=> - signal_callback(this, on_physics_box_entered); - - signal::connect(projectile) <=> - signal_callback(this, on_physics_box_exited); - } - - this->add_child(projectile); - } - } - - [[signal_slot]] - void Level::on_character_position_changed(const godot::Object* const node, - godot::Vector2 location) const - { - runtime_assert(node != nullptr); - auto console{ console::get() }; - console->print("{} ({},{})", io::green(to(node->get_class()) + " location: "), - io::orange(location.x), io::orange(location.y)); - } - - void Level::_bind_methods() - { - bind_member_function(Level, on_character_position_changed); - bind_member_function(Level, on_player_spawn_projectile); - bind_member_function(Level, on_physics_box_entered); - bind_member_function(Level, on_physics_box_exited); - } -} diff --git a/src/entity/level.hpp b/src/entity/level.hpp deleted file mode 100644 index 92be857..0000000 --- a/src/entity/level.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#include "core/constants.hpp" -#include "entity/character/player.hpp" -#include "entity/controller/player_controller.hpp" -#include "entity/projectile/projectile_spawner.hpp" -#include "util/bind.hpp" -#include "util/scene.hpp" - -namespace godot -{ - class RigidBody2D; -} - -namespace rl -{ - class Player; - - class Level : public godot::Node2D - { - GDCLASS(Level, godot::Node2D); - - public: - Level(); - ~Level() = default; - - virtual void _ready() override; - void _draw() override; - void _process(double delta_time) override; - - void activate(bool active = true); - bool active() const; - - protected: - static void _bind_methods(); - - [[signal_slot]] void on_physics_box_entered(godot::Node* node) const; - [[signal_slot]] void on_physics_box_exited(godot::Node* node) const; - [[signal_slot]] void on_player_spawn_projectile(godot::Node* obj); - [[signal_slot]] void on_character_position_changed(const godot::Object* const obj, - godot::Vector2 location) const; - - private: - std::atomic m_active{ false }; - godot::Node* m_background{ nullptr }; - ProjectileSpawner* m_projectile_spawner{ memnew(rl::ProjectileSpawner) }; - Player* m_player{ nullptr }; - godot::RigidBody2D* m_physics_box{ nullptr }; - }; -} diff --git a/src/entity/projectile/projectile.cpp b/src/entity/projectile/projectile.cpp deleted file mode 100644 index 0762391..0000000 --- a/src/entity/projectile/projectile.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include "entity/projectile/projectile.hpp" -#include "util/engine.hpp" - -namespace rl -{ - void Projectile::_ready() - { - m_start_pos = this->get_global_position(); - auto forward{ this->get_transform()[0].normalized() }; - this->apply_impulse(forward * m_velocity); - } - - void Projectile::_process(double delta_time) - { - if (engine::editor_active()) - return; - - m_time_to_live -= delta_time; - if (m_time_to_live <= 0) - { - this->queue_free(); - return; - } - - godot::Vector2 curr_pos{ this->get_global_position() }; - double dist_traveled{ m_start_pos.distance_squared_to(curr_pos) }; - if (dist_traveled >= m_max_travel_dist) - { - this->queue_free(); - return; - } - } - - [[property]] - double Projectile::get_movement_speed() const - { - return m_movement_speed; - } - - [[property]] - double Projectile::get_time_to_live() const - { - return m_time_to_live; - } - - [[property]] - double Projectile::get_acceleration() const - { - return m_acceleration; - } - - [[property]] - double Projectile::get_max_travel_dist() const - { - return godot::Math::sqrt(m_max_travel_dist); - } - - [[property]] - double Projectile::get_velocity() const - { - return m_velocity; - } - - [[property]] - void Projectile::set_movement_speed(double speed) - { - m_movement_speed = speed; - } - - [[property]] - void Projectile::set_time_to_live(double ttl) - { - m_time_to_live = ttl; - } - - [[property]] - void Projectile::set_acceleration(double acceleration) - { - m_acceleration = acceleration; - } - - [[property]] - void Projectile::set_max_travel_dist(double dist) - { - m_max_travel_dist = dist * dist; - } - - [[property]] - void Projectile::set_velocity(double velocity) - { - m_velocity = velocity; - } -} diff --git a/src/entity/projectile/projectile.hpp b/src/entity/projectile/projectile.hpp deleted file mode 100644 index 8b3ba07..0000000 --- a/src/entity/projectile/projectile.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include -#include - -#include "core/attributes.hpp" -#include "singletons/console.hpp" -#include "util/bind.hpp" -#include "util/conversions.hpp" -#include "util/io.hpp" - -namespace rl -{ - class Projectile : public godot::RigidBody2D - { - GDCLASS(Projectile, godot::RigidBody2D); - - public: - Projectile() = default; - virtual ~Projectile() = default; - - void _ready() override; - void _process(double delta_time) override; - - [[property]] double get_movement_speed() const; - [[property]] double get_time_to_live() const; - [[property]] double get_max_travel_dist() const; - [[property]] double get_acceleration() const; - [[property]] double get_velocity() const; - - [[property]] void set_movement_speed(double speed); - [[property]] void set_time_to_live(double ttl); - [[property]] void set_max_travel_dist(double dist); - [[property]] void set_acceleration(double acceleration); - [[property]] void set_velocity(double velocity); - - protected: - static void _bind_methods() - { - bind_member_function(Projectile, get_movement_speed); - bind_member_function(Projectile, get_time_to_live); - bind_member_function(Projectile, get_max_travel_dist); - bind_member_function(Projectile, get_acceleration); - bind_member_function(Projectile, get_velocity); - bind_member_function(Projectile, set_movement_speed); - bind_member_function(Projectile, set_time_to_live); - bind_member_function(Projectile, set_max_travel_dist); - bind_member_function(Projectile, set_acceleration); - bind_member_function(Projectile, set_velocity); - } - - protected: - godot::Vector2 m_start_pos{ 0.0, 0.0 }; - // projectile movement velocity (pixels) - double m_velocity{ 1500 }; - // projectile movement speed (pixels/s) - double m_movement_speed{ 1000.0 }; - // projectile acceleration (pixels/s/s) - double m_acceleration{ 100.0 }; - // max time duration alive (seconds) - double m_time_to_live{ 2.5 }; - // max travel distance (pixels) - uint32_t? - double m_max_travel_dist{ 1000.0 * 1000.0 }; - }; -} diff --git a/src/entity/projectile/projectile_spawner.cpp b/src/entity/projectile/projectile_spawner.cpp deleted file mode 100644 index b19e0f4..0000000 --- a/src/entity/projectile/projectile_spawner.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "entity/projectile/projectile_spawner.hpp" -#include "util/bind.hpp" - -namespace rl -{ - [[nodiscard]] - Projectile* ProjectileSpawner::spawn_projectile() - { - auto elapsed{ clock_t::now() - m_prev_spawn_time }; - if (elapsed < m_spawn_delay) - return nullptr; - else - { - Projectile* projectile{ m_scene.instantiate() }; - m_prev_spawn_time = clock_t::now(); - return projectile; - } - } - - [[property]] - double ProjectileSpawner::get_fire_rate() const - { - return m_fire_rate; - } - - [[property]] - void ProjectileSpawner::set_fire_rate(double fire_rate) - { - m_fire_rate = fire_rate; - m_spawn_delay = ProjectileSpawner::calculate_spawn_delay(m_fire_rate); - } - - ProjectileSpawner::millisec_t ProjectileSpawner::calculate_spawn_delay(double fire_rate) - { - // converts fire rate (shots per second) to the time delay between shots in ms. - // the multiplication by 100 is just to offset the rounding errors by shifting - // the decimal place to the right a few places before dividing. - return (1000ms * 100) / static_cast(fire_rate * 100); - } - - void ProjectileSpawner::_bind_methods() - { - bind_property(ProjectileSpawner, fire_rate, double); - } -} diff --git a/src/entity/projectile/projectile_spawner.hpp b/src/entity/projectile/projectile_spawner.hpp deleted file mode 100644 index 06f81eb..0000000 --- a/src/entity/projectile/projectile_spawner.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "core/constants.hpp" -#include "entity/projectile/projectile.hpp" -#include "util/bind.hpp" -#include "util/scene.hpp" - -namespace rl -{ - using namespace std::chrono_literals; - - class ProjectileSpawner : public godot::Node2D - { - GDCLASS(ProjectileSpawner, godot::Node2D); - - public: - ProjectileSpawner() = default; - ~ProjectileSpawner() = default; - - Projectile* spawn_projectile(); - - protected: - [[property]] double get_fire_rate() const; - [[property]] void set_fire_rate(double fire_rate); - - static void _bind_methods(); - - private: - using clock_t = std::chrono::high_resolution_clock; - using millisec_t = std::chrono::milliseconds; - static millisec_t calculate_spawn_delay(double fire_rate); - - private: - // number of prjectiles per second - double m_fire_rate{ 10.0 }; - // time delay between shots (ms). multiplication by 100 is just to offset rounding errors. - millisec_t m_spawn_delay{ ProjectileSpawner::calculate_spawn_delay(m_fire_rate) }; - // the time point that keeps track of when the last projectile was spawned. - clock_t::time_point m_prev_spawn_time{ clock_t::now() }; - // preloaded packed scene that will be instantiated per spawn - resource::preload::packed_scene m_scene{ path::scene::Bullet }; - }; -} diff --git a/src/main.cpp b/src/main.cpp index 46ca903..f22ba1e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,59 +1,22 @@ -#include "core/assert.hpp" #include "main.hpp" -#include "util/conversions.hpp" -#include "util/engine.hpp" -#include "util/input.hpp" -namespace rl +Main::Main() { - Main::Main() - { - resource::preload::packed_scene level{ path::scene::Level1 }; - resource::preload::packed_scene dialog{ path::ui::MainDialog }; - - m_active_level = level.instantiate(); - runtime_assert(m_active_level != nullptr); - m_main_dialog = dialog.instantiate(); - runtime_assert(m_main_dialog != nullptr); - - if (m_main_dialog != nullptr) - { - m_canvas_layer = gdcast( - m_main_dialog->find_child(name::dialog::canvas_layer, true, false)); - - runtime_assert(m_canvas_layer != nullptr); - if (m_active_level != nullptr && m_canvas_layer != nullptr) - m_canvas_layer->add_child(m_active_level); - - if (m_main_dialog != nullptr) - this->add_child(m_main_dialog); - } - } - - void Main::_ready() - { - this->apply_default_settings(); - } - - void Main::_physics_process(double delta) - { - if (engine::editor_active()) - return; - - m_signal_timer += delta; - if (m_signal_timer > 1.0) - { - this->emit_signal(event::signal_example, delta); - m_signal_timer -= 1.0; - } - } - - void Main::apply_default_settings() - { - engine::set_fps(60); - input::use_accumulated_inputs(false); - - if (not engine::editor_active()) - engine::root_window()->set_size({ 1920, 1080 }); - } + time_passed = 0.0; +} + +Main::~Main() +{ + // Required destructor implementation +} + +void Main::_bind_methods() +{ + ClassDB::bind_method(D_METHOD("_process", "delta"), &Main::_process); +} + +void Main::_process(double delta) +{ + time_passed += delta; + set_rotation(time_passed); } diff --git a/src/main.hpp b/src/main.hpp index 9c3cdaf..4f82aca 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -1,36 +1,20 @@ -#pragma once +#include -#include -#include +using namespace godot; -#include "entity/level.hpp" -#include "ui/main_dialog.hpp" - -namespace rl +class Main : public Sprite2D { - class Main : public godot::Node - { - GDCLASS(Main, godot::Node); + GDCLASS(Main, Sprite2D) // Must be in public section - public: - Main(); - ~Main() = default; +private: + double time_passed; - void _ready() override; - void _physics_process(double delta) override; +protected: + static void _bind_methods(); - protected: - void apply_default_settings(); +public: + Main(); + virtual ~Main() override; // Required for proper destruction - static void _bind_methods() - { - signal_binding::add(); - } - - private: - double m_signal_timer{ 0.0 }; - godot::CanvasLayer* m_canvas_layer{ nullptr }; - MainDialog* m_main_dialog{ nullptr }; - Level* m_active_level{ nullptr }; - }; -} + void _process(double delta) override; +}; diff --git a/src/singletons/console.hpp b/src/singletons/console.hpp deleted file mode 100644 index 5bc48cb..0000000 --- a/src/singletons/console.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace rl -{ - template - class Console : public godot::Object - { - GDCLASS(Console, godot::Object); - - public: - Console() - { - m_static_inst = this; - init_loggers(); - } - - ~Console() - { - m_static_inst = nullptr; - } - - static inline rl::Console* get() - { - return m_static_inst; - } - - void set_context(TContext* context) - { - m_gui_console = context; - } - - void clear_context() - { - m_gui_console = nullptr; - } - - void stop_logging() - { - m_logger->flush(); - m_stop = true; - } - - void init_loggers() - requires std::same_as - { - auto stdout_sink{ std::make_shared() }; - auto stderr_sink{ std::make_shared() }; - auto callbk_sink{ std::make_shared( - [this](const spdlog::details::log_msg& msg) { - if (!m_stop.load(std::memory_order_relaxed)) - { - if (m_gui_console == nullptr) - return; - - using duration_t = std::chrono::duration; - const duration_t elapsed{ clock_t::now() - m_start_time }; - - m_gui_console->append_text( - fmt::format("[color=gray]{:5} [{:>7.2}] [b]=>[/b] {}[/color]\n", - m_line_num.fetch_add(1, std::memory_order_relaxed), elapsed, - msg.payload) - .c_str()); - } - }) }; - - stderr_sink->set_level(spdlog::level::err); - stdout_sink->set_level(spdlog::level::info); - callbk_sink->set_level(spdlog::level::debug); - - m_logger = std::unique_ptr( - new spdlog::logger{ "custom_callback_logger", - { stdout_sink, stderr_sink, callbk_sink } }); - - using namespace std::chrono_literals; - spdlog::flush_every(0.25s); - } - - template - void print(fmt::format_string format_str, TArgs&&... args) - { - m_logger->info(format_str, std::forward(args)...); - } - - protected: - static void _bind_methods() - { - } - - private: - std::unique_ptr m_logger{ nullptr }; - std::atomic m_stop{ false }; - std::atomic m_line_num{ 0 }; - TContext* m_gui_console{ nullptr }; - - using clock_t = std::chrono::high_resolution_clock; - const clock_t::time_point m_start_time{ clock_t::now() }; - - private: - static inline Console* m_static_inst{ nullptr }; - }; - - using console = Console; -} diff --git a/src/ui/main_dialog.cpp b/src/ui/main_dialog.cpp deleted file mode 100644 index bd52c7b..0000000 --- a/src/ui/main_dialog.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include - -#include "core/assert.hpp" -#include "core/constants.hpp" -#include "singletons/console.hpp" -#include "ui/main_dialog.hpp" -#include "util/conversions.hpp" -#include "util/engine.hpp" - -namespace rl::inline ui -{ - void MainDialog::_ready() - { - if (engine::editor_active()) - return; - - Console* game_console{ console::get() }; - - godot::Node* root{ scene::tree::root_node(this) }; - godot::Node* label{ root->find_child(name::dialog::console, true, false) }; - godot::Node* level{ this->find_child(name::level::level1, true, false) }; - - m_level = gdcast(level); - m_console_label = gdcast(label); - - game_console->set_context(m_console_label); - } - - void MainDialog::_notification(int notification) - { - switch (notification) - { - case Object::NOTIFICATION_PREDELETE: - [[fallthrough]]; - case Node::NOTIFICATION_UNPARENTED: - { - console::get()->clear_context(); - console::get()->stop_logging(); - break; - } - case Control::NOTIFICATION_MOUSE_ENTER: - { - m_level->activate(true); - break; - } - case Control::NOTIFICATION_MOUSE_EXIT: - { - m_level->activate(false); - break; - } - } - - auto console{ console::get() }; - console->print("notification: {}", notification); - } -} diff --git a/src/ui/main_dialog.hpp b/src/ui/main_dialog.hpp deleted file mode 100644 index b21a98b..0000000 --- a/src/ui/main_dialog.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include - -#include "entity/level.hpp" - -namespace rl::inline ui -{ - class MainDialog : public godot::Panel - { - GDCLASS(MainDialog, godot::Panel); - - public: - MainDialog() = default; - ~MainDialog() = default; - - void _ready() override; - void _notification(int notification); - - static void _bind_methods() - { - } - - protected: - Level* m_level{ nullptr }; - godot::RichTextLabel* m_console_label{ nullptr }; - }; -} diff --git a/src/util/bind.hpp b/src/util/bind.hpp deleted file mode 100644 index 6a607f5..0000000 --- a/src/util/bind.hpp +++ /dev/null @@ -1,216 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "core/assert.hpp" -#include "core/concepts.hpp" -#include "core/function_traits.hpp" -#include "util/conversions.hpp" -#include "util/variant.hpp" - -#define bind_member_function(class_name, func_name) method<&class_name::func_name>::bind(#func_name) - -#define signal_callback(slot_owner, slot_callback) \ - std::forward_as_tuple(godot::Callable(slot_owner, #slot_callback), slot_owner) - -#define bind_property(class_name, prop_name, prop_type) \ - node_property::add(#prop_name) - -namespace rl::inline utils -{ - template - requires std::is_member_function_pointer_v - struct method : public function_traits - { - using traits_t = function_traits; - - static constexpr void bind(std::string_view&& func_name) - { - constexpr std::size_t tup_size = std::tuple_size_v; - if constexpr (tup_size == 0) - godot::ClassDB::bind_method(godot::D_METHOD(func_name.data()), Method); - else - { - const typename traits_t::arg_types_nocvref func_args{}; - std::apply( - [&](auto&&... args) { - godot::ClassDB::bind_method(godot::D_METHOD(func_name.data()), Method, - args...); - }, - func_args); - } - } - }; - - template - struct node_property - { - using getter_traits = function_traits; - using setter_traits = function_traits; - - static constexpr void add(std::string&& prop_name) - { - const std::string getter_name{ "get_" + prop_name }; - const std::string setter_name{ "set_" + prop_name }; - - method::bind(getter_name); - method::bind(setter_name); - - const godot::PropertyInfo property_info( - variant_traits::type_info::get_class_info().type, - godot::String(prop_name.c_str())); - - godot::ClassDB::add_property(TNode::get_class_static(), property_info, - godot::String(setter_name.c_str()), - godot::String(getter_name.c_str())); - } - }; - - template - struct callback_func : public function_traits - { - using traits_t = function_traits; - - static void bind(std::string_view&& func_name) - { - auto class_name = godot::StringName("Main"); - static constexpr std::size_t tup_size = std::tuple_size_v; - if constexpr (tup_size == 0) - godot::ClassDB::bind_static_method(class_name, godot::D_METHOD(func_name.data()), - Function); - else - { - const typename traits_t::arg_types_nocvref func_args{}; - std::vector vec_strs = rl::detail::to_arg_vec(func_args); - std::tuple arg_types_str{ detail::arg_vec_to_tuple(vec_strs) }; - - std::apply( - [&](auto&&... args) { - godot::ClassDB::bind_static_method( - class_name, godot::D_METHOD(func_name.data()), Function, args...); - }, - func_args); - } - } - }; - - template - class signal_binding - { - public: - using object_t = std::type_identity_t; - using signal_t = std::type_identity_t>; - static inline constexpr std::string_view signal_name{ SignalName }; - static inline std::vector signal_params{}; - - // even though we know what TObject is here (the class type adding the signal binding) - // we can't call TObject::get_class_static() yet since this struct is instantiated before - // the bindings library initializes the gdextension library, which will just lead to a - // crash. this will just be set with the class name at runtime when signal_binding::add() is - // invoked. - static inline std::string class_name{}; - - public: - template - struct add - { - using arg_types = std::tuple...>; - static constexpr inline size_t arg_count{ std::tuple_size_v }; - - add() - { - if (class_name.empty()) - class_name = rl::to(object_t::get_class_static()); - else - { - std::string temp_name = rl::to(object_t::get_class_static()); - runtime_assert(class_name == temp_name); - } - - if constexpr (arg_count == 0) - godot::ClassDB::add_signal(class_name.data(), - godot::MethodInfo(signal_name.data())); - else - { - arg_types signal_args{}; - - std::apply( - [&](auto&&... arg) { - signal_params = { - variant_traits::type_info::get_class_info()... - }; - }, - signal_args); - - godot::ClassDB::add_signal( - class_name.data(), - godot::MethodInfo(signal_name.data(), - std::forward(signal_params))); - } - - runtime_assert(signal_params.size() == arg_count); - } - }; - }; - - template - struct signal - { - public: - static inline constexpr std::string_view signal_name{ SignalName }; - - public: - template - struct connect - { - private: - static inline TOwnerObj* m_signal_owner{ nullptr }; - - public: - explicit connect(TOwnerObj* signal_owner) - { - static_assert(std::is_same_v); - - m_signal_owner = signal_owner; - const std::string class_name = rl::to(m_signal_owner->get_class()); - runtime_assert(m_signal_owner->has_signal(signal_name.data())); - } - - template - auto operator<=>(std::tuple callback) - { - auto&& cb{ std::forward(std::get<0>(callback)) }; - auto&& callback_owner{ std::get<1>(callback) }; - - if (m_signal_owner == nullptr) - { - error_msg("Attempting to connect a signal to a null object"); - return godot::Error::ERR_DOES_NOT_EXIST; - } - - if (!callback_owner->has_method(cb.get_method())) - { - error_msg("Signal connection method missing bindings"); - return godot::Error::ERR_METHOD_NOT_FOUND; - } - - // TODO: compare and validate the arg count, raw types, and variant conversions - // between the matching signal binding record and the callback being connected. - return m_signal_owner->connect(signal_name.data(), cb); - } - }; - }; -} diff --git a/src/util/conversions.hpp b/src/util/conversions.hpp deleted file mode 100644 index 790df1f..0000000 --- a/src/util/conversions.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "core/assert.hpp" - -namespace rl::inline utils -{ - /** Converts std string types to godot::String at compile time */ - template - struct gd_str_conv - { - explicit constexpr gd_str_conv(TStr&& s) - : m_str{ std::forward(s) } - { - } - - explicit operator godot::String() - requires std::same_as - { - return godot::String(m_str.c_str()); - } - - explicit operator godot::String() - requires std::same_as - { - return godot::String(m_str.data()); - } - - TStr m_str{}; - }; - - template - requires std::derived_from, godot::Object> - constexpr inline TOut* gdcast(TIn* obj) - { - runtime_assert(obj != nullptr); - auto ret{ godot::Object::cast_to(obj) }; - runtime_assert(ret != nullptr); - return ret; - } - - template - inline auto to(const auto& in) -> TOut - { - return TOut(in); - } - - template <> - inline auto to(const godot::String& in) -> std::string - { - static_assert(std::is_same_v>); - return std::string(in.ascii().ptr()); - } - - template <> - inline auto to(const godot::StringName& in) -> std::string - { - static_assert(std::is_same_v>); - godot::String tmp(in); - return std::string(tmp.utf8().ptr()); - } -} diff --git a/src/util/debug.hpp b/src/util/debug.hpp deleted file mode 100644 index 40c5dbc..0000000 --- a/src/util/debug.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -namespace rl::inline utils -{ - namespace diag - { - enum Option : uint_fast8_t { - RootProcess, - RootPhysics, - RootViewport, - RootInputs, - LevelProcess, - LevelLoad, - LevelUnload, - MainMenuInit, - All - }; - - using optval_t = std::pair; - static constexpr inline auto DebugSettings{ - std::to_array>({ - { Option::All, false }, - { Option::RootProcess, true }, - { Option::RootPhysics, true }, - { Option::RootViewport, true }, - { Option::RootInputs, true }, - { Option::LevelProcess, true }, - { Option::LevelLoad, true }, - { Option::LevelUnload, true }, - { Option::MainMenuInit, true }, - }), - }; - - static constexpr inline bool is_enabled(const Option& diag_type) - { - for (auto&& [opt, val] : DebugSettings) - { - if (opt == Option::All && val) - return true; - if (opt == diag_type) - return val; - } - return false; - } - } -} diff --git a/src/util/engine.cpp b/src/util/engine.cpp deleted file mode 100644 index 9db3e07..0000000 --- a/src/util/engine.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include - -#include "util/engine.hpp" - -namespace rl::inline utils -{ - godot::Engine* engine::get() - { - godot::Engine* engine{ godot::Engine::get_singleton() }; - return engine; - } - - godot::MainLoop* engine::main_loop() - { - auto engine{ engine::get() }; - return engine->get_main_loop(); - } - - godot::SceneTree* engine::scene_tree() - { - auto loop{ engine::main_loop() }; - return ::godot::Object::cast_to(loop); - } - - godot::Window* engine::root_window() - { - auto tree{ engine::scene_tree() }; - return tree->get_root(); - } - - godot::Node* engine::root_node() - { - return godot::Object::cast_to(engine::root_window()); - } - - void engine::set_fps(const uint32_t fps) - { - auto engine{ engine::get() }; - return engine->set_max_fps(fps); - } - - int32_t engine::max_fps() - { - auto engine{ engine::get() }; - return engine->get_max_fps(); - } - - bool engine::editor_active() - { - auto engine{ engine::get() }; - return engine->is_editor_hint(); - } -} diff --git a/src/util/engine.hpp b/src/util/engine.hpp deleted file mode 100644 index 303f44c..0000000 --- a/src/util/engine.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -namespace godot -{ - class Engine; - class MainLoop; - class Node; - class SceneTree; - class Window; -} - -namespace rl::inline utils -{ - struct engine - { - static godot::Engine* get(); - static godot::MainLoop* main_loop(); - static godot::SceneTree* scene_tree(); - static godot::Window* root_window(); - static godot::Node* root_node(); - static void set_fps(const uint32_t fps); - static int32_t max_fps(); - static bool editor_active(); - }; -} diff --git a/src/util/input.cpp b/src/util/input.cpp deleted file mode 100644 index 5faeade..0000000 --- a/src/util/input.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include - -#include "util/input.hpp" - -namespace rl::inline utils -{ - godot::InputMap* input::map::get() - { - godot::InputMap* mappings{ godot::InputMap::get_singleton() }; - return mappings; - } - - godot::Input* input::get() - { - godot::Input* input{ godot::Input::get_singleton() }; - return input; - } - - void input::hide_cursor() - { - godot::Input* const input{ input::get() }; - input->set_mouse_mode(godot::Input::MOUSE_MODE_HIDDEN); - } - - void input::show_cursor() - { - godot::Input* const input{ input::get() }; - input->set_mouse_mode(godot::Input::MOUSE_MODE_VISIBLE); - } - - bool input::cursor_visible() - { - godot::Input* const input{ input::get() }; - return input->get_mouse_mode() == godot::Input::MOUSE_MODE_VISIBLE; - } - - void input::load_project_inputs() - { - auto input_map{ godot::InputMap::get_singleton() }; - return input_map->load_from_project_settings(); - } - - void input::use_accumulated_inputs(bool enable) - { - auto input{ godot::Input::get_singleton() }; - return input->set_use_accumulated_input(enable); - } -} diff --git a/src/util/input.hpp b/src/util/input.hpp deleted file mode 100644 index e0b74ce..0000000 --- a/src/util/input.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -namespace godot -{ - class InputMap; - class Input; -} - -namespace rl::inline utils -{ - namespace input - { - namespace action - { - constexpr inline auto move_left{ "move_left" }; - constexpr inline auto move_right{ "move_right" }; - constexpr inline auto move_up{ "move_up" }; - constexpr inline auto move_down{ "move_down" }; - constexpr inline auto shoot{ "shoot" }; - } - - struct map - { - static godot::InputMap* get(); - }; - - godot::Input* get(); - - void hide_cursor(); - void show_cursor(); - bool cursor_visible(); - void load_project_inputs(); - void use_accumulated_inputs(bool enable); - }; -} diff --git a/src/util/io.hpp b/src/util/io.hpp deleted file mode 100644 index da0b3b0..0000000 --- a/src/util/io.hpp +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "core/concepts.hpp" - -namespace rl::inline utils -{ - namespace io - { - static inline auto white(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=white]{}[/color]"), - std::forward(val)); - } - - static inline auto gray(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=gray]{}[/color]"), - std::forward(val)); - } - - static inline auto black(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=black]{}[/color]"), - std::forward(val)); - } - - static inline auto red(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=red]{}[/color]"), - std::forward(val)); - } - - static inline auto orange(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=orange]{}[/color]"), - std::forward(val)); - } - - static inline auto yellow(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=yellow]{}[/color]"), - std::forward(val)); - } - - static inline auto green(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=green]{}[/color]"), - std::forward(val)); - } - - static inline auto blue(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=blue]{}[/color]"), - std::forward(val)); - } - - static inline auto purple(auto&& val) - { - return fmt::format(FMT_COMPILE("[color=purple]{}[/color]"), - std::forward(val)); - } - - } - - struct log - { - enum DetailLevel : uint_fast8_t { - None, - Error, - Warning, - Info, - Debug, - Trace - }; - - static constexpr const DetailLevel DETAIL_LEVEL{ log::DetailLevel::Debug }; - - static constexpr inline bool level_active(const log::DetailLevel level) - { - return level <= log::DETAIL_LEVEL; - } - - template - static inline void error(TString msg) - { - if (log::level_active(log::DetailLevel::Error)) - ERR_PRINT_ED(std::forward(msg)); - } - - template - static inline void warning(TString msg) - { - if (log::level_active(log::DetailLevel::Warning)) - WARN_PRINT_ED(std::forward(msg)); - } - - template - static inline void info(TString msg) - { - if (log::level_active(log::DetailLevel::Info)) - WARN_PRINT_ED(std::forward(msg)); - } - - template - static inline void trace(TString msg) - { - if (log::level_active(log::DetailLevel::Trace)) - WARN_PRINT_ED(std::forward(msg)); - } - - template - static inline void print(spdlog::format_string_t fmt, Args&&... args) - { - std::string msg{ fmt::format(fmt, std::forward(args)...) }; - ERR_PRINT_ED(msg.data()); - } - }; -} diff --git a/src/util/os.hpp b/src/util/os.hpp deleted file mode 100644 index daf27b4..0000000 --- a/src/util/os.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -namespace rl::inline utils -{ - struct os - { - static inline godot::OS* get() - { - return godot::OS::get_singleton(); - } - }; -} diff --git a/src/util/scene.hpp b/src/util/scene.hpp deleted file mode 100644 index f4efd4f..0000000 --- a/src/util/scene.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -#include "core/assert.hpp" -#include "util/conversions.hpp" - -namespace rl::inline utils -{ - namespace scene - { - namespace node - { - template - requires std::derived_from - static inline void set_unique_name(TNode* node, const char* name) - { - runtime_assert(node != nullptr); - node->set_name(name); - node->set_unique_name_in_owner(true); - } - - /** Sets the owner of a node and all it's children. */ - template - requires std::derived_from && - std::derived_from - static inline void set_owner(TNodeA* node, TNodeB* owner) - { - runtime_assert(node != nullptr && owner != nullptr); - const int node_child_count = node->get_child_count(); - for (int i = 0; i < node_child_count; ++i) - { - auto child = node->get_child(i); - child->set_owner(owner); - set_owner(child, owner); - } - } - } - - namespace tree - { - template - requires std::derived_from - static inline godot::SceneTree* get(TNode* node) - { - godot::SceneTree* scene_tree{ node->get_tree() }; - return scene_tree; - } - - template - requires std::derived_from - static inline godot::Node* edited_root(TNode* node) - { - godot::Node* edited_root{ node->get_tree()->get_edited_scene_root() }; - return edited_root; - } - - template - requires std::derived_from - static inline godot::Node* root_node(TNode* node) - { - godot::SceneTree* scene_tree{ tree::get(node) }; - godot::Window* root_window{ scene_tree->get_root() }; - godot::Node* root_node{ gdcast(root_window) }; - return root_node; - } - } - - namespace packer - { - /** - @return PackedScene from godot::Node parameter. - */ - template - requires std::derived_from - static inline godot::PackedScene* pack(TNode* node) - { - node::set_owner(node, node); - godot::PackedScene* package = memnew(godot::PackedScene); - package->pack(node); - return package; - } - } - } - - namespace resource - { - namespace loader - { - static inline godot::ResourceLoader* get() - { - return godot::ResourceLoader::get_singleton(); - } - } - - namespace saver - { - static inline godot::ResourceSaver* get() - { - return godot::ResourceSaver::get_singleton(); - } - } - - namespace preload - { - template - requires std::derived_from && - std::convertible_to - class packed_scene - { - public: - using scene_t = TScene; - using object_t = TObj; - - /** Load and pack from path. */ - packed_scene(const godot::String& load_resource_path, - const godot::String& load_type_hint = godot::String(), - godot::ResourceLoader::CacheMode load_cache_mode = - godot::ResourceLoader::CacheMode::CACHE_MODE_REUSE) - { - godot::ResourceLoader* resource_loader{ loader::get() }; - - bool resource_exists{ resource_loader->exists(load_resource_path) }; - runtime_assert(resource_exists); - - if (resource_exists) - { - m_packed_resource = resource_loader->load(load_resource_path, - load_type_hint, load_cache_mode); - initialized = m_packed_resource.is_valid(); - } - } - - /* Pack from existing instance. */ - packed_scene(godot::Node* node) - { - m_packed_resource = scene::packer::pack(node); - initialized = m_packed_resource.is_valid(); - } - - [[nodiscard]] auto instantiate() -> object_t* - { - assertion(initialized, - "Resource instantiation invoked from uninitialized scene loader."); - if (!initialized) [[unlikely]] - return nullptr; - - object_t* obj{ gdcast(m_packed_resource->instantiate()) }; - runtime_assert(obj != nullptr); - - return obj; - } - - /** Save this resource to specified path. */ - void save(godot::String& resource_save_path) - { - if (initialized) - { - auto error = saver::get()->save(m_packed_resource, resource_save_path); - assertion(error != godot::Error::OK, "Packed resource save failed."); - } - } - - private: - godot::Ref m_packed_resource{}; - bool initialized{ false }; - }; - } - } -} diff --git a/src/util/variant.hpp b/src/util/variant.hpp deleted file mode 100644 index 4d60634..0000000 --- a/src/util/variant.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "core/concepts.hpp" - -namespace rl::inline utils -{ - template - struct variant_traits - { - using raw_type = T; - using type_info = godot::GetTypeInfo>; - static constexpr inline godot::Variant::Type variant_type = - static_cast(type_info::VARIANT_TYPE); - }; -}