diff --git a/asteroids/View.cc b/asteroids/View.cc index 53e2ee5..752855f 100644 --- a/asteroids/View.cc +++ b/asteroids/View.cc @@ -40,7 +40,7 @@ int View::OnInit (int argc, char* argv[]) { mOverlayManager.Register (mConsoleOverlay, GameStateMainMenu); */ - LoadFont("AldotheApache.ttf", 20); + LoadFont("AldotheApache.ttf size=20 color=#000000"); // This is a simple star field that makes the game so spacy int i; @@ -411,7 +411,7 @@ void View::DrawUiMainMenu() { void View::DrawUiGameRunning() { // We choose a different font and also draw it aligned to the right as this // looks nicer with the points - SelectFont ("AldotheApache.ttf"); + SelectFont ("AldotheApache.ttf size=20 color=#ffffff"); SetFontJustification (Engine::FontJustificationRight); std::ostringstream out_stream; @@ -530,9 +530,9 @@ void View::DrawUiHighscore() { // the name) if (GetModel()->mNewestHighscoreEntryIndex < GetModel()->mHighscoreList.size() && GetModel()->mNewestHighscoreEntryIndex == i) { - SetFontColor (224./255., 200/255., 0.); + SelectFont("console.ttf color=#e8d500"); Engine::DrawGLString ( x, y, out_stream.str().c_str()); - SetFontColor (1., 1., 1.); + SelectFont("console.ttf color=#ffffff"); } else { Engine::DrawGLString ( x, y, out_stream.str().c_str()); } @@ -554,7 +554,8 @@ void View::DrawUiEnterPlayername() { // Enter your name std::string player_name = GetModel()->GetPlayerName(); - + + SelectFont("console.ttf"); Engine::GUI::Label (1, "Enter your name: ", screen_right * 0.5 - 100, 250); if (Engine::GUI::LineEdit (2, screen_right * 0.5 + 20, 238, player_name, 16)) { diff --git a/engine/ViewBase.cc b/engine/ViewBase.cc index f04524d..2f7e5f0 100644 --- a/engine/ViewBase.cc +++ b/engine/ViewBase.cc @@ -55,7 +55,6 @@ int ViewBase::OnInit (int argc, char* argv[]) { LoadFont ("console.ttf"); mCurrentFont = mFonts["console.ttf"]; - SetFontColor (1., 1., 1.); // Overlays OverlayBasePtr console_overlay(new SimpleConsoleOverlay); @@ -189,20 +188,107 @@ void ViewBase::PostDraw() { } /* Fonts */ -bool ViewBase::LoadFont (const char *font_name, float point_size) { + +/** \brief Parses font specifications strings into its values + * + * Fonts can be specified by strings such as + * name=default.ttf color=#ff0000 size=12 + * color=#ff00ff size=12 otherfont.ttf + * myfont.ttf + * for which the appropriate values will be parsed. Default size is 12 and + * default color is white (#ffffff) + */ +void parse_font_spec_string (const std::string &spec_string, + std::string &font_name, + float font_color[3], + float *font_size) { + // set default values + font_name = "default.ttf"; + font_color[0] = 1.f; + font_color[1] = 1.f; + font_color[2] = 1.f; + *font_size = 12.f; + + // perform the actual parsing + std::string::size_type pos = 0; + + while (pos < spec_string.size()) { + std::string::size_type next_start = spec_string.find_first_not_of(" \t", pos); + // if we don't find anything we break out of this loop + if (next_start == std::string::npos) + break; + + // find the next token + std::string::size_type next_end = spec_string.find_first_of("\t ", next_start); + std::string token (spec_string.substr(next_start, next_end - next_start)); + + // If no id was given it is automatically set to name + std::string id("name"); + std::string value(token); + + // Split the token into id and value if there is an '=' sign. + if (token.find('=', 0) != std::string::npos) { + id = token.substr(0, token.find('=',0)); + value = token.substr(id.size() + 1, token.size()); + } + + // std::cout << "id = " << id << " value = " << value << std::endl; + + if (id == "name") + font_name = value; + else if (id == "size") { + std::istringstream istr(value); + istr >> *font_size; + } else if (id == "color") { + // we assume #RRGGBB specification + if (value[0] != '#' || value.size() != 7) + LogError ("Invalid font color specification '%s'. Please specify as #rrggbb!", value.c_str()); + + // convert the color string to float values + int num; + std::istringstream istr(value.substr(1, 2)); + istr >> std::hex >> num; + font_color[0] = static_cast(num) / 255.; + + istr.clear(); + istr.str(value.substr(3,2)); + istr >> std::hex >> num; + font_color[1] = static_cast(num) / 255.; + + istr.clear(); + istr.str(value.substr(5,2)); + istr >> std::hex >> num; + font_color[2] = static_cast(num) / 255.; + } + + pos = next_end; + } +} + +bool ViewBase::LoadFont (const std::string &font_spec_string) { + // font_spec_string can be of the form + // (name=) (color=) (size=) + + std::string font_name; + float font_size = 12.; + float font_color[3] = {1., 1., 1.}; + + parse_font_spec_string(font_spec_string, font_name, font_color, &font_size); + std::string font_path ("./data/fonts/"); font_path += font_name; - - LogDebug ("Loading font %s size %f from %s", font_name, point_size, font_path.c_str()); - OGLFT::Monochrome *font = new OGLFT::Monochrome (font_path.c_str(), point_size); + LogDebug ("Loading font %s color (%1.2f, %1.2f, %1.2f) size %f from %s", font_name.c_str(), font_color[0], font_color[1], font_color[2], font_size, font_path.c_str()); + + OGLFT::Monochrome *font = new OGLFT::Monochrome (font_path.c_str(), font_size); if ( font == 0 || !font->isValid() ) { LogError ("Could not load font %s!", font_path.c_str()); return false; } - font->setForegroundColor(1., 1., 1.); - mFonts.insert(std::make_pair(font_name, font)); + font->setForegroundColor(font_color[0], font_color[1], font_color[2]); + + mFonts.insert(std::make_pair(font_spec_string, font)); return true; } @@ -217,8 +303,10 @@ void ViewBase::SelectFont (const char *font) { return; } - LogDebug ("Font %s not found, trying to load it", font); + LogDebug ("Selecting font %s failed, trying to load it", font); + LogDebug ("font count = %d", mFonts.size()); if (LoadFont (font)) { + LogDebug ("font count = %d", mFonts.size()); font_iter = mFonts.find(font); assert (mFonts.find(font) != mFonts.end()); @@ -232,6 +320,8 @@ void ViewBase::SelectFont (const char *font) { } void ViewBase::SetFontJustification (FontJustification justification) { + assert (mCurrentFont != NULL); + if (justification == FontJustificationRight) mCurrentFont->setHorizontalJustification(OGLFT::Face::RIGHT); else if (justification == FontJustificationCenter) @@ -240,11 +330,6 @@ void ViewBase::SetFontJustification (FontJustification justification) { } -void ViewBase::SetFontColor (float r, float g, float b) { - assert (mCurrentFont); - mCurrentFont->setForegroundColor(r, g, b); -}; - void ViewBase::DrawGLString (float x, float y, const char* str) { glPixelStorei (GL_UNPACK_ALIGNMENT, 1); mCurrentFont->draw (x, y, str); diff --git a/engine/ViewBase.h b/engine/ViewBase.h index 8dddd5f..7b7a919 100644 --- a/engine/ViewBase.h +++ b/engine/ViewBase.h @@ -36,14 +36,20 @@ class ViewBase : public Module{ virtual void Draw (); /* Fonts */ - bool LoadFont (const char *font_name, float point_size=12); - void SelectFont (const char *font_name); - void SetFontJustification (FontJustification justification); - /** \brief Sets the color of the current font + + /** \brief Selects a font with a given specification or loads it if it was not found + * + * Fonts can be specified by strings such as + * "name=default.ttf color=#ff0000 size=12" + * "color=#ff00ff size=12 otherfont.ttf" + * "myfont.ttf" + * for which the appropriate values will be parsed. * - * \note This function should be avoided as the glyphs have to be re-rendered + * Default size is 12 and default color is white (#ffffff). */ - void SetFontColor (float r, float g, float b); + void SelectFont (const char *font_spec); + void SetFontJustification (FontJustification justification); + /** \brief Draws a string at the given position using current projection * and modelview matrices */ void DrawGLString (float x, float y, const char* str); @@ -94,6 +100,8 @@ class ViewBase : public Module{ void DrawGrid (); bool mDrawGrid; + /** \brief Loads a font that was not yet loaded */ + bool LoadFont (const std::string &font_spec_string); ModelBase *mModel; CameraBase *mCamera;