File: Messages.cpp

package info (click to toggle)
endless-sky 0.10.16-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 414,608 kB
  • sloc: cpp: 73,435; python: 893; xml: 666; sh: 271; makefile: 28
file content (155 lines) | stat: -rw-r--r-- 4,618 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* Messages.cpp
Copyright (c) 2014 by Michael Zahniser

Endless Sky 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.

Endless Sky 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 <https://www.gnu.org/licenses/>.
*/

#include "Messages.h"

#include "Color.h"
#include "GameData.h"

#include <mutex>

using namespace std;

namespace {
	const int MAX_LOG = 10000;

	mutex incomingMutex;

	vector<pair<string, Messages::Importance>> incoming;
	vector<Messages::Entry> recent;
	deque<pair<string, Messages::Importance>> logged;
}



// Add a message to the list along with its level of importance
// When forced, the message is forcibly added to the log, but not to the list.
void Messages::Add(const string &message, Importance importance, bool force)
{
	lock_guard<mutex> lock(incomingMutex);
	incoming.emplace_back(message, importance);
	AddLog(message, importance, force);
}



// Add a message to the log. For messages meant to be shown
// also on the main panel, use Add instead.
void Messages::AddLog(const string &message, Importance importance, bool force)
{
	if(force || logged.empty() || message != logged.front().first || importance == Importance::HighestDuplicating)
	{
		logged.emplace_front(message, importance);
		if(logged.size() > MAX_LOG)
			logged.pop_back();
	}
}



// Get the messages for the given game step. Any messages that are too old
// will be culled out, and new ones that have just been added will have
// their "step" set to the given value.
const vector<Messages::Entry> &Messages::Get(int step, int animationDuration)
{
	lock_guard<mutex> lock(incomingMutex);

	// Erase messages that have reached the end of their lifetime.
	auto it = recent.begin();
	while(it != recent.end())
	{
		if(step - it->step > 1000 + animationDuration || (it->deathStep >= 0 && it->deathStep <= step))
			it = recent.erase(it);
		else
			++it;
	}

	// Load the incoming messages.
	for(const pair<string, Importance> &item : incoming)
	{
		const string &message = item.first;
		Importance importance = item.second;

		// If this message is not important and it is already being shown in the
		// list, ignore it.
		if(importance == Importance::Low || importance == Importance::HighestNoRepeat)
		{
			bool skip = false;
			for(const Messages::Entry &entry : recent)
				skip |= (entry.message == message);
			if(skip)
				continue;
		}

		for(auto &it : recent)
		{
			// Each time a new message comes in, "age" all the existing ones,
			// except for cases where it would interrupt an animation, to
			// limit how many of them appear at once.
			if(step - it.step > animationDuration)
				it.step -= 60;
			// For each incoming message, if it exactly matches an existing message,
			// replace that one with this new one by scheduling the old one for removal.
			if(importance != Importance::Low && importance != Importance::HighestNoRepeat
					&& importance != Importance::HighestDuplicating && it.message == message && it.deathStep < 0)
				it.deathStep = step + animationDuration;
		}
		recent.emplace_back(step, message, importance);
	}
	incoming.clear();
	return recent;
}



const deque<pair<string, Messages::Importance>> &Messages::GetLog()
{
	return logged;
}



// Reset the messages (i.e. because a new game was loaded).
void Messages::Reset()
{
	lock_guard<mutex> lock(incomingMutex);
	incoming.clear();
	recent.clear();
	logged.clear();
}



// Get color that should be used for drawing messages of given importance.
const Color *Messages::GetColor(Importance importance, bool isLogPanel)
{
	string prefix = isLogPanel ? "message log importance " : "message importance ";
	switch(importance)
	{
		case Messages::Importance::Highest:
		case Messages::Importance::HighestNoRepeat:
		case Messages::Importance::HighestDuplicating:
			return GameData::Colors().Get(prefix + "highest");
		case Messages::Importance::High:
			return GameData::Colors().Get(prefix + "high");
		case Messages::Importance::Info:
			return GameData::Colors().Get(prefix + "info");
		case Messages::Importance::Daily:
			return GameData::Colors().Get(prefix + "daily");
		case Messages::Importance::Low:
		default:
			return GameData::Colors().Get(prefix + "low");
	}
}