Compare commits

...

10 Commits

8 changed files with 32 additions and 41 deletions

View File

@ -2,7 +2,7 @@
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/scene_state.hpp>
#include "utils/godot_macros.hpp"
#include "godot_macros.hpp"
namespace utils {
void GameMode::_bind_methods() {

View File

@ -6,12 +6,13 @@
#include "player_input.hpp"
#include "player.hpp"
#include "spawn_point.hpp"
#include "utils/game_state.hpp"
#include "game_state.hpp"
#include <cstdint>
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/input.hpp>
#include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/scene_state.hpp>
#include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/variant/string_name.hpp>
@ -36,19 +37,21 @@ bool GameRoot3D::has_singleton() {
return GameRoot3D::singleton_instance != nullptr;
}
void GameRoot3D::_enter_tree() { GDGAMEONLY();
void GameRoot3D::_enter_tree() {
// TODO: Replace this with detecting input devices
this->player_input_connected();
this->grab_singleton();
this->rng = godot::Ref<godot::RandomNumberGenerator>(memnew(godot::RandomNumberGenerator));
}
void GameRoot3D::_ready() { GDGAMEONLY();
void GameRoot3D::_ready() {
this->game_state = gd::ResourceLoader::get_singleton()->load("user://savegame.res");
if(!this->game_state.is_valid())
this->game_state = this->game_state_prototype->duplicate(true);
this->load_level(this->first_boot_level);
// TODO: try load save data from file.
this->game_state = this->game_state_prototype->duplicate(true);
}
void GameRoot3D::_exit_tree() { GDGAMEONLY();
void GameRoot3D::_exit_tree() {
this->release_singleton();
}
@ -119,7 +122,7 @@ Level3D *GameRoot3D::load_level_at(gd::Ref<gd::PackedScene> level, gd::Transform
// store and add to tree at desired transform
// if this is the first level containing a game mode currently active use it's gamemode as a prototype
gd::Ref<gd::PackedScene> game_mode_prototype{instance->get_game_mode_prototype()};
bool const switch_game_mode{!this->game_mode || this->game_mode->get_scene_file_path() != game_mode_prototype->get_path()};
bool const switch_game_mode{!this->game_mode || !game_mode_prototype.is_valid() || this->game_mode->get_scene_file_path() != game_mode_prototype->get_path()};
if(switch_game_mode) {
this->set_game_mode(instance->get_game_mode_prototype());
}
@ -138,7 +141,7 @@ void GameRoot3D::unload_all_levels() {
gd::HashMap<gd::StringName, Level3D*> levels = this->get_levels();
for(gd::KeyValue<gd::StringName, Level3D*> &kvp : levels)
kvp.value->call_deferred("queue_free");
this->get_levels().clear();
this->levels.clear();
this->reset_game_mode();
}
@ -180,8 +183,10 @@ void GameRoot3D::set_game_mode(gd::Ref<gd::PackedScene> prototype) {
this->remove_all_players();
if(this->game_mode != nullptr)
this->game_mode->queue_free();
if(prototype.is_null() || !prototype.is_valid())
if(prototype.is_null() || !prototype.is_valid()) {
this->game_mode = nullptr;
return; // allow "unsetting" the gamemode by passing an invalid gamemode
}
// Detect passing of valid scene that is an invalid game mode
if(!gd::ClassDB::is_parent_class(prototype->get_state()->get_node_type(0), "GameMode")) {
gd::UtilityFunctions::push_error("Attempted to load non-gamemode scene as gamemode");

View File

@ -10,7 +10,6 @@
#include <godot_cpp/templates/hash_map.hpp>
#include <godot_cpp/templates/hash_set.hpp>
#include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/templates/vector.hpp>
namespace gd = godot;
@ -159,7 +158,7 @@ private:
*
* `*get_game_mode()`
*/
GameMode *game_mode{};
GameMode *game_mode{};
/*! Active game state.
*
* Will be assigned loaded save data, or game_state_prototype if no save data is found.
@ -171,14 +170,14 @@ private:
*
* `get_first_boot_level()` `set_first_boot_level(value)`
*/
gd::Ref<gd::PackedScene> first_boot_level{};
gd::Ref<gd::PackedScene> first_boot_level{};
/*! The default game state data.
*
* Duplicated and assigned to game_state if no save data is available.
*
* `get_game_state_prototype()` `set_game_state_prototype(value)`
*/
gd::Ref<GameState> game_state_prototype{};
gd::Ref<GameState> game_state_prototype{};
};
}

View File

@ -37,28 +37,28 @@
/*! \def GDFUNCTION(FnName_)
* \brief Register a function CLASSNAME::FnName_() to godot.
*
*
* Requires setting CLASSNAME as a #define first.
*/
#define GDFUNCTION(FnName_) godot::ClassDB::bind_method(godot::D_METHOD(#FnName_), &CLASSNAME::FnName_)
/*! \def GDFUNCTION_ARGS(FnName_, ...)
* \brief Register a function CLASSNAME::FnName_(...) to godot.
*
*
* Requires setting CLASSNAME as a #define first.
*/
#define GDFUNCTION_ARGS(FnName_, ...) godot::ClassDB::bind_method(godot::D_METHOD(#FnName_, __VA_ARGS__), &CLASSNAME::FnName_)
/*! \def GDFUNCTION_STATIC(FnName_)
* \brief Register a static member function CLASSNAME::FnName_() to godot.
*
*
* Requires setting CLASSNAME as a #define first.
*/
#define GDFUNCTION_STATIC(FnName_) godot::ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), godot::D_METHOD(#FnName_), &CLASSNAME::_FnName)
/*! \def GDFUNCTION_STATIC_ARGS(FnName_, ...)
* \brief Register a static member function CLASSNAME::FnName_(...) to godot.
*
*
* Requires setting CLASSNAME as a #define first.
*/
#define GDFUNCTION_STATIC_ARGS(FnName_, ...) godot::ClassDB::bind_static_method(MACRO_STRING(CLASSNAME), godot::D_METHOD(#FnName_, __VA_ARGS__), &CLASSNAME::FnName_)
@ -77,19 +77,6 @@
#define GDNODETYPE(Class_) godot::vformat("%s/%s:%s", godot::Variant::OBJECT, godot::PROPERTY_HINT_NODE_TYPE, Class_)
#define GDENUMTYPE(EnumString_) godot::vformat("%s/%s:%s", godot::Variant::INT, godot::PROPERTY_HINT_ENUM, EnumString_)
/*! \def GDEDITORONLY()
* \brief Execute the rest of the function only if currently running as editor.
*
* Useful for _ready, _enter/_exit, _process, etc. functions.
*/
#define GDEDITORONLY() if(!godot::Engine::get_singleton()->is_editor_hint()) return;
/*! \def GDGAMEONLY()
* \brief Execute the rest of the function only if currently running as game.
*
* Useful for _ready, _enter/_exit, _process, etc. functions.
*/
#define GDGAMEONLY() if(godot::Engine::get_singleton()->is_editor_hint()) return;
/*! \def GDENUM(Name_, ...)
* \brief Declare a scoped enum struct.
*

View File

@ -1,6 +1,6 @@
#include "level.hpp"
#include "godot_macros.hpp"
#include <godot_cpp/core/class_db.hpp>
#include "utils/godot_macros.hpp"
#include <godot_cpp/classes/scene_state.hpp>
namespace utils {

View File

@ -74,21 +74,21 @@ gd::Vector2 PlayerInput::get_last_mouse_motion() {
return PlayerInput::lastMouseMotion;
}
void PlayerInput::_enter_tree() { GDGAMEONLY();
void PlayerInput::_enter_tree() {
if(!PlayerInput::primaryExists) {
this->isPrimary = true;
PlayerInput::primaryExists = true;
}
}
void PlayerInput::_exit_tree() { GDGAMEONLY();
void PlayerInput::_exit_tree() {
if(this->isPrimary) {
this->isPrimary = false;
PlayerInput::primaryExists = false;
}
}
void PlayerInput::_unhandled_input(gd::Ref<gd::InputEvent> const &event) { GDGAMEONLY();
void PlayerInput::_unhandled_input(gd::Ref<gd::InputEvent> const &event) {
if(this->isPrimary && event->is_class("InputEventMouseMotion"))
PlayerInput::lastMouseMotion = gd::Object::cast_to<gd::InputEventMouseMotion>(*event)->get_relative();
for(Listener& listener: this->listeners) {

View File

@ -9,11 +9,11 @@
namespace utils {
void godot_cpp_utils_register_types() {
GDREGISTER_CLASS(utils::GameMode);
GDREGISTER_CLASS(utils::GameRoot3D);
GDREGISTER_RUNTIME_CLASS(utils::GameMode);
GDREGISTER_RUNTIME_CLASS(utils::GameRoot3D);
GDREGISTER_CLASS(utils::GameState);
GDREGISTER_CLASS(utils::Level3D);
GDREGISTER_CLASS(utils::PlayerInput);
GDREGISTER_CLASS(utils::SpawnPoint3D);
GDREGISTER_RUNTIME_CLASS(utils::Level3D);
GDREGISTER_RUNTIME_CLASS(utils::PlayerInput);
GDREGISTER_RUNTIME_CLASS(utils::SpawnPoint3D);
}
}

View File

@ -1,5 +1,5 @@
#include "spawn_point.hpp"
#include "utils/game_root.hpp"
#include "game_root.hpp"
namespace utils {
void SpawnPoint3D::_bind_methods() {