From 5e0663017ab253d5888ec47bcf69cc25c110104f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=A4henb=C3=BChl?= Date: Mon, 23 Aug 2021 17:09:08 -0500 Subject: [PATCH] New init function and graphics config. (#32) * Removing the SUPERTUXKART_DATADIR env variable * Creating a none graphics config --- CMakeLists.txt | 12 ------- examples/benchmark.py | 10 +++--- pystk_cpp/binding.cpp | 23 ++++-------- pystk_cpp/pickle.cpp | 2 ++ pystk_cpp/pystk.cpp | 36 ++++++++++++++----- pystk_cpp/pystk.hpp | 8 +++-- pystk_data/setup.py | 2 +- src/io/file_manager.cpp | 79 ++++------------------------------------- src/io/file_manager.hpp | 2 +- 9 files changed, 55 insertions(+), 119 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc08d045d..e07a631b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,18 +162,6 @@ LIST(REMOVE_ITEM STK_SOURCES "src/main.cpp") if(APPLE) add_library(stk ${STK_SOURCES} ${STK_RESOURCES} ${STK_HEADERS}) else() - # Set data dir (absolute or relative to CMAKE_INSTALL_PREFIX) - if(NOT STK_INSTALL_DATA_DIR_ABSOLUTE) - get_filename_component(STK_INSTALL_DATA_DIR_ABSOLUTE ${STK_INSTALL_DATA_DIR} ABSOLUTE) - if(${STK_INSTALL_DATA_DIR_ABSOLUTE} STREQUAL ${STK_INSTALL_DATA_DIR}) - add_definitions(-DSUPERTUXKART_DATADIR=\"${STK_INSTALL_DATA_DIR_ABSOLUTE}\") - else() - add_definitions(-DSUPERTUXKART_DATADIR=\"${CMAKE_INSTALL_PREFIX}/${STK_INSTALL_DATA_DIR}\") - endif() - else() - add_definitions(-DSUPERTUXKART_DATADIR=\"${STK_INSTALL_DATA_DIR_ABSOLUTE}\") - endif() - add_library(stk ${STK_SOURCES} ${STK_RESOURCES} ${STK_HEADERS}) endif() diff --git a/examples/benchmark.py b/examples/benchmark.py index 2520932c7..2c7ef51d2 100644 --- a/examples/benchmark.py +++ b/examples/benchmark.py @@ -15,14 +15,14 @@ t0 = time() render = True if config is None: - config = pystk.GraphicsConfig.ld() - render = False - config.screen_width = 320 - config.screen_height = 240 + config = pystk.GraphicsConfig.none() + else: + config.screen_width = 320 + config.screen_height = 240 pystk.init(config) init_time, t0 = time() - t0, time() - config = pystk.RaceConfig(render=render) + config = pystk.RaceConfig() if args.kart != '': config.players[0].kart = args.kart if args.track is not None: diff --git a/pystk_cpp/binding.cpp b/pystk_cpp/binding.cpp index db156bb52..e35814891 100644 --- a/pystk_cpp/binding.cpp +++ b/pystk_cpp/binding.cpp @@ -25,10 +25,7 @@ PYBIND11_MAKE_OPAQUE(std::vector); void path_and_init(const PySTKGraphicsConfig & config) { auto pystk_data = py::module::import("pystk_data"), os = py::module::import("os"); - auto env = os.attr("environ"); - // Give supertuxkart a hint where the assets are - env["SUPERTUXKART_DATADIR"] = py::str(pystk_data.attr("data_dir")); - PySTKRace::init(config); + PySTKRace::init(config, py::cast(py::str(pystk_data.attr("data_dir")))); } PYBIND11_MODULE(pystk, m) { m.doc() = "Python SuperTuxKart interface"; @@ -39,13 +36,6 @@ PYBIND11_MODULE(pystk, m) { m.attr("has_graphics") = true; #endif // SERVER_ONLY - // Make offscreen rendering default - if (!getenv("IRR_DEVICE_TYPE")) -#ifdef WIN32 - _putenv_s("IRR_DEVICE_TYPE", "offscreen"); -#else - setenv("IRR_DEVICE_TYPE", "offscreen", 0); -#endif // Adjust the log level Log::setLogLevel(Log::LL_FATAL); if (getenv("PYSTK_LOG_LEVEL")) { @@ -91,7 +81,7 @@ PYBIND11_MODULE(pystk, m) { { py::class_> cls(m, "GraphicsConfig", "SuperTuxKart graphics configuration."); - cls.def(py::init(), py::arg("screen_width") = 600, py::arg("screen_height") = 400, py::arg("display_adapter") = 0, py::arg("glow") = false, py::arg("") = true, py::arg("") = true, py::arg("") = true, py::arg("") = true, py::arg("particles_effects") = 2, py::arg("animated_characters") = true, py::arg("motionblur") = true, py::arg("mlaa") = true, py::arg("texture_compression") = true, py::arg("ssao") = true, py::arg("degraded_IBL") = false, py::arg("high_definition_textures") = 2 | 1) + cls.def(py::init(), py::arg("screen_width") = 600, py::arg("screen_height") = 400, py::arg("display_adapter") = 0, py::arg("glow") = false, py::arg("") = true, py::arg("") = true, py::arg("") = true, py::arg("") = true, py::arg("particles_effects") = 2, py::arg("animated_characters") = true, py::arg("motionblur") = true, py::arg("mlaa") = true, py::arg("texture_compression") = true, py::arg("ssao") = true, py::arg("degraded_IBL") = false, py::arg("high_definition_textures") = 2 | 1, py::arg("render") = true) .def_readwrite("screen_width", &PySTKGraphicsConfig::screen_width, "Width of the rendering surface") .def_readwrite("screen_height", &PySTKGraphicsConfig::screen_height, "Height of the rendering surface") .def_readwrite("display_adapter", &PySTKGraphicsConfig::display_adapter, "GPU to use (Linux only)") @@ -107,12 +97,14 @@ PYBIND11_MODULE(pystk, m) { .def_readwrite("texture_compression", &PySTKGraphicsConfig::texture_compression, "Use texture compression") .def_readwrite("ssao", &PySTKGraphicsConfig::ssao, "Enable screen space ambient occlusion") .def_readwrite("degraded_IBL", &PySTKGraphicsConfig::degraded_IBL, "Disable specular IBL") - .def_readwrite("high_definition_textures", &PySTKGraphicsConfig::high_definition_textures, "Enable high definition textures 0 / 2"); + .def_readwrite("high_definition_textures", &PySTKGraphicsConfig::high_definition_textures, "Enable high definition textures 0 / 2") + .def_readwrite("render", &PySTKGraphicsConfig::render, "Is rendering enabled?"); add_pickle(cls); cls.def_static("hd", &PySTKGraphicsConfig::hd, "High-definitaiton graphics settings"); cls.def_static("sd", &PySTKGraphicsConfig::sd, "Standard-definition graphics settings"); cls.def_static("ld", &PySTKGraphicsConfig::ld, "Low-definition graphics settings"); + cls.def_static("none", &PySTKGraphicsConfig::none, "Disable graphics and rendering"); } { @@ -145,7 +137,7 @@ PYBIND11_MODULE(pystk, m) { .value("SOCCER", PySTKRaceConfig::RaceMode::SOCCER); cls - .def(py::init,std::string,bool,int,int,int,float,bool>(), py::arg("difficulty") = 2, py::arg("mode") = PySTKRaceConfig::NORMAL_RACE, py::arg("players") = std::vector{{"",PySTKPlayerConfig::PLAYER_CONTROL}}, py::arg("track") = "", py::arg("reverse") = false, py::arg("laps") = 3, py::arg("seed") = 0, py::arg("num_kart") = 1, py::arg("step_size") = 0.1, py::arg("render") = true) + .def(py::init,std::string,bool,int,int,int,float>(), py::arg("difficulty") = 2, py::arg("mode") = PySTKRaceConfig::NORMAL_RACE, py::arg("players") = std::vector{{"",PySTKPlayerConfig::PLAYER_CONTROL}}, py::arg("track") = "", py::arg("reverse") = false, py::arg("laps") = 3, py::arg("seed") = 0, py::arg("num_kart") = 1, py::arg("step_size") = 0.1) .def_readwrite("difficulty", &PySTKRaceConfig::difficulty, "Skill of AI players 0..2") .def_readwrite("mode", &PySTKRaceConfig::mode, "Specify the type of race") .def_readwrite("players", &PySTKRaceConfig::players, "List of all agent players") @@ -154,8 +146,7 @@ PYBIND11_MODULE(pystk, m) { .def_readwrite("laps", &PySTKRaceConfig::laps, "Number of laps the race runs for") .def_readwrite("seed", &PySTKRaceConfig::seed, "Random seed") .def_readwrite("num_kart", &PySTKRaceConfig::num_kart, "Total number of karts, fill the race with num_kart - len(players) AI karts") - .def_readwrite("step_size", &PySTKRaceConfig::step_size, "Game time between different step calls") - .def_readwrite("render", &PySTKRaceConfig::render, "Is rendering enabled?"); + .def_readwrite("step_size", &PySTKRaceConfig::step_size, "Game time between different step calls"); add_pickle(cls); } diff --git a/pystk_cpp/pickle.cpp b/pystk_cpp/pickle.cpp index 1d16a2b8d..c46a9a5c4 100644 --- a/pystk_cpp/pickle.cpp +++ b/pystk_cpp/pickle.cpp @@ -30,6 +30,7 @@ void pickle(std::ostream & s, const PySTKGraphicsConfig & o) { pickle(s, o.ssao); pickle(s, o.degraded_IBL); pickle(s, o.high_definition_textures); + pickle(s, o.render); } void unpickle(std::istream & s, PySTKGraphicsConfig * o) { unpickle(s, &o->screen_width); @@ -48,6 +49,7 @@ void unpickle(std::istream & s, PySTKGraphicsConfig * o) { unpickle(s, &o->ssao); unpickle(s, &o->degraded_IBL); unpickle(s, &o->high_definition_textures); + unpickle(s, &o->render); } void pickle(std::ostream & s, const PySTKPlayerConfig & o) { pickle(s, o.kart); diff --git a/pystk_cpp/pystk.cpp b/pystk_cpp/pystk.cpp index 619d3e4bf..a26db25ea 100644 --- a/pystk_cpp/pystk.cpp +++ b/pystk_cpp/pystk.cpp @@ -141,6 +141,21 @@ const PySTKGraphicsConfig & PySTKGraphicsConfig::ld() { }; return config; } +const PySTKGraphicsConfig & PySTKGraphicsConfig::none() { + static PySTKGraphicsConfig config = {1,1, 0, + false, false, false, false, false, + 0, // particle_effects + false, // animated_characters + false, // motionblur + false, // mlaa + false, // texture_compression + false, // ssao + false, // degraded_IBL + 0, // high_definition_textures + false, // render + }; + return config; +} #ifndef SERVER_ONLY class PySTKRenderTarget { @@ -211,18 +226,20 @@ void PySTKAction::get(const KartControl * control) { } PySTKRace * PySTKRace::running_kart = 0; +PySTKGraphicsConfig PySTKRace::graphics_config_ = {}; static int is_init = 0; #ifdef RENDERDOC static RENDERDOC_API_1_1_2 *rdoc_api = NULL; #endif -void PySTKRace::init(const PySTKGraphicsConfig & config) { +void PySTKRace::init(const PySTKGraphicsConfig & config, const std::string & data_dir) { if (running_kart) throw std::invalid_argument("Cannot init while supertuxkart is running!"); if (is_init) { throw std::invalid_argument("PySTK already initialized! Call clean first!"); } else { is_init = 1; - initUserConfig(); + graphics_config_ = config; + initUserConfig(data_dir); stk_config->load(file_manager->getAsset("stk_config.xml")); initGraphicsConfig(config); initRest(); @@ -273,8 +290,9 @@ PySTKRace::PySTKRace(const PySTKRaceConfig & config) { setupConfig(config); #ifndef SERVER_ONLY - for(int i=0; i(irr_driver->createRenderTarget( {(unsigned int)UserConfigParams::m_width, (unsigned int)UserConfigParams::m_height}, "player"+std::to_string(i))) ); + if (graphics_config_.render) + for(int i=0; i(irr_driver->createRenderTarget( {(unsigned int)UserConfigParams::m_width, (unsigned int)UserConfigParams::m_height}, "player"+std::to_string(i))) ); #endif // SERVER_ONLY } std::vector PySTKRace::listTracks() { @@ -373,7 +391,7 @@ void PySTKRace::stop() { void PySTKRace::render(float dt) { World *world = World::getWorld(); #ifndef SERVER_ONLY - if (world) + if (world && graphics_config_.render) { // Render all views for(unsigned int i = 0; i < Camera::getNumCameras() && i < render_targets_.size(); i++) { @@ -421,7 +439,7 @@ bool PySTKRace::step() { PropertyAnimator::get()->update(dt); // Then render - if (config_.render) { + if (graphics_config_.render) { World::getWorld()->updateGraphics(dt); irr_driver->minimalUpdate(dt); @@ -430,7 +448,7 @@ bool PySTKRace::step() { World::getWorld()->updateGraphicsMinimal(dt); } - if (config_.render && !irr_driver->getDevice()->run()) + if (graphics_config_.render && !irr_driver->getDevice()->run()) return false; #ifdef RENDERDOC if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); @@ -531,9 +549,9 @@ void PySTKRace::initGraphicsConfig(const PySTKGraphicsConfig & config) { //============================================================================= /** Initialises the minimum number of managers to get access to user_config. */ -void PySTKRace::initUserConfig() +void PySTKRace::initUserConfig(const std::string & data_dir) { - file_manager = new FileManager(); + file_manager = new FileManager(data_dir); // Some parts of the file manager needs user config (paths for models // depend on artist debug flag). So init the rest of the file manager // after reading the user config file. diff --git a/pystk_cpp/pystk.hpp b/pystk_cpp/pystk.hpp index 9e4fc860e..eb91f4ac8 100644 --- a/pystk_cpp/pystk.hpp +++ b/pystk_cpp/pystk.hpp @@ -15,10 +15,12 @@ struct PySTKGraphicsConfig { bool ssao = true; bool degraded_IBL = false; int high_definition_textures = 2 | 1; + bool render = true; static const PySTKGraphicsConfig & hd(); static const PySTKGraphicsConfig & sd(); static const PySTKGraphicsConfig & ld(); + static const PySTKGraphicsConfig & none(); }; struct PySTKPlayerConfig { enum Controller: uint8_t { @@ -49,7 +51,6 @@ struct PySTKRaceConfig { int seed = 0; int num_kart = 1; float step_size = 0.1; - bool render = true; }; class PySTKRenderTarget; @@ -77,14 +78,15 @@ struct PySTKAction { class PySTKRace { protected: // Static methods static void initRest(); - static void initUserConfig(); + static void initUserConfig(const std::string & data_dir); static void initGraphicsConfig(const PySTKGraphicsConfig & config); static void cleanSuperTuxKart(); static void cleanUserConfig(); + static PySTKGraphicsConfig graphics_config_; public: // Static methods static PySTKRace * running_kart; - static void init(const PySTKGraphicsConfig & config); + static void init(const PySTKGraphicsConfig & config, const std::string & data_dir); static void load(); static void clean(); static bool isRunning(); diff --git a/pystk_data/setup.py b/pystk_data/setup.py index e48e72cc6..9a25713f6 100644 --- a/pystk_data/setup.py +++ b/pystk_data/setup.py @@ -78,7 +78,7 @@ def ignore(base, entries): setup( name='PySuperTuxKartData', - version='1.0.0', + version='1.0.1', author='Philipp Krähenbühl', author_email='philkr@utexas.edu', description='Python SuperTuxKart interface -- data package', diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index 65f499de1..0269a05ab 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -127,7 +127,7 @@ FileManager* file_manager = 0; * config file is read. This is necessary since part of discoverPaths * depend on artist debug mode. */ -FileManager::FileManager() +FileManager::FileManager(const std::string & data_dir) { m_subdir_name.resize(ASSET_COUNT); m_subdir_name[CHALLENGE ] = "challenges"; @@ -169,44 +169,11 @@ FileManager::FileManager() // Also check for data dirs relative to the path of the executable. // This is esp. useful for Visual Studio, since it's not necessary // to define the working directory when debugging, it works automatically. - std::string root_dir; + std::string root_dir = data_dir; const std::string version = std::string("supertuxkart.git"); - if (fileExists(CommandLine::getExecName())) - { - exe_path = StringUtils::getPath(CommandLine::getExecName()); - } - if(exe_path.size()==0 || exe_path[exe_path.size()-1]!='/') - exe_path += "/"; - if ( getenv ( "SUPERTUXKART_DATADIR" ) != NULL && fileExists((std::string(getenv("SUPERTUXKART_DATADIR"))+"/data/").c_str(), version) ) - root_dir = std::string(getenv("SUPERTUXKART_DATADIR"))+"/data/" ; -#ifdef __APPLE__ -// else if( macSetBundlePathIfRelevant( root_dir ) ) { root_dir = root_dir + "data/"; } -#endif - else if(fileExists("data/", version)) - root_dir = "data/" ; - else if(fileExists("../data/", version)) - root_dir = "../data/" ; - else if(fileExists("../../data/", version)) - root_dir = "../../data/" ; - // Test for old style build environment, with executable in root of stk - else if(fileExists(exe_path+"data/"+version)) - root_dir = (exe_path+"data/").c_str(); - // Check for windows cmake style: bld/Debug/bin/supertuxkart.exe - else if (fileExists(exe_path + "../../../data/"+version)) - root_dir = exe_path + "../../../data/"; - else if (fileExists(exe_path + "../data/"+version)) - { - root_dir = exe_path.c_str(); - root_dir += "../data/"; - } - else - { -#ifdef SUPERTUXKART_DATADIR - root_dir = SUPERTUXKART_DATADIR"/data/"; -#else - root_dir = "/usr/local/share/games/supertuxkart/"; -#endif - } + + if (m_file_system->existFile((root_dir+"/data/"+version).c_str())) + root_dir = root_dir + "/data/"; if (!m_file_system->existFile((root_dir + version).c_str())) { @@ -215,39 +182,13 @@ FileManager::FileManager() Log::error("FileManager", "Last location checked '%s'.", root_dir.c_str()); Log::fatal("FileManager", - "Set $SUPERTUXKART_DATADIR to point to the data directory."); + "Failed to locate PySuperTuxKartData. Got '%s', but data not found!", data_dir.c_str()); // fatal will exit the application } addRootDirs(root_dir); - addRootDirs(root_dir + "../stk-assets/"); std::string assets_dir; -#ifdef MOBILE_STK - // Check if the bundled data includes stk-assets, if not download it later - // Check only 1 entry for now (karts) - if (!fileExists(root_dir + "/karts")) - { - assets_dir = getenv("HOME"); -#ifdef IOS_STK - assets_dir += "/Library/Application Support/SuperTuxKart/stk-assets"; -#elif defined (ANDROID) - assets_dir += "/stk-assets"; -#endif - m_stk_assets_download_dir = assets_dir; - // Those will be filled with real data later - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/karts"); - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/library"); - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/models"); - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/music"); - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/textures"); - checkAndCreateDirectoryP(m_stk_assets_download_dir + "/tracks"); - } -#else - if (getenv("SUPERTUXKART_ASSETS_DIR") != NULL) - { - assets_dir = std::string(getenv("SUPERTUXKART_ASSETS_DIR")); - } - else if (fileExists(root_dir + "../../stk-assets")) + if (fileExists(root_dir + "../../stk-assets")) { assets_dir = root_dir + "../../stk-assets"; } @@ -255,12 +196,6 @@ FileManager::FileManager() { assets_dir = root_dir + "../../supertuxkart-assets"; } - else if (getenv("SUPERTUXKART_ROOT_PATH") != NULL) - { - //is this needed? - assets_dir = std::string(getenv("SUPERTUXKART_ROOT_PATH")); - } -#endif if (!assets_dir.empty() && assets_dir != root_dir) { addRootDirs(assets_dir); diff --git a/src/io/file_manager.hpp b/src/io/file_manager.hpp index e55cabe84..2d2d378ef 100644 --- a/src/io/file_manager.hpp +++ b/src/io/file_manager.hpp @@ -132,7 +132,7 @@ class FileManager : public NoCopy #endif public: - FileManager(); + FileManager(const std::string & data_dir); ~FileManager(); void init(); void reinitAfterDownloadAssets();