From 8ce23fe0786c7444c92c2d95b872bbe1f7fa7679 Mon Sep 17 00:00:00 2001 From: Ben Krajancic Date: Tue, 10 Oct 2017 09:53:15 +1100 Subject: [PATCH 01/43] Small clarification to prevent build errors Building outside of this directory prevents the executable from launching, this small addition can help prevent this issue from happening. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6722749791..03804f03cb6 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ To Build SuperTuxKart on Windows, follow these instructions: *Note: If you downloaded the source package from here: [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), then both `stk-code` and `stk-assets` **must** be in the same directory, otherwise the build can result in failure* 3. Download the Windows dependencies package from either [SuperTuxKart download area: Dependecies - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/) or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies), and unpack it; then, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory -4. Download CMake from here: [CMake - download page](https://cmake.org/download/), install it; once CMake is installed, double click on the CMake icon on your desktop, and point it towards your `stk-code` directory in the 'Where is the source code' field, and point it to a directory called `build` or `bld` +4. Download CMake from here: [CMake - download page](https://cmake.org/download/), install it; once CMake is installed, double click on the CMake icon on your desktop, and point it towards your `stk-code` directory in the 'Where is the source code' field, and point it to a directory called `build` or `bld` inside the stk-code directory. 5. Press 'Configure'; CMake will ask you if it is OK to create the aformentioned directory, press `Yes`. CMake will then ask you about your version of Visual Studio. Confirm your selection; *Please look at the table below to avoid confusion between version numbers and releases of Visual Studio*; CMake will begin creating the required files for the build in the directory. From 74cdd07ba7b5c7a66c1fece1b434eda5240a09fb Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Thu, 26 Oct 2017 09:11:57 +1100 Subject: [PATCH 02/43] Added string array for karts per gamemode, and references to it to replace num_karts --- src/config/user_config.hpp | 17 ++++++++++++++++- src/states_screens/track_info_screen.cpp | 11 +++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 457c19192e5..5b61479ffbc 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -369,7 +369,22 @@ namespace UserConfigParams PARAM_PREFIX StringUserConfigParam m_last_used_kart_group PARAM_DEFAULT( StringUserConfigParam("all", "last_kart_group", "Last selected kart group") ); - + // ---- Gamemode setup + + PARAM_PREFIX StringListUserConfigParam m_karts_per_gamemode + PARAM_DEFAULT(StringListUserConfigParam("karts_per_gamemode", + "Number of karts per gamemode. Order corresponds to Enum value", + 10, + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3", + "3")); // ---- Wiimote data PARAM_PREFIX GroupUserConfigParam m_wiimote_group PARAM_DEFAULT( GroupUserConfigParam("WiiMote", diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index f4ea1bc9b13..f99741ee7e4 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -163,15 +163,20 @@ void TrackInfoScreen::init() race_manager->hasAI()); m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); + + std::vector karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; + if (has_AI) { m_ai_kart_spinner->setActive(true); - + + int num_ai = stoi(karts_per_gamemode[race_manager->getMinorMode()]) - local_players; // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - int num_ai = UserConfigParams::m_num_karts - local_players; + if (num_ai < 0) num_ai = 0; m_ai_kart_spinner->setValue(num_ai); + race_manager->setNumKarts(num_ai + local_players); // Set the max karts supported based on the battle arena selected if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES || @@ -240,6 +245,8 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setValue(0); m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); + karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); + UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); } else if (record_available) From df69a684a3635b60e4ca1fa0e360175e84de1d41 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Thu, 26 Oct 2017 09:39:48 +1100 Subject: [PATCH 03/43] Identified cause of compile error --- src/config/user_config.hpp | 4 +++- src/states_screens/track_info_screen.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 5b61479ffbc..d95610a9111 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -371,8 +371,9 @@ namespace UserConfigParams "Last selected kart group") ); // ---- Gamemode setup + PARAM_PREFIX StringListUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(StringListUserConfigParam("karts_per_gamemode", + PARAM_DEFAULT(StringListUserConfigParam("karts_per_gamemode", "The karts per gamemode" "Number of karts per gamemode. Order corresponds to Enum value", 10, "3", @@ -385,6 +386,7 @@ namespace UserConfigParams "3", "3", "3")); + // ---- Wiimote data PARAM_PREFIX GroupUserConfigParam m_wiimote_group PARAM_DEFAULT( GroupUserConfigParam("WiiMote", diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index f99741ee7e4..55007ff474b 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -245,8 +245,10 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setValue(0); m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); - UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; + + //This is causing an error + karts_per_gamemode[race_manager->getMinorMode()] = std::to_string(race_manager->getNumLocalPlayers()); + UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; //Causes error UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); } else if (record_available) From af7fefee1e5744d3e68599600876347d1f69f99b Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Thu, 26 Oct 2017 11:32:43 +1100 Subject: [PATCH 04/43] note errors --- src/states_screens/track_info_screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index 55007ff474b..f789e59bde0 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -169,8 +169,8 @@ void TrackInfoScreen::init() if (has_AI) { m_ai_kart_spinner->setActive(true); - - int num_ai = stoi(karts_per_gamemode[race_manager->getMinorMode()]) - local_players; + int gamemode = race_manager->getMinorMode(); + int num_ai = stoi(karts_per_gamemode[gamemode]) - local_players; //TODO error caused by enums not being sequential // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. @@ -248,7 +248,7 @@ void TrackInfoScreen::init() //This is causing an error karts_per_gamemode[race_manager->getMinorMode()] = std::to_string(race_manager->getNumLocalPlayers()); - UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; //Causes error + // UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; //TODO Causes error UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); } else if (record_available) From 823d3112ad678a2886bc39f528f1c92ce73ef8f3 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Fri, 27 Oct 2017 22:31:54 +1100 Subject: [PATCH 05/43] Begun making template for dictionary --- src/config/user_config.cpp | 139 +++++++++++++++++++++++ src/config/user_config.hpp | 52 ++++++++- src/states_screens/track_info_screen.cpp | 2 +- 3 files changed, 188 insertions(+), 5 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 95f013d9147..954f4beb26c 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -321,7 +321,146 @@ core::stringc ListUserConfigParam::toString() const return ""; } // toString + // ============================================================================ +template +MapUserConfigParam::MapUserConfigParam(const char* param_name, + const char* comment) +{ + m_param_name = param_name; + all_params.push_back(this); + if (comment != NULL) m_comment = comment; +} // MapUserConfigParam + + // ============================================================================ +template +MapUserConfigParam::MapUserConfigParam(const char* param_name, + const char* comment, + int nb_elements, + ...) +{ + m_param_name = param_name; + all_params.push_back(this); + if (comment != NULL) m_comment = comment; + + // add the default list + va_list arguments; + va_start(arguments, nb_elements); + for (int i = 0; i < nb_elements; i++) + m_elements.push_back(T(va_arg(arguments, U))); + va_end(arguments); // Cleans up the list +} // MapUserConfigParam + + // ============================================================================ +template +MapUserConfigParam::MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment) +{ + m_param_name = param_name; + group->addChild(this); + if (comment != NULL) m_comment = comment; +} // MapUserConfigParam + + // ============================================================================ +template +MapUserConfigParam::MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment, + int nb_elements, + ...) +{ + m_param_name = param_name; + group->addChild(this); + if (comment != NULL) m_comment = comment; + + // add the default list + va_list arguments; + va_start(arguments, nb_elements); + for (int i = 0; i < nb_elements; i++) + m_elements.push_back(va_arg(arguments, T)); + va_end(arguments); // Cleans up the list +} // MapUserConfigParam + + // ---------------------------------------------------------------------------- +template +void MapUserConfigParam::write(std::ofstream& stream) const +{ + const int elts_amount = m_elements.size(); + + // comment + if (m_comment.size() > 0) stream << " \n <" << m_param_name.c_str() << "\n"; + + stream << " Size=\"" << elts_amount << "\"\n"; + // actual elements + //for (int n = 0; n::iterator it = m_elements.begin(); it != m_elements.end(); ++it) + { + stream << " " << it->first << "=\"" << it->second << "\"\n"; + } + stream << " >\n"; + stream << " \n\n"; +} // write + + // ---------------------------------------------------------------------------- + +template +void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) +{ + const XMLNode* child = node->getNode(m_param_name); + if (child == NULL) + { + //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str()); + return; + } + + int attr_count = 0; + child->get("Size", &attr_count); + for (int n = 0; nget(StringUtils::toString(n), &str); + StringUtils::fromString(str, elt); + + // check if the element is already there : + bool there = false; + for (unsigned int i = 0; i < m_elements.size(); i++) + { + if (elt == m_elements[i]) + { + there = true; + break; + } + } + if (!there) + { + m_elements.push_back(elt); + } + } +} // findYourDataInAChildOf + + // ---------------------------------------------------------------------------- +template +void MapUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node) +{ +} // findYourDataInAnAttributeOf + + // ---------------------------------------------------------------------------- +template +void MapUserConfigParam::addElement(T element, U value) +{ + m_elements[element] = value; +} // findYourDataInAnAttributeOf + + // ---------------------------------------------------------------------------- +template +core::stringc MapUserConfigParam::toString() const +{ + return ""; +} // toString // ============================================================================ IntUserConfigParam::IntUserConfigParam(int default_value, diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index d95610a9111..f76161f081e 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -136,6 +136,50 @@ class ListUserConfigParam : public UserConfigParam }; // ListUserConfigParam typedef ListUserConfigParam StringListUserConfigParam; +template +class MapUserConfigParam : public UserConfigParam +{ + std::map m_elements; + +public: + MapUserConfigParam(const char* param_name, + const char* comment = NULL); + MapUserConfigParam(const char* param_name, + const char* comment, + int nb_elts, + ...); + MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment = NULL); + MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment, + int nb_elts, + ...); + + void write(std::ofstream& stream) const; + void findYourDataInAChildOf(const XMLNode* node); + void findYourDataInAnAttributeOf(const XMLNode* node); + + void addElement(T element, U value); + + irr::core::stringc toString() const; + + operator std::map() const + { + return m_elements; + } + float& operator=(const std::map& v) + { + m_elements = std::map(v); return m_elements; + } + float& operator=(const MapUserConfigParam& v) + { + m_elements = std::map(v); return m_elements; + } +}; // ListUserConfigParam +typedef MapUserConfigParam StringToStringUserConfigParam; + // ============================================================================ class IntUserConfigParam : public UserConfigParam { @@ -372,12 +416,12 @@ namespace UserConfigParams // ---- Gamemode setup - PARAM_PREFIX StringListUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(StringListUserConfigParam("karts_per_gamemode", "The karts per gamemode" + PARAM_PREFIX StringToStringUserConfigParam m_karts_per_gamemode + PARAM_DEFAULT(StringToStringUserConfigParam("karts_per_gamemode", "The karts per gamemode" "Number of karts per gamemode. Order corresponds to Enum value", 10, - "3", - "3", + "3", + "3", "3", "3", "3", diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index f789e59bde0..7e956dbf6e4 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -164,7 +164,7 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); - std::vector karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; + std::vector karts_per_gamemode;//UserConfigParams::m_karts_per_gamemode; if (has_AI) { From f10feb77fdb614c60d498db029f6ab4e8a36adaf Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 09:16:28 +1100 Subject: [PATCH 06/43] Can now load a map type --- src/config/user_config.cpp | 44 ++++++++++++++---------- src/config/user_config.hpp | 27 ++++++--------- src/states_screens/track_info_screen.cpp | 13 ++++--- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 954f4beb26c..50fe0d76d9d 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -29,6 +29,7 @@ static PtrVector all_params; // X-macros #define PARAM_PREFIX #define PARAM_DEFAULT(X) = X + #include "config/user_config.hpp" #include "config/saved_grand_prix.hpp" @@ -345,8 +346,11 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - for (int i = 0; i < nb_elements; i++) - m_elements.push_back(T(va_arg(arguments, U))); + typedef std::pair DictThing; + for (int i = 0; i < nb_elements; i++) { + std::pair key_value_pair = va_arg(arguments, DictThing); + m_elements.insert(key_value_pair); + } va_end(arguments); // Cleans up the list } // MapUserConfigParam @@ -376,8 +380,11 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - for (int i = 0; i < nb_elements; i++) - m_elements.push_back(va_arg(arguments, T)); + + for (int i = 0; i < nb_elements; i++) { + std::pair key_value_pair = va_arg(arguments, DictThing); + m_elements.insert(key_value_pair); + } va_end(arguments); // Cleans up the list } // MapUserConfigParam @@ -395,9 +402,8 @@ void MapUserConfigParam::write(std::ofstream& stream) const // actual elements //for (int n = 0; n::iterator it = m_elements.begin(); it != m_elements.end(); ++it) - { - stream << " " << it->first << "=\"" << it->second << "\"\n"; + for (const auto& kv : m_elements) { + stream << " " << kv.first << "=\"" << kv.second << "\"\n"; } stream << " >\n"; stream << " \n\n"; @@ -417,29 +423,29 @@ void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) int attr_count = 0; child->get("Size", &attr_count); - for (int n = 0; n elt; std::string str; - child->get(StringUtils::toString(n), &str); - StringUtils::fromString(str, elt); - - // check if the element is already there : + child->get(kv.first, &str); + elt.first = kv.first; + elt.second = str.c_str(); + bool there = false; - for (unsigned int i = 0; i < m_elements.size(); i++) - { - if (elt == m_elements[i]) + + for (const auto& kvRHS : m_elements) { + if (elt.second == kvRHS.second) { there = true; break; } + } if (!there) { - m_elements.push_back(elt); + m_elements.insert(elt); } } - } // findYourDataInAChildOf // ---------------------------------------------------------------------------- diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index f76161f081e..6f71d9389b1 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -178,7 +178,7 @@ class MapUserConfigParam : public UserConfigParam m_elements = std::map(v); return m_elements; } }; // ListUserConfigParam -typedef MapUserConfigParam StringToStringUserConfigParam; +typedef MapUserConfigParam StringToStringUserConfigParam; // ============================================================================ class IntUserConfigParam : public UserConfigParam @@ -416,20 +416,7 @@ namespace UserConfigParams // ---- Gamemode setup - PARAM_PREFIX StringToStringUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(StringToStringUserConfigParam("karts_per_gamemode", "The karts per gamemode" - "Number of karts per gamemode. Order corresponds to Enum value", - 10, - "3", - "3", - "3", - "3", - "3", - "3", - "3", - "3", - "3", - "3")); + // ---- Wiimote data PARAM_PREFIX GroupUserConfigParam m_wiimote_group @@ -766,7 +753,15 @@ namespace UserConfigParams "stun.voxalot.com", "stun.voxgratia.org", "stun.xten.com") ); - + PARAM_PREFIX StringToStringUserConfigParam m_karts_per_gamemode + PARAM_DEFAULT(StringToStringUserConfigParam("karts_per_gamemode", "The karts per gamemode" + "Number of karts per gamemode. Order corresponds to Enum value", + 4, + std::make_pair("3", "1"), + std::make_pair("f", "2"), + std::make_pair("e", "4"), + std::make_pair("te", "5") + )); PARAM_PREFIX BoolUserConfigParam m_log_packets PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets", "If all network packets should be logged") ); diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index 7e956dbf6e4..d13ec39b9a2 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -164,14 +164,19 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); - std::vector karts_per_gamemode;//UserConfigParams::m_karts_per_gamemode; + UserConfigParams::m_num_karts; + std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; + auto data = UserConfigParams::m_karts_per_gamemode; if (has_AI) { m_ai_kart_spinner->setActive(true); int gamemode = race_manager->getMinorMode(); - int num_ai = stoi(karts_per_gamemode[gamemode]) - local_players; //TODO error caused by enums not being sequential - // Avoid negative numbers (which can happen if e.g. the number of karts + //Temp fix + //int num_ai = stoi(karts_per_gamemode[ "3"/*gamemode*/]) - local_players; //TODO error caused by enums not being sequential + int num_ai = 1; + + // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. if (num_ai < 0) num_ai = 0; @@ -247,7 +252,7 @@ void TrackInfoScreen::init() race_manager->setNumKarts(race_manager->getNumLocalPlayers()); //This is causing an error - karts_per_gamemode[race_manager->getMinorMode()] = std::to_string(race_manager->getNumLocalPlayers()); +/// karts_per_gamemode[race_manager->getMinorMode()] = std::to_string(race_manager->getNumLocalPlayers()); // UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; //TODO Causes error UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); } From ca330b1ac0aad9391905285c861a254495f3942f Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 11:35:11 +1100 Subject: [PATCH 07/43] Map compiles now and can be set --- src/config/user_config.cpp | 5 ++--- src/config/user_config.hpp | 24 +++++++++++---------- src/states_screens/track_info_screen.cpp | 27 ++++++++++++------------ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 50fe0d76d9d..e2d93c2b862 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -426,10 +426,9 @@ void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) for (const auto& kv : m_elements) { std::pair elt; - std::string str; - child->get(kv.first, &str); elt.first = kv.first; - elt.second = str.c_str(); + elt.second = kv.second; + bool there = false; diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 6f71d9389b1..ab58ddd2a57 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -169,17 +169,19 @@ class MapUserConfigParam : public UserConfigParam { return m_elements; } - float& operator=(const std::map& v) + std::map& operator=(const std::map& v) { - m_elements = std::map(v); return m_elements; + m_elements = std::map(v); + return m_elements; } - float& operator=(const MapUserConfigParam& v) + std::map& operator=(const MapUserConfigParam& v) { - m_elements = std::map(v); return m_elements; + m_elements = std::map(v); + return m_elements; } }; // ListUserConfigParam typedef MapUserConfigParam StringToStringUserConfigParam; - +typedef MapUserConfigParam IntToIntUserConfigParam; // ============================================================================ class IntUserConfigParam : public UserConfigParam { @@ -753,14 +755,14 @@ namespace UserConfigParams "stun.voxalot.com", "stun.voxgratia.org", "stun.xten.com") ); - PARAM_PREFIX StringToStringUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(StringToStringUserConfigParam("karts_per_gamemode", "The karts per gamemode" + PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode + PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", "The karts per gamemode" "Number of karts per gamemode. Order corresponds to Enum value", 4, - std::make_pair("3", "1"), - std::make_pair("f", "2"), - std::make_pair("e", "4"), - std::make_pair("te", "5") + std::make_pair(0, 1), + std::make_pair(1, 2), + std::make_pair(3, 4), + std::make_pair(4, 5) )); PARAM_PREFIX BoolUserConfigParam m_log_packets PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets", diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index d13ec39b9a2..cab8ae79578 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -165,21 +165,24 @@ void TrackInfoScreen::init() getWidget("ai-text")->setVisible(has_AI); UserConfigParams::m_num_karts; - std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; - auto data = UserConfigParams::m_karts_per_gamemode; + std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; if (has_AI) { m_ai_kart_spinner->setActive(true); int gamemode = race_manager->getMinorMode(); - //Temp fix - //int num_ai = stoi(karts_per_gamemode[ "3"/*gamemode*/]) - local_players; //TODO error caused by enums not being sequential - int num_ai = 1; - - // Avoid negative numbers (which can happen if e.g. the number of karts + int num_ai = karts_per_gamemode[gamemode]; + + // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - if (num_ai < 0) num_ai = 0; + if (num_ai < 0) + { + num_ai = 0; + karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); + UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; + } + m_ai_kart_spinner->setValue(num_ai); race_manager->setNumKarts(num_ai + local_players); @@ -250,11 +253,9 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setValue(0); m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - - //This is causing an error -/// karts_per_gamemode[race_manager->getMinorMode()] = std::to_string(race_manager->getNumLocalPlayers()); - // UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; //TODO Causes error - UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); + + karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); + UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; } else if (record_available) { From 4fbc39572bf81bb0ffea767c683ebae849dbcc55 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 11:56:52 +1100 Subject: [PATCH 08/43] Removed Tab, first working version! --- src/config/user_config.cpp | 202 +++++++++++------------ src/config/user_config.hpp | 103 ++++++------ src/states_screens/track_info_screen.cpp | 37 ++--- 3 files changed, 170 insertions(+), 172 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index e2d93c2b862..7c05a89ace5 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -322,149 +322,149 @@ core::stringc ListUserConfigParam::toString() const return ""; } // toString - // ============================================================================ + // ============================================================================ template MapUserConfigParam::MapUserConfigParam(const char* param_name, - const char* comment) + const char* comment) { - m_param_name = param_name; - all_params.push_back(this); - if (comment != NULL) m_comment = comment; + m_param_name = param_name; + all_params.push_back(this); + if (comment != NULL) m_comment = comment; } // MapUserConfigParam - // ============================================================================ + // ============================================================================ template MapUserConfigParam::MapUserConfigParam(const char* param_name, - const char* comment, - int nb_elements, - ...) -{ - m_param_name = param_name; - all_params.push_back(this); - if (comment != NULL) m_comment = comment; - - // add the default list - va_list arguments; - va_start(arguments, nb_elements); - typedef std::pair DictThing; - for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, DictThing); - m_elements.insert(key_value_pair); - } - va_end(arguments); // Cleans up the list + const char* comment, + int nb_elements, + ...) +{ + m_param_name = param_name; + all_params.push_back(this); + if (comment != NULL) m_comment = comment; + + // add the default list + va_list arguments; + va_start(arguments, nb_elements); + typedef std::pair DictThing; + for (int i = 0; i < nb_elements; i++) { + std::pair key_value_pair = va_arg(arguments, DictThing); + m_elements.insert(key_value_pair); + } + va_end(arguments); // Cleans up the list } // MapUserConfigParam - // ============================================================================ + // ============================================================================ template MapUserConfigParam::MapUserConfigParam(const char* param_name, - GroupUserConfigParam* group, - const char* comment) + GroupUserConfigParam* group, + const char* comment) { - m_param_name = param_name; - group->addChild(this); - if (comment != NULL) m_comment = comment; + m_param_name = param_name; + group->addChild(this); + if (comment != NULL) m_comment = comment; } // MapUserConfigParam - // ============================================================================ + // ============================================================================ template MapUserConfigParam::MapUserConfigParam(const char* param_name, - GroupUserConfigParam* group, - const char* comment, - int nb_elements, - ...) -{ - m_param_name = param_name; - group->addChild(this); - if (comment != NULL) m_comment = comment; - - // add the default list - va_list arguments; - va_start(arguments, nb_elements); - - for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, DictThing); - m_elements.insert(key_value_pair); - } - va_end(arguments); // Cleans up the list + GroupUserConfigParam* group, + const char* comment, + int nb_elements, + ...) +{ + m_param_name = param_name; + group->addChild(this); + if (comment != NULL) m_comment = comment; + + // add the default list + va_list arguments; + va_start(arguments, nb_elements); + + for (int i = 0; i < nb_elements; i++) { + std::pair key_value_pair = va_arg(arguments, DictThing); + m_elements.insert(key_value_pair); + } + va_end(arguments); // Cleans up the list } // MapUserConfigParam - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- template void MapUserConfigParam::write(std::ofstream& stream) const { - const int elts_amount = m_elements.size(); - - // comment - if (m_comment.size() > 0) stream << " \n <" << m_param_name.c_str() << "\n"; - - stream << " Size=\"" << elts_amount << "\"\n"; - // actual elements - //for (int n = 0; n\n"; - stream << " \n\n"; + const int elts_amount = m_elements.size(); + + // comment + if (m_comment.size() > 0) stream << " \n <" << m_param_name.c_str() << "\n"; + + stream << " Size=\"" << elts_amount << "\"\n"; + // actual elements + //for (int n = 0; n\n"; + stream << " \n\n"; } // write - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- template void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) { - const XMLNode* child = node->getNode(m_param_name); - if (child == NULL) - { - //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str()); - return; - } - - int attr_count = 0; - child->get("Size", &attr_count); - - for (const auto& kv : m_elements) { - std::pair elt; - elt.first = kv.first; - elt.second = kv.second; - - - bool there = false; - - for (const auto& kvRHS : m_elements) { - if (elt.second == kvRHS.second) - { - there = true; - break; - } - - } - if (!there) - { - m_elements.insert(elt); - } - } + const XMLNode* child = node->getNode(m_param_name); + if (child == NULL) + { + //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str()); + return; + } + + int attr_count = 0; + child->get("Size", &attr_count); + + for (const auto& kv : m_elements) { + std::pair elt; + elt.first = kv.first; + elt.second = kv.second; + + + bool there = false; + + for (const auto& kvRHS : m_elements) { + if (elt.second == kvRHS.second) + { + there = true; + break; + } + + } + if (!there) + { + m_elements.insert(elt); + } + } } // findYourDataInAChildOf - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- template void MapUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node) { } // findYourDataInAnAttributeOf - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- template void MapUserConfigParam::addElement(T element, U value) { - m_elements[element] = value; + m_elements[element] = value; } // findYourDataInAnAttributeOf - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- template core::stringc MapUserConfigParam::toString() const { - return ""; + return ""; } // toString // ============================================================================ diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index ab58ddd2a57..bdaeb4f7781 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -139,46 +139,49 @@ typedef ListUserConfigParam StringListUserConfigPar template class MapUserConfigParam : public UserConfigParam { - std::map m_elements; + std::map m_elements; public: - MapUserConfigParam(const char* param_name, - const char* comment = NULL); - MapUserConfigParam(const char* param_name, - const char* comment, - int nb_elts, - ...); - MapUserConfigParam(const char* param_name, - GroupUserConfigParam* group, - const char* comment = NULL); - MapUserConfigParam(const char* param_name, - GroupUserConfigParam* group, - const char* comment, - int nb_elts, - ...); - - void write(std::ofstream& stream) const; - void findYourDataInAChildOf(const XMLNode* node); - void findYourDataInAnAttributeOf(const XMLNode* node); - - void addElement(T element, U value); - - irr::core::stringc toString() const; - - operator std::map() const - { - return m_elements; - } - std::map& operator=(const std::map& v) - { - m_elements = std::map(v); - return m_elements; - } - std::map& operator=(const MapUserConfigParam& v) - { - m_elements = std::map(v); - return m_elements; - } + MapUserConfigParam(const char* param_name, + const char* comment = NULL); + MapUserConfigParam(const char* param_name, + const char* comment, + int nb_elts, + ...); + MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment = NULL); + MapUserConfigParam(const char* param_name, + GroupUserConfigParam* group, + const char* comment, + int nb_elts, + ...); + + void write(std::ofstream& stream) const; + void findYourDataInAChildOf(const XMLNode* node); + void findYourDataInAnAttributeOf(const XMLNode* node); + + void addElement(T element, U value); + + irr::core::stringc toString() const; + + operator std::map() const + { + return m_elements; + } + std::map& operator=(const std::map& v) + { + m_elements = std::map(v); + return m_elements; + } + std::map& operator=(const MapUserConfigParam& v) + { + m_elements = std::map(v); + return m_elements; + } + U& operator[] (const T key) { + return m_elements[key]; + } }; // ListUserConfigParam typedef MapUserConfigParam StringToStringUserConfigParam; typedef MapUserConfigParam IntToIntUserConfigParam; @@ -415,10 +418,10 @@ namespace UserConfigParams PARAM_PREFIX StringUserConfigParam m_last_used_kart_group PARAM_DEFAULT( StringUserConfigParam("all", "last_kart_group", "Last selected kart group") ); - // ---- Gamemode setup - + // ---- Gamemode setup + - + // ---- Wiimote data PARAM_PREFIX GroupUserConfigParam m_wiimote_group @@ -755,15 +758,15 @@ namespace UserConfigParams "stun.voxalot.com", "stun.voxgratia.org", "stun.xten.com") ); - PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", "The karts per gamemode" - "Number of karts per gamemode. Order corresponds to Enum value", - 4, - std::make_pair(0, 1), - std::make_pair(1, 2), - std::make_pair(3, 4), - std::make_pair(4, 5) - )); + PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode + PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", "The karts per gamemode" + "Number of karts per gamemode. Order corresponds to Enum value", + 4, + std::make_pair(0, 1), + std::make_pair(1, 2), + std::make_pair(3, 4), + std::make_pair(4, 5) + )); PARAM_PREFIX BoolUserConfigParam m_log_packets PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets", "If all network packets should be logged") ); diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index cab8ae79578..15f7614cfb7 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -164,25 +164,19 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); - UserConfigParams::m_num_karts; - std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; + UserConfigParams::m_num_karts; + std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; if (has_AI) { m_ai_kart_spinner->setActive(true); - int gamemode = race_manager->getMinorMode(); - int num_ai = karts_per_gamemode[gamemode]; - - // Avoid negative numbers (which can happen if e.g. the number of karts + int gamemode = race_manager->getMinorMode(); + int num_ai = karts_per_gamemode[gamemode]; + + // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - - if (num_ai < 0) - { - num_ai = 0; - karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); - UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; - } - + + if (num_ai < 0) num_ai = 0; m_ai_kart_spinner->setValue(num_ai); race_manager->setNumKarts(num_ai + local_players); @@ -253,9 +247,9 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setValue(0); m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - - karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); - UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; + + karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); + UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; } else if (record_available) { @@ -382,10 +376,11 @@ void TrackInfoScreen::onEnterPressedInternal() if (has_AI) num_ai = m_ai_kart_spinner->getValue(); - if (UserConfigParams::m_num_karts != (local_players + num_ai)) + + if (UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] != (local_players + num_ai)) { race_manager->setNumKarts(local_players + num_ai); - UserConfigParams::m_num_karts = local_players + num_ai; + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = local_players + num_ai; } // Disable accidentally unlocking of a challenge @@ -435,7 +430,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers(); + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumberOfKarts(); } else { @@ -454,7 +449,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai; + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumberOfKarts(); updateHighScores(); } } // eventCallback From 4a0db1926d4afe8faf9eca5ff1d6b2dab296db14 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 12:09:23 +1100 Subject: [PATCH 09/43] Highlighted issue that needs resolving --- src/config/user_config.cpp | 8 ++++---- src/states_screens/track_info_screen.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 7c05a89ace5..e2d92c30cbc 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -346,9 +346,9 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair DictThing; + typedef std::pair PairType; //Necessary to prevent compile error below for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, DictThing); + std::pair key_value_pair = va_arg(arguments, PairType); m_elements.insert(key_value_pair); } va_end(arguments); // Cleans up the list @@ -380,9 +380,9 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - + typedef std::pair PairType; //Necessary to prevent compile error below for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, DictThing); + std::pair key_value_pair = va_arg(arguments, PairType); m_elements.insert(key_value_pair); } va_end(arguments); // Cleans up the list diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index 15f7614cfb7..b1d51e0fb76 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -164,7 +164,7 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); - UserConfigParams::m_num_karts; + std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; if (has_AI) From cb1a2b1e258fea9b2d108fbeece2777faf281dd6 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 12:51:49 +1100 Subject: [PATCH 10/43] Rename m_num_karts to be more appropriate, removed redundant variables I've made --- src/challenges/challenge_data.cpp | 12 ++++----- src/challenges/challenge_data.hpp | 4 +-- src/config/user_config.cpp | 3 ++- src/config/user_config.hpp | 13 ++++------ src/main.cpp | 10 ++++---- src/modes/demo_world.cpp | 6 ++--- src/modes/demo_world.hpp | 4 +-- src/race/race_manager.cpp | 32 ++++++++++++------------ src/race/race_manager.hpp | 8 +++--- src/states_screens/gp_info_screen.cpp | 4 +-- src/states_screens/track_info_screen.cpp | 14 ++++------- 11 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/challenges/challenge_data.cpp b/src/challenges/challenge_data.cpp index 6a0e6c52c79..3b7c55bc30a 100644 --- a/src/challenges/challenge_data.cpp +++ b/src/challenges/challenge_data.cpp @@ -47,7 +47,7 @@ ChallengeData::ChallengeData(const std::string& filename) for (int d=0; dget("number", &num_karts)) error("karts"); - m_num_karts[d] = num_karts; + m_default_num_karts[d] = num_karts; std::string replay_file; if (karts_node->get("replay_file", &replay_file)) @@ -385,7 +385,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const race_manager->setMinorMode(m_minor); race_manager->setTrack(m_track_id); race_manager->setNumLaps(m_num_laps); - race_manager->setNumKarts(m_num_karts[d]); + race_manager->setNumKarts(m_default_num_karts[d]); race_manager->setNumPlayers(1); race_manager->setCoinTarget(m_energy[d]); race_manager->setDifficulty(d); @@ -400,7 +400,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const race_manager->setMinorMode(m_minor); race_manager->setGrandPrix(*grand_prix_manager->getGrandPrix(m_gp_id)); race_manager->setDifficulty(d); - race_manager->setNumKarts(m_num_karts[d]); + race_manager->setNumKarts(m_default_num_karts[d]); race_manager->setNumPlayers(1); } @@ -444,7 +444,7 @@ bool ChallengeData::isChallengeFulfilled() const if (kart->isEliminated() ) return false; if (track_name != m_track_id ) return false; - if ((int)world->getNumKarts() < m_num_karts[d] ) return false; + if ((int)world->getNumKarts() < m_default_num_karts[d] ) return false; if (m_energy[d] > 0 && kart->getEnergy() < m_energy[d] ) return false; if (m_position[d] > 0 && kart->getPosition() > m_position[d]) return false; @@ -491,7 +491,7 @@ bool ChallengeData::isGPFulfilled() const if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX || race_manager->getMinorMode() != m_minor || race_manager->getGrandPrix().getId() != m_gp_id || - race_manager->getNumberOfKarts() < (unsigned int)m_num_karts[d] || + race_manager->getNumberOfKarts() < (unsigned int)m_default_num_karts[d] || race_manager->getNumPlayers() > 1) return false; // check if the player came first. diff --git a/src/challenges/challenge_data.hpp b/src/challenges/challenge_data.hpp index 0cebc45568f..6e45f23c24d 100644 --- a/src/challenges/challenge_data.hpp +++ b/src/challenges/challenge_data.hpp @@ -84,7 +84,7 @@ class ChallengeData int m_num_laps; int m_position[RaceManager::DIFFICULTY_COUNT]; - int m_num_karts[RaceManager::DIFFICULTY_COUNT]; + int m_default_num_karts[RaceManager::DIFFICULTY_COUNT]; std::string m_ai_kart_ident[RaceManager::DIFFICULTY_COUNT]; std::string m_replay_files[RaceManager::DIFFICULTY_COUNT]; float m_time[RaceManager::DIFFICULTY_COUNT]; @@ -208,7 +208,7 @@ class ChallengeData */ int getNumKarts(RaceManager::Difficulty difficulty) const { - return m_num_karts[difficulty]; + return m_default_num_karts[difficulty]; } // getNumKarts // ------------------------------------------------------------------------ /** Returns the maximum time in which the kart must finish. diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index e2d92c30cbc..6184debd027 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -346,7 +346,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair PairType; //Necessary to prevent compile error below + typedef std::pair PairType; //Necessary to prevent compile error below for (int i = 0; i < nb_elements; i++) { std::pair key_value_pair = va_arg(arguments, PairType); m_elements.insert(key_value_pair); @@ -381,6 +381,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, va_list arguments; va_start(arguments, nb_elements); typedef std::pair PairType; //Necessary to prevent compile error below + for (int i = 0; i < nb_elements; i++) { std::pair key_value_pair = va_arg(arguments, PairType); m_elements.insert(key_value_pair); diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index bdaeb4f7781..c11dea61406 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -384,7 +384,7 @@ namespace UserConfigParams PARAM_DEFAULT( GroupUserConfigParam("RaceSetup", "Race Setup Settings") ); - PARAM_PREFIX IntUserConfigParam m_num_karts + PARAM_PREFIX IntUserConfigParam m_default_num_karts PARAM_DEFAULT( IntUserConfigParam(4, "numkarts", &m_race_setup_group, "Default number of karts. -1 means use all") ); @@ -759,13 +759,10 @@ namespace UserConfigParams "stun.voxgratia.org", "stun.xten.com") ); PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", "The karts per gamemode" - "Number of karts per gamemode. Order corresponds to Enum value", - 4, - std::make_pair(0, 1), - std::make_pair(1, 2), - std::make_pair(3, 4), - std::make_pair(4, 5) + PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", + "The Number of karts per gamemode.", + 1, + std::make_pair(1100, 4) )); PARAM_PREFIX BoolUserConfigParam m_log_packets PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets", diff --git a/src/main.cpp b/src/main.cpp index c6b5932a5b0..5eefa3f1bb4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1189,16 +1189,16 @@ int handleCmdLine() if(CommandLine::has("--numkarts", &n) ||CommandLine::has("-k", &n)) { - UserConfigParams::m_num_karts = n; - if(UserConfigParams::m_num_karts > stk_config->m_max_karts) + UserConfigParams::m_default_num_karts = n; + if(UserConfigParams::m_default_num_karts > stk_config->m_max_karts) { Log::warn("main", "Number of karts reset to maximum number %d.", stk_config->m_max_karts); - UserConfigParams::m_num_karts = stk_config->m_max_karts; + UserConfigParams::m_default_num_karts = stk_config->m_max_karts; } - race_manager->setNumKarts( UserConfigParams::m_num_karts ); + race_manager->setNumKarts( UserConfigParams::m_default_num_karts ); Log::verbose("main", "%d karts will be used.", - (int)UserConfigParams::m_num_karts); + (int)UserConfigParams::m_default_num_karts); } // --numkarts if(CommandLine::has( "--no-start-screen") || diff --git a/src/modes/demo_world.cpp b/src/modes/demo_world.cpp index 867b6ad151b..078ba126888 100644 --- a/src/modes/demo_world.cpp +++ b/src/modes/demo_world.cpp @@ -29,7 +29,7 @@ #include "tracks/track_manager.hpp" std::vector DemoWorld::m_demo_tracks; -int DemoWorld::m_num_karts = 2; +int DemoWorld::m_default_num_karts = 2; float DemoWorld::m_max_idle_time = 99999.0f; float DemoWorld::m_current_idle_time = 0; bool DemoWorld::m_do_demo = false; @@ -49,7 +49,7 @@ DemoWorld::DemoWorld() race_manager->setReverseTrack(false); race_manager->setMinorMode (RaceManager::MINOR_MODE_NORMAL_RACE); race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD); - race_manager->setNumKarts(m_num_karts); + race_manager->setNumKarts(m_default_num_karts); race_manager->setNumPlayers(1); race_manager->setPlayerKart(0, UserConfigParams::m_default_kart); @@ -149,7 +149,7 @@ bool DemoWorld::updateIdleTimeAndStartDemo(float dt) input_manager->getDeviceManager()->setAssignMode(ASSIGN); m_do_demo = true; - race_manager->setNumKarts(m_num_karts); + race_manager->setNumKarts(m_default_num_karts); race_manager->setPlayerKart(0, "tux"); race_manager->setupPlayerKartInfo(); race_manager->startSingleRace(m_demo_tracks[0], m_num_laps, false); diff --git a/src/modes/demo_world.hpp b/src/modes/demo_world.hpp index a2d047a2f52..bce6940bed3 100644 --- a/src/modes/demo_world.hpp +++ b/src/modes/demo_world.hpp @@ -40,7 +40,7 @@ class DemoWorld : public ProfileWorld static std::vector m_demo_tracks; /** Number of karts to use in demo mode. */ - static int m_num_karts; + static int m_default_num_karts; /** Idle time after which demo mode should be started. */ static float m_max_idle_time; @@ -66,7 +66,7 @@ class DemoWorld : public ProfileWorld static void setNumLaps(unsigned int num_laps) { m_num_laps = num_laps; } // ------------------------------------------------------------------------ /** Sets the number of karts to use in demo mode. */ - static void setNumKarts(unsigned int num_karts) { m_num_karts = num_karts;} + static void setNumKarts(unsigned int num_karts) { m_default_num_karts = num_karts;} // ------------------------------------------------------------------------ static void setTracks(const std::vector &tracks); // ------------------------------------------------------------------------ diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 7808712a16c..13483d96524 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -66,7 +66,7 @@ RaceManager::RaceManager() { // Several code depends on this, e.g. kart_properties assert(DIFFICULTY_FIRST == 0); - m_num_karts = UserConfigParams::m_num_karts; + m_default_num_karts = UserConfigParams::m_default_num_karts; m_difficulty = DIFFICULTY_HARD; m_major_mode = MAJOR_MODE_SINGLE; m_minor_mode = MINOR_MODE_NORMAL_RACE; @@ -266,16 +266,16 @@ void RaceManager::setTrack(const std::string& track) */ void RaceManager::computeRandomKartList() { - int n = m_num_karts - (int)m_player_karts.size(); + int n = m_default_num_karts - (int)m_player_karts.size(); if(UserConfigParams::logMisc()) - Log::info("RaceManager", "AI karts count = %d for m_num_karts = %d and " - "m_player_karts.size() = %d", n, m_num_karts, m_player_karts.size()); + Log::info("RaceManager", "AI karts count = %d for m_default_num_karts = %d and " + "m_player_karts.size() = %d", n, m_default_num_karts, m_player_karts.size()); // If less kart selected than there are player karts, adjust the number of // karts to the minimum if(n<0) { - m_num_karts -= n; + m_default_num_karts -= n; n = 0; } @@ -363,20 +363,20 @@ void RaceManager::startNew(bool from_overworld) } // if grand prix // command line parameters: negative numbers=all karts - if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts; - if((size_t)m_num_karts < m_player_karts.size()) - m_num_karts = (int)m_player_karts.size(); + if(m_default_num_karts < 0 ) m_default_num_karts = stk_config->m_max_karts; + if((size_t)m_default_num_karts < m_player_karts.size()) + m_default_num_karts = (int)m_player_karts.size(); // Create the kart status data structure to keep track of scores, times, ... // ========================================================================== m_kart_status.clear(); if (gk > 0) - m_num_karts += gk; + m_default_num_karts += gk; Log::verbose("RaceManager", "Nb of karts=%u, ghost karts:%u ai:%lu players:%lu\n", - (unsigned int) m_num_karts, gk, m_ai_kart_list.size(), m_player_karts.size()); + (unsigned int) m_default_num_karts, gk, m_ai_kart_list.size(), m_player_karts.size()); - assert((unsigned int)m_num_karts == gk+m_ai_kart_list.size()+m_player_karts.size()); + assert((unsigned int)m_default_num_karts == gk+m_ai_kart_list.size()+m_player_karts.size()); // First add the ghost karts (if any) // ---------------------------------------- @@ -550,7 +550,7 @@ void RaceManager::startNextRace() // The race is rerun, and the points and scores get reset ... but if // a kart hasn't finished the race at this stage, last_score and time // would be undefined. - for(int i=0; igetNumGhostKart(); + m_default_num_karts = ReplayPlay::get()->getNumGhostKart(); m_kart_status.clear(); Log::verbose("RaceManager", "%u ghost kart(s) for watching replay only\n", - (unsigned int)m_num_karts); + (unsigned int)m_default_num_karts); int init_gp_rank = 0; - for(int i = 0; i < m_num_karts; i++) + for(int i = 0; i < m_default_num_karts; i++) { m_kart_status.push_back(KartStatus(ReplayPlay::get()->getGhostKartName(i), i, -1, -1, init_gp_rank, KT_GHOST, PLAYER_DIFFICULTY_NORMAL)); diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 7be0e82276c..e218be5022e 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -329,7 +329,7 @@ class RaceManager int m_track_number; GrandPrixData m_grand_prix; SavedGrandPrix* m_saved_gp; - int m_num_karts; + int m_default_num_karts; unsigned int m_num_spare_tire_karts; unsigned int m_num_finished_karts; unsigned int m_num_finished_players; @@ -469,7 +469,7 @@ class RaceManager // ------------------------------------------------------------------------ void setNumKarts(int num) { - m_num_karts = num; + m_default_num_karts = num; m_ai_kart_override = ""; m_ai_superpower = SUPERPOWER_NONE; } // setNumKarts @@ -492,7 +492,7 @@ class RaceManager // ------------------------------------------------------------------------ /** Returns the selected number of karts (selected number of players and * AI karts. */ - unsigned int getNumberOfKarts() const {return m_num_karts; } + unsigned int getNumberOfKarts() const {return m_default_num_karts; } // ------------------------------------------------------------------------ MajorRaceModeType getMajorMode() const { return m_major_mode; } // ------------------------------------------------------------------------ @@ -759,7 +759,7 @@ class RaceManager m_kart_status.push_back(KartStatus(name, 0, -1, -1, -1, KT_SPARE_TIRE, PLAYER_DIFFICULTY_NORMAL)); m_num_spare_tire_karts++; - m_num_karts++; + m_default_num_karts++; } // addSpareTireKart // ------------------------------------------------------------------------ void setSpareTireKartNum(unsigned int i) diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp index 161de15e8d5..c45fc6af8f1 100644 --- a/src/states_screens/gp_info_screen.cpp +++ b/src/states_screens/gp_info_screen.cpp @@ -235,7 +235,7 @@ void GPInfoScreen::init() // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - int num_ai = UserConfigParams::m_num_karts - race_manager->getNumLocalPlayers(); + int num_ai = UserConfigParams::m_default_num_karts - race_manager->getNumLocalPlayers(); if (num_ai < 0) num_ai = 0; m_ai_kart_spinner->setValue(num_ai); race_manager->setNumKarts(num_ai + race_manager->getNumLocalPlayers()); @@ -345,7 +345,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai; + UserConfigParams::m_default_num_karts = race_manager->getNumLocalPlayers() + num_ai; } else if(name=="back") { diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index b1d51e0fb76..4cec05e868e 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -164,14 +164,11 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setVisible(has_AI); getWidget("ai-text")->setVisible(has_AI); - - std::map karts_per_gamemode = UserConfigParams::m_karts_per_gamemode; - if (has_AI) { m_ai_kart_spinner->setActive(true); - int gamemode = race_manager->getMinorMode(); - int num_ai = karts_per_gamemode[gamemode]; + + int num_ai = UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] - local_players; // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. @@ -248,8 +245,7 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumPlayers(); - UserConfigParams::m_karts_per_gamemode = karts_per_gamemode; + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); } else if (record_available) { @@ -430,7 +426,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumberOfKarts(); + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); } else { @@ -449,7 +445,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumberOfKarts(); + UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers() + num_ai; updateHighScores(); } } // eventCallback From d366dd84cd1a6e71d1ac561b9f887fe5cc83da88 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 12:59:04 +1100 Subject: [PATCH 11/43] Updated to naming conventions --- src/config/user_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 6184debd027..acdd8c954bc 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -346,9 +346,9 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair PairType; //Necessary to prevent compile error below + typedef std::pair pair_type; //Necessary to prevent compile error below for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, PairType); + std::pair key_value_pair = va_arg(arguments, pair_type); m_elements.insert(key_value_pair); } va_end(arguments); // Cleans up the list From e50d295c870a26353ea629e8ebaeefcfcba39af5 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 13:05:08 +1100 Subject: [PATCH 12/43] Remvoe redundancy --- src/config/user_config.cpp | 1 - src/config/user_config.hpp | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index acdd8c954bc..d8a529eb103 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -29,7 +29,6 @@ static PtrVector all_params; // X-macros #define PARAM_PREFIX #define PARAM_DEFAULT(X) = X - #include "config/user_config.hpp" #include "config/saved_grand_prix.hpp" diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index c11dea61406..02bbf982d99 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -183,7 +183,6 @@ class MapUserConfigParam : public UserConfigParam return m_elements[key]; } }; // ListUserConfigParam -typedef MapUserConfigParam StringToStringUserConfigParam; typedef MapUserConfigParam IntToIntUserConfigParam; // ============================================================================ class IntUserConfigParam : public UserConfigParam @@ -418,11 +417,7 @@ namespace UserConfigParams PARAM_PREFIX StringUserConfigParam m_last_used_kart_group PARAM_DEFAULT( StringUserConfigParam("all", "last_kart_group", "Last selected kart group") ); - // ---- Gamemode setup - - - // ---- Wiimote data PARAM_PREFIX GroupUserConfigParam m_wiimote_group PARAM_DEFAULT( GroupUserConfigParam("WiiMote", @@ -758,12 +753,15 @@ namespace UserConfigParams "stun.voxalot.com", "stun.voxgratia.org", "stun.xten.com") ); + + // ---- Gamemode setup PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", "The Number of karts per gamemode.", 1, std::make_pair(1100, 4) )); + PARAM_PREFIX BoolUserConfigParam m_log_packets PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets", "If all network packets should be logged") ); From 7fff73afa6029124b1dd3da57d02e5a0b14a40d5 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 14:13:57 +1100 Subject: [PATCH 13/43] Clarifies the cause of compiler errors for some systems --- src/config/user_config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index d8a529eb103..d431cca3408 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -345,7 +345,8 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair pair_type; //Necessary to prevent compile error below + typedef std::pair pair_type; //Necessary to prevent compile error below. Causes errors on some compilers though + for (int i = 0; i < nb_elements; i++) { std::pair key_value_pair = va_arg(arguments, pair_type); m_elements.insert(key_value_pair); From 702d7f71c56eb9e467b03376017fc51271f6dcf2 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Sat, 28 Oct 2017 18:41:26 +1100 Subject: [PATCH 14/43] Replaced pair with temporary struct, to ensure POD-typing --- src/config/user_config.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index d431cca3408..fd2ad84597c 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -345,11 +345,12 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair pair_type; //Necessary to prevent compile error below. Causes errors on some compilers though + + struct pair_type { T key; U value; }; for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, pair_type); - m_elements.insert(key_value_pair); + pair_type key_value_pair = va_arg(arguments, pair_type); + m_elements.insert(std::pair(key_value_pair.key, key_value_pair.value)); } va_end(arguments); // Cleans up the list } // MapUserConfigParam @@ -380,11 +381,12 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - typedef std::pair PairType; //Necessary to prevent compile error below - + + struct pair_type { T key; U value; }; + for (int i = 0; i < nb_elements; i++) { - std::pair key_value_pair = va_arg(arguments, PairType); - m_elements.insert(key_value_pair); + pair_type key_value_pair = va_arg(arguments, pair_type); + m_elements.insert(std::pair(key_value_pair.key, key_value_pair.value)); } va_end(arguments); // Cleans up the list } // MapUserConfigParam From a094a5a3d6136ce6a71e896643eb76d33c0f2ffe Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Tue, 31 Oct 2017 11:15:38 +1100 Subject: [PATCH 15/43] Fix non newline brackets --- src/config/user_config.cpp | 12 ++++++++---- src/config/user_config.hpp | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index fd2ad84597c..69b97e944db 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -348,7 +348,8 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, struct pair_type { T key; U value; }; - for (int i = 0; i < nb_elements; i++) { + for (int i = 0; i < nb_elements; i++) + { pair_type key_value_pair = va_arg(arguments, pair_type); m_elements.insert(std::pair(key_value_pair.key, key_value_pair.value)); } @@ -405,7 +406,8 @@ void MapUserConfigParam::write(std::ofstream& stream) const // actual elements //for (int n = 0; n\n"; @@ -427,7 +429,8 @@ void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) int attr_count = 0; child->get("Size", &attr_count); - for (const auto& kv : m_elements) { + for (const auto& kv : m_elements) + { std::pair elt; elt.first = kv.first; elt.second = kv.second; @@ -435,7 +438,8 @@ void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) bool there = false; - for (const auto& kvRHS : m_elements) { + for (const auto& kvRHS : m_elements) + { if (elt.second == kvRHS.second) { there = true; diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index 02bbf982d99..e39dc355e93 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -179,7 +179,8 @@ class MapUserConfigParam : public UserConfigParam m_elements = std::map(v); return m_elements; } - U& operator[] (const T key) { + U& operator[] (const T key) + { return m_elements[key]; } }; // ListUserConfigParam From 367eeb8c20a4915cc9b67b5fa1d29925a205351e Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Tue, 31 Oct 2017 17:57:19 +1100 Subject: [PATCH 16/43] fix innapropriate name changes --- src/race/race_manager.cpp | 32 ++++++++++++++++---------------- src/race/race_manager.hpp | 8 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 13483d96524..6ce0f38827c 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -66,7 +66,7 @@ RaceManager::RaceManager() { // Several code depends on this, e.g. kart_properties assert(DIFFICULTY_FIRST == 0); - m_default_num_karts = UserConfigParams::m_default_num_karts; + m_num_karts = UserConfigParams::m_default_num_karts; m_difficulty = DIFFICULTY_HARD; m_major_mode = MAJOR_MODE_SINGLE; m_minor_mode = MINOR_MODE_NORMAL_RACE; @@ -266,16 +266,16 @@ void RaceManager::setTrack(const std::string& track) */ void RaceManager::computeRandomKartList() { - int n = m_default_num_karts - (int)m_player_karts.size(); + int n = m_num_karts - (int)m_player_karts.size(); if(UserConfigParams::logMisc()) - Log::info("RaceManager", "AI karts count = %d for m_default_num_karts = %d and " - "m_player_karts.size() = %d", n, m_default_num_karts, m_player_karts.size()); + Log::info("RaceManager", "AI karts count = %d for m_num_karts = %d and " + "m_player_karts.size() = %d", n, m_num_karts, m_player_karts.size()); // If less kart selected than there are player karts, adjust the number of // karts to the minimum if(n<0) { - m_default_num_karts -= n; + m_num_karts -= n; n = 0; } @@ -363,20 +363,20 @@ void RaceManager::startNew(bool from_overworld) } // if grand prix // command line parameters: negative numbers=all karts - if(m_default_num_karts < 0 ) m_default_num_karts = stk_config->m_max_karts; - if((size_t)m_default_num_karts < m_player_karts.size()) - m_default_num_karts = (int)m_player_karts.size(); + if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts; + if((size_t)m_num_karts < m_player_karts.size()) + m_num_karts = (int)m_player_karts.size(); // Create the kart status data structure to keep track of scores, times, ... // ========================================================================== m_kart_status.clear(); if (gk > 0) - m_default_num_karts += gk; + m_num_karts += gk; Log::verbose("RaceManager", "Nb of karts=%u, ghost karts:%u ai:%lu players:%lu\n", - (unsigned int) m_default_num_karts, gk, m_ai_kart_list.size(), m_player_karts.size()); + (unsigned int) m_num_karts, gk, m_ai_kart_list.size(), m_player_karts.size()); - assert((unsigned int)m_default_num_karts == gk+m_ai_kart_list.size()+m_player_karts.size()); + assert((unsigned int)m_num_karts == gk+m_ai_kart_list.size()+m_player_karts.size()); // First add the ghost karts (if any) // ---------------------------------------- @@ -550,7 +550,7 @@ void RaceManager::startNextRace() // The race is rerun, and the points and scores get reset ... but if // a kart hasn't finished the race at this stage, last_score and time // would be undefined. - for(int i=0; igetNumGhostKart(); + m_num_karts = ReplayPlay::get()->getNumGhostKart(); m_kart_status.clear(); Log::verbose("RaceManager", "%u ghost kart(s) for watching replay only\n", - (unsigned int)m_default_num_karts); + (unsigned int)m_num_karts); int init_gp_rank = 0; - for(int i = 0; i < m_default_num_karts; i++) + for(int i = 0; i < m_num_karts; i++) { m_kart_status.push_back(KartStatus(ReplayPlay::get()->getGhostKartName(i), i, -1, -1, init_gp_rank, KT_GHOST, PLAYER_DIFFICULTY_NORMAL)); diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index e218be5022e..7be0e82276c 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -329,7 +329,7 @@ class RaceManager int m_track_number; GrandPrixData m_grand_prix; SavedGrandPrix* m_saved_gp; - int m_default_num_karts; + int m_num_karts; unsigned int m_num_spare_tire_karts; unsigned int m_num_finished_karts; unsigned int m_num_finished_players; @@ -469,7 +469,7 @@ class RaceManager // ------------------------------------------------------------------------ void setNumKarts(int num) { - m_default_num_karts = num; + m_num_karts = num; m_ai_kart_override = ""; m_ai_superpower = SUPERPOWER_NONE; } // setNumKarts @@ -492,7 +492,7 @@ class RaceManager // ------------------------------------------------------------------------ /** Returns the selected number of karts (selected number of players and * AI karts. */ - unsigned int getNumberOfKarts() const {return m_default_num_karts; } + unsigned int getNumberOfKarts() const {return m_num_karts; } // ------------------------------------------------------------------------ MajorRaceModeType getMajorMode() const { return m_major_mode; } // ------------------------------------------------------------------------ @@ -759,7 +759,7 @@ class RaceManager m_kart_status.push_back(KartStatus(name, 0, -1, -1, -1, KT_SPARE_TIRE, PLAYER_DIFFICULTY_NORMAL)); m_num_spare_tire_karts++; - m_default_num_karts++; + m_num_karts++; } // addSpareTireKart // ------------------------------------------------------------------------ void setSpareTireKartNum(unsigned int i) From 83c14fc0dc4befae46cfaf3cf7386c907f565e1d Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Tue, 31 Oct 2017 18:11:45 +1100 Subject: [PATCH 17/43] Added default num karts for GP --- src/states_screens/gp_info_screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp index c45fc6af8f1..5f6021ab65a 100644 --- a/src/states_screens/gp_info_screen.cpp +++ b/src/states_screens/gp_info_screen.cpp @@ -235,7 +235,7 @@ void GPInfoScreen::init() // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - int num_ai = UserConfigParams::m_default_num_karts - race_manager->getNumLocalPlayers(); + int num_ai = UserConfigParams::m_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] - race_manager->getNumLocalPlayers(); if (num_ai < 0) num_ai = 0; m_ai_kart_spinner->setValue(num_ai); race_manager->setNumKarts(num_ai + race_manager->getNumLocalPlayers()); @@ -345,7 +345,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_default_num_karts = race_manager->getNumLocalPlayers() + num_ai; + UserConfigParams::m_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] = race_manager->getNumLocalPlayers() + num_ai; } else if(name=="back") { From 98231956fb9ef94a52b918466e8dfe56e1e841e8 Mon Sep 17 00:00:00 2001 From: Fantasmos Date: Wed, 1 Nov 2017 08:38:34 +1100 Subject: [PATCH 18/43] rename to more appropriate variable --- src/config/user_config.hpp | 4 ++-- src/states_screens/gp_info_screen.cpp | 4 ++-- src/states_screens/track_info_screen.cpp | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index e39dc355e93..b4e2491dff8 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -756,8 +756,8 @@ namespace UserConfigParams "stun.xten.com") ); // ---- Gamemode setup - PARAM_PREFIX IntToIntUserConfigParam m_karts_per_gamemode - PARAM_DEFAULT(IntToIntUserConfigParam("karts_per_gamemode", + PARAM_PREFIX IntToIntUserConfigParam m_num_karts_per_gamemode + PARAM_DEFAULT(IntToIntUserConfigParam("num_karts_per_gamemode", "The Number of karts per gamemode.", 1, std::make_pair(1100, 4) diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp index 5f6021ab65a..ee44125084f 100644 --- a/src/states_screens/gp_info_screen.cpp +++ b/src/states_screens/gp_info_screen.cpp @@ -235,7 +235,7 @@ void GPInfoScreen::init() // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. - int num_ai = UserConfigParams::m_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] - race_manager->getNumLocalPlayers(); + int num_ai = UserConfigParams::m_num_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] - race_manager->getNumLocalPlayers(); if (num_ai < 0) num_ai = 0; m_ai_kart_spinner->setValue(num_ai); race_manager->setNumKarts(num_ai + race_manager->getNumLocalPlayers()); @@ -345,7 +345,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] = race_manager->getNumLocalPlayers() + num_ai; + UserConfigParams::m_num_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] = race_manager->getNumLocalPlayers() + num_ai; } else if(name=="back") { diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index 4cec05e868e..0001cc0f6e3 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -168,7 +168,7 @@ void TrackInfoScreen::init() { m_ai_kart_spinner->setActive(true); - int num_ai = UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] - local_players; + int num_ai = UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] - local_players; // Avoid negative numbers (which can happen if e.g. the number of karts // in a previous race was lower than the number of players now. @@ -245,7 +245,7 @@ void TrackInfoScreen::init() m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); + UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); } else if (record_available) { @@ -373,10 +373,10 @@ void TrackInfoScreen::onEnterPressedInternal() num_ai = m_ai_kart_spinner->getValue(); - if (UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] != (local_players + num_ai)) + if (UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] != (local_players + num_ai)) { race_manager->setNumKarts(local_players + num_ai); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = local_players + num_ai; + UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = local_players + num_ai; } // Disable accidentally unlocking of a challenge @@ -426,7 +426,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { m_ai_kart_spinner->setActive(false); race_manager->setNumKarts(race_manager->getNumLocalPlayers()); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); + UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers(); } else { @@ -445,7 +445,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, { const int num_ai = m_ai_kart_spinner->getValue(); race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai ); - UserConfigParams::m_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers() + num_ai; + UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers() + num_ai; updateHighScores(); } } // eventCallback From 4d4c514c755c948e97d1960ff0969eefdc79ae18 Mon Sep 17 00:00:00 2001 From: Deve Date: Wed, 15 Nov 2017 22:02:19 +0100 Subject: [PATCH 19/43] Corrrect gp info screen to keep consistency with track info screen. Now num karts config param is updated only if spinner button or start button has been pressed. --- src/states_screens/gp_info_screen.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp index 1a5169d5b9a..6119f480317 100644 --- a/src/states_screens/gp_info_screen.cpp +++ b/src/states_screens/gp_info_screen.cpp @@ -235,7 +235,7 @@ void GPInfoScreen::init() const int local_players = race_manager->getNumLocalPlayers(); int min_ai = 0; int num_ai = UserConfigParams::m_num_karts - local_players; - + // A ftl reace needs at least three karts to make any sense if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER) { @@ -243,9 +243,7 @@ void GPInfoScreen::init() } num_ai = std::max(min_ai, num_ai); - UserConfigParams::m_num_karts = num_ai + local_players; - race_manager->setNumKarts(num_ai + local_players); - + m_ai_kart_spinner->setActive(true); m_ai_kart_spinner->setValue(num_ai); m_ai_kart_spinner->setMax(stk_config->m_max_karts - local_players); @@ -315,11 +313,24 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name, /*new tracks*/ true ); addTracks(); } - else if (button == "start" || button == "continue") + else if (button == "start") + { + // Normal GP: start GP + const int local_players = race_manager->getNumLocalPlayers(); + const bool has_AI = race_manager->hasAI(); + const int num_ai = has_AI ? m_ai_kart_spinner->getValue() : 0; + + race_manager->setNumKarts(local_players + num_ai); + UserConfigParams::m_num_karts = local_players + num_ai; + + m_gp.changeReverse(getReverse()); + race_manager->startGP(m_gp, false, false); + } + else if (button == "continue") { - // Normal GP: start/continue a saved GP + // Normal GP: continue a saved GP m_gp.changeReverse(getReverse()); - race_manager->startGP(m_gp, false, (button == "continue")); + race_manager->startGP(m_gp, false, true); } } // name=="buttons" else if (name=="group-spinner") From d92476ae700ee9ccee2850946a0ac701c94433ca Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Sat, 25 Nov 2017 18:51:49 -0500 Subject: [PATCH 20/43] First implementation prototype of the new netwoking UI, as discussed. --- data/gui/online/lan.stkgui | 29 +++ data/gui/online/online.stkgui | 29 +++ .../online/profile_achievements_tab.stkgui | 1 - data/gui/online/profile_friends.stkgui | 1 - data/gui/online/profile_servers.stkgui | 74 ++----- data/gui/online/profile_settings.stkgui | 1 - src/states_screens/main_menu_screen.cpp | 41 +--- src/states_screens/main_menu_screen.hpp | 7 - src/states_screens/online_lan.cpp | 112 ++++++++++ src/states_screens/online_lan.hpp | 57 +++++ src/states_screens/online_profile_base.cpp | 7 - src/states_screens/online_profile_base.hpp | 1 - src/states_screens/online_profile_servers.cpp | 36 +--- src/states_screens/online_profile_servers.hpp | 2 +- src/states_screens/online_screen.cpp | 200 ++++++++++++++++++ src/states_screens/online_screen.hpp | 73 +++++++ src/states_screens/user_screen.cpp | 1 + 17 files changed, 540 insertions(+), 132 deletions(-) create mode 100644 data/gui/online/lan.stkgui create mode 100644 data/gui/online/online.stkgui create mode 100644 src/states_screens/online_lan.cpp create mode 100644 src/states_screens/online_lan.hpp create mode 100644 src/states_screens/online_screen.cpp create mode 100644 src/states_screens/online_screen.hpp diff --git a/data/gui/online/lan.stkgui b/data/gui/online/lan.stkgui new file mode 100644 index 00000000000..c94e6082a01 --- /dev/null +++ b/data/gui/online/lan.stkgui @@ -0,0 +1,29 @@ + + + + +
+
+ + +
+
diff --git a/data/gui/online/online.stkgui b/data/gui/online/online.stkgui new file mode 100644 index 00000000000..3572916bc52 --- /dev/null +++ b/data/gui/online/online.stkgui @@ -0,0 +1,29 @@ + + +
+
+ +
+ + +
diff --git a/data/gui/online/profile_achievements_tab.stkgui b/data/gui/online/profile_achievements_tab.stkgui index dbf3256b503..7d519d6612c 100644 --- a/data/gui/online/profile_achievements_tab.stkgui +++ b/data/gui/online/profile_achievements_tab.stkgui @@ -9,7 +9,6 @@ - diff --git a/data/gui/online/profile_friends.stkgui b/data/gui/online/profile_friends.stkgui index 0e1213c61e6..e0e49473b41 100644 --- a/data/gui/online/profile_friends.stkgui +++ b/data/gui/online/profile_friends.stkgui @@ -9,7 +9,6 @@ - diff --git a/data/gui/online/profile_servers.stkgui b/data/gui/online/profile_servers.stkgui index 25ca99ffaa8..88de78d8c05 100644 --- a/data/gui/online/profile_servers.stkgui +++ b/data/gui/online/profile_servers.stkgui @@ -3,59 +3,25 @@
-
- - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
-
+
+ + +
diff --git a/data/gui/online/profile_settings.stkgui b/data/gui/online/profile_settings.stkgui index 126519d9f1e..d89d52c23a1 100644 --- a/data/gui/online/profile_settings.stkgui +++ b/data/gui/online/profile_settings.stkgui @@ -8,7 +8,6 @@ - setBadge(LOADING_BADGE); } - m_online = getWidget("online"); + IconButtonWidget* online = getWidget("online"); - if(!m_enable_online) - m_online->setActive(false); + if (!m_enable_online) + online->setActive(false); LabelWidget* w = getWidget("info_addons"); const core::stringw &news_text = NewsManager::get()->getNextNewsMessage(); @@ -179,32 +177,25 @@ void MainMenuScreen::init() } // init // ---------------------------------------------------------------------------- -void MainMenuScreen::onUpdate(float delta) +void MainMenuScreen::onUpdate(float delta) { PlayerProfile *player = PlayerManager::getCurrentPlayer(); if(PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST || PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN) { m_user_id->setText(player->getLastOnlineName() + "@stk"); - m_online->setActive(true); - m_online->setLabel(m_online_string); } else if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_OUT) { - m_online->setActive(true); - m_online->setLabel(m_login_string); m_user_id->setText(player->getName()); } else { // now must be either logging in or logging out - m_online->setActive(false); m_user_id->setText(player->getName()); } - m_online->setLabel(PlayerManager::getCurrentOnlineId() ? m_online_string - : m_login_string); IconButtonWidget* addons_icon = getWidget("addons"); if (addons_icon != NULL) { @@ -472,6 +463,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, } else if (selection == "story") { + NetworkConfig::get()->unsetNetworking(); PlayerProfile *player = PlayerManager::getCurrentPlayer(); if (player->isFirstTime()) { @@ -505,24 +497,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, } else if (selection == "online") { - if(UserConfigParams::m_internet_status!=RequestManager::IPERM_ALLOWED) - { - new MessageDialog(_("You can not play online without internet access. " - "If you want to play online, go to options, select " - " tab 'User Interface', and edit " - "\"Connect to the Internet\".")); - return; - } - - if (PlayerManager::getCurrentOnlineId()) - { - ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId()); - OnlineProfileServers::getInstance()->push(); - } - else - { - UserScreen::getInstance()->push(); - } + OnlineScreen::getInstance()->push(); } else if (selection == "addons") { diff --git a/src/states_screens/main_menu_screen.hpp b/src/states_screens/main_menu_screen.hpp index 4e79c453264..8da6c94ab4c 100644 --- a/src/states_screens/main_menu_screen.hpp +++ b/src/states_screens/main_menu_screen.hpp @@ -32,13 +32,6 @@ class MainMenuScreen : public GUIEngine::Screen, public GUIEngine::ScreenSinglet private: friend class GUIEngine::ScreenSingleton; - core::stringw m_online_string; - - core::stringw m_login_string; - - /** Keep the widget to avoid looking it up every frame. */ - GUIEngine::IconButtonWidget* m_online; - /** Keep the widget to to the user name. */ GUIEngine::ButtonWidget *m_user_id; diff --git a/src/states_screens/online_lan.cpp b/src/states_screens/online_lan.cpp new file mode 100644 index 00000000000..9e22fa10447 --- /dev/null +++ b/src/states_screens/online_lan.cpp @@ -0,0 +1,112 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2010-2015 Glenn De Jonghe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "states_screens/online_profile_servers.hpp" + +#include "audio/sfx_manager.hpp" +#include "config/player_manager.hpp" +#include "guiengine/engine.hpp" +#include "guiengine/scalable_font.hpp" +#include "guiengine/screen.hpp" +#include "guiengine/widget.hpp" +#include "network/network_config.hpp" +#include "network/protocol_manager.hpp" +#include "network/protocols/connect_to_server.hpp" +#include "network/protocols/request_connection.hpp" +#include "network/servers_manager.hpp" +#include "states_screens/state_manager.hpp" +#include "states_screens/create_server_screen.hpp" +#include "states_screens/networking_lobby.hpp" +#include "states_screens/online_lan.hpp" +#include "states_screens/server_selection.hpp" +#include "utils/translation.hpp" + +#include + +#include +#include + +using namespace GUIEngine; +using namespace irr::core; +using namespace irr::gui; +using namespace Online; + +DEFINE_SCREEN_SINGLETON( OnlineLanScreen ); + +// ----------------------------------------------------------------------------- + +OnlineLanScreen::OnlineLanScreen() : GUIEngine::Screen("online/lan.stkgui") +{ +} // OnlineLanScreen + +// ----------------------------------------------------------------------------- + +void OnlineLanScreen::loadedFromFile() +{ +} // loadedFromFile + +// ----------------------------------------------------------------------------- + +void OnlineLanScreen::init() +{ + RibbonWidget* ribbon = getWidget("lan"); + assert(ribbon != NULL); + ribbon->select("find_lan_server", PLAYER_ID_GAME_MASTER); + ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER); +} // init + +// ----------------------------------------------------------------------------- + +void OnlineLanScreen::eventCallback(Widget* widget, const std::string& name, const int playerID) +{ + if (name == "back") + { + StateManager::get()->popMenu(); + return; + } + if (name == "lan") + { + RibbonWidget* ribbon = dynamic_cast(widget); + std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER); + if (selection == "create_lan_server") + { + NetworkConfig::get()->setIsLAN(); + NetworkConfig::get()->setIsServer(true); + CreateServerScreen::getInstance()->push(); + // TODO: create lan server + } + else if (selection == "find_lan_server") + { + NetworkConfig::get()->setIsLAN(); + NetworkConfig::get()->setIsServer(false); + ServerSelection::getInstance()->push(); + } + } + +} // eventCallback + +// ---------------------------------------------------------------------------- +/** Also called when pressing the back button. It resets the flags to indicate + * a networked game. + */ +bool OnlineLanScreen::onEscapePressed() +{ + NetworkConfig::get()->unsetNetworking(); + //StateManager::get()->popMenu(); + return true; +} // onEscapePressed + diff --git a/src/states_screens/online_lan.hpp b/src/states_screens/online_lan.hpp new file mode 100644 index 00000000000..615cb9e3751 --- /dev/null +++ b/src/states_screens/online_lan.hpp @@ -0,0 +1,57 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2013-2015 Glenn De Jonghe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef __HEADER_OLAN_HPP__ +#define __HEADER_OLAN_HPP__ + +#include +#include + +#include "guiengine/screen.hpp" +#include "guiengine/widgets.hpp" +#include "states_screens/online_profile_base.hpp" + +namespace GUIEngine { class Widget; } + + +/** + * \brief Online profiel overview screen + * \ingroup states_screens + */ +class OnlineLanScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton +{ +protected: + OnlineLanScreen(); + +public: + friend class GUIEngine::ScreenSingleton; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void loadedFromFile() OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name, + const int playerID) OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void init() OVERRIDE; + virtual bool onEscapePressed() OVERRIDE; + +}; // class OnlineProfileServers + +#endif diff --git a/src/states_screens/online_profile_base.cpp b/src/states_screens/online_profile_base.cpp index 20812375098..0088cdaf3b0 100644 --- a/src/states_screens/online_profile_base.cpp +++ b/src/states_screens/online_profile_base.cpp @@ -42,7 +42,6 @@ using namespace Online; OnlineProfileBase::OnlineProfileBase(const std::string &filename) : Screen(filename.c_str()) { - m_servers_tab = NULL; m_friends_tab = NULL; m_achievements_tab = NULL; m_settings_tab = NULL; @@ -63,9 +62,6 @@ void OnlineProfileBase::loadedFromFile() m_friends_tab = (IconButtonWidget *)m_profile_tabs->findWidgetNamed("tab_friends"); assert(m_friends_tab != NULL); - m_servers_tab = (IconButtonWidget *)m_profile_tabs->findWidgetNamed("tab_servers"); - assert(m_servers_tab != NULL); - m_achievements_tab = (IconButtonWidget*)m_profile_tabs->findWidgetNamed("tab_achievements"); assert(m_profile_tabs == NULL || m_achievements_tab != NULL); @@ -107,7 +103,6 @@ void OnlineProfileBase::init() if (m_profile_tabs) { - m_servers_tab->setTooltip(_("Servers")); m_friends_tab->setTooltip(_("Friends")); m_achievements_tab->setTooltip(_("Achievements")); m_settings_tab->setTooltip(_("Account Settings")); @@ -159,8 +154,6 @@ void OnlineProfileBase::eventCallback(Widget* widget, const std::string& name, sm->replaceTopMostScreen(TabOnlineProfileAchievements::getInstance()); else if (selection == m_settings_tab->m_properties[PROP_ID]) sm->replaceTopMostScreen(OnlineProfileSettings::getInstance()); - else if (selection == m_servers_tab->m_properties[PROP_ID]) - sm->replaceTopMostScreen(OnlineProfileServers::getInstance()); } else if (name == "back") { diff --git a/src/states_screens/online_profile_base.hpp b/src/states_screens/online_profile_base.hpp index 95a6906fac6..0285edb4b5a 100644 --- a/src/states_screens/online_profile_base.hpp +++ b/src/states_screens/online_profile_base.hpp @@ -42,7 +42,6 @@ class OnlineProfileBase : public GUIEngine::Screen /** Pointer to the various widgets on the screen. */ GUIEngine::LabelWidget * m_header; GUIEngine::RibbonWidget* m_profile_tabs; - GUIEngine::IconButtonWidget * m_servers_tab; GUIEngine::IconButtonWidget * m_friends_tab; GUIEngine::IconButtonWidget * m_achievements_tab; GUIEngine::IconButtonWidget * m_settings_tab; diff --git a/src/states_screens/online_profile_servers.cpp b/src/states_screens/online_profile_servers.cpp index 7d3400b0fce..0787d2fefab 100644 --- a/src/states_screens/online_profile_servers.cpp +++ b/src/states_screens/online_profile_servers.cpp @@ -48,7 +48,7 @@ DEFINE_SCREEN_SINGLETON( OnlineProfileServers ); // ----------------------------------------------------------------------------- -OnlineProfileServers::OnlineProfileServers() : OnlineProfileBase("online/profile_servers.stkgui") +OnlineProfileServers::OnlineProfileServers() : GUIEngine::Screen("online/profile_servers.stkgui") { } // OnlineProfileServers @@ -56,44 +56,28 @@ OnlineProfileServers::OnlineProfileServers() : OnlineProfileBase("online/profile void OnlineProfileServers::loadedFromFile() { - OnlineProfileBase::loadedFromFile(); } // loadedFromFile // ----------------------------------------------------------------------------- void OnlineProfileServers::init() { - OnlineProfileBase::init(); - m_profile_tabs->select( m_servers_tab->m_properties[PROP_ID], PLAYER_ID_GAME_MASTER ); - m_servers_tab->setFocusForPlayer(PLAYER_ID_GAME_MASTER); - // OnlineScreen::getInstance()->push(); + RibbonWidget* ribbon = getWidget("wan"); + assert(ribbon != NULL); + ribbon->select("find_wan_server", PLAYER_ID_GAME_MASTER); + ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER); } // init // ----------------------------------------------------------------------------- void OnlineProfileServers::eventCallback(Widget* widget, const std::string& name, const int playerID) { - OnlineProfileBase::eventCallback( widget, name, playerID); - - if (name == "lan") + if (name == "back") { - RibbonWidget* ribbon = dynamic_cast(widget); - std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "create_lan_server") - { - NetworkConfig::get()->setIsLAN(); - NetworkConfig::get()->setIsServer(true); - CreateServerScreen::getInstance()->push(); - // TODO: create lan server - } - else if (selection == "find_lan_server") - { - NetworkConfig::get()->setIsLAN(); - NetworkConfig::get()->setIsServer(false); - ServerSelection::getInstance()->push(); - } + StateManager::get()->popMenu(); + return; } - else if (name == "wan") + if (name == "wan") { RibbonWidget* ribbon = dynamic_cast(widget); std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER); @@ -176,6 +160,6 @@ void OnlineProfileServers::doQuickPlay() bool OnlineProfileServers::onEscapePressed() { NetworkConfig::get()->unsetNetworking(); - return OnlineProfileBase::onEscapePressed(); + return true; } // onEscapePressed diff --git a/src/states_screens/online_profile_servers.hpp b/src/states_screens/online_profile_servers.hpp index b840f103e2d..0d30b6fe6ed 100644 --- a/src/states_screens/online_profile_servers.hpp +++ b/src/states_screens/online_profile_servers.hpp @@ -33,7 +33,7 @@ namespace GUIEngine { class Widget; } * \brief Online profiel overview screen * \ingroup states_screens */ -class OnlineProfileServers : public OnlineProfileBase, public GUIEngine::ScreenSingleton +class OnlineProfileServers : public GUIEngine::Screen, public GUIEngine::ScreenSingleton { protected: OnlineProfileServers(); diff --git a/src/states_screens/online_screen.cpp b/src/states_screens/online_screen.cpp new file mode 100644 index 00000000000..e7a9d357285 --- /dev/null +++ b/src/states_screens/online_screen.cpp @@ -0,0 +1,200 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2009-2015 Marianne Gagnon +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include "states_screens/main_menu_screen.hpp" + +#include "config/player_manager.hpp" +#include "config/user_config.hpp" +#include "graphics/irr_driver.hpp" +#include "guiengine/scalable_font.hpp" +#include "guiengine/widgets/label_widget.hpp" +#include "guiengine/widgets/list_widget.hpp" +#include "guiengine/widgets/ribbon_widget.hpp" +#include "input/device_manager.hpp" +#include "input/input_manager.hpp" +#include "input/keyboard_device.hpp" +#include "io/file_manager.hpp" +#include "main_loop.hpp" +#include "network/network_config.hpp" +#include "online/request_manager.hpp" +#include "states_screens/online_lan.hpp" +#include "states_screens/online_profile_achievements.hpp" +#include "states_screens/online_profile_servers.hpp" +#include "states_screens/online_screen.hpp" +#include "states_screens/state_manager.hpp" +#include "states_screens/user_screen.hpp" +#include "states_screens/dialogs/message_dialog.hpp" +#include "tracks/track_manager.hpp" +#include "utils/string_utils.hpp" + + +#include + + +using namespace GUIEngine; +using namespace Online; + +DEFINE_SCREEN_SINGLETON( OnlineScreen ); + +bool OnlineScreen::m_enable_online = true; + +// ---------------------------------------------------------------------------- + +OnlineScreen::OnlineScreen() : Screen("online/online.stkgui") +{ + m_online_string = _("Your profile"); + //I18N: Used as a verb, appears on the main networking menu (login button) + m_login_string = _("Login"); +} // OnlineScreen + +// ---------------------------------------------------------------------------- + +void OnlineScreen::loadedFromFile() +{ +} // loadedFromFile + +// ---------------------------------------------------------------------------- + +void OnlineScreen::beforeAddingWidget() +{ + bool is_logged_in = false; + PlayerProfile *player = PlayerManager::getCurrentPlayer(); + if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST || + PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN) + { + is_logged_in = true; + } + + IconButtonWidget* wan = getWidget("wan"); + wan->setActive(is_logged_in); + wan->setVisible(is_logged_in); +} // beforeAddingWidget + +// ---------------------------------------------------------------------------- +// +void OnlineScreen::init() +{ + Screen::init(); + + m_online = getWidget("online"); + + if (!m_enable_online) + m_online->setActive(false); + + m_user_id = getWidget("user-id"); + assert(m_user_id); + + RibbonWidget* r = getWidget("menu_toprow"); + r->setFocusForPlayer(PLAYER_ID_GAME_MASTER); + +} // init + +// ---------------------------------------------------------------------------- + +void OnlineScreen::onUpdate(float delta) +{ + PlayerProfile *player = PlayerManager::getCurrentPlayer(); + if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST || + PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN) + { + m_online->setActive(true); + m_online->setLabel(m_online_string); + m_user_id->setText(player->getLastOnlineName() + "@stk"); + } + else if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_OUT) + { + m_online->setActive(true); + m_online->setLabel(m_login_string); + m_user_id->setText(player->getName()); + } + else + { + // now must be either logging in or logging out + m_online->setActive(false); + m_user_id->setText(player->getName()); + } + + m_online->setLabel(PlayerManager::getCurrentOnlineId() ? m_online_string + : m_login_string); +} // onUpdate + +// ---------------------------------------------------------------------------- + +void OnlineScreen::eventCallback(Widget* widget, const std::string& name, + const int playerID) +{ + if (name == "user-id") + { + UserScreen::getInstance()->push(); + return; + } + else if (name == "back") + { + StateManager::get()->popMenu(); + return; + } + + RibbonWidget* ribbon = dynamic_cast(widget); + if (ribbon == NULL) return; // what's that event?? + + // ---- A ribbon icon was clicked + std::string selection = + ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER); + + if (selection == "lan") + { + OnlineLanScreen::getInstance()->push(); + } + else if (selection == "wan") + { + OnlineProfileServers::getInstance()->push(); + } + else if (selection == "online") + { + if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED) + { + new MessageDialog(_("You can not play online without internet access. " + "If you want to play online, go to options, select " + " tab 'User Interface', and edit " + "\"Connect to the Internet\".")); + return; + } + + if (PlayerManager::getCurrentOnlineId()) + { + ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId()); + TabOnlineProfileAchievements::getInstance()->push(); + } + else + { + UserScreen::getInstance()->push(); + } + } +} // eventCallback + +// ---------------------------------------------------------------------------- + +void OnlineScreen::tearDown() +{ +} // tearDown + +// ---------------------------------------------------------------------------- + +void OnlineScreen::onDisabledItemClicked(const std::string& item) +{ +} // onDisabledItemClicked diff --git a/src/states_screens/online_screen.hpp b/src/states_screens/online_screen.hpp new file mode 100644 index 00000000000..d02f83a3d57 --- /dev/null +++ b/src/states_screens/online_screen.hpp @@ -0,0 +1,73 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2009-2015 Marianne Gagnon +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_ONLINE_SCREEN_HPP +#define HEADER_ONLINE_SCREEN_HPP + +#include "guiengine/screen.hpp" + +namespace GUIEngine { class Widget; class ListWidget; + class ButtonWidget; class IconButtonWidget; } + +/** + * \brief Handles the networking main menu + * \ingroup states_screens + */ +class OnlineScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton +{ +private: + friend class GUIEngine::ScreenSingleton; + + core::stringw m_online_string; + + core::stringw m_login_string; + + /** Keep the widget to to the user name. */ + GUIEngine::ButtonWidget *m_user_id; + + /** Keep the widget to avoid looking it up every frame. */ + GUIEngine::IconButtonWidget* m_online; + + OnlineScreen(); + +public: + /** Temporary disable the online menu while it is being worked at. */ + static bool m_enable_online; + + virtual void onUpdate(float delta) OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void loadedFromFile() OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void beforeAddingWidget() OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name, + const int playerID) OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void init() OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void tearDown() OVERRIDE; + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual void onDisabledItemClicked(const std::string& item) OVERRIDE; +}; + +#endif diff --git a/src/states_screens/user_screen.cpp b/src/states_screens/user_screen.cpp index 91071c59709..e73feb207c9 100644 --- a/src/states_screens/user_screen.cpp +++ b/src/states_screens/user_screen.cpp @@ -400,6 +400,7 @@ void BaseUserScreen::eventCallback(Widget* widget, */ void BaseUserScreen::closeScreen() { + // TODO: return user to where they come from StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); } // closeScreen From 4f528c258db38c2a2edcf0e2688ed812d684a979 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Sun, 26 Nov 2017 21:48:45 -0500 Subject: [PATCH 21/43] Disable new networking menus, will be enabled back in the networking branch --- src/states_screens/main_menu_screen.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index 445f0b8c91c..beb01f3b4c4 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -497,7 +497,26 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, } else if (selection == "online") { - OnlineScreen::getInstance()->push(); + //OnlineScreen::getInstance()->push(); + + if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED) + { + new MessageDialog(_("You can not play online without internet access. " + "If you want to play online, go to options, select " + " tab 'User Interface', and edit " + "\"Connect to the Internet\".")); + return; + } + + if (PlayerManager::getCurrentOnlineId()) + { + ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId()); + TabOnlineProfileAchievements::getInstance()->push(); + } + else + { + UserScreen::getInstance()->push(); + } } else if (selection == "addons") { From 579a4aa3ccd83ff2c59632591d932f8363f46dc0 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Sun, 26 Nov 2017 21:54:48 -0500 Subject: [PATCH 22/43] Improve the way to enable/disable the networking menu, use the --online switch that previously existed --- src/states_screens/main_menu_screen.cpp | 40 +++++++++++++------------ src/states_screens/online_screen.cpp | 4 +-- src/states_screens/online_screen.hpp | 2 -- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index beb01f3b4c4..17f1d325710 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -70,7 +70,7 @@ using namespace Online; DEFINE_SCREEN_SINGLETON( MainMenuScreen ); -bool MainMenuScreen::m_enable_online = true; +bool MainMenuScreen::m_enable_online = false; // ---------------------------------------------------------------------------- @@ -151,9 +151,6 @@ void MainMenuScreen::init() IconButtonWidget* online = getWidget("online"); - if (!m_enable_online) - online->setActive(false); - LabelWidget* w = getWidget("info_addons"); const core::stringw &news_text = NewsManager::get()->getNextNewsMessage(); w->setText(news_text, true); @@ -497,25 +494,30 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, } else if (selection == "online") { - //OnlineScreen::getInstance()->push(); - - if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED) - { - new MessageDialog(_("You can not play online without internet access. " - "If you want to play online, go to options, select " - " tab 'User Interface', and edit " - "\"Connect to the Internet\".")); - return; - } - - if (PlayerManager::getCurrentOnlineId()) + if (MainMenuScreen::m_enable_online) { - ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId()); - TabOnlineProfileAchievements::getInstance()->push(); + OnlineScreen::getInstance()->push(); } else { - UserScreen::getInstance()->push(); + if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED) + { + new MessageDialog(_("You can not play online without internet access. " + "If you want to play online, go to options, select " + " tab 'User Interface', and edit " + "\"Connect to the Internet\".")); + return; + } + + if (PlayerManager::getCurrentOnlineId()) + { + ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId()); + TabOnlineProfileAchievements::getInstance()->push(); + } + else + { + UserScreen::getInstance()->push(); + } } } else if (selection == "addons") diff --git a/src/states_screens/online_screen.cpp b/src/states_screens/online_screen.cpp index e7a9d357285..e0601c56ee9 100644 --- a/src/states_screens/online_screen.cpp +++ b/src/states_screens/online_screen.cpp @@ -51,8 +51,6 @@ using namespace Online; DEFINE_SCREEN_SINGLETON( OnlineScreen ); -bool OnlineScreen::m_enable_online = true; - // ---------------------------------------------------------------------------- OnlineScreen::OnlineScreen() : Screen("online/online.stkgui") @@ -93,7 +91,7 @@ void OnlineScreen::init() m_online = getWidget("online"); - if (!m_enable_online) + if (!MainMenuScreen::m_enable_online) m_online->setActive(false); m_user_id = getWidget("user-id"); diff --git a/src/states_screens/online_screen.hpp b/src/states_screens/online_screen.hpp index d02f83a3d57..69f2b371b1d 100644 --- a/src/states_screens/online_screen.hpp +++ b/src/states_screens/online_screen.hpp @@ -45,8 +45,6 @@ class OnlineScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton OnlineScreen(); public: - /** Temporary disable the online menu while it is being worked at. */ - static bool m_enable_online; virtual void onUpdate(float delta) OVERRIDE; From 48aded5f6d60593f6b6df1e3895e3655d3d9efd2 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Mon, 27 Nov 2017 18:07:42 -0500 Subject: [PATCH 23/43] Login screen : proper post-login redirection --- src/states_screens/user_screen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/states_screens/user_screen.cpp b/src/states_screens/user_screen.cpp index e73feb207c9..c9ef957ee41 100644 --- a/src/states_screens/user_screen.cpp +++ b/src/states_screens/user_screen.cpp @@ -400,8 +400,7 @@ void BaseUserScreen::eventCallback(Widget* widget, */ void BaseUserScreen::closeScreen() { - // TODO: return user to where they come from - StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); + StateManager::get()->popMenu(); } // closeScreen // ---------------------------------------------------------------------------- From ae57be8f3b444f20277e9d7f8ff4662fd07f5d0e Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 30 Nov 2017 17:47:24 +1100 Subject: [PATCH 24/43] Changed version number to be git, added 32bit to installer name, and only include the 32 bit redistributable. --- tools/windows_installer/supertuxkart.nsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/windows_installer/supertuxkart.nsi b/tools/windows_installer/supertuxkart.nsi index 4b9aefb22fb..89e4e498f8d 100755 --- a/tools/windows_installer/supertuxkart.nsi +++ b/tools/windows_installer/supertuxkart.nsi @@ -35,7 +35,7 @@ !define VERSION_MINOR 9 !define VERSION_REVISION 3 ; Empty means stable, could be -git, -rc1 - !define VERSION_BUILD "-rc1" + !define VERSION_BUILD "-git" ;Name and file !define APPNAME "SuperTuxKart" @@ -43,7 +43,7 @@ !define DESCRIPTION "3D open-source arcade racer with a variety characters, tracks, and modes to play" Name "${APPNAMEANDVERSION}" - OutFile "${APPNAMEANDVERSION} installer.exe" + OutFile "${APPNAMEANDVERSION} installer-32bit.exe" # These will be displayed by the "Click here for support information" link in "Add/Remove Programs" # It is possible to use "mailto:" links in here to open the email client @@ -206,7 +206,7 @@ Section "Install" SecMain File *.ico ; prereqs SetOutPath "$INSTDIR\prerequisites" - File /r prerequisites\*.* + File /r prerequisites\vcredist_x86.exe ; data + assets SetOutPath "$INSTDIR\data\" From 4f5b4aed0b1f9b1731a57c20c620a5d870aa207d Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 30 Nov 2017 17:48:34 +1100 Subject: [PATCH 25/43] Change the bld directories to be looked for to all include -64; changed name of installer and only include 64-bit redistributable. --- tools/windows_installer/supertuxkart-64bit.nsi | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/windows_installer/supertuxkart-64bit.nsi b/tools/windows_installer/supertuxkart-64bit.nsi index 5d4f5aaad83..c53a1d4ea30 100755 --- a/tools/windows_installer/supertuxkart-64bit.nsi +++ b/tools/windows_installer/supertuxkart-64bit.nsi @@ -43,7 +43,7 @@ !define DESCRIPTION "3D open-source arcade racer with a variety characters, tracks, and modes to play" Name "${APPNAMEANDVERSION}" - OutFile "${APPNAMEANDVERSION} installer.exe" + OutFile "${APPNAMEANDVERSION} installer-64bit.exe" # These will be displayed by the "Click here for support information" link in "Add/Remove Programs" # It is possible to use "mailto:" links in here to open the email client @@ -174,12 +174,12 @@ Section "Install" SecMain ; Try to find the binary directory in a list of 'typical' names: ; The first found directory is used - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld\bin\RelWithDebInfo\*.* - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld\bin\Release\*.* - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\build\bin\RelWithDebInfo\*.* - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\build\bin\Release\*.* - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build\bin\RelWithDebInfo\*.* - ${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build\bin\Release\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld-64\bin\RelWithDebInfo\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld-64\bin\Release\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\build-64\bin\RelWithDebInfo\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\build-64\bin\Release\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build-64\bin\RelWithDebInfo\*.* + ${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build-64\bin\Release\*.* File /x *.ilk ${EXEC_PATH} @@ -206,7 +206,7 @@ Section "Install" SecMain File *.ico ; prereqs SetOutPath "$INSTDIR\prerequisites" - File /r prerequisites\*.* + File /r prerequisites\vcredist_x64.exe ; data + assets SetOutPath "$INSTDIR\data\" @@ -281,7 +281,6 @@ Section "Uninstall" redist DELETE /REBOOTOK "$INSTDIR\icon.ico" DELETE /REBOOTOK "$INSTDIR\libcurl-4.dll" DELETE /REBOOTOK "$INSTDIR\libeay32.dll" - DELETE /REBOOTOK "$INSTDIR\libidn-11.dll" DELETE /REBOOTOK "$INSTDIR\License.txt" DELETE /REBOOTOK "$INSTDIR\libfreetype.dll" DELETE /REBOOTOK "$INSTDIR\libfribidi-0.dll" From 30938037622c46ada22957fdf0dad17dfa3799bc Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 16 May 2017 22:00:35 +1000 Subject: [PATCH 26/43] Add support for a 'prefix' to be printed for all log messages. --- src/utils/log.cpp | 10 ++++++++++ src/utils/log.hpp | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/utils/log.cpp b/src/utils/log.cpp index e5d39167e83..4816d15d54c 100644 --- a/src/utils/log.cpp +++ b/src/utils/log.cpp @@ -35,6 +35,7 @@ Log::LogLevel Log::m_min_log_level = Log::LL_VERBOSE; bool Log::m_no_colors = false; FILE* Log::m_file_stdout = NULL; +std::string Log::m_prefix = ""; // ---------------------------------------------------------------------------- /** Selects background/foreground colors for the message depending on @@ -181,6 +182,8 @@ void Log::printMessage(int level, const char *component, const char *format, #ifdef ANDROID __android_log_vprint(alp, "SuperTuxKart", format, out); #else + if(!m_prefix.empty()) + printf("%s ", m_prefix.c_str()); printf("[%s] %s: ", names[level], component); vprintf(format, out); #endif @@ -193,6 +196,11 @@ void Log::printMessage(int level, const char *component, const char *format, static char szBuff[2048]; vsnprintf(szBuff, sizeof(szBuff), format, copy2); + if (!m_prefix.empty()) + { + OutputDebugString(m_prefix.c_str()); + OutputDebugString(" "); + } OutputDebugString("["); OutputDebugString(names[level]); OutputDebugString("] "); @@ -205,6 +213,8 @@ void Log::printMessage(int level, const char *component, const char *format, if(m_file_stdout) { + if(!m_prefix.empty()) + fprintf(m_file_stdout, "%s ", m_prefix.c_str()); fprintf (m_file_stdout, "[%s] %s: ", names[level], component); vfprintf(m_file_stdout, format, copy); fprintf (m_file_stdout, "\n"); diff --git a/src/utils/log.hpp b/src/utils/log.hpp index 61726cb8b5f..2d4c69a654a 100644 --- a/src/utils/log.hpp +++ b/src/utils/log.hpp @@ -59,6 +59,9 @@ class Log /** The file where stdout output will be written */ static FILE* m_file_stdout; + /** An optional prefix to be printed. */ + static std::string m_prefix; + static void setTerminalColor(LogLevel level); static void resetTerminalColor(); @@ -120,5 +123,9 @@ class Log { m_no_colors = true; } // disableColor + // ------------------------------------------------------------------------ + /** Sets a prefix to be printed before each line. To disable the prefix, + * set it to "". */ + static void setPrefix(const std::string &prefix) { m_prefix = prefix; } }; // Log #endif From 60a3890c78e5a4e00a7948e8130954adae22b6be Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 1 Dec 2017 13:59:00 +0800 Subject: [PATCH 27/43] Add support for meta library objects --- src/tracks/track.cpp | 9 +++++++++ src/tracks/track.hpp | 6 ++++++ src/tracks/track_object.cpp | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index f29266e268c..ca3fabb6337 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -466,6 +466,7 @@ void Track::cleanup() } #endif + m_meta_library.clear(); Scripting::ScriptEngine::getInstance()->cleanupCache(); m_current_track = NULL; @@ -1757,6 +1758,14 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) loadObjects(root, path, model_def_loader, true, NULL, NULL); + // Correct the parenting of meta library + for (auto& p : m_meta_library) + { + auto* ln = p.first->getPresentation(); + assert(ln); + p.second->setParent(ln->getNode()); + } + model_def_loader.cleanLibraryNodesAfterLoad(); Scripting::ScriptEngine::getInstance()->compileLoadedScripts(); diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index a0d5a5adb6a..4a4603547d0 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -374,6 +374,8 @@ class Track /** List of all bezier curves in the track - for e.g. camera, ... */ std::vector m_all_curves; + std::vector > m_meta_library; + /** The number of laps the track will be raced in a random GP. * m_actual_number_of_laps is initialised with this value.*/ int m_default_number_of_laps; @@ -672,6 +674,10 @@ class Track // ------------------------------------------------------------------------ /** Adds mesh to cleanup list */ void addCachedMesh(scene::IMesh* mesh) { m_all_cached_meshes.push_back(mesh); } + // ------------------------------------------------------------------------ + /** Adds the parent of the meta library for correction later */ + void addMetaLibrary(TrackObject* parent, scene::ISceneNode* meta_library) + { m_meta_library.emplace_back(parent, meta_library); } }; // class Track #endif diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 0d441d12341..0e11cd069f7 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -31,6 +31,7 @@ #include "physics/physical_object.hpp" #include "race/race_manager.hpp" #include "scriptengine/script_engine.hpp" +#include "tracks/track.hpp" #include "tracks/model_definition_loader.hpp" #include @@ -160,6 +161,11 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, { xml_node.get("name", &m_name); m_presentation = new TrackObjectPresentationLibraryNode(this, xml_node, model_def_loader); + if (parent_library != NULL) + { + Track::getCurrentTrack()->addMetaLibrary(parent_library, + (dynamic_cast(m_presentation))->getNode()); + } } else if (type == "sfx-emitter") { From 2161efd9c498bdb25e97007062834f9164394bab Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 2 Dec 2017 02:36:43 +0800 Subject: [PATCH 28/43] Allow configure animation set through scripting --- lib/irrlicht/include/IAnimatedMeshSceneNode.h | 1 + .../source/Irrlicht/CAnimatedMeshSceneNode.h | 1 + src/scriptengine/script_track.cpp | 32 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/lib/irrlicht/include/IAnimatedMeshSceneNode.h b/lib/irrlicht/include/IAnimatedMeshSceneNode.h index 6929dd34777..79de58e12a1 100644 --- a/lib/irrlicht/include/IAnimatedMeshSceneNode.h +++ b/lib/irrlicht/include/IAnimatedMeshSceneNode.h @@ -182,6 +182,7 @@ namespace scene virtual s32 getAnimationSet() const = 0; virtual void addAnimationSet(u32 start, u32 end) = 0; virtual void useAnimationSet(u32 set_num) = 0; + virtual void removeAllAnimationSet() = 0; }; } // end namespace scene diff --git a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h index 68dc937487c..8735dc5388a 100644 --- a/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/lib/irrlicht/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -167,6 +167,7 @@ namespace scene m_animation_set.push_back(start); m_animation_set.push_back(end); } + virtual void removeAllAnimationSet() { m_animation_set.clear(); } virtual void useAnimationSet(u32 set_num); virtual void setFrameLoopOnce(s32 begin, s32 end); protected: diff --git a/src/scriptengine/script_track.cpp b/src/scriptengine/script_track.cpp index 2ca00ea0ca9..a221e0ce414 100644 --- a/src/scriptengine/script_track.cpp +++ b/src/scriptengine/script_track.cpp @@ -295,6 +295,33 @@ namespace Scripting return -1; } + /** Remove all animation set for a skeletal animation */ + void removeAllAnimationSet(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */) + { + if (memory) + { + ((scene::IAnimatedMeshSceneNode*)(memory))->removeAllAnimationSet(); + } + } + + /** Add an animation set for a skeletal animation */ + void addAnimationSet(int start/** \cond DOXYGEN_IGNORE */, int end/** \cond DOXYGEN_IGNORE */, /** \cond DOXYGEN_IGNORE */void *memory /** \endcond */) + { + if (memory) + { + ((scene::IAnimatedMeshSceneNode*)(memory))->addAnimationSet(start, end); + } + } + + /** use an current frame for a skeletal animation */ + void useAnimationSet(int set_num /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */) + { + if (memory) + { + ((scene::IAnimatedMeshSceneNode*)(memory))->useAnimationSet(set_num); + } + } + /** Sets the current frame for a skeletal animation */ void setCurrentFrame(int frame /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */) { @@ -465,6 +492,8 @@ namespace Scripting r = engine->RegisterObjectMethod("TrackObject", "void moveTo(const Vec3 &in, bool)", asMETHOD(::TrackObject, moveTo), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("TrackObject", "Vec3 getCenterPosition()", asFUNCTION(TrackObject::getCenterPosition), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("TrackObject", "Vec3 getOrigin()", asFUNCTION(TrackObject::getOrigin), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("TrackObject", "TrackObject@ getParentLibrary()", asMETHOD(::TrackObject, getParentLibrary), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("TrackObject", "string getName()", asMETHOD(::TrackObject, getName), asCALL_THISCALL); assert(r >= 0); // PhysicalObject r = engine->RegisterObjectMethod("PhysicalObject", "bool isFlattenKartObject()", asMETHOD(PhysicalObject, isFlattenKartObject), asCALL_THISCALL); assert(r >= 0); @@ -476,6 +505,9 @@ namespace Scripting r = engine->RegisterObjectMethod("Mesh", "void setFrameLoopOnce(int start, int end)", asFUNCTION(Mesh::setFrameLoopOnce), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("Mesh", "int getFrameNr()", asFUNCTION(Mesh::getFrameNr), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("Mesh", "int getAnimationSet()", asFUNCTION(Mesh::getAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("Mesh", "void useAnimationSet(int set_num)", asFUNCTION(Mesh::useAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("Mesh", "void addAnimationSet(int start, int end)", asFUNCTION(Mesh::addAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("Mesh", "void removeAllAnimationSet()", asFUNCTION(Mesh::removeAllAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0); r = engine->RegisterObjectMethod("Mesh", "void setCurrentFrame(int frame)", asFUNCTION(Mesh::setCurrentFrame), asCALL_CDECL_OBJLAST); assert(r >= 0); //r = engine->RegisterObjectMethod("Mesh", "void move(Vec3 &in)", asFUNCTION(movePresentation), asCALL_CDECL_OBJLAST); assert(r >= 0); From 3607c7d520508ca505e32e5f97207e788d89690e Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 2 Dec 2017 15:24:05 +0800 Subject: [PATCH 29/43] Adjust irrlicht CSkinnedMesh class for .spm The last frame in .spm is usable --- lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp | 2 +- lib/irrlicht/source/Irrlicht/CSkinnedMesh.h | 3 ++- src/graphics/sp_mesh_loader.cpp | 10 +++++++--- src/graphics/sp_mesh_loader.hpp | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp index eb11aeababa..27850ed244c 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.cpp @@ -68,7 +68,7 @@ namespace scene //! constructor CSkinnedMesh::CSkinnedMesh() -: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f), +: AnimationFrames(0.f), SkinningBuffers(0), FramesPerSecond(25.f), LastAnimatedFrame(-1), SkinnedLastFrame(false), InterpolationMode(EIM_LINEAR), HasAnimation(false), PreparedForSkinning(false), diff --git a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h index 0dd936f0d63..24d3306a7fc 100644 --- a/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h +++ b/lib/irrlicht/source/Irrlicht/CSkinnedMesh.h @@ -175,6 +175,8 @@ namespace scene u32 getTotalJoints() const { return m_total_joints; } + f32 AnimationFrames; + private: void toStaticPose(); @@ -215,7 +217,6 @@ namespace scene core::aabbox3d BoundingBox; - f32 AnimationFrames; f32 FramesPerSecond; f32 LastAnimatedFrame; diff --git a/src/graphics/sp_mesh_loader.cpp b/src/graphics/sp_mesh_loader.cpp index fec1a8e2ce2..57c1cd614c6 100644 --- a/src/graphics/sp_mesh_loader.cpp +++ b/src/graphics/sp_mesh_loader.cpp @@ -20,6 +20,7 @@ #include "utils/constants.hpp" #include "utils/mini_glm.hpp" +#include "../../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h" const uint8_t VERSION_NOW = 1; #include @@ -47,7 +48,7 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f) } m_bind_frame = 0; m_joint_count = 0; - //m_frame_count = 0; + m_frame_count = 0; m_mesh = NULL; m_mesh = m_scene_manager->createSkinnedMesh(); io::IFileSystem* fs = m_scene_manager->getFileSystem(); @@ -196,6 +197,9 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f) f->read(&pre_computed_size, 2); } m_mesh->finalize(); + // Because the last frame in spm is usable + static_cast(m_mesh)->AnimationFrames = + (float)m_frame_count + 1.0f; m_all_armatures.clear(); m_to_bind_pose_matrices.clear(); m_joints.clear(); @@ -366,8 +370,8 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm) } for (unsigned i = 0; i < armature_size; i++) { - //m_frame_count = std::max(m_frame_count, - // (unsigned)m_all_armatures[i].m_frame_pose_matrices.back().first); + m_frame_count = std::max(m_frame_count, + (unsigned)m_all_armatures[i].m_frame_pose_matrices.back().first); m_joint_count += m_all_armatures[i].m_joint_used; } diff --git a/src/graphics/sp_mesh_loader.hpp b/src/graphics/sp_mesh_loader.hpp index 64e257bf85b..55fc031ae5a 100644 --- a/src/graphics/sp_mesh_loader.hpp +++ b/src/graphics/sp_mesh_loader.hpp @@ -79,7 +79,7 @@ class SPMeshLoader : public scene::IMeshLoader unsigned id); }; // ------------------------------------------------------------------------ - unsigned m_bind_frame, m_joint_count;//, m_frame_count; + unsigned m_bind_frame, m_joint_count, m_frame_count; // ------------------------------------------------------------------------ std::vector m_all_armatures; // ------------------------------------------------------------------------ From 7ab8477a53ee6c48b1d31a17e244ebc1f2b0d298 Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 2 Dec 2017 15:24:36 +0800 Subject: [PATCH 30/43] Reserve onReset of scripting method for library nodes (unused atm) --- src/tracks/track_object_presentation.cpp | 17 +++++++++++++++++ src/tracks/track_object_presentation.hpp | 9 +++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index 414106b1b6f..5fe1e839c0f 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -180,6 +180,7 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode( { m_parent = NULL; m_start_executed = false; + m_reset_executed = false; std::string name; xml_node.get("name", &name); @@ -289,6 +290,22 @@ void TrackObjectPresentationLibraryNode::update(float dt) m_start_executed = true; std::string fn_name = StringUtils::insertValues("void %s::onStart(const string)", m_name.c_str()); + if (m_parent != NULL) + { + std::string lib_id = m_parent->getID(); + std::string* lib_id_ptr = &lib_id; + + Scripting::ScriptEngine::getInstance()->runFunction(false, fn_name, + [&](asIScriptContext* ctx) { + ctx->SetArgObject(0, lib_id_ptr); + }); + } + } + if (!m_reset_executed) + { + m_reset_executed = true; + std::string fn_name = StringUtils::insertValues("void %s::onReset(const string)", m_name.c_str()); + if (m_parent != NULL) { std::string lib_id = m_parent->getID(); diff --git a/src/tracks/track_object_presentation.hpp b/src/tracks/track_object_presentation.hpp index a2eedf32ac2..4a990b29650 100644 --- a/src/tracks/track_object_presentation.hpp +++ b/src/tracks/track_object_presentation.hpp @@ -187,13 +187,18 @@ class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNo TrackObject* m_parent; using TrackObjectPresentationSceneNode::move; std::string m_name; - bool m_start_executed; + bool m_start_executed, m_reset_executed; public: TrackObjectPresentationLibraryNode(TrackObject* parent, const XMLNode& xml_node, ModelDefinitionLoader& model_def_loader); virtual ~TrackObjectPresentationLibraryNode(); - virtual void update(float dt); + virtual void update(float dt) OVERRIDE; + virtual void reset() OVERRIDE + { + m_reset_executed = false; + TrackObjectPresentationSceneNode::reset(); + } void move(const core::vector3df& xyz, const core::vector3df& hpr, const core::vector3df& scale, bool isAbsoluteCoord, bool moveChildrenPhysicalBodies); }; // TrackObjectPresentationLibraryNode From d9937d7b3397ca58a0fe59a5b884c726bd8476a0 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 3 Dec 2017 23:58:17 +0800 Subject: [PATCH 31/43] Fix physical object from meta library --- src/tracks/track.cpp | 40 ++++++++++++++++++++++++++++++++++++- src/tracks/track.hpp | 4 ++-- src/tracks/track_object.cpp | 3 +-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index ca3fabb6337..48818f4bd17 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1571,6 +1571,39 @@ void Track::createWater(const XMLNode &node) scene_node->getMaterial(0).setFlag(video::EMF_GOURAUD_SHADING, true); } // createWater +// ---------------------------------------------------------------------------- +static void recursiveUpdatePosition(scene::ISceneNode *node) +{ + node->updateAbsolutePosition(); + + scene::ISceneNodeList::ConstIterator it = node->getChildren().begin(); + for (; it != node->getChildren().end(); ++it) + { + recursiveUpdatePosition(*it); + } +} // recursiveUpdatePosition + +// ---------------------------------------------------------------------------- +static void recursiveUpdatePhysics(std::vector& tos) +{ + for (TrackObject* to : tos) + { + if (to->getPhysicalObject()) + { + TrackObjectPresentationSceneNode* sn = to + ->getPresentation(); + if (sn) + { + to->getPhysicalObject()->move( + sn->getNode()->getAbsoluteTransformation().getTranslation(), + sn->getNode()->getAbsoluteTransformation() + .getRotationDegrees()); + } + } + recursiveUpdatePhysics(to->getChildren()); + } +} // recursiveUpdatePhysics + // ---------------------------------------------------------------------------- /** This function load the actual scene, i.e. all parts of the track, * animations, items, ... It is called from world during initialisation. @@ -1763,7 +1796,12 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) { auto* ln = p.first->getPresentation(); assert(ln); - p.second->setParent(ln->getNode()); + TrackObjectPresentationLibraryNode* meta_ln = p.second + ->getPresentation(); + assert(meta_ln); + meta_ln->getNode()->setParent(ln->getNode()); + recursiveUpdatePosition(meta_ln->getNode()); + recursiveUpdatePhysics(p.second->getChildren()); } model_def_loader.cleanLibraryNodesAfterLoad(); diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 4a4603547d0..f050f5959f6 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -374,7 +374,7 @@ class Track /** List of all bezier curves in the track - for e.g. camera, ... */ std::vector m_all_curves; - std::vector > m_meta_library; + std::vector > m_meta_library; /** The number of laps the track will be raced in a random GP. * m_actual_number_of_laps is initialised with this value.*/ @@ -676,7 +676,7 @@ class Track void addCachedMesh(scene::IMesh* mesh) { m_all_cached_meshes.push_back(mesh); } // ------------------------------------------------------------------------ /** Adds the parent of the meta library for correction later */ - void addMetaLibrary(TrackObject* parent, scene::ISceneNode* meta_library) + void addMetaLibrary(TrackObject* parent, TrackObject* meta_library) { m_meta_library.emplace_back(parent, meta_library); } }; // class Track diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 0e11cd069f7..255f001297c 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -163,8 +163,7 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, m_presentation = new TrackObjectPresentationLibraryNode(this, xml_node, model_def_loader); if (parent_library != NULL) { - Track::getCurrentTrack()->addMetaLibrary(parent_library, - (dynamic_cast(m_presentation))->getNode()); + Track::getCurrentTrack()->addMetaLibrary(parent_library, this); } } else if (type == "sfx-emitter") From 1afb62c97df325ba1ed966a6fc185516749ebf18 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Sun, 3 Dec 2017 18:44:50 -0500 Subject: [PATCH 32/43] Bring back the ability to skip the unlock cutscense, fixes #3069 --- src/states_screens/feature_unlocked.cpp | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/states_screens/feature_unlocked.cpp b/src/states_screens/feature_unlocked.cpp index 8ae059181f0..eb69539b491 100644 --- a/src/states_screens/feature_unlocked.cpp +++ b/src/states_screens/feature_unlocked.cpp @@ -581,20 +581,20 @@ bool FeatureUnlockedCutScene::onEscapePressed() void FeatureUnlockedCutScene::continueButtonPressed() { - //if (m_global_time < GIFT_EXIT_TO) - //{ - // // If animation was not over yet, the button is used to skip the animation - // while (m_global_time < GIFT_EXIT_TO) - // { - // // simulate all the steps of the animation until we reach the end - // onUpdate(0.4f); - // World::getWorld()->updateWorld(0.4f); - // } - //} - //else - //{ + if (m_global_time < GIFT_EXIT_TO) + { + // If animation was not over yet, the button is used to skip the animation + while (m_global_time < GIFT_EXIT_TO) + { + // simulate all the steps of the animation until we reach the end + onUpdate(0.4f); + World::getWorld()->updateWorld(0.4f); + } + } + else + { ((CutsceneWorld*)World::getWorld())->abortCutscene(); - //} + } } // continueButtonPressed From 55d0df7bad94715c8e58cc67ef27f3136a8a94da Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 4 Dec 2017 11:32:09 +1100 Subject: [PATCH 33/43] Added option to buffer log messages (which can reduce debug output overhead). --- sources.cmake | 2 +- src/main.cpp | 7 ++ src/utils/log.cpp | 188 +++++++++++++++++++++++----------------------- src/utils/log.hpp | 27 ++++++- 4 files changed, 129 insertions(+), 95 deletions(-) diff --git a/sources.cmake b/sources.cmake index d4f28ae4de4..13db008ff50 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/main.cpp b/src/main.cpp index c3868be7b39..28ba7201e4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -594,6 +594,7 @@ void cmdLineHelp() " -h, --help Show this help.\n" " --log=N Set the verbosity to a value between\n" " 0 (Debug) and 5 (Only Fatal messages)\n" + " --logbuffer=N Buffers up to N lines log lines before writing.\n" " --root=DIR Path to add to the list of STK root directories.\n" " You can specify more than one by separating them\n" " with colons (:).\n" @@ -664,6 +665,8 @@ int handleCmdLineOutputModifier() int n; if(CommandLine::has("--log", &n)) Log::setLogLevel(n); + if (CommandLine::has("--logbuffer", &n)) + Log::setBufferSize(n); if(CommandLine::has("--log=nocolor")) { @@ -1807,8 +1810,10 @@ int main(int argc, char *argv[] ) } // try catch (std::exception &e) { + Log::flushBuffers(); Log::error("main", "Exception caught : %s.",e.what()); Log::error("main", "Aborting SuperTuxKart."); + Log::flushBuffers(); } /* Program closing...*/ @@ -1832,6 +1837,8 @@ int main(int argc, char *argv[] ) MemoryLeaks::checkForLeaks(); #endif + Log::flushBuffers(); + #ifndef WIN32 if (user_config) //close logfiles { diff --git a/src/utils/log.cpp b/src/utils/log.cpp index 4816d15d54c..f5475a9acaa 100644 --- a/src/utils/log.cpp +++ b/src/utils/log.cpp @@ -36,6 +36,8 @@ Log::LogLevel Log::m_min_log_level = Log::LL_VERBOSE; bool Log::m_no_colors = false; FILE* Log::m_file_stdout = NULL; std::string Log::m_prefix = ""; +size_t Log::m_buffer_size = 1; +Synchronised > Log::m_line_buffer; // ---------------------------------------------------------------------------- /** Selects background/foreground colors for the message depending on @@ -107,25 +109,22 @@ void Log::setTerminalColor(LogLevel level) */ void Log::resetTerminalColor() { - if(m_no_colors) - { - printf("\n"); - return; - } - + if(m_no_colors) return; #ifdef WIN32 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), /*TERM_BLACK*/0 << 4 | /*TERM_LIGHTGRAY*/7); - printf("\n"); #else printf("%c[0;;m\n", 0x1B); #endif } // resetTerminalColor // ---------------------------------------------------------------------------- -/** This actually prints the log message. If log messages are not redirected - * to a file, it tries to select a terminal colour. +/** This actually creates a log message. If the messages are to be buffered, + * it will be appended to the output buffer. If the buffer is full, it will + * be flushed. If the message is not to be buffered, it will be immediately + * written using writeLine(). + * \param level Log level of the message to print. * \param format A printf-like format string. * \param va_list The values to be printed for the format. @@ -133,114 +132,119 @@ void Log::resetTerminalColor() void Log::printMessage(int level, const char *component, const char *format, VALIST args) { - assert(level>=0 && level <=LL_FATAL); + assert(level >= 0 && level <= LL_FATAL); - if(level= LL_WARN || + if (!m_file_stdout || level >= LL_WARN || UserConfigParams::m_log_errors_to_console) // log to console & file { - VALIST out; - va_copy(out, args); - setTerminalColor((LogLevel)level); - #ifdef ANDROID - __android_log_vprint(alp, "SuperTuxKart", format, out); - #else - if(!m_prefix.empty()) - printf("%s ", m_prefix.c_str()); - printf("[%s] %s: ", names[level], component); - vprintf(format, out); - #endif +#ifdef ANDROID + android_LogPriority alp; + switch (level) + { + // STK is using the levels slightly different from android + // (debug lowest, verbose above it; while android reverses + // this order. So to get the same behaviour (e.g. filter + // out debug message, but still get verbose, we swap + // the order here. + case LL_VERBOSE: alp = ANDROID_LOG_DEBUG; break; + case LL_DEBUG: alp = ANDROID_LOG_VERBOSE; break; + case LL_INFO: alp = ANDROID_LOG_INFO; break; + case LL_WARN: alp = ANDROID_LOG_WARN; break; + case LL_ERROR: alp = ANDROID_LOG_ERROR; break; + case LL_FATAL: alp = ANDROID_LOG_FATAL; break; + default: alp = ANDROID_LOG_FATAL; + } + __android_log_vprint(alp, "SuperTuxKart", line); +#else + printf(line); +#endif resetTerminalColor(); // this prints a \n - - va_end(out); } #if defined(_MSC_FULL_VER) && defined(_DEBUG) - static char szBuff[2048]; - vsnprintf(szBuff, sizeof(szBuff), format, copy2); - - if (!m_prefix.empty()) - { - OutputDebugString(m_prefix.c_str()); - OutputDebugString(" "); - } - OutputDebugString("["); - OutputDebugString(names[level]); - OutputDebugString("] "); - OutputDebugString(component); - OutputDebugString(": "); - OutputDebugString(szBuff); - OutputDebugString("\r\n"); + OutputDebugString(line); #endif - - if(m_file_stdout) - { - if(!m_prefix.empty()) - fprintf(m_file_stdout, "%s ", m_prefix.c_str()); - fprintf (m_file_stdout, "[%s] %s: ", names[level], component); - vfprintf(m_file_stdout, format, copy); - fprintf (m_file_stdout, "\n"); - va_end(copy); - } + if (m_file_stdout) fprintf(m_file_stdout, line); #ifdef WIN32 if (level >= LL_FATAL) { - std::string message; - - char tmp[2048]; - sprintf(tmp, "[%s] %s: ", names[level], component); - message += tmp; - - VALIST out; - va_copy(out, args); - vsprintf(tmp, format, out); - message += tmp; - va_end(out); - - MessageBoxA(NULL, message.c_str(), "SuperTuxKart - Fatal error", MB_OK); + MessageBoxA(NULL, line, "SuperTuxKart - Fatal error", MB_OK); } #endif -} // printMessage +} // _fluhBuffers +// ---------------------------------------------------------------------------- +/** Flushes all stored log messages to the various output devices (thread safe). + */ +void Log::flushBuffers() +{ + m_line_buffer.lock(); + for (unsigned int i = 0; i < m_line_buffer.getData().size(); i++) + { + const LineInfo &li = m_line_buffer.getData()[i]; + writeLine(li.m_line.c_str(), li.m_level); + } + m_line_buffer.getData().clear(); + m_line_buffer.unlock(); +} // flushBuffers // ---------------------------------------------------------------------------- /** This function opens the files that will contain the output. diff --git a/src/utils/log.hpp b/src/utils/log.hpp index 2d4c69a654a..1d5ceb5bcdb 100644 --- a/src/utils/log.hpp +++ b/src/utils/log.hpp @@ -20,11 +20,15 @@ #ifndef HEADER_LOG_HPP #define HEADER_LOG_HPP +#include "utils/synchronised.hpp" + #include #include #include #include #include +#include + #ifdef __GNUC__ # define VALIST __gnuc_va_list @@ -59,16 +63,30 @@ class Log /** The file where stdout output will be written */ static FILE* m_file_stdout; + /** An optional buffer for lines to be output. */ + struct LineInfo + { + std::string m_line; + int m_level; + }; + static Synchronised > m_line_buffer; + + /** <0 if no buffered logging is to be used, otherwise this is + ** the maximum number of lines the buffer should hold. */ + static size_t m_buffer_size; + /** An optional prefix to be printed. */ static std::string m_prefix; static void setTerminalColor(LogLevel level); static void resetTerminalColor(); - -public: + static void writeLine(const char *line, int level); static void printMessage(int level, const char *component, const char *format, VALIST va_list); + +public: + // ------------------------------------------------------------------------ /** A simple macro to define the various log functions. * Note that an assert is added so that a debugger is triggered @@ -98,7 +116,12 @@ class Log static void openOutputFiles(const std::string &logout); static void closeOutputFiles(); + static void flushBuffers(); + // ------------------------------------------------------------------------ + /** Sets the number of lines to buffer. Setting the buffer size to a + * a value <=1 means no buffering, lines will be immediately printed. */ + static void setBufferSize(size_t n) { m_buffer_size = n; } // ------------------------------------------------------------------------ /** Defines the minimum log level to be displayed. */ static void setLogLevel(int n) From ebcab8d4e06e82f7f97156381a7316c26f5e4565 Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 7 Dec 2017 09:43:27 +1100 Subject: [PATCH 34/43] Fixed compiler warning. --- src/karts/kart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 938273ad7e9..79edf6f9331 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -2181,7 +2181,7 @@ void Kart::playCrashSFX(const Material* m, AbstractKart *k) { const float speed_for_max_volume = 15; //The speed at which the sound plays at maximum volume const float max_volume = 1; //The maximum volume a sound is played at - const float min_volume = 0.2; //The minimum volume a sound is played at + const float min_volume = 0.2f; //The minimum volume a sound is played at float volume; //The volume the crash sound will be played at From f70af4677c4691df1d8114ad5be20a659f1ca793 Mon Sep 17 00:00:00 2001 From: Benau Date: Sat, 9 Dec 2017 16:06:43 +0800 Subject: [PATCH 35/43] Add direct conversion to map for xml nodes --- src/config/user_config.cpp | 61 ++++++++------------------------- src/graphics/command_buffer.cpp | 4 ++- src/graphics/command_buffer.hpp | 5 ++- src/graphics/draw_calls.cpp | 4 +-- src/io/xml_node.cpp | 1 - src/io/xml_node.hpp | 23 +++++++++++++ 6 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 79511fd2af1..788efc0dceb 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -321,7 +321,7 @@ core::stringc ListUserConfigParam::toString() const return ""; } // toString - // ============================================================================ +// ---------------------------------------------------------------------------- template MapUserConfigParam::MapUserConfigParam(const char* param_name, const char* comment) @@ -331,7 +331,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, if (comment != NULL) m_comment = comment; } // MapUserConfigParam - // ============================================================================ +// ---------------------------------------------------------------------------- template MapUserConfigParam::MapUserConfigParam(const char* param_name, const char* comment, @@ -345,7 +345,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - + struct pair_type { T key; U value; }; for (int i = 0; i < nb_elements; i++) @@ -356,7 +356,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, va_end(arguments); // Cleans up the list } // MapUserConfigParam - // ============================================================================ +// ---------------------------------------------------------------------------- template MapUserConfigParam::MapUserConfigParam(const char* param_name, GroupUserConfigParam* group, @@ -367,7 +367,7 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, if (comment != NULL) m_comment = comment; } // MapUserConfigParam - // ============================================================================ +// ---------------------------------------------------------------------------- template MapUserConfigParam::MapUserConfigParam(const char* param_name, GroupUserConfigParam* group, @@ -382,30 +382,25 @@ MapUserConfigParam::MapUserConfigParam(const char* param_name, // add the default list va_list arguments; va_start(arguments, nb_elements); - + struct pair_type { T key; U value; }; - for (int i = 0; i < nb_elements; i++) { + for (int i = 0; i < nb_elements; i++) + { pair_type key_value_pair = va_arg(arguments, pair_type); m_elements.insert(std::pair(key_value_pair.key, key_value_pair.value)); } va_end(arguments); // Cleans up the list } // MapUserConfigParam - // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- template void MapUserConfigParam::write(std::ofstream& stream) const { - const int elts_amount = m_elements.size(); - // comment if (m_comment.size() > 0) stream << " \n <" << m_param_name.c_str() << "\n"; - stream << " Size=\"" << elts_amount << "\"\n"; - // actual elements - //for (int n = 0; n::write(std::ofstream& stream) const stream << " \n\n"; } // write - // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- template void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) @@ -425,56 +420,30 @@ void MapUserConfigParam::findYourDataInAChildOf(const XMLNode* node) //Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str()); return; } - - int attr_count = 0; - child->get("Size", &attr_count); - - for (const auto& kv : m_elements) - { - std::pair elt; - elt.first = kv.first; - elt.second = kv.second; - - - bool there = false; - - for (const auto& kvRHS : m_elements) - { - if (elt.second == kvRHS.second) - { - there = true; - break; - } - - } - if (!there) - { - m_elements.insert(elt); - } - } + child->get(&m_elements); } // findYourDataInAChildOf - // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- template void MapUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node) { } // findYourDataInAnAttributeOf - // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- template void MapUserConfigParam::addElement(T element, U value) { m_elements[element] = value; } // findYourDataInAnAttributeOf - // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- template core::stringc MapUserConfigParam::toString() const { return ""; } // toString -// ============================================================================ +// ---------------------------------------------------------------------------- IntUserConfigParam::IntUserConfigParam(int default_value, const char* param_name, const char* comment) diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index 761ae122bc9..d2f09a96229 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -166,7 +166,9 @@ void SolidCommandBuffer::fill(MeshMap *mesh_map) fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); - + /* glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0,10000 * 20); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER,0);*/ if (!CVS->supportsAsyncInstanceUpload()) glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); } //SolidCommandBuffer::fill diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 35021a8f4ac..23349ff43ec 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -218,7 +218,10 @@ class CommandBuffer mesh_map, instance_buffer); } - + /*glBindBuffer(GL_ARRAY_BUFFER, + VAOManager::getInstance()->getInstanceBuffer(instance_type)); + glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0,10000 * sizeof(InstanceDataThreeTex)); + glBindBuffer(GL_ARRAY_BUFFER,0);*/ if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 58170838d0c..0073fc73c6b 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -721,8 +721,8 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices, solid_poly_count = m_solid_cmd_buffer->getPolyCount(); shadow_poly_count = m_shadow_cmd_buffer->getPolyCount(); - if (CVS->supportsAsyncInstanceUpload()) - glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); + //if (CVS->supportsAsyncInstanceUpload()) + // glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); #endif // !defined(USE_GLES2) } diff --git a/src/io/xml_node.cpp b/src/io/xml_node.cpp index cbc8dc21a2d..12d38c1e710 100644 --- a/src/io/xml_node.cpp +++ b/src/io/xml_node.cpp @@ -18,7 +18,6 @@ #include "io/file_manager.hpp" #include "io/xml_node.hpp" -#include "utils/string_utils.hpp" #include "utils/interpolation_array.hpp" #include "utils/vec3.hpp" diff --git a/src/io/xml_node.hpp b/src/io/xml_node.hpp index ed990dab4cf..66baea9db11 100644 --- a/src/io/xml_node.hpp +++ b/src/io/xml_node.hpp @@ -33,9 +33,11 @@ using namespace irr; #include "utils/leak_check.hpp" #include "utils/no_copy.hpp" +#include "utils/string_utils.hpp" #include "utils/time.hpp" #include "utils/types.hpp" + class InterpolationArray; class Vec3; @@ -95,6 +97,27 @@ class XMLNode : public NoCopy int getHPR(core::vector3df *value) const; int getHPR(Vec3 *value) const; + template + int get(std::map* out_map) const + { + using namespace StringUtils; + for (auto& p : m_attributes) + { + T val_1; + if (!fromString(p.first, val_1)) + { + return 0; + } + U val_2; + if (!fromString(wideToUtf8(p.second), val_2)) + { + return 0; + } + (*out_map)[val_1] = val_2; + } + return (int)m_attributes.size(); + } + bool hasChildNamed(const char* name) const; /** Handy functions to test the bit pattern returned by get(vector3df*).*/ From dc562103c5b9ea41f84903888e18b2c8a6a8e626 Mon Sep 17 00:00:00 2001 From: Benau Date: Sun, 10 Dec 2017 00:12:35 +0800 Subject: [PATCH 36/43] Remove wrong commit --- src/graphics/command_buffer.cpp | 3 --- src/graphics/command_buffer.hpp | 4 ---- src/graphics/draw_calls.cpp | 4 ++-- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp index d2f09a96229..3c5e9762cfe 100644 --- a/src/graphics/command_buffer.cpp +++ b/src/graphics/command_buffer.cpp @@ -166,9 +166,6 @@ void SolidCommandBuffer::fill(MeshMap *mesh_map) fillInstanceData (mesh_map, four_tex_material_list, InstanceTypeFourTex); - /* glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); - glFlushMappedBufferRange(GL_DRAW_INDIRECT_BUFFER, 0,10000 * 20); - glBindBuffer(GL_DRAW_INDIRECT_BUFFER,0);*/ if (!CVS->supportsAsyncInstanceUpload()) glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); } //SolidCommandBuffer::fill diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp index 23349ff43ec..2706b9239c7 100644 --- a/src/graphics/command_buffer.hpp +++ b/src/graphics/command_buffer.hpp @@ -218,10 +218,6 @@ class CommandBuffer mesh_map, instance_buffer); } - /*glBindBuffer(GL_ARRAY_BUFFER, - VAOManager::getInstance()->getInstanceBuffer(instance_type)); - glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0,10000 * sizeof(InstanceDataThreeTex)); - glBindBuffer(GL_ARRAY_BUFFER,0);*/ if (!CVS->supportsAsyncInstanceUpload()) { glUnmapBuffer(GL_ARRAY_BUFFER); diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index 0073fc73c6b..58170838d0c 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -721,8 +721,8 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices, solid_poly_count = m_solid_cmd_buffer->getPolyCount(); shadow_poly_count = m_shadow_cmd_buffer->getPolyCount(); - //if (CVS->supportsAsyncInstanceUpload()) - // glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); + if (CVS->supportsAsyncInstanceUpload()) + glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); #endif // !defined(USE_GLES2) } From a55e7d204a08173941d4490a0e6075a52b4ec33e Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 11 Dec 2017 11:00:06 +0800 Subject: [PATCH 37/43] Fix wrong newline in linux terminal --- src/utils/log.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/log.cpp b/src/utils/log.cpp index f5475a9acaa..2b5ea0557f1 100644 --- a/src/utils/log.cpp +++ b/src/utils/log.cpp @@ -115,7 +115,7 @@ void Log::resetTerminalColor() SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), /*TERM_BLACK*/0 << 4 | /*TERM_LIGHTGRAY*/7); #else - printf("%c[0;;m\n", 0x1B); + printf("%c[0;;m", 0x1B); #endif } // resetTerminalColor From 2b8737a75bdb6706b71d67be2ff9edb7426af3f4 Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 12 Dec 2017 23:07:01 +0100 Subject: [PATCH 38/43] Remove known issues from android readme. We can use github issues for it. --- android/README.ANDROID | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/android/README.ANDROID b/android/README.ANDROID index 689d0992821..4dda169857d 100644 --- a/android/README.ANDROID +++ b/android/README.ANDROID @@ -143,38 +143,3 @@ you have to run: and then: zipalign -v 4 SuperTuxKart-release-unsigned.apk SuperTuxKart-release.apk - - - --------------------------------------------------------------------------------- - KNOWN ISSUES --------------------------------------------------------------------------------- - -1. It's not possible to compile STK for Android < 4.4 due to missing GLES 3.0 - functions. It is technically possible to do - check GLES context version, - load OpenGL functions dynamically using EGL, and if they are not loaded - properly, then fallback to GLES 2.0. - -2. It never ocurred for me, but it's possible that EGL context is lost in some - cases. SuperTuxKart is not designed to re-create all textures at any moment, - so this is a "Wontfix", at least for now. - -3. We use "exit(0)" at the end of main function. We shouldn't do it and we - should just return from the main function. But STK uses some global - variables and their values are remembered when the game is restarted. We - should properly clear them or re-initialize on startup. Using the "exit(0)" - is not-that-bad workaround, but it may cause a crash on exit sometimes. - It seems to affect only Android 5.0. More information about the crash: - https://code.google.com/p/android/issues/detail?id=160824 - -4. STK crashes on startup on some devices when aarch64 build is made using - Android r13 NDK. The r13 version has rather big modifications (it uses clang - instead of gcc by default). This is probably a bug in NDK/compiler/OS, but - for this reason using NDK r12 for 64-bit arm compilation is preferred. - -5. Angelscript doesn't have full support for aarch64 builds, so that scripting - won't work on this platform. - -6. Turning left/right using accelerometer is available, but at this stage the - default screen orientation is not automatically detected and user must - manually choose if he needs "phone" or "tablet" accelerometer. From 6f6ac84495ab36529f7f8cf2dae2c12f7d258041 Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 22 Dec 2017 21:02:37 +0100 Subject: [PATCH 39/43] Fixed android compilation --- src/utils/log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/log.cpp b/src/utils/log.cpp index 2b5ea0557f1..d9c25e7bf53 100644 --- a/src/utils/log.cpp +++ b/src/utils/log.cpp @@ -210,7 +210,7 @@ void Log::writeLine(const char *line, int level) case LL_FATAL: alp = ANDROID_LOG_FATAL; break; default: alp = ANDROID_LOG_FATAL; } - __android_log_vprint(alp, "SuperTuxKart", line); + __android_log_print(alp, "SuperTuxKart", "%s", line); #else printf(line); #endif @@ -221,7 +221,7 @@ void Log::writeLine(const char *line, int level) OutputDebugString(line); #endif - if (m_file_stdout) fprintf(m_file_stdout, line); + if (m_file_stdout) fprintf(m_file_stdout, "%s", line); #ifdef WIN32 if (level >= LL_FATAL) From 31f8b7ec35c22dc9f46b251ca98b579dcd7e7b20 Mon Sep 17 00:00:00 2001 From: Deve Date: Fri, 22 Dec 2017 21:51:41 +0100 Subject: [PATCH 40/43] Allow to install debug version without uninstalling release version on android --- .gitignore | 1 + android/icon-dbg.png | Bin 0 -> 42674 bytes android/{res/drawable => }/icon.png | Bin android/make.sh | 37 +++++++++++++++++++++++++++ android/res/drawable-hdpi/icon.png | Bin 5874 -> 0 bytes android/res/drawable-mdpi/icon.png | Bin 3208 -> 0 bytes android/res/drawable-xhdpi/icon.png | Bin 9068 -> 0 bytes android/res/drawable-xxhdpi/icon.png | Bin 17129 -> 0 bytes android/res/values/strings.xml | 4 --- 9 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 android/icon-dbg.png rename android/{res/drawable => }/icon.png (100%) delete mode 100644 android/res/drawable-hdpi/icon.png delete mode 100644 android/res/drawable-mdpi/icon.png delete mode 100644 android/res/drawable-xhdpi/icon.png delete mode 100644 android/res/drawable-xxhdpi/icon.png delete mode 100644 android/res/values/strings.xml diff --git a/.gitignore b/.gitignore index 6a4a4c428d6..057e8029cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ android/bin android/build android/libs android/obj +android/res android/.gradle android-* *.apk diff --git a/android/icon-dbg.png b/android/icon-dbg.png new file mode 100644 index 0000000000000000000000000000000000000000..cc9799a64a1ee3ff62c75d20a761a131af170a1e GIT binary patch literal 42674 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" > "$STRINGS_FILE" +echo "" >> "$STRINGS_FILE" +echo " $APP_NAME" >> "$STRINGS_FILE" +echo "" >> "$STRINGS_FILE" + sed -i "s/minSdkVersion=\".*\"/minSdkVersion=\"$SDK_VERSION\"/g" \ "$DIRNAME/AndroidManifest.xml" + +sed -i "s/package=\".*\"/package=\"$PACKAGE_NAME\"/g" \ + "$DIRNAME/AndroidManifest.xml" + +cp "$APP_ICON" "$DIRNAME/res/drawable/icon.png" +convert -scale 72x72 "$APP_ICON" "$DIRNAME/res/drawable-hdpi/icon.png" +convert -scale 48x48 "$APP_ICON" "$DIRNAME/res/drawable-mdpi/icon.png" +convert -scale 96x96 "$APP_ICON" "$DIRNAME/res/drawable-xhdpi/icon.png" +convert -scale 144x144 "$APP_ICON" "$DIRNAME/res/drawable-xxhdpi/icon.png" if [ "$BUILD_TOOL" = "gradle" ]; then diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png deleted file mode 100644 index 33de3e8038eefec0c3eb61f79892497c080e8025..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5874 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 BTLAz7 diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png deleted file mode 100644 index 0a8f484e6bf35f468b4eab2f8834c8d31f5d2779..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3208 zcmV;340rR1P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru;0p*7Ga=5F zz?%R73wKFGK~!ko?U;X%RMnNoKj*&pdU{^}nqLev42beWg$YC^f*`U?2#85EnA&A^ z&6@a!302~n+D&C6l`XZbY+S68{Uepinvktp-3nO*$%dfDRjP2;xPn<`BSIU)kHCz~ z&z>Ls>vi{g_wFCB8)gYHVFMcV?+?Dm$|Z)!{`Mg{J3Fr;%#TYB!2Wduv+ANOykR-2r-w>VK^sHFz@Q265VSEA z3=H^XDQRO@K`(ccrpa$AazKI}UE!*8Iy;Cy5$E!I;QQ%bwPUApr!?Xp2gCI*5EflbQc!snq=V zmmKc6#Rdee!!?T~#gF&imcRDUu`%z&iCt%d;H&rL^M&7q2dpD_ba@{u)8y2&!%-4Oe`d z|JwPTY`&#sfBBtX48K|ll0XqKml}Y2Ne9m1Qt5$d75^Ib@=JBjn{QgEWi08#lhLwSF1M zU9uRuKm>4snZPwbC$I?Ujz*(jyJ^);!F5Zn`zA0Cm<7!KEnr~lfD5g;S$iQ`VC_ZM~)o%$SbeB zLN1r1tE)>a%VK1B(}2x zBoe{%yxL!dFbwVUUw=C+?={N?uDInBAK&$#KY8ss&+}-V-fCj87(oz-@B6I3=>~T1 zdy&E6^B|N`w6wJFhA7ty=BW59gD>-Z1^-Gt={?Dx2BB6DWxWZ7zA414+xv{t?;)*XC+qSWl;^VeW zcRWrR*f}x5i@6*XW2O<(?9Qskr?m4H&>V?Gnmal=E{c4nZSzE18>?fnx{Bi{M8wgW zby{;v%b#|3cD9~6b&3nTAP+P)(&0EDVH4*B0TJJ)4%nkL0dVTn zDORuUrlT#6_TB~ovEmqGuq=x?bLOyh>)-L=dE>O!y~K*oSTrs7vHXBzBQ|3`tc}Gu zQ!XDI3xWf{lsdk1t%O@&KbB6XFEkz-xXN)5KpTS+q3F6qOC=h#W{C(tRfe@oGk8D0 zjZqEgJV*pP-bJK&BP2JlbipX8$U6+CALFh&Y@{0I$(5R`aygEDJI2s!!oy8XtG_ii z7Jc3G@`U*(yazMc)j_}Bb-nblV;2QbXUw@w7C?*0Xj7AkXS4jpH8A_H71vy8VRQks zgpp}{{Om#e>_PelA7sWfpD*5}+4fHrRxNfYj|<+AqHxxtJYMwzRkXbg^}@Qo%~C~~5Z=j){s%5m;fN}+=ms_e-vxr&paNz9e+B&IMcgH~M9_NSoJh>nsXN=^GF?nMsny`7gJ(1v# zlZonNgE3$!g{gWE5io|HVv&~%1-{(eOkfP6s?C5g{BtHF`-(-gY}qpE>+9vffdl3O z0085Jls^cVS~FKybC5L}K}d4I9+4i{wcS?R2HM7EmIXs@C4FtG_FyaBJZq z0!kqwn2;c3Ni@p5;bEfbv|L%KaD{D4QYlKtP(1(Mw}77jevO5Sg!eaNz$?|?DphrW zMag8++;h)8JpcUjOiWB%lo8I9N;r`S6~GvS)*4YNEH)wp#$W-W6qX3S?_)U*K@ebB z7HEx#5Uo^DqodpyjiT!6LN95}8Lj!(d|v*&RMNV76qxLRGB81St2PJ>1EW9zXc3XS zPM$nzoj!dU-~Zo5(iLHCEXF4j3F46mMr$mQu+=pNEDNjZC1VUCf@qDdfq4p&4zGH>4eeaDagB3@$#2h1$X z;*VUHkGd{#tx-yWG3aX28m*}q1CA5MyHeq9L%7?3)*9Qg!iL)S1!If^0m>K=t&P-f z2aGYwROvu#(}!&QyjR>~PXT~7#uRPa8q-?G31i*-eJn=Q2`j!;^@wPV(HdJRf@(Ne z)m>KA93TinuNZ?E6Xu9WsBkVHYASVgM5a&2ojaHK)mIanKcB?aSCc<_EXC&goGAeS zis^LvB;i>ZnKn%pKl-TY-MW>^;9wXM)fiVIm>@tA(uY;0Pio;*O>QC)EZ4@Gr)s@n@Xifr_)F_%gKix!aH>e<+`Z)dMww)s;@^}7t3`~@i=xeiQUkE-PnlJ z)P$W%VWm=7t_!wJrBd+=g+e(yF_F(?GGoKTBNKgny(7nuA0K|}t)m0S(#Hme1_wut zG1+QfzDvlKV^aYjgf-$rz$##YQmVXV%a$3NHf>tf(9jUCR4V5ZvQnv3eBY;7D0t;^ zImqYpg;KffXD24I*=)`mA0ID{WJYoW{rwYt@4h?H*V{YZ+uJujI-1FPo|iYqMg z7-Ishb!F0v%GKwZ0UqZMPPOOqB;zWCb;;-ap$ab2)V<&1o0_EcKm*}D64e(@MK3%` zn)fnrD&g@#05UK!HZ3tREigD#GB7$dF*-0eD=;xSFfhyhdn5n=03~!qSaf7zbY(hiZ)9m^ uc>ppnF*YqQIV~|aR4_3*F*!OlGAl4LIxsLuvguI(0000?iqPzcH=bF74WdBumJ!7o|2-R_OmwoZ(+T7K5yjuf}a(-t&Exs z08p2Lb8n9Ee9d5~sI3M7e0l=_ghm1Yx6h`~zW{(YF97h*3;+<#1pvt1Agx;B&o^FJ zs3^z*p8h*ZI=*B)TVA>;8h8Q#I3)iq6hJ{nm96RgYC6 ziQ|lQtQ5(=&`B~<W~8KZzI3x?|-PQDMu9%dnNZ3!|!kS9ibY z-(TET5~X+lTvJ{3{MY{J;@^zN)m=vuwvB!E|0}zCvZv~%-7+TS01-3%H8eppirAIi zgu5$MRJ#(iYno#nGeQb9AG9k}TR!d*1JTION&=4^-EX=(dx%klQRSsOrpX_UqQr@# zi?Gh?TnEH1$$qLycUKbz+iSCo9=+&9P&;-OoQS-D$Xf_D$oeH@Vl1?D_e*C*kcVOf zV>PCt@0u3m9=lAD$#1-i?^aNZoHVln=4>`jt8b3-kF#KfZxJZFU(VZlPARdLW`5%N z9&gHz(q6y@Xbs&|;wy?CaD*Mq=$Sf)+)fuS_ zc*Yv6k(Ct6VRez6yVQkpZI2pH5dD%W3OpTJ@>z6t`tv>P?yxOoJovJK6dNNO_;Gk` zjUh$il0taJkGTk0$i*a|F8%1z()2LZw#~$kaxERa<6Y=6%$}H%;<=e5>~Z!>xWRi- zC~)br6*>UfK;L*$q?zk?#`_kZtIvm!_qVs8P%4jORzeW5kn|3Ho zfvfy+Yy9h+;|5M5bp+Y5{KP;>rcIx`F6^gh%p^8m`6lU#%{UCvVuRrfI(&!W&IUMlc4G{ zIC_?{oFuCq-UfQ#Iw86na1vVMgBVia>RSJa5%ct=&bC-^SZ}(e1^M@<8Hi6Bywu;3eReeWTIsUVlMS+y?%57)@-FrvSCnA=q< zT-~CH7>*<$dv35TC57|m&_ULi)cu&LPx5L2kC;oxg`4TOglx8XpK_pyo3r)5ta#5$ z>8pDe;?NIkMrqdELXQc9{+gTh>p zl-(96lF!7MA|Y6QbYm0{Vn`j1iVE9sN=w}b7*yB9RROTPFacjP(gi{7ji^>jl% zgxz5zF>}EvJ@GueE;U=^)Iym#TptbTU(G|Szk#(f3L7yweXmvJ*!^zI!QmAEpV>+l1iEjE?Qm3pPih?Xpi#ITXDbK_U`4e0*c zU8cqyh|^8_rY3i>tjwMiD{l0SewTPjY7%hZeoKkWDDV|ALCXJ*IfTyo;s6&gfbVoU zd)ima-L7-&&XfZ;gr(MNns5Idk$bkVUaG3&>mx5yyXVSTD6{>)-Q95$G@{@L zcolD9axTJ~21WNQ3xU=8r3)Vl*?Ki3D~D?j()CF<-TgfJ^WTFAMSh4jBjTImLGadw zyZA_;gkCD&U*9n6dDk=KII=W`&SHBw3ydVx0#nB)#6Sdf%I;lQO{mis)Ivg}$W8pr zpKdSqx*&YP=oHFQBhnAcERkp}3@R4&-e~Y*g>|7ax7g1XGws*y#~Wt`w-lcjIb{fG z=4NKLkrF|DfBxue7IAguulU(K*4U#=gncnWpZ#s=>6f9&MwZ~^jnBYm)_x2vc zPU=kNhkHpB4!Os}#T?J|sIBDL2{^e67Z;Er9fjT+Jl9-|_Ocs_`z^ik$-*qWk0amn zqB@>CRe!`zvUs&||Eo1;mUgQ#u-4>h=@v5yq$90Z7DO3ATaseT>-)Ijf1oD;w?`V7 zd7a6hpPx@mPM$>PurcASOB3hvv}_S~K3>!oH<Ocvj?tb0zu}yt1pBi0G7;nD zv-GUQOk1-(&?rUepiLOgwUT?)63Jo8eE+J+CN3l(aBkfC#Kv265Hed;ZlrGN|NH4? z(z8H4|LgC3Ml2#C$%{%2_Z5F6Bh#;hSj9K@PDm&BC|Q}?ySwc;)*^j;2=+Z&$Dwc5 zWp9tUjKN%`0ic|HS|OB(i1NKM9y|0BzwRoe*B!xJ?R6Ra6DA0u4e{Eh`TKVMu1KhU+^{ zAL!78+@DZ7Jp`}Gq(7dt;WLZsvoY~6=JlvF&i+e;+oCToFYCSkHba0*fETdXMrvgJvmulBgP1pOZU-zQT6H4(_&qo6HK@Tj}3#M$a$qN=d zGal6WFh8FYP{DZfn`AaRq@SlfQQ0wqrEE^27Fv?#Ku=6+^*V z6G38k9>J2z{?b5SNk~XQJjX=N5BImjFzJqkoEQ3P=6oin7G#Z#7Sp37aBAu4=x)#U zTpssGOp7LvW4r9N4?{W{M|VHPQ$~Poi5VIOZ}s%ZWe6FV5|fhL_h3z@S0PVV#vVhj z10TY>|?AC+vT*?nS?_3&ZaR~_cC56<1Ic;T@V@tN}vUkNbCiUlkWUo<4wofHB+zwli z9?RY#-}SH!fjKv)IbEa6zN>1!zQV$*f&2#t2eFE1*@Q$z{yUT}Uc6ZSyMRn@l;EDG zoELkCIUIg@)x{)>7|udG4LG)$h;2q)@C+VL@V5CL?L0fR+1bu7IW0LSi^f?yjfA?2 zlFZw_9b5Y1fU!Fb>on8N7!C2E3fLllsnFNjT8-f22>S1yNOieL3>>m!y^ssNrQo{* zU5;0jl$7RkH6J}@4Q#cz$f!p{*1|BGck&%saQD2tyfka)u9S7ciczG@i|u!7JEbl@ z@S!qR>Mw>K;_$Q{a}MMt&;^}qap=4fAGch&_a7}3%P|Jd4eBR?h!J%SvldC_hvEH8 z$Ga-m|AagH$BX=dVl@TsbeKv)UiT-6>BYs7e>2}&PKPkxFFd$X{NSDYW3yYAY$ zEZ2WV1)deGZdDYxczpW+OD}L~jr;LKNb+_vWom9N=VcGd92x-%a|w5D;vRkGG%NYfX<`osRai^Bg1NBfFyo(0~pyS zf)sG;oyqYSdAb)`^tn9L15kQ3SxV~A(s7v(!GpPZa@?mVJJ20RAH%P}iS z_3QlPtaUQCv$Cq?zwOkZLGUlX^QbFQ0OpjN)K1UMA<9!El}V$VmYUP>sD%J#iR&>^ z_lzAK9siNfSgbi?PrRlj4;*(I9Jf=H$mO?umgjBVT_-|_m-FL37%Ql;5ncsof&}~F zx&VyS-X7TLy%`j_OH#&5YMIE)-q=Y{t?^VKw*S2sSSaRtnD+4SkcgX7;tshevh=&o z!!rQ9>i+0G^S=6HTXqb6u)ay~jkU0VfE-lY-b$KNuSSmj_2Lib=LlxcQg*pITux%Z z1w%9KV4wlF1Nhu&KTmKPLD1i~c#IuA4`WuRz_q5(;;v=cTz|%Sub=c80E5k4zIUjC z`>yKzM(;wUFlqpju=UpI)}6=e+s$O}kotYaJJ#jp%V>u0NE)FdZ$!(@PJuJ*LxUD+ zi${wSCMM?oSfSX#Koa%Aa26-GnZ&rKp0RsW&@=5{ZuQ>V&lhy0LJ$#c-gRQ^Q`$nz zeUDb0zf@H0$Bc`O)9w2Eya(DM?VT^ej(Sk9GOSd)(y?3Tn^x16AEe2_XH7d77qBv* zWRw2w`Kp(<#2rt+#XZ_;Qwn<6!<_NhBU^D3`Hp9;*qC0|?R%q2T_=j@8k5>Zr?|4g z8l$E$A0MBE{~XDCZ+5<}4kQc$nfo3t*=tBWobQ9*IXd%nUR$&|&eaS&h1{Kv93UdP zgKNJaR+gtNpIX}%O%^B3^^hJv*fv(yI%U_Kh)YhKmD1`d73!5Gb-u3OPEN30V;*PTzInP<<5cD*Rza2?0= z8nyU-i*@(#(B?S;Bh3eQeicv;{+(2y|JBra!L1C{-h482j4sEj{m{F8HhLyLb{;gw zMn)NLc~}V9vV~J!bXcYk1QPn??`B@4ww9>^IIM#?zf&FadDRUy(Ve4=b7X6o8mWH8T$)xobj{k zKM2VI$J&m8Lf@64%Y#M#iy1uwxWlVd^c@GNEXLsbZ-0&PIm5v*m*P8|{qnT5TvaoE zeje!(?&Z=x-FGsbD8LQpSd2VCeO7+6LilGva_otqR6Z_}NHq4}4s3*w-Z)Ltbt1<~RZbbc^&j4x zy}iu!HovHpF?w``iPi2Y_)m14#A8nv<#&nGeFF0_w(cZVvS}Ef&NZ$k=Gw9dibWMw zF4SF`UjVP2i+@tdpMcdy;^IZfIYj4VJD1}NPlvLi5V)D>WQ;V~BXO7{9p={|o4fyR zQZI?}In6N@Z37&OLD4HKCJyigNzSPtTB|ywpnz7KS#|&PC(%>~wHDnnXODE%q{Xlq zCh;XNe4<<_Rwk;}g1MsLxQ#Mwp+G!a$K6%ZjbA;Sg|fUyo7c3q%q#8D7NSVMqe{eS zDSYH+j=rP2oWNzrk{&xY$!x=_X+WS5tEK;E+3JsTW4@ufMFGb{Zod1#Q2hwLfsZS* zvn_Ian~yeLUVDpLan@udO7|gq_cv!LL}^z?D;-9|+x5R4;L$#vC`xqKN!er`hO9#Q zhGFXW3YI<-TOMnWYxCTFR$0vB@1Ee)OS0xiU-8aIQ;+*u{~|9k%(@c_a71j`I);;) zQxMMN@zv)} z>Ph?Yn`|^aPRT#FfoC$vbKXv}ka?Sf{CA;cQv7o0oXK@T-kNNJO)m4&7>JddoBPL> zs+k8nv>nb6?vAg4p2_5cj{zpi^lS!KEG#H*-8HJIhQc8wq+gI+h!9=(2Uaw)Q9TN@ zI;8=^45NH^4SOk*W49CD^pApgI-LHvq3%w zB1JhMn6sHe6>o!2j#*avm7X5Da$jHFNCMYK=sA?C(}obQ@e4HZjlJ(}rBAi$9QW~f zclMjdXHtR3NMU)29!4*M4399E+@05@DbIDGQmMKbGlXdW@hV8NEDJ2sf(_|8X5Ldh zZK~vpu-dzsQGK*s$0OktKC3~8a)nXJ$VGq~iEAF4$ICTh0{2#8r&CUNUoq0?{eBm@ zkXqKdSpF;~&3JLIC%e zYo_xW4{M;0%Ld&uRaryLx`{gdl5AC|o92p5APQLBtPnPL9a$Y2Om`zbQN|#Fq_k*! z^Wxg8P<&=W5rU>78p#Pp8@43+byBnp zEJU$6$@=zjy;WSHMO=uO2HO%(`K94YWrjww*CNIYq{G&kSOtmeV}?myCgtztK8PXt zUI>??=T$XVT=a$pC~8JM{Ss(wAh#B~V|jmECR^87)d4$5etcX$P-C5^XJHI&`+e2Y z4vlhHC_F9f9ROM2vY-+YKpH+kJn>2j}obg*AD)xnk8 zx<#y${TbEPE67FCf zd5#hn0WGHJ?RQTkN62+&^M0n0S2a+XH+)lQiJg8Sa8V6b_$5-c$CxfBFKNtmGL)Rm za%t7CH%y^YU)5KdS<+}Wy$Zn^(AUI=>S~vWAYQi6D14&Z>rFjyA5D{)U?VK_9C|7c zVUz99w|Yx@Vgdem{R0kn9|a*axybzY>kw2?8z_p}{hd);lZy@{wO7OdfnQ;w$Y{mz z5t(ThM}NlT?GE$5ht;}%)h4de@tE?v$$J&UjRE-y3k$rvgk%8a*C#C2>2*KSPKEYO z_T(tW)W#*^kJq*1x@hT4eD~Z#+2S*$^AVMU&$D$tI}jB z1{pf`wM4Ef3+DU=c(L{8^_MvjynT_>BZ_#XXWSG2iqmQ&o7-un-Qd#Q)wQuk@eRD# z>K#|Eh*^OO2CwYtgcsRC!G*x4GXzL91hMs>Sh)S*c!uA16%@FtQMDn=2$(|Kk>83m z#xK}V0O#zS2-v*s7a3Yh+Anjmpp?zPIm;~LhqY(T2FMTZgYg)JX-7!XuE?>^qZ!-w zygw8N@)dgS3>K9#20#ARaeW7v$DO*GT6DCMUrD5OV3DyzzZUvlX!T*W0+X6KkI0+l zubJRO2rXfOfM+mk@i^vlU+neVqnuA`(Cc!8GEA`ELg0#|VcLK9E2&`av*Fq=`3uYr z*(Pluo_5gs&-S+gqNQmDDm$};GGAPN$!yGOqi_(_6o}=RTe2;Arr?U-vYm0fTFDvb zx5H%~;59$!QT2nT3ixmclve#hFUTMZFT;}Jfm4A`J`D6@-0 zV|7Y7(pX&d6Y9tg{Bywrt?w8#1}sA9Ruu*ih18Vm;I+OM&qDraEDFKs94^hr zi?dcAoh4tX)j|{LXPhPdhOANCpK!{(x9pZ36$dA{C{}LHtV*JLt*x#4Z9d#GgcGx~ zm)Yo=-pLZ?gG(7R|510Y0amTLQ2MDPnkau=4 z5}dP#cgv}yvDy0Qrj>nJP*h=a@WCvE`Fr*@6V3F(@arhl)q?!=7zg+|@46O=PiE%K zU8`>fUt>15Rh4}uuf(RQN>rAFhLEXakW7ckRhD-9`IO3YDC7+dDS-zWxTKqAAs@Mh z?O`y#ehX&XX?s>YOF7p3V)3t~>FS=*Xm+Wih7fp?O^gmUs3J|PU+dI3Ok0^sa`lW@ z_*Hc5Y+0sqBp%qYj%kBE%3D1X4n`g~l95C!9kC>nTytmpF`I1)YU#itf%NZ*uu+CD^1z($2!>u9=F`4MWKd(e;buH8?E9x%sOO44C#OMV6t0lPd8s ziL(zSGpVNV3n=LuS{faDvnxevHLXbHwRvfC-pY+}lsrcX46zgJ@~Pby=X;D}1F zw16H@%Z_~h5ay|vAI>5D&l{EKURTDesw2InB{L7Kz}O;|y7l@c9$RnjXO8hp=dx-Z zCUz#Sp*m04FwkA- z33P;^Duzq6RD?ymI29@<0CuLVE+|jTY-7jJ1EJ-~WnSl#d__E4EgM(ZpXK*UKYdht z6YA#V9+R6&F^5*k= z@haJ=rj1x#j6dcs>0ggaFH)!g2NpPk*f ze#ldIUvi{r88E zSAbZs9(k~W!l{U>$`pZDE`b(hd?Fx& z#X8HoiHQl#mZm1x>s{L-xyscv<-GG4k8+h${BGG#;(OM|R(Dnp3cNq@G z7Zs=+T7tY+UF_D`Us)NJVqXp{IS-L9r#I2jHnpSn*PaEUg`=**fs(Px6pk>syVFwYwn+anO%9c%7)PGXP`fmj9#nm+5v_y4V1KKfyL$&H z++AuXxaa2*-KUQREqFrkh7u!3zH7uZ%o53)(;(`;&F$GZI5==5GEx4erznI#s*@6v zqs4x>QdjGK^V!Sh?%h7s{oUq?l%t4RzrOa9NGuzq$^d~~rv4@lT~O}LU+p~9KiMJ% zv)|SJ(@dVXcI`M|>WL()KxMBW+kmRL4d)AbKJDdno`+p^90hS=M}?EiPnx8>h8o6! z24?pz@*A@MP;C5Z_GmGtr>CYB9w0=3n3>D7(k9dDz{ww>hD~C=PV_ap6+b ze1^3%YAxcF2lEYI{y`cBa&c3}Dbj*c^0RH;j2RQy?k|om<*}WN&T;i7Zf!lMvVc$Z zic^>es#5#{@4v`$q={3^ecFg)^$GdAM8Na1S6@Rl5n*I9FW?08p4BHuM4!Z+d~fna zW~x!`%!=3+de6T8y3t8TY`;1YmX3Sff8h18@ z@KCR**0`H_u_$F0yr(?WVc>NV#lJsyJGM3BR#Rb;t9J9N2|o)c+clDcIdKET*w7dX z5Ub|5><}iU31G!)!5!Y6#dQyt4gD&u>*#2nYM}wg#QB4Bx#{*dqkQV$bOA;Rv#x&M za8#L_Fh@q4vg%y3*^kf##}|c#YYU`oYmW8;ejNOg92Zh)5cq%PNow*5Et&1F!Ad{c ze}A65_LA54vNHFw7Pa)SepUcJUXTzs2*k|`*5%_B6$FV23Ul&;M0t55=)9%>55U>g s%HGERe*wHA+#q4y=jT8oqJn&!ynN39#rj>XX8=G+UR|z6)-3#g0NEd)u>b%7 diff --git a/android/res/drawable-xxhdpi/icon.png b/android/res/drawable-xxhdpi/icon.png deleted file mode 100644 index 7bbbc461b34df09cad5a35b2191714ae6cbe80ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17129 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 diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml deleted file mode 100644 index 931a3c2c9c4..00000000000 --- a/android/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - SuperTuxKart - From c35599f3e257bb3749e89e2e329596ae79869171 Mon Sep 17 00:00:00 2001 From: Ben Krajancic Date: Sat, 23 Dec 2017 11:06:24 +1100 Subject: [PATCH 41/43] Flashing bubble gum (#3080) * Initial Implementation * Name values to give meaning --- src/items/attachment.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index b4b1dfd9f80..dbaeaf35550 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -497,6 +497,28 @@ void Attachment::update(float dt) bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD); float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f; + int slow_flashes = 3; + if (is_shield & m_time_left < slow_flashes) + { + int flashes_per_second = 4; + int divisor = 2; + + float fast_flashes = 0.5F; + if (m_time_left < fast_flashes) + { + flashes_per_second = 12; + } + + float mod = (int)(m_time_left * flashes_per_second * 2) % divisor; + if (mod < divisor / 2) + { + m_node->setVisible(false); + } + else + { + m_node->setVisible(true); + } + } if (m_node_scale < m_wanted_node_scale) { From 87d43063ed0b2a0a032b1cf690aa1d2df30fec01 Mon Sep 17 00:00:00 2001 From: Deve Date: Mon, 25 Dec 2017 23:59:49 +0100 Subject: [PATCH 42/43] Assume that "HandleSRGB == false" means "don't care". It solves the issue with nvidia when HandleSRGB is set to false. --- lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp index 5ee1d365ece..1c57e0a1987 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp @@ -694,6 +694,12 @@ bool CIrrDeviceLinux::createWindow() visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; } + + if (CreationParams.HandleSRGB == false) + { + visualAttrBuffer[21] = GLX_DONT_CARE; + } + // first round with unchanged values { configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); From 7c10a5559d3967c0ec19c274b16a18c74316a1f4 Mon Sep 17 00:00:00 2001 From: Ben Krajancic Date: Thu, 28 Dec 2017 13:08:34 +1100 Subject: [PATCH 43/43] Ghost replay selection fix (#3081) * Label unknown replay makers as "Unknown" * Language neutral result --- src/states_screens/ghost_replay_selection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/ghost_replay_selection.cpp b/src/states_screens/ghost_replay_selection.cpp index c5e90191b7a..3205ce9182d 100644 --- a/src/states_screens/ghost_replay_selection.cpp +++ b/src/states_screens/ghost_replay_selection.cpp @@ -128,7 +128,7 @@ void GhostReplaySelection::loadList() row.push_back(GUIEngine::ListWidget::ListCell (StringUtils::toWString(rd.m_min_time) + L"s", -1, 1, true)); row.push_back(GUIEngine::ListWidget::ListCell - (rd.m_user_name, -1, 1, true)); + (rd.m_user_name.empty() ? " " : rd.m_user_name, -1, 1, true)); m_replay_list_widget->addItem(StringUtils::toString(i), row); } } // loadList