diff --git a/CMakeLists.txt b/CMakeLists.txt index 63f1ace6..94c3a574 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,9 +192,9 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(DEBUG_CXX_FLAGS "/MTd /ZI") else(MSVC_STATIC) set(RELEASE_CXX_FLAGS "/MD /Ox") - set(DEBUG_CXX_FLAGS "/MDd /ZI") + set(DEBUG_CXX_FLAGS "/MDd /Od /ZI") endif() - set(TEST_CXX_FLAGS "") + set(TEST_CXX_FLAGS "${DEBUG_CXX_FLAGS}") add_definitions(-DNOEXCEPT= -DHAS_MSVC_EXCEPTION_BUG) # Needed for Debug information (it's set to "No" by default for some reason) diff --git a/po/colobot.pot b/po/colobot.pot index a6b61ea3..53bfda71 100644 --- a/po/colobot.pot +++ b/po/colobot.pot @@ -84,6 +84,9 @@ msgstr "" msgid "Load a saved mission" msgstr "" +msgid "Mods" +msgstr "" + msgid "Chapters:" msgstr "" @@ -120,10 +123,19 @@ msgstr "" msgid "2) Then press the key you want to use instead." msgstr "" -msgid "Unloaded Mods:" +msgid "Mods:" msgstr "" -msgid "Loaded Mods:" +msgid "Information:" +msgstr "" + +msgid "Description:" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + +msgid "Disable\\Disable the selected mod" msgstr "" msgid "Face type:" @@ -186,6 +198,9 @@ msgstr "" msgid "The address %s could not be opened in a web browser." msgstr "" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "Keyword help(\\key cbot;)" msgstr "" @@ -336,6 +351,9 @@ msgstr "" msgid "SatCom" msgstr "" +msgid "Mods\\Mod manager" +msgstr "" + msgid "Change player\\Change player" msgstr "" @@ -363,16 +381,22 @@ msgstr "" msgid "Play\\Start mission!" msgstr "" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" -msgid "Load\\Load Mod" +msgid "Apply\\Apply the current mod configuration" msgstr "" -msgid "Unload\\Unload Mod" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + +msgid "Refresh\\Refresh the list of currently installed mods" msgstr "" msgid "Device\\Driver and resolution settings" @@ -390,9 +414,6 @@ msgstr "" msgid "Sound\\Music and game sound volume" msgstr "" -msgid "Mods\\Manage installed mods" -msgstr "" - msgid "Unit" msgstr "" diff --git a/po/cs.po b/po/cs.po index 7fff13fe..532510ea 100644 --- a/po/cs.po +++ b/po/cs.po @@ -125,6 +125,9 @@ msgstr "Vzhled\\Upravte svůj vzhled" msgid "Apply changes\\Activates the changed settings" msgstr "Uložit změny\\Aktivovat změny nastavení" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Chybí vhodný konstruktor" @@ -479,6 +482,10 @@ msgstr "Vrtná věž" msgid "Descend\\Reduces the power of the jet" msgstr "Klesat\\Snížit tah tryskového motoru" +#, fuzzy +msgid "Description:" +msgstr "Rozlišení:" + msgid "Destroy" msgstr "Zbourat" @@ -491,6 +498,10 @@ msgstr "Drtič" msgid "Device\\Driver and resolution settings" msgstr "Obrazovka\\Nastavení grafické karty a rozlišení" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Smazat\\Smaže vybraný soubor" + msgid "Dividing by zero" msgstr "Dělení nulou" @@ -507,6 +518,9 @@ msgstr "Dveře blokuje robot nebo jiný objekt" msgid "Down (\\key gdown;)" msgstr "Dolů (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Tužkobot" @@ -534,6 +548,10 @@ msgstr "Vejce" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Nahrát\\Nahraje vybranou misi" + msgid "End of block missing" msgstr "Chybí konec bloku" @@ -760,6 +778,9 @@ msgstr "Infikováno virem; dočasně mimo provoz" msgid "Information exchange post" msgstr "Komunikační stanice" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Příkaz \"break\" mimo cyklus" @@ -850,18 +871,12 @@ msgstr "Seznam uložených misí" msgid "Load a saved mission" msgstr "Nahrát uloženou misi" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Nahrát\\Nahrát uloženou misi" msgid "Load\\Loads the selected mission" msgstr "Nahrát\\Nahraje vybranou misi" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Načítám základní nastavení mapy" @@ -916,7 +931,13 @@ msgstr "Mise na této planetě:" msgid "Missions\\Select mission" msgstr "Mise\\Vyberte misi" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1087,7 +1108,7 @@ msgstr "Otevřít" msgid "Open (Ctrl+O)" msgstr "Otevřít (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1300,6 +1321,9 @@ msgstr "Červená vlajka" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Odlesky na tlačítkách\\Blyštivá tlačítka" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Pozůstatky mise Apollo" @@ -1584,6 +1608,9 @@ msgstr "" msgid "The types of the two operands are incompatible" msgstr "Operaci nelze provést s operandy těchto dvou typů" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Tato třída již existuje" @@ -1717,15 +1744,12 @@ msgstr "Neznámá zástupná sekvence" msgid "Unknown function" msgstr "Neznámá funkce" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Vzhůru (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Uranové ložisko (místo pro vrtnou věž)" @@ -1798,7 +1822,7 @@ msgstr "Létající detektor" msgid "Withdraw shield (\\key action;)" msgstr "Vypnout štít (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -1956,3 +1980,7 @@ msgstr "colobot.info" msgid "epsitec.com" msgstr "epsitec.com" + +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Žádné uživatelské mapy nejsou nainstalovány!" diff --git a/po/de.po b/po/de.po index 702bab19..15f4c336 100644 --- a/po/de.po +++ b/po/de.po @@ -126,6 +126,9 @@ msgstr "Aussehen\\Erscheinungsbild des Astronauten einstellen" msgid "Apply changes\\Activates the changed settings" msgstr "Änderungen anwenden\\Getätigte Einstellungen anwenden" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Es gibt keinen geeigneten Konstruktor" @@ -480,6 +483,10 @@ msgstr "Bohrturm" msgid "Descend\\Reduces the power of the jet" msgstr "Sinken\\Leistung des Triebwerks drosseln" +#, fuzzy +msgid "Description:" +msgstr "Auflösung:" + msgid "Destroy" msgstr "Zerstören" @@ -492,6 +499,10 @@ msgstr "Einstampfer" msgid "Device\\Driver and resolution settings" msgstr "Bildschirm\\Driver und Bildschirmauflösung" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Löschen\\Löscht die gespeicherte Mission" + msgid "Dividing by zero" msgstr "Division durch Null" @@ -508,6 +519,9 @@ msgstr "Die Türen werden von einem Gegenstand blockiert" msgid "Down (\\key gdown;)" msgstr "Sinkt (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Zeichner" @@ -535,6 +549,10 @@ msgstr "Ei" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Laden\\Öffnet eine gespeicherte Mission" + msgid "End of block missing" msgstr "Es fehlt eine geschlossene geschweifte Klammer \"}\" (Ende des Blocks)" @@ -762,6 +780,9 @@ msgstr "Von Virus infiziert, zeitweise außer Betrieb" msgid "Information exchange post" msgstr "Infoserver" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Anweisung \"break\" außerhalb einer Schleife" @@ -852,18 +873,12 @@ msgstr "Liste der gespeicherten Missionen" msgid "Load a saved mission" msgstr "Gespeicherte Mission laden" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Laden\\Eine gespeicherte Mission öffnen" msgid "Load\\Loads the selected mission" msgstr "Laden\\Öffnet eine gespeicherte Mission" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Lade Level-Grundeinstellungen" @@ -932,7 +947,13 @@ msgstr "Liste der Missionen des Planeten:" msgid "Missions\\Select mission" msgstr "Missionen\\Aufbruch ins Weltall" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1103,7 +1124,7 @@ msgstr "Öffnen" msgid "Open (Ctrl+O)" msgstr "Öffnen (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1317,6 +1338,9 @@ msgstr "Rote Fahne" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Glänzende Tasten\\Glänzende Tasten in den Menüs" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Überreste einer Apollo-Mission" @@ -1601,6 +1625,9 @@ msgstr "" msgid "The types of the two operands are incompatible" msgstr "Die zwei Operanden sind nicht kompatibel" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Diese Klasse gibt es schon" @@ -1734,15 +1761,12 @@ msgstr "" msgid "Unknown function" msgstr "Unbekannte Funktion" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Steigt (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Markierung für unterirdisches Platinvorkommen" @@ -1815,7 +1839,7 @@ msgstr "Schnüffler" msgid "Withdraw shield (\\key action;)" msgstr "Schutzschild einholen (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -2051,6 +2075,10 @@ msgstr "epsitec.com" #~ msgid "Mouse shadow\\Gives the mouse a shadow" #~ msgstr "Schatten unter der Maus\\Ein Schatten erscheint unter der Maus" +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Keine benutzerdefinierten Level vorhanden" + #~ msgid "No other robot" #~ msgstr "Kein anderer Roboter" diff --git a/po/fr.po b/po/fr.po index dcb5d42e..1b07f1fe 100644 --- a/po/fr.po +++ b/po/fr.po @@ -125,6 +125,9 @@ msgstr "Aspect\\Choisir votre aspect" msgid "Apply changes\\Activates the changed settings" msgstr "Appliquer les changements\\Active les changements effectués" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Constructeur approprié manquant" @@ -482,6 +485,10 @@ msgstr "Derrick" msgid "Descend\\Reduces the power of the jet" msgstr "Descendre\\Diminuer la puissance du réacteur" +#, fuzzy +msgid "Description:" +msgstr "Résolutions :" + msgid "Destroy" msgstr "Détruire" @@ -494,6 +501,10 @@ msgstr "Destructeur" msgid "Device\\Driver and resolution settings" msgstr "Affichage\\Pilote et résolution d'affichage" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Supprimer\\Supprime l'enregistrement sélectionné" + msgid "Dividing by zero" msgstr "Division par zéro" @@ -510,6 +521,9 @@ msgstr "Portes bloquées par un robot ou un objet" msgid "Down (\\key gdown;)" msgstr "Descend (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Robot dessinateur" @@ -537,6 +551,10 @@ msgstr "Oeuf" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Charger\\Charger la mission sélectionnée" + msgid "End of block missing" msgstr "Il manque la fin du bloc" @@ -764,6 +782,9 @@ msgstr "Infecté par un virus; ne fonctionne plus temporairement" msgid "Information exchange post" msgstr "Station relais" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Instruction \"break\" en dehors d'une boucle" @@ -854,18 +875,12 @@ msgstr "Liste des missions enregistrées" msgid "Load a saved mission" msgstr "Chargement d'une mission enregistrée" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Charger\\Charger une mission enregistrée" msgid "Load\\Loads the selected mission" msgstr "Charger\\Charger la mission sélectionnée" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Chargement des configurations de base du niveau" @@ -934,7 +949,13 @@ msgstr "Liste des missions du chapitre :" msgid "Missions\\Select mission" msgstr "Missions\\La grande aventure" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1105,7 +1126,7 @@ msgstr "Ouvrir" msgid "Open (Ctrl+O)" msgstr "Ouvrir (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1319,6 +1340,9 @@ msgstr "Drapeau rouge" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Reflets sur les boutons\\Boutons brillants" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Vestige d'une mission Apollo" @@ -1603,6 +1627,9 @@ msgstr "" msgid "The types of the two operands are incompatible" msgstr "Les deux opérandes ne sont pas de types compatibles" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Cette classe existe déjà" @@ -1736,15 +1763,12 @@ msgstr "Séquence d'échappement inconnue" msgid "Unknown function" msgstr "Routine inconnue" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Monte (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Emplacement pour un derrick (minerai d'uranium)" @@ -1817,7 +1841,7 @@ msgstr "Robot renifleur volant" msgid "Withdraw shield (\\key action;)" msgstr "Refermer le bouclier (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -2055,6 +2079,10 @@ msgstr "epsitec.com" #~ msgid "Mouse shadow\\Gives the mouse a shadow" #~ msgstr "Souris ombrée\\Jolie souris avec une ombre" +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Pas de niveaux spéciaux installés !" + #~ msgid "No other robot" #~ msgstr "Pas d'autre robot" diff --git a/po/pl.po b/po/pl.po index 9535ab56..251de7fe 100644 --- a/po/pl.po +++ b/po/pl.po @@ -124,6 +124,9 @@ msgstr "Wygląd\\Wybierz swoją postać" msgid "Apply changes\\Activates the changed settings" msgstr "Zastosuj zmiany\\Aktywuje zmienione ustawienia" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Brak odpowiedniego konstruktora" @@ -478,6 +481,10 @@ msgstr "Kopalnia" msgid "Descend\\Reduces the power of the jet" msgstr "W dół\\Zmniejsza moc silnika" +#, fuzzy +msgid "Description:" +msgstr "Rozdzielczość:" + msgid "Destroy" msgstr "Zniszcz" @@ -490,6 +497,10 @@ msgstr "Destroyer" msgid "Device\\Driver and resolution settings" msgstr "Urządzenie\\Ustawienia sterownika i rozdzielczości" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Usuń\\Usuwa zaznaczony plik" + msgid "Dividing by zero" msgstr "Dzielenie przez zero" @@ -506,6 +517,9 @@ msgstr "Drzwi zablokowane przez robota lub inny obiekt" msgid "Down (\\key gdown;)" msgstr "Dół (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Robot rysownik" @@ -533,6 +547,10 @@ msgstr "Jajo" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Wczytaj\\Wczytuje zaznaczoną misję" + msgid "End of block missing" msgstr "Brak końca bloku" @@ -759,6 +777,9 @@ msgstr "Zainfekowane wirusem, chwilowo niesprawne" msgid "Information exchange post" msgstr "Stacja przekaźnikowa informacji" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Polecenie \"break\" na zewnątrz pętli" @@ -849,18 +870,12 @@ msgstr "Lista zapisanych misji" msgid "Load a saved mission" msgstr "Wczytaj zapisaną misję" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Wczytaj\\Wczytuje zapisaną misję" msgid "Load\\Loads the selected mission" msgstr "Wczytaj\\Wczytuje zaznaczoną misję" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Wczytywanie ustawień poziomu" @@ -915,7 +930,13 @@ msgstr "Misje na tej planecie:" msgid "Missions\\Select mission" msgstr "Misje\\Wybierz misję" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1086,7 +1107,7 @@ msgstr "Otwórz" msgid "Open (Ctrl+O)" msgstr "Otwórz (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1299,6 +1320,9 @@ msgstr "Czerwona flaga" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Odbicia na przyciskach \\Świecące przyciski" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Pozostałości z misji Apollo" @@ -1583,6 +1607,9 @@ msgstr "Nie udało się otworzyć ścieżki %s w przeglądarce plików." msgid "The types of the two operands are incompatible" msgstr "Niezgodne typy operatorów" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Taka klasa już istnieje" @@ -1716,15 +1743,12 @@ msgstr "" msgid "Unknown function" msgstr "Funkcja nieznana" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Góra (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Złoże uranu (miejsce na kopalnię)" @@ -1797,7 +1821,7 @@ msgstr "Szperacz latający" msgid "Withdraw shield (\\key action;)" msgstr "Wyłącz osłonę (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -2034,6 +2058,10 @@ msgstr "epsitec.com" #~ msgid "Mouse shadow\\Gives the mouse a shadow" #~ msgstr "Cień kursora myszy\\Dodaje cień kursorowi myszy" +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Brak zainstalowanych poziomów użytkownika!" + #~ msgid "No other robot" #~ msgstr "Brak innego robota" diff --git a/po/pt.po b/po/pt.po index 159dd313..aed2d681 100644 --- a/po/pt.po +++ b/po/pt.po @@ -122,6 +122,9 @@ msgstr "Aparência\\Escolha sua aparência" msgid "Apply changes\\Activates the changed settings" msgstr "Aplicar mudanças\\Ativa as configurações alteradas" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Construtor apropriado faltando" @@ -477,6 +480,10 @@ msgstr "Extrator" msgid "Descend\\Reduces the power of the jet" msgstr "Descer\\Diminui o poder do jato" +#, fuzzy +msgid "Description:" +msgstr "Resolução:" + msgid "Destroy" msgstr "Destruir" @@ -489,6 +496,10 @@ msgstr "Destruidor" msgid "Device\\Driver and resolution settings" msgstr "Dispositivo\\Configurações de driver e resolução" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Excluir\\Exclui o arquivo selecionado" + msgid "Dividing by zero" msgstr "Dividindo por zero" @@ -505,6 +516,9 @@ msgstr "Portas bloqueadas por um robô ou outro objeto" msgid "Down (\\key gdown;)" msgstr "Baixo (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Robô cartoonista" @@ -532,6 +546,10 @@ msgstr "Ovo" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Carregar\\Carrega a missão selecionada" + msgid "End of block missing" msgstr "Fim do bloco ausente" @@ -759,6 +777,9 @@ msgstr "Infectado por vírus; temporariamento fora de serviço" msgid "Information exchange post" msgstr "Posto de troca de informação" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Intrução \"break\" fora de um laço" @@ -849,18 +870,12 @@ msgstr "Lista das missões salvas" msgid "Load a saved mission" msgstr "Carregar uma missão salva" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Carregar\\Carregar uma missão salva" msgid "Load\\Loads the selected mission" msgstr "Carregar\\Carrega a missão selecionada" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Carregando configurações de nível básico" @@ -929,7 +944,13 @@ msgstr "Lista de missões neste planeta:" msgid "Missions\\Select mission" msgstr "Missões\\Selecione uma missão" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1100,7 +1121,7 @@ msgstr "Abrir" msgid "Open (Ctrl+O)" msgstr "Abrir (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1314,6 +1335,9 @@ msgstr "Bandeira vermelha" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Reflexões nos botões\\Botões brilhantes" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Restos da missão Apollo" @@ -1598,6 +1622,9 @@ msgstr "" msgid "The types of the two operands are incompatible" msgstr "Os tipos dos dois operandos são incompativeis" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Esta classe já existe" @@ -1731,15 +1758,12 @@ msgstr "Sequência de escape desconhecidade" msgid "Unknown function" msgstr "Função desconhecida" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Cima (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Depósito de urânio (local para extrator)" @@ -1812,7 +1836,7 @@ msgstr "Farejador alado" msgid "Withdraw shield (\\key action;)" msgstr "Retirar escudo (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -2053,6 +2077,10 @@ msgstr "epsitec.com" #~ msgid "Mouse shadow\\Gives the mouse a shadow" #~ msgstr "Souris ombrée\\Jolie souris avec une ombre" +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Nenhum nível de usuário instalado!" + #~ msgid "No other robot" #~ msgstr "Pas d'autre robot" diff --git a/po/ru.po b/po/ru.po index 04d9187a..d450ccf4 100644 --- a/po/ru.po +++ b/po/ru.po @@ -124,6 +124,9 @@ msgstr "Внешность\\Настройка внешности" msgid "Apply changes\\Activates the changed settings" msgstr "Принять\\Принять изменения настроек" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Соответствующий конструктор отсутствует" @@ -486,6 +489,10 @@ msgstr "Космический корабль" msgid "Descend\\Reduces the power of the jet" msgstr "Снижение и посадка\\Понижение мощности реактивного двигателя" +#, fuzzy +msgid "Description:" +msgstr "Разрешение:" + msgid "Destroy" msgstr "Уничтожить" @@ -498,6 +505,10 @@ msgstr "Уничтожитель" msgid "Device\\Driver and resolution settings" msgstr "Устройство\\Драйвер и настройки разрешения" +#, fuzzy +msgid "Disable\\Disable the selected mod" +msgstr "Удалить\\Удаление выбранного файла" + msgid "Dividing by zero" msgstr "Деление на ноль (запрещено!)" @@ -514,6 +525,9 @@ msgstr "Двери заблокированы роботом или другим msgid "Down (\\key gdown;)" msgstr "Вниз (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Рисовальщик" @@ -541,6 +555,10 @@ msgstr "Яйцо" msgid "Empty character constant" msgstr "" +#, fuzzy +msgid "Enable\\Enable the selected mod" +msgstr "Загрузить\\Загрузить выбранную миссию" + msgid "End of block missing" msgstr "Отсутствует конец блока" @@ -768,6 +786,9 @@ msgstr "Заражено вирусом. Временно вышел из стр msgid "Information exchange post" msgstr "Пост обмена информацией" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Инструкция \"break\" вне цикла" @@ -858,18 +879,12 @@ msgstr "Список сохраненных миссий" msgid "Load a saved mission" msgstr "Загрузить" -msgid "Load\\Load Mod" -msgstr "" - msgid "Load\\Load a saved mission" msgstr "Загрузить\\Загрузить сохраненную миссию" msgid "Load\\Loads the selected mission" msgstr "Загрузить\\Загрузить выбранную миссию" -msgid "Loaded Mods:" -msgstr "" - msgid "Loading basic level settings" msgstr "Загрузка основных настроек уровня" @@ -938,7 +953,13 @@ msgstr "Миссии на этой планете:" msgid "Missions\\Select mission" msgstr "Миссии\\Выбор миссии" -msgid "Mods\\Manage installed mods" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" msgstr "" msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" @@ -1111,7 +1132,7 @@ msgstr "Открыть" msgid "Open (Ctrl+O)" msgstr "Открыть (Ctrl+O)" -msgid "Open Directory\\Open Mods directory" +msgid "Open Directory\\Open the mods directory" msgstr "" msgid "Opening brace missing" @@ -1326,6 +1347,9 @@ msgstr "Красный флаг" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Отражения на кнопках \\Блестящие кнопки" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Остатки миссии Аполлон" @@ -1614,6 +1638,9 @@ msgstr "" msgid "The types of the two operands are incompatible" msgstr "Типы операндов несовместимы" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Этот класс уже существует" @@ -1747,15 +1774,12 @@ msgstr "" msgid "Unknown function" msgstr "Неизвестная функция" -msgid "Unload\\Unload Mod" -msgstr "" - -msgid "Unloaded Mods:" -msgstr "" - msgid "Up (\\key gup;)" msgstr "Вверх (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Запасы урана (место для буровой вышки)" @@ -1828,7 +1852,7 @@ msgstr "Летающий искатель" msgid "Withdraw shield (\\key action;)" msgstr "Снять щит (\\key action;)" -msgid "Workshop\\Open Workshop to search Mods" +msgid "Workshop\\Open the workshop to search for mods" msgstr "" msgid "Worm" @@ -2063,6 +2087,10 @@ msgstr "epsitec.com" #~ msgid "Mouse shadow\\Gives the mouse a shadow" #~ msgstr "Тень мыши\\Мышь отбрасывает тень" +#, fuzzy +#~ msgid "No mods installed!" +#~ msgstr "Не установленны пользовательские уровни!" + #~ msgid "No other robot" #~ msgstr "Нет робота" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f70489ab..df752615 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -569,6 +569,8 @@ set(BASE_SOURCES ui/screen/screen_loading.h ui/screen/screen_main_menu.cpp ui/screen/screen_main_menu.h + ui/screen/screen_mod_list.cpp + ui/screen/screen_mod_list.h ui/screen/screen_player_select.cpp ui/screen/screen_player_select.h ui/screen/screen_quit.cpp @@ -583,8 +585,6 @@ set(BASE_SOURCES ui/screen/screen_setup_game.h ui/screen/screen_setup_graphics.cpp ui/screen/screen_setup_graphics.h - ui/screen/screen_setup_mods.cpp - ui/screen/screen_setup_mods.h ui/screen/screen_setup_sound.cpp ui/screen/screen_setup_sound.h ui/screen/screen_welcome.cpp diff --git a/src/app/modman.cpp b/src/app/modman.cpp index e2fb3468..cf552641 100644 --- a/src/app/modman.cpp +++ b/src/app/modman.cpp @@ -30,9 +30,10 @@ #include "common/resources/resourcemanager.h" #include -#include +#include #include #include +#include "modman.h" using namespace boost::filesystem; @@ -104,26 +105,40 @@ void CModManager::FindMods() } } -void CModManager::EnableMod(const std::string& modName) +void CModManager::EnableMod(size_t i) { - Mod* mod = FindMod(modName); - if (!mod) - { - GetLogger()->Error("Could not enable mod: %s not found\n", modName.c_str()); - return; - } - mod->enabled = true; + m_mods[i].enabled = true; } -void CModManager::DisableMod(const std::string& modName) +void CModManager::DisableMod(size_t i) { - Mod* mod = FindMod(modName); - if (!mod) + m_mods[i].enabled = false; +} + +size_t CModManager::MoveUp(size_t i) +{ + if (i != 0) { - GetLogger()->Error("Could not disable mod: %s not found\n", modName.c_str()); - return; + std::swap(m_mods[i - 1], m_mods[i]); + return i - 1; + } + else + { + return i; + } +} + +size_t CModManager::MoveDown(size_t i) +{ + if (i != m_mods.size() - 1) + { + std::swap(m_mods[i], m_mods[i + 1]); + return i + 1; + } + else + { + return i; } - mod->enabled = false; } void CModManager::UpdatePaths() @@ -158,19 +173,17 @@ void CModManager::SaveMods() GetConfigFile().Save(); } -boost::optional CModManager::GetMod(const std::string& modName) +size_t CModManager::CountMods() const { - Mod* mod = FindMod(modName); - return mod != nullptr ? *mod : boost::optional(); + return m_mods.size(); +} + +const Mod& CModManager::GetMod(size_t i) const +{ + return m_mods[i]; } const std::vector& CModManager::GetMods() const { return m_mods; } - -Mod* CModManager::FindMod(const std::string& modName) -{ - auto it = std::find_if(m_mods.begin(), m_mods.end(), [&](Mod& mod) { return mod.name == modName; }); - return it != m_mods.end() ? &(*it) : nullptr; -} diff --git a/src/app/modman.h b/src/app/modman.h index 5ce3efa2..984d54ea 100644 --- a/src/app/modman.h +++ b/src/app/modman.h @@ -37,11 +37,17 @@ struct Mod }; /** - * \class CApplication - * \brief Main application + * \class CModManager + * \brief This class handles the list of mods. * - * This class handles the list of currently loaded mods. - * The order matters since the order in which files are loaded matters. + * The order matters since the order in which files are loaded matters, + * because some files can be overwritten. + * + * The list can be kept in the config file with the \ref SaveMods function. + * + * The changes in the list do not immediately apply. + * Separate calls to \ref UpdatePaths and \ref ReloadResources, probably in this order, + * need to be done for the changes to apply. * */ class CModManager @@ -53,10 +59,16 @@ public: void FindMods(); //! Removes a mod from the list of loaded mods - void EnableMod(const std::string& modName); + void EnableMod(size_t i); //! Adds a mod to the list of loaded mods - void DisableMod(const std::string& modName); + void DisableMod(size_t i); + + //! Moves the selected mod up in the list so that it's loaded sooner than others, returns the new index + size_t MoveUp(size_t i); + + //! Moves the selected mod down in the list so that it's loaded later than others, returns the new index + size_t MoveDown(size_t i); //! Reloads application resources so the enabled mods are applied void ReloadResources(); @@ -67,11 +79,14 @@ public: //! Updates the paths in Path Manager according to the current mod configuration void UpdatePaths(); - boost::optional GetMod(const std::string& modName); - const std::vector& GetMods() const; + //! Number of mods loaded + size_t CountMods() const; -private: - Mod* FindMod(const std::string& modName); + //! Returns the reference to the mod in given position + const Mod& GetMod(size_t i) const; + + //! Returns the list of mods + const std::vector& GetMods() const; private: CApplication* m_app; diff --git a/src/common/event.cpp b/src/common/event.cpp index 3de67fc1..5bae84f2 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -190,6 +190,7 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_ABORT] = "EVENT_INTERFACE_ABORT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_USER] = "EVENT_INTERFACE_USER"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SATCOM] = "EVENT_INTERFACE_SATCOM"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS] = "EVENT_INTERFACE_MODS"; EVENT_TYPE_TEXT[EVENT_INTERFACE_CHAP] = "EVENT_INTERFACE_CHAP"; EVENT_TYPE_TEXT[EVENT_INTERFACE_LIST] = "EVENT_INTERFACE_LIST"; @@ -201,7 +202,6 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPp] = "EVENT_INTERFACE_SETUPp"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPc] = "EVENT_INTERFACE_SETUPc"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPs] = "EVENT_INTERFACE_SETUPs"; - EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPm] = "EVENT_INTERFACE_SETUPm"; EVENT_TYPE_TEXT[EVENT_INTERFACE_DEVICE] = "EVENT_INTERFACE_DEVICE"; EVENT_TYPE_TEXT[EVENT_INTERFACE_RESOL] = "EVENT_INTERFACE_RESOL"; @@ -273,12 +273,15 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT"; - EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_UNLOADED] = "EVENT_INTERFACE_MODS_UNLOADED"; - EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_LOADED] = "EVENT_INTERFACE_MODS_LOADED"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_LIST] = "EVENT_INTERFACE_MOD_LIST"; EVENT_TYPE_TEXT[EVENT_INTERFACE_WORKSHOP] = "EVENT_INTERFACE_WORKSHOP"; EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_DIR] = "EVENT_INTERFACE_MODS_DIR"; - EVENT_TYPE_TEXT[EVENT_INTERFACE_LOAD] = "EVENT_INTERFACE_LOAD"; - EVENT_TYPE_TEXT[EVENT_INTERFACE_UNLOAD] = "EVENT_INTERFACE_UNLOAD"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE] = "EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_APPLY] = "EVENT_INTERFACE_MODS_APPLY"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_DETAILS] = "EVENT_INTERFACE_MOD_DETAILS"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_MOVE_UP] = "EVENT_INTERFACE_MOD_MOVE_UP"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_MOVE_DOWN] = "EVENT_INTERFACE_MOD_MOVE_DOWN"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_REFRESH] = "EVENT_INTERFACE_MODS_REFRESH"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTl] = "EVENT_INTERFACE_GLINTl"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTr] = "EVENT_INTERFACE_GLINTr"; diff --git a/src/common/event.h b/src/common/event.h index 91d79439..d55c9664 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -225,6 +225,7 @@ enum EventType EVENT_INTERFACE_ABORT = 412, EVENT_INTERFACE_USER = 413, EVENT_INTERFACE_SATCOM = 414, + EVENT_INTERFACE_MODS = 416, EVENT_INTERFACE_CHAP = 420, EVENT_INTERFACE_LIST = 421, @@ -236,7 +237,6 @@ enum EventType EVENT_INTERFACE_SETUPp = 432, EVENT_INTERFACE_SETUPc = 433, EVENT_INTERFACE_SETUPs = 434, - EVENT_INTERFACE_SETUPm = 435, EVENT_INTERFACE_DEVICE = 440, EVENT_INTERFACE_RESOL = 441, @@ -312,12 +312,16 @@ enum EventType EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT = 573, EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT = 574, - EVENT_INTERFACE_MODS_UNLOADED = 580, - EVENT_INTERFACE_MODS_LOADED = 581, - EVENT_INTERFACE_WORKSHOP = 582, - EVENT_INTERFACE_MODS_DIR = 583, - EVENT_INTERFACE_LOAD = 584, - EVENT_INTERFACE_UNLOAD = 585, + EVENT_INTERFACE_MOD_LIST = 580, + EVENT_INTERFACE_WORKSHOP = 581, + EVENT_INTERFACE_MODS_DIR = 582, + EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE = 583, + EVENT_INTERFACE_MODS_APPLY = 584, + EVENT_INTERFACE_MOD_SUMMARY = 585, + EVENT_INTERFACE_MOD_DETAILS = 586, + EVENT_INTERFACE_MOD_MOVE_UP = 587, + EVENT_INTERFACE_MOD_MOVE_DOWN = 888, + EVENT_INTERFACE_MODS_REFRESH = 589, EVENT_INTERFACE_GLINTl = 590, EVENT_INTERFACE_GLINTr = 591, diff --git a/src/common/restext.cpp b/src/common/restext.cpp index 11270e46..664b8ac3 100644 --- a/src/common/restext.cpp +++ b/src/common/restext.cpp @@ -71,12 +71,13 @@ void InitializeRestext() stringsText[RT_TITLE_MISSION] = TR("Missions"); stringsText[RT_TITLE_FREE] = TR("Free game"); stringsText[RT_TITLE_USER] = TR("User levels"); - stringsText[RT_TITLE_CODE_BATTLES]=TR("Code battles"); + stringsText[RT_TITLE_CODE_BATTLES] = TR("Code battles"); stringsText[RT_TITLE_SETUP] = TR("Options"); stringsText[RT_TITLE_NAME] = TR("Player's name"); stringsText[RT_TITLE_PERSO] = TR("Customize your appearance"); stringsText[RT_TITLE_WRITE] = TR("Save the current mission"); stringsText[RT_TITLE_READ] = TR("Load a saved mission"); + stringsText[RT_TITLE_MODS] = TR("Mods"); stringsText[RT_PLAY_CHAP_CHAPTERS] = TR("Chapters:"); stringsText[RT_PLAY_CHAP_PLANETS] = TR("Planets:"); @@ -92,8 +93,11 @@ void InitializeRestext() stringsText[RT_SETUP_KEY1] = TR("1) First click on the key you want to redefine."); stringsText[RT_SETUP_KEY2] = TR("2) Then press the key you want to use instead."); - stringsText[RT_MODS_UNLOADED] = TR("Unloaded Mods:"); - stringsText[RT_MODS_LOADED] = TR("Loaded Mods:"); + stringsText[RT_MOD_LIST] = TR("Mods:"); + stringsText[RT_MOD_DETAILS] = TR("Information:"); + stringsText[RT_MOD_SUMMARY] = TR("Description:"); + stringsText[RT_MOD_ENABLE] = TR("Enable\\Enable the selected mod"); + stringsText[RT_MOD_DISABLE] = TR("Disable\\Disable the selected mod"); stringsText[RT_PERSO_FACE] = TR("Face type:"); stringsText[RT_PERSO_GLASSES] = TR("Eyeglasses:"); @@ -115,6 +119,7 @@ void InitializeRestext() stringsText[RT_DIALOG_OPEN_PATH_FAILED_TEXT] = TR("The path %s could not be opened in a file explorer."); stringsText[RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE] = TR("Could not open the web browser!"); stringsText[RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT] = TR("The address %s could not be opened in a web browser."); + stringsText[RT_DIALOG_CHANGES_QUESTION] = TR("There are unsaved changes. Do you want to save them before leaving?"); stringsText[RT_STUDIO_LISTTT] = TR("Keyword help(\\key cbot;)"); stringsText[RT_STUDIO_COMPOK] = TR("Compilation ok (0 errors)"); @@ -180,6 +185,7 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_CODE_BATTLES] = TR("Code battles\\Program your robot to be the best of them all!"); stringsEvent[EVENT_INTERFACE_USER] = TR("Custom levels\\Levels from mods created by the users"); stringsEvent[EVENT_INTERFACE_SATCOM] = TR("SatCom"); + stringsEvent[EVENT_INTERFACE_MODS] = TR("Mods\\Mod manager"); stringsEvent[EVENT_INTERFACE_NAME] = TR("Change player\\Change player"); stringsEvent[EVENT_INTERFACE_SETUP] = TR("Options\\Preferences"); stringsEvent[EVENT_INTERFACE_AGAIN] = TR("Restart\\Restart the mission from the beginning"); @@ -189,16 +195,17 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_QUIT] = TR("Quit\\Quit Colobot: Gold Edition"); stringsEvent[EVENT_INTERFACE_BACK] = TR("<< Back \\Back to the previous screen"); stringsEvent[EVENT_INTERFACE_PLAY] = TR("Play\\Start mission!"); - stringsEvent[EVENT_INTERFACE_WORKSHOP] = TR("Workshop\\Open Workshop to search Mods"); - stringsEvent[EVENT_INTERFACE_MODS_DIR] = TR("Open Directory\\Open Mods directory"); - stringsEvent[EVENT_INTERFACE_LOAD] = TR("Load\\Load Mod"); - stringsEvent[EVENT_INTERFACE_UNLOAD] = TR("Unload\\Unload Mod"); + stringsEvent[EVENT_INTERFACE_WORKSHOP] = TR("Workshop\\Open the workshop to search for mods"); + stringsEvent[EVENT_INTERFACE_MODS_DIR] = TR("Open Directory\\Open the mods directory"); + stringsEvent[EVENT_INTERFACE_MODS_APPLY] = TR("Apply\\Apply the current mod configuration"); + stringsEvent[EVENT_INTERFACE_MOD_MOVE_UP] = TR("Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)"); + stringsEvent[EVENT_INTERFACE_MOD_MOVE_DOWN] = TR("Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)"); + stringsEvent[EVENT_INTERFACE_MODS_REFRESH] = TR("Refresh\\Refresh the list of currently installed mods"); stringsEvent[EVENT_INTERFACE_SETUPd] = TR("Device\\Driver and resolution settings"); stringsEvent[EVENT_INTERFACE_SETUPg] = TR("Graphics\\Graphics settings"); stringsEvent[EVENT_INTERFACE_SETUPp] = TR("Game\\Game settings"); stringsEvent[EVENT_INTERFACE_SETUPc] = TR("Controls\\Keyboard, joystick and mouse settings"); stringsEvent[EVENT_INTERFACE_SETUPs] = TR("Sound\\Music and game sound volume"); - stringsEvent[EVENT_INTERFACE_SETUPm] = TR("Mods\\Manage installed mods"); stringsEvent[EVENT_INTERFACE_DEVICE] = TR("Unit"); stringsEvent[EVENT_INTERFACE_RESOL] = TR("Resolution"); stringsEvent[EVENT_INTERFACE_FULL] = TR("Full screen\\Full screen or window mode"); diff --git a/src/common/restext.h b/src/common/restext.h index 9edf4105..241b6c38 100644 --- a/src/common/restext.h +++ b/src/common/restext.h @@ -71,6 +71,7 @@ enum ResTextType RT_TITLE_WRITE = 50, RT_TITLE_READ = 51, RT_TITLE_USER = 52, + RT_TITLE_MODS = 54, RT_PLAY_CHAP_CHAPTERS = 60, RT_PLAY_CHAP_PLANETS = 61, @@ -86,9 +87,6 @@ enum ResTextType RT_SETUP_KEY1 = 82, RT_SETUP_KEY2 = 83, - RT_MODS_UNLOADED = 85, - RT_MODS_LOADED = 86, - RT_PERSO_FACE = 90, RT_PERSO_GLASSES = 91, RT_PERSO_HAIR = 92, @@ -109,6 +107,7 @@ enum ResTextType RT_DIALOG_OPEN_PATH_FAILED_TEXT = 114, RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE = 115, RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT = 116, + RT_DIALOG_CHANGES_QUESTION = 117, RT_STUDIO_LISTTT = 120, RT_STUDIO_COMPOK = 121, @@ -154,6 +153,11 @@ enum ResTextType RT_SCOREBOARD_RESULTS_TIME= 232, RT_SCOREBOARD_RESULTS_LINE= 233, + RT_MOD_LIST = 234, + RT_MOD_DETAILS = 235, + RT_MOD_SUMMARY = 236, + RT_MOD_ENABLE = 237, + RT_MOD_DISABLE = 238, RT_MAX //! < number of values }; diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index b9e3633f..7092b32b 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -320,19 +320,18 @@ std::string PhaseToString(Phase phase) if (phase == PHASE_APPERANCE) return "PHASE_APPERANCE"; if (phase == PHASE_MAIN_MENU) return "PHASE_MAIN_MENU"; if (phase == PHASE_LEVEL_LIST) return "PHASE_LEVEL_LIST"; + if (phase == PHASE_MOD_LIST) return "PHASE_MOD_LIST"; if (phase == PHASE_SIMUL) return "PHASE_SIMUL"; if (phase == PHASE_SETUPd) return "PHASE_SETUPd"; if (phase == PHASE_SETUPg) return "PHASE_SETUPg"; if (phase == PHASE_SETUPp) return "PHASE_SETUPp"; if (phase == PHASE_SETUPc) return "PHASE_SETUPc"; if (phase == PHASE_SETUPs) return "PHASE_SETUPs"; - if (phase == PHASE_SETUPm) return "PHASE_SETUPm"; if (phase == PHASE_SETUPds) return "PHASE_SETUPds"; if (phase == PHASE_SETUPgs) return "PHASE_SETUPgs"; if (phase == PHASE_SETUPps) return "PHASE_SETUPps"; if (phase == PHASE_SETUPcs) return "PHASE_SETUPcs"; if (phase == PHASE_SETUPss) return "PHASE_SETUPss"; - if (phase == PHASE_SETUPms) return "PHASE_SETUPms"; if (phase == PHASE_WRITEs) return "PHASE_WRITEs"; if (phase == PHASE_READ) return "PHASE_READ"; if (phase == PHASE_READs) return "PHASE_READs"; @@ -345,7 +344,7 @@ std::string PhaseToString(Phase phase) bool IsInSimulationConfigPhase(Phase phase) { - return (phase >= PHASE_SETUPds && phase <= PHASE_SETUPms) || phase == PHASE_READs || phase == PHASE_WRITEs; + return (phase >= PHASE_SETUPds && phase <= PHASE_SETUPss) || phase == PHASE_READs || phase == PHASE_WRITEs; } bool IsPhaseWithWorld(Phase phase) @@ -3913,7 +3912,7 @@ void CRobotMain::ChangeColor() m_phase != PHASE_SETUPps && m_phase != PHASE_SETUPcs && m_phase != PHASE_SETUPss && - m_phase != PHASE_SETUPms && + m_phase != PHASE_MOD_LIST && m_phase != PHASE_WIN && m_phase != PHASE_LOST && m_phase != PHASE_APPERANCE ) return; diff --git a/src/level/robotmain.h b/src/level/robotmain.h index b339cfdc..731d7a1a 100644 --- a/src/level/robotmain.h +++ b/src/level/robotmain.h @@ -55,19 +55,18 @@ enum Phase PHASE_APPERANCE, PHASE_MAIN_MENU, PHASE_LEVEL_LIST, + PHASE_MOD_LIST, PHASE_SIMUL, PHASE_SETUPd, PHASE_SETUPg, PHASE_SETUPp, PHASE_SETUPc, PHASE_SETUPs, - PHASE_SETUPm, PHASE_SETUPds, PHASE_SETUPgs, PHASE_SETUPps, PHASE_SETUPcs, PHASE_SETUPss, - PHASE_SETUPms, PHASE_WRITEs, PHASE_READ, PHASE_READs, diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index b21070fb..5cdfdd47 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -107,7 +107,6 @@ bool CMainDialog::EventProcess(const Event &event) if ( CScreenSetup::GetTab() == PHASE_SETUPp ) m_main->ChangePhase(PHASE_SETUPps); if ( CScreenSetup::GetTab() == PHASE_SETUPc ) m_main->ChangePhase(PHASE_SETUPcs); if ( CScreenSetup::GetTab() == PHASE_SETUPs ) m_main->ChangePhase(PHASE_SETUPss); - if ( CScreenSetup::GetTab() == PHASE_SETUPm ) m_main->ChangePhase(PHASE_SETUPss); } if ( pressedButton == EVENT_INTERFACE_WRITE ) diff --git a/src/ui/mainui.cpp b/src/ui/mainui.cpp index 57436f89..daca36c7 100644 --- a/src/ui/mainui.cpp +++ b/src/ui/mainui.cpp @@ -49,13 +49,13 @@ #include "ui/screen/screen_level_list.h" #include "ui/screen/screen_loading.h" #include "ui/screen/screen_main_menu.h" +#include "ui/screen/screen_mod_list.h" #include "ui/screen/screen_player_select.h" #include "ui/screen/screen_quit.h" #include "ui/screen/screen_setup_controls.h" #include "ui/screen/screen_setup_display.h" #include "ui/screen/screen_setup_game.h" #include "ui/screen/screen_setup_graphics.h" -#include "ui/screen/screen_setup_mods.h" #include "ui/screen/screen_setup_sound.h" #include "ui/screen/screen_welcome.h" @@ -81,11 +81,11 @@ CMainUserInterface::CMainUserInterface() m_screenIORead = MakeUnique(m_screenLevelList.get()); m_screenIOWrite = MakeUnique(m_screenLevelList.get()); m_screenLoading = MakeUnique(); + m_screenModList = MakeUnique(m_dialog.get(), m_app->GetModManager()); m_screenSetupControls = MakeUnique(); m_screenSetupDisplay = MakeUnique(); m_screenSetupGame = MakeUnique(); m_screenSetupGraphics = MakeUnique(); - m_screenSetupMods = MakeUnique(m_dialog.get(), m_app->GetModManager()); m_screenSetupSound = MakeUnique(); m_screenMainMenu = MakeUnique(); m_screenPlayerSelect = MakeUnique(m_dialog.get()); @@ -146,7 +146,6 @@ CScreenSetup* CMainUserInterface::GetSetupScreen(Phase phase) if(phase == PHASE_SETUPp) return m_screenSetupGame.get(); if(phase == PHASE_SETUPc) return m_screenSetupControls.get(); if(phase == PHASE_SETUPs) return m_screenSetupSound.get(); - if(phase == PHASE_SETUPm) return m_screenSetupMods.get(); assert(false); return nullptr; } @@ -187,14 +186,18 @@ void CMainUserInterface::ChangePhase(Phase phase) m_screenLevelList->SetLevelCategory(m_main->GetLevelCategory()); m_currentScreen = m_screenLevelList.get(); } - if (m_phase >= PHASE_SETUPd && m_phase <= PHASE_SETUPm) + if (m_phase == PHASE_MOD_LIST) + { + m_currentScreen = m_screenModList.get(); + } + if (m_phase >= PHASE_SETUPd && m_phase <= PHASE_SETUPs) { CScreenSetup* screenSetup = GetSetupScreen(m_phase); screenSetup->SetInSimulation(false); screenSetup->SetActive(); m_currentScreen = screenSetup; } - if (m_phase >= PHASE_SETUPds && m_phase <= PHASE_SETUPms) + if (m_phase >= PHASE_SETUPds && m_phase <= PHASE_SETUPss) { CScreenSetup* screenSetup = GetSetupScreen(static_cast(m_phase - PHASE_SETUPds + PHASE_SETUPd)); screenSetup->SetInSimulation(true); @@ -350,7 +353,6 @@ void CMainUserInterface::GlintMove() m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPs || - m_phase == PHASE_SETUPm || m_phase == PHASE_SETUPds || m_phase == PHASE_SETUPgs || m_phase == PHASE_SETUPps || @@ -535,12 +537,12 @@ void CMainUserInterface::FrameParticle(float rTime) } else if ( m_phase == PHASE_PLAYER_SELECT || m_phase == PHASE_LEVEL_LIST || + m_phase == PHASE_MOD_LIST || m_phase == PHASE_SETUPd || m_phase == PHASE_SETUPg || m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPs || - m_phase == PHASE_SETUPm || m_phase == PHASE_READ ) { pParti = partiPosBig; diff --git a/src/ui/mainui.h b/src/ui/mainui.h index 76440a40..2cae1d18 100644 --- a/src/ui/mainui.h +++ b/src/ui/mainui.h @@ -50,6 +50,7 @@ class CScreenIOWrite; class CScreenLevelList; class CScreenLoading; class CScreenMainMenu; +class CScreenModList; class CScreenPlayerSelect; class CScreenQuit; class CScreenSetup; @@ -57,7 +58,6 @@ class CScreenSetupControls; class CScreenSetupDisplay; class CScreenSetupGame; class CScreenSetupGraphics; -class CScreenSetupMods; class CScreenSetupSound; class CScreenWelcome; @@ -115,13 +115,13 @@ protected: std::unique_ptr m_screenLevelList; std::unique_ptr m_screenLoading; std::unique_ptr m_screenMainMenu; + std::unique_ptr m_screenModList; std::unique_ptr m_screenPlayerSelect; std::unique_ptr m_screenQuit; std::unique_ptr m_screenSetupControls; std::unique_ptr m_screenSetupDisplay; std::unique_ptr m_screenSetupGame; std::unique_ptr m_screenSetupGraphics; - std::unique_ptr m_screenSetupMods; std::unique_ptr m_screenSetupSound; std::unique_ptr m_screenWelcome; diff --git a/src/ui/screen/screen_main_menu.cpp b/src/ui/screen/screen_main_menu.cpp index 2d69ae1c..30c771a0 100644 --- a/src/ui/screen/screen_main_menu.cpp +++ b/src/ui/screen/screen_main_menu.cpp @@ -170,6 +170,13 @@ void CScreenMainMenu::CreateInterface() pb = pw->CreateButton(pos, ddim, 128+60, EVENT_INTERFACE_SATCOM); pb->SetState(STATE_SHADOW); + // Mods button + pos.x = 447.0f/640.0f; + pos.y = 313.0f/480.0f; + ddim.x = 0.09f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MODS); + pb->SetState(STATE_SHADOW); + SetBackground("textures/interface/interface.png"); CreateVersionDisplay(); } @@ -235,6 +242,9 @@ bool CScreenMainMenu::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SATCOM); break; + case EVENT_INTERFACE_MODS: + m_main->ChangePhase(PHASE_MOD_LIST); + default: return true; } diff --git a/src/ui/screen/screen_mod_list.cpp b/src/ui/screen/screen_mod_list.cpp new file mode 100644 index 00000000..b8558f81 --- /dev/null +++ b/src/ui/screen/screen_mod_list.cpp @@ -0,0 +1,490 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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, see http://gnu.org/licenses + */ + +#include "ui/screen/screen_mod_list.h" + +#include "common/config.h" + +#include "app/app.h" +#include "app/modman.h" + +#include "common/logger.h" +#include "common/restext.h" +#include "common/stringutils.h" + +#include "common/resources/resourcemanager.h" + +#include "common/system/system.h" + +#include "math/func.h" + +#include "ui/controls/button.h" +#include "ui/controls/edit.h" +#include "ui/controls/interface.h" +#include "ui/controls/label.h" +#include "ui/controls/list.h" +#include "ui/controls/window.h" + +namespace Ui +{ + +CScreenModList::CScreenModList(CMainDialog* dialog, CModManager* modManager) + : m_dialog(dialog), + m_modManager(modManager) +{ +} + +void CScreenModList::CreateInterface() +{ + CWindow* pw; + CEdit* pe; + CLabel* pl; + CButton* pb; + CList* pli; + Math::Point pos, ddim; + std::string name; + + m_changes = false; + ApplyChanges(); + + // Display the window + pos.x = 0.10f; + pos.y = 0.10f; + ddim.x = 0.80f; + ddim.y = 0.80f; + pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5); + pw->SetClosable(true); + GetResource(RES_TEXT, RT_TITLE_MODS, name); + pw->SetName(name); + + pos.x = 0.10f; + pos.y = 0.40f; + ddim.x = 0.50f; + ddim.y = 0.50f; + pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner + pos.x = 0.40f; + pos.y = 0.10f; + ddim.x = 0.50f; + ddim.y = 0.50f; + pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner + + // Display the list of mods + pos.x = ox+sx*3; + pos.y = oy+sy*10.5f; + ddim.x = dim.x*7.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_LIST, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*6.7f; + ddim.y = dim.y*4.5f; + ddim.x = dim.x*6.5f; + pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MOD_LIST); + pli->SetState(STATE_SHADOW); + pli->SetState(STATE_EXTEND); + + UpdateModList(); + + // Displays the mod details + pos.x = ox+sx*9.5f; + pos.y = oy+sy*10.5f; + ddim.x = dim.x*7.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_DETAILS, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*6.7f; + ddim.y = dim.y*4.5f; + ddim.x = dim.x*6.5f; + pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_LIST); + pli->SetState(STATE_SHADOW); + + UpdateModDetails(); + + pos = pli->GetPos(); + ddim = pli->GetDim(); + + // Displays the mod summary + pos.x = ox+sx*3; + pos.y = oy+sy*5.4f; + ddim.x = dim.x*6.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_SUMMARY, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.x = ox+sx*3; + pos.y = oy+sy*3.6f; + ddim.x = dim.x*13.4f; + ddim.y = dim.y*1.9f; + pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_MOD_SUMMARY); + pe->SetState(STATE_SHADOW); + pe->SetMaxChar(500); + pe->SetEditCap(false); // just to see + pe->SetHighlightCap(false); + + UpdateModSummary(); + + // Apply button + pos.x = ox+sx*13.75f; + pos.y = oy+sy*2; + ddim.x = dim.x*2.0f; + ddim.y = dim.y*1; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MODS_APPLY); + pb->SetState(STATE_SHADOW); + + UpdateApplyButton(); + + // Display the enable/disable button + pos.x -= dim.x*2.3f; + ddim.x = dim.x*2.0f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE); + pb->SetState(STATE_SHADOW); + + UpdateEnableDisableButton(); + + // Display the move up button + pos.x -= dim.x*1.3f; + ddim.x = dim.x*1; + pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_MOD_MOVE_UP); + pb->SetState(STATE_SHADOW); + + // Display the move down button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 50, EVENT_INTERFACE_MOD_MOVE_DOWN); + pb->SetState(STATE_SHADOW); + + UpdateUpDownButtons(); + + // Display the refresh button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 87, EVENT_INTERFACE_MODS_REFRESH); + pb->SetState(STATE_SHADOW); + + // Display the open website button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 40, EVENT_INTERFACE_WORKSHOP); + pb->SetState(STATE_SHADOW); + + // Display the open directory button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 57, EVENT_INTERFACE_MODS_DIR); + pb->SetState(STATE_SHADOW); + + // Back button + pos.x = ox+sx*3; + ddim.x = dim.x*2.3f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK); + pb->SetState(STATE_SHADOW); + + // Background + SetBackground("textures/interface/interface.png"); + CreateVersionDisplay(); +} + +bool CScreenModList::EventProcess(const Event &event) +{ + CWindow* pw; + CList* pl; + + const std::string workshopUrl = "https://www.moddb.com/games/colobot-gold-edition"; + const std::string modDir = CResourceManager::GetSaveLocation() + "/mods"; + + auto systemUtils = CSystemUtils::Create(); // platform-specific utils + + Mod const * mod; + + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return false; + + if (event.type == pw->GetEventTypeClose() || + event.type == EVENT_INTERFACE_BACK || + (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE))) + { + if (m_changes) + { + m_dialog->StartQuestion(RT_DIALOG_CHANGES_QUESTION, true, true, false, + [this]() + { + ApplyChanges(); + CloseWindow(); + }, + [this]() + { + m_changes = false; // do not save changes on "No" + ApplyChanges(); + CloseWindow(); + }); + } + else + { + ApplyChanges(); + CloseWindow(); + } + return false; + } + + switch( event.type ) + { + case EVENT_INTERFACE_MOD_LIST: + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_LIST)); + if (pl == nullptr) break; + m_modSelectedIndex = pl->GetSelect(); + UpdateModSummary(); + UpdateModDetails(); + UpdateEnableDisableButton(); + UpdateUpDownButtons(); + break; + + case EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE: + mod = &m_modManager->GetMod(m_modSelectedIndex); + if (mod->enabled) + { + m_modManager->DisableMod(m_modSelectedIndex); + } + else + { + m_modManager->EnableMod(m_modSelectedIndex); + } + UpdateModList(); + UpdateEnableDisableButton(); + m_changes = true; + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MOD_MOVE_UP: + m_modSelectedIndex = m_modManager->MoveUp(m_modSelectedIndex); + UpdateModList(); + UpdateUpDownButtons(); + m_changes = true; + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MOD_MOVE_DOWN: + m_modSelectedIndex = m_modManager->MoveDown(m_modSelectedIndex); + UpdateModList(); + UpdateUpDownButtons(); + m_changes = true; + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MODS_REFRESH: + case EVENT_INTERFACE_MODS_APPLY: + ApplyChanges(); + // Update the whole UI + UpdateModList(); + UpdateModSummary(); + UpdateModDetails(); + UpdateEnableDisableButton(); + UpdateApplyButton(); + UpdateUpDownButtons(); + break; + + case EVENT_INTERFACE_MODS_DIR: + if (!systemUtils->OpenPath(modDir)) + { + std::string title, text; + GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TITLE, title); + GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TEXT, text); + + // Workaround for Windows: the label skips everything after the first \\ character + std::string modDirWithoutBackSlashes = modDir; + std::replace(modDirWithoutBackSlashes.begin(), modDirWithoutBackSlashes.end(), '\\', '/'); + + m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), modDirWithoutBackSlashes.c_str())); + } + break; + + case EVENT_INTERFACE_WORKSHOP: + if (!systemUtils->OpenWebsite(workshopUrl)) + { + std::string title, text; + GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE, title); + GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT, text); + m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), workshopUrl.c_str())); + } + break; + + default: + return true; + } + return false; +} + +void CScreenModList::ApplyChanges() +{ + if (m_changes) + { + m_changes = false; + m_modManager->SaveMods(); + } + + m_modManager->FindMods(); + m_modManager->SaveMods(); + + m_empty = (m_modManager->CountMods() == 0); + + m_modManager->UpdatePaths(); + m_modManager->ReloadResources(); + + m_modSelectedIndex = Math::Clamp(m_modSelectedIndex, static_cast(0), m_modManager->CountMods() - 1); +} + +void CScreenModList::CloseWindow() +{ + m_main->ChangePhase(PHASE_MAIN_MENU); +} + +void CScreenModList::UpdateModList() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CList* pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_LIST)); + if (pl == nullptr) return; + + pl->Flush(); + + if (m_empty) + { + return; + } + + auto mods = m_modManager->GetMods(); + for (size_t i = 0; i < mods.size(); ++i) + { + const auto& mod = mods[i]; + pl->SetItemName(i, mod.name); + pl->SetCheck(i, mod.enabled); + pl->SetEnable(i, true); + } + + pl->SetSelect(m_modSelectedIndex); + pl->ShowSelect(false); +} + +void CScreenModList::UpdateModDetails() +{ + //TODO +} + +void CScreenModList::UpdateModSummary() +{ + //TODO +} + +void CScreenModList::UpdateEnableDisableButton() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE)); + if (pb == nullptr) return; + + std::string buttonName{}; + + if (m_empty) + { + pb->ClearState(STATE_ENABLE); + + // Set some default name + GetResource(RES_TEXT, RT_MOD_ENABLE, buttonName); + pb->SetName(buttonName); + + return; + } + + const auto& mod = m_modManager->GetMod(m_modSelectedIndex); + + if (mod.enabled) + { + GetResource(RES_TEXT, RT_MOD_DISABLE, buttonName); + pb->SetName(buttonName); + } + else + { + GetResource(RES_TEXT, RT_MOD_ENABLE, buttonName); + pb->SetName(buttonName); + } +} + +void CScreenModList::UpdateApplyButton() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_APPLY)); + if (pb == nullptr) return; + + if (m_empty) + { + pb->ClearState(STATE_ENABLE); + return; + } + + if (m_changes) + { + pb->SetState(STATE_ENABLE); + } + else + { + pb->ClearState(STATE_ENABLE); + } +} + +void CScreenModList::UpdateUpDownButtons() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb_up = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_MOVE_UP)); + if (pb_up == nullptr) return; + + CButton* pb_down = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_MOVE_DOWN)); + if (pb_down == nullptr) return; + + if (m_empty) + { + pb_up->ClearState(STATE_ENABLE); + pb_down->ClearState(STATE_ENABLE); + return; + } + + if (m_modSelectedIndex == 0) + { + pb_up->ClearState(STATE_ENABLE); + } + else + { + pb_up->SetState(STATE_ENABLE); + } + + if (m_modSelectedIndex >= m_modManager->CountMods() - 1) + { + pb_down->ClearState(STATE_ENABLE); + } + else + { + pb_down->SetState(STATE_ENABLE); + } +} + +} // namespace Ui diff --git a/src/ui/screen/screen_mod_list.h b/src/ui/screen/screen_mod_list.h new file mode 100644 index 00000000..ac039bee --- /dev/null +++ b/src/ui/screen/screen_mod_list.h @@ -0,0 +1,96 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * 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, see http://gnu.org/licenses + */ + +#pragma once + +#include "app/modman.h" + +#include "ui/screen/screen.h" + +#include "level/level_category.h" + +#include +#include + +namespace Ui +{ +class CMainDialog; + +/** + * \class CScreenModList + * \brief This class is the front-end for the \ref CModManager. + * + * \section Assumptions Assumptions + * + * It assumes the user is changing something in the mods folders while the screen is visible, + * e.g. removing them or adding more. For this reason, the mods are always reloaded after the user + * lefts the screen, possibly after asking the user if their changes should be saved. They are also reloaded + * when the user opens the screen to avoid weird situations like "the mod is no longer there but in theory + * it's still in the game's memory even if it's not visible on the list". + * + * Unsafe changes, like removing a mod which is still enabled, are a sole responsibility of the user and + * we basically can't guarantee the game will behave properly in such cases even when they happen while + * this screen is visible. + * + * \section Features UI Features + * + * The user can reorder mods with appropriate buttons and enable/disable them. To avoid reloading + * the resources after every change, the changes are not immediate. The resources are reloaded in the + * cases described above and also after using the Apply or Refresh buttons. The only technical + * difference between them is that the Refresh button is always enabled, but Apply is only enabled + * if the user made any changes in the list by using the UI. The reason is, again, to avoid dealing with + * weird situations like described above. + * + * The UI also shows the selected mod metadata like description, version, etc. + * + * There is also a button which will try to open the default web browser with the Workshop website, + * where the user can search for new mods. + * + * For convenience, also a button opening a saves/mods folder is provided. + */ +class CScreenModList : public CScreen +{ +public: + CScreenModList(CMainDialog* dialog, CModManager* modManager); + + void CreateInterface() override; + bool EventProcess(const Event &event) override; + +protected: + void ApplyChanges(); + void CloseWindow(); + + void UpdateModList(); + void UpdateModDetails(); + void UpdateModSummary(); + void UpdateEnableDisableButton(); + void UpdateApplyButton(); + void UpdateUpDownButtons(); + +protected: + Ui::CMainDialog* m_dialog; + + CModManager* m_modManager; + + size_t m_modSelectedIndex = 0; + bool m_changes = false; + bool m_empty = true; +}; + +} // namespace Ui diff --git a/src/ui/screen/screen_setup.cpp b/src/ui/screen/screen_setup.cpp index 7a83ae1e..67848640 100644 --- a/src/ui/screen/screen_setup.cpp +++ b/src/ui/screen/screen_setup.cpp @@ -83,7 +83,7 @@ void CScreenSetup::CreateInterface() ddim.y = 0.05f; pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray - ddim.x = 0.65f/5-0.01f; + ddim.x = 0.78f/5-0.01f; ddim.y = 0.06f; pos.x = 0.115f; pos.y = 0.76f; @@ -116,12 +116,6 @@ void CScreenSetup::CreateInterface() pb->SetState(STATE_CARD); pb->SetState(STATE_CHECK, (m_tab == PHASE_SETUPs)); - pos.x += ddim.x+0.01f; - pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPm); - pb->SetState(STATE_SHADOW); - pb->SetState(STATE_CARD); - pb->SetState(STATE_CHECK, (m_tab == PHASE_SETUPm)); - pos.x = 0.10f; ddim.x = 0.80f; pos.y = 0.34f; @@ -154,10 +148,6 @@ bool CScreenSetup::EventProcess(const Event &event) CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return false; - CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_SETUPm)); - if ( pb == nullptr ) return false; - pb->SetState(STATE_ENABLE); - if ( event.type == pw->GetEventTypeClose() || event.type == EVENT_INTERFACE_BACK || (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE)) ) @@ -189,10 +179,6 @@ bool CScreenSetup::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SETUPs); return false; - case EVENT_INTERFACE_SETUPm: - m_main->ChangePhase(PHASE_SETUPm); - return false; - default: break; } @@ -202,10 +188,6 @@ bool CScreenSetup::EventProcess(const Event &event) CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == nullptr ) return false; - CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_SETUPm)); - if ( pb == nullptr ) return false; - pb->ClearState(STATE_ENABLE); - if ( event.type == pw->GetEventTypeClose() || event.type == EVENT_INTERFACE_BACK || (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE)) ) @@ -239,9 +221,6 @@ bool CScreenSetup::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SETUPss); return false; - case EVENT_INTERFACE_SETUPm: - assert(false); // should never get here - default: break; } diff --git a/src/ui/screen/screen_setup_mods.cpp b/src/ui/screen/screen_setup_mods.cpp deleted file mode 100644 index 69cd13fe..00000000 --- a/src/ui/screen/screen_setup_mods.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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, see http://gnu.org/licenses - */ - -#include "ui/screen/screen_setup_mods.h" - -#include "common/config.h" - -#include "app/app.h" -#include "app/modman.h" - -#include "common/logger.h" -#include "common/restext.h" -#include "common/settings.h" -#include "common/stringutils.h" - -#include "common/resources/resourcemanager.h" - -#include "common/system/system.h" - -#include "level/parser/parser.h" - -#include "ui/controls/button.h" -#include "ui/controls/edit.h" -#include "ui/controls/interface.h" -#include "ui/controls/label.h" -#include "ui/controls/list.h" -#include "ui/controls/window.h" - -#include -#include -#include - -using namespace boost::filesystem; - -namespace Ui -{ - -CScreenSetupMods::CScreenSetupMods(CMainDialog* dialog, CModManager* modManager) - : m_dialog(dialog), - m_modManager(modManager) -{ -} - -void CScreenSetupMods::SetActive() -{ - m_tab = PHASE_SETUPm; -} - -void CScreenSetupMods::CreateInterface() -{ - CWindow* pw; - CLabel* pl; - CButton* pb; - CList* pli; - Math::Point pos, ddim; - std::string name; - - m_modManager->FindMods(); - - CScreenSetup::CreateInterface(); - pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == nullptr ) return; - - // Displays a list of unloaded mods: - pos.x = ox+sx*3; - pos.y = oy+sy*9; - ddim.x = dim.x*6; - ddim.y = dim.y*1; - GetResource(RES_TEXT, RT_MODS_UNLOADED, name); - pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name); - pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); - - pos.y = oy+sy*3.75f; - ddim.x = dim.x*6.5f; - ddim.y = dim.y*6.05f; - pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MODS_UNLOADED); - pli->SetState(STATE_SHADOW); - UpdateUnloadedModList(); - - // Displays a list of loaded mods: - pos.x = ox+sx*9.5f; - pos.y = oy+sy*9; - ddim.x = dim.x*6; - ddim.y = dim.y*1; - GetResource(RES_TEXT, RT_MODS_LOADED, name); - pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name); - pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); - - pos.y = oy+sy*3.75f; - ddim.x = dim.x*6.5f; - ddim.y = dim.y*6.05f; - pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MODS_LOADED); - pli->SetState(STATE_SHADOW); - UpdateLoadedModList(); - - pos = pli->GetPos(); - ddim = pli->GetDim(); - pos.x = ox+sx*8.2f; - pos.y = oy+sy*2; - ddim.x = dim.x*1; - ddim.y = dim.y*1; - pb = pw->CreateButton(pos, ddim, 40, EVENT_INTERFACE_WORKSHOP); - pb->SetState(STATE_SHADOW); - - pos.x += dim.x*1.3f; - pb = pw->CreateButton(pos, ddim, 57, EVENT_INTERFACE_MODS_DIR); - pb->SetState(STATE_SHADOW); - - pos.x += dim.x*1.3f; - ddim.x = dim.x*2.5f; - pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_LOAD); - pb->SetState(STATE_SHADOW); - pb->ClearState(STATE_ENABLE); - - pos.x += dim.x*2.8f; - pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_UNLOAD); - pb->SetState(STATE_SHADOW); - pb->ClearState(STATE_ENABLE); -} - -bool CScreenSetupMods::EventProcess(const Event &event) -{ - CWindow* pw; - CButton* pb; - CList* pl; - std::string modName; - const std::string website = "https://www.moddb.com/games/colobot-gold-edition"; - const std::string modDir = CResourceManager::GetSaveLocation() + "/mods"; - auto systemUtils = CSystemUtils::Create(); // platform-specific utils - - if (!CScreenSetup::EventProcess(event)) return false; - - pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == nullptr ) return false; - - switch (event.type) - { - case EVENT_INTERFACE_LOAD: - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); - if (pl == nullptr) return false; - modName = pl->GetItemName(pl->GetSelect()); - - m_modManager->EnableMod(modName); - m_modManager->SaveMods(); - m_modManager->UpdatePaths(); - m_modManager->ReloadResources(); - - m_main->ChangePhase(PHASE_SETUPm); - break; - - case EVENT_INTERFACE_UNLOAD: - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); - if (pl == nullptr) return false; - modName = pl->GetItemName(pl->GetSelect()); - - m_modManager->DisableMod(modName); - m_modManager->SaveMods(); - m_modManager->UpdatePaths(); - m_modManager->ReloadResources(); - - m_main->ChangePhase(PHASE_SETUPm); - break; - - case EVENT_INTERFACE_MODS_UNLOADED: - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); - if ( pl == nullptr ) break; - - pb = static_cast(pw->SearchControl(EVENT_INTERFACE_UNLOAD)); - if ( pb == nullptr ) break; - pl->SetSelect(-1); - pb->ClearState(STATE_ENABLE); - - pb = static_cast(pw->SearchControl(EVENT_INTERFACE_LOAD)); - if ( pb == nullptr ) break; - pb->SetState(STATE_ENABLE); - break; - - case EVENT_INTERFACE_MODS_LOADED: - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); - if ( pl == nullptr ) break; - - pb = static_cast(pw->SearchControl(EVENT_INTERFACE_LOAD)); - if ( pb == nullptr ) break; - pl->SetSelect(-1); - pb->ClearState(STATE_ENABLE); - - pb = static_cast(pw->SearchControl(EVENT_INTERFACE_UNLOAD)); - if ( pb == nullptr ) break; - pb->SetState(STATE_ENABLE); - break; - - case EVENT_INTERFACE_MODS_DIR: - if (!systemUtils->OpenPath(modDir)) - { - std::string title, text; - GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TITLE, title); - GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TEXT, text); - - // Workaround for Windows: the label skips everything after the first \\ character - std::string modDirWithoutBackSlashes = modDir; - std::replace(modDirWithoutBackSlashes.begin(), modDirWithoutBackSlashes.end(), '\\', '/'); - - m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), modDirWithoutBackSlashes.c_str())); - } - break; - - case EVENT_INTERFACE_WORKSHOP: - if (!systemUtils->OpenWebsite(website)) - { - std::string title, text; - GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE, title); - GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT, text); - m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), website.c_str())); - } - break; - - default: - return true; - } - return false; -} - -void CScreenSetupMods::UpdateUnloadedModList() -{ - CWindow* pw; - CList* pl; - int i = 0; - directory_iterator end_itr; - - pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == nullptr ) return; - - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_UNLOADED)); - if ( pl == nullptr ) return; - pl->Flush(); - - for (const auto& mod : m_modManager->GetMods()) - { - if (!mod.enabled) - { - pl->SetItemName(i++, mod.name); - } - } - - pl->ShowSelect(false); // shows the selected columns -} - -void CScreenSetupMods::UpdateLoadedModList() -{ - CWindow* pw; - CList* pl; - int i = 0; - directory_iterator end_itr; - - pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == nullptr ) return; - - pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_LOADED)); - if ( pl == nullptr ) return; - pl->Flush(); - - for (const auto& mod : m_modManager->GetMods()) - { - if (mod.enabled) - { - pl->SetItemName(i++, mod.name); - } - } - - pl->ShowSelect(false); // shows the selected columns -} - -} // namespace Ui diff --git a/src/ui/screen/screen_setup_mods.h b/src/ui/screen/screen_setup_mods.h deleted file mode 100644 index 9098d7d7..00000000 --- a/src/ui/screen/screen_setup_mods.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam - * http://epsitec.ch; http://colobot.info; http://github.com/colobot - * - * 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, see http://gnu.org/licenses - */ - -#pragma once - -#include "ui/maindialog.h" - -#include "ui/screen/screen_setup.h" - -#include - -class CModManager; - -namespace Ui -{ - -class CScreenSetupMods : public CScreenSetup -{ -public: - CScreenSetupMods(CMainDialog* dialog, CModManager* modManager); - void SetActive() override; - - void CreateInterface() override; - bool EventProcess(const Event &event) override; - -protected: - void UpdateUnloadedModList(); - void UpdateLoadedModList(); - -protected: - CMainDialog* m_dialog; - - CModManager* m_modManager; -}; - -} // namespace Ui