tron@2186: /* $Id$ */ tron@2186: rubidium@9111: /** @file signs.cpp Handling of signs. */ belugas@6420: truelight@988: #include "stdafx.h" Darkvater@1891: #include "openttd.h" maedhros@6453: #include "landscape.h" rubidium@10208: #include "company_func.h" rubidium@8790: #include "signs_base.h" rubidium@8790: #include "signs_func.h" truelight@988: #include "saveload.h" rubidium@8116: #include "command_func.h" tron@2153: #include "variables.h" rubidium@8114: #include "strings_func.h" rubidium@8225: #include "viewport_func.h" rubidium@9148: #include "tilehighlight_func.h" rubidium@8123: #include "zoom_func.h" rubidium@8131: #include "functions.h" rubidium@8131: #include "window_func.h" rubidium@8139: #include "map_func.h" rubidium@8214: #include "string_func.h" smatz@8847: #include "oldpool_func.h" truelight@988: rubidium@8264: #include "table/strings.h" rubidium@8264: rubidium@7295: SignID _new_sign_id; tron@2789: rubidium@7384: /* Initialize the sign-pool */ rubidium@7384: DEFINE_OLD_POOL_GENERIC(Sign, Sign) rubidium@7384: rubidium@10207: Sign::Sign(Owner owner) truelight@1283: { peter1138@8258: this->owner = owner; truelight@1283: } truelight@1283: rubidium@7384: Sign::~Sign() rubidium@7384: { peter1138@8258: free(this->name); smatz@10156: smatz@10156: if (CleaningPool()) return; smatz@10156: smatz@10156: DeleteRenameSignWindow(this->index); rubidium@10207: this->owner = INVALID_OWNER; rubidium@7384: } rubidium@7384: truelight@988: /** truelight@988: * truelight@988: * Update the coordinate of one sign belugas@6420: * @param si Pointer to the Sign truelight@988: * truelight@988: */ truelight@4349: static void UpdateSignVirtCoords(Sign *si) truelight@988: { truelight@4349: Point pt = RemapCoords(si->x, si->y, si->z); peter1138@7056: SetDParam(0, si->index); truelight@4349: UpdateViewportSignPos(&si->sign, pt.x, pt.y - 6, STR_2806); truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@990: * Update the coordinates of all signs truelight@988: * truelight@988: */ rubidium@6247: void UpdateAllSignVirtCoords() truelight@988: { truelight@4349: Sign *si; truelight@988: truelight@4349: FOR_ALL_SIGNS(si) UpdateSignVirtCoords(si); truelight@988: truelight@988: } truelight@988: truelight@988: /** rubidium@7545: * Marks the region of a sign as dirty. truelight@988: * rubidium@7545: * This function marks the sign in all viewports as dirty for repaint. truelight@988: * truelight@4349: * @param si Pointer to the Sign rubidium@7545: * @ingroup dirty truelight@988: */ truelight@4349: static void MarkSignDirty(Sign *si) truelight@988: { truelight@6700: /* We use ZOOM_LVL_MAX here, as every viewport can have an other zoom, truelight@6700: * and there is no way for us to know which is the biggest. So make the truelight@6700: * biggest area dirty, and we are safe for sure. */ truelight@988: MarkAllViewportsDirty( truelight@4349: si->sign.left - 6, truelight@4349: si->sign.top - 3, truelight@6700: si->sign.left + ScaleByZoom(si->sign.width_1 + 12, ZOOM_LVL_MAX), truelight@6700: si->sign.top + ScaleByZoom(12, ZOOM_LVL_MAX)); truelight@988: } truelight@988: truelight@988: /** truelight@4400: * Place a sign at the given coordinates. Ownership of sign has Darkvater@1793: * no effect whatsoever except for the colour the sign gets for easy recognition, Darkvater@1793: * but everybody is able to rename/remove it. tron@3491: * @param tile tile to place sign at belugas@6420: * @param flags type of operation Darkvater@1793: * @param p1 unused Darkvater@1793: * @param p2 unused truelight@988: */ rubidium@6943: CommandCost CmdPlaceSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@988: { truelight@988: /* Try to locate a new sign */ rubidium@9036: if (!Sign::CanAllocateItem()) return_cmd_error(STR_2808_TOO_MANY_SIGNS); truelight@988: truelight@988: /* When we execute, really make the sign */ truelight@988: if (flags & DC_EXEC) { rubidium@10207: Sign *si = new Sign(_current_company); tron@3491: int x = TileX(tile) * TILE_SIZE; tron@3491: int y = TileY(tile) * TILE_SIZE; tron@3491: truelight@4349: si->x = x; truelight@4349: si->y = y; rubidium@6491: si->z = GetSlopeZ(x, y); truelight@4349: UpdateSignVirtCoords(si); truelight@4349: MarkSignDirty(si); peter1138@9734: InvalidateWindowData(WC_SIGN_LIST, 0, 0); rubidium@7295: _new_sign_id = si->index; truelight@988: } truelight@988: rubidium@6950: return CommandCost(); truelight@988: } truelight@988: Darkvater@1793: /** Rename a sign. If the new name of the sign is empty, we assume Darkvater@1793: * the user wanted to delete it. So delete it. Ownership of signs Darkvater@1793: * has no meaning/effect whatsoever except for eyecandy tron@3491: * @param tile unused belugas@6420: * @param flags type of operation Darkvater@1793: * @param p1 index of the sign to be renamed/removed Darkvater@1793: * @param p2 unused belugas@6420: * @return 0 if succesfull, otherwise CMD_ERROR truelight@988: */ rubidium@6943: CommandCost CmdRenameSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@988: { truelight@4352: if (!IsValidSignID(p1)) return CMD_ERROR; Darkvater@1837: Darkvater@1837: /* If _cmd_text 0 means the new text for the sign is non-empty. Darkvater@1793: * So rename the sign. If it is empty, it has no name, so delete it */ rubidium@7511: if (!StrEmpty(_cmd_text)) { rubidium@9914: if (strlen(_cmd_text) >= MAX_LENGTH_SIGN_NAME_BYTES) return CMD_ERROR; rubidium@9914: truelight@988: if (flags & DC_EXEC) { truelight@4349: Sign *si = GetSign(p1); truelight@988: truelight@988: /* Delete the old name */ peter1138@8258: free(si->name); truelight@988: /* Assign the new one */ peter1138@8258: si->name = strdup(_cmd_text); rubidium@10207: si->owner = _current_company; truelight@988: Darkvater@1793: /* Update; mark sign dirty twice, because it can either becom longer, or shorter */ truelight@4349: MarkSignDirty(si); truelight@4349: UpdateSignVirtCoords(si); truelight@4349: MarkSignDirty(si); peter1138@9734: InvalidateWindowData(WC_SIGN_LIST, 0, 1); truelight@988: } belugas@6420: } else { // Delete sign truelight@988: if (flags & DC_EXEC) { truelight@4349: Sign *si = GetSign(p1); truelight@988: truelight@4384: MarkSignDirty(si); rubidium@7384: delete si; truelight@988: frosch@9959: InvalidateWindowData(WC_SIGN_LIST, 0, 0); truelight@988: } truelight@988: } truelight@988: rubidium@6950: return CommandCost(); truelight@988: } truelight@988: truelight@988: /** truelight@988: * Callback function that is called after a sign is placed belugas@6420: * @param success of the operation belugas@6420: * @param tile unused belugas@6420: * @param p1 unused belugas@6420: * @param p2 unused truelight@988: */ tron@1977: void CcPlaceSign(bool success, TileIndex tile, uint32 p1, uint32 p2) truelight@988: { truelight@988: if (success) { rubidium@7295: ShowRenameSignWindow(GetSign(_new_sign_id)); truelight@988: ResetObjectToPlace(); truelight@988: } truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * PlaceProc function, called when someone pressed the button if the truelight@988: * sign-tool is selected belugas@6420: * @param tile on which to place the sign truelight@988: */ tron@1977: void PlaceProc_Sign(TileIndex tile) truelight@988: { tron@2783: DoCommandP(tile, 0, 0, CcPlaceSign, CMD_PLACE_SIGN | CMD_MSG(STR_2809_CAN_T_PLACE_SIGN_HERE)); truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Initialize the signs truelight@988: * truelight@988: */ rubidium@6247: void InitializeSigns() truelight@988: { rubidium@7384: _Sign_pool.CleanPool(); rubidium@7384: _Sign_pool.AddBlockToPool(); truelight@988: } truelight@988: Darkvater@1881: static const SaveLoad _sign_desc[] = { peter1138@8258: SLE_CONDVAR(Sign, name, SLE_NAME, 0, 83), peter1138@8258: SLE_CONDSTR(Sign, name, SLE_STR, 0, 84, SL_MAX_VERSION), truelight@4349: SLE_CONDVAR(Sign, x, SLE_FILE_I16 | SLE_VAR_I32, 0, 4), truelight@4349: SLE_CONDVAR(Sign, y, SLE_FILE_I16 | SLE_VAR_I32, 0, 4), truelight@4349: SLE_CONDVAR(Sign, x, SLE_INT32, 5, SL_MAX_VERSION), truelight@4349: SLE_CONDVAR(Sign, y, SLE_INT32, 5, SL_MAX_VERSION), truelight@4349: SLE_CONDVAR(Sign, owner, SLE_UINT8, 6, SL_MAX_VERSION), truelight@4349: SLE_VAR(Sign, z, SLE_UINT8), truelight@988: SLE_END() truelight@988: }; truelight@988: truelight@988: /** truelight@988: * truelight@988: * Save all signs truelight@988: * truelight@988: */ rubidium@6247: static void Save_SIGN() truelight@988: { truelight@4349: Sign *si; truelight@988: truelight@4349: FOR_ALL_SIGNS(si) { truelight@4349: SlSetArrayIndex(si->index); truelight@4349: SlObject(si, _sign_desc); truelight@988: } truelight@988: } truelight@988: truelight@988: /** truelight@988: * truelight@988: * Load all signs truelight@988: * truelight@988: */ rubidium@6247: static void Load_SIGN() truelight@988: { truelight@988: int index; truelight@988: while ((index = SlIterateArray()) != -1) { rubidium@7384: Sign *si = new (index) Sign(); truelight@4349: SlObject(si, _sign_desc); truelight@988: } truelight@988: } truelight@988: rubidium@5587: extern const ChunkHandler _sign_chunk_handlers[] = { truelight@988: { 'SIGN', Save_SIGN, Load_SIGN, CH_ARRAY | CH_LAST}, truelight@988: };