/
Console.h
184 lines (140 loc) · 5.28 KB
/
Console.h
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* Copyright 2016 Arx Libertatis Team (see the AUTHORS file)
*
* This file is part of Arx Libertatis.
*
* Arx Libertatis 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.
*
* Arx Libertatis 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 Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARX_GUI_CONSOLE_H
#define ARX_GUI_CONSOLE_H
#include <vector>
#include <string>
#include <utility>
#include <deque>
#include <stddef.h>
#include "core/TimeTypes.h"
#include "game/GameTypes.h"
#include "input/TextInput.h"
#include "io/log/LogBackend.h"
class Entity;
class ConsoleBuffer {
std::vector<std::string> m_lines;
size_t m_width;
size_t m_line;
size_t m_pos;
bool m_newline;
public:
ConsoleBuffer(size_t lines, size_t width)
: m_lines(lines)
, m_width(width)
, m_line(0)
, m_pos(0)
, m_newline(false)
{ }
size_t lines() const { return m_lines.size(); }
std::string & line(size_t index) {
return m_lines[(m_line + 1 + index) % m_lines.size()];
}
const std::string & line(size_t index) const {
return m_lines[(m_line + 1 + index) % m_lines.size()];
}
void append(const std::string & text);
};
class MemoryLogger : public logger::Backend {
ConsoleBuffer * m_buffer;
public:
explicit MemoryLogger(ConsoleBuffer * buffer) : m_buffer(buffer) { }
void log(const logger::Source & file, int line, Logger::LogLevel level, const std::string & str);
};
class ScriptConsole : protected BasicTextInput {
typedef BasicTextInput Base;
static const size_t MaxSuggestions = 1000;
static const size_t MaxVisibleSuggestions = 20;
static const size_t ScrollbackLines = 10;
static const size_t ScrollbackColumns = 100;
static const size_t MaxHistorySize = 100;
bool m_enabled;
bool m_wasPaused;
typedef std::pair<size_t, std::string> Suggestion;
ConsoleBuffer m_buffer;
bool m_updateSuggestions; //!< Controls whether \ref parse() updates the suggestions/auto-completion
std::deque<std::string> m_history; //!< History of unique commands, from oldest to most recently used
std::vector<Suggestion> m_suggestions; //!< Suggestions and corresponding start positions in \ref text()
std::string m_originalText; //!< \ref text() that was used to generate the suggestions / search the history
size_t m_originalCursorPos; //!< Cursor position in the original text
Suggestion m_completion; //!< Tab completion and corresponding start position in \ref text()
Suggestion m_error; //!< Error message and corresponding position in \ref text()
int m_selection; //!< The selected suggestion (positive) history item (negative) or current line (0)
EntityHandle m_lastSelectedEntity;
PlatformDuration m_blinkTime;
bool m_blink;
size_t m_contextBegin; //!< Start of the context entity ID in \ref text()
size_t m_contextEnd; //!< End of the context entity ID in \ref text()
size_t m_commandBegin; //!< Start of the command in \ref text()
size_t m_suggestionPos; //!< Start of the command in \ref text()
bool keyPressed(Keyboard::Key key, KeyModifiers mod);
void textUpdated();
void cursorUpdated();
void paste(const std::string & text);
/*!
* Parse the current command and update suggestions
*/
void parse(bool allowEmptyPrefix = false);
/*!
* Select a history entry (negative), a suggestion (positive) or the current command (0)
*
* \param dir The direction in which to move the selection. Must be 1 or -1.
*/
void select(int dir);
//! Finalize the selection, apply characters from \ref m_completion, or suggest all entities and commands
void autocomplete(size_t characters = size_t(-1));
//! Edit a suggestion into \ref m_originalText at \ref m_originalCursorPos and use it as the new text
void applySuggestion(const Suggestion & suggestion);
static bool addContextSuggestion(void * self, const std::string & suggestion);
static bool addCommandSuggestion(void * self, const std::string & suggestion);
public:
ScriptConsole()
: m_enabled(false)
, m_wasPaused(false)
, m_buffer(ScrollbackLines, ScrollbackColumns)
, m_updateSuggestions(true)
, m_originalCursorPos(true)
, m_selection(0)
, m_lastSelectedEntity(EntityHandle_Player)
, m_blinkTime(PlatformDuration_ZERO)
, m_blink(true)
, m_contextBegin(0)
, m_contextEnd(0)
, m_commandBegin(0)
, m_suggestionPos(0)
{ }
//! Show the console and unlock the hotkey
void open();
//! Hide the console
void close();
//! ID of the current context entity or an empty string
std::string context() { return text().substr(m_contextBegin, m_contextEnd - m_contextBegin); }
//! Current command
std::string command() { return text().substr(m_commandBegin); }
//! Current context entity
Entity * contextEntity();
//!< Execute the current command
void execute();
void update();
void draw();
//! The console's output buffer
ConsoleBuffer & buffer() { return m_buffer; }
};
extern ScriptConsole g_console;
#endif // ARX_GUI_CONSOLE_H