Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/GAMEPLAY10
-rw-r--r--doc/TODO4
-rw-r--r--src/client/chat.cc9
-rw-r--r--src/client/client.cc22
-rw-r--r--src/client/client.h5
-rw-r--r--src/client/console.cc424
-rw-r--r--src/client/console.h77
-rw-r--r--src/client/input.cc69
-rw-r--r--src/client/view.cc17
-rw-r--r--src/core/application.cc4
-rw-r--r--src/core/gameserver.cc7
-rw-r--r--src/server/console.cc63
-rw-r--r--src/server/console.h13
-rw-r--r--src/server/server.cc4
-rw-r--r--src/sys/consoleinterface.cc288
-rw-r--r--src/sys/consoleinterface.h150
-rw-r--r--src/sys/sys.cc32
-rw-r--r--src/sys/sys.h10
-rw-r--r--src/ui/container.cc4
-rw-r--r--src/ui/input.cc8
-rw-r--r--src/ui/paint.cc4
-rw-r--r--src/ui/paint.h10
-rw-r--r--src/ui/ui.cc37
-rw-r--r--src/ui/ui.h2
-rw-r--r--src/ui/widget.cc14
-rw-r--r--src/ui/window.cc9
-rw-r--r--src/ui/window.h5
27 files changed, 649 insertions, 652 deletions
diff --git a/doc/GAMEPLAY b/doc/GAMEPLAY
index 5379654..2f2160b 100644
--- a/doc/GAMEPLAY
+++ b/doc/GAMEPLAY
@@ -31,11 +31,15 @@ Universe
A basic description of the universe, how it is organised and who lives there.
The universe is a collection of stand-alone star systems. Each star system
- is a small world on it's on. The only direct interaction between systems
+ is a small world on its on. The only direct interaction between systems
is a player traveling between them. The background story should provide
(some of the) star systems and their relations. The universe is a static.
Players can not intentionally destroyed planets, stations or other objects.
+ The Project::OSiRiON universe is an open universe. This means players are
+ free to travel around and visit the places they want, but this does not
+ mean the player will be welcomed anywhere he goes.
+
Destructable objects are probably part of a mission, will respawn later or
have some other special meaning.
@@ -87,7 +91,7 @@ Traveling
Neither of these engines will allow the player the leave the star system.
Interstellar travel is only possible using a hyperdrive. A hyperdrive is an
- expensive piece of equipment that has massive power requirements. Only very
+ expensive piece of equipment with a massive power requirement. Only very
large ships will be capable of carrying a hyperspace jump drive.
Interstellar travel for the common men is possible through the use
@@ -108,7 +112,7 @@ Traveling
Jump gates are built in the vicinity of stable intersection faults and thus have a fixed
destination.
- Ships equiped with a hyoerdrive work on the same principle. They seek out a sensitive
+ Ships equiped with a hyperdrive work on the same principle. They seek out a sensitive
spot in the hyperspace field and fold local space to punch a hole through the other side.
This has several major consequences: a pilot has to determine has destination by finding
a good departure point in local space. Also, only a small number of connections between
diff --git a/doc/TODO b/doc/TODO
index b851d74..b87a3f2 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -45,7 +45,7 @@ core:
toggle func to toggle a bool cvar (ok)
game module loading/unloading (breaks network proto, server must send module type)
- zone changes, clear entities
+ zone changes, clear entities (ok)
network:
UDP datagrams (ok)
@@ -58,7 +58,7 @@ network:
round thrust/speed on 1/100 (ok)
protocol description (incomplete)
- private chat
+ private chat (ok)
zone/system chat (requires zones)
group/clan chat (requires groups)
rcon authentication, rcon command, servers must be able to disable rcon
diff --git a/src/client/chat.cc b/src/client/chat.cc
index 87ba437..6d294ba 100644
--- a/src/client/chat.cc
+++ b/src/client/chat.cc
@@ -6,15 +6,14 @@
#include "auxiliary/functions.h"
#include "client/chat.h"
-#include "client/client.h"
-#include "client/console.h"
#include "core/core.h"
-#include "render/render.h"
#include "sys/sys.h"
#include "ui/ui.h"
namespace client {
+const size_t DEFAULT_MAX_HISTO_LINES = 512;
+
Chat::Chat(ui::Widget *parent) : ui::Window(parent)
{
set_label("chat");
@@ -83,7 +82,7 @@ bool Chat::on_keypress(const int key, const unsigned int modifier)
(*history_pos).assign(chat_input->text());
// store input into history
- while (history.size() >= MAXHISTOLINES) {
+ while (history.size() >= DEFAULT_MAX_HISTO_LINES) {
history.pop_front();
}
@@ -127,7 +126,7 @@ bool Chat::on_keypress(const int key, const unsigned int modifier)
void Chat::event_draw()
{
- if (!client()->connected()) {
+ if (!core::application()->connected()) {
hide();
return;
}
diff --git a/src/client/client.cc b/src/client/client.cc
index ae4f232..200becd 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -58,6 +58,11 @@ void func_ui_chat(std::string const &args)
}
}
+void func_ui_console(std::string const &args)
+{
+ client()->console()->toggle();
+}
+
//--- public ------------------------------------------------------
void client_main(int count, char **arguments)
@@ -93,7 +98,6 @@ void Client::init(int count, char **arguments)
// initialize core
core::Cvar::sv_dedicated = core::Cvar::set("sv_private", "0");
core::Application::init(count, arguments);
- Console::init();
// client variables
core::Cvar *cvar = 0;
@@ -114,7 +118,9 @@ void Client::init(int count, char **arguments)
// initialize user interface
ui::init();
+
client_view = new View(ui::root());
+ client_console = new Console(ui::root());
// Initialize the video subsystem
if (!video::init()) {
@@ -136,6 +142,9 @@ void Client::init(int count, char **arguments)
func = core::Func::add("ui_chat", func_ui_chat);
func->set_info("toggle chat window");
+ func = core::Func::add("ui_console", func_ui_console);
+ func->set_info("toggle console on or off");
+
//func = core::Func::add("snd_restart", (core::FuncPtr) func_snd_restart);
//func->set_info("restart audio subsystem");
}
@@ -149,10 +158,8 @@ void Client::run()
Uint32 client_current_timestamp = 0;
Uint32 client_previous_timestamp = 0;
-
-
- console()->flush();
- console()->clear_notify();
+
+ //console()->clear_notify();
while (true) {
// current time in microseconds
@@ -222,12 +229,11 @@ void Client::shutdown()
core::Func::remove("r_restart");
core::Func::remove("ui_chat");
+ core::Func::remove("ui_console");
//core::Func::remove("snd_restart");
audio::shutdown();
- Console::shutdown();
-
input::shutdown();
video::shutdown();
@@ -290,7 +296,7 @@ void Client::notify_message(core::Message::Channel const channel, std::string co
}
con_print << message << std::endl;
- console()->notify(message);
+ //console()->notify(message);
}
/* FIXME
diff --git a/src/client/client.h b/src/client/client.h
index dc70e16..6e19848 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -8,6 +8,7 @@
#define __INCLUDED_CLIENT_H__
#include "core/application.h"
+#include "client/console.h"
#include "client/view.h"
/// client part of the engine
@@ -50,12 +51,16 @@ public:
/// the main client view
inline View *view() { return client_view; }
+ /// the client console
+ inline Console *console() { return client_console; }
+
protected:
/// run a client frame
virtual void frame(float seconds);
private:
View *client_view;
+ Console *client_console;
};
diff --git a/src/client/console.cc b/src/client/console.cc
index 47f95f7..0ab0767 100644
--- a/src/client/console.cc
+++ b/src/client/console.cc
@@ -21,97 +21,112 @@
namespace client {
-Console client_console;
+const float DEFAULT_CONSOLE_HEIGHT = 0.7f;
+const size_t DEFAULT_MAX_HISTO_LINES = 512;
-Console *console() {
- return &client_console;
-}
-
-//--- public ------------------------------------------------------
-
-void Console::init()
+/* -- ConsoleBuffer ------------------------------------------------ */
+ConsoleBuffer::ConsoleBuffer()
{
con_print << "^BInitializing console..." << std::endl;
- console()->load_history();
+
}
-void Console::shutdown()
+ConsoleBuffer::~ConsoleBuffer()
{
con_print << "^BShutting down console..." << std::endl;
- console()->save_history();
}
+// the global console buffer object
+ConsoleBuffer Console::con_buffer;
+
//--- Console -----------------------------------------------------
-Console::Console()
+Console::Console(ui::Widget *parent) : ui::Window(parent)
{
- clear();
-}
+ set_visible(false);
+ set_border(false);
+ set_background(true);
+ set_label("console");
-Console::~Console()
-{
- history.clear();
-}
+ //clear_notify();
+ load_history();
-void Console::clear()
-{
- console_visible = false;
- console_scroll = 0;
+ console_scroll = 0;
history.clear();
history.push_back("");
history_pos = history.rbegin();
- input_pos = 0;
-
- clear_notify();
+ console_input = new ui::Input(this);
+ console_input->set_focus();
+ console_input->set_border(false);
+ console_input->set_background(false);
}
-void Console::draw(bool draw_ui_notifications) {
- flush();
- if (visible())
- draw_console();
- else if (draw_ui_notifications)
- draw_notify();
+Console::~Console()
+{
+ save_history();
+ history.clear();
}
-void Console::toggle()
+void Console::show()
{
- console_visible = !console_visible;
-
- if (console_visible) {
- console_scroll = 0;
- input_pos = 0;
+ ui::Window::show();
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(SDL_ENABLE);
- history_pos = history.rbegin();
- (*history_pos).clear();
+ console_scroll = 0;
+ history_pos = history.rbegin();
+ (*history_pos).clear();
+ console_input->set_text((*history_pos));
- SDL_WM_GrabInput(SDL_GRAB_OFF);
- SDL_ShowCursor(SDL_ENABLE);
- } else {
- SDL_WM_GrabInput(SDL_GRAB_ON);
- SDL_ShowCursor(SDL_DISABLE);
- }
+ audio::play("ui/console");
+}
- //setkeyboardmode(console()->visible() || (core::application()->connected() && chat::visible()));
+void Console::hide()
+{
+ ui::Window::hide();
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(SDL_DISABLE);
audio::play("ui/console");
}
-void Console::keypressed(unsigned int key)
+void Console::toggle()
+{
+ if (visible())
+ hide();
+ else
+ show();
+}
+
+bool Console::on_keypress(const int key, const unsigned int modifier)
{
// number of lines to scroll
const size_t scroll_offset = 3;
- std::deque<std::string>::reverse_iterator upit;
+ Text::reverse_iterator upit;
switch( key ) {
+
+ case SDLK_ESCAPE:
+ if (visible()) {
+ hide();
+ return true;
+ } else {
+ return false;
+ }
+ break;
+/*
case SDLK_TAB:
core::CommandBuffer::complete( (*history_pos), input_pos);
+ return true;
break;
+*/
case SDLK_RETURN:
- if ((*history_pos).size()) {
- // store input into history
- while (history.size() >= MAXHISTOLINES) {
+ if (console_input->text().size()) {
+ // store input in history
+ (*history_pos).assign(console_input->text());
+ while (history.size() >= DEFAULT_MAX_HISTO_LINES) {
history.pop_front();
}
@@ -121,132 +136,88 @@ void Console::keypressed(unsigned int key)
history.push_back("");
history_pos = history.rbegin();
- input_pos = 0;
+ console_input->set_text((*history_pos));
}
+ return true;
break;
+
case SDLK_UP:
upit = history_pos;
++upit;
if (upit != history.rend()) {
history_pos = upit;
- input_pos = (*history_pos).size();
+ console_input->set_text((*history_pos));
}
+ return true;
break;
case SDLK_DOWN:
if (history_pos != history.rbegin()) {
--history_pos;
- input_pos = (*history_pos).size();
- }
- break;
- case SDLK_HOME:
- input_pos = 0;
- break;
- case SDLK_END:
- input_pos = (*history_pos).size();
- break;
- case SDLK_LEFT:
- if (input_pos > 0)
- input_pos--;
- break;
- case SDLK_RIGHT:
- if (input_pos < (*history_pos).size())
- input_pos++;
- break;
- case SDLK_DELETE:
- if ((*history_pos).size() && input_pos < (*history_pos).size()) {
- (*history_pos).erase(input_pos, 1);
- }
- break;
- case SDLK_BACKSPACE:
- if ((*history_pos).size() && input_pos) {
- (*history_pos).erase(input_pos-1, 1);
- input_pos--;
+ console_input->set_text((*history_pos));
}
+ return true;
break;
case SDLK_PAGEUP:
console_scroll += scroll_offset;
- if (console_scroll > consoleinterface_text.size())
- console_scroll = consoleinterface_text.size();
+ if (console_scroll > log().size())
+ console_scroll = log().size();
+ return true;
break;
+
case SDLK_PAGEDOWN:
if (console_scroll > scroll_offset)
console_scroll -= scroll_offset;
else
console_scroll = 0;
- break;
- default:
- if ((key >= 32 ) && (key <175) && ((*history_pos).size() < MAXCMDSIZE)) {
- if (input_pos == (*history_pos).size())
- (*history_pos) += (char)key;
- else
- (*history_pos).insert(input_pos, 1, (char)key);
- input_pos++;
- }
+ return true;
break;
}
-
+ return false;
}
-void Console::save_history()
+void Console::event_draw()
{
- if (history.size() <= 1)
- return;
-
- std::string filename(filesystem::writedir());
- filename.append("history.txt");
- std::ofstream ofs(filename.c_str());
-
- if (!ofs.is_open()) {
- con_warn << "Could not write " << filename << std::endl;
- return;
- }
- std::deque<std::string>::iterator it;
- size_t l = 1;
- for (it = history.begin(); it != history.end(); it++) {
- if (l < history.size())
- ofs << (*it) << std::endl;
- l++;
+ if (core::application()->connected()) {
+ set_size(parent()->size().width(), parent()->size().height() * DEFAULT_CONSOLE_HEIGHT);
+ } else {
+ set_size(parent()->size());
}
- ofs.close();
+ ui::Window::event_draw();
}
-void Console::load_history()
+void Console::draw()
{
- std::string filename(filesystem::writedir());
- filename.append("history.txt");
- std::ifstream ifs(filename.c_str(), std::ifstream::in);
-
- if (!ifs.is_open()) {
- con_warn << "Could not read " << filename << std::endl;
- return;
- }
+ console_input->set_size(this->width(), font()->height());
+ console_input->set_location(0, this->height()-font()->height());
- history.clear();
- char line[MAXCMDSIZE];
- while (ifs.getline(line, MAXCMDSIZE-1)) {
- history.push_back(line);
- }
+ draw_background();
+ draw_border();
- ifs.close();
+ render::Text::setfont(font()->name().c_str(), font()->width(), font()->height());
+ render::gl::enable(GL_TEXTURE_2D);
- history.push_back("");
- history_pos = history.rbegin();
- input_pos = 0;
-}
+ // draw version below the bottom of the console
+ std::string version(core::name());
+ version += ' ';
+ version.append(core::version());
+ render::gl::color(0.0f, 1.0f, 0.0f, 0.5f);
+ render::Text::draw(width()-font()->width()*(version.size()+1), height()-font()->height()-4, version);
-void Console::draw_notify()
-{
- using namespace render;
+ // draw the console log()
+ if (console_scroll > log().size())
+ console_scroll = log().size();
+
+ size_t height = (size_t) (this->height() / font()->height()) -1;
+ size_t width = (size_t) ((this->width()-8) / font()->width());
+ size_t bottom = log().size() - console_scroll;
+ size_t current_line = 0;
- // draw notifications
- size_t width = (size_t) ((video::width-8) / Text::fontwidth());
- size_t n = notify_pos % MAXNOTIFYLINES;
- float h = video::height/2;
- for (size_t l = 0; l < MAXNOTIFYLINES; l++) {
- if (notify_text[n].size() > 2 && notify_time[n] + 5 > core::application()->time()) {
- std::string linedata(notify_text[n]);
+ Text lines;
+ for (Text::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) {
+ if (current_line >= bottom - height) {
+ std::string linedata(*it);
linedata += '\n';
std::string word;
@@ -258,7 +229,6 @@ void Console::draw_notify()
const char *c = linedata.c_str();
char pen = 'N';
char wordpen = 'N';
- Text::setcolor('N');
while (*c) {
@@ -275,8 +245,7 @@ void Console::draw_notify()
if (line_length + word_length > width) {
if (line.size()) {
- Text::draw(4, h, line);
- h += Text::fontheight();
+ lines.push_back(line);
line.clear();
line += '^';
line += wordpen;
@@ -293,8 +262,7 @@ void Console::draw_notify()
// new line
if (*c == '\n' ) {
- Text::draw(4, h, line);
- h += Text::fontheight();
+ lines.push_back(line);
line.clear();
line_length = 0;
// new word
@@ -311,8 +279,7 @@ void Console::draw_notify()
if (word_length == width) {
if (line.size()) {
- Text::draw(4, h, line);
- h += Text::fontheight();
+ lines.push_back(line);
line.clear();
line += '^';
line += wordpen;
@@ -332,49 +299,78 @@ void Console::draw_notify()
}
}
- n = (n+1) % MAXNOTIFYLINES;
+ current_line++;
+ }
+
+ float y = this->height()-2*font()->height()-4;
+ render::Text::setcolor('N');
+ for (Text::reverse_iterator rit = lines.rbegin(); (y >= 4) && (rit != lines.rend()); ++rit) {
+ render::Text::draw(4, y, (*rit));
+ y -= font()->height();
}
+
+ render::gl::disable(GL_TEXTURE_2D);
+
}
-void Console::draw_console()
+void Console::save_history()
{
- using namespace render;
+ if (history.size() <= 1)
+ return;
- float con_height = 0.70f;
-
- gl::disable(GL_TEXTURE_2D);
+ std::string filename(filesystem::writedir());
+ filename.append("history.txt");
+ std::ofstream ofs(filename.c_str());
- // draw the transparent console background
- gl::color(0.0f, 0.0f, 0.0f, 0.5f);
- gl::begin(gl::Quads);
- gl::vertex(0.0f, 0.0f, 0.0f);
- gl::vertex(video::width, 0.0f,0.0f);
- gl::vertex(video::width,video::height*con_height,0.0f);
- gl::vertex(0,video::height*con_height,0.0f);
- gl::end();
+ if (!ofs.is_open()) {
+ con_warn << "Could not write " << filename << std::endl;
+ return;
+ }
+ Text::iterator it;
+ size_t l = 1;
+ for (it = history.begin(); it != history.end(); it++) {
+ if (l < history.size())
+ ofs << (*it) << std::endl;
+ l++;
+ }
- gl::enable(GL_TEXTURE_2D);
+ ofs.close();
+}
- // draw version below the bottom of the console
- std::string version(core::name());
- version += ' ';
- version.append(core::version());
- gl::color(0.0f, 1.0f, 0.0f, 0.5f);
- Text::draw(video::width-Text::fontwidth()*(version.size()+1), video::height*con_height-Text::fontheight()-4, version);
+void Console::load_history()
+{
+ std::string filename(filesystem::writedir());
+ filename.append("history.txt");
+ std::ifstream ifs(filename.c_str(), std::ifstream::in);
- // draw the console consoleinterface_text
- if (console_scroll > consoleinterface_text.size())
- console_scroll = consoleinterface_text.size();
-
- size_t height = (size_t) (video::height * con_height / Text::fontheight()) -1;
- size_t width = (size_t) ((video::width-8) / Text::fontwidth());
- size_t bottom = consoleinterface_text.size() - console_scroll;
- size_t current_line = 0;
+ if (!ifs.is_open()) {
+ con_warn << "Could not read " << filename << std::endl;
+ return;
+ }
- std::deque<std::string> lines;
- for (std::deque<std::string>::iterator it = consoleinterface_text.begin(); it != consoleinterface_text.end() && current_line < bottom; it++) {
- if (current_line >= bottom - height) {
- std::string linedata(*it);
+ history.clear();
+ char line[MAXCMDSIZE];
+ while (ifs.getline(line, MAXCMDSIZE-1)) {
+ history.push_back(line);
+ }
+
+ ifs.close();
+
+ history.push_back("");
+ history_pos = history.rbegin();
+}
+
+
+/*
+void Console::draw_notify()
+{
+ // draw notifications
+ size_t width = (size_t) ((width()-8) / font()->width());
+ size_t n = notify_pos % MAXNOTIFYLINES;
+ float h = height()/2;
+ for (size_t l = 0; l < MAXNOTIFYLINES; l++) {
+ if (notify_text[n].size() > 2 && notify_time[n] + 5 > core::application()->time()) {
+ std::string linedata(notify_text[n]);
linedata += '\n';
std::string word;
@@ -386,6 +382,7 @@ void Console::draw_console()
const char *c = linedata.c_str();
char pen = 'N';
char wordpen = 'N';
+ render::Text::setcolor('N');
while (*c) {
@@ -402,7 +399,8 @@ void Console::draw_console()
if (line_length + word_length > width) {
if (line.size()) {
- lines.push_back(line);
+ render::Text::draw(4, h, line);
+ h += font()->width();
line.clear();
line += '^';
line += wordpen;
@@ -419,7 +417,8 @@ void Console::draw_console()
// new line
if (*c == '\n' ) {
- lines.push_back(line);
+ render::Text::draw(4, h, line);
+ h += font()->width();
line.clear();
line_length = 0;
// new word
@@ -436,7 +435,8 @@ void Console::draw_console()
if (word_length == width) {
if (line.size()) {
- lines.push_back(line);
+ render::Text::draw(4, h, line);
+ h += font()->width();
line.clear();
line += '^';
line += wordpen;
@@ -456,65 +456,8 @@ void Console::draw_console()
}
}
- current_line++;
- }
-
- float y = video::height*con_height-2*Text::fontheight()-4;
- Text::setcolor('N');
- for (std::deque<std::string>::reverse_iterator rit = lines.rbegin(); (y >= 4) && (rit != lines.rend()); ++rit) {
- Text::draw(4, y, (*rit));
- y -= Text::fontheight();
- }
-
-
- // draw the console input
- y = video::height*con_height - Text::fontheight() - 4;
- Text::draw(4, y, "^B>");
-
- std::string firstpart((*history_pos).substr(0, input_pos));
- size_t draw_width = 0;
- const char *c = firstpart.c_str();
-
- while (*c) {
- if (aux::is_color_code(c)) {
- c++;
- } else {
- draw_width++;
- }
- c++;
- }
-
- c = firstpart.c_str();
- while (*c && draw_width > width - 2) {
- if (aux::is_color_code(c)) {
- c++;
- Text::setcolor(*c);
- } else {
- draw_width--;
- }
- c++;
- }
-
- if (*c) {
- Text::draw(4+Text::fontwidth(), y, c);
- }
-
- if (input_pos < (*history_pos).size()) {
- // FIXME limit to width
- if (input_pos > 1 && aux::is_color_code((*history_pos).c_str() + input_pos -1)) {
- Text::setcolor((*history_pos)[input_pos]);
- }
- c = (*history_pos).c_str() + input_pos;
- Text::draw(4+Text::fontwidth()*(draw_width+1), y, c);
- }
-
- // draw cursor
- if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) {
- std::string cursor("^B");
- cursor += (char) 11;
- Text::draw(4+Text::fontwidth()*(draw_width+1), y , cursor);
+ n = (n+1) % MAXNOTIFYLINES;
}
-
}
@@ -534,6 +477,7 @@ void Console::notify(std::string const & message)
notify_time[notify_pos] = core::application()->time();
notify_pos = (notify_pos+1) % MAXNOTIFYLINES;
}
+*/
} // namespace client
diff --git a/src/client/console.h b/src/client/console.h
index e280e9d..4b2df20 100644
--- a/src/client/console.h
+++ b/src/client/console.h
@@ -8,35 +8,31 @@
#define __INCLUDED_CLIENT_CONSOLE_H__
#include "sys/consoleinterface.h"
+#include "ui/window.h"
+#include "ui/input.h"
namespace client {
-const size_t MAXNOTIFYLINES = 5;
-const size_t MAXHISTOLINES = 512;
+/* -- class ConsoleBuffer ------------------------------------------ */
-/// client console implementation
-class Console : public sys::ConsoleInterface {
+/// client console buffer
+/** stores incoming console messages
+ */
+class ConsoleBuffer : public sys::ConsoleInterface {
public:
- Console();
- virtual ~Console();
-
- /// add notification
- void notify(std::string const &message);
-
- /// clear notifications
- void clear_notify();
-
- /// draw client notifications or console text
- void draw(bool draw_ui_notifications);
+ ConsoleBuffer();
+ ~ConsoleBuffer();
+};
- /// toggle the console on or off
- void toggle();
+/* -- class Console ------------------------------------------------ */
- /// handle keyboard input
- void keypressed(unsigned int key);
+/// client system console widget
+class Console : public ui::Window {
+public:
+ typedef std::deque<std::string> Text;
- /// true of the console is visible
- inline bool visible() { return console_visible; }
+ Console(Widget *parent);
+ virtual ~Console();
/// load input history
void load_history();
@@ -44,37 +40,40 @@ public:
/// save input history
void save_history();
- /// clear console
- void clear();
+ /// show console
+ virtual void show();
- /// initialize client console
- static void init();
+ /// hide console
+ virtual void hide();
- /// shutdown the client console
- static void shutdown();
+ void toggle();
protected:
- void draw_console();
+ /// draw event
+ virtual void event_draw();
- void draw_notify();
+ /// draw the client console text
+ virtual void draw();
+
+ /// handle keypress events
+ virtual bool on_keypress(const int key, const unsigned int modifier);
private:
- // notifications
- size_t notify_pos;
- std::string notify_text[MAXNOTIFYLINES];
- float notify_time[MAXNOTIFYLINES];
+ inline Text & log() { return con_buffer.log(); }
// input history
- std::deque<std::string> history;
- std::deque<std::string>::reverse_iterator history_pos;
- size_t input_pos;
+ Text history;
+ Text::reverse_iterator history_pos;
- bool console_visible;
+ // scroll position
size_t console_scroll;
-};
+ // input widget
+ ui::Input *console_input;
-Console *console();
+ // console buffer
+ static ConsoleBuffer con_buffer;
+};
}
diff --git a/src/client/input.cc b/src/client/input.cc
index 22fd1c0..a72999e 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -133,11 +133,6 @@ void func_ui_control(std::string const &args)
audio::play("ui/control");
}
-void func_ui_console(std::string const &args)
-{
- console()->toggle();
-}
-
void func_view_next(std::string const &args)
{
if (core::application()->connected() && core::localcontrol()) {
@@ -268,12 +263,6 @@ void init()
input_mousedelay->set_info("[int] mouse click time-out in milliseconds");
core::Func *func = 0;
- func = core::Func::add("ui_console", func_ui_console);
- func->set_info("toggle console on or off");
-
- //func = core::Func::add("ui_chat", func_ui_chat);
- //func->set_info("toggle chatbox on or of");
-
func = core::Func::add("ui_control",func_ui_control);
func->set_info("toggle mouse control");
@@ -323,9 +312,7 @@ void shutdown()
core::Func::remove("screenshot");
- core::Func::remove("ui_console");
- //core::Func::remove("ui_control");
- //core::Func::remove("ui_chat");
+ core::Func::remove("ui_control");
core::Func::remove("ui_view");
keyboard->save_binds();
@@ -489,38 +476,8 @@ Key::Modifier convert_SDL_modifier(int const sdlmodifier)
void key_pressed(Key *key)
{
- ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers);
-
- if (key->sym() == SDLK_ESCAPE) {
-
- if (console()->visible()) {
- console()->toggle();
- local_direction = 0.0f;
- local_pitch = 0.0f;
- local_roll = 0.0f;
-
- render::Camera::set_direction(0.0f);
- render::Camera::set_pitch(0.0f);
-
- } else {
- if (ui::root()->active()) {
- ui::root()->hide_menu();
- local_direction = 0.0f;
- local_pitch = 0.0f;
- local_roll = 0.0f;
-
- render::Camera::set_direction(0.0f);
- render::Camera::set_pitch(0.0f);
- } else {
- if (core::application()->connected()) {
- ui::root()->show_menu("game");
- } else {
- ui::root()->show_menu("main");
- }
- }
- }
-
- } else if (key->bind(Key::None).compare("ui_console") == 0) {
+ if (key->bind(Key::None).compare("ui_console") == 0) {
+ // FIXME bah
local_direction = 0.0f;
local_pitch = 0.0f;
local_roll = 0.0f;
@@ -528,21 +485,11 @@ void key_pressed(Key *key)
render::Camera::set_direction(0.0f);
render::Camera::set_pitch(0.0f);
- console()->toggle();
+ client()->console()->toggle();
- } else if (console()->visible()) {
- // send key events to the console
- if (key->sym() < 512)
- console()->keypressed(Keyboard::translate_keysym(key->sym(), keyboard_modifiers));
+ } else if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) {
+ return;
- } else if (ui::root()->active()) {
-/* ui::root()->input_key(true, key->sym(), keyboard_modifiers);
-*/
-/* } else if (chat::visible()) {
- // send key events to the chat box
- if (key->sym() < 512)
- chat::keypressed(translate_keysym(key->sym(), keyboard_modifiers));
-*/
} else if (core::application()->connected() && core::localcontrol()) {
char c = key->bind(convert_SDL_modifier(keyboard_modifiers)).c_str()[0];
@@ -553,6 +500,7 @@ void key_pressed(Key *key)
// normal bind
core::cmd() << key->bind(convert_SDL_modifier(keyboard_modifiers)) << "\n";
}
+
} else if (core::application()->connected()) {
char c = key->bind(convert_SDL_modifier(keyboard_modifiers)).c_str()[0];
@@ -561,7 +509,6 @@ void key_pressed(Key *key)
core::cmd() << key->bind(convert_SDL_modifier(keyboard_modifiers)) << "\n";
}
}
-
}
void key_released(Key *key)
@@ -813,7 +760,7 @@ void frame(float seconds)
mouse_deadzone = false;
if (core::application()->connected() && core::localcontrol()) {
- mouse_control = !console()->visible() && ((input_mousecontrol->value() > 0) || (mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time())));
+ mouse_control = client()->console()->hidden() && !ui::root()->active() && ((input_mousecontrol->value() > 0) || (mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time())));
if (mouse_control && joystick_control && ((render::Camera::mode() == render::Camera::Track) || (render::Camera::mode() == render::Camera::Cockpit))) {
if (!(mouse_control_override && (mouse_control_override_time + (input_mousedelay->value() / 1000.0f) < core::application()->time()))) {
diff --git a/src/client/view.cc b/src/client/view.cc
index 463d254..a8d9c4f 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -243,12 +243,6 @@ void View::draw()
} else {
view_center->set_visible(false);
}
-
- if (!ui::root()->active() && !has_input_focus()) {
- set_focus();
- }
-
-
}
/* -- namespace view ----------------------------------------------- */
@@ -628,7 +622,7 @@ void draw_hud()
void draw_cursor()
{
- if (console()->visible())
+ if (client()->console()->visible())
return;
float angle = 0;
@@ -731,9 +725,6 @@ void frame(float elapsed)
{
using namespace render;
- // flush console messages
- console()->flush();
-
// Clear the color and depth buffers.
gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -778,11 +769,7 @@ void frame(float elapsed)
draw_cursor();
}
- // draw console or notifications
- Text::setfont("gui", 12, 18);
-
- console()->draw((bool) draw_ui->value());
-
+
gl::disable(GL_TEXTURE_2D);
gl::disable(GL_BLEND);
}
diff --git a/src/core/application.cc b/src/core/application.cc
index db4f338..f98d44e 100644
--- a/src/core/application.cc
+++ b/src/core/application.cc
@@ -230,7 +230,7 @@ void Application::init(int count, char **arguments)
Cvar::con_ansi = Cvar::get("con_ansi", "1", Cvar::Archive);
#endif
Cvar::con_ansi->set_info("[bool] console ANSI colors");
- sys::ConsoleInterface::instance()->set_ansi(Cvar::con_ansi->value());
+ sys::set_ansi(Cvar::con_ansi->value());
#ifdef _WIN32
// Initialize win32 socket library
@@ -302,8 +302,6 @@ void Application::shutdown()
void Application::quit(int status)
{
- console()->flush();
-
sys::quit(status);
}
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 46c3624..e42d1b2 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -484,7 +484,6 @@ void GameServer::exec(Player *player, std::string const & cmdline)
Func *function = Func::find(command);
if (function ) {
-
std::string args;
if (cmdline.size() > command.size() +1 )
args.assign(cmdline.substr(command.size()+1));
@@ -499,9 +498,9 @@ void GameServer::exec(Player *player, std::string const & cmdline)
console()->set_rcon(true);
function->exec(args);
- char line[MAXCMDSIZE];
- while(console()->buffer().getline(line, MAXCMDSIZE-1)) {
- send(player, std::string(line));
+ while(console()->rconbuf().size()) {
+ send(player, (*console()->rconbuf().begin()));
+ console()->rconbuf().pop_front();
}
// disable rcon buffering
diff --git a/src/server/console.cc b/src/server/console.cc
index 3f32337..ab03c58 100644
--- a/src/server/console.cc
+++ b/src/server/console.cc
@@ -59,14 +59,15 @@ void Console::init()
init_pair(4, COLOR_BLUE, -1);
init_pair(5, COLOR_CYAN, -1);
init_pair(6, COLOR_MAGENTA, -1);
- init_pair(7, -1, -1);
+ init_pair(7, COLOR_WHITE, -1);
+ init_pair(8, -1, -1);
}
console_initialized = true;
console_updated = true;
#endif // HAVE_CURSES
- con_print << "Initializing console..." << std::endl;
+ con_print << "^BInitializing console..." << std::endl;
#ifdef HAVE_CURSES
server_console.history.clear();
@@ -80,7 +81,7 @@ void Console::init()
void Console::shutdown()
{
- con_print << "Shutting down console..." << std::endl;
+ con_print << "^BShutting down console..." << std::endl;
#ifdef HAVE_CURSES
server_console.draw();
@@ -91,15 +92,20 @@ void Console::shutdown()
#endif
}
+Console::Console()
+{
+}
+
+Console::~Console()
+{
+}
+
#ifdef HAVE_CURSES
void Console::dump()
{
- flush();
-
// dump console content
- for (std::deque<std::string>::iterator it = consoleinterface_text.begin(); it != consoleinterface_text.end(); it++) {
- print_ansi((*it).c_str());
- std::cout << std::endl;
+ for (Text::iterator it = log().begin(); it != log().end(); it++) {
+ sys::ConsoleInterface::print((*it));
}
}
@@ -114,23 +120,9 @@ void Console::resize()
draw();
}
-void Console::flush()
+void Console::print(const std::string & text)
{
- if (rcon())
- return;
-
- char line[MAXCMDSIZE];
-
- while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) {
-
- while (consoleinterface_text.size() >= sys::MAXCONLINES) {
- consoleinterface_text.pop_front();
- }
- consoleinterface_text.push_back(std::string(line));
- console_updated = true;
- }
-
- consoleinterface_buffer.clear();
+ console_updated = true;
}
void Console::set_color(const char *color_code)
@@ -143,10 +135,10 @@ void Console::set_color(const char *color_code)
if (aux::is_base_color_code(color_code)) {
// base colors
- // Black=0, Red=1, Green=2, Yellow=3, Blue=4, Cyan=5, Magenta=6, White=7
+ // Default=0, Red=1, Green=2, Yellow=3, Blue=4, Cyan=5, Magenta=6, White=7
color = *(color_code+1) - '0';
- if (color == 3 || color == 0)
+ if (color == 3 || color == 7)
bold = true;
else
bold = false;
@@ -223,15 +215,15 @@ void Console::draw_text()
if ((w < 3) || (h < 3))
return;
- std::deque<std::string> lines;
+ Text lines;
int height = stdwin->_maxy - 1;
int width = stdwin->_maxx - 1;
- int bottom = (int) consoleinterface_text.size() - console_scroll;
+ int bottom = (int) log().size() - console_scroll;
int current_line = 0;
// parse console text, wrap long lines
- for (std::deque<std::string>::iterator it = consoleinterface_text.begin(); it != consoleinterface_text.end() && current_line < bottom; it++) {
+ for (Text::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) {
if (current_line >= bottom - height) {
std::string linedata(*it);
linedata += '\n';
@@ -322,7 +314,7 @@ void Console::draw_text()
color_set(0, NULL);
attroff(A_BOLD);
- for (std::deque<std::string>::reverse_iterator rit = lines.rbegin(); (y > 0) && (rit != lines.rend()); ++rit) {
+ for (Text::reverse_iterator rit = lines.rbegin(); (y > 0) && (rit != lines.rend()); ++rit) {
const char *c = (*rit).c_str();
int x = 0;
@@ -366,20 +358,16 @@ void Console::draw()
wrefresh(stdwin);
console_updated = false;
- console_lastrefresh = 0;
}
void Console::frame(float seconds)
{
const size_t scroll_offset = 3;
- std::deque<std::string>::reverse_iterator upit;
-
- flush();
+ Text::reverse_iterator upit;
if (!console_initialized)
return;
- console_lastrefresh += seconds;
bool input_updated = false;
int key = wgetch(stdwin);
@@ -450,8 +438,8 @@ void Console::frame(float seconds)
break;
} else if (key == KEY_PPAGE) {
console_scroll += scroll_offset;
- if (console_scroll > consoleinterface_text.size())
- console_scroll = consoleinterface_text.size();
+ if (console_scroll > log().size())
+ console_scroll = log().size();
console_updated = true;
break;
} else if (key == KEY_NPAGE) {
@@ -487,6 +475,7 @@ void Console::frame(float seconds)
if (input_updated) {
// move the cursor to input position
move(stdwin->_maxy, 1 + input_pos);
+ wrefresh(stdwin);
}
}
}
diff --git a/src/server/console.h b/src/server/console.h
index bf77ecd..59d65d9 100644
--- a/src/server/console.h
+++ b/src/server/console.h
@@ -13,14 +13,15 @@ namespace server {
class Console : public sys::ConsoleInterface {
public:
+ Console();
+ ~Console();
+
/// initialize the server console
static void init();
/// shutdown the server console
static void shutdown();
#ifdef HAVE_CURSES
- /// flush buffered messages
- virtual void flush();
/// resize the console
virtual void resize();
/// run one console frame
@@ -39,16 +40,16 @@ protected:
void draw_input();
/// dump console content to cout
void dump();
+ /// print one line of text (do nothing)
+ virtual void print(const std::string & text);
private:
/// set ncurses drawing color
void set_color(const char *color_code);
- /// timestamp for screen refresh timeout
- float console_lastrefresh;
// input history
- std::deque<std::string> history;
- std::deque<std::string>::reverse_iterator history_pos;
+ Text history;
+ Text::reverse_iterator history_pos;
size_t input_pos;
size_t console_scroll;
diff --git a/src/server/server.cc b/src/server/server.cc
index 27cf6bd..f08ca6c 100644
--- a/src/server/server.cc
+++ b/src/server/server.cc
@@ -56,7 +56,7 @@ void main(int count, char **arguments)
void Server::init(int count, char **arguments)
{
- con_print << "Initializing server..." << std::endl;
+ con_print << "^BInitializing server..." << std::endl;
core::Cvar::sv_private = core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly);
core::Application::init(count, arguments);
@@ -92,7 +92,7 @@ void Server::run()
void Server::shutdown()
{
- con_print << "Shutting down server..." << std::endl;
+ con_print << "^BShutting down server..." << std::endl;
float ratio = 0;
if (core::Stats::network_uncompressed_bytes_sent > 0)
diff --git a/src/sys/consoleinterface.cc b/src/sys/consoleinterface.cc
index 073f34b..284a48d 100644
--- a/src/sys/consoleinterface.cc
+++ b/src/sys/consoleinterface.cc
@@ -6,187 +6,213 @@
#include "sys/consoleinterface.h"
-#include <iostream>
-
-#include <stdlib.h>
-
namespace sys
{
-ConsoleInterface *ConsoleInterface::consoleinterface_instance = 0;
-
-ConsoleInterface::ConsoleInterface()
-{
- consoleinterface_ansi = true;
- if (consoleinterface_instance) {
- std::cerr << "multiple sys::ConsoleInterface instances!" << std::endl;
- sys::quit(2);
- }
-
- consoleinterface_rcon = false;
-
- consoleinterface_instance = this;
- consoleinterface_text.clear();
- consoleinterface_buffer.clear();
-}
-
-ConsoleInterface::~ConsoleInterface()
-{
- consoleinterface_instance = 0;
-}
-
-ConsoleInterface *ConsoleInterface::instance()
-{
- return consoleinterface_instance;
-}
-
-std::ostream & ConsoleInterface::messagestream()
-{
- flush();
- return (consoleinterface_buffer << "^N");
-}
+const size_t DEFAULT_LOGSIZE = 2048;
-std::ostream & ConsoleInterface::warningstream()
-{
- flush();
- return (consoleinterface_buffer << "^W");
-}
+/* -- ANSI color code support -------------------------------------- */
-std::ostream & ConsoleInterface::errorstream()
-{
- flush();
- return (consoleinterface_buffer << "^R");
-}
+bool con_ansicolor = false;
-std::ostream & ConsoleInterface::debugstream()
+bool ansi()
{
- flush();
- return (consoleinterface_buffer << "^D");
+ return con_ansicolor;
}
-void ConsoleInterface::flush()
+void set_ansi(const bool ansi)
{
- if (rcon())
- return;
-
- char line[MAXCMDSIZE];
-
- while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) {
- while (consoleinterface_text.size() >= MAXCONLINES) {
- consoleinterface_text.pop_front();
- }
- consoleinterface_text.push_back(std::string(line));
-
- // print to stdout
- print_ansi(line);
- std::cout << std::endl;
+ con_ansicolor = ansi;
+ if (con_ansicolor) {
+ // ANSI default color
+ std::cout << "\033[0;39m";
}
-
- consoleinterface_buffer.clear();
-}
-
-void ConsoleInterface::resize()
-{
}
-void ConsoleInterface::print_ansi(const char *line)
+void fallback_print(const std::string &text)
{
- if (consoleinterface_ansi)
- std::cout << "\033[0;39m";
-
- const char *c = line;
+ bool is_color_code = false;
+ int ansi_bold = 0;
+ int ansi_color = 39;
+
+ const char *c = text.c_str();
while (*c) {
+
+ if ((*c) == '\n') {
+ std::cout << std::endl;
+
+ } else if ((*c) == '^') {
- if ((*c == '^')) {
- bool is_code = true;
- int bold = 0;
- int color = 39;
-
+ is_color_code = true;
+ ansi_bold = 0;
+ ansi_color = 39;
+
switch (*(c+1)) {
case '0': // black
- color = 0;
- bold = 1;
- break;
- case '1': // red
- color = 31;
- break;
- case '2': // green
- color = 32;
- break;
- case '3': // yellow
- bold = 1;
- color = 33;
- break;
- case '4': // blue
- color = 34;
- break;
- case '5': // cyan
- color = 36;
- break;
- case '6': // magenta
- color = 35;
- break;
- case '7': // white is mapped to foreground color
- bold = 1;
- color = 39;
+ ansi_color = 0;
+ ansi_bold = 1;
break;
-
+ case '1': // red
+ ansi_color = 31;
+ break;
+ case '2': // green
+ ansi_color = 32;
+ break;
+ case '3': // yellow
+ ansi_color = 1;
+ ansi_color = 33;
+ break;
+ case '4': // blue
+ ansi_color = 34;
+ break;
+ case '5': // cyan
+ ansi_color = 36;
+ break;
+ case '6': // magenta
+ ansi_color = 35;
+ break;
+ case '7': // white is mapped to foreground color
+ ansi_bold = 1;
+ ansi_color = 39;
+ break;
+
case 'N': // normal
- bold = 0;
- color = 39;
+ ansi_bold = 0;
+ ansi_color = 39;
break;
case 'B': // bold
- bold = 1;
- color = 39;
+ ansi_bold = 1;
+ ansi_color = 39;
break;
case 'D': // debug
- bold = 0;
- color = 39;
+ ansi_bold = 0;
+ ansi_color = 39;
break;
case 'R': // error
- bold = 0;
- color = 31;
+ ansi_bold = 0;
+ ansi_color = 31;
break;
case 'W': // warning
- bold = 1;
- color = 33;
+ ansi_bold = 1;
+ ansi_color = 33;
break;
case 'F': // fancy
- bold = 0;
- color = 32;
+ ansi_bold = 0;
+ ansi_color = 32;
break;
default:
- is_code = false;
+ is_color_code = false;
}
- if (is_code) {
+
+ if (is_color_code) {
+ if (con_ansicolor)
+ std::cout << "\033[" << ansi_bold << ";" << ansi_color << "m";
c++;
- if (consoleinterface_ansi)
- std::cout << "\033[" << bold << ";" << color << "m";
- } else
+ } else {
std::cout << *c;
+ }
+
} else {
std::cout << *c;
}
+
c++;
}
+}
- if (consoleinterface_ansi)
- std::cout << "\033[0;39m";
+/* -- ConsoleBuffer ------------------------------------------------ */
+
+int ConsoleBuffer::overflow(int c)
+{
+ if (c == Traits::eof())
+ return Traits::not_eof(c);
+
+ if (c == '\n') {
+ if (ConsoleInterface::instance()) {
+ ConsoleInterface::instance()->event_text(con_buffer);
+ } else {
+ fallback_print(con_buffer);
+ std::cout << std::endl;
+ }
+ con_buffer.clear();
+ } else {
+ con_buffer += c;
+ }
+ return c;
}
-void ConsoleInterface::set_ansi(bool enable)
+/* -- ConsoleStream ------------------------------------------------ */
+
+ConsoleStream con_out;
+
+ConsoleStream::ConsoleStream() : std::basic_ostream<char, Traits>(&con_buffer)
{
- consoleinterface_ansi = enable;
+ clear();
}
-void ConsoleInterface::set_rcon(bool enable)
+ConsoleStream::~ConsoleStream()
{
- if (enable) {
- flush();
+ if (con_ansicolor) {
+ // ANSI default color
+ std::cout << "\033[0;39m" << std::endl;
}
+}
+
+/* -- Console ------------------------------------------------------ */
+
+ConsoleInterface *ConsoleInterface::consoleinterface_instance = 0;
+
+ConsoleInterface::ConsoleInterface()
+{
+ if (consoleinterface_instance) {
+ std::cerr << "multiple sys::ConsoleInterface instances!" << std::endl;
+ sys::quit(2);
+ }
+
+ consoleinterface_rcon = false;
+ consoleinterface_instance = this;
+ consoleinterface_logsize = DEFAULT_LOGSIZE;
+}
+
+ConsoleInterface::~ConsoleInterface()
+{
+ consoleinterface_instance = 0;
+}
+
+ConsoleInterface *ConsoleInterface::instance()
+{
+ return consoleinterface_instance;
+}
+
+void ConsoleInterface::set_rcon(bool enable)
+{
consoleinterface_rcon = enable;
}
-} // namespace sys
+void ConsoleInterface::set_logsize(const size_t logsize)
+{
+ consoleinterface_logsize = logsize < 16 ? 16 : logsize;
+}
+void ConsoleInterface::event_text(const std::string & text)
+{
+ if (rcon()) {
+ consoleinterface_rconbuf.push_back(text);
+ } else {
+ while (consoleinterface_log.size() >= consoleinterface_logsize) {
+ consoleinterface_log.pop_front();
+ }
+
+ consoleinterface_log.push_back(std::string(text));
+ print(text);
+ }
+}
+
+void ConsoleInterface::print(const std::string & text)
+{
+ fallback_print(text);
+ std::cout << std::endl;
+}
+
+} // namespace sys
diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h
index 5411cb6..3a7d3ed 100644
--- a/src/sys/consoleinterface.h
+++ b/src/sys/consoleinterface.h
@@ -8,89 +8,141 @@
#define __INCLUDED_SYS_CONSOLEINTERFACE_H__
#include <iostream>
+#include <string>
+#include <streambuf>
+#include <ostream>
#include <sstream>
#include <deque>
#include "sys/sys.h"
-/// global define to send a message to the system console
-#define con_print sys::ConsoleInterface::instance()->messagestream()
-/// global define to send a warning message to the system console
-#define con_warn sys::ConsoleInterface::instance()->warningstream()
-/// global define to send an error message to the system console
-#define con_error sys::ConsoleInterface::instance()->errorstream()
-
-#ifdef HAVE_DEBUG_MESSAGES
-/// global define to send a debug message to the system console
-#define con_debug sys::ConsoleInterface::instance()->debugstream()
-#else
-#define con_debug if (0) *(std::ostream*)(0)
-#endif
namespace sys
{
-const size_t MAXCONLINES = 2048;
+/// true if ANSI colors are enabled
+bool ansi();
-/// interface for the client and server Console classes
-class ConsoleInterface
-{
-public:
- /// default constructor
- ConsoleInterface();
+/// enable or disable ANSI colors
+void set_ansi(bool enable = true);
- /// default destructor
- virtual ~ConsoleInterface();
-
- /// stream to send normal messages to
- std::ostream & messagestream();
+/* -- ConsoleBuffer ------------------------------------------------ */
- /// stream to send warning messages to
- std::ostream & warningstream();
+typedef std::char_traits<char> Traits;
- /// stream to send error messages to
- std::ostream & errorstream();
+/// buffer back-end for console output
+class ConsoleBuffer : public std::basic_streambuf<char, Traits >
+{
+public:
+ const std::string & str() const
+ {
+ return con_buffer;
+ }
+
+protected:
+ /// stream overflow
+ virtual int overflow(int c = Traits::eof());
+
+private:
+ std::string con_buffer;
+};
- /// stream to send debug messages to
- std::ostream & debugstream();
- /// flush buffered messages
- virtual void flush();
+/* -- ConsoleStream ------------------------------------------------ */
- /// resize the console (ncurses stub)
- virtual void resize();
+/// provides global streams for console output
+class ConsoleStream : public std::basic_ostream<char, Traits >
+{
+public:
+ ConsoleStream();
+ ~ConsoleStream();
+
+ inline ConsoleBuffer & buf()
+ {
+ return con_buffer;
+ }
+
+private:
+ ConsoleBuffer con_buffer;
+};
- /// return the console inputbuffer
- inline std::stringstream & buffer() { return consoleinterface_buffer; }
+/// global console output stream
+extern ConsoleStream con_out;
- inline bool rcon() { return consoleinterface_rcon; }
- inline bool ansi() { return consoleinterface_ansi; }
+/* -- Console ------------------------------------------------------ */
- /// enable or disable ANSI escape sequences
- void set_ansi(bool enable = true);
+/// interface for the client and server Console classes
+class ConsoleInterface
+{
+public:
+ /// default constructor
+ ConsoleInterface();
+
+ /// default destructor
+ virtual ~ConsoleInterface();
+
+ /// set maximal number of lines in the log
+ void set_logsize(const size_t logsize);
+
+ /// return rcon state
+ inline bool rcon()
+ {
+ return consoleinterface_rcon;
+ }
+
/// enable or disable rcon
void set_rcon(bool enable = true);
-
+
+ typedef std::deque<std::string> Text;
+
+ inline Text & rconbuf()
+ {
+ return consoleinterface_rconbuf;
+ }
+
+ inline Text & log()
+ {
+ return consoleinterface_log;
+ }
+
/// a pointer to the current console instance
static ConsoleInterface *instance();
-
+
+ /// incoming text event handler
+ void event_text(const std::string & text);
+
+ /// ncurses resize event
+ virtual void resize()
+ {};
+
protected:
- std::deque<std::string> consoleinterface_text;
- std::stringstream consoleinterface_buffer;
+ /// print one line of text
+ virtual void print(const std::string & text);
- /// print a string to stdout with ansi color codes
- void print_ansi(const char *line);
-
private:
/// console singleton
static ConsoleInterface *consoleinterface_instance;
- bool consoleinterface_ansi;
+
bool consoleinterface_rcon;
+ Text consoleinterface_rconbuf;
+
+ Text consoleinterface_log;
+ size_t consoleinterface_logsize;
};
} // namespace sys
+#define con_print sys::con_out << "^N"
+#define con_warn sys::con_out << "^W"
+#define con_error sys::con_out << "^R"
+#ifdef HAVE_DEBUG_MESSAGES
+#define con_debug sys::con_out << "^D"
+#else
+#define con_debug if (0) *(std::ostream*)(0)
+#endif
+
+
#endif // __INCLUDED_SYS_CONSOLEINTERFACE_H__
diff --git a/src/sys/sys.cc b/src/sys/sys.cc
index db2be4d..59ed11d 100644
--- a/src/sys/sys.cc
+++ b/src/sys/sys.cc
@@ -29,18 +29,19 @@
#include "sys/sys.h"
-namespace sys {
+namespace sys
+{
-bool isdirectory(std::string const &path)
+bool isdirectory(const std::string &path)
{
#ifdef _WIN32
struct ::_stat path_stat;
memset(&path_stat, 0, sizeof(struct ::_stat));
-
+
if (::_stat(path.c_str(), &path_stat) != 0) {
return false;
}
-
+
if (path_stat.st_mode & _S_IFDIR) {
return true;
}
@@ -48,11 +49,11 @@ bool isdirectory(std::string const &path)
#else
struct stat path_stat;
memset(&path_stat, 0, sizeof(path_stat));
-
+
if (stat(path.c_str(), &path_stat) != 0) {
return false;
}
-
+
if (path_stat.st_mode & S_IFDIR) {
return true;
}
@@ -61,7 +62,7 @@ bool isdirectory(std::string const &path)
#endif
}
-void mkdir(std::string const &path)
+void mkdir(const std::string &path)
{
#ifdef _WIN32
std::string p(path);
@@ -69,7 +70,7 @@ void mkdir(std::string const &path)
if (p[i] == '/') p[i] = '\\';
if (p.size() && (p[p.size()-1] == '\\'))
p.erase(p.size() -1, 1);
-
+
if (_mkdir(p.c_str()) != 0) {
con_warn << "Could not create directory '" << p << "'" << std::endl;
}
@@ -83,23 +84,23 @@ void signal(int signum, signalfunc handler)
{
#ifndef _WIN32
struct sigaction sa;
-
+
sa.sa_sigaction = 0;
memset(&sa.sa_mask, 0 ,sizeof(sigset_t));
sa.sa_flags = 0;
sa.sa_handler = handler;
-
+
::sigaction(signum, &sa, 0);
#endif
}
-unsigned long time()
+unsigned long time()
{
#ifndef _WIN32
struct ::tm localtime;
time_t epochtime = ::time(0);
::localtime_r(&epochtime, &localtime);
- return ((unsigned long) (localtime.tm_sec + localtime.tm_min*60 + localtime.tm_hour*3600));
+ return ((unsigned long)(localtime.tm_sec + localtime.tm_min*60 + localtime.tm_hour*3600));
#else
return 0;
#endif
@@ -108,13 +109,14 @@ unsigned long time()
void sleep(float seconds)
{
#ifndef _WIN32
- ::usleep((useconds_t) (seconds * 1000000.0f) );
+ ::usleep((useconds_t)(seconds * 1000000.0f));
#else
- Sleep((DWORD) (seconds*1000.0f));
+ Sleep((DWORD)(seconds*1000.0f));
#endif
}
-void quit(int status) {
+void quit(int status)
+{
::exit(status);
}
diff --git a/src/sys/sys.h b/src/sys/sys.h
index 66040f0..81eba94 100644
--- a/src/sys/sys.h
+++ b/src/sys/sys.h
@@ -19,18 +19,18 @@
*/
namespace sys
{
-typedef void (* signalfunc)(int signum);
+typedef void(* signalfunc)(int signum);
-/// check if a path exists and if it is a directory
-bool isdirectory(std::string const &path);
+/// returns true if a path exists and it is a directory
+bool isdirectory(const std::string &path);
/// create a directory
-void mkdir(std::string const &path);
+void mkdir(const std::string &path);
/// intercept OS signals
void signal(int signum, signalfunc handler);
-/**
+/**
* @brief operation system exit() application
* @param status return value
*/
diff --git a/src/ui/container.cc b/src/ui/container.cc
index d544244..5a12e8e 100644
--- a/src/ui/container.cc
+++ b/src/ui/container.cc
@@ -30,12 +30,12 @@ Container::~Container()
void Container::resize()
{
float w = container_childsize.width() * 1.5f;
- float h = children().size() * container_childsize.height() + (children().size()+1) * container_margin;
+ float h = children().size() * (container_childsize.height() + margin()) + container_childsize.height();
set_size(w, h);
const float x = container_childsize.width() * 0.25f;
- float y = container_margin;
+ float y = container_childsize.height() * 0.5f;
// reposition all children within the container
for (Children::iterator it = children().begin(); it != children().end(); it++) {
diff --git a/src/ui/input.cc b/src/ui/input.cc
index 5e000d2..8113354 100644
--- a/src/ui/input.cc
+++ b/src/ui/input.cc
@@ -8,7 +8,6 @@
#include "ui/paint.h"
#include "auxiliary/functions.h"
#include "core/core.h"
-#include "render/render.h"
namespace ui
{
@@ -52,7 +51,7 @@ void Input::draw()
draw_background();
draw_border();
- size_t text_width = (size_t) width() / font()->width();
+ size_t text_width = (size_t) floorf(width() / font()->width());
math::Vector2f v(global_location());
paint::color(palette()->foreground());
@@ -74,7 +73,7 @@ void Input::draw()
while (*c && draw_width > text_width - 2) {
if (aux::is_color_code(c)) {
c++;
- render::Text::setcolor(*c);
+ paint::color_code(*c);
} else {
draw_width--;
}
@@ -89,7 +88,7 @@ void Input::draw()
v.x += draw_width * font()->width();
if (input_pos < input_text.size()) {
if (input_pos > 1 && aux::is_color_code(input_text.c_str() + input_pos -1)) {
- render::Text::setcolor(input_text[input_pos]);
+ paint::color_code(input_text[input_pos]);
}
// limit to width
std::string secondpart;
@@ -119,6 +118,7 @@ bool Input::on_keypress(const int key, const unsigned int modifier)
{
switch (key) {
case SDLK_TAB:
+ // FIXME should not be here
core::CommandBuffer::complete(input_text, input_pos);
return true;
break;
diff --git a/src/ui/paint.cc b/src/ui/paint.cc
index 33ee54f..d50e3b5 100644
--- a/src/ui/paint.cc
+++ b/src/ui/paint.cc
@@ -27,9 +27,9 @@ void color(math::Color const & color)
render::gl::color(color);
}
-void color_code(const char *c)
+void color_code(const char c)
{
- render::Text::setcolor(*c);
+ render::Text::setcolor(c);
}
void border(math::Vector2f const &location, math::Vector2f const &size)
diff --git a/src/ui/paint.h b/src/ui/paint.h
index 367b001..c90f1b5 100644
--- a/src/ui/paint.h
+++ b/src/ui/paint.h
@@ -22,7 +22,7 @@ void color(float r=0.0f, float g=0.0f, float b=0.0f, float a=1.0f);
void color(math::Color const & color);
/// set paint color
-void color_code(const char *c);
+void color_code(const char c);
/// draw a border
void border(math::Vector2f const &location, math::Vector2f const &size);
@@ -33,12 +33,12 @@ void rectangle(math::Vector2f const &location, math::Vector2f const &size);
/// draw a rectangular bitmap
void bitmap(math::Vector2f const &location, math::Vector2f const &size, std::string const &texture);
-/// draw text
+/// draw one line of text from a string
void text(math::Vector2f const &location, math::Vector2f const &size, Font const *font,
std::string const &text, unsigned int align = AlignCenter);
-
-/// draw textstream
-void text(math::Vector2f const &location, Font const *font, std::stringstream & textstream);
+
+/// draw unaligned text from a stringstream
+void text(math::Vector2f const &location, Font const *font, std::stringstream & textstream);
}
diff --git a/src/ui/ui.cc b/src/ui/ui.cc
index 2cadd8b..baedd38 100644
--- a/src/ui/ui.cc
+++ b/src/ui/ui.cc
@@ -381,13 +381,12 @@ void UI::show_menu(const char *label)
} else {
menu->clear_previous();
}
- ui_active_menu = menu;
- ui_active_menu->event_resize();
- ui_active_menu->raise();
- ui_active_menu->show();
- ui_active_menu->set_focus();
ui_mouse_focus = this;
ui_input_focus = this;
+
+ ui_active_menu = menu;
+ ui_active_menu->event_resize();
+ ui_active_menu->show();
} else {
con_warn << "Unknown window '" << label << "'" << std::endl;
}
@@ -436,20 +435,22 @@ void UI::input_mouse(const float x, const float y)
ui_mouse_focus = f;
}
-void UI::input_key(const bool pressed, const int key, const unsigned int modifier)
+bool UI::input_key(const bool pressed, const int key, const unsigned int modifier)
{
+ bool handled = false;
if (key < 512) {
// keyboard keys
Widget *f = find_input_focus();
if (f) {
- f->event_key(pressed, key, modifier);
+ handled = f->event_key(pressed, key, modifier);
}
ui_input_focus = f;
} else {
// mosue buttons
if (ui_mouse_focus)
- ui_mouse_focus->event_key(pressed, key, modifier);
+ handled = ui_mouse_focus->event_key(pressed, key, modifier);
}
+ return handled;
}
/* -- event handlers ----------------------------------------------- */
@@ -459,12 +460,28 @@ void UI::input_key(const bool pressed, const int key, const unsigned int modifie
*/
bool UI::on_keypress(const int key, const unsigned int modifier)
{
- return true;
+ switch( key ) {
+
+ case SDLK_ESCAPE:
+ if (active()) {
+ previous_menu();
+ } else {
+ if (core::application()->connected()) {
+ show_menu("game");
+ }
+ }
+ return true;
+ break;
+ default:
+ break;
+ }
+
+ return false;
}
bool UI::on_keyrelease(const int key, const unsigned int modifier)
{
- return true;
+ return false;
}
}
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 583f76c..8fa32c2 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -61,7 +61,7 @@ public:
void input_mouse(const float x, const float y);
/// receive global key input
- void input_key(const bool pressed, const int key, const unsigned int modifier);
+ bool input_key(const bool pressed, const int key, const unsigned int modifier);
/// run a user interface frame
void frame();
diff --git a/src/ui/widget.cc b/src/ui/widget.cc
index 1ecfcc8..24dfe5c 100644
--- a/src/ui/widget.cc
+++ b/src/ui/widget.cc
@@ -128,6 +128,20 @@ void Widget::show()
void Widget::hide()
{
widget_visible = false;
+ if (parent() && focus()) {
+ Widget::Children::reverse_iterator it = parent()->children().rbegin();
+
+ while (it != parent()->children().rend()) {
+ Widget *w = (*it);
+ if (w != this && w->visible()) {
+ widget_focus = false;
+ w->widget_focus = true;
+ it = parent()->children().rend();
+ } else {
+ it++;
+ }
+ }
+ }
}
diff --git a/src/ui/window.cc b/src/ui/window.cc
index e79262f..3015a10 100644
--- a/src/ui/window.cc
+++ b/src/ui/window.cc
@@ -23,11 +23,16 @@ Window::~Window()
{
}
-void Window::show() {
+void Window::show()
+{
resize();
Widget::show();
raise();
- set_focus();
+ Widget *w = this;
+ while (w && w->visible()) {
+ w->set_focus();
+ w = w->parent();
+ }
}
void Window::set_previous(Window *previous)
diff --git a/src/ui/window.h b/src/ui/window.h
index 2c0e2a5..412d1f1 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -12,6 +12,7 @@
namespace ui
{
+/// a user interface window
class Window : public Widget
{
@@ -27,7 +28,9 @@ public:
/// clear the label of the previous window
void clear_previous();
- /// showing a window sets focus
+ /// show the window
+ /**show() sets focus on the window and all of its parents
+ */
virtual void show();
inline const std::string &previous() const {