# signs.cpp

Go to the documentation of this file.

    00001 /* $Id: signs.cpp 15434 2009-02-09 21:20:05Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "landscape.h"
    00007 #include "company_func.h"
    00008 #include "signs_base.h"
    00009 #include "signs_func.h"
    00010 #include "command_func.h"
    00011 #include "strings_func.h"
    00012 #include "viewport_func.h"
    00013 #include "tilehighlight_func.h"
    00014 #include "zoom_func.h"
    00015 #include "functions.h"
    00016 #include "window_func.h"
    00017 #include "map_func.h"
    00018 #include "string_func.h"
    00019 #include "oldpool_func.h"
    00020
    00021 #include "table/strings.h"
    00022
    00023 SignID _new_sign_id;
    00024
    00025 /* Initialize the sign-pool */
    00026 DEFINE_OLD_POOL_GENERIC(Sign, Sign)
    00027
    00028 Sign::Sign(Owner owner)
    00029 {
    00030   this->owner = owner;
    00031 }
    00032
    00033 Sign::~Sign()
    00034 {
    00035   free(this->name);
    00036
    00037   if (CleaningPool()) return;
    00038
    00039   DeleteRenameSignWindow(this->index);
    00040   this->owner = INVALID_OWNER;
    00041 }
    00042
    00049 static void UpdateSignVirtCoords(Sign *si)
    00050 {
    00051   Point pt = RemapCoords(si->x, si->y, si->z);
    00052   SetDParam(0, si->index);
    00053   UpdateViewportSignPos(&si->sign, pt.x, pt.y - 6, STR_2806);
    00054 }
    00055
    00057 void UpdateAllSignVirtCoords()
    00058 {
    00059   Sign *si;
    00060
    00061   FOR_ALL_SIGNS(si) UpdateSignVirtCoords(si);
    00062 }
    00063
    00072 static void MarkSignDirty(Sign *si)
    00073 {
    00074   /* We use ZOOM_LVL_MAX here, as every viewport can have an other zoom,
    00075     *  and there is no way for us to know which is the biggest. So make the
    00076     *  biggest area dirty, and we are safe for sure. */
    00077   MarkAllViewportsDirty(
    00078     si->sign.left - 6,
    00079     si->sign.top  - 3,
    00080     si->sign.left + ScaleByZoom(si->sign.width_1 + 12, ZOOM_LVL_MAX),
    00081     si->sign.top  + ScaleByZoom(12, ZOOM_LVL_MAX));
    00082 }
    00083
    00093 CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00094 {
    00095   /* Try to locate a new sign */
    00096   if (!Sign::CanAllocateItem()) return_cmd_error(STR_2808_TOO_MANY_SIGNS);
    00097
    00098   /* Check sign text length if any */
    00099   if (!StrEmpty(text) && strlen(text) >= MAX_LENGTH_SIGN_NAME_BYTES) return CMD_ERROR;
    00100
    00101   /* When we execute, really make the sign */
    00102   if (flags & DC_EXEC) {
    00103     Sign *si = new Sign(_current_company);
    00104     int x = TileX(tile) * TILE_SIZE;
    00105     int y = TileY(tile) * TILE_SIZE;
    00106
    00107     si->x = x;
    00108     si->y = y;
    00109     si->z = GetSlopeZ(x, y);
    00110     if (!StrEmpty(text)) {
    00111       si->name = strdup(text);
    00112     }
    00113     UpdateSignVirtCoords(si);
    00114     MarkSignDirty(si);
    00115     InvalidateWindowData(WC_SIGN_LIST, 0, 0);
    00116     _new_sign_id = si->index;
    00117   }
    00118
    00119   return CommandCost();
    00120 }
    00121
    00131 CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00132 {
    00133   if (!IsValidSignID(p1)) return CMD_ERROR;
    00134
    00135   /* Rename the signs when empty, otherwise remove it */
    00136   if (!StrEmpty(text)) {
    00137     if (strlen(text) >= MAX_LENGTH_SIGN_NAME_BYTES) return CMD_ERROR;
    00138
    00139     if (flags & DC_EXEC) {
    00140       Sign *si = GetSign(p1);
    00141
    00142       /* Delete the old name */
    00143       free(si->name);
    00144       /* Assign the new one */
    00145       si->name = strdup(text);
    00146       si->owner = _current_company;
    00147
    00148       /* Update; mark sign dirty twice, because it can either becom longer, or shorter */
    00149       MarkSignDirty(si);
    00150       UpdateSignVirtCoords(si);
    00151       MarkSignDirty(si);
    00152       InvalidateWindowData(WC_SIGN_LIST, 0, 1);
    00153     }
    00154   } else { // Delete sign
    00155     if (flags & DC_EXEC) {
    00156       Sign *si = GetSign(p1);
    00157
    00158       MarkSignDirty(si);
    00159       delete si;
    00160
    00161       InvalidateWindowData(WC_SIGN_LIST, 0, 0);
    00162     }
    00163   }
    00164
    00165   return CommandCost();
    00166 }
    00167
    00175 void CcPlaceSign(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00176 {
    00177   if (success) {
    00178     ShowRenameSignWindow(GetSign(_new_sign_id));
    00179     ResetObjectToPlace();
    00180   }
    00181 }
    00182
    00189 void PlaceProc_Sign(TileIndex tile)
    00190 {
    00191   DoCommandP(tile, 0, 0, CMD_PLACE_SIGN | CMD_MSG(STR_2809_CAN_T_PLACE_SIGN_HERE), CcPlaceSign);
    00192 }
    00193
    00199 void InitializeSigns()
    00200 {
    00201   _Sign_pool.CleanPool();
    00202   _Sign_pool.AddBlockToPool();
    00203 }