# 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 }