feat: swapped from godot:: to utils:: namespace
parent
54fcbcbb6b
commit
3cad3af3fe
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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{};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
24
level.cpp
24
level.cpp
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
29
level.hpp
29
level.hpp
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
11
player.hpp
11
player.hpp
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,18 +63,18 @@ 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);
|
||||||
void stop_listening(Node *node);
|
void stop_listening(Node *node);
|
||||||
void stop_listening(Listener const& listener);
|
void stop_listening(Listener const &listener);
|
||||||
void clear_listeners();
|
void clear_listeners();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue