texteff.cpp

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

Generated on Thu Sep 24 19:35:06 2009 for OpenTTD by  doxygen 1.5.6