1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 #include "app/pausemanager.h"
21 
22 #include "app/app.h"
23 
24 #include "common/logger.h"
25 
26 #include "level/robotmain.h"
27 
28 #include <algorithm>
29 #include <boost/algorithm/string/join.hpp>
30 
31 struct ActivePause
32 {
ActivePauseActivePause33     explicit ActivePause(PauseType type, PauseMusic music = PAUSE_MUSIC_NONE)
34         : type(type),
35           music(music)
36     {}
37 
38     ActivePause(const ActivePause&) = delete;
39     ActivePause& operator=(const ActivePause&) = delete;
40 
41     PauseType type;
42     PauseMusic music;
43 };
44 
GetPauseName(PauseType type)45 static std::string GetPauseName(PauseType type)
46 {
47     std::vector<std::string> x;
48     if ((type & PAUSE_ENGINE) != 0) x.push_back("engine");
49     if ((type & PAUSE_HIDE_SHORTCUTS) != 0) x.push_back("hide_shortcuts");
50     if ((type & PAUSE_PHOTO) != 0) x.push_back("photo");
51     if ((type & PAUSE_OBJECT_UPDATES) != 0) x.push_back("object_updates");
52     if ((type & PAUSE_MUTE_SOUND) != 0) x.push_back("mute_sound");
53     if ((type & PAUSE_CAMERA) != 0) x.push_back("camera");
54     return boost::algorithm::join(x, "|");
55 }
56 
CPauseManager()57 CPauseManager::CPauseManager()
58 {
59     m_main = CRobotMain::GetInstancePointer();
60 }
61 
~CPauseManager()62 CPauseManager::~CPauseManager()
63 {}
64 
ActivatePause(PauseType type,PauseMusic music)65 ActivePause* CPauseManager::ActivatePause(PauseType type, PauseMusic music)
66 {
67     GetLogger()->Debug("Activated pause mode - %s\n", GetPauseName(type).c_str());
68     auto pause = MakeUnique<ActivePause>(type, music);
69     ActivePause* ptr = pause.get();
70     m_activePause.push_back(std::move(pause));
71     Update();
72     return ptr;
73 }
74 
DeactivatePause(ActivePause * pause)75 void CPauseManager::DeactivatePause(ActivePause* pause)
76 {
77     if (pause == nullptr) return;
78     GetLogger()->Debug("Deactivated pause mode - %s\n", GetPauseName(pause->type).c_str());
79     auto it = std::remove_if(
80         m_activePause.begin(), m_activePause.end(),
81         [&](const std::unique_ptr<ActivePause>& x) { return x.get() == pause; }
82     );
83     if (it == m_activePause.end())
84     {
85         GetLogger()->Warn("Releasing previously not deactivated pause now!\n");
86         std::free(pause);
87     }
88     m_activePause.erase(it);
89     Update();
90 }
91 
FlushPause()92 void CPauseManager::FlushPause()
93 {
94     for (auto& pause : m_activePause)
95     {
96         GetLogger()->Warn("Pause not deactivated before phase change!\n");
97         pause.release();
98     }
99     m_activePause.clear();
100 }
101 
GetPause()102 PauseType CPauseManager::GetPause()
103 {
104     PauseType current = PAUSE_NONE;
105     for(auto& pause : m_activePause)
106     {
107         current |= pause->type;
108     }
109     return current;
110 }
111 
IsPauseType(PauseType type)112 bool CPauseManager::IsPauseType(PauseType type)
113 {
114     PauseType current = GetPause();
115     return (current & type) == type;
116 }
117 
Update()118 void CPauseManager::Update()
119 {
120     m_main->UpdatePause(GetPause()); //TODO
121 
122     PauseMusic music = PAUSE_MUSIC_NONE;
123     for(int i = m_activePause.size()-1; i >= 0; i--)
124     {
125         if (m_activePause[i]->music != PAUSE_MUSIC_NONE)
126         {
127             music = m_activePause[i]->music;
128             break;
129         }
130     }
131     if (music != m_lastPauseMusic)
132     {
133         m_main->UpdatePauseMusic(music);
134         m_lastPauseMusic = music;
135     }
136 }
137