texteff.cpp

Go to the documentation of this file.
00001 /* $Id: texteff.cpp 14047 2008-08-11 22:45:11Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "landscape.h"
00008 #include "gfx_func.h"
00009 #include "variables.h"
00010 #include "texteff.hpp"
00011 #include "core/bitmath_func.hpp"
00012 #include "transparency.h"
00013 #include "strings_func.h"
00014 #include "core/alloc_func.hpp"
00015 #include "functions.h"
00016 #include "viewport_func.h"
00017 #include "settings_type.h"
00018 
00019 enum {
00020   INIT_NUM_TEXT_EFFECTS  =  20,
00021 };
00022 
00023 struct TextEffect {
00024   StringID string_id;
00025   int32 x;
00026   int32 y;
00027   int32 right;
00028   int32 bottom;
00029   uint16 duration;
00030   uint64 params_1;
00031   uint64 params_2;
00032   TextEffectMode mode;
00033 };
00034 
00035 /* used for text effects */
00036 static TextEffect *_text_effect_list = NULL;
00037 static uint16 _num_text_effects = INIT_NUM_TEXT_EFFECTS;
00038 
00039 /* Text Effects */
00048 static void MarkTextEffectAreaDirty(TextEffect *te)
00049 {
00050   /* Width and height of the text effect are doubled, so they are correct in both zoom out levels 1x and 2x. */
00051   MarkAllViewportsDirty(
00052     te->x,
00053     te->y - 1,
00054     (te->right - te->x)*2 + te->x + 1,
00055     (te->bottom - (te->y - 1)) * 2 + (te->y - 1) + 1
00056   );
00057 }
00058 
00059 TextEffectID AddTextEffect(StringID msg, int x, int y, uint16 duration, TextEffectMode mode)
00060 {
00061   TextEffect *te;
00062   int w;
00063   char buffer[100];
00064   TextEffectID i;
00065 
00066   if (_game_mode == GM_MENU) return INVALID_TE_ID;
00067 
00068   /* Look for a free spot in the text effect array */
00069   for (i = 0; i < _num_text_effects; i++) {
00070     if (_text_effect_list[i].string_id == INVALID_STRING_ID) break;
00071   }
00072 
00073   /* If there is none found, we grow the array */
00074   if (i == _num_text_effects) {
00075     _num_text_effects += 25;
00076     _text_effect_list = ReallocT<TextEffect>(_text_effect_list, _num_text_effects);
00077     for (; i < _num_text_effects; i++) _text_effect_list[i].string_id = INVALID_STRING_ID;
00078     i = _num_text_effects - 1;
00079   }
00080 
00081   te = &_text_effect_list[i];
00082 
00083   /* Start defining this object */
00084   te->string_id = msg;
00085   te->duration = duration;
00086   te->y = y - 5;
00087   te->bottom = y + 5;
00088   te->params_1 = GetDParam(0);
00089   te->params_2 = GetDParam(4);
00090   te->mode = mode;
00091 
00092   GetString(buffer, msg, lastof(buffer));
00093   w = GetStringBoundingBox(buffer).width;
00094 
00095   te->x = x - (w >> 1);
00096   te->right = x + (w >> 1) - 1;
00097   MarkTextEffectAreaDirty(te);
00098 
00099   return i;
00100 }
00101 
00102 void UpdateTextEffect(TextEffectID te_id, StringID msg)
00103 {
00104   assert(te_id < _num_text_effects);
00105   TextEffect *te;
00106 
00107   /* Update details */
00108   te = &_text_effect_list[te_id];
00109   te->string_id = msg;
00110   te->params_1 = GetDParam(0);
00111   te->params_2 = GetDParam(4);
00112 
00113   /* Update width of text effect */
00114   char buffer[100];
00115   GetString(buffer, msg, lastof(buffer));
00116   int w = GetStringBoundingBox(buffer).width;
00117 
00118   /* Only allow to make it broader, so it completely covers the old text. That avoids remnants of the old text. */
00119   int right_new = te->x + w;
00120   if (te->right < right_new) te->right = right_new;
00121 
00122   MarkTextEffectAreaDirty(te);
00123 }
00124 
00125 void RemoveTextEffect(TextEffectID te_id)
00126 {
00127   assert(te_id < _num_text_effects);
00128   TextEffect *te;
00129 
00130   te = &_text_effect_list[te_id];
00131   MarkTextEffectAreaDirty(te);
00132   te->string_id = INVALID_STRING_ID;
00133 }
00134 
00135 static void MoveTextEffect(TextEffect *te)
00136 {
00137   /* Never expire for duration of 0xFFFF */
00138   if (te->duration == 0xFFFF) return;
00139   if (te->duration < 8) {
00140     te->string_id = INVALID_STRING_ID;
00141   } else {
00142     te->duration -= 8;
00143     te->y--;
00144     te->bottom--;
00145   }
00146   MarkTextEffectAreaDirty(te);
00147 }
00148 
00149 void MoveAllTextEffects()
00150 {
00151   for (TextEffectID i = 0; i < _num_text_effects; i++) {
00152     TextEffect *te = &_text_effect_list[i];
00153     if (te->string_id != INVALID_STRING_ID && te->mode == TE_RISING) MoveTextEffect(te);
00154   }
00155 }
00156 
00157 void InitTextEffects()
00158 {
00159   if (_text_effect_list == NULL) _text_effect_list = MallocT<TextEffect>(_num_text_effects);
00160 
00161   for (TextEffectID i = 0; i < _num_text_effects; i++) _text_effect_list[i].string_id = INVALID_STRING_ID;
00162 }
00163 
00164 void DrawTextEffects(DrawPixelInfo *dpi)
00165 {
00166   switch (dpi->zoom) {
00167     case ZOOM_LVL_NORMAL:
00168       for (TextEffectID i = 0; i < _num_text_effects; i++) {
00169         TextEffect *te = &_text_effect_list[i];
00170         if (te->string_id != INVALID_STRING_ID &&
00171             dpi->left <= te->right &&
00172             dpi->top  <= te->bottom &&
00173             dpi->left + dpi->width  > te->x &&
00174             dpi->top  + dpi->height > te->y) {
00175           if (te->mode == TE_RISING || (_settings_client.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) {
00176             AddStringToDraw(te->x, te->y, te->string_id, te->params_1, te->params_2);
00177           }
00178         }
00179       }
00180       break;
00181 
00182     case ZOOM_LVL_OUT_2X:
00183       for (TextEffectID i = 0; i < _num_text_effects; i++) {
00184         TextEffect *te = &_text_effect_list[i];
00185         if (te->string_id != INVALID_STRING_ID &&
00186             dpi->left <= te->right  * 2 - te->x &&
00187             dpi->top  <= te->bottom * 2 - te->y &&
00188             dpi->left + dpi->width  > te->x &&
00189             dpi->top  + dpi->height > te->y) {
00190           if (te->mode == TE_RISING || (_settings_client.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) {
00191             AddStringToDraw(te->x, te->y, (StringID)(te->string_id - 1), te->params_1, te->params_2);
00192           }
00193         }
00194       }
00195       break;
00196 
00197     case ZOOM_LVL_OUT_4X:
00198     case ZOOM_LVL_OUT_8X:
00199       break;
00200 
00201     default: NOT_REACHED();
00202   }
00203 }

Generated on Fri Jan 9 19:01:52 2009 for openttd by  doxygen 1.5.6