feat: swapped from godot:: to utils:: namespace

main
Sara 2024-05-28 16:28:36 +02:00
parent 54fcbcbb6b
commit 3cad3af3fe
17 changed files with 222 additions and 229 deletions

View File

@ -5,25 +5,25 @@
#include "utils/godot_macros.h" #include "utils/godot_macros.h"
#include "game_state.hpp" #include "game_state.hpp"
namespace godot { namespace utils {
void GameMode::_bind_methods() { void GameMode::_bind_methods() {
#define CLASSNAME GameMode #define CLASSNAME GameMode
GDPROPERTY_HINTED(game_state, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameState"); GDPROPERTY_HINTED(game_state, gd::Variant::OBJECT, gd::PROPERTY_HINT_RESOURCE_TYPE, "GameState");
GDPROPERTY_HINTED(player_scene, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"); GDPROPERTY_HINTED(player_scene, gd::Variant::OBJECT, gd::PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
} }
void GameMode::_begin() {} void GameMode::_begin() {}
void GameMode::_end() {} void GameMode::_end() {}
void GameMode::set_player_scene(Ref<PackedScene> scene) { void GameMode::set_player_scene(gd::Ref<gd::PackedScene> scene) {
this->player_scene = scene; this->player_scene = scene;
} }
Ref<PackedScene> GameMode::get_player_scene() const { gd::Ref<gd::PackedScene> GameMode::get_player_scene() const {
return this->player_scene; return this->player_scene;
} }
void GameMode::set_game_state(Ref<GameState> state) { void GameMode::set_game_state(gd::Ref<GameState> state) {
if(state.is_null() || !state.is_valid()) { if(state.is_null() || !state.is_valid()) {
this->game_state.unref(); this->game_state.unref();
return; return;
@ -31,7 +31,7 @@ void GameMode::set_game_state(Ref<GameState> state) {
this->game_state = state; this->game_state = state;
} }
Ref<GameState> GameMode::get_game_state() { gd::Ref<GameState> GameMode::get_game_state() {
return this->game_state; return this->game_state;
} }
} }

View File

@ -1,26 +1,28 @@
#ifndef GAME_MODE_H #ifndef GAME_MODE_HPP
#define GAME_MODE_H #define GAME_MODE_HPP
#include <godot_cpp/classes/packed_scene.hpp> #include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/resource.hpp> #include <godot_cpp/classes/resource.hpp>
#include "game_state.hpp" #include "game_state.hpp"
namespace godot { namespace gd = godot;
class GameMode : public Resource {
GDCLASS(GameMode, Resource); namespace utils {
class GameMode : public gd::Resource {
GDCLASS(GameMode, gd::Resource);
static void _bind_methods(); static void _bind_methods();
public: public:
virtual void _begin(); virtual void _begin();
virtual void _end(); virtual void _end();
void set_player_scene(Ref<PackedScene> scene); void set_player_scene(gd::Ref<gd::PackedScene> scene);
Ref<PackedScene> get_player_scene() const; gd::Ref<gd::PackedScene> get_player_scene() const;
void set_game_state(Ref<GameState> state); void set_game_state(gd::Ref<GameState> state);
Ref<GameState> get_game_state(); gd::Ref<GameState> get_game_state();
private: private:
Ref<PackedScene> player_scene{}; gd::Ref<gd::PackedScene> player_scene{};
Ref<GameState> game_state{}; gd::Ref<GameState> game_state{};
}; };
} }
#endif // !GAME_MODE_H #endif // !GAME_MODE_HPP

View File

@ -4,6 +4,7 @@
#include "level.hpp" #include "level.hpp"
#include "player.hpp" #include "player.hpp"
#include "player_input.hpp" #include "player_input.hpp"
#include "player.hpp"
#include "spawn_point.hpp" #include "spawn_point.hpp"
#include <cstdint> #include <cstdint>
#include <godot_cpp/classes/global_constants.hpp> #include <godot_cpp/classes/global_constants.hpp>
@ -15,14 +16,14 @@
#include <godot_cpp/variant/string_name.hpp> #include <godot_cpp/variant/string_name.hpp>
#include <godot_cpp/variant/utility_functions.hpp> #include <godot_cpp/variant/utility_functions.hpp>
namespace godot { namespace utils {
void GameRoot3D::_bind_methods() { void GameRoot3D::_bind_methods() {
#define CLASSNAME GameRoot3D #define CLASSNAME GameRoot3D
GDFUNCTION(reset_game_mode); GDFUNCTION(reset_game_mode);
GDPROPERTY_HINTED(first_boot_level, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"); GDPROPERTY_HINTED(first_boot_level, gd::Variant::OBJECT, gd::PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
GDSIGNAL("player_connected", PropertyInfo(Variant::OBJECT, "player_input", PROPERTY_HINT_NODE_TYPE, "PlayerInput")); GDSIGNAL("player_connected", gd::PropertyInfo(gd::Variant::OBJECT, "player_input", gd::PROPERTY_HINT_NODE_TYPE, "PlayerInput"));
GDSIGNAL("player_disconnected", PropertyInfo(Variant::OBJECT, "player_input", PROPERTY_HINT_NODE_TYPE, "PlayerInput")); GDSIGNAL("player_disconnected", gd::PropertyInfo(gd::Variant::OBJECT, "player_input", gd::PROPERTY_HINT_NODE_TYPE, "PlayerInput"));
GDSIGNAL("player_spawned", PropertyInfo(Variant::OBJECT, "player_info", PROPERTY_HINT_NODE_TYPE, "Node")); GDSIGNAL("player_spawned", gd::PropertyInfo(gd::Variant::OBJECT, "player_info", gd::PROPERTY_HINT_NODE_TYPE, "Node"));
} }
GameRoot3D *GameRoot3D::get_singleton() { GameRoot3D *GameRoot3D::get_singleton() {
@ -53,16 +54,16 @@ void GameRoot3D::player_input_connected() {
PlayerInput *input = memnew(PlayerInput); PlayerInput *input = memnew(PlayerInput);
this->add_child(input); this->add_child(input);
this->players.insert(this->next_player_id++, {input, nullptr}); this->players.insert(this->next_player_id++, {input, nullptr});
this->emit_signal(StringName("player_connected"), input); this->emit_signal(gd::StringName("player_connected"), input);
} }
void GameRoot3D::remove_player(uint32_t player_id) { void GameRoot3D::remove_player(uint32_t player_id) {
if(!this->players.has(player_id)) if(!this->players.has(player_id))
return; return;
// convert player object to node // convert player object to node
Node *node = this->players.get(player_id).second->to_node(); gd::Node *node = this->players.get(player_id).second->to_node();
if(node == nullptr) { if(node == nullptr) {
UtilityFunctions::push_error("IPlayer::to_node failed for player with id '", player_id, "'"); gd::UtilityFunctions::push_error("IPlayer::to_node failed for player with id '", player_id, "'");
return; return;
} }
node->queue_free(); node->queue_free();
@ -71,7 +72,7 @@ void GameRoot3D::remove_player(uint32_t player_id) {
void GameRoot3D::remove_all_players() { void GameRoot3D::remove_all_players() {
// free all player instances in use // free all player instances in use
for(KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> &pair : this->players) { for(gd::KeyValue<uint32_t, gd::Pair<PlayerInput*, IPlayer*>> &pair : this->players) {
// skip unused player slots // skip unused player slots
if(pair.value.second == nullptr) if(pair.value.second == nullptr)
continue; continue;
@ -84,7 +85,7 @@ bool GameRoot3D::initialize_player(IPlayer *player, uint32_t id) {
if(!this->players.has(id)) if(!this->players.has(id))
return false; return false;
// register the player // register the player
Pair<PlayerInput*, IPlayer*> &found{this->players.get(id)}; gd::Pair<PlayerInput*, IPlayer*> &found{this->players.get(id)};
found.second = player; found.second = player;
// set player id // set player id
player->player_id = id; player->player_id = id;
@ -95,20 +96,20 @@ bool GameRoot3D::initialize_player(IPlayer *player, uint32_t id) {
} }
void GameRoot3D::reset_game_mode() { void GameRoot3D::reset_game_mode() {
this->set_game_mode(Ref<GameMode>()); this->set_game_mode(gd::Ref<GameMode>());
} }
Level3D *GameRoot3D::load_level(Ref<PackedScene> level) { Level3D *GameRoot3D::load_level(gd::Ref<gd::PackedScene> level) {
return this->load_level_at(level, Transform3D()); return this->load_level_at(level, gd::Transform3D());
} }
Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) { Level3D *GameRoot3D::load_level_at(gd::Ref<gd::PackedScene> level, gd::Transform3D at) {
if(!GameRoot3D::is_valid_level(level)) { if(!GameRoot3D::is_valid_level(level)) {
return nullptr; return nullptr;
} }
Level3D *instance = Object::cast_to<Level3D>(level->instantiate()); Level3D *instance = Object::cast_to<Level3D>(level->instantiate());
if(instance == nullptr) { if(instance == nullptr) {
UtilityFunctions::push_error("Unexpected failure to instantiate level scene '", level->get_path(), "'."); gd::UtilityFunctions::push_error("Unexpected failure to instantiate level scene '", level->get_path(), "'.");
return nullptr; return nullptr;
} }
this->levels.insert(level->get_path(), instance); this->levels.insert(level->get_path(), instance);
@ -122,7 +123,7 @@ Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
this->add_child(instance); this->add_child(instance);
instance->set_global_transform(at); instance->set_global_transform(at);
if(switch_game_mode && this->game_mode.is_valid()) { if(switch_game_mode && this->game_mode.is_valid()) {
for(KeyValue<uint32_t, Pair<PlayerInput *, IPlayer *>> const &kvp : this->players) { for(gd::KeyValue<uint32_t, gd::Pair<PlayerInput *, IPlayer *>> const &kvp : this->players) {
this->place_player_at_spawnpoint(kvp.value.second); this->place_player_at_spawnpoint(kvp.value.second);
} }
} }
@ -130,21 +131,21 @@ Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
} }
void GameRoot3D::unload_all_levels() { void GameRoot3D::unload_all_levels() {
HashMap<StringName, Level3D*> levels = this->get_levels(); gd::HashMap<gd::StringName, Level3D*> levels = this->get_levels();
for(KeyValue<StringName, Level3D*> &kvp : levels) for(gd::KeyValue<gd::StringName, Level3D*> &kvp : levels)
kvp.value->call_deferred("queue_free"); kvp.value->call_deferred("queue_free");
this->get_levels().clear(); this->get_levels().clear();
this->reset_game_mode(); this->reset_game_mode();
} }
void GameRoot3D::replace_levels(Ref<PackedScene> scene) { void GameRoot3D::replace_levels(gd::Ref<gd::PackedScene> scene) {
this->unload_all_levels(); this->unload_all_levels();
this->load_level(scene); this->load_level(scene);
} }
void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) { void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) {
if(this->spawn_points.has(spawn_point)) { if(this->spawn_points.has(spawn_point)) {
UtilityFunctions::push_error("Duplicate attempt to register spawnpoint '", spawn_point->get_path(), "'"); gd::UtilityFunctions::push_error("Duplicate attempt to register spawnpoint '", spawn_point->get_path(), "'");
return; return;
} }
if(!this->spawn_points.has(spawn_point)) if(!this->spawn_points.has(spawn_point))
@ -153,7 +154,7 @@ void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) {
void GameRoot3D::unregister_spawn_point(SpawnPoint3D *spawn_point) { void GameRoot3D::unregister_spawn_point(SpawnPoint3D *spawn_point) {
if(!this->spawn_points.has(spawn_point)) { if(!this->spawn_points.has(spawn_point)) {
UtilityFunctions::push_error("Attempt to unregister spawnpoint '", spawn_point->get_path(), "', which is not registered."); gd::UtilityFunctions::push_error("Attempt to unregister spawnpoint '", spawn_point->get_path(), "', which is not registered.");
return; return;
} }
this->spawn_points.erase(spawn_point); this->spawn_points.erase(spawn_point);
@ -166,12 +167,12 @@ void GameRoot3D::place_player_at_spawnpoint(IPlayer *player) {
} }
void GameRoot3D::player_despawned(uint32_t id) { void GameRoot3D::player_despawned(uint32_t id) {
Pair<PlayerInput*, IPlayer*> &pair = this->players.get(id); gd::Pair<PlayerInput*, IPlayer*> &pair = this->players.get(id);
pair.second = nullptr; pair.second = nullptr;
pair.first->clear_listeners(); pair.first->clear_listeners();
} }
void GameRoot3D::set_game_mode(Ref<GameMode> prototype) { void GameRoot3D::set_game_mode(gd::Ref<GameMode> prototype) {
this->remove_all_players(); this->remove_all_players();
// allow "unsetting" the gamemode by passing an invalid gamemode // allow "unsetting" the gamemode by passing an invalid gamemode
// shorthand for this behaviour is reset_game_mode // shorthand for this behaviour is reset_game_mode
@ -197,33 +198,33 @@ void GameRoot3D::set_game_mode(Ref<GameMode> prototype) {
} }
} }
Ref<GameMode> GameRoot3D::get_game_mode() const { gd::Ref<GameMode> GameRoot3D::get_game_mode() const {
return this->game_mode; return this->game_mode;
} }
Ref<GameState> GameRoot3D::get_game_state() const { gd::Ref<GameState> GameRoot3D::get_game_state() const {
return this->game_mode->get_game_state(); return this->game_mode->get_game_state();
} }
void GameRoot3D::set_first_boot_level(Ref<PackedScene> level) { void GameRoot3D::set_first_boot_level(gd::Ref<gd::PackedScene> level) {
if(level.is_null() || !level.is_valid()) { if(level.is_null() || !level.is_valid()) {
this->first_boot_level.unref(); this->first_boot_level.unref();
return; return;
} }
StringName const root_type = level->get_state()->get_node_type(0); gd::StringName const root_type = level->get_state()->get_node_type(0);
if(!ClassDB::is_parent_class(root_type, "Level3D")) { if(!gd::ClassDB::is_parent_class(root_type, "Level3D")) {
UtilityFunctions::push_error("First boot level cannot be of type '", root_type, "'. First boot level has to inherit from Level3D"); gd::UtilityFunctions::push_error("First boot level cannot be of type '", root_type, "'. First boot level has to inherit from Level3D");
this->first_boot_level.unref(); this->first_boot_level.unref();
return; return;
} }
this->first_boot_level = level; this->first_boot_level = level;
} }
Ref<PackedScene> GameRoot3D::get_first_boot_level() const { gd::Ref<gd::PackedScene> GameRoot3D::get_first_boot_level() const {
return this->first_boot_level; return this->first_boot_level;
} }
HashMap<StringName, Level3D *> &GameRoot3D::get_levels() { gd::HashMap<gd::StringName, Level3D *> &GameRoot3D::get_levels() {
return this->levels; return this->levels;
} }
@ -231,9 +232,9 @@ IPlayer *GameRoot3D::get_player(uint32_t id) {
return this->players[id].second; return this->players[id].second;
} }
Vector<IPlayer*> GameRoot3D::get_players() { gd::Vector<IPlayer*> GameRoot3D::get_players() {
Vector<IPlayer*> players{}; gd::Vector<IPlayer*> players{};
for(KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> pair : this->players) { for(gd::KeyValue<uint32_t, gd::Pair<PlayerInput*, IPlayer*>> pair : this->players) {
players.push_back(pair.value.second); players.push_back(pair.value.second);
} }
return players; return players;
@ -242,7 +243,7 @@ Vector<IPlayer*> GameRoot3D::get_players() {
void GameRoot3D::grab_singleton() { void GameRoot3D::grab_singleton() {
if(GameRoot3D::has_singleton()) { if(GameRoot3D::has_singleton()) {
this->set_process_mode(PROCESS_MODE_DISABLED); this->set_process_mode(PROCESS_MODE_DISABLED);
UtilityFunctions::push_error("More than one GameRoot instance active"); gd::UtilityFunctions::push_error("More than one GameRoot instance active");
} else { } else {
GameRoot3D::singleton_instance = this; GameRoot3D::singleton_instance = this;
} }
@ -252,12 +253,12 @@ void GameRoot3D::release_singleton() {
if(GameRoot3D::singleton_instance == this) { if(GameRoot3D::singleton_instance == this) {
GameRoot3D::singleton_instance = nullptr; GameRoot3D::singleton_instance = nullptr;
} else { } else {
UtilityFunctions::push_error("GameRoot instance attempted to release singleton while it is not the singleton instance"); gd::UtilityFunctions::push_error("GameRoot instance attempted to release singleton while it is not the singleton instance");
} }
} }
uint32_t GameRoot3D::find_empty_player_slot() const { uint32_t GameRoot3D::find_empty_player_slot() const {
for(KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> const &kvp : this->players) { for(gd::KeyValue<uint32_t, gd::Pair<PlayerInput*, IPlayer*>> const &kvp : this->players) {
if(kvp.value.second == nullptr) { if(kvp.value.second == nullptr) {
return kvp.key; return kvp.key;
} }
@ -267,17 +268,17 @@ uint32_t GameRoot3D::find_empty_player_slot() const {
IPlayer *GameRoot3D::spawn_player(uint32_t id) { IPlayer *GameRoot3D::spawn_player(uint32_t id) {
if(id == 0) { if(id == 0) {
UtilityFunctions::push_error("Failed to find any valid player slot when spawning player"); gd::UtilityFunctions::push_error("Failed to find any valid player slot when spawning player");
return nullptr; return nullptr;
} }
Node *player_node = this->game_mode->get_player_scene()->instantiate(); Node *player_node = this->game_mode->get_player_scene()->instantiate();
if(player_node == nullptr) { if(player_node == nullptr) {
UtilityFunctions::push_error("Failed to instantiate player scene '", this->game_mode->get_player_scene()->get_path(), "'"); gd::UtilityFunctions::push_error("Failed to instantiate player scene '", this->game_mode->get_player_scene()->get_path(), "'");
return nullptr; return nullptr;
} }
IPlayer *player = dynamic_cast<IPlayer*>(player_node); IPlayer *player = dynamic_cast<IPlayer*>(player_node);
if(player == nullptr) { if(player == nullptr) {
UtilityFunctions::push_error("Player scene does not implement required IPlayer interface"); gd::UtilityFunctions::push_error("Player scene does not implement required IPlayer interface");
player_node->queue_free(); player_node->queue_free();
return nullptr; return nullptr;
} }
@ -285,18 +286,18 @@ IPlayer *GameRoot3D::spawn_player(uint32_t id) {
return player; return player;
} }
void GameRoot3D::level_unloaded(StringName scene_path) { void GameRoot3D::level_unloaded(gd::StringName scene_path) {
this->levels.erase(scene_path); this->levels.erase(scene_path);
} }
bool GameRoot3D::is_valid_level(Ref<PackedScene> &level) { bool GameRoot3D::is_valid_level(gd::Ref<gd::PackedScene> &level) {
if(level.is_null() || !level.is_valid() || !level->can_instantiate()) { if(level.is_null() || !level.is_valid() || !level->can_instantiate()) {
UtilityFunctions::push_error("Can't load level from invalid packed scene"); gd::UtilityFunctions::push_error("Can't load level from invalid packed scene");
return false; return false;
} }
StringName const root_type = level->get_state()->get_node_type(0); gd::StringName const root_type = level->get_state()->get_node_type(0);
if(!ClassDB::is_parent_class(root_type, "Level3D")) { if(!gd::ClassDB::is_parent_class(root_type, "Level3D")) {
UtilityFunctions::push_error("Can't load level with root type '", root_type, "'. Root node has to be of type Level3D"); gd::UtilityFunctions::push_error("Can't load level with root type '", root_type, "'. Root node has to be of type Level3D");
return false; return false;
} }
return true; return true;

View File

@ -2,23 +2,25 @@
#define GAME_ROOT_HPP #define GAME_ROOT_HPP
#include "game_mode.hpp" #include "game_mode.hpp"
#include "godot_cpp/classes/random_number_generator.hpp"
#include "level.hpp" #include "level.hpp"
#include <godot_cpp/classes/node.hpp> #include <godot_cpp/classes/node.hpp>
#include <godot_cpp/classes/packed_scene.hpp> #include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/random_number_generator.hpp>
#include <godot_cpp/templates/hash_map.hpp> #include <godot_cpp/templates/hash_map.hpp>
#include <godot_cpp/templates/hash_set.hpp> #include <godot_cpp/templates/hash_set.hpp>
#include <godot_cpp/templates/pair.hpp> #include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/templates/pair.hpp> #include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/templates/vector.hpp> #include <godot_cpp/templates/vector.hpp>
namespace godot { namespace gd = godot;
namespace utils {
class PlayerInput; class PlayerInput;
class IPlayer; class IPlayer;
class SpawnPoint3D; class SpawnPoint3D;
class GameRoot3D : public Node { class GameRoot3D : public gd::Node {
GDCLASS(GameRoot3D, Node); GDCLASS(GameRoot3D, gd::Node);
static void _bind_methods(); static void _bind_methods();
public: public:
// get the current active singleton instance of GameRoot // get the current active singleton instance of GameRoot
@ -46,12 +48,12 @@ public:
void reset_game_mode(); void reset_game_mode();
// shorthand for load_level(level, Transform3D()) // shorthand for load_level(level, Transform3D())
Level3D *load_level(Ref<PackedScene> level); Level3D *load_level(gd::Ref<gd::PackedScene> level);
// load a level, only works if 'level' is a valid scene where the root Node can cast to 'Level3D' // load a level, only works if 'level' is a valid scene where the root Node can cast to 'Level3D'
// sets the level's root node's global transform // sets the level's root node's global transform
Level3D *load_level_at(Ref<PackedScene> level, Transform3D at); Level3D *load_level_at(gd::Ref<gd::PackedScene> level, gd::Transform3D at);
void unload_all_levels(); void unload_all_levels();
void replace_levels(Ref<PackedScene> level); void replace_levels(gd::Ref<gd::PackedScene> level);
// register a spawnpoint for use when spawning players // register a spawnpoint for use when spawning players
void register_spawn_point(SpawnPoint3D *spawn_point); void register_spawn_point(SpawnPoint3D *spawn_point);
@ -63,14 +65,14 @@ public:
// ----- getter / setters ----- // ----- getter / setters -----
// override the current gamemode // override the current gamemode
// force-respawns all players // force-respawns all players
void set_game_mode(Ref<GameMode> prototype); void set_game_mode(gd::Ref<GameMode> prototype);
Ref<GameMode> get_game_mode() const; gd::Ref<GameMode> get_game_mode() const;
Ref<GameState> get_game_state() const; gd::Ref<GameState> get_game_state() const;
void set_first_boot_level(Ref<PackedScene> level); void set_first_boot_level(gd::Ref<gd::PackedScene> level);
Ref<PackedScene> get_first_boot_level() const; gd::Ref<gd::PackedScene> get_first_boot_level() const;
HashMap<StringName, Level3D *> &get_levels(); gd::HashMap<gd::StringName, Level3D *> &get_levels();
IPlayer *get_player(uint32_t id); IPlayer *get_player(uint32_t id);
Vector<IPlayer*> get_players(); gd::Vector<IPlayer*> get_players();
protected: protected:
// attempt to make 'this' the current singleton instance // attempt to make 'this' the current singleton instance
void grab_singleton(); void grab_singleton();
@ -79,20 +81,20 @@ protected:
void release_singleton(); void release_singleton();
uint32_t find_empty_player_slot() const; uint32_t find_empty_player_slot() const;
IPlayer *spawn_player(uint32_t id); IPlayer *spawn_player(uint32_t id);
void level_unloaded(StringName scene_path); void level_unloaded(gd::StringName scene_path);
static bool is_valid_level(Ref<PackedScene> &level); static bool is_valid_level(gd::Ref<gd::PackedScene> &level);
protected: protected:
static GameRoot3D *singleton_instance; static GameRoot3D *singleton_instance;
uint32_t next_player_id{1}; // 0 is the "invalid" player id uint32_t next_player_id{1}; // 0 is the "invalid" player id
HashMap<uint32_t, Pair<PlayerInput*, IPlayer*>> players{}; gd::HashMap<uint32_t, gd::Pair<PlayerInput*, IPlayer*>> players{};
Ref<GameMode> game_mode{}; gd::Ref<GameMode> game_mode{};
private: private:
RandomNumberGenerator rng{}; gd::RandomNumberGenerator rng{};
HashMap<StringName, Level3D*> levels{}; gd::HashMap<gd::StringName, Level3D*> levels{};
Vector<SpawnPoint3D*> spawn_points{}; gd::Vector<SpawnPoint3D*> spawn_points{};
Ref<PackedScene> first_boot_level{}; gd::Ref<gd::PackedScene> first_boot_level{};
}; };
} }

View File

@ -1,6 +1,8 @@
#include "game_state.hpp" #include "game_state.hpp"
namespace godot { using namespace godot;
namespace utils {
void GameState::_bind_methods() { void GameState::_bind_methods() {
#define CLASSNAME GameState #define CLASSNAME GameState
} }

View File

@ -1,10 +1,11 @@
#ifndef GAME_STATE_HPP #ifndef GAME_STATE_HPP
#define GAME_STATE_HPP #define GAME_STATE_HPP
#include "godot_cpp/classes/resource.hpp" #include <godot_cpp/classes/resource.hpp>
namespace godot {
class GameState : public Resource { namespace utils {
GDCLASS(GameState, Resource); class GameState : public godot::Resource {
GDCLASS(GameState, godot::Resource);
static void _bind_methods(); static void _bind_methods();
public: public:
}; };

View File

@ -4,37 +4,33 @@
#include "godot_cpp/classes/engine.hpp" #include "godot_cpp/classes/engine.hpp"
#include "godot_cpp/core/class_db.hpp" #include "godot_cpp/core/class_db.hpp"
#define MACRO_STRING_INNER(_Arg) #_Arg #define MACRO_STRING_INNER(_Arg) #_Arg
#define MACRO_STRING(_Arg) MACRO_STRING_INNER(_Arg) #define MACRO_STRING(_Arg) MACRO_STRING_INNER(_Arg)
#define GDPROPERTY(_PropName, _PropType) \ #define GDPROPERTY(_PropName, _PropType) \
ClassDB::bind_method(D_METHOD("get_" #_PropName), &CLASSNAME::get_##_PropName); \ godot::ClassDB::bind_method(godot::D_METHOD("get_" #_PropName), &CLASSNAME::get_##_PropName); \
ClassDB::bind_method(D_METHOD("set_" #_PropName, "value"), &CLASSNAME::set_##_PropName); \ godot::ClassDB::bind_method(godot::D_METHOD("set_" #_PropName, "value"), &CLASSNAME::set_##_PropName); \
ClassDB::add_property(MACRO_STRING(CLASSNAME), PropertyInfo(_PropType, #_PropName), "set_" #_PropName, \ godot::ClassDB::add_property(MACRO_STRING(CLASSNAME), godot::PropertyInfo(_PropType, #_PropName), "set_" #_PropName, "get_" #_PropName)
"get_" #_PropName)
#define GDPROPERTY_HINTED(_PropName, _PropType, ...) \ #define GDPROPERTY_HINTED(_PropName, _PropType, ...) \
ClassDB::bind_method(D_METHOD("get_" #_PropName), &CLASSNAME::get_##_PropName); \ godot::ClassDB::bind_method(godot::D_METHOD("get_" #_PropName), &CLASSNAME::get_##_PropName); \
ClassDB::bind_method(D_METHOD("set_" #_PropName, "value"), &CLASSNAME::set_##_PropName); \ godot::ClassDB::bind_method(godot::D_METHOD("set_" #_PropName, "value"), &CLASSNAME::set_##_PropName); \
ClassDB::add_property(MACRO_STRING(CLASSNAME), PropertyInfo(_PropType, #_PropName, __VA_ARGS__), \ godot::ClassDB::add_property(MACRO_STRING(CLASSNAME), godot::PropertyInfo(_PropType, #_PropName, __VA_ARGS__), "set_" #_PropName, "get_" #_PropName)
"set_" #_PropName, "get_" #_PropName)
#define GDFUNCTION(_FnName) ClassDB::bind_method(D_METHOD(#_FnName), &CLASSNAME::_FnName) #define GDFUNCTION(_FnName) godot::ClassDB::bind_method(godot::D_METHOD(#_FnName), &CLASSNAME::_FnName)
#define GDFUNCTION_ARGS(_FnName, ...) ClassDB::bind_method(D_METHOD(#_FnName, __VA_ARGS__), &CLASSNAME::_FnName) #define GDFUNCTION_ARGS(_FnName, ...) godot::ClassDB::bind_method(godot::D_METHOD(#_FnName, __VA_ARGS__), &CLASSNAME::_FnName)
#define GDFUNCTION_STATIC(_FnName) \ #define GDFUNCTION_STATIC(_FnName) godot::ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), godot::D_METHOD(#_FnName), &CLASSNAME::_FnName)
ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), D_METHOD(#_FnName), &CLASSNAME::_FnName)
#define GDFUNCTION_STATIC_ARGS(_FnName, ...) \ #define GDFUNCTION_STATIC_ARGS(_FnName, ...) godot::ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), godot::D_METHOD(#_FnName, __VA_ARGS__), &CLASSNAME::_FnName)
ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), D_METHOD(#_FnName, __VA_ARGS__), &CLASSNAME::_FnName)
#define GDSIGNAL(...)\ #define GDSIGNAL(...) godot::ClassDB::add_signal(MACRO_STRING(CLASSNAME), godot::MethodInfo(__VA_ARGS__))
ClassDB::add_signal(MACRO_STRING(CLASSNAME), MethodInfo(__VA_ARGS__))
#define GDRESOURCETYPE(_Class) vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, #_Class) #define GDRESOURCETYPE(_Class) godot::vformat("%s/%s:%s", godot::Variant::OBJECT, godot::PROPERTY_HINT_RESOURCE_TYPE, #_Class)
#define GDEDITORONLY() if(!Engine::get_singleton()->is_editor_hint()) return; #define GDEDITORONLY() if(!godot::Engine::get_singleton()->is_editor_hint()) return;
#define GDGAMEONLY() if(Engine::get_singleton()->is_editor_hint()) return; #define GDGAMEONLY() if(godot::Engine::get_singleton()->is_editor_hint()) return;
#endif // !UC_GODOT_MACROS_H #endif // !UC_GODOT_MACROS_H

View File

@ -1,33 +1,17 @@
#include "level.hpp" #include "level.hpp"
#include "utils/godot_macros.h" #include "utils/godot_macros.h"
namespace godot { namespace utils {
void Level3D::_bind_methods() { void Level3D::_bind_methods() {
#define CLASSNAME Level3D #define CLASSNAME Level3D
GDPROPERTY_HINTED(game_mode_prototype, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameMode"); GDPROPERTY_HINTED(game_mode_prototype, gd::Variant::OBJECT, gd::PROPERTY_HINT_RESOURCE_TYPE, "GameMode");
} }
void Level3D::set_game_mode_prototype(Ref<GameMode> prototype) { void Level3D::set_game_mode_prototype(gd::Ref<GameMode> prototype) {
this->game_mode_prototype = prototype; this->game_mode_prototype = prototype;
} }
Ref<GameMode> Level3D::get_game_mode_prototype() const { gd::Ref<GameMode> Level3D::get_game_mode_prototype() const {
return this->game_mode_prototype; return this->game_mode_prototype;
} }
#undef CLASSNAME // Level3D
void Level2D::_bind_methods() {
#define CLASSNAME Level3D
GDPROPERTY_HINTED(game_mode_prototype, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameMode");
}
void Level2D::set_game_mode_prototype(Ref<GameMode> prototype) {
this->game_mode_prototype = prototype;
}
Ref<GameMode> Level2D::get_game_mode_prototype() const {
return this->game_mode_prototype;
}
} }

View File

@ -1,32 +1,21 @@
#ifndef LEVEL_HPP #ifndef LEVEL_HPP
#define LEVEL_HPP #define LEVEL_HPP
#include <godot_cpp/classes/node2d.hpp>
#include <godot_cpp/classes/node3d.hpp>
#include "game_mode.hpp" #include "game_mode.hpp"
#include <godot_cpp/classes/node3d.hpp>
namespace godot { namespace gd = godot;
class Level3D : public Node3D {
GDCLASS(Level3D, Node3D); namespace utils {
class Level3D : public gd::Node3D {
GDCLASS(Level3D, gd::Node3D);
static void _bind_methods(); static void _bind_methods();
public: public:
void set_game_mode_prototype(Ref<GameMode> prototype); void set_game_mode_prototype(gd::Ref<GameMode> prototype);
Ref<GameMode> get_game_mode_prototype() const; gd::Ref<GameMode> get_game_mode_prototype() const;
private: private:
Ref<GameMode> game_mode_prototype{}; gd::Ref<GameMode> game_mode_prototype{};
}; };
class Level2D : public Node2D {
GDCLASS(Level2D, Node2D);
static void _bind_methods();
public:
void set_game_mode_prototype(Ref<GameMode> prototype);
Ref<GameMode> get_game_mode_prototype() const;
private:
Ref<GameMode> game_mode_prototype{};
};
} }
#endif // !LEVEL_HPP #endif // !LEVEL_HPP

View File

@ -1,6 +1,6 @@
#include "player.hpp" #include "player.hpp"
namespace godot { namespace utils {
uint32_t IPlayer::get_player_id() { uint32_t IPlayer::get_player_id() {
return this->player_id.value_or(0); return this->player_id.value_or(0);
} }

View File

@ -5,16 +5,19 @@
#include <optional> #include <optional>
#include <godot_cpp/variant/transform3d.hpp> #include <godot_cpp/variant/transform3d.hpp>
namespace godot { namespace godot { class Node; }
namespace gd = godot;
namespace utils {
class PlayerInput; class PlayerInput;
class Node;
class IPlayer { class IPlayer {
friend class GameRoot3D; friend class GameRoot3D;
public: public:
virtual void setup_player_input(PlayerInput *input) = 0; virtual void setup_player_input(PlayerInput *input) = 0;
virtual Node *to_node() = 0; virtual gd::Node *to_node() = 0;
virtual void spawn_at_position(Transform3D const &at) = 0; virtual void spawn_at_position(gd::Transform3D const &at) = 0;
uint32_t get_player_id(); uint32_t get_player_id();

View File

@ -1,31 +1,32 @@
#include "player_input.hpp" #include "player_input.hpp"
#include "godot_macros.h" #include "godot_macros.h"
#include "godot_cpp/classes/input.hpp" #include <godot_cpp/classes/input.hpp>
#include "godot_cpp/classes/input_event.hpp" #include <godot_cpp/classes/input_event.hpp>
#include "godot_cpp/classes/input_event_mouse_motion.hpp" #include <godot_cpp/classes/input_event_mouse_motion.hpp>
#include "godot_cpp/variant/callable.hpp" #include <godot_cpp/variant/callable.hpp>
#include <algorithm>
#include <optional> #include <optional>
namespace godot { namespace utils {
void PlayerInput::_bind_methods() {} void PlayerInput::_bind_methods() {
#define CLASSNAME PlayerInput
}
Vector2 PlayerInput::lastMouseMotion{0.f, 0.f}; gd::Vector2 PlayerInput::lastMouseMotion{0.f, 0.f};
bool PlayerInput::primaryExists{false}; bool PlayerInput::primaryExists{false};
PlayerInput::Listener::Listener(String positive, String negative, Callable callable) PlayerInput::Listener::Listener(gd::String positive, gd::String negative, gd::Callable callable)
: actionNegative{negative} : actionNegative{negative}
, actionPositive{positive} , actionPositive{positive}
, callable{callable} , callable{callable}
, isMouseEvent{positive.begins_with("_mouse_") || negative.begins_with("_mouse_")} {} , isMouseEvent{positive.begins_with("_mouse_") || negative.begins_with("_mouse_")} {}
PlayerInput::Listener::Listener(String action, Callable callable) PlayerInput::Listener::Listener(gd::String action, gd::Callable callable)
: PlayerInput::Listener::Listener(action, String(), callable) {} : PlayerInput::Listener::Listener(action, gd::String(), callable) {}
std::optional<float> PlayerInput::Listener::evaluate_action(String const &action) { std::optional<float> PlayerInput::Listener::evaluate_action(gd::String const &action) {
Input *input = Input::get_singleton(); gd::Input *input = gd::Input::get_singleton();
if(action.begins_with("_mouse_")) { if(action.begins_with("_mouse_")) {
Vector2 vector = PlayerInput::get_last_mouse_motion(); gd::Vector2 vector = PlayerInput::get_last_mouse_motion();
if(action.ends_with("_up")) if(action.ends_with("_up"))
return vector.y > 0.f ? vector.y : 0.f; return vector.y > 0.f ? vector.y : 0.f;
else if(action.ends_with("_down")) else if(action.ends_with("_down"))
@ -42,14 +43,14 @@ std::optional<float> PlayerInput::Listener::evaluate_action(String const &action
} }
} }
bool PlayerInput::Listener::has_changed(Ref<InputEvent> const &event) { bool PlayerInput::Listener::has_changed(gd::Ref<gd::InputEvent> const &event) {
bool const mouse_changed{this->isMouseEvent && event->is_class("InputEventMouseMotion")}; bool const mouse_changed{this->isMouseEvent && event->is_class("InputEventMouseMotion")};
bool const negative_changed{!this->actionNegative.is_empty() && event->is_action(this->actionNegative)}; bool const negative_changed{!this->actionNegative.is_empty() && event->is_action(this->actionNegative)};
bool const positive_changed{!this->actionPositive.is_empty() && event->is_action(this->actionPositive)}; bool const positive_changed{!this->actionPositive.is_empty() && event->is_action(this->actionPositive)};
return mouse_changed || negative_changed || positive_changed; return mouse_changed || negative_changed || positive_changed;
} }
float PlayerInput::Listener::evaluate(Ref<InputEvent> const &event) { float PlayerInput::Listener::evaluate(gd::Ref<gd::InputEvent> const &event) {
std::optional<float> positive = PlayerInput::Listener::evaluate_action(this->actionPositive); std::optional<float> positive = PlayerInput::Listener::evaluate_action(this->actionPositive);
std::optional<float> negative = PlayerInput::Listener::evaluate_action(this->actionNegative); std::optional<float> negative = PlayerInput::Listener::evaluate_action(this->actionNegative);
if(!positive.has_value() || !negative.has_value()) if(!positive.has_value() || !negative.has_value())
@ -60,13 +61,13 @@ float PlayerInput::Listener::evaluate(Ref<InputEvent> const &event) {
return (this->lastCached = newest); return (this->lastCached = newest);
} }
bool PlayerInput::Listener::operator==(godot::PlayerInput::Listener const& b) { bool PlayerInput::Listener::operator==(PlayerInput::Listener const& b) const {
return this->callable == b.callable return this->callable == b.callable
&& this->actionNegative == b.actionNegative && this->actionNegative == b.actionNegative
&& this->actionPositive == b.actionPositive; && this->actionPositive == b.actionPositive;
} }
Vector2 PlayerInput::get_last_mouse_motion() { gd::Vector2 PlayerInput::get_last_mouse_motion() {
return PlayerInput::lastMouseMotion; return PlayerInput::lastMouseMotion;
} }
@ -86,10 +87,10 @@ void PlayerInput::_exit_tree() {
} }
} }
void PlayerInput::_unhandled_input(Ref<InputEvent> const &event) { void PlayerInput::_unhandled_input(gd::Ref<gd::InputEvent> const &event) {
GDGAMEONLY(); GDGAMEONLY();
if(this->isPrimary && event->is_class("InputEventMouseMotion")) if(this->isPrimary && event->is_class("InputEventMouseMotion"))
PlayerInput::lastMouseMotion = Object::cast_to<InputEventMouseMotion>(*event)->get_relative(); PlayerInput::lastMouseMotion = gd::Object::cast_to<gd::InputEventMouseMotion>(*event)->get_relative();
for(Listener& listener: this->listeners) { for(Listener& listener: this->listeners) {
if(listener.has_changed(event)) { if(listener.has_changed(event)) {
listener.evaluate(event); listener.evaluate(event);
@ -108,18 +109,16 @@ void PlayerInput::listen_to(Listener const& listener) {
void PlayerInput::stop_listening(Node *node) { void PlayerInput::stop_listening(Node *node) {
for(size_t i = 0; i < this->listeners.size(); ++i) { for(size_t i = 0; i < this->listeners.size(); ++i) {
Listener& l = this->listeners.at(i); Listener l = this->listeners.get(i);
if(l.callable.get_object() == node) { if(l.callable.get_object() == node) {
this->listeners.erase(this->listeners.begin() + i); this->listeners.remove_at(i);
i--; i--;
} }
} }
} }
void PlayerInput::stop_listening(Listener const& listener) { void PlayerInput::stop_listening(Listener const& listener) {
std::vector<Listener>::iterator itr = std::find(this->listeners.begin(), this->listeners.end(), listener); this->listeners.erase(listener);
if(itr != this->listeners.end())
this->listeners.erase(itr);
} }
void PlayerInput::clear_listeners() { void PlayerInput::clear_listeners() {

View File

@ -1,55 +1,60 @@
#ifndef PLAYER_INPUT_HPP #ifndef PLAYER_INPUT_HPP
#define PLAYER_INPUT_HPP #define PLAYER_INPUT_HPP
#include <vector>
#include <optional> #include <optional>
#include "godot_cpp/classes/input.hpp" #include <godot_cpp/classes/input.hpp>
#include "godot_cpp/classes/input_event.hpp" #include <godot_cpp/classes/input_event.hpp>
#include "godot_cpp/classes/node.hpp" #include <godot_cpp/classes/node.hpp>
#include "godot_cpp/variant/callable.hpp" #include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/variant/callable.hpp>
namespace godot { namespace gd = godot;
class PlayerInput : public Node {
GDCLASS(PlayerInput, Node) namespace utils {
/*! An event-driven input observer.
*
* Listen for events with `listen_to`, registering godot input action names to callbacks. It's possible to register an "axis" by registering a listener with a positive and negative action.
*/
class PlayerInput : public gd::Node {
GDCLASS(PlayerInput, gd::Node)
static void _bind_methods(); static void _bind_methods();
public: public:
// a listener is a combination of a positive and negative action and a listener function. /*! A PlayerInput action listener.
// listener functions use godot's Object::call function. * A listener is a combination of a positive and negative action and a callable.
// So they require a Node instance and a function name. * The expected callable signature is `void (godot::Ref<godot::InputEvent> event, float value)`
// The expected signature is void(Ref<InputEvent>, float) * actions can also be "special" actions prefixed with `_`.
// actions can also be "special" actions prefixed with _. * Special actions include `_mouse_up`, `_mouse_down`, `_mouse_left`, and `_mouse_right`.
// special actions include _mouse_up, _mouse_down, _mouse_left and _mouse_right */
// which rather than checking action_is_down,
// will use PlayerInput::get_last_mouse_motion() to poll the current state.
struct Listener { struct Listener {
friend class PlayerInput; friend class PlayerInput;
private: private:
// the two actions, evaluated as positive - negative // the two actions, evaluated as positive - negative
String actionNegative{""}; gd::String actionNegative{""};
String actionPositive{""}; gd::String actionPositive{""};
// the last cached action, if the newest result matches this, the event will be considered // the last cached action, if the newest result matches this, the event will be considered
// duplicate and ignored (not passed to listener) // duplicate and ignored (not passed to listener)
float lastCached{0.f}; float lastCached{0.f};
Callable callable; gd::Callable callable;
// if either actionNegative or actionPositive is a _mouse_ event this will be true // if either actionNegative or actionPositive is a _mouse_ event this will be true
bool isMouseEvent{false}; bool isMouseEvent{false};
public: public:
Listener(String positive, String negative, Callable callable); Listener() = default;
Listener(String action, Callable callable); Listener(gd::String positive, gd::String negative, gd::Callable callable);
Listener(gd::String action, gd::Callable callable);
// evaluate the current state of an action. // evaluate the current state of an action.
static std::optional<float> evaluate_action(String const &action); static std::optional<float> evaluate_action(gd::String const &action);
// check if this event has any chance to result in a trigger, does not evaluate the event or // check if this event has any chance to result in a trigger, does not evaluate the event or
// poll current input state // poll current input state
bool has_changed(Ref<InputEvent> const &event); bool has_changed(gd::Ref<gd::InputEvent> const &event);
// evaluate the event for changes to either actionPositive or actionNegative // evaluate the event for changes to either actionPositive or actionNegative
float evaluate(Ref<InputEvent> const &event); float evaluate(gd::Ref<gd::InputEvent> const &event);
bool operator==(godot::PlayerInput::Listener const& b); bool operator==(PlayerInput::Listener const& b) const;
}; };
private: private:
// the last mouse motion, updated by the primary instance // the last mouse motion, updated by the primary instance
static Vector2 lastMouseMotion; static gd::Vector2 lastMouseMotion;
// does a primary instance exist // does a primary instance exist
static bool primaryExists; static bool primaryExists;
// is this the primary instance // is this the primary instance
@ -58,13 +63,13 @@ private:
bool isPrimary{false}; bool isPrimary{false};
// current listeners for this instance // current listeners for this instance
std::vector<Listener> listeners{}; gd::Vector<Listener> listeners{};
public: public:
static Vector2 get_last_mouse_motion(); static gd::Vector2 get_last_mouse_motion();
virtual void _enter_tree() override; virtual void _enter_tree() override;
virtual void _exit_tree() override; virtual void _exit_tree() override;
virtual void _unhandled_input(Ref<InputEvent> const &event) override; virtual void _unhandled_input(gd::Ref<gd::InputEvent> const &event) override;
virtual void _process(double deltaTime) override; virtual void _process(double deltaTime) override;
void listen_to(Listener const &listener); void listen_to(Listener const &listener);

View File

@ -1,17 +1,21 @@
#include "register_types.hpp" #include "register_types.hpp"
#include <godot_cpp/core/class_db.hpp>
#include "game_root.hpp"
#include "game_mode.hpp" #include "game_mode.hpp"
#include "game_root.hpp"
#include "game_state.hpp" #include "game_state.hpp"
#include "level.hpp" #include "level.hpp"
#include "player_input.hpp"
#include "spawn_point.hpp"
#include <godot_cpp/core/class_db.hpp>
using namespace godot; namespace gd = godot;
namespace utils {
void godot_cpp_utils_register_types() { void godot_cpp_utils_register_types() {
ClassDB::register_class<GameRoot3D>(); gd::ClassDB::register_class<utils::GameMode>();
ClassDB::register_class<GameMode>(); gd::ClassDB::register_class<utils::GameRoot3D>();
ClassDB::register_class<GameState>(); gd::ClassDB::register_class<utils::GameState>();
ClassDB::register_class<Level3D>(); gd::ClassDB::register_class<utils::Level3D>();
ClassDB::register_class<SpawnPoint3D>(); gd::ClassDB::register_class<utils::PlayerInput>();
ClassDB::register_class<PlayerInput>(); gd::ClassDB::register_class<utils::SpawnPoint3D>();
}
} }

View File

@ -1,6 +1,8 @@
#ifndef UTILS_REGISTER_TYPES_HPP #ifndef UTILS_REGISTER_TYPES_HPP
#define UTILS_REGISTER_TYPES_HPP #define UTILS_REGISTER_TYPES_HPP
namespace utils {
void godot_cpp_utils_register_types(); void godot_cpp_utils_register_types();
}
#endif // !UTILS_REGISTER_TYPES_HPP #endif // !UTILS_REGISTER_TYPES_HPP

View File

@ -1,12 +1,12 @@
#include "spawn_point.hpp" #include "spawn_point.hpp"
#include "utils/game_root.hpp" #include "utils/game_root.hpp"
namespace godot { namespace utils {
void SpawnPoint3D::_bind_methods() { void SpawnPoint3D::_bind_methods() {
} }
void SpawnPoint3D::_enter_tree() { void SpawnPoint3D::_enter_tree() {
GameRoot3D *root = Object::cast_to<GameRoot3D>(GameRoot3D::get_singleton()); GameRoot3D *root = gd::Object::cast_to<GameRoot3D>(GameRoot3D::get_singleton());
if(root == nullptr) { if(root == nullptr) {
return; return;
} }

View File

@ -1,10 +1,13 @@
#ifndef UTILS_SPAWN_POINT_HPP #ifndef UTILS_SPAWN_POINT_HPP
#define UTILS_SPAWN_POINT_HPP #define UTILS_SPAWN_POINT_HPP
#include "godot_cpp/classes/node3d.hpp" #include <godot_cpp/classes/node3d.hpp>
namespace godot {
class SpawnPoint3D : public Node3D { namespace gd = godot;
GDCLASS(SpawnPoint3D, Node3D);
namespace utils {
class SpawnPoint3D : public gd::Node3D {
GDCLASS(SpawnPoint3D, gd::Node3D);
static void _bind_methods(); static void _bind_methods();
public: public:
virtual void _enter_tree() override; virtual void _enter_tree() override;