Skip to content

Commit a921794

Browse files
committed
Add a simple script console
1 parent a10af51 commit a921794

File tree

4 files changed

+371
-0
lines changed

4 files changed

+371
-0
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,7 @@ set(GRAPHICS_OPENGL_SOURCES
900900

901901
set(GUI_SOURCES
902902
src/gui/CinematicBorder.cpp
903+
src/gui/Console.cpp
903904
src/gui/Credits.cpp
904905
src/gui/Cursor.cpp
905906
src/gui/DebugHud.cpp

src/core/ArxGame.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
108108
#include "graphics/particle/Spark.h"
109109
#include "graphics/texture/TextureStage.h"
110110

111+
#include "gui/Console.h"
111112
#include "gui/Cursor.h"
112113
#include "gui/DebugHud.h"
113114
#include "gui/Hud.h"
@@ -1748,6 +1749,8 @@ void ArxGame::updateInput() {
17481749
drawDebugCycleViews();
17491750
}
17501751

1752+
g_console.update();
1753+
17511754
#ifdef ARX_DEBUG
17521755
if(GInput->isKeyPressedNowPressed(Keyboard::Key_Pause)) {
17531756
if(!arxtime.is_paused()) {
@@ -2258,6 +2261,8 @@ void ArxGame::render() {
22582261
}
22592262
}
22602263

2264+
g_console.draw();
2265+
22612266
if(ARXmenu.currentmode == AMCM_OFF) {
22622267
ARX_SCRIPT_AllowInterScriptExec();
22632268
ARX_SCRIPT_EventStackExecute();

src/gui/Console.cpp

+262
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
/*
2+
* Copyright 2016 Arx Libertatis Team (see the AUTHORS file)
3+
*
4+
* This file is part of Arx Libertatis.
5+
*
6+
* Arx Libertatis 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+
* Arx Libertatis 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. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "gui/Console.h"
21+
22+
#include <algorithm>
23+
24+
#include "core/Config.h"
25+
#include "core/Core.h"
26+
#include "core/GameTime.h"
27+
#include "game/Entity.h"
28+
#include "game/EntityManager.h"
29+
#include "graphics/Draw.h"
30+
#include "graphics/DrawLine.h"
31+
#include "graphics/font/Font.h"
32+
#include "gui/Interface.h"
33+
#include "gui/Text.h"
34+
#include "input/Input.h"
35+
#include "math/Rectangle.h"
36+
#include "script/ScriptEvent.h"
37+
#include "util/Unicode.h"
38+
39+
// TODO Share some of this with the save name entry field
40+
41+
void ConsoleBuffer::append(const std::string & text) {
42+
43+
std::string::const_iterator i = text.begin();
44+
std::string::const_iterator end = text.end();
45+
46+
while(i != end) {
47+
48+
// Remember newline but don't apply until there is content
49+
if(m_pos < m_width + 1 && *i == '\n') {
50+
// Delay newline
51+
m_pos = m_width + 1;
52+
++i;
53+
}
54+
55+
if(i == end) {
56+
break;
57+
}
58+
59+
// Apply delayed newline
60+
if(m_pos >= m_width) {
61+
m_newline = false;
62+
m_line = (m_line + 1) % m_lines.size();
63+
m_lines[m_line].clear();
64+
m_pos = 0;
65+
}
66+
67+
// Find the next line break
68+
std::string::const_iterator line_end = i;
69+
size_t length = 0;
70+
while(line_end != end && *line_end != '\n'
71+
&& length < m_width - m_pos) {
72+
line_end = util::UTF8::next(line_end, end);
73+
++length;
74+
}
75+
76+
m_lines[m_line].append(i, line_end);
77+
m_pos += length;
78+
i = line_end;
79+
80+
}
81+
82+
}
83+
84+
bool ScriptConsole::keyPressed(Keyboard::Key key, KeyModifiers mod) {
85+
86+
switch(key) {
87+
88+
case Keyboard::Key_Escape: {
89+
close();
90+
return true;
91+
}
92+
93+
case Keyboard::Key_Enter: {
94+
execute();
95+
clear();
96+
return true;
97+
}
98+
99+
case Keyboard::Key_LeftCtrl:
100+
case Keyboard::Key_RightCtrl: {
101+
// We use control as a modifier, disable other uses while the console is open
102+
return true;
103+
}
104+
105+
default: break;
106+
}
107+
108+
if(mod.control) {
109+
switch(key) {
110+
111+
case Keyboard::Key_J: {
112+
execute();
113+
clear();
114+
return true;
115+
}
116+
117+
case Keyboard::Key_O: {
118+
execute();
119+
moveEnd();
120+
return true;
121+
}
122+
123+
default: break;
124+
}
125+
}
126+
127+
return BasicTextInput::keyPressed(key, mod);
128+
}
129+
130+
void ScriptConsole::open() {
131+
if(!m_enabled) {
132+
config.input.allowConsole = true;
133+
m_enabled = true;
134+
}
135+
}
136+
137+
void ScriptConsole::close() {
138+
if(m_enabled) {
139+
GInput->stopTextInput();
140+
m_enabled = false;
141+
}
142+
}
143+
144+
void ScriptConsole::execute() {
145+
146+
m_buffer.append("> " + text() + "\n");
147+
148+
Entity * entity = entities.player();
149+
150+
std::string script = command() + "\naccept\n";
151+
EERIE_SCRIPT es;
152+
es.size = script.size();
153+
es.data = const_cast<char *>(script.c_str());
154+
es.master = entity ? &entity->script : NULL;
155+
// TODO Some script commands (timers, etc.) store references to the script
156+
157+
long pos = 0;
158+
ScriptEvent::send(&es, SM_EXECUTELINE, std::string(), entity, std::string(), pos);
159+
}
160+
161+
void ScriptConsole::update() {
162+
163+
if(!m_enabled) {
164+
if(config.input.allowConsole && GInput->actionNowPressed(CONTROLS_CUST_CONSOLE)) {
165+
open();
166+
} else {
167+
return;
168+
}
169+
}
170+
171+
s32 lineHeight = hFontDebug->getLineHeight();
172+
Rect box = g_size;
173+
box.top += lineHeight * s32(m_buffer.lines());
174+
box.bottom = box.top + lineHeight;
175+
box.left += hFontDebug->getTextSize("> ").advance();
176+
GInput->startTextInput(box, this);
177+
178+
{
179+
static const PlatformDuration BlinkDuration = PlatformDurationMs(600);
180+
m_blinkTime += g_platformTime.lastFrameDuration();
181+
if(m_blinkTime > (BlinkDuration + BlinkDuration))
182+
m_blinkTime = PlatformDuration_ZERO;
183+
m_blink = m_blinkTime > BlinkDuration;
184+
}
185+
186+
}
187+
188+
void ScriptConsole::draw() {
189+
190+
if(!m_enabled) {
191+
return;
192+
}
193+
194+
UseRenderState state(render2D());
195+
196+
Color background = Color::black;
197+
background.a = 150;
198+
Color line = Color::gray(0.8f);
199+
Color selection = Color::yellow;
200+
selection.a = 40;
201+
202+
Rectf box = Rectf(g_size);
203+
box.bottom = box.top + (m_buffer.lines() + 1) * hFontDebug->getLineHeight() + 4;
204+
EERIEDrawBitmap(box, 0.f, NULL, background);
205+
206+
Vec2i pos = Vec2i_ZERO;
207+
for(size_t i = 0; i < m_buffer.lines(); i++) {
208+
hFontDebug->draw(pos, m_buffer.line(i), Color::white);
209+
pos.y += hFontDebug->getLineHeight();
210+
}
211+
212+
pos.y += 1;
213+
214+
drawLine(Vec2f(0, pos.y), Vec2f(g_size.width(), pos.y), 0.f, line);
215+
216+
pos.y += 2;
217+
218+
pos.x += hFontDebug->draw(pos, "> ", Color::green).advance();
219+
220+
std::string displayText = text();
221+
if(!editText().empty()) {
222+
displayText = displayText.substr(0, cursorPos()) + editText() + displayText.substr(cursorPos());
223+
}
224+
size_t displayCursorPos = cursorPos() + editCursorPos();
225+
226+
std::string::const_iterator begin = displayText.begin();
227+
std::string::const_iterator end = displayText.end();
228+
229+
// Highlight edit area
230+
if(!editText().empty()) {
231+
int left = hFontDebug->getTextSize(begin, begin + cursorPos()).advance();
232+
int right = hFontDebug->getTextSize(begin, begin + cursorPos() + editText().size()).advance();
233+
int height = hFontDebug->getLineHeight();
234+
Rectf box = Rectf(pos + Vec2i(left, 0), right - left, height);
235+
EERIEDrawBitmap(box, 0.f, NULL, selection);
236+
}
237+
238+
// Draw text
239+
s32 x = hFontDebug->draw(pos.x, pos.y, begin, end, Color::white).next();
240+
241+
// Draw cursor
242+
if(m_blink) {
243+
int cursor = x;
244+
if(cursorPos() != displayText.size()) {
245+
cursor = pos.x + hFontDebug->getTextSize(begin, begin + displayCursorPos).next();
246+
}
247+
drawLine(Vec2f(cursor, pos.y), Vec2f(cursor, pos.y + hFontDebug->getLineHeight()), 0.f, line);
248+
if(editCursorLength() > 0) {
249+
int end = pos.x + hFontDebug->getTextSize(begin, begin + displayCursorPos + editCursorLength()).next();
250+
drawLine(Vec2f(end, pos.y), Vec2f(end, pos.y + hFontDebug->getLineHeight()), 0.f, line);
251+
}
252+
}
253+
254+
pos.y += hFontDebug->getLineHeight();
255+
256+
pos.y += 1;
257+
258+
drawLine(Vec2f(0, pos.y), Vec2f(g_size.width(), pos.y), 0.f, line);
259+
260+
}
261+
262+
ScriptConsole g_console;

0 commit comments

Comments
 (0)