diff --git a/.hgignore b/.hgignore index b640b3e..811cc28 100644 --- a/.hgignore +++ b/.hgignore @@ -11,6 +11,7 @@ engine/libraries/oglft/liboglft/OGLFT.h start runtests fysxasteroids +fysxasteroidseditor config.rc Debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b1f150..d7aa9b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,13 +38,35 @@ SET ( ASTEROIDS_SOURCES asteroids/View.cc ) +SET ( ASTEROIDSEDITOR_SOURCES + asteroids/AsteroidEntity.cc + asteroids/Controller.cc + asteroids/ControllerCommands.cc + asteroids/EntityFactory.cc + asteroids/EnumToString.cc + asteroids/Game.cc + asteroids/editormain.cc + asteroids/Model.cc + asteroids/ModelCommands.cc + asteroids/Physics.cc + asteroids/RocketEntity.cc + asteroids/ShipEntity.cc + asteroids/View.cc + ) + ADD_EXECUTABLE ( fysxasteroids ${ASTEROIDS_SOURCES} ) +ADD_EXECUTABLE ( fysxasteroidseditor ${ASTEROIDSEDITOR_SOURCES} ) TARGET_LINK_LIBRARIES ( fysxasteroids Engine oglft ) +TARGET_LINK_LIBRARIES ( fysxasteroidseditor + Engine + oglft + ) + SET ( DATA_DIR data/ ) @@ -54,6 +76,11 @@ INSTALL (TARGETS fysxasteroids LIBRARY DESTINATION lib ) +INSTALL (TARGETS fysxasteroidseditor + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ) + INSTALL (DIRECTORY ${DATA_DIR} DESTINATION share/fysxasteroids/data ) diff --git a/asteroids/View.h b/asteroids/View.h index 929eef9..35fb6a8 100644 --- a/asteroids/View.h +++ b/asteroids/View.h @@ -31,6 +31,39 @@ class View : public Engine::ViewBase { public: virtual ~View() {}; + /** \brief Pushes the given state onto mViewStateStack */ + void PushViewState (const ViewState state) { + Engine::LogDebug ("Pushing ViewState %s", GetStringViewState(state)); + mViewStateStack.push(state); + + // Fire the view state change event to properly clear the IMGUI state + Engine::EventBasePtr changeviewstate_event (new Engine::EventBase()); + changeviewstate_event->mEventType = EventChangeViewState; + QueueEvent (changeviewstate_event); + } + /** \brief Returns the current ViewState */ + ViewState GetViewState () { + return mViewStateStack.top(); + } + /** \brief Removes the top element of the current ViewState stack */ + void PopViewState () { + // Warning: you must not query for an invalid enum with + // GetStringENUM_NAME! + std::string popped_name = GetStringViewState(mViewStateStack.top()); + mViewStateStack.pop(); + + std::string current_name ("None"); + if (mViewStateStack.size() > 0) + current_name = GetStringViewState(mViewStateStack.top()); + + Engine::LogDebug("Popped ViewState: %s current %s remaining: %u", popped_name.c_str(), current_name.c_str(), mViewStateStack.size()); + + // Fire the view state change event to properly clear the IMGUI state + Engine::EventBasePtr changeviewstate_event (new Engine::EventBase()); + changeviewstate_event->mEventType = EventChangeViewState; + QueueEvent (changeviewstate_event); + } + protected: /** \brief Initializes the system */ virtual int OnInit (int argc, char* argv[]); @@ -74,38 +107,6 @@ class View : public Engine::ViewBase { /** \brief The ViewState stack that is used for non-linear menus */ std::stack mViewStateStack; - /** \brief Pushes the given state onto mViewStateStack */ - void PushViewState (const ViewState state) { - Engine::LogDebug ("Pushing ViewState %s", GetStringViewState(state)); - mViewStateStack.push(state); - - // Fire the view state change event to properly clear the IMGUI state - Engine::EventBasePtr changeviewstate_event (new Engine::EventBase()); - changeviewstate_event->mEventType = EventChangeViewState; - QueueEvent (changeviewstate_event); - } - /** \brief Returns the current ViewState */ - ViewState GetViewState () { - return mViewStateStack.top(); - } - /** \brief Removes the top element of the current ViewState stack */ - void PopViewState () { - // Warning: you must not query for an invalid enum with - // GetStringENUM_NAME! - std::string popped_name = GetStringViewState(mViewStateStack.top()); - mViewStateStack.pop(); - - std::string current_name ("None"); - if (mViewStateStack.size() > 0) - current_name = GetStringViewState(mViewStateStack.top()); - - Engine::LogDebug("Popped ViewState: %s current %s remaining: %u", popped_name.c_str(), current_name.c_str(), mViewStateStack.size()); - - // Fire the view state change event to properly clear the IMGUI state - Engine::EventBasePtr changeviewstate_event (new Engine::EventBase()); - changeviewstate_event->mEventType = EventChangeViewState; - QueueEvent (changeviewstate_event); - } /** \brief Removes all elements of the ViewState stack */ void ResetViewState() { Engine::LogDebug ("Resetting ViewState stack"); diff --git a/asteroids/editormain.cc b/asteroids/editormain.cc new file mode 100644 index 0000000..1421c8e --- /dev/null +++ b/asteroids/editormain.cc @@ -0,0 +1,176 @@ +#include +#include + +#include "Engine.h" + +#include "Controller.h" +#include "View.h" +#include "Model.h" +#include "Physics.h" +#include "EntityFactory.h" + +#include "Game.h" + +#include + +#ifdef WIN32 +#include +#endif + +using namespace std; + +/* Returns a path where files such as logs and config files can be + * written to + */ +std::string create_user_path () { + std::string result_dir = "."; + std::string test_file_path = result_dir; + + // first we check in $HOME/.fysxasteroids + char* env_home_dir = getenv("HOME"); + result_dir = env_home_dir; + result_dir += "/.fysxasteroids"; + + boost::filesystem::path result_dir_path(result_dir); + if(!boost::filesystem::is_directory (result_dir_path)) { + if (!boost::filesystem::create_directory(result_dir_path)) { + cerr << "Warning: could not create user data directory " << result_dir<< endl; + result_dir = ""; + } + } + + test_file_path = result_dir; + test_file_path += "/game.log"; + ofstream test_file (test_file_path.c_str(), ios_base::app); + if (!test_file) { + test_file.close(); + cerr << "Warning: user data directory not writable! " << result_dir << endl; + result_dir = ""; + } else { + test_file.close(); + return result_dir; + } + + // then we check the local directory + result_dir = "."; + test_file_path = result_dir; + test_file_path += "/game.log"; + test_file.open (test_file_path.c_str(), ios_base::out); + if (test_file) { + test_file.close(); + return result_dir; + } else { + cerr << "Warning could not find suitable user data directory" << endl; + result_dir = ""; + } + test_file.close(); + + return result_dir; +} + +std::string find_game_data_dir () { + std::string result; + + std::vector paths; + paths.push_back("."); + paths.push_back("/usr/local/share/fysxasteroids"); + paths.push_back("/usr/share/fysxasteroids"); + + std::vector::iterator iter = paths.begin(); + for (iter; iter != paths.end(); iter++) { + std::string test_path = *iter; + + if (!boost::filesystem::is_directory(test_path + "/data/fonts")) + continue; + if (!boost::filesystem::is_directory(test_path + "/data/levels")) + continue; + if (!boost::filesystem::is_directory(test_path + "/data/sounds")) + continue; + if (!boost::filesystem::is_directory(test_path + "/data/textures")) + continue; + + break; + } + + if (iter != paths.end()) + return *iter; + + cerr << "Could not find game data" << endl; + return result; +} + +int main (int argc, char* argv[]) { + cout << "Game Start" << endl; + +#ifdef WIN32 + HWND hWnd = GetConsoleWindow(); + ShowWindow( hWnd, SW_HIDE ); +#endif + + Engine::Engine engine; + + engine.SetEntityFactory (new asteroids::EntityFactory); + engine.SetController (new asteroids::Controller); + engine.SetModel (new asteroids::Model); + engine.SetPhysics (new asteroids::Physics); + engine.SetView (new asteroids::View); + + SetLogPrintLevel (Engine::LogLevelMessage); + + // we assume the user path to be local folder + std::string user_path = create_user_path(); + std::string log_file_path = user_path; + log_file_path += "/editor.log"; + + cout << "User Data Dir = " << user_path << endl; + engine.SetUserDataPath (user_path); + Engine::SetLogFilename (log_file_path.c_str()); + + std::string game_data_path = find_game_data_dir(); + engine.SetGameDataPath (game_data_path); + cout << "Game Data Dir = " << game_data_path << endl; + + if (engine.Init (argc, argv) != 0) { + cout << "Could not start engine!" << endl; + exit (-1); + } + + Engine::SetMusicVolume (0.); + + // Load the icon + Uint32 colorkey; + SDL_Surface *image = NULL; + image = SDL_LoadBMP("./data/textures/icon.bmp"); + if (!image) + Engine::LogWarning("Could not load icon: ./data/textures/icon.bmp"); + else + SDL_WM_SetIcon(image,NULL); + + SDL_WM_SetCaption("Asteroids -BETA1-","Asteroids -BETA 1-"); + + engine.GetView()->SetGridSize (8,8); + + /// \todo get rid of the world settings in asteroids + dynamic_cast(engine.GetPhysics())->SetWorldSize (26, 20); + engine.GetPhysics()->SetWorldBounds (vector3d (-13, 0, -10), vector3d (13, 0, 10)); + engine.GetPhysics()->EnableWorldWarp(Engine::PhysicsBase::WorldWarpModeX); + engine.GetPhysics()->EnableWorldWarp(Engine::PhysicsBase::WorldWarpModeZ); + + // run the default commands and load the configuration + Engine::RunCommand ("exec asteroids.rc"); + Engine::RunCommand ("exec config.rc"); + + asteroids::GetView()->PopViewState(); + asteroids::GetView()->PushViewState(asteroids::ViewStateEditor); + + engine.MainLoop (); + + SDL_WM_SetIcon(NULL,NULL); + SDL_FreeSurface (image); + + engine.Destroy (); + + cout << "Game Quit" << endl; + + return 0; +} diff --git a/asteroids/main.cc b/asteroids/main.cc index c59486d..f21a0d1 100644 --- a/asteroids/main.cc +++ b/asteroids/main.cc @@ -105,9 +105,6 @@ int main (int argc, char* argv[]) { ShowWindow( hWnd, SW_HIDE ); #endif - create_dir ("./root"); - create_dir ("./root/blaa"); - Engine::Engine engine; engine.SetEntityFactory (new asteroids::EntityFactory); diff --git a/engine/Utils.cc b/engine/Utils.cc new file mode 100644 index 0000000..3b922ae --- /dev/null +++ b/engine/Utils.cc @@ -0,0 +1,38 @@ +#include "Utils.h" + +#include +#include +#include + +#include +#include + +std::string strip_whitespaces (const std::string input_str) { + std::string result = input_str.substr(input_str.find_first_not_of (" \t\n\r"), input_str.size()); + return result.substr (0, result.find_last_not_of(" \t\n\r") + 1); +} + +bool create_dir (const std::string &dir_str) { + boost::filesystem::path dir_str_path(dir_str); + if(!boost::filesystem::is_directory (dir_str_path)) { + if (!boost::filesystem::create_directory(dir_str_path)) { + std::cerr << "Warning: could not create directory " << dir_str<< std::endl; + return false; + } + } + + std::string test_file_path = dir_str; + test_file_path += "/fysxasteroids_write_test_delete_me.txt"; + std::ofstream test_file (test_file_path.c_str(), std::ios_base::app); + if (!test_file) { + test_file.close(); + std::cerr << "Warning: directory not writable! " << dir_str << std::endl; + return false; + } else { + test_file.close(); + boost::filesystem::remove (test_file_path); + return true; + } + + return false; +} diff --git a/engine/Utils.h b/engine/Utils.h new file mode 100644 index 0000000..a986bca --- /dev/null +++ b/engine/Utils.h @@ -0,0 +1,9 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#include + +std::string strip_whitespaces (const std::string input_str); +bool create_dir (const std::string &dir_str); + +#endif /* _UTILS_H */