From 1a28393dabf4f4696bf433ddde52e7a25253c955 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Thu, 16 Oct 2008 16:34:15 +0000 Subject: various user interface related updates --- src/audio/audio.cc | 19 ++++- src/audio/audio.h | 3 + src/audio/buffers.cc | 8 +- src/audio/buffers.h | 1 + src/audio/sources.cc | 15 +++- src/audio/sources.h | 1 + src/client/chat.cc | 15 ++-- src/client/chat.h | 4 +- src/client/client.cc | 30 ++++--- src/client/client.h | 4 +- src/client/console.cc | 28 +++---- src/client/console.h | 4 +- src/client/input.cc | 34 +++++--- src/client/input.h | 2 +- src/client/targets.cc | 4 +- src/client/video.cc | 41 ++++++++-- src/client/video.h | 11 +-- src/client/view.cc | 170 +++++++++++++-------------------------- src/core/application.cc | 19 +++-- src/core/application.h | 11 ++- src/core/clientstate.cc | 16 +++- src/core/cvar.cc | 25 +++--- src/core/cvar.h | 1 + src/core/func.cc | 2 +- src/core/gameconnection.cc | 22 +++--- src/core/gameconnection.h | 11 +-- src/core/gameinterface.cc | 48 ++++------- src/core/gameinterface.h | 35 ++------ src/core/gameserver.cc | 37 ++++----- src/core/gameserver.h | 11 +-- src/core/net.h | 2 +- src/core/netconnection.cc | 9 ++- src/core/netconnection.h | 7 +- src/core/netserver.cc | 12 +-- src/core/netserver.h | 6 +- src/core/timer.cc | 14 +++- src/core/timer.h | 5 +- src/filesystem/diskfile.cc | 4 + src/filesystem/filesystem.cc | 9 ++- src/render/image.cc | 25 ++++++ src/render/image.h | 3 + src/render/render.cc | 17 +++- src/render/render.h | 3 + src/server/console.cc | 20 ++--- src/server/console.h | 8 +- src/server/server.cc | 13 ++- src/sys/consoleinterface.h | 10 +-- src/ui/Makefile.am | 4 +- src/ui/button.cc | 14 ++-- src/ui/container.cc | 17 +++- src/ui/container.h | 2 + src/ui/definitions.h | 2 + src/ui/input.cc | 184 ------------------------------------------- src/ui/input.h | 55 ------------- src/ui/inputbox.cc | 184 +++++++++++++++++++++++++++++++++++++++++++ src/ui/inputbox.h | 55 +++++++++++++ src/ui/menu.h | 2 +- src/ui/palette.cc | 27 +++++++ src/ui/palette.h | 16 ++-- src/ui/ui.cc | 68 ++++++++++++++-- src/ui/ui.h | 16 +++- src/ui/widget.cc | 4 +- src/ui/widget.h | 2 +- src/ui/window.cc | 8 +- src/ui/window.h | 3 +- 65 files changed, 808 insertions(+), 654 deletions(-) delete mode 100644 src/ui/input.cc delete mode 100644 src/ui/input.h create mode 100644 src/ui/inputbox.cc create mode 100644 src/ui/inputbox.h diff --git a/src/audio/audio.cc b/src/audio/audio.cc index 81a260c..ca30590 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -18,13 +18,13 @@ ALCcontext *audio_context = 0; void init() { - con_print << "^BInitializing audio..."; + con_print << "^BInitializing audio..." << std::endl; // open the default audio device audio_device = alcOpenDevice(0); if (!audio_device) { - con_warn << "Could not initialize audio!"; + con_warn << "Could not initialize audio!" << std::endl; return; } @@ -34,7 +34,7 @@ void init() if (!audio_context) { alcCloseDevice(audio_device); audio_device = 0; - con_warn << "Could not create audio context!"; + con_warn << "Could not create audio context!" << std::endl; return; } @@ -56,6 +56,17 @@ void init() load("ui/console"); } +void reset() +{ + con_print << "^BReloading audio..." << std::endl; + + Sources::reset(); + Buffers::reset(); + + load("ui/nosnd"); + load("ui/console"); +} + void load (const char *name) { Buffers::load(std::string(name)); @@ -63,7 +74,7 @@ void load (const char *name) void shutdown() { - con_print << "^BShutting down audio..."; + con_print << "^BShutting down audio..." << std::endl; Sources::shutdown(); diff --git a/src/audio/audio.h b/src/audio/audio.h index c0479d3..930edaf 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -29,6 +29,9 @@ void init(); /// shut down the audio subsystem void shutdown(); +/// reload audio +void reset(); + /// load an audio sample void load(const char *name); diff --git a/src/audio/buffers.cc b/src/audio/buffers.cc index af14cb1..33c4dbf 100644 --- a/src/audio/buffers.cc +++ b/src/audio/buffers.cc @@ -25,7 +25,7 @@ void Buffers::init() alGenBuffers(MAXBUFFERS, buffers); if ((error = alGetError()) != AL_NO_ERROR) { - con_warn << "Error " << std::hex << error << " initializing OpenAL buffers!" << std::endl; + con_warn << "Error " << error << " initializing OpenAL buffers!" << std::endl; return; } } @@ -44,6 +44,12 @@ void Buffers::clear() index = 0; } +void Buffers::reset() +{ + shutdown(); + init(); +} + size_t Buffers::load(std::string name) { // check if it is already loaded diff --git a/src/audio/buffers.h b/src/audio/buffers.h index cc7a6c8..462afff 100644 --- a/src/audio/buffers.h +++ b/src/audio/buffers.h @@ -23,6 +23,7 @@ class Buffers { public: static void init(); static void shutdown(); + static void reset(); /// find previously loaded PCM data static size_t find(std::string name); diff --git a/src/audio/sources.cc b/src/audio/sources.cc index 584f366..01fbafb 100644 --- a/src/audio/sources.cc +++ b/src/audio/sources.cc @@ -23,7 +23,7 @@ void Sources::init() alGenSources(MAXSOURCES, sources); if ((error = alGetError()) != AL_NO_ERROR) { - con_warn << "Error " << std::hex << error << " initializing OpenAL sources!" << std::endl; + con_warn << "Error " << error << " initializing OpenAL sources!" << std::endl; return; } @@ -55,6 +55,19 @@ void Sources::clear() } +void Sources::reset() +{ + for (size_t index= 0; index < MAXSOURCES; index++) { + source_available[index] = true; + alSourceRewind(sources[index]); + } + + // reserve ui sound sources + for (size_t i=0; i < MAXUISOURCES; i++) { + source_available[i] = false; + } +} + size_t Sources::get() { for (size_t i= MAXUISOURCES; i < MAXSOURCES; i++) { diff --git a/src/audio/sources.h b/src/audio/sources.h index 078c424..f01e7a4 100644 --- a/src/audio/sources.h +++ b/src/audio/sources.h @@ -23,6 +23,7 @@ class Sources { public: static void init(); static void shutdown(); + static void reset(); static inline bool available(size_t index) { return source_available[index]; } diff --git a/src/client/chat.cc b/src/client/chat.cc index 6d294ba..9d51adc 100644 --- a/src/client/chat.cc +++ b/src/client/chat.cc @@ -23,9 +23,10 @@ Chat::Chat(ui::Widget *parent) : ui::Window(parent) chat_label = new ui::Label(this, "^BSay^F:^B"); chat_label->set_alignment(ui::AlignLeft | ui::AlignVCenter); + chat_label->set_border(false); - chat_input = new ui::Input(this); - chat_input->set_border(true); + chat_input = new ui::InputBox(this); + chat_input->set_border(false); chat_input->set_focus(); @@ -79,19 +80,17 @@ bool Chat::on_keypress(const int key, const unsigned int modifier) } case SDLK_RETURN: if (chat_input->text().size()) { - (*history_pos).assign(chat_input->text()); - // store input into history while (history.size() >= DEFAULT_MAX_HISTO_LINES) { history.pop_front(); } - if ((*history_pos).c_str()[0] == '/' || (*history_pos).c_str()[0] == '\\') { - core::cmd() << &(*history_pos).c_str()[1] << std::endl; + if (chat_input->text().c_str()[0] == '/' || chat_input->text().c_str()[0] == '\\') { + core::cmd() << &chat_input->text().c_str()[1] << std::endl; } else { - core::cmd() << "say " << (*history_pos) << std::endl; + core::cmd() << "say " << chat_input->text() << std::endl; } - (*history.rbegin()) = (*history_pos); + (*history.rbegin()) = chat_input->text(); history.push_back(""); history_pos = history.rbegin(); diff --git a/src/client/chat.h b/src/client/chat.h index f076075..c7232a9 100644 --- a/src/client/chat.h +++ b/src/client/chat.h @@ -10,7 +10,7 @@ #include #include -#include "ui/input.h" +#include "ui/inputbox.h" #include "ui/label.h" #include "ui/window.h" @@ -34,7 +34,7 @@ protected: private: ui::Label *chat_label; - ui::Input *chat_input; + ui::InputBox *chat_input; typedef std::deque History; diff --git a/src/client/client.cc b/src/client/client.cc index 200becd..13c6214 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -41,9 +41,7 @@ void func_snd_restart(std::string const &args) entity->state()->clearsound(); } - audio::shutdown(); - - audio::init(); + audio::reset(); } void func_r_restart(std::string const &args) @@ -96,7 +94,7 @@ void Client::init(int count, char **arguments) con_print << "^BInitializing client..." << std::endl; // initialize core - core::Cvar::sv_dedicated = core::Cvar::set("sv_private", "0"); + core::Cvar::sv_private = core::Cvar::set("sv_private", "0"); core::Application::init(count, arguments); // client variables @@ -145,8 +143,10 @@ void Client::init(int count, char **arguments) 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"); + func = core::Func::add("snd_restart", (core::FuncPtr) func_snd_restart); + func->set_info("restart audio subsystem"); + + previous_timestamp = 0; } void Client::run() @@ -182,10 +182,7 @@ void Client::run() Uint32 d = client_current_timestamp - client_previous_timestamp; if ((d > 0)) { if (d >= client_frame_lenght) { - float elapsed = (float)(d) / 1000.f; - - frame(elapsed); - + frame(client_current_timestamp); client_previous_timestamp = client_current_timestamp; } else { SDL_Delay(client_frame_lenght - d); @@ -197,9 +194,9 @@ void Client::run() } -void Client::frame(float seconds) +void Client::frame(unsigned long timestamp) { - core::Application::frame(seconds); + core::Application::frame(timestamp); if (!core::application()->connected()) { // load the intro if nothing is running @@ -217,8 +214,9 @@ void Client::frame(float seconds) } } - video::frame(seconds); - input::frame(seconds); + video::frame((float)(timestamp - previous_timestamp) / 1000.0f); + input::frame(); + previous_timestamp = timestamp; } void Client::shutdown() @@ -230,7 +228,7 @@ void Client::shutdown() core::Func::remove("r_restart"); core::Func::remove("ui_chat"); core::Func::remove("ui_console"); - //core::Func::remove("snd_restart"); + core::Func::remove("snd_restart"); audio::shutdown(); @@ -254,7 +252,7 @@ void Client::notify_connect() void Client::notify_disconnect() { - // FIXME unload sounds + audio::reset(); render::reset(); input::reset(); } diff --git a/src/client/client.h b/src/client/client.h index 6e19848..67fba13 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -56,11 +56,13 @@ public: protected: /// run a client frame - virtual void frame(float seconds); + virtual void frame(unsigned long timestamp); private: View *client_view; Console *client_console; + + unsigned long previous_timestamp; }; diff --git a/src/client/console.cc b/src/client/console.cc index 0ab0767..80b6224 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -48,18 +48,17 @@ Console::Console(ui::Widget *parent) : ui::Window(parent) set_background(true); set_label("console"); - //clear_notify(); - load_history(); - console_scroll = 0; history.clear(); history.push_back(""); history_pos = history.rbegin(); - console_input = new ui::Input(this); + console_input = new ui::InputBox(this); console_input->set_focus(); console_input->set_border(false); console_input->set_background(false); + + load_history(); } Console::~Console() @@ -125,15 +124,12 @@ bool Console::on_keypress(const int key, const unsigned int modifier) case SDLK_RETURN: 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(); } - - core::cmd() << (*history_pos) << std::endl; - con_print << "^B>" << (*history_pos) << std::endl; - (*history.rbegin()) = (*history_pos); - + core::cmd() << console_input->text() << std::endl; + con_print << "^B>" << console_input->text() << std::endl; + (*history.rbegin()).assign(console_input->text()); history.push_back(""); history_pos = history.rbegin(); console_input->set_text((*history_pos)); @@ -209,10 +205,10 @@ void Console::draw() 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; + int height = (size_t) (this->height() / font()->height()) -1; + int width = (size_t) ((this->width()-8) / font()->width()); + int bottom = (int) log().size() - console_scroll; + int current_line = 0; Text lines; for (Text::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) { @@ -243,7 +239,7 @@ void Console::draw() // new word, wrap if necessary else if ((*c == '\n' ) || ( *c == ' ')) { - if (line_length + word_length > width) { + if (line_length + word_length > (size_t) width) { if (line.size()) { lines.push_back(line); line.clear(); @@ -277,7 +273,7 @@ void Console::draw() word += *c; word_length++; - if (word_length == width) { + if (word_length == (size_t) width) { if (line.size()) { lines.push_back(line); line.clear(); diff --git a/src/client/console.h b/src/client/console.h index 4b2df20..7400c32 100644 --- a/src/client/console.h +++ b/src/client/console.h @@ -9,7 +9,7 @@ #include "sys/consoleinterface.h" #include "ui/window.h" -#include "ui/input.h" +#include "ui/inputbox.h" namespace client { @@ -69,7 +69,7 @@ private: size_t console_scroll; // input widget - ui::Input *console_input; + ui::InputBox *console_input; // console buffer static ConsoleBuffer con_buffer; diff --git a/src/client/input.cc b/src/client/input.cc index a72999e..1e018f5 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -486,8 +486,19 @@ void key_pressed(Key *key) render::Camera::set_pitch(0.0f); client()->console()->toggle(); + return; + } + + if (ui::root()->active()) { + local_direction = 0.0f; + local_pitch = 0.0f; + local_roll = 0.0f; - } else if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) { + render::Camera::set_direction(0.0f); + render::Camera::set_pitch(0.0f); + } + + if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) { return; } else if (core::application()->connected() && core::localcontrol()) { @@ -609,8 +620,8 @@ void reset() } mouse_pitch = 0.0f; mouse_direction = 0.0f; - mouse_x = video::width / 2; - mouse_y = video::height / 2; + mouse_x = render::Camera::width() / 2; + mouse_y = render::Camera::height() / 2; render::Camera::reset(); render::Dust::reset(); mouse_control_override = false; @@ -631,7 +642,7 @@ void reset() joystick_lastmoved = 0; } -void frame(float seconds) +void frame() { /* -- detect localcontrol() changes --------------- */ if (core::localcontrol() && (last_control != core::localcontrol()->id())) { @@ -662,6 +673,9 @@ void frame(float seconds) key = 0; switch (event.type) { + case SDL_VIDEORESIZE: + video::resize((float) event.resize.w, (float) event.resize.h); + break; case SDL_MOUSEMOTION: mouse_x = event.motion.x; @@ -774,26 +788,26 @@ void frame(float seconds) mouse_deadzone = true; // direction - int l = mouse_x - (video::width >> 1); + int l = mouse_x - (render::Camera::width() >> 1); if (abs(l) < ( deadzone_size >> 1 )) { // dead zone mouse_direction = 0; } else { - l = (mouse_x - deadzone_size) - ((video::width - deadzone_size) >> 1); - mouse_direction = float (-l) / (float) ((video::width - deadzone_size) >> 1); + l = (mouse_x - deadzone_size) - ((render::Camera::width() - deadzone_size) >> 1); + mouse_direction = float (-l) / (float) ((render::Camera::width() - deadzone_size) >> 1); mouse_deadzone = false; } // pitch - int h = mouse_y - (video::height >> 1); + int h = mouse_y - (render::Camera::height() >> 1); if (abs(h) < ( deadzone_size >> 1 )) { // dead zone mouse_pitch = 0; } else { - h = (mouse_y - deadzone_size) - ((video::height - deadzone_size) >> 1); - mouse_pitch = float (-h) / (float) ((video::height - deadzone_size) >> 1); + h = (mouse_y - deadzone_size) - ((render::Camera::height() - deadzone_size) >> 1); + mouse_pitch = float (-h) / (float) ((render::Camera::height() - deadzone_size) >> 1); mouse_deadzone = false; } diff --git a/src/client/input.h b/src/client/input.h index a954040..88a65b3 100644 --- a/src/client/input.h +++ b/src/client/input.h @@ -23,7 +23,7 @@ void init(); void shutdown(); /// handle one frame of input events -void frame(float seconds); +void frame(); /// reset input state void reset(); diff --git a/src/client/targets.cc b/src/client/targets.cc index b533974..c7fcf9e 100644 --- a/src/client/targets.cc +++ b/src/client/targets.cc @@ -413,8 +413,8 @@ void draw() x = 0; y = 0; } else { - x = (float)(input::mouse_position_x() - video::width /2) / (float)video::width; - y = (float)(input::mouse_position_y() - video::height /2) / (float)video::height / render::Camera::aspect(); + x = (float)(input::mouse_position_x() - render::Camera::width() /2) / (float)render::Camera::width(); + y = (float)(input::mouse_position_y() - render::Camera::height() /2) / (float)render::Camera::height() / render::Camera::aspect(); } Vector3f cursor = render::Camera::eye() + render::Camera::axis().forward() * (render::Camera::frustum_front() + 0.001); diff --git a/src/client/video.cc b/src/client/video.cc index 7338d70..d8ba316 100644 --- a/src/client/video.cc +++ b/src/client/video.cc @@ -28,6 +28,9 @@ namespace video { float fullscreen = 0; +int bpp = 0; +int flags = 0; + int width = 0; int height = 0; @@ -57,9 +60,6 @@ bool init() r_fullscreen = core::Cvar::get("r_fullscreen", "0", core::Cvar::Archive); r_fullscreen->set_info("[bool] enable or disable fullscreen video"); - int bpp = 0; - int flags = 0; - if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) { con_error << "SDL_InitSubSystem() failed: " << SDL_GetError() << std::endl; return false; @@ -103,7 +103,7 @@ bool init() if (r_fullscreen->value()) { flags = SDL_OPENGL | SDL_FULLSCREEN; } else { - flags = SDL_OPENGL; + flags = SDL_OPENGL | SDL_RESIZABLE; } if(!SDL_SetVideoMode(width, height, bpp, flags )) { @@ -147,17 +147,42 @@ bool init() // resize user interface ui::root()->set_size((float) width, (float) height); ui::root()->event_resize(); + + // to grab or not to grab + if (client()->console()->visible()) { + SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(SDL_ENABLE); + } else { + SDL_WM_GrabInput(SDL_GRAB_ON); + SDL_ShowCursor(SDL_DISABLE); + } // initialize renderer - render::Camera::resize(width, height); render::init(); - render::Camera::resize(width, height); // yes twice, bug + render::resize(width, height); view::init(); return true; } +void resize(float w, float h) +{ + if (fullscreen) + return; + + if (h < 64) h = 64; + if (w < 64) w = 64; + + if (SDL_SetVideoMode(w, h, bpp, flags )) { + render::resize(w, h); + ui::root()->set_size(w, h); + ui::root()->event_resize(); + } else { + con_warn << "Could not resize window!" << std::endl; + } +} + void restart() { shutdown(); @@ -168,14 +193,14 @@ void restart() input::reset(); } -void frame(float seconds) +void frame(float elapsed) { // detect fullscreen/windowed mode switch if (fullscreen != r_fullscreen->value()) restart(); // render a client frame - view::frame(seconds); + view::frame(elapsed); SDL_GL_SwapBuffers(); } diff --git a/src/client/video.h b/src/client/video.h index daa136c..a28b17d 100644 --- a/src/client/video.h +++ b/src/client/video.h @@ -24,14 +24,11 @@ namespace video */ void restart(); - /// draw the next client video frame - void frame(float seconds); - - /// width of the application window in pixels - extern int width; + /// application window resize event in windowed mode + void resize(float w, float h); - /// height of the application window in pixels - extern int height; + /// draw the next client video frame + void frame(float elapsed); } // namespace video diff --git a/src/client/view.cc b/src/client/view.cc index a8d9c4f..22d39a7 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -38,7 +38,7 @@ core::Cvar *draw_keypress = 0; core::Cvar *ui_pointercolor = 0; core::Cvar *ui_pointerhovercolor = 0; -const float pointer_size = 48.0f; +unsigned long previousframe = 0; void time_to_stream(std::stringstream &str, float time) { @@ -127,7 +127,7 @@ void Stats::draw() if (core::game()) { textstream << "^Ntime ^B"; - time_to_stream(textstream, core::game()->clientframetime()); + time_to_stream(textstream, core::game()->time()); } textstream << std::setfill(' ') << "\n"; @@ -226,7 +226,7 @@ void View::resize() height() - view_keypress->height() - font()->height() * 0.5f); // reposition center - view_center->set_size(pointer_size, pointer_size); + view_center->set_size(ui::pointer_size, ui::pointer_size); view_center->set_location((size() - view_center->size()) * 0.5f); view_center->set_color(palette()->pointer()); } @@ -263,6 +263,8 @@ void init() ui_pointerhovercolor->set_info("[r g b] mouse pointer hover color"); targets::init(); + + previousframe = 0; } void shutdown() @@ -366,9 +368,9 @@ void draw_entity_offscreen_target(core::Entity *entity, bool is_active_target) const float r = 16; const float margin = 24; - cx = (0.5f - cx) * ((float) video::width - margin*2); + cx = (0.5f - cx) * ((float) render::Camera::width() - margin*2); cx += margin; - cy = (0.5f - cy) * ((float)video::height - margin*2); + cy = (0.5f - cy) * ((float) render::Camera::height() - margin*2); cy += margin; render::gl::disable(GL_TEXTURE_2D); @@ -419,16 +421,15 @@ void draw_entity_target(core::Entity *entity, bool is_active_target) float t = (render::Camera::frustum_front() + 0.001f) / target.x; Vector3f center(target *t); - float cx = video::width * (0.5 - center.y); - float cy = video::height * (0.5 - center.z * render::Camera::aspect()); + float cx = render::Camera::width() * (0.5 - center.y); + float cy = render::Camera::height() * (0.5 - center.z * render::Camera::aspect()); - if ((cx < 0 ) || (cy < 0) || (cx > video::width) || (cy > video::height)) { + if ((cx < 0 ) || (cy < 0) || (cx > render::Camera::width()) || (cy > render::Camera::height())) { draw_entity_offscreen_target(entity, is_active_target); return; } - const float pointer_size = 48.0f; - float r = pointer_size; + float r = ui::pointer_size; if (!is_active_target) r *= 0.5; @@ -524,7 +525,7 @@ void draw_hud() statestr << "^FJumping..."; } - Text::draw(4, video::height - Text::fontheight()*3-4, statestr); + Text::draw(4, render::Camera::height() - Text::fontheight()*3-4, statestr); } core::Entity *target = targets::current(); @@ -550,28 +551,28 @@ void draw_hud() strtarget << " --"; } strtarget << '\n'; - Text::draw(video::width - 4-Text::fontwidth()*32, video::height - Text::fontheight()*2 -4, strtarget); + Text::draw(render::Camera::width() - 4-Text::fontwidth()*32, render::Camera::height() - Text::fontheight()*2 -4, strtarget); y = 3.0f; } Text::setcolor('N'); //set normal color - Text::draw(video::width-4-Text::fontwidth()*32, video::height-Text::fontheight()*y-4, core::localcontrol()->zone()->name()); + Text::draw(render::Camera::width()-4-Text::fontwidth()*32, render::Camera::height()-Text::fontheight()*y-4, core::localcontrol()->zone()->name()); Textures::bind("bitmaps/hud/thruster_base"); // 316 x 32 bitmap gl::color(1, 1, 1, 1); gl::begin(render::gl::Quads); glTexCoord2f(0, 0); - gl::vertex(4, video::height - 4 - 32, 0); + gl::vertex(4, render::Camera::height() - 4 - 32, 0); glTexCoord2f(1, 0); - gl::vertex(4 + 316, video::height - 4 - 32, 0); + gl::vertex(4 + 316, render::Camera::height() - 4 - 32, 0); glTexCoord2f(1, 1); - gl::vertex(4 + 316, video::height - 4 , 0); + gl::vertex(4 + 316, render::Camera::height() - 4 , 0); glTexCoord2f(0, 1); - gl::vertex(4, video::height - 4 , 0); + gl::vertex(4, render::Camera::height() - 4 , 0); gl::end(); @@ -594,16 +595,16 @@ void draw_hud() Textures::bind("bitmaps/hud/thruster_indicator"); // 316 x 32 bitmap gl::begin(render::gl::Quads); glTexCoord2f(0, 0); - gl::vertex(4, video::height - 4 - 32, 0); + gl::vertex(4, render::Camera::height() - 4 - 32, 0); glTexCoord2f(u, 0); - gl::vertex(4.0f + u * 316.0f, video::height - 4 - 32, 0); + gl::vertex(4.0f + u * 316.0f, render::Camera::height() - 4 - 32, 0); glTexCoord2f(u, 1); - gl::vertex(4.0f + u * 316.0f, video::height - 4 , 0); + gl::vertex(4.0f + u * 316.0f, render::Camera::height() - 4 , 0); glTexCoord2f(0, 1); - gl::vertex(4, video::height - 4 , 0); + gl::vertex(4, render::Camera::height() - 4 , 0); gl::end(); } @@ -613,7 +614,7 @@ void draw_hud() std::stringstream speedstr; speedstr << "^B" << roundf(core::localcontrol()->speed() * 100.0f); - Text::draw( 316+4+10, video::height - 6 -16 - render::Text::fontwidth() /2, speedstr); + Text::draw( 316+4+10, render::Camera::height() - 6 -16 - render::Text::fontwidth() /2, speedstr); Text::setfont("gui", 12, 18); Text::setcolor('N'); //set normal color @@ -622,102 +623,45 @@ void draw_hud() void draw_cursor() { - if (client()->console()->visible()) - return; + if (client()->console()->visible()) { + ui::root()->set_pointer(); - float angle = 0; - - float x = (float) input::mouse_position_x() - (pointer_size / 2.0f); - float y = (float) input::mouse_position_y() - (pointer_size / 2.0f); - bool cursor_animated = false; - math::Color color(1.0, 0.5); - - if(ui::root()->active()) { - render::Textures::bind("bitmaps/pointers/pointer"); + } else if(ui::root()->active()) { - } else if (core::localcontrol()) { + ui::root()->set_pointer("pointer"); - if (render::Camera::mode() == render::Camera::Overview) { - render::Textures::bind("bitmaps/pointers/aim"); - - } else { - if (targets::hover()) { - - if (ui_pointerhovercolor) { - std::stringstream colorstr(ui_pointerhovercolor->str()); - colorstr >> color; - } - render::Textures::bind("bitmaps/pointers/target"); - - cursor_animated = true; - - if (input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) { - x = (video::width - pointer_size) /2; - y = (video::height - pointer_size) /2; - } - - } else if (input::mouse_control) { - - if (ui_pointercolor) { - std::stringstream colorstr(ui_pointercolor->str()); - colorstr >> color; - } - - render::Textures::bind("bitmaps/pointers/control"); - - if (!input::mouse_deadzone) { - x = input::mouse_position_x() - (pointer_size /2); - y = input::mouse_position_y() - (pointer_size /2); - - } else { - x = (video::width - pointer_size) /2; - y = (video::height - pointer_size) /2; - } - - } else { - if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { - color.assign(1.0, 0.0); - } else { - color.assign(1.0, 0.5); - } - render::Textures::bind("bitmaps/pointers/aim"); - } - - } + } else if (!core::localcontrol()) { - } else { - return; - } + ui::root()->set_pointer(); - if (cursor_animated) { - render::gl::push(); - render::gl::translate(x+pointer_size/2, y+pointer_size/2, 0.0f); + } else if (render::Camera::mode() == render::Camera::Overview) { - angle = core::application()->time()* 0.75f - floorf(core::application()->time() * 0.75f); - angle *= 360.0f; - render::gl::rotate(angle, math::Vector3f(0, 0, 1.0f)); - render::gl::translate(-x-pointer_size/2, -y-pointer_size/2, 0.0f); - } + ui::root()->set_pointer("aim"); - render::gl::color(color); - render::gl::begin(render::gl::Quads); + } else if (targets::hover()) { - glTexCoord2f(0,0 ); - render::gl::vertex(x,y,0.0f); + ui::root()->set_pointer("target", ui::Palette::Active, true); - glTexCoord2f(1, 0); - render::gl::vertex(x+pointer_size, y, 0.0f); + if (input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) { + ui::root()->input_mouse(render::Camera::width()/2, render::Camera::height() /2); + } - glTexCoord2f(1, 1); - render::gl::vertex(x+pointer_size, y+pointer_size, 0.0f); + } else if (input::mouse_control) { - glTexCoord2f(0, 1); - render::gl::vertex(x, y+pointer_size, 0.0f); + ui::root()->set_pointer("control", ui::Palette::Pointer); - render::gl::end(); + if (input::mouse_deadzone) { + ui::root()->input_mouse(render::Camera::width()/2, render::Camera::height() /2); + } + + } else if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && + (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { + + ui::root()->set_pointer(); + + } else { - if (cursor_animated) { - render::gl::pop(); + ui::root()->set_pointer("aim", ui::Palette::Foreground); } } @@ -730,7 +674,7 @@ void frame(float elapsed) render::Stats::clear(); - if (core::application()->connected() && core::game()->serverframetime() && core::localplayer()->zone()) { + if (core::application()->connected() && core::game()->time() && core::localplayer()->zone()) { render::Camera::frame(elapsed); render::Camera::frustum(); @@ -751,24 +695,18 @@ void frame(float elapsed) gl::disable(GL_TEXTURE_2D); gl::enable(GL_BLEND); + draw_cursor(); ui::root()->frame(); // draw the hud - TODO move as much as possible into ui:: - - gl::enable(GL_TEXTURE_2D); - gl::color(1.0f, 1.0f, 1.0f, 1.0f); - - // draw text elements - if (draw_ui->value()) { + if (draw_ui->value() && !ui::root()->active()) { + gl::enable(GL_TEXTURE_2D); + gl::color(1.0f, 1.0f, 1.0f, 1.0f); Text::setfont("gui", 12, 18); // draw the hud draw_hud(); - - // draw the mouse cursor - draw_cursor(); } - gl::disable(GL_TEXTURE_2D); gl::disable(GL_BLEND); diff --git a/src/core/application.cc b/src/core/application.cc index f98d44e..837f294 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -147,7 +147,7 @@ Application::Application() } application_instance = this; - application_time = 0; + application_timestamp = 0; application_game = 0; module_interactive = 0; @@ -171,9 +171,8 @@ Application::~Application() void Application::init(int count, char **arguments) { - con_debug << "Debug messages enabled\n"; con_print << "^BInitializing core...\n"; - + con_debug << " debug messages enabled\n"; filesystem::init("base", ""); CommandBuffer::init(); @@ -243,6 +242,7 @@ void Application::init(int count, char **arguments) // register our engine functions Func *func = 0; + func = Func::add("help", func_help); func->set_info("help function"); @@ -258,11 +258,13 @@ void Application::init(int count, char **arguments) func = Func::add("disconnect", func_disconnect); func->set_info("leave the current game"); - func = Func::add("say",func_say); + func = Func::add("say", func_say); func->set_info("say [text] say something on the public chat"); - func = Func::add("msg",func_msg); + func = Func::add("msg", func_msg); func->set_info("msg [player] [text] send a private message to another player"); + + func = 0; } void Application::shutdown() @@ -282,6 +284,7 @@ void Application::shutdown() Module::clear(); // remove our engine functions + Func::remove("msg"); Func::remove("say"); Func::remove("help"); Func::remove("quit"); @@ -373,9 +376,9 @@ void Application::disconnect() } } -void Application::frame(float seconds) +void Application::frame(unsigned long timestamp) { - application_time += seconds; + application_timestamp = timestamp; // execute commands in the buffer CommandBuffer::exec(); @@ -384,7 +387,7 @@ void Application::frame(float seconds) return; // run a game interface frame - application_game->frame(seconds); + application_game->frame(timestamp); if (!application_game->running()) disconnect(); diff --git a/src/core/application.h b/src/core/application.h index e55c37f..229f318 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -30,9 +30,12 @@ public: /*----- inspectors ----------------------------------------------- */ - /// time the application has been running - inline float time() const { return application_time; } + /// the current application time, in microseconds + inline unsigned long timestamp() const { return application_timestamp; } + /// the current application time, in seconds + float time() const { return ((float)(timestamp()) / 1000.0f); } + /// true if the core is connected to a running game interface inline bool connected() const { return (application_game && application_game->running()); } @@ -88,7 +91,7 @@ public: protected: /// run a core frame - virtual void frame(float seconds); + virtual void frame(unsigned long timestamp); /// load cvar config void load_config(); @@ -104,7 +107,7 @@ protected: private: /// time the core has been running - float application_time; + unsigned long application_timestamp; GameInterface *application_game; static Application *application_instance; diff --git a/src/core/clientstate.cc b/src/core/clientstate.cc index 84e1fe0..298e653 100644 --- a/src/core/clientstate.cc +++ b/src/core/clientstate.cc @@ -65,10 +65,22 @@ void ClientState::clearsound() { if (state_engineloopsource) { application()->notify_remove_sound(state_engineloopsource); + } + + if (state_engineeventsource) { application()->notify_remove_sound(state_engineeventsource); - state_engineloopsource = 0; - state_engineloopbuffer = 0; } + + state_thusterloopbuffer = 0; + state_impulseloopbuffer = 0; + state_impulsestartbuffer = 0; + state_impulsestopbuffer = 0; + + state_engineloopbuffer = 0; + state_engineloopsource = 0; + + state_engineeventbuffer = 0; + state_engineeventsource = 0; } void ClientState::assign(Entity * entity) diff --git a/src/core/cvar.cc b/src/core/cvar.cc index 50043f2..7db202d 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -35,16 +35,10 @@ Cvar *Cvar::rconpassword = 0; Cvar::Registry Cvar::cvar_registry; -Cvar::Cvar(const char *name, const unsigned int flags) +Cvar::Cvar(const char *name, const unsigned int flags) : cvar_name(), cvar_info(), cvar_str() { cvar_flags = flags; - - if (name) - cvar_name.assign(name); - else - cvar_name.clear(); - - cvar_info.clear(); + cvar_name.assign(name); } void Cvar::set_info(const char *info) @@ -64,7 +58,8 @@ Cvar & Cvar::operator=(const std::string &other) Cvar & Cvar::operator=(const char *other) { - return ((*this) = std::string(other)); + std::string value(other); + return (this->operator=(value)); } Cvar & Cvar::operator=(float other) @@ -81,11 +76,10 @@ Cvar* Cvar::get(const char *name, const char *value, const unsigned int flags) Cvar *c = find(name); if (c) { //con_debug << "get " << name << " already exist with value " << cvar->str() << std::endl; - c->cvar_flags |= flags; } else { //con_debug << "get " << name << " " << value << std::endl; c = new Cvar(name, flags); - cvar_registry[std::string(name)] = c; + cvar_registry[c->name()] = c; (*c) = value; } c->cvar_flags |= flags; @@ -100,7 +94,7 @@ Cvar* Cvar::get(const char *name, float value, const unsigned int flags) } else { //con_debug << "get " << name << " " << value << std::endl; c = new Cvar(name, flags); - cvar_registry[std::string(name)] = c; + cvar_registry[c->name()] = c; (*c) = value; } c->cvar_flags |= flags; @@ -112,7 +106,7 @@ Cvar* Cvar::set(const char *name, const char *value, const unsigned int flags) Cvar *c = find(name); if (!c) { c = new Cvar(name, flags); - cvar_registry[std::string(name)] = c; + cvar_registry[c->name()] = c; } (*c) = value; c->cvar_flags = flags; @@ -126,7 +120,7 @@ Cvar* Cvar::set(const char *name, float value, unsigned int flags) Cvar *c = find(name); if (!c) { c = new Cvar(name, flags); - cvar_registry[std::string(name)] = c; + cvar_registry[c->name()] = c; } (*c) = value; c->cvar_flags = flags; @@ -161,7 +155,8 @@ Cvar *Cvar::find(std::string const &name) Cvar *Cvar::find(const char *name) { - return(find(std::string(name))); + std::string s(name); + return(find(s)); } void Cvar::list() diff --git a/src/core/cvar.h b/src/core/cvar.h index d934872..acb6f89 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -130,6 +130,7 @@ private: std::string cvar_name; std::string cvar_info; std::string cvar_str; + unsigned int cvar_flags; float cvar_value; diff --git a/src/core/func.cc b/src/core/func.cc index edebc8a..81175f8 100644 --- a/src/core/func.cc +++ b/src/core/func.cc @@ -39,7 +39,7 @@ Func *Func::add(const char *name, GameFuncPtr gamefunctionptr, unsigned int flag Registry::iterator it = func_registry.find(name); if (it == func_registry.end()) { func = new Func(name, (void *)gamefunctionptr, flags | Func::Game); - func_registry[std::string(name)] = func; + func_registry[func->name()] = func; //con_debug << "Function '" << name << "' registered." << std::endl; } else { con_warn << "Function '" << name << "' already registered!" << std::endl; diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 114931c..eaafe91 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -22,7 +22,9 @@ GameConnection::GameConnection(std::string const &connectionstr) connection_instance = this; connection_network = 0; connection_running = false; - connection_frametime = 0; + + connection_timestamp = 0; + connection_netframe = 0; unsigned int port = DEFAULTPORT; std::string host(connectionstr); @@ -101,7 +103,7 @@ void GameConnection::private_message(std::string const &args) connection_network->send_private_message(args); } -void GameConnection::frame(float seconds) +void GameConnection::frame(unsigned long timestamp) { if (!running()) return; @@ -111,20 +113,21 @@ void GameConnection::frame(float seconds) return; } - update_clientstate(seconds); - - connection_network->frame(seconds); + update_clientstate(); - connection_frametime += seconds; + // get incoming messages + connection_network->frame(); float f = 0; if (core::Cvar::net_framerate->value()) { - f = 0.5f / core::Cvar::net_framerate->value(); - if (connection_frametime < f) { + f = 1000.0f / core::Cvar::net_framerate->value(); + if (connection_netframe + f > timestamp) { return; } } + connection_netframe = timestamp; + if (connection_network->state() == NetConnection::Connected) { if(localcontrol() && localcontrol()->dirty()) { @@ -139,9 +142,8 @@ void GameConnection::frame(float seconds) } } + connection_timestamp = connection_network->timestamp(); connection_network->transmit(); - - connection_frametime = 0; } } diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h index 95df9f3..70e3015 100644 --- a/src/core/gameconnection.h +++ b/src/core/gameconnection.h @@ -32,12 +32,12 @@ public: inline bool interactive() const { return true; } /// return the current game time - inline float time() const { return game_clientframetime; } + inline unsigned long timestamp() const { return connection_timestamp; } /*----- mutators -------------------------------------------------- */ /// run a game connection time frame - void frame(float seconds); + void frame(unsigned long timestamp); /// forward a command line to the remote server void forward(std::string const &cmdline); @@ -59,10 +59,11 @@ protected: private: bool connection_running; - static GameConnection *connection_instance; + unsigned long connection_timestamp; // server game time + unsigned long connection_netframe; // last network frame timestamp + NetConnection *connection_network; - float connection_frametime; - + static GameConnection *connection_instance; }; inline GameConnection *connection() { return GameConnection::instance(); } diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 74acced..d99ec15 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -118,16 +118,13 @@ void GameInterface::clear() } game_players.clear(); - - game_previousframetime = 0; - game_serverframetime = 0; - game_clientframetime = 0; } -void GameInterface::reset_clientstate(float timestamp, float prevtimestamp) +void GameInterface::reset_clientstate() { - game_previousframetime = prevtimestamp; - game_serverframetime = timestamp; +// game_previousframetime = prevtimestamp; +// game_serverframetime = timestamp; +// game_time = timestamp; for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { @@ -137,10 +134,10 @@ void GameInterface::reset_clientstate(float timestamp, float prevtimestamp) entity->state()->assign(entity); } - if ( game_clientframetime < game_previousframetime) - game_clientframetime = game_previousframetime; - else if ( game_clientframetime > game_serverframetime) - game_clientframetime = game_serverframetime; +// if ( game_clientframetime < game_previousframetime) +// game_clientframetime = game_previousframetime; +// else if ( game_clientframetime > game_serverframetime) +// game_clientframetime = game_serverframetime; } @@ -150,14 +147,11 @@ void GameInterface::update_entity_clientstate(Entity *entity) if (!entity->state()) { entity->entity_clientstate = new ClientState(entity); entity->entity_clientstate->assign(entity); - } - - if(Cvar::cl_prediction->value() == 0) { - + } else entity->state()->assign(entity); - return; } +/* if (!(entity->flags() & Entity::Static)) { // clientstate location @@ -181,7 +175,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) if (angle > MIN_DELTA) entity->state()->state_axis.rotate(n, -angle); } - /* + n.assign(math::crossproduct( entity->state()->axis().left(), entity->axis().left())); if (!(n.length() < MIN_DELTA)) { n.normalize(); @@ -199,7 +193,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) if (angle > MIN_DELTA) entity->state()->state_axis.rotate(n, -angle); } - */ + } else { entity->state()->state_axis.assign(entity->axis()); } @@ -211,29 +205,15 @@ void GameInterface::update_entity_clientstate(Entity *entity) entity->state()->assign(entity); } } +*/ -void GameInterface::update_clientstate(float seconds) +void GameInterface::update_clientstate() { - game_clientframetime += seconds; - for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { update_entity_clientstate((*it).second); } } -float GameInterface::timeoffset() { - - if (game_clientframetime > game_serverframetime) - return 1; - - float d = game_serverframetime - game_previousframetime; - if (d <= 0) - return 0; - - float t = game_clientframetime - game_previousframetime; - return t/d; -} - void GameInterface::list_players() { using namespace std; diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index fea86fe..c916d15 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -30,20 +30,6 @@ public: /// return the local player inline Player *localplayer() { return &game_localplayer; } - /// return the server time of the last received server frame - inline float serverframetime() const { return game_serverframetime; } - - /// return the server time of the previous received server frame - inline float previousframetime() const { return game_previousframetime; } - - /// return the server time of the previous received server frame - inline float clientframetime() const { return game_clientframetime; } - - /// client frame time between previousframetime and serverframetime, from 0 - 1 - float timeoffset(); - - inline float timestep() const { return game_timestep; } - inline Players & players() { return game_players; } /// show a list of connected players @@ -58,7 +44,10 @@ public: virtual bool interactive() const = 0; /// return the current game time - virtual float time() const = 0; + virtual unsigned long timestamp() const = 0; + + /// return the current game time, in seconds + float time() const { return ((float)(timestamp()) / 1000.0f); } /*----- mutators ------------------------------------------------- */ @@ -66,18 +55,18 @@ public: void clear(); /// reset the client state - void reset_clientstate(float timestamp, float prevtimestamp); + void reset_clientstate(); /// update the client state timers - void update_clientstate(float seconds); + void update_clientstate(); void update_entity_clientstate(Entity *entity); /*----- virtual mutators ------------------------------------------ */ /// run one game time frame - /// @param seconds time since the previous frame, in seconds - virtual void frame(float seconds) = 0; + /// @param timestamp current application time + virtual void frame(unsigned long timestamp) = 0; protected: /// the local player @@ -85,14 +74,6 @@ protected: /// all the players Players game_players; - - float game_serverframetime; - float game_previousframetime; - - float game_timestep; - float game_clientframetime; - - unsigned int game_serverframelength; }; /// global local player instance diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index e42d1b2..4fc3924 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -120,10 +120,10 @@ GameServer::GameServer() : GameInterface() con_print << "^BInitializing game server...\n"; server_instance = this; server_network = 0; - server_time = 0; + server_timestamp = 0; server_previoustime = 0; - server_frametime = 0.0f; server_maxplayerid = 1; + server_startup = application()->timestamp(); server_module = Module::current(); if (!server_module) { @@ -558,14 +558,11 @@ void GameServer::player_disconnect(Player *player) } } -void GameServer::frame(float seconds) +void GameServer::frame(unsigned long timestamp) { if (error()) return; - server_time += seconds; - server_frametime += seconds; - // process incoming network messages if (server_network) { server_network->receive(); @@ -580,24 +577,25 @@ void GameServer::frame(float seconds) localplayer()->update_info(); if (!Cvar::sv_dedicated->value()) { - update_clientstate(seconds); + update_clientstate(); } if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { if (core::Cvar::sv_framerate->value()) { - float f = 1.0f / core::Cvar::sv_framerate->value(); - if (server_frametime < f) { + float f = 1000.0f / core::Cvar::sv_framerate->value(); + if (server_startup + server_timestamp + f > timestamp) { return; } } - } + } + + server_previoustime = server_timestamp; + server_timestamp = timestamp - server_startup; + float elapsed = (float) (server_timestamp - server_previoustime) / 1000.0f; // copy the previous entity state to the client state if (!Cvar::sv_dedicated->value()) { - reset_clientstate(server_time, server_previoustime); - } else { - game_serverframetime = server_time; - game_previousframetime = server_previoustime; + reset_clientstate(); } // run a time frame on each entity @@ -605,13 +603,13 @@ void GameServer::frame(float seconds) Entity *entity = (*it).second; if ((entity->type() == Entity::Controlable) || (entity->type() == Entity::Dynamic)) { - entity->frame(server_frametime); + entity->frame(elapsed); } } // run a frame on the module if (server_module) { - server_module->frame(server_frametime); + server_module->frame(elapsed); if (server_module->error()) { abort(); return; @@ -620,7 +618,7 @@ void GameServer::frame(float seconds) if (server_network) { // send network updates - server_network->frame(server_time, server_previoustime); + server_network->frame(server_timestamp); } // mark all entities as updated @@ -643,11 +641,8 @@ void GameServer::frame(float seconds) } if (!Cvar::sv_dedicated->value()) { - update_clientstate(0); + update_clientstate(); } - - server_frametime = 0; - server_previoustime = server_time; } void GameServer::save_config() diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 550dd99..4ea476b 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -37,7 +37,7 @@ public: virtual bool interactive() const; /// current server game time - virtual inline float time() const { return server_time; } + virtual inline unsigned long timestamp() const { return server_timestamp; } /*----- mutators -------------------------------------------------- */ @@ -48,7 +48,7 @@ public: void player_disconnect(Player *player); /// run a game server time frame - void frame(float seconds); + void frame(unsigned long timestamp); /// a player sends a chat message to the public channel void say(Player *player, std::string const &args); @@ -104,9 +104,10 @@ private: NetServer *server_network; unsigned int server_maxplayerid; - float server_frametime; - float server_time; - float server_previoustime; + + unsigned long server_timestamp; + unsigned long server_previoustime; + unsigned long server_startup; }; inline GameServer *server() { return GameServer::instance(); } diff --git a/src/core/net.h b/src/core/net.h index 4909136..c724f85 100644 --- a/src/core/net.h +++ b/src/core/net.h @@ -11,7 +11,7 @@ namespace core { /// network protocol version -const unsigned int PROTOCOLVERSION = 10; +const unsigned int PROTOCOLVERSION = 11; /// maximum lenght of a (compressed) network message block const unsigned int FRAMESIZE = 1152; diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index ae1118f..704551b 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -23,6 +23,7 @@ NetConnection::NetConnection() { connection_timeout = core::application()->time(); connection_state = Connecting; + connection_timestamp = 0; receive_compressed = false; received_compressed_size = 0; @@ -233,7 +234,7 @@ void NetConnection::receive() } -void NetConnection::frame(float seconds) +void NetConnection::frame() { timeval timeout; timeout.tv_sec = 0; @@ -458,9 +459,9 @@ void NetConnection::parse_incoming_message(const std::string & message) } else if (command == "ping") { } else if (command == "frame") { - float timestamp, prevtimestamp; - if ((msgstream >> timestamp) && (msgstream >> prevtimestamp)) { - game()->reset_clientstate(timestamp, prevtimestamp); + unsigned long timestamp; + if ((msgstream >> timestamp)) { + connection_timestamp = timestamp; } } else if (command == "die") { diff --git a/src/core/netconnection.h b/src/core/netconnection.h index cb04ce2..66f7369 100644 --- a/src/core/netconnection.h +++ b/src/core/netconnection.h @@ -48,7 +48,7 @@ public: virtual void disconnect(); /// process pending incoming messages - void frame(float seconds); + void frame(); /// send a connect message to the remote server void send_connect(); @@ -93,6 +93,9 @@ public: State connection_state; + /// return the current game time + inline unsigned long timestamp() const { return connection_timestamp; } + protected: /// add a raw network message to the send queue void send_raw(std::string const &msg); @@ -128,6 +131,8 @@ private: size_t received_compressed_size; size_t compressed_size; char zrecvbuf[BLOCKSIZE]; + + unsigned long connection_timestamp; }; } diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 95b047a..cdcdad7 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -300,7 +300,7 @@ void NetServer::client_initialize(NetClient *client) { } // send updates to one client -void NetServer::client_frame(NetClient *client, float timestamp, float previoustimestamp) +void NetServer::client_frame(NetClient *client, unsigned long timestamp) { if (client->state() != NetClient::Connected) return; @@ -328,7 +328,7 @@ void NetServer::client_frame(NetClient *client, float timestamp, float previoust } else { // send a server frame marker - send_frame_marker(client, timestamp, previoustimestamp); + send_frame_marker(client, timestamp); // send updates for entities in the zone for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { @@ -361,7 +361,7 @@ void NetServer::client_frame(NetClient *client, float timestamp, float previoust } // run a network server frame, send updates to clients -void NetServer::frame(float timestamp, float previoustimestamp) +void NetServer::frame(unsigned long timestamp) { /* FIXME Only entities within visual range should send updates (1024 game units?) @@ -376,7 +376,7 @@ void NetServer::frame(float timestamp, float previoustimestamp) client->transmit(fd()); if (client->state() == NetClient::Connected) - client_frame(client, timestamp, previoustimestamp); + client_frame(client, timestamp); // update player info always gets through if (client->player()->dirty() || client->player()->zonechange()) { @@ -449,10 +449,10 @@ void NetServer::send_disconnect(NetClient *client) } // send a "frame" message to a client -void NetServer::send_frame_marker(NetClient *client, float timestamp, float previoustimestamp) +void NetServer::send_frame_marker(NetClient *client, unsigned long timestamp) { std::ostringstream msg(""); - msg << "frame " << timestamp << " " << previoustimestamp << "\n"; + msg << "frame " << timestamp << "\n"; if (client->state() == NetClient::Connected) { client->send_raw(msg.str()); diff --git a/src/core/netserver.h b/src/core/netserver.h index 1d2e131..8877707 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -53,7 +53,7 @@ public: /*----- mutators -------------------------------------------------- */ /// run a network server frame - void frame(float timestamp, float previoustimestamp); + void frame(unsigned long timestamp); /// receive data from clients void receive(); @@ -72,7 +72,7 @@ public: protected: /// send a server frame marker - void send_frame_marker(NetClient *client, float timestamp, float previoustimestamp); + void send_frame_marker(NetClient *client, unsigned long timestamp); /// send a create entity event void send_entity_create(NetClient *client, Entity *entity); @@ -105,7 +105,7 @@ protected: void parse_incoming_message(NetClient *client, const std::string & message); /// send a server frame to a single client - void client_frame(NetClient *client, float timestamp, float previoustimestamp); + void client_frame(NetClient *client, unsigned long timestamp); private: bool netserver_error; diff --git a/src/core/timer.cc b/src/core/timer.cc index e5a808e..b614af1 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -8,6 +8,7 @@ #include #include +#include namespace core { @@ -26,7 +27,7 @@ void Timer::mark() gettimeofday(&timer_tick, &timer_tz); } -float Timer::elapsed() +unsigned long Timer::timestamp() { struct timeval tick; struct timezone tick_tz; @@ -34,8 +35,15 @@ float Timer::elapsed() gettimeofday(&tick, &tick_tz); // calculate elapsed time in 10^-6 seconds - long delta = (tick.tv_sec - timer_tick.tv_sec) * 1000000 + (tick.tv_usec - timer_tick.tv_usec); - return( (float) delta / 1000000.0f); + unsigned long delta = 0; + delta = tick.tv_sec * 1000 + tick.tv_usec / 1000; + delta -= timer_tick.tv_sec * 1000 + timer_tick.tv_usec / 1000; + return delta; +} + +float Timer::elapsed() +{ + return ((float) timestamp() / 1000.0f); } } diff --git a/src/core/timer.h b/src/core/timer.h index 9e172bf..b878875 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -28,11 +28,14 @@ public: */ void mark(); - /*! return the time elapsed since the last mark + /*! return the time elapsed since the last mark, in seconds * @see mark() */ float elapsed(); + /// return timestamp since last mark, in microseconds + unsigned long timestamp(); + private: float timer_elapsed; struct timezone timer_tz; diff --git a/src/filesystem/diskfile.cc b/src/filesystem/diskfile.cc index 6554f1e..6def055 100644 --- a/src/filesystem/diskfile.cc +++ b/src/filesystem/diskfile.cc @@ -35,6 +35,10 @@ bool DiskFile::open(const char *filename) file_name.assign(filename); file_path.clear(); +#ifdef _WIN32 + for (size_t i = 0; i < file_name.size(); i++) + if (file_name[i] == '/') file_name[i] = '\\'; +#endif for (SearchPath::iterator path = searchpath().begin(); path != searchpath().end(); path++) { std::string fn((*path)); fn.append(filename); diff --git a/src/filesystem/filesystem.cc b/src/filesystem/filesystem.cc index 3404296..a8fca1d 100644 --- a/src/filesystem/filesystem.cc +++ b/src/filesystem/filesystem.cc @@ -153,12 +153,15 @@ void init(std::string const & basename, std::string const & modname) // print search path for (SearchPath::iterator path = filesystem_searchpath.begin(); path != filesystem_searchpath.end(); ++path) { - con_print << " " << (*path) << std::endl; +#ifdef _WIN32 + for (size_t i = 0; i < (*path).size(); i++) + if ((*path)[i] == '/') (*path)[i] = '\\'; +#endif + con_print << " directory: " << (*path) << std::endl; } - con_print << " " << filesystem_searchpath.size() << " directories added to searchpath" << std::endl; // create writedir - con_print << " files are created in " << filesystem_writedir << std::endl; + con_print << " home directory: " << filesystem_writedir << std::endl; } void shutdown() diff --git a/src/render/image.cc b/src/render/image.cc index 7ce8113..e740d56 100644 --- a/src/render/image.cc +++ b/src/render/image.cc @@ -44,6 +44,31 @@ void Image::swap_channels() } } +void Image::pad() +{ + unsigned int w = width(); + unsigned int h = height(); + + if ((w % 8) != 0) { + image_width = w + (8 - (w % 8)); + } + + if ((w % 8) != 0) { + image_height = h + (8 - (h % 8)); + } + + unsigned char *image_new = (unsigned char *) malloc(size()); + memset(image_new, 0, size()); + + for (size_t y =0; y < h; y++) { + memcpy((void *)&image_new[y * image_width * image_channels], + (void *)image_data[y * w * image_channels], (size_t) w); + } + + free(image_data); + image_data = image_new; +} + void Image::flip() { unsigned char line[image_width*image_channels]; diff --git a/src/render/image.h b/src/render/image.h index 3c82792..c7add6f 100644 --- a/src/render/image.h +++ b/src/render/image.h @@ -47,6 +47,9 @@ public: /// flip upside-down void flip(); + /// pad width and height up to 8 bytes + void pad(); + private: unsigned char *image_data; diff --git a/src/render/render.cc b/src/render/render.cc index fbbaba1..55756d9 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -43,9 +43,6 @@ void func_list_textures(std::string const &args) void reset_gl() { - // setup our viewport. - gl::viewport(0, 0, Camera::width(), Camera::height()); - // set clear color gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); @@ -152,6 +149,13 @@ void init() func->set_info("list loaded textures"); } +void resize(int width, int height) +{ + // setup our viewport. + gl::viewport(0, 0, width, height); + Camera::resize(width, height); +} + // unload game assets (zone change) void unload() { @@ -313,8 +317,15 @@ void screenshot() image.flip(); if (filetype == TYPEPNG) { +/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { + image.pad(); + }*/ render::PNG::save(filename.c_str(), image); } else if (filetype == TYPEJPG) { +/* if ((Camera::width() % 8 != 0 ) || (Camera::height() % 8 != 0 )) { + image.pad(); + } +*/ render::JPG::save(filename.c_str(), image, (int) screenshotquality->value()); } else if (filetype == TYPETGA) { render::TGA::save(filename.c_str(), image); diff --git a/src/render/render.h b/src/render/render.h index cd90953..a7aec70 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -38,6 +38,9 @@ namespace render { /// make a screenshot void screenshot(); + /// resize viewport + void resize(int w, int h); + extern core::Cvar *r_arraysize; extern core::Cvar *r_bbox; extern core::Cvar *r_grid; diff --git a/src/server/console.cc b/src/server/console.cc index ab03c58..9fdad4f 100644 --- a/src/server/console.cc +++ b/src/server/console.cc @@ -104,7 +104,7 @@ Console::~Console() void Console::dump() { // dump console content - for (Text::iterator it = log().begin(); it != log().end(); it++) { + for (Queue::iterator it = log().begin(); it != log().end(); it++) { sys::ConsoleInterface::print((*it)); } } @@ -200,8 +200,8 @@ void Console::draw_status() if (core::game()) { attroff(A_BOLD); color_set(2, NULL); - int minutes = (int) floorf(core::game()->serverframetime() / 60.0f); - int seconds = (int) floorf( core::game()->serverframetime() - (float) minutes* 60.0f); + int minutes = (int) floorf(core::game()->time() / 60.0f); + int seconds = (int) floorf( core::game()->time() - (float) minutes* 60.0f); std::stringstream status; status << "time " << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; mvaddnstr(0, 2, status.str().c_str(), status.str().size()); @@ -215,7 +215,7 @@ void Console::draw_text() if ((w < 3) || (h < 3)) return; - Text lines; + Queue lines; int height = stdwin->_maxy - 1; int width = stdwin->_maxx - 1; @@ -223,7 +223,7 @@ void Console::draw_text() int current_line = 0; // parse console text, wrap long lines - for (Text::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) { + for (Queue::iterator it = log().begin(); it != log().end() && current_line < bottom; it++) { if (current_line >= bottom - height) { std::string linedata(*it); linedata += '\n'; @@ -314,7 +314,7 @@ void Console::draw_text() color_set(0, NULL); attroff(A_BOLD); - for (Text::reverse_iterator rit = lines.rbegin(); (y > 0) && (rit != lines.rend()); ++rit) { + for (Queue::reverse_iterator rit = lines.rbegin(); (y > 0) && (rit != lines.rend()); ++rit) { const char *c = (*rit).c_str(); int x = 0; @@ -360,10 +360,10 @@ void Console::draw() console_updated = false; } -void Console::frame(float seconds) +void Console::frame() { const size_t scroll_offset = 3; - Text::reverse_iterator upit; + History::reverse_iterator upit; if (!console_initialized) return; @@ -467,9 +467,9 @@ void Console::frame(float seconds) if (input_updated) { draw_input(); } - if (roundf(core::game()->serverframetime()) != prev_time) { + if (roundf(core::application()->time()) != prev_time) { draw_status(); - prev_time = roundf(core::game()->serverframetime()); + prev_time = roundf(core::application()->time()); input_updated = true; } if (input_updated) { diff --git a/src/server/console.h b/src/server/console.h index 59d65d9..13db3fc 100644 --- a/src/server/console.h +++ b/src/server/console.h @@ -25,7 +25,7 @@ public: /// resize the console virtual void resize(); /// run one console frame - void frame(float seconds); + void frame(); protected: /// draw the ncurses console @@ -44,12 +44,14 @@ protected: virtual void print(const std::string & text); private: + typedef std::deque History; + /// set ncurses drawing color void set_color(const char *color_code); // input history - Text history; - Text::reverse_iterator history_pos; + History history; + History::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 f08ca6c..a4424a0 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -58,7 +58,8 @@ void Server::init(int count, char **arguments) { con_print << "^BInitializing server..." << std::endl; - core::Cvar::sv_private = core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly); + core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly); + core::Application::init(count, arguments); Console::init(); @@ -78,15 +79,13 @@ void Server::run() server_framerate = 1.0f / core::Cvar::sv_framerate->value(); core::Timer timer; - float elapsed = 0; + timer.mark(); - while(connected()) { - timer.mark(); - frame(elapsed); + while(connected()) { + frame(timer.timestamp()); #ifdef HAVE_CURSES - console()->frame(elapsed); + console()->frame(); #endif - elapsed = timer.elapsed(); } } diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h index 3a7d3ed..2eae1d8 100644 --- a/src/sys/consoleinterface.h +++ b/src/sys/consoleinterface.h @@ -95,14 +95,14 @@ public: /// enable or disable rcon void set_rcon(bool enable = true); - typedef std::deque Text; + typedef std::deque Queue; - inline Text & rconbuf() + inline Queue & rconbuf() { return consoleinterface_rconbuf; } - inline Text & log() + inline Queue & log() { return consoleinterface_log; } @@ -126,9 +126,9 @@ private: static ConsoleInterface *consoleinterface_instance; bool consoleinterface_rcon; - Text consoleinterface_rconbuf; + Queue consoleinterface_rconbuf; - Text consoleinterface_log; + Queue consoleinterface_log; size_t consoleinterface_logsize; }; diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index a68c307..4bfad3d 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -7,9 +7,9 @@ else noinst_LTLIBRARIES = libui.la endif -noinst_HEADERS = bitmap.h button.h container.h definitions.h font.h input.h label.h \ +noinst_HEADERS = bitmap.h button.h container.h definitions.h font.h inputbox.h label.h \ menu.h paint.h palette.h ui.h widget.h window.h -libui_la_SOURCES = bitmap.cc button.cc container.cc font.cc input.cc label.cc \ +libui_la_SOURCES = bitmap.cc button.cc container.cc font.cc inputbox.cc label.cc \ menu.cc paint.cc palette.cc ui.cc widget.cc window.cc libui_la_LDFLAGS = -avoid-version -no-undefined diff --git a/src/ui/button.cc b/src/ui/button.cc index 08fd0e9..e36d036 100644 --- a/src/ui/button.cc +++ b/src/ui/button.cc @@ -71,18 +71,18 @@ void Button::draw_text() } bool Button::on_keypress(const int key, const unsigned int modifier) -{ - return false; -} - -bool Button::on_keyrelease(const int key, const unsigned int modifier) -{ +{ if (key == 512 + SDL_BUTTON_LEFT) { core::cmd() << button_command << std::endl; audio::play("ui/button"); return true; } - + + return false; +} + +bool Button::on_keyrelease(const int key, const unsigned int modifier) +{ return false; } diff --git a/src/ui/container.cc b/src/ui/container.cc index 5a12e8e..37fbea8 100644 --- a/src/ui/container.cc +++ b/src/ui/container.cc @@ -6,6 +6,7 @@ #include "ui/container.h" +#include "ui/paint.h" namespace ui { @@ -31,9 +32,8 @@ void Container::resize() { float w = container_childsize.width() * 1.5f; 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_childsize.height() * 0.5f; @@ -56,4 +56,17 @@ void Container::set_margin(const float margin) container_margin = margin; } +void Container::draw_border() +{ + if (!border()) + return; + + if(focus()) { + paint::color(palette()->foreground()); + } else { + paint::color(palette()->border()); + } + paint::border(global_location(), size()); +} + } diff --git a/src/ui/container.h b/src/ui/container.h index ae97bdf..5556759 100644 --- a/src/ui/container.h +++ b/src/ui/container.h @@ -27,6 +27,8 @@ public: inline float margin() const { return container_margin; } protected: + virtual void draw_border(); + virtual void resize(); private: diff --git a/src/ui/definitions.h b/src/ui/definitions.h index b9b4e3c..ea3e040 100644 --- a/src/ui/definitions.h +++ b/src/ui/definitions.h @@ -23,6 +23,8 @@ enum Alignment { AlignCenter = AlignHCenter | AlignVCenter }; +const float pointer_size = 48.0f; + } #endif // __INCLUDED_UI_DEFINITIONS_H__ diff --git a/src/ui/input.cc b/src/ui/input.cc deleted file mode 100644 index 8113354..0000000 --- a/src/ui/input.cc +++ /dev/null @@ -1,184 +0,0 @@ -/* - ui/input.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#include "ui/input.h" -#include "ui/paint.h" -#include "auxiliary/functions.h" -#include "core/core.h" - -namespace ui -{ - -Input::Input(Widget *parent) : Widget(parent) -{ - input_text.clear(); - input_pos = 0; - - set_label("input"); - set_background(false); - set_border(false); -} - -Input::~Input() -{ -} - -void Input::clear() -{ - input_text.clear(); - input_pos = 0; -} -void Input::set_text(std::string const &text) -{ - input_text.assign(text); - input_pos = input_text.size(); -} - -void Input::set_text(const char *text) -{ - if (text) - input_text.assign(text); - else - input_text.clear(); - input_pos = input_text.size(); -} - -void Input::draw() -{ - draw_background(); - draw_border(); - - size_t text_width = (size_t) floorf(width() / font()->width()); - math::Vector2f v(global_location()); - paint::color(palette()->foreground()); - - // draw the part before the cursor - std::string firstpart(input_text.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 > text_width - 2) { - if (aux::is_color_code(c)) { - c++; - paint::color_code(*c); - } else { - draw_width--; - } - c++; - } - - if (*c) { - paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter); - } - - // draw the part behind the cursor - 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)) { - paint::color_code(input_text[input_pos]); - } - // limit to width - std::string secondpart; - c = &input_text.c_str()[input_pos]; - while (*c && (draw_width <= (text_width - 2))) { - if (aux::is_color_code(c)) { - c++; - } else { - draw_width++; - secondpart += *c; - } - c++; - } - - paint::text(v, size(), font(), secondpart, AlignLeft | AlignVCenter); - } - - // draw the cursor - if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { - std::string cursor("^B"); - cursor += (char) 11; - paint::text(v, size(), font(), cursor, AlignLeft | AlignVCenter); - } -} - -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; - - case SDLK_HOME: - input_pos = 0; - return true; - break; - - case SDLK_END: - input_pos = input_text.size(); - return true; - break; - - case SDLK_LEFT: - if (input_pos > 0) - input_pos--; - return true; - break; - - case SDLK_RIGHT: - if (input_pos < input_text.size()) - input_pos++; - return true; - break; - - case SDLK_DELETE: - if (input_text.size() && input_pos < input_text.size()) { - input_text.erase(input_pos, 1); - } - return true; - break; - - case SDLK_BACKSPACE: - if (input_text.size() && input_pos) { - input_text.erase(input_pos-1, 1); - input_pos--; - } - return true; - break; - - default: - if ((key >= 32) && (key <175)) { - if (input_pos == input_text.size()) - input_text += (char)key; - else - input_text.insert(input_pos, 1, (char)key); - input_pos++; - return true; - } - break; - } - - return false; -} -bool Input::on_keyrelease(const int key, const unsigned int modifier) -{ - return false; -} - -} - - diff --git a/src/ui/input.h b/src/ui/input.h deleted file mode 100644 index 214f63e..0000000 --- a/src/ui/input.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - ui/input.h - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#ifndef __INCLUDED_UI_INPUT_H__ -#define __INCLUDED_UI_INPUT_H__ - -#include "ui/widget.h" - -namespace ui -{ - -/// text input widget -class Input : public Widget -{ -public: - Input(Widget *parent); - ~Input(); - - /// set the text displayed by the label - void set_text(std::string const &text); - - /// set the text displayed by the label - void set_text(const char *text); - - /// return the text displayed by the label - inline std::string const &text() const { - return input_text; - } - - /// clear the text - void clear(); - -protected: - /// draw the widget - virtual void draw(); - - /// called when the widget receives a key press - virtual bool on_keypress(const int key, const unsigned int modifier); - - /// called when the widget receives a key release - virtual bool on_keyrelease(const int key, const unsigned int modifier); - -private: - - std::string input_text; - size_t input_pos; -}; - -} - -#endif // __INCLUDED_UI_INPUT_H__ - diff --git a/src/ui/inputbox.cc b/src/ui/inputbox.cc new file mode 100644 index 0000000..30cae3b --- /dev/null +++ b/src/ui/inputbox.cc @@ -0,0 +1,184 @@ +/* + ui/inputbox.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/inputbox.h" +#include "ui/paint.h" +#include "auxiliary/functions.h" +#include "core/core.h" + +namespace ui +{ + +InputBox::InputBox(Widget *parent) : Widget(parent) +{ + input_text.clear(); + input_pos = 0; + + set_label("input"); + set_background(false); + set_border(false); +} + +InputBox::~InputBox() +{ +} + +void InputBox::clear() +{ + input_text.clear(); + input_pos = 0; +} +void InputBox::set_text(std::string const &text) +{ + input_text.assign(text); + input_pos = input_text.size(); +} + +void InputBox::set_text(const char *text) +{ + if (text) + input_text.assign(text); + else + input_text.clear(); + input_pos = input_text.size(); +} + +void InputBox::draw() +{ + draw_background(); + draw_border(); + + size_t text_width = (size_t) floorf(width() / font()->width()); + math::Vector2f v(global_location()); + paint::color(palette()->foreground()); + + // draw the part before the cursor + std::string firstpart(input_text.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 > text_width - 2) { + if (aux::is_color_code(c)) { + c++; + paint::color_code(*c); + } else { + draw_width--; + } + c++; + } + + if (*c) { + paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter); + } + + // draw the part behind the cursor + 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)) { + paint::color_code(input_text[input_pos]); + } + // limit to width + std::string secondpart; + c = &input_text.c_str()[input_pos]; + while (*c && (draw_width <= (text_width - 2))) { + if (aux::is_color_code(c)) { + c++; + } else { + draw_width++; + secondpart += *c; + } + c++; + } + + paint::text(v, size(), font(), secondpart, AlignLeft | AlignVCenter); + } + + // draw the cursor + if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { + std::string cursor("^B"); + cursor += (char) 11; + paint::text(v, size(), font(), cursor, AlignLeft | AlignVCenter); + } +} + +bool InputBox::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; + + case SDLK_HOME: + input_pos = 0; + return true; + break; + + case SDLK_END: + input_pos = input_text.size(); + return true; + break; + + case SDLK_LEFT: + if (input_pos > 0) + input_pos--; + return true; + break; + + case SDLK_RIGHT: + if (input_pos < input_text.size()) + input_pos++; + return true; + break; + + case SDLK_DELETE: + if (input_text.size() && input_pos < input_text.size()) { + input_text.erase(input_pos, 1); + } + return true; + break; + + case SDLK_BACKSPACE: + if (input_text.size() && input_pos) { + input_text.erase(input_pos-1, 1); + input_pos--; + } + return true; + break; + + default: + if ((key >= 32) && (key <175)) { + if (input_pos == input_text.size()) + input_text += (char)key; + else + input_text.insert(input_pos, 1, (char)key); + input_pos++; + return true; + } + break; + } + + return false; +} +bool InputBox::on_keyrelease(const int key, const unsigned int modifier) +{ + return false; +} + +} + + diff --git a/src/ui/inputbox.h b/src/ui/inputbox.h new file mode 100644 index 0000000..557ca6c --- /dev/null +++ b/src/ui/inputbox.h @@ -0,0 +1,55 @@ +/* + ui/inputbox.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_INPUTBOX_H__ +#define __INCLUDED_UI_INPUTBOX_H__ + +#include "ui/widget.h" + +namespace ui +{ + +/// text input widget +class InputBox : public Widget +{ +public: + InputBox(Widget *parent); + ~InputBox(); + + /// set the text displayed by the label + void set_text(std::string const &text); + + /// set the text displayed by the label + void set_text(const char *text); + + /// return the text displayed by the label + inline std::string const &text() const { + return input_text; + } + + /// clear the text + void clear(); + +protected: + /// draw the widget + virtual void draw(); + + /// called when the widget receives a key press + virtual bool on_keypress(const int key, const unsigned int modifier); + + /// called when the widget receives a key release + virtual bool on_keyrelease(const int key, const unsigned int modifier); + +private: + + std::string input_text; + size_t input_pos; +}; + +} + +#endif // __INCLUDED_UI_INPUTBOX_H__ + diff --git a/src/ui/menu.h b/src/ui/menu.h index a909e20..e3a853a 100644 --- a/src/ui/menu.h +++ b/src/ui/menu.h @@ -36,7 +36,7 @@ public: /// add a button with a command Button *add_button(char const *text=0, char const *command=0); - + protected: /// resize event virtual void resize(); diff --git a/src/ui/palette.cc b/src/ui/palette.cc index 20d1e93..3a9dc78 100644 --- a/src/ui/palette.cc +++ b/src/ui/palette.cc @@ -24,6 +24,33 @@ Palette::~Palette() { } +const math::Color &Palette::color(Color palettecolor) const +{ + switch(palettecolor) { + case Foreground: + return foreground(); + break; + case Background: + return background(); + break; + case Highlight: + return highlight(); + break; + case Border: + return border(); + break; + case Pointer: + return pointer(); + break; + case Active: + return active(); + break; + default: + return foreground(); + break; + } +} + void Palette::set_foreground(math::Color const &color) { palette_foreground.assign(color); diff --git a/src/ui/palette.h b/src/ui/palette.h index 9d27f95..41eee03 100644 --- a/src/ui/palette.h +++ b/src/ui/palette.h @@ -19,6 +19,8 @@ public: Palette(); ~Palette(); + enum Color { Foreground=0, Background=1, Highlight=2, Border=3, Pointer=4, Active=5 }; + void set_foreground(math::Color const &color); void set_highlight(math::Color const &color); @@ -31,29 +33,31 @@ public: void set_active(math::Color const &color); - inline math::Color const &foreground() const { + inline const math::Color &foreground() const { return palette_foreground; } - inline math::Color const &highlight() const { + inline const math::Color &highlight() const { return palette_highlight; } - inline math::Color const &background() const { + inline const math::Color &background() const { return palette_background; } - inline math::Color const &border() const { + inline const math::Color &border() const { return palette_border; } - inline math::Color const &pointer() const { + inline const math::Color &pointer() const { return palette_pointer; } - inline math::Color const &active() const { + inline const math::Color &active() const { return palette_active; } + + const math::Color &color(Palette::Color palettecolor) const; private: diff --git a/src/ui/ui.cc b/src/ui/ui.cc index baedd38..1ecfbb1 100644 --- a/src/ui/ui.cc +++ b/src/ui/ui.cc @@ -7,13 +7,16 @@ #include #include +#include "audio/audio.h" #include "auxiliary/functions.h" #include "core/core.h" #include "filesystem/filesystem.h" +#include "render/gl.h" #include "sys/sys.h" #include "ui/button.h" #include "ui/label.h" #include "ui/menu.h" +#include "ui/paint.h" #include "ui/ui.h" #include "ui/widget.h" @@ -204,6 +207,9 @@ UI::UI() : Window(0) ui_mouse_focus = this; ui_input_focus = this; set_focus(); + + mouse_pointer_color = Palette::Pointer; + mouse_pointer_bitmap.assign("pointer"); } UI::~UI() @@ -386,7 +392,9 @@ void UI::show_menu(const char *label) ui_active_menu = menu; ui_active_menu->event_resize(); - ui_active_menu->show(); + ui_active_menu->show(); + + set_pointer("pointer"); } else { con_warn << "Unknown window '" << label << "'" << std::endl; } @@ -418,6 +426,9 @@ void UI::frame() } event_draw(); + + if (visible()) + draw_pointer(); } /* -- global event handlers ---------------------------------------- */ @@ -453,21 +464,18 @@ bool UI::input_key(const bool pressed, const int key, const unsigned int modifie return handled; } -/* -- event handlers ----------------------------------------------- */ -/* - These functions handle events for this widget only. They are - the fallback input handlers -*/ bool UI::on_keypress(const int key, const unsigned int modifier) { switch( key ) { case SDLK_ESCAPE: if (active()) { - previous_menu(); + hide_menu(); + audio::play("ui/menu"); } else { if (core::application()->connected()) { show_menu("game"); + audio::play("ui/menu"); } } return true; @@ -484,5 +492,51 @@ bool UI::on_keyrelease(const int key, const unsigned int modifier) return false; } +void UI::set_pointer(const char *pointerbitmap, const Palette::Color color, const bool animated) +{ + if (!pointerbitmap) { + mouse_pointer_bitmap.clear(); + } else { + mouse_pointer_bitmap.assign(pointerbitmap); + } + mouse_pointer_animated = animated; + mouse_pointer_color = color; +} + +void UI::draw_pointer() +{ + if (!mouse_pointer_bitmap.size()) + return; + + math::Color c(palette()->color(mouse_pointer_color)); + if (mouse_pointer_animated) { + c.a = 1; + } else { + c.a = 0.5f; + } + paint::color(c); + math::Vector2f pos(mouse_cursor.x - pointer_size * 0.5f, mouse_cursor.y - pointer_size * 0.5f); + math::Vector2f s(pointer_size, pointer_size); + + std::string texture("pointers/"); + texture.append(mouse_pointer_bitmap); + + if (mouse_pointer_animated) { + render::gl::push(); + render::gl::translate(mouse_cursor.x, mouse_cursor.y, 0); + + float angle = core::application()->time()* 0.75f - floorf(core::application()->time() * 0.75f); + angle *= 360.0f; + render::gl::rotate(angle, math::Vector3f(0, 0, 1.0f)); + render::gl::translate(-mouse_cursor.x, -mouse_cursor.y, 0); + } + + paint::bitmap(pos, s, texture); + + if (mouse_pointer_animated) { + render::gl::pop(); + } +} + } diff --git a/src/ui/ui.h b/src/ui/ui.h index 8fa32c2..24f9793 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -62,7 +62,7 @@ public: /// receive global key input bool input_key(const bool pressed, const int key, const unsigned int modifier); - + /// run a user interface frame void frame(); @@ -77,7 +77,12 @@ public: inline const Font *font_large() const { return ui_font_large; } - + + /* -- mouse pointer ---------------------------------------- */ + + /// set mouse pointer bitmap + void set_pointer(const char *pointerbitmap=0, const Palette::Color color = Palette::Highlight,const bool animated = false); + protected: typedef std::list Menus; @@ -95,6 +100,8 @@ protected: virtual bool on_keyrelease(const int key, const unsigned int modifier); private: + void draw_pointer(); + Palette *ui_palette; Font *ui_font_small; Font *ui_font_large; @@ -106,7 +113,10 @@ private: Menus ui_menus; /// TODO move to separate object to handle mouse cursor drawing - math::Vector2f mouse_cursor; + math::Vector2f mouse_cursor; + std::string mouse_pointer_bitmap; + Palette::Color mouse_pointer_color; + bool mouse_pointer_animated; }; /// initialize the user interface diff --git a/src/ui/widget.cc b/src/ui/widget.cc index 24dfe5c..606c4ab 100644 --- a/src/ui/widget.cc +++ b/src/ui/widget.cc @@ -209,6 +209,7 @@ void Widget::set_width(float const w) { widget_size.x = w; } + void Widget::set_height(float const h) { widget_size.y = h; @@ -339,10 +340,11 @@ void Widget::event_draw() void Widget::event_resize() { + resize(); + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { (*it)->event_resize(); } - resize(); } /* -- event handlers ----------------------------------------------- */ diff --git a/src/ui/widget.h b/src/ui/widget.h index 41ad795..ef386c0 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -200,7 +200,7 @@ protected: /// find the widget that has input focus virtual Widget *find_input_focus(); - + /// find widget that has mosue focus /** @param cursor mouse cursor position relative to this widget's location */ diff --git a/src/ui/window.cc b/src/ui/window.cc index 3015a10..9ae9ec5 100644 --- a/src/ui/window.cc +++ b/src/ui/window.cc @@ -50,12 +50,8 @@ void Window::draw_border() if (!border()) return; - if(focus()) { - paint::color(palette()->foreground()); - } else { - paint::color(palette()->border()); - } - paint::border(global_location(), size()); + paint::color(palette()->border()); + paint::border(global_location(), size()); } } diff --git a/src/ui/window.h b/src/ui/window.h index 412d1f1..2a077ff 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -20,8 +20,6 @@ public: Window(Widget *parent=0); ~Window(); - virtual void draw_border(); - /// set the label of the previous window void set_previous(Window *previous); @@ -38,6 +36,7 @@ public: } protected: + virtual void draw_border(); std::string window_previous; }; -- cgit v1.2.3