From 67fa5a23b9ee6cfd34465a26e6b696d22eb5ecb1 Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 25 Jan 2021 18:42:15 +0000 Subject: [PATCH 001/275] Update: Translations from eints estonian: 7 changes by siimsoni --- src/lang/estonian.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 1d9c4ab649..4f9c00dde0 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -365,6 +365,8 @@ STR_SORT_BY_CARGO_CAPACITY :Kandevõime STR_SORT_BY_RANGE :Vahekaugus STR_SORT_BY_POPULATION :Rahvaarv STR_SORT_BY_RATING :Hinnang +STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Eelmise aasta keskmine kasum +STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Selle aasta keskmine kasum # Group by options for vehicle list @@ -521,6 +523,7 @@ STR_TOOLBAR_SOUND_MUSIC :Heli/muusika ############ range for message menu starts STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT :Viimane teade STR_NEWS_MENU_MESSAGE_HISTORY_MENU :Teadete ajalugu +STR_NEWS_MENU_DELETE_ALL_MESSAGES :Kustuta kõik teated ############ range ends here ############ range for about menu starts @@ -1038,14 +1041,14 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Vali kas STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Tavaline STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Topeltsuurus -STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Ruudu suurus +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suurus STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Kirja suurus STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Vali kasutatav liideseelementide suurus STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Tavaline STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Topeltsuurus -STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Ruudu suurus +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suurus STR_GAME_OPTIONS_BASE_GRF :{BLACK}Alusgraafika kogu STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Valib kasutatava alusgraafika kogu @@ -4032,7 +4035,7 @@ STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Toggle m STR_AI_DEBUG_CONTINUE :{BLACK}Jätka STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Jätka tee ja tee edasi AI-d STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Vaata selle AI silumisinfo väljundit -STR_AI_GAME_SCRIPT :{BLACK}Mängu Skript +STR_AI_GAME_SCRIPT :{BLACK}GameScript STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Kontrolli GameScripti logi STR_ERROR_AI_NO_AI_FOUND :Laadimiseks sobivat tehismõistust ei leitud.{}See on asendustehismõistus, ning ei tee midagi.{}Tehismõistuseid saab laadida kasutades 'Internetisisu' süsteemi. @@ -4128,7 +4131,7 @@ STR_FEEDER_INCOME_TINY :{TINY_FONT}{YEL STR_FEEDER_INCOME :{YELLOW}Ümberlaadimine: {CURRENCY_LONG}{WHITE} / {GREEN}Sissetulek: {CURRENCY_LONG} STR_FEEDER_COST_TINY :{TINY_FONT}{YELLOW}Ümberlaadimine: {CURRENCY_LONG}{WHITE} / {RED}Hind: {CURRENCY_LONG} STR_FEEDER_COST :{YELLOW}Ümberlaadimine: {CURRENCY_LONG}{WHITE} / {RED}Hind: {CURRENCY_LONG} -STR_MESSAGE_ESTIMATED_COST :{WHITE}Eeldatav hind: {CURRENCY_LONG} +STR_MESSAGE_ESTIMATED_COST :{WHITE}Eeldatav kulu: {CURRENCY_LONG} STR_MESSAGE_ESTIMATED_INCOME :{WHITE}Eeldatavad tulud: {CURRENCY_LONG} # Saveload messages From 027452fef8073f6f5b0be505f3621620d95380c8 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 26 Jan 2021 18:14:06 +0000 Subject: [PATCH 002/275] Update: Translations from eints german: 11 changes by Wuzzy2 --- src/lang/german.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lang/german.txt b/src/lang/german.txt index 2361ef4d7b..052dcdee7b 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -1875,7 +1875,7 @@ STR_LIVERY_DMU :VT STR_LIVERY_EMU :ET STR_LIVERY_PASSENGER_WAGON_STEAM :Passagierwaggon (Dampf) STR_LIVERY_PASSENGER_WAGON_DIESEL :Passagierwaggon (Diesel) -STR_LIVERY_PASSENGER_WAGON_ELECTRIC :Passagierwaggon (elektrisch) +STR_LIVERY_PASSENGER_WAGON_ELECTRIC :Passagierwaggon (Elektrisch) STR_LIVERY_PASSENGER_WAGON_MONORAIL :Passagierwaggon (Einschienenbahn) STR_LIVERY_PASSENGER_WAGON_MAGLEV :Passagierwaggon (Magnetschwebebahn) STR_LIVERY_FREIGHT_WAGON :Güterwaggon @@ -4672,15 +4672,15 @@ STR_ERROR_CAN_T_DELETE_SIGN :{WHITE}Kann Sch STR_DESKTOP_SHORTCUT_COMMENT :Ein auf der Idee von Transport Tycoon Deluxe basierendes Spiel # Translatable descriptions in media/baseset/*.ob* files -STR_BASEGRAPHICS_DOS_DESCRIPTION :Original Transport Tycoon Deluxe DOS Basisgrafiken. -STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Original Transport Tycoon Deluxe DOS (Deutsch) Basisgrafiken. -STR_BASEGRAPHICS_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows Basisgrafiken. -STR_BASESOUNDS_DOS_DESCRIPTION :Original Transport Tycoon Deluxe DOS Basissounds. -STR_BASESOUNDS_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows Basissounds. -STR_BASESOUNDS_NONE_DESCRIPTION :Basissounds ohne Sound. -STR_BASEMUSIC_WIN_DESCRIPTION :Original Transport Tycoon Deluxe Windows Musikset. -STR_BASEMUSIC_DOS_DESCRIPTION :Original Transport Tycoon Deluxe DOS edition music. -STR_BASEMUSIC_TTO_DESCRIPTION :Original Transport Tycoon (Original/World Editor) DOS edition music. +STR_BASEGRAPHICS_DOS_DESCRIPTION :Originale „Transport Tycoon Deluxe“-DOS-Basisgrafiken. +STR_BASEGRAPHICS_DOS_DE_DESCRIPTION :Originale „Transport Tycoon Deluxe“-DOS-Basisgrafiken (Deutsch). +STR_BASEGRAPHICS_WIN_DESCRIPTION :Originale „Transport Tycoon Deluxe“-Windows-Basisgrafiken. +STR_BASESOUNDS_DOS_DESCRIPTION :Originale „Transport Tycoon Deluxe“-DOS-Basissounds. +STR_BASESOUNDS_WIN_DESCRIPTION :Originale „Transport Tycoon Deluxe“-Windows-Basissounds. +STR_BASESOUNDS_NONE_DESCRIPTION :Ein Soundpaket ohne Sounds. +STR_BASEMUSIC_WIN_DESCRIPTION :Originales „Transport Tycoon Deluxe“-Windows-Musikset. +STR_BASEMUSIC_DOS_DESCRIPTION :Originales „Transport Tycoon Deluxe“-DOS-Musikset. +STR_BASEMUSIC_TTO_DESCRIPTION :Originales „Transport Tycoon (Original/World Editor)“-DOS-Musikset. STR_BASEMUSIC_NONE_DESCRIPTION :Ein Musikset ohne Musik. ##id 0x2000 @@ -4890,7 +4890,7 @@ STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 „Cyclops STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV3_PEGASUS_ELECTRIC :Lev3 „Pegasus“ (elektrisch) STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV4_CHIMAERA_ELECTRIC :Lev4 „Chimaera“ (elektrisch) STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer -STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PASSENGER_CAR :Passagierwaggon (Magnetschwebebahn) +STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PASSENGER_CAR :Passagierwaggon STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_MAIL_VAN :Postwaggon STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_COAL_CAR :Kohlewaggon STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_OIL_TANKER :Öltanker From da78b5c13006dc420ebc2ade00be8ae5259a7494 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 27 Jan 2021 18:14:58 +0000 Subject: [PATCH 003/275] Update: Translations from eints estonian: 117 changes by siimsoni german: 5 changes by Wuzzy2 slovak: 23 changes by FuryPapaya --- src/lang/estonian.txt | 233 +++++++++++++++++++++--------------------- src/lang/german.txt | 10 +- src/lang/slovak.txt | 27 ++++- 3 files changed, 145 insertions(+), 125 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 4f9c00dde0..d3fda10ccf 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -348,7 +348,7 @@ STR_SORT_BY_MODEL :Mudel STR_SORT_BY_VALUE :Väärtus STR_SORT_BY_LENGTH :Pikkus STR_SORT_BY_LIFE_TIME :Amortiseerumiseni -STR_SORT_BY_TIMETABLE_DELAY :Hilinemine sõiduplaanis +STR_SORT_BY_TIMETABLE_DELAY :Hilinemine graafikus STR_SORT_BY_FACILITY :Jaama tüüp STR_SORT_BY_WAITING_TOTAL :Kaupa kokku STR_SORT_BY_WAITING_AVAILABLE :Kaupa saadaval @@ -820,7 +820,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Näita k STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Näita viimast teadet STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * SEISATUS * * -STR_STATUSBAR_AUTOSAVE :{RED}AUTOMAATSALVESTUS +STR_STATUSBAR_AUTOSAVE :{RED}VÄLPSALVESTUS STR_STATUSBAR_SAVING_GAME :{RED}* * MÄNGU SALVESTAMINE * * # News message history @@ -892,10 +892,10 @@ STR_NEWS_SHIP_IS_WAITING :{WHITE}{VEHICLE STR_NEWS_AIRCRAFT_IS_WAITING :{WHITE}{VEHICLE} ootab lennukiangaaris # Order review system / warnings -STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS :{WHITE}{VEHICLE} sõiduplaanis on liiga vähe ülesandeid -STR_NEWS_VEHICLE_HAS_VOID_ORDER :{WHITE}Sõidukil {VEHICLE} on tühistatud ülesanne -STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY :{WHITE}Sõidukil {VEHICLE} on topeltülesandeid -STR_NEWS_VEHICLE_HAS_INVALID_ENTRY :{WHITE}Sõiduki «{VEHICLE}» ülesannetes on kõlbmatu jaam +STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS :{WHITE}{VEHICLE}: graafikus pole piisavalt korraldusi +STR_NEWS_VEHICLE_HAS_VOID_ORDER :{WHITE}Sõidukil {VEHICLE} on tühistatud korraldus +STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY :{WHITE}Sõidukil {VEHICLE} on topeltkorraldusi +STR_NEWS_VEHICLE_HAS_INVALID_ENTRY :{WHITE}Sõiduki «{VEHICLE}» korraldustes on kõlbmatu jaam STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY :{WHITE}{VEHICLE} lennugraafikus on lennujaam, mille maandumisrada on liiga lühike STR_NEWS_VEHICLE_IS_GETTING_OLD :{WHITE}{VEHICLE} on vanaks saamas @@ -1015,15 +1015,15 @@ STR_GAME_OPTIONS_TOWN_NAME_ITALIAN :Itaalia STR_GAME_OPTIONS_TOWN_NAME_CATALAN :Katalaani ############ end of townname region -STR_GAME_OPTIONS_AUTOSAVE_FRAME :{BLACK}Isesalvestamine -STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :{BLACK}Vali automaatselt mängu salvestamise vahemik +STR_GAME_OPTIONS_AUTOSAVE_FRAME :{BLACK}Salvestusvälp +STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :{BLACK}Vali salvestamise välp ############ start of autosave dropdown STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF :Väljas -STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH :Iga kuu -STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS :Iga 3 kuu tagant -STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS :Iga 6 kuu tagant -STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :Iga 12 kuu tagant +STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH :1 kuu +STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS :3 kuud +STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS :6 kuud +STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :12 kuud ############ end of autosave dropdown STR_GAME_OPTIONS_LANGUAGE :{BLACK}Keel @@ -1050,19 +1050,19 @@ STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Tavaline STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Topeltsuurus STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suurus -STR_GAME_OPTIONS_BASE_GRF :{BLACK}Alusgraafika kogu -STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Valib kasutatava alusgraafika kogu +STR_GAME_OPTIONS_BASE_GRF :{BLACK}Lähtegraafikakogu +STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Valib kasutatava lähtegraafikakogu STR_GAME_OPTIONS_BASE_GRF_STATUS :{RED}{NUM} puuduv{P "" ad}/viga{P ne sed} fail{P "" id} -STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}Lisateave alusgraafika kogu kohta +STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}Lisateave lähtegraafikakogu kohta -STR_GAME_OPTIONS_BASE_SFX :{BLACK}Alushelide kogu -STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}Valib kasutatava põhihelide kogu -STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}Lisateave alushelide kogu kohta +STR_GAME_OPTIONS_BASE_SFX :{BLACK}Lähtehelikogu +STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}Valib kasutatava lähtehelikogu +STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}Lisateave lähtehelikogu kohta -STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Alusmuusika kogu -STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Valib alusmuusikamuusika kogu +STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Lähtemuusikakogu +STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Valib kasutatava lähtemuusikakogu STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM} viga{P "ne" "sed"} fail{P "" "id"} -STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Rohkem teavet alusmuusika kogu kohta +STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Rohkem teavet lähtemuusikakogu kohta STR_ERROR_RESOLUTION_LIST_FAILED :{WHITE}Ei õnnestunud tuvastada toetatud resulutsioone STR_ERROR_FULLSCREEN_FAILED :{WHITE}Täisekraanrežiim ebaõnnestus @@ -1149,7 +1149,7 @@ STR_CITY_APPROVAL_PERMISSIVE :Soodustav STR_CITY_APPROVAL_TOLERANT :Salliv STR_CITY_APPROVAL_HOSTILE :Vaenulik -STR_WARNING_NO_SUITABLE_AI :{WHITE}Sobiv tehismõistus puudub...{}Tehismõistuseid võib laadida Internetisisu laadimise aknast. +STR_WARNING_NO_SUITABLE_AI :{WHITE}Sobiv AI puudub...{}Mitmesuguseid AI-sid saab alla laadida 'aineste allalaadimise' kaudu # Settings tree window STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Seaded @@ -1276,9 +1276,9 @@ STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :Sõltuvalt suun STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :Paremal STR_CONFIG_SETTING_SHOWFINANCES :Aasta lõpul näidatakse rahavoogude aruannet: {STRING} STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :Sisse lülitamisel ilmub iga aasta lõpus rahavoogude aruanne, mis annab hea ülevaate ettevõtte rahalisest olukorrast -STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Ülesanded on esialgselt «Peatusteta»: {STRING} +STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Uued korraldused on esialgselt vahepeatusteta: {STRING} STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :Tavaliselt peatub sõiduk igas peatuses, mida ta läbib. Selle seadega sõidab sõiduk lõppsihini ilma vahejaamades peatumata. NB! See seade määrab vaid uute korralduste esialgse seadistuse. Korraldusi saab hiljem eraldi ümber seadistada -STR_CONFIG_SETTING_STOP_LOCATION :Esialgne platvormi peatumisosa uute rongide ülesannetes: {STRING} +STR_CONFIG_SETTING_STOP_LOCATION :Esialgne platvormi peatumisosa uute rongide korraldustes: {STRING} STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Esialgne peatumiskoht rongiplatvormil. «alguses» tähendab sisenemispunkti lähistel. «keskel» tähendab keset platvormi. «lõpus» tähendab sisenemispunktist kaugeimal. NB! See seade määrab vaid uute korralduste esialgse seadistuse. Korraldusi saab hiljem eraldi ümber seadistada STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :alguses STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :keskel @@ -1324,7 +1324,7 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT :Selle seade sis STR_CONFIG_SETTING_WARN_LOST_VEHICLE :Hoiata kui sõiduk on eksinud: {STRING} STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Tekita teateid kui sõidukid ei suuda leida teekonda nendele määratud sihtkohani -STR_CONFIG_SETTING_ORDER_REVIEW :Sõiduki ülesannete ülevaade: {STRING} +STR_CONFIG_SETTING_ORDER_REVIEW :Sõiduki korralduste ülevaade: {STRING} STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Kui on aktiveeritud, siis kontrollitakse perioodiliselt sõidukitele antud käsklusi ja leitud vead raporteeritakse uudistena STR_CONFIG_SETTING_ORDER_REVIEW_OFF :Ei STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :Jah, kuid jäta välja seisatud veovahendid @@ -1356,7 +1356,7 @@ STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Graafikutes kas STR_CONFIG_SETTING_LANDSCAPE :Maastik: {STRING} STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Igal maastikul on oma kaubatüübid ja nõuded linnade kasvamiseks. Täpsemaid muudatusi saab teha NewGRFi ja mänguskriptide abil. STR_CONFIG_SETTING_LAND_GENERATOR :Maatekituse meetod: {STRING} -STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Originaalne generaator sõltub alusgraafikast ja tekitab kindlaksmääratud maastikuvorme. TerraGenesis on Perlini müral põhinev generaator, mida saab täpsemalt seadistada +STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Originaalne generaator sõltub lähtegraafikast ja tekitab kindlaksmääratud maastikuvorme. TerraGenesis on Perlini müral põhinev generaator, mida saab täpsemalt seadistada STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Algupärane STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Maapinna tüüp: {STRING} @@ -1420,8 +1420,8 @@ STR_CONFIG_SETTING_SCROLLWHEEL_SCROLL :Kaardil liikumi STR_CONFIG_SETTING_SCROLLWHEEL_OFF :Väljas STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER :Hiirerulli tundlikkus: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER_HELPTEXT :Muudab hiirerulli tundlikkust -STR_CONFIG_SETTING_OSK_ACTIVATION :Klaviatuuri näitamine ekraanil: {STRING} -STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT :Ekraaniklaviatuuri avamise viis. Ekraaniklaviatuur võimaldab teksti sisestamist ainult hiireosutiga. See on mõeldud kasutamiseks väikeste seadmetega, millel ei ole klaviatuuri +STR_CONFIG_SETTING_OSK_ACTIVATION :Virtuaalne klaviatuur: {STRING} +STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT :Vali viis, kuidas avada virtuaalne klaviatuur hiireosuti abil teksti sisestamiseks. See on mõeldud klaviatuurita väikeseadmetele STR_CONFIG_SETTING_OSK_ACTIVATION_DISABLED :Väljas STR_CONFIG_SETTING_OSK_ACTIVATION_DOUBLE_CLICK :Topeltklõpsuga STR_CONFIG_SETTING_OSK_ACTIVATION_SINGLE_CLICK_FOCUS :Ühe klõpsuga (kui on fookuses) @@ -1435,8 +1435,8 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Väljas STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Akna sulgemine paremklõpsuga: {STRING} -STR_CONFIG_SETTING_AUTOSAVE :Automaatne salvestamine: {STRING} -STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vali automaatse salvestamise intervall +STR_CONFIG_SETTING_AUTOSAVE :Välpsalvestus: {STRING} +STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vali välpsalvestuste vaheline ajavahemik STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Salvestatud mängu nimes kasutatakse {STRING} kuupäevavormingut STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT :Kuupäeva vorming salvestatud mängu nimes @@ -1456,12 +1456,12 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Põhjalikku sõ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Lubab kasutada põhjalikke sõidukiregistreid, kus saab sõidukeid rühmitada STR_CONFIG_SETTING_LOADING_INDICATORS :Laadimisnäidikute kasutamine: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Vali, kas näidata sõiduki peale- ja mahalaadimise ajal laadimisnäidikut -STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Sõiduplaan on sammudes, mitte päevades: {STRING} -STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Sõiduplaanis on ajad märgitud mitte päevades, vaid sammudes -STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Sõiduplaanis on saabumis- ja väljumisajad: {STRING} -STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Sõiduki sõiduplaanis esitatakse eeldatavaid saabumis- ja väljumisaegu -STR_CONFIG_SETTING_QUICKGOTO :Sõidukile määratakse kohe ülesandeid: {STRING} -STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Sõiduki sihtide avamisel saab kohe «Mine» ülesandeid anda +STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Graafik on sammudes, mitte päevades: {STRING} +STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Graafikus on ajad märgitud mitte päevades, vaid sammudes +STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Graafikus on saabumis- ja väljumisajad: {STRING} +STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Sõiduki graafikus esitatakse eeldatavaid saabumis- ja väljumisaegu +STR_CONFIG_SETTING_QUICKGOTO :Sõiduki korralduste kiirloomine: {STRING} +STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Sõiduki sihtide avamisel saab kohe «Mine» korraldusi anda STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :Algne rööbastee liik (mängu alustamisel/jätkamisel): {STRING} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Määrab mängu alguses või selle jätkamisel käibel oleva rööbastee liigi. «Esimesena saadaval» valib kõige vanema rööbastee liigi, «Viimasena saadaval» valib kõige uuema rööbastee liigi, ning «Enim kasutatud» valib kõige rohkem kasutatud rööbastee liigi STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Esimesena saadaval @@ -1512,12 +1512,12 @@ STR_CONFIG_SETTING_AI_BUILDS_SHIPS :Laevakeeld arvu STR_CONFIG_SETTING_AI_BUILDS_SHIPS_HELPTEXT :Selle seade sisse lülitamise korral ei ole arvuti juhitud mängijal lubatud laevade ehitamine STR_CONFIG_SETTING_AI_PROFILE :Vaikeseadistus: {STRING} -STR_CONFIG_SETTING_AI_PROFILE_HELPTEXT :Valib suvalise tehismõistuse ja lisatava tehismõistuse ja mänguskripti vaikeseadistuse +STR_CONFIG_SETTING_AI_PROFILE_HELPTEXT :Vali seadistus, mida kasutada suvalistes AI-des või uue AI/GameScripti lisamisel STR_CONFIG_SETTING_AI_PROFILE_EASY :Lihtne STR_CONFIG_SETTING_AI_PROFILE_MEDIUM :Keskmine STR_CONFIG_SETTING_AI_PROFILE_HARD :Keeruline -STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :Tehismõistus mitmikmängus: {STRING} +STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :AI mitmikmängus: {STRING} STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Võimaldab arvutil osaleda mitmikmängudes STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :#opcode-d ennem skripte on peatatud: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maksimaalne arv arvutamise käike mida skript võib teha ühel sammul @@ -1774,9 +1774,9 @@ STR_CONFIG_ERROR_INVALID_GRF_INCOMPATIBLE :Mitteühilduv s STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN :tundmatu STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_LEVEL :{WHITE}... tihendusaste «{STRING}» ei sobi STR_CONFIG_ERROR_INVALID_SAVEGAME_COMPRESSION_ALGORITHM :{WHITE}... mängu salvestamise vormingut «{STRING}» ei ole. Taastatakse «{STRING}» -STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND :{WHITE}... eiratakse alusgraafika kogu «{STRING}»: ei leitud -STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND :{WHITE}... eiratakse alushelide kogu «{STRING}»: ei leitud -STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}... eiratakse alusmuusika kogu «{STRING}»: ei leitud +STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND :{WHITE}... eiratakse lähtegraafikakogu «{STRING}»: ei leitud +STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND :{WHITE}... eiratakse lähtehelikogu «{STRING}»: ei leitud +STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}... eiratakse lähtemuusikakogu «{STRING}»: ei leitud STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}Vahemälu on täis STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Pildipuhvri (ingl k «spritecache») suurendamine {BYTES} võrra ebaõnnestus. Pildipuhvri uus suurus on {BYTES}. Seetõttu on OpenTTD nüüd aeglasem. 32 bpp graafika keelamine ja suurendusastme ülempiiri vähendamine piirab vahemälu tarbimist @@ -1818,7 +1818,7 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Otsi all STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Ava AI/GameScripti seaded STR_INTRO_TOOLTIP_QUIT :{BLACK}Välju 'OpenTTD'st -STR_INTRO_TRANSLATION :{BLACK}Puudub {NUM} tõlge{P "" t}. Tule tee OpenTTD paremaks, aita tõlkida. Rohkem teavet leiad «readme.txt» failist. +STR_INTRO_TRANSLATION :{BLACK}Puudub {NUM} tõlge{P "" t}. Aita teha OpenTTD paremaks, panusta tõlkimisega. Rohkem teavet leiad «readme.txt» failist. # Quit window STR_QUIT_CAPTION :{WHITE}Mängust väljumine @@ -2270,14 +2270,14 @@ STR_CONTENT_NO_ZLIB :{WHITE}OpenTTD STR_CONTENT_NO_ZLIB_SUB :{WHITE}... aineste allalaadimine pole võimalik! # Order of these is important! -STR_CONTENT_TYPE_BASE_GRAPHICS :Alusgraafika +STR_CONTENT_TYPE_BASE_GRAPHICS :Lähtegraafika STR_CONTENT_TYPE_NEWGRF :NewGRF -STR_CONTENT_TYPE_AI :Tehismõistus -STR_CONTENT_TYPE_AI_LIBRARY :Tehismõistuse teek +STR_CONTENT_TYPE_AI :AI +STR_CONTENT_TYPE_AI_LIBRARY :AI teek STR_CONTENT_TYPE_SCENARIO :Stsenaarium STR_CONTENT_TYPE_HEIGHTMAP :Kõrguskaart -STR_CONTENT_TYPE_BASE_SOUNDS :Alushelid -STR_CONTENT_TYPE_BASE_MUSIC :Alusmuusika +STR_CONTENT_TYPE_BASE_SOUNDS :Lähtehelid +STR_CONTENT_TYPE_BASE_MUSIC :Lähtemuusika STR_CONTENT_TYPE_GAME_SCRIPT :Mängu skript STR_CONTENT_TYPE_GS_LIBRARY :GS teek @@ -2741,6 +2741,7 @@ STR_FRAMERATE_MS_BAD :{RED}{DECIMAL} STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} kaadrit/s STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL} kaadrit/s STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL} kaadrit/s +STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms ############ Leave those lines in this order!! STR_FRAMERATE_GAMELOOP :{BLACK}Mängutsükli lõppkokkuvõte: STR_FRAMERATE_GL_AIRCRAFT :{BLACK} Õhusõiduki sammud: @@ -3555,20 +3556,20 @@ STR_DEPOT_CLONE_ROAD_VEHICLE :{BLACK}Kloonimi STR_DEPOT_CLONE_SHIP :{BLACK}Klooni laev STR_DEPOT_CLONE_AIRCRAFT :{BLACK}Klooni lennuk -STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Ostetakse samasugune rong koos kõikide vagunitega. Vajuta sellele nupule, ning seejärel rongile depoo sees või väljas. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda -STR_DEPOT_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Ostetakse samasugune mootorsõiduk. Vajuta sellele nupule, ning seejärel mootorsõidukil depoos või sellest väljas. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda -STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Ostetakse samasugune laev. Vajuta sellele nupule, ning seejärel laevale laevaremonditehase sees või väljas. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda -STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Ostetakse samasugune õhusõiduk. Vajuta sellele nupule, ning seejärel lennukile angaari sees või väljas. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda +STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Ostetakse samasugune rong koos kõikide vagunitega. Vajuta sellele nupule, ning seejärel rongile depoo sees või väljas. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda +STR_DEPOT_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Ostetakse samasugune mootorsõiduk. Vajuta sellele nupule, ning seejärel mootorsõidukil depoos või sellest väljas. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda +STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Ostetakse samasugune laev. Vajuta sellele nupule, ning seejärel laevale laevaremonditehase sees või väljas. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda +STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Ostetakse samasugune õhusõiduk. Vajuta sellele nupule, ning seejärel lennukile angaari sees või väljas. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda STR_DEPOT_TRAIN_LOCATION_TOOLTIP :{BLACK}Keskenda põhivaade rongidepoo kohale STR_DEPOT_ROAD_VEHICLE_LOCATION_TOOLTIP :{BLACK}Vii vaade garaažile. Ctrl+klõps avab garaažil uue vaate. STR_DEPOT_SHIP_LOCATION_TOOLTIP :{BLACK}Vii pea vaade paadikuuri juurde STR_DEPOT_AIRCRAFT_LOCATION_TOOLTIP :{BLACK}Vii vaade angaarile -STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TOOLTIP :{BLACK}Koosta nimekiri kõikidest rongidest, mille ülesannete hulgas on see depoo -STR_DEPOT_VEHICLE_ORDER_LIST_ROAD_VEHICLE_TOOLTIP :{BLACK}Koosta nimekiri kõikidest mootorsõidukitest, mille ülesannete hulgas on see depoo -STR_DEPOT_VEHICLE_ORDER_LIST_SHIP_TOOLTIP :{BLACK}Koosta nimekiri kõikidest laevadest, mille ülesannete hulgas on see angaar -STR_DEPOT_VEHICLE_ORDER_LIST_AIRCRAFT_TOOLTIP :{BLACK}Koosta nimekiri kõikidest rongidest, mille ülesannete hulgas on selle lennujaama angaar +STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TOOLTIP :{BLACK}Koosta nimekiri kõikidest rongidest, mille korralduste hulgas on see depoo +STR_DEPOT_VEHICLE_ORDER_LIST_ROAD_VEHICLE_TOOLTIP :{BLACK}Koosta nimekiri kõikidest mootorsõidukitest, mille korralduste hulgas on see depoo +STR_DEPOT_VEHICLE_ORDER_LIST_SHIP_TOOLTIP :{BLACK}Koosta nimekiri kõikidest laevadest, mille korralduste hulgas on see angaar +STR_DEPOT_VEHICLE_ORDER_LIST_AIRCRAFT_TOOLTIP :{BLACK}Koosta nimekiri kõikidest rongidest, mille korralduste hulgas on selle lennujaama angaar STR_DEPOT_MASS_STOP_DEPOT_TRAIN_TOOLTIP :{BLACK}Vajuta, kui tahad seisata kõiki ronge jaamas STR_DEPOT_MASS_STOP_DEPOT_ROAD_VEHICLE_TOOLTIP :{BLACK}Vajuta, kui tahad seisata kõiki masinaid garaažis @@ -3652,9 +3653,9 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Saada s STR_VEHICLE_VIEW_SHIP_SEND_TO_DEPOT_TOOLTIP :{BLACK}Saada laev angaari. Ctrl+klõps ainult teenindab STR_VEHICLE_VIEW_AIRCRAFT_SEND_TO_DEPOT_TOOLTIP :{BLACK}Saada lennuk angaari -STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Ostab samasuguse rongi koos kõikide vagunitega. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda -STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Ostab samasuguse maanteesõiduki. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda -STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Ostab samasuguse laeva. Vajuta sellele nuppule, ning seejärel laevale laevaremonditehase sees või väljas. «Ctrl»+klõps jagab ülesandeid. «Shift»+klõps näitab eeldatavat ostuhinda +STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Ostab samasuguse rongi koos kõikide vagunitega. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda +STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Ostab samasuguse maanteesõiduki. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda +STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Ostab samasuguse laeva. Vajuta sellele nuppule, ning seejärel laevale laevaremonditehase sees või väljas. «Ctrl»+klõps jagab korraldusi. «Shift»+klõps näitab eeldatavat ostuhinda STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Ostab samasuguse õhusõiduki. Ctrl+klõpsuga jagatakse sihtpunkte. Shift+klõpsuga kuvatakse eeldatav ostuhind STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}Sunni rongi signaale eirama @@ -3667,10 +3668,10 @@ STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Seadista STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP :{BLACK}Pööra rong ümber STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP :{BLACK}Sunni veovahendit ümber pöörama -STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP :{BLACK}Näita rongi ülesandeid. «Ctrl»+klõps näitab rongi sõiduplaani -STR_VEHICLE_VIEW_ROAD_VEHICLE_ORDERS_TOOLTIP :{BLACK}Näita mootorsõiduki ülesandeid. «Ctrl»+klõps näitab mootorsõiduki sõiduplaani -STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Näita laeva ülesanded. «Ctrl»+klõps näitab laeva sõiduplaani -STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Näita lennuki ülesandeid. «Ctrl»+klõps näitab õhusõiduki sõiduplaani +STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP :{BLACK}Näita rongi korraldusi. «Ctrl»+klõps näitab rongi graafikut +STR_VEHICLE_VIEW_ROAD_VEHICLE_ORDERS_TOOLTIP :{BLACK}Näita mootorsõiduki korraldusi. «Ctrl»+klõps näitab mootorsõiduki graafikut +STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Näita laeva korraldusi. «Ctrl»+klõps näitab laeva graafikut +STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Näita lennuki korraldusi. «Ctrl»+klõps näitab õhusõiduki graafikut STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Näita rongi täpsustusi STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Näita mootorsõiduki täpsustusi @@ -3795,38 +3796,38 @@ STR_REFIT_SHIP_REFIT_TOOLTIP :{BLACK}Seadista STR_REFIT_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Seadista lennuk ümber, et kanda valitud kaubatüüpi # Order view -STR_ORDERS_CAPTION :{WHITE}{VEHICLE} (ülesanded) -STR_ORDERS_TIMETABLE_VIEW :{BLACK}Sõiduplaan -STR_ORDERS_TIMETABLE_VIEW_TOOLTIP :{BLACK}Näita sõiduplaani +STR_ORDERS_CAPTION :{WHITE}{VEHICLE} (korraldused) +STR_ORDERS_TIMETABLE_VIEW :{BLACK}Graafik +STR_ORDERS_TIMETABLE_VIEW_TOOLTIP :{BLACK}Näita graafikut -STR_ORDERS_LIST_TOOLTIP :{BLACK}Ülesannete register - ülesanne valitakse klõpsamisega. Ctrl+klõps keskendab vaate ülesande sihile +STR_ORDERS_LIST_TOOLTIP :{BLACK}Korralduste register - korraldus valitakse klõpsamisega. Ctrl+klõps keskendab vaate korralduse sihtpunktile STR_ORDER_INDEX :{COMMA}:{NBSP} STR_ORDER_TEXT :{STRING} {STRING} {STRING} -STR_ORDERS_END_OF_ORDERS :- - Ülesannete lõpp - - -STR_ORDERS_END_OF_SHARED_ORDERS :- - Jagatud käskluste lõpp - - +STR_ORDERS_END_OF_ORDERS :- - Korraldused läbi - - +STR_ORDERS_END_OF_SHARED_ORDERS :- - Jagatud korraldused läbi - - # Order bottom buttons -STR_ORDER_NON_STOP :{BLACK}Peatusteta +STR_ORDER_NON_STOP :{BLACK}Vahepeatusteta STR_ORDER_GO_TO :Mine STR_ORDER_GO_NON_STOP_TO :Mine peatumata STR_ORDER_GO_VIA :Mine läbi STR_ORDER_GO_NON_STOP_VIA :Mine peatumata läbi -STR_ORDER_TOOLTIP_NON_STOP :{BLACK}Valitud ülesande peatumisprotseduuri muutmine +STR_ORDER_TOOLTIP_NON_STOP :{BLACK}Valitud korralduse peatumisprotseduuri muutmine STR_ORDER_TOGGLE_FULL_LOAD :{BLACK}Laadi üks täis STR_ORDER_DROP_LOAD_IF_POSSIBLE :Laadi peale STR_ORDER_DROP_FULL_LOAD_ALL :Laadi kõik kaubad täis STR_ORDER_DROP_FULL_LOAD_ANY :Laadi üks kaup täis STR_ORDER_DROP_NO_LOADING :Mitte laadida -STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}Valitud ülesande pealelaadimisprotseduuri muutmine +STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}Valitud korralduse pealelaadimisprotseduuri muutmine STR_ORDER_TOGGLE_UNLOAD :{BLACK}Laadi kõik maha STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :Laadi tühjaks nõudlusel STR_ORDER_DROP_UNLOAD :Laadi tühjaks STR_ORDER_DROP_TRANSFER :Laadi ümber STR_ORDER_DROP_NO_UNLOADING :Mitte maha laadida -STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Valitud ülesande mahalaadimisprotseduuri muutmine +STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Valitud korralduse mahalaadimisprotseduuri muutmine STR_ORDER_REFIT :{BLACK}Taasseadista STR_ORDER_REFIT_TOOLTIP :{BLACK}Vali, millist laadungit ümber seadistada selles järjestuses. Ümberseadistuse käsu eemaldamiseks hoia klõpsamise ajal all Control nuppu @@ -3841,7 +3842,7 @@ STR_ORDER_DROP_SERVICE_DEPOT :Vajadusel hoold STR_ORDER_DROP_HALT_DEPOT :Peatu STR_ORDER_SERVICE_TOOLTIP :{BLACK}Jäta see käsk vahele, kui hooldust ei vajata -STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP :{BLACK}Sõiduki andmed, millel ülesande vahetamine põhineb +STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP :{BLACK}Sõiduki andmed, millel korralduse vahelejätmine põhineb # Conditional order variables, must follow order of OrderConditionVariable enum STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE :Koorem protsentides @@ -3866,20 +3867,20 @@ STR_ORDER_CONDITIONAL_VALUE_TOOLTIP :{BLACK}Väärtu STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Sisesta väärtus, millega võrrelda STR_ORDERS_SKIP_BUTTON :{BLACK}Jäta vahele -STR_ORDERS_SKIP_TOOLTIP :{BLACK}Jäta praegune ülesannete vahele ja alusta järgmisega. Ctrl+klõps valib ülesande ja jätab teised ülesanded vahele +STR_ORDERS_SKIP_TOOLTIP :{BLACK}Jäta praegune korraldus vahele ja alusta järgmisega. Ctrl+klõps valib korralduse ja jätab teised korraldused vahele STR_ORDERS_DELETE_BUTTON :{BLACK}Kustuta -STR_ORDERS_DELETE_TOOLTIP :{BLACK}Kustuta valitud ülesanne -STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}Tühjenda sihiloend +STR_ORDERS_DELETE_TOOLTIP :{BLACK}Kustuta valitud korraldus +STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}Eemalda kõik korraldused STR_ORDERS_STOP_SHARING_BUTTON :{BLACK}Lõpeta jagamine -STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}Lõpeta sihiloendi jagamine. Sihiloend tühjendatakse Ctrl+klõpsu abil +STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}Lõpeta korralduste jagamine. Ctrl+klõps eemaldab kõik selle sõiduki korraldused STR_ORDERS_GO_TO_BUTTON :{BLACK}Mine STR_ORDER_GO_TO_NEAREST_DEPOT :Mine lähimasse depoosse STR_ORDER_GO_TO_NEAREST_HANGAR :Mine lähimasse angaari -STR_ORDER_CONDITIONAL :Ülesande vahetamine tingimusel +STR_ORDER_CONDITIONAL :Korralduste tinglik vahelejätmine STR_ORDER_SHARE :Jaga korraldusi -STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Lisa valitud käsu ette uus ülesanne, või kui ülesannet ei ole valitud, siis nimekirja lõppu. «Ctrl» määrab jaama puhul ülesandeks «peale laadida üks kaup», meldepunkti puhul «peatuseta» ja depoo puhul «hooldus». «Jaga korraldusi» või «Ctrl» klahv lubab sellel sõidukil jagada ülesandeid valitud sõidukiga. Klõpsates teisel sõidukil, dubleeritakse selle ülesanded +STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Lisa valitud käsu ette uus korraldus, või kui korraldust ei ole valitud, siis nimekirja lõppu. «Ctrl» määrab jaama puhul korralduseks «peale laadida üks kaup», meldepunkti puhul «peatuseta» ja depoo puhul «hooldus». «Jaga korraldusi» või «Ctrl» klahv lubab sellel sõidukil jagada korraldusi valitud sõidukiga. Klõpsates teisel sõidukil, dubleeritakse selle korraldused STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP :{BLACK}Näita kõiki sama sõidugraafikuga mootorsõidukeid @@ -3947,18 +3948,18 @@ STR_ORDER_CONDITIONAL_UNCONDITIONAL :Mine sihtpunkti STR_ORDER_CONDITIONAL_NUM :Mine sihtpunkti {COMMA}, kui {STRING} {STRING} {COMMA} STR_ORDER_CONDITIONAL_TRUE_FALSE :Mine sihtpunkti{COMMA}, kui {STRING} {STRING} -STR_INVALID_ORDER :{RED} (Kõlbmatu ülesanne) +STR_INVALID_ORDER :{RED} (Kõlbmatu korraldus) # Time table window -STR_TIMETABLE_TITLE :{WHITE}{VEHICLE} (Sõiduplaan) +STR_TIMETABLE_TITLE :{WHITE}{VEHICLE} (Graafik) STR_TIMETABLE_ORDER_VIEW :{BLACK}Korraldused STR_TIMETABLE_ORDER_VIEW_TOOLTIP :{BLACK}Lülita korralduste vaatesse -STR_TIMETABLE_TOOLTIP :{BLACK}Sõiduplaan - ülesanne märgitakse klõpsuga +STR_TIMETABLE_TOOLTIP :{BLACK}Graafik - korraldus märgitakse klõpsuga STR_TIMETABLE_NO_TRAVEL :Sõitu pole STR_TIMETABLE_NOT_TIMETABLEABLE :Reisi (automaatne; ajakava järgmise manuaalse käsu järgi) -STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Sõitmine (sõiduplaanita) +STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Sõitmine (graafikuta) STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Reisi kõike suurema {2:VELOCITY} (ei ole ajastatud) STR_TIMETABLE_TRAVEL_FOR :Sõida {STRING} STR_TIMETABLE_TRAVEL_FOR_SPEED :Reisi selleks {STRING} kõige rohkema {VELOCITY} @@ -3971,23 +3972,23 @@ STR_TIMETABLE_AND_TRAVEL_FOR :ja sõida {STRI STR_TIMETABLE_DAYS :{COMMA} päev{P "" a} STR_TIMETABLE_TICKS :{COMMA} samm{P "" u} -STR_TIMETABLE_TOTAL_TIME :{BLACK}Selle sõiduplaani täitmine võtab {STRING} -STR_TIMETABLE_TOTAL_TIME_INCOMPLETE :{BLACK}Selle sõiduplaani täitmine võtab vähemalt {STRING} (kõik ei ole planeeritud) +STR_TIMETABLE_TOTAL_TIME :{BLACK}Selle graafiku läbimine võtab {STRING} +STR_TIMETABLE_TOTAL_TIME_INCOMPLETE :{BLACK}Selle graafiku läbimine võtab vähemalt {STRING} (kõik ei ole planeeritud) STR_TIMETABLE_STATUS_ON_TIME :{BLACK}Sõiduk on graafikus STR_TIMETABLE_STATUS_LATE :{BLACK}See sõiduk on {STRING} hiljaks jäämas STR_TIMETABLE_STATUS_EARLY :{BLACK}See sõiduk on {STRING} varajane -STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}Sõiduplaani pole veel alustatud -STR_TIMETABLE_STATUS_START_AT :{BLACK}Sõiduplaani alustatakse {STRING} +STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}Graafikuga pole veel alustatud +STR_TIMETABLE_STATUS_START_AT :{BLACK}Graafikuga alustatakse {STRING} STR_TIMETABLE_STARTING_DATE :{BLACK}Alguskuupäev -STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Vali sõiduplaani alguskuupäev. Ctrl-klõps määrab sõiduplaani alguskuupäeva ja jaotab sõidukid ühtlaselt, kasutades järjestust, kui sihid on planeeritud +STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Vali graafiku alguskuupäev. Ctrl-klõps määrab graafiku alguskuupäeva ja jaotab sõidukid ühtlaselt, kasutades järjestust, kui sihid on planeeritud STR_TIMETABLE_CHANGE_TIME :{BLACK}Muuda aega -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Muuda märgitud ülesandeks vajalikku aega +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Muuda märgitud korraldusele määratud aega STR_TIMETABLE_CLEAR_TIME :{BLACK}Tühista aeg -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Eemalda ülesandeks vajalik aeg +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Tühista korralduse täitmiseks määratud aeg STR_TIMETABLE_CHANGE_SPEED :{BLACK}Muuda kiiruspiirangut STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Muuda märgitud korralduse kiiruspiirangut @@ -4003,7 +4004,7 @@ STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Kasuta l STR_TIMETABLE_EXPECTED :{BLACK}Eeldatav STR_TIMETABLE_SCHEDULED :{BLACK}Plaanis -STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Vaheta eeldatava ja graafikupõhise sõiduplaani vahel +STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Vaheta eeldatava ja graafiku vahel STR_TIMETABLE_ARRIVAL_ABBREVIATION :S: STR_TIMETABLE_DEPARTURE_ABBREVIATION :V: @@ -4012,7 +4013,7 @@ STR_TIMETABLE_DEPARTURE_ABBREVIATION :V: # Date window (for timetable) STR_DATE_CAPTION :{WHITE}Määra kuupäev STR_DATE_SET_DATE :{BLACK}Määra kuupäev -STR_DATE_SET_DATE_TOOLTIP :{BLACK}Kasuta sõiduplaani alguskuupäevana +STR_DATE_SET_DATE_TOOLTIP :{BLACK}Kasuta graafiku alguskuupäevana STR_DATE_DAY_TOOLTIP :{BLACK}Vali päev STR_DATE_MONTH_TOOLTIP :{BLACK}Vali kuu STR_DATE_YEAR_TOOLTIP :{BLACK}Vali aasta @@ -4024,8 +4025,8 @@ STR_AI_DEBUG_NAME_AND_VERSION :{BLACK}{STRING} STR_AI_DEBUG_NAME_TOOLTIP :{BLACK}Skripti nimi STR_AI_DEBUG_SETTINGS :{BLACK}Seaded STR_AI_DEBUG_SETTINGS_TOOLTIP :{BLACK}Skripti seadistamine -STR_AI_DEBUG_RELOAD :{BLACK}Laadi tehismõistus uuesti -STR_AI_DEBUG_RELOAD_TOOLTIP :{BLACK}Sulge tehismõistus, laadi skript uuesti ning taaskäivita tehismõistus +STR_AI_DEBUG_RELOAD :{BLACK}Laadi AI uuesti +STR_AI_DEBUG_RELOAD_TOOLTIP :{BLACK}Sulge AI, laadi skript uuesti ning taaskäivita AI STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Enable/disable breaking when an AI log message matches the break string STR_AI_DEBUG_BREAK_ON_LABEL :{BLACK}Vahe sees: STR_AI_DEBUG_BREAK_STR_OSKTITLE :{BLACK}Vahe sees @@ -4038,29 +4039,29 @@ STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Vaata se STR_AI_GAME_SCRIPT :{BLACK}GameScript STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Kontrolli GameScripti logi -STR_ERROR_AI_NO_AI_FOUND :Laadimiseks sobivat tehismõistust ei leitud.{}See on asendustehismõistus, ning ei tee midagi.{}Tehismõistuseid saab laadida kasutades 'Internetisisu' süsteemi. -STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}Tõrge ühe töötava tehismõistusega. Palun teavitage sellest tehismõistuse autorit koos kuvapaugutusega tehismõistuse tõrkeotsingu aknast. +STR_ERROR_AI_NO_AI_FOUND :Laadimiseks sobivat AI-d ei leitud.{}See AI on makett, ning ei tee midagi.{}AI-sid alla saab laadida kasutades 'aineste allalaadimise' süsteemi. +STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}Üks skriptidest jooksis kokku. Palun teatada sellest skripti autorit koos ekraanipildiga AI/GamesScripti debugimise aknast STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}AI/GameScripti debugimise akent saab kasutada ainult serveris # AI configuration window STR_AI_CONFIG_CAPTION :{WHITE}AI/Game Script seadistus STR_AI_CONFIG_GAMELIST_TOOLTIP :{BLACK}Järgmises mängus laaditav GameScript -STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}Tehismõistused mis laetakse järgmise mänguga +STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}AI-d järgmises mängus STR_AI_CONFIG_HUMAN_PLAYER :Inimene -STR_AI_CONFIG_RANDOM_AI :Suvaline tehismõistus +STR_AI_CONFIG_RANDOM_AI :Suvaline AI STR_AI_CONFIG_NONE :(mitte ühtegi) STR_AI_CONFIG_MOVE_UP :{BLACK}Liigutamine ülespoole -STR_AI_CONFIG_MOVE_UP_TOOLTIP :{BLACK}Valitud tehismõistuse liigutamine loendis ülespoole +STR_AI_CONFIG_MOVE_UP_TOOLTIP :{BLACK}Valitud AI liigutamine loendis ülespoole STR_AI_CONFIG_MOVE_DOWN :{BLACK}Liigutamine allapoole -STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Valitud tehismõistuse liigutamine loendis allapoole +STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Valitud AI liigutamine loendis allapoole STR_AI_CONFIG_GAMESCRIPT :{SILVER}GameScript -STR_AI_CONFIG_AI :{SILVER}Tehismõistused +STR_AI_CONFIG_AI :{SILVER}AI-d STR_AI_CONFIG_CHANGE :{BLACK}Vali {STRING} STR_AI_CONFIG_CHANGE_NONE : -STR_AI_CONFIG_CHANGE_AI :Tehismõistus +STR_AI_CONFIG_CHANGE_AI :AI STR_AI_CONFIG_CHANGE_GAMESCRIPT :GameScript STR_AI_CONFIG_CHANGE_TOOLTIP :{BLACK}Lae teine skript STR_AI_CONFIG_CONFIGURE :{BLACK}Seadista @@ -4068,7 +4069,7 @@ STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}Muuda sk # Available AIs window STR_AI_LIST_CAPTION :{WHITE}Kasutatav {STRING} -STR_AI_LIST_CAPTION_AI :Tehismõistused +STR_AI_LIST_CAPTION_AI :AI-d STR_AI_LIST_CAPTION_GAMESCRIPT :GameScriptid STR_AI_LIST_TOOLTIP :{BLACK}Klõpsa skripti valimiseks @@ -4091,12 +4092,12 @@ STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Väikese # AI Parameters STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parameetrid -STR_AI_SETTINGS_CAPTION_AI :Tehismõistus +STR_AI_SETTINGS_CAPTION_AI :AI STR_AI_SETTINGS_CAPTION_GAMESCRIPT :GameScript STR_AI_SETTINGS_CLOSE :{BLACK}Sulge STR_AI_SETTINGS_RESET :{BLACK}Nulli STR_AI_SETTINGS_SETTING :{STRING}: {ORANGE}{STRING} -STR_AI_SETTINGS_START_DELAY :Päevade arv eelmise tehismõistuse alustamisest pärast mida antud tehismõistus alustab (umbkaudne): {ORANGE}{STRING} +STR_AI_SETTINGS_START_DELAY :Päevade arv pärast eelmise AI lõpetamist, millal see AI käivitub (umbkaudselt): {ORANGE}{STRING} # Textfile window @@ -4136,7 +4137,7 @@ STR_MESSAGE_ESTIMATED_INCOME :{WHITE}Eeldatav # Saveload messages STR_ERROR_SAVE_STILL_IN_PROGRESS :{WHITE}Ikka salvestamisel,{}palun oota salvestuse lõpuni! -STR_ERROR_AUTOSAVE_FAILED :{WHITE}Automaatsalvestus ebaõnnestus +STR_ERROR_AUTOSAVE_FAILED :{WHITE}Välpsalvestus ebaõnnestus STR_ERROR_UNABLE_TO_READ_DRIVE :{BLACK}Ei suuda kettalt lugeda STR_ERROR_GAME_SAVE_FAILED :{WHITE}Mängu salvestamine nurjus{}{STRING} STR_ERROR_UNABLE_TO_DELETE_FILE :{WHITE}Faili ei saa kustutada @@ -4502,17 +4503,17 @@ STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Maantees STR_ERROR_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Lennuk on õhus # Order related errors -STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Ülesannetele pole rohkem ruumi -STR_ERROR_TOO_MANY_ORDERS :{WHITE}Liiga palju ülesandeid -STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}Ei saa lisada uut ülesannet... -STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}Seda ülesannet ei saa kustutada... -STR_ERROR_CAN_T_MODIFY_THIS_ORDER :{WHITE}Seda ülesannet ei saa muuta... -STR_ERROR_CAN_T_MOVE_THIS_ORDER :{WHITE}Seda ülesannet ei saa liigutada... -STR_ERROR_CAN_T_SKIP_ORDER :{WHITE}Praegust ülesannet ei ole saa vahele jätta... -STR_ERROR_CAN_T_SKIP_TO_ORDER :{WHITE}Teisi ülesandeid ei saa vahele jätta... +STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Korraldustele pole rohkem ruumi +STR_ERROR_TOO_MANY_ORDERS :{WHITE}Liiga palju korraldusi +STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}Ei saa lisada uut korraldust... +STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}Seda korraldust ei saa kustutada... +STR_ERROR_CAN_T_MODIFY_THIS_ORDER :{WHITE}Seda korraldust ei saa muuta... +STR_ERROR_CAN_T_MOVE_THIS_ORDER :{WHITE}Seda korraldust ei saa liigutada... +STR_ERROR_CAN_T_SKIP_ORDER :{WHITE}Praegust korraldust pole võimalik vahele jätta... +STR_ERROR_CAN_T_SKIP_TO_ORDER :{WHITE}Teisi korraldusi ei saa vahele jätta... STR_ERROR_CAN_T_COPY_SHARE_ORDER :{WHITE}sõiduk ei saa igasse jaama minna STR_ERROR_CAN_T_ADD_ORDER :{WHITE}sõiduk ei saa antud jaama minna -STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... seda ülesannet jagav sõiduk ei saa sinna jaama minna +STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... seda korraldust jagav sõiduk ei saa sinna jaama minna STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Sihtpunktide nimekirja ei saa jagada... STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Korralduste jagamist ei saa peatada... @@ -4521,7 +4522,7 @@ STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... liig STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... lennukil pole piisavalt pikka tegevusraadiust # Timetable related errors -STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Sõidukile ei saa sõiduplaani anda... +STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Sõidukile ei saa graafikut määrata... STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Sõidukid saavad ainult peatustes oodata STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}See sõiduk ei peatu selles jaamas diff --git a/src/lang/german.txt b/src/lang/german.txt index 052dcdee7b..30abbbb445 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -1025,10 +1025,10 @@ STR_GAME_OPTIONS_BASE_SFX :{BLACK}Basissou STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}Basissounds auswählen STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}Zusatzinformationen zu den Basissounds -STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Musikset -STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Ein Musikset auswählen +STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Basismusikset +STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Ein Basismusikset auswählen STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM} fehlerhafte Datei{P "" en} -STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Zusätzliche Informationen über das Musikset +STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Zusätzliche Informationen über das Basismusikset STR_ERROR_RESOLUTION_LIST_FAILED :{WHITE}Eine Liste unterstützter Auflösungen konnte nicht ermittelt werden STR_ERROR_FULLSCREEN_FAILED :{WHITE}Vollbildmodus nicht möglich @@ -2289,7 +2289,7 @@ STR_CONTENT_TYPE_AI_LIBRARY :{G=w}KI-Bibliot STR_CONTENT_TYPE_SCENARIO :{G=n}Szenario STR_CONTENT_TYPE_HEIGHTMAP :{G=w}Reliefkarte STR_CONTENT_TYPE_BASE_SOUNDS :Basissound -STR_CONTENT_TYPE_BASE_MUSIC :Musikset +STR_CONTENT_TYPE_BASE_MUSIC :Basismusik STR_CONTENT_TYPE_GAME_SCRIPT :Skript STR_CONTENT_TYPE_GS_LIBRARY :Skript - Bibliothek @@ -4681,7 +4681,7 @@ STR_BASESOUNDS_NONE_DESCRIPTION :Ein Soundpaket STR_BASEMUSIC_WIN_DESCRIPTION :Originales „Transport Tycoon Deluxe“-Windows-Musikset. STR_BASEMUSIC_DOS_DESCRIPTION :Originales „Transport Tycoon Deluxe“-DOS-Musikset. STR_BASEMUSIC_TTO_DESCRIPTION :Originales „Transport Tycoon (Original/World Editor)“-DOS-Musikset. -STR_BASEMUSIC_NONE_DESCRIPTION :Ein Musikset ohne Musik. +STR_BASEMUSIC_NONE_DESCRIPTION :Ein Musikpaket ohne Musik. ##id 0x2000 # Town building names diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index b3821b6099..565b811678 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -815,6 +815,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Nerovný terén STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Trávnatý terén STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Holý terén +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Dážďový prales STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Polia STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Stromy STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Skaly @@ -1517,6 +1518,8 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Zachovať stave STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Zachovaj okno s nástrojmi na stavbu mostov/tunelov otvorené aj po použití STR_CONFIG_SETTING_EXPENSES_LAYOUT :Zoskupiť výdavky v okne financií spoločnosti: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Definujte rozloženie okna s financiami. +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Automaticky odstraňovať návestidlá pri výstavbe železnice: {STRING} +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automaticky odstraňovať návestidla pri výstavbe železnice, ak návestidlá blokujú výstavbu. To však môže niekedy smerovať k zrážke vlakov. STR_CONFIG_SETTING_SOUND_TICKER :Oznamovač správ: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Prehrať zvuk pri zhrnutých správach @@ -1901,6 +1904,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Ste si # Cheat window STR_CHEATS :{WHITE}Cheaty STR_CHEATS_TOOLTIP :{BLACK}Zaškrtávacie pole indikuje opakované použite cheatu +STR_CHEATS_NOTE :{BLACK}Poznámka: použitie akéhokoľvek z týchto nastavení bude zaznamenané v uloženej hre STR_CHEAT_MONEY :{LTBLUE}Zvýšiť hotovosť o {CURRENCY_LONG} STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Hrať za spoločnosť: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magický buldozér (odstráni priemysel a nehnuteľnosti): {ORANGE}{STRING} @@ -2297,6 +2301,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} sa STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} založil novú spoločnosť (č. {2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} opustil hru ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} zmenil/-a svoje meno na {STRING} +STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} dal {2:CURRENCY_LONG} spoločnosti {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server ukoncil relaciu STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server sa reštartuje...{}Čakajte prosím... STR_NETWORK_MESSAGE_KICKED :*** Hráč {STRING} bol vyhodený. Dôvod: ({STRING}) @@ -2416,6 +2421,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Spojiť STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Postaviť smerový bod oddelene # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Vypnuté, pretože v súčasnosti nie sú dostuné žiadne vozidlá pre tento typ infraštruktúry # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Výstavba železnice @@ -2693,6 +2699,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Vyber pr # Land area window STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Informácie o pozemku +STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu políčka. Ctrl+klik otvorí nové okno s pohľadom na políčko STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}Náklady na odstránenie: {LTBLUE}N/A STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Náklady na odstránenie: {RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Zisk pri odstránení: {LTBLUE}{CURRENCY_LONG} @@ -3163,8 +3170,9 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Brať/ne # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}Upraviť text popisu -STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Prejst na dalsiu znacku -STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Prejsť na predchádzajúcu značku +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu popisu. Ctrl+klik otvorí nové okno s pohľadom na popis +STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Prejsť na ďalší popis +STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Prejsť na predchádzajúci popis STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Zadajte názov pre popis @@ -3439,7 +3447,8 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Premiest STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Sídlo spoločnosti je možné premiestniť za 1% hodnoty spoločnosti. Shift+klik zobrazí odhadovanú cenu STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Detaily STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Zobraziť podrobné políčka infraštruktúry -STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Presuň peniaze do tejto spoločnosti +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Dať peniaze +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Presunúť peniaze do tejto spoločnosti STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}Nová tvár STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Vybrať novú tvár prezidenta @@ -3457,6 +3466,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}Predať STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :Názov spoločnosti STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :Meno prezidenta +STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :Zadajte množstvo peňazí, ktoré chcete dať spoločnosti STR_BUY_COMPANY_MESSAGE :{WHITE}Hľadáme záujemcu o kúpu našej spoločnosti{}{}Chcete kúpiť našu spoločnosť {COMPANY} za {CURRENCY_LONG}? @@ -3817,6 +3827,10 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Zachovan # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu vlaku. Dvojité kliknutie bude sledovať vlak v hlavnom pohľade. Ctrl+klik otvorí nové okno s pohľadom na vlak +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu vozidla. Dvojité kliknutie bude sledovať vozidlo v hlavnom pohľade. Ctrl+klik otvorí nové okno s pohľadom na vozidlo +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu lode. Dvojité kliknutie bude sledovať loď v hlavnom pohľade. Ctrl+klik otvorí nové okno s pohľadom na loď +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Vycentrovať pohľad na pozíciu lietadla. Dvojité kliknutie bude sledovať lietadlo v hlavnom pohľade. Ctrl+klik otvorí nové okno s pohľadom na lietadlo STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Poslať vlak do depa. Ctrl+klik iba servis STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Poslať vozidlo do garáže. Ctrl+klik iba servis. @@ -3853,6 +3867,7 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Činnos STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Činnosť aktuálnej lode - kliknite na zastavenie/spustenie lode STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Činnosť aktuálneho lietadla - kliknite na zastavenie/spustenie lietadla +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Vycentrovať pohľad na cieľovú pozíciu. Ctrl+klik otvorí nové okno s pohľadom na cieľ # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Nakláda / Vykláda @@ -4080,6 +4095,7 @@ STR_ORDER_REFIT_STOP_ORDER :(Prestavba na { STR_ORDER_STOP_ORDER :(Zastav) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} +STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(Nemožno použiť stanicu){POP_COLOUR} {STRING} {STATION} {STRING} STR_ORDER_IMPLICIT :(Predpokladané) @@ -4404,7 +4420,8 @@ STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY :{WHITE}Nemôže STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... úver už bol splatený STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} potrebuješ STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Úver sa nedá splatiť... -STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je mozne poskytnut peniaze, ktore su pozicane z banky ... +STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Nie je možné presunúť peniaze, ktoré sú požičané z banky... +STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Nie je možné presunúť peniaze tejto spoločnosti... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Spoločnosť nie je možné kúpiť ... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Nemôžeš postaviť sídlo spoločnosti... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Nemôžeš kúpiť 25% podiel v tejto spoločnosti... @@ -4531,6 +4548,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Nesprávny typ STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} je dlho po výmene STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}Neboli využité žiadne pravidlá pre obnovu. STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(finančný limit) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}Nové vozidlo nemôže prevážať {STRING} +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}Nové vozidlo nemôže uskutočniť prestavbu v príkaze {NUM} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Nemožná kombinácia trate From 3dac139b005f41e8d8e1026f08dcffdf466aad54 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 28 Jan 2021 18:16:32 +0000 Subject: [PATCH 004/275] Update: Translations from eints estonian: 5 changes by siimsoni hungarian: 7 changes by andrejmoltok --- src/lang/estonian.txt | 9 +++++---- src/lang/hungarian.txt | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index d3fda10ccf..1c033f7b71 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -4051,20 +4051,21 @@ STR_AI_CONFIG_HUMAN_PLAYER :Inimene STR_AI_CONFIG_RANDOM_AI :Suvaline AI STR_AI_CONFIG_NONE :(mitte ühtegi) -STR_AI_CONFIG_MOVE_UP :{BLACK}Liigutamine ülespoole +STR_AI_CONFIG_MOVE_UP :{BLACK}Tõsta STR_AI_CONFIG_MOVE_UP_TOOLTIP :{BLACK}Valitud AI liigutamine loendis ülespoole -STR_AI_CONFIG_MOVE_DOWN :{BLACK}Liigutamine allapoole +STR_AI_CONFIG_MOVE_DOWN :{BLACK}Langeta STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Valitud AI liigutamine loendis allapoole STR_AI_CONFIG_GAMESCRIPT :{SILVER}GameScript STR_AI_CONFIG_AI :{SILVER}AI-d -STR_AI_CONFIG_CHANGE :{BLACK}Vali {STRING} +STR_AI_CONFIG_CHANGE :{BLACK}{STRING.g} valimine STR_AI_CONFIG_CHANGE_NONE : STR_AI_CONFIG_CHANGE_AI :AI STR_AI_CONFIG_CHANGE_GAMESCRIPT :GameScript +STR_AI_CONFIG_CHANGE_GAMESCRIPT.g :GameScripti STR_AI_CONFIG_CHANGE_TOOLTIP :{BLACK}Lae teine skript -STR_AI_CONFIG_CONFIGURE :{BLACK}Seadista +STR_AI_CONFIG_CONFIGURE :{BLACK}Seadistamine STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}Muuda skripti parameetreid # Available AIs window diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 369d534b2e..9089fbe439 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -1617,6 +1617,7 @@ STR_CONFIG_SETTING_ENDING_YEAR :Játék végi p STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :A játék ebben az évben ér véget pontozás szempontjából. Ennek az évnek a végén a vállalat teljesítménypontszáma rögzítésre kerül, és adott esetben megjelenik a rekord táblán, de a játékosok ezután folytathatják a játékot.{}Ha ez a kezdő év elé van állítva, akkor a rekord tábla sosem jelenik meg. STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Soha +STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :Eredeti STR_CONFIG_SETTING_ALLOW_SHARES :Más vállalatokból lehet részvényt vásárolni: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Bekapcsolva engedélyezi más vállalatok részvényeinek megvásárlását. A részvények csak akkor elérhetőek, ha a vállalat elért egy bizonyos kort STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Vállalatok minimális életkora részvénykibocsátáshoz: {STRING} @@ -2253,6 +2254,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :A játék tová STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :A játék továbbra is szünetel ({STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :A játék továbbra is szünetel ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :A játék továbbra is szünetel ({STRING}, {STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :A játék továbbra is szünetel ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :A játék folytatódik ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :játékosok száma STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :kapcsolódó kliensek @@ -2657,6 +2659,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Válaszd # Land area window STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Terület-információ +STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}A főnézetet a csempére állítja. Ctrl+Klikk megnyit egy új főnézetet a csempén. STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}{LTBLUE}Nem lehet lerombolni STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}A megtisztítás költsége: {RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Bevétel lerombolás esetén: {LTBLUE}{CURRENCY_LONG} @@ -3403,6 +3406,8 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}SZH áth STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}A vállalat székházának újraépítése máshol a vállalat értékének 1%-áért. Shift+kattintással megmutatja a becsült költséget a székhely áthelyezése nélkül STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Részletek STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Részletes információk megtekintése az infrastruktúráról +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Adományozz pénzt +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Utalj pénzt ennek a vállalatnak STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}Új arc STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Új arc választása az elnöknek @@ -4039,6 +4044,7 @@ STR_ORDER_REFIT_STOP_ORDER :(átalakít err STR_ORDER_STOP_ORDER :(megáll) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} +STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(Az állomás nem használható){POP_COLOUR} {STRING} {STATION} {STRING} STR_ORDER_IMPLICIT :(Automata) @@ -5114,6 +5120,7 @@ STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} {COMMA}. STR_FORMAT_BUOY_NAME_SERIAL.ba :{TOWN} {COMMA}. sz. Bóján STR_FORMAT_COMPANY_NUM :({COMMA}. vállalat) STR_FORMAT_GROUP_NAME :{COMMA} csoport +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN}i {STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN} Ellenőrző pont STR_FORMAT_WAYPOINT_NAME.ba :{TOWN} Ellenőrző ponton From 1187dc3217417d5cdc4f686b8ea2c0bae9afd99f Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Thu, 28 Jan 2021 12:54:56 +0000 Subject: [PATCH 005/275] Feature: [Actions] Create .zip for macOS build --- .github/workflows/release.yml | 23 +++++++++++++++++++++++ os/macosx/notarize.sh | 10 ++++++++++ 2 files changed, 33 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81d3cd5b91..08babe0ae4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -496,6 +496,29 @@ jobs: cd build-x64 ../os/macosx/notarize.sh + - name: Build zip + run: | + cd build-x64 + + pushd _CPack_Packages/*/Bundle/openttd-*/ + + # Remove the Applications symlink from the staging folder + rm -f Applications + + # Remove the original dmg built by CPack to avoid a conflict when resolving + # the zip_filename variable below + rm -f ../*.dmg + + zip_filename=(../openttd-*) + + # Package up the existing, notarised .app into a zip file + zip -r -9 ${zip_filename}.zip OpenTTD.app + + popd + + # Now move it into place to be uploaded + mv _CPack_Packages/*/Bundle/openttd-*.zip bundles/ + - name: Store bundles uses: actions/upload-artifact@v2 with: diff --git a/os/macosx/notarize.sh b/os/macosx/notarize.sh index 3434c31256..55405cdd89 100755 --- a/os/macosx/notarize.sh +++ b/os/macosx/notarize.sh @@ -56,3 +56,13 @@ cat < notarize.json EOF gon notarize.json + +app_filename=(_CPack_Packages/*/Bundle/openttd-*/OpenTTD.app) + +if [ "${app_filename}" = "_CPack_Packages/*/Bundle/openttd-*/OpenTTD.app" ]; then + echo "No .app found in the _CPack_Packages directory, skipping stapling." + exit 0 +fi; + +# Now staple the ticket to the .app +xcrun stapler staple "${app_filename[0]}" From 4831b4fa968bcc25945cab50a9c99fa0a5dd8e5c Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 29 Jan 2021 10:38:58 +0100 Subject: [PATCH 006/275] Codechange: [Actions] we no longer need xdg-basedir (#8615) This was already removed from the "ci-build", but not yet from "release". --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08babe0ae4..4003787fc5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -317,7 +317,6 @@ jobs: liblzma-dev \ liblzo2-dev \ libsdl2-dev \ - libxdg-basedir-dev \ lsb-release \ zlib1g-dev \ # EOF From 48698403a8a095611aa2575587008e7c7f419308 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 29 Jan 2021 18:17:44 +0000 Subject: [PATCH 007/275] Update: Translations from eints estonian: 85 changes by siimsoni korean: 30 changes by telk5093 portuguese: 24 changes by CheapWebdesign --- src/lang/estonian.txt | 129 ++++++++++++++++++++++++++-------------- src/lang/korean.txt | 60 +++++++++---------- src/lang/portuguese.txt | 24 ++++++++ 3 files changed, 139 insertions(+), 74 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 1c033f7b71..e800ef85a7 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -244,6 +244,8 @@ STR_COLOUR_ORANGE :Oranž STR_COLOUR_BROWN :Pruun STR_COLOUR_GREY :Hall STR_COLOUR_WHITE :Valge +STR_COLOUR_RANDOM :Suvaline +STR_COLOUR_DEFAULT :Esialgne # Units used in OpenTTD STR_UNITS_VELOCITY_IMPERIAL :{COMMA} miili tunnis @@ -279,7 +281,7 @@ STR_UNITS_HEIGHT_METRIC :{COMMA} m STR_UNITS_HEIGHT_SI :{COMMA} m # Common window strings -STR_LIST_FILTER_TITLE :{BLACK}Filtri tekst: +STR_LIST_FILTER_TITLE :{BLACK}Märksõna: STR_LIST_FILTER_OSKTITLE :{BLACK}Sisesta filterkirjend STR_LIST_FILTER_TOOLTIP :{BLACK}Sisesta märksõna mida loendist otsida @@ -365,6 +367,7 @@ STR_SORT_BY_CARGO_CAPACITY :Kandevõime STR_SORT_BY_RANGE :Vahekaugus STR_SORT_BY_POPULATION :Rahvaarv STR_SORT_BY_RATING :Hinnang +STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Selle aasta kogukasum STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Eelmise aasta keskmine kasum STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Selle aasta keskmine kasum @@ -1153,7 +1156,7 @@ STR_WARNING_NO_SUITABLE_AI :{WHITE}Sobiv AI # Settings tree window STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Seaded -STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtri tekst: +STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Märksõna: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Ava kõik STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Sulge kõik STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(seletus puudub) @@ -1169,10 +1172,10 @@ STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Rühm: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Liik: STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT :{BLACK}Piirab varem tehtud filtridega alljärgnevat loendit STR_CONFIG_SETTING_RESTRICT_BASIC :Põhilised (kuva vaid tähtsad seaded) -STR_CONFIG_SETTING_RESTRICT_ADVANCED :Edasijõudnud (enim seadeid) -STR_CONFIG_SETTING_RESTRICT_ALL :Ekspert (kuva kõik seaded, isegi veidrad) -STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT :Seaded mis erinevad vaikeväärtustest -STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Seaded mis erinevad sinu valitud uue mängu seadetest +STR_CONFIG_SETTING_RESTRICT_ADVANCED :Täpsustatud (näita enamikke seadeid) +STR_CONFIG_SETTING_RESTRICT_ALL :Asjatundja (näita kõiki seaded, s.h. ebatavalisi) +STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT :Lähteväärtusest muudetud seaded +STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Uue mängu seadetest erineva väärtusega seaded STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT :{BLACK}Piirab allolevat nimekirja valitud sätte tüübi järgi STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL :Kõik seadistused @@ -1191,8 +1194,8 @@ STR_CONFIG_SETTING_ON :Sees STR_CONFIG_SETTING_DISABLED :väljas STR_CONFIG_SETTING_COMPANIES_OFF :Väljas -STR_CONFIG_SETTING_COMPANIES_OWN :Oma ettevõttel -STR_CONFIG_SETTING_COMPANIES_ALL :Igal ettevõttel +STR_CONFIG_SETTING_COMPANIES_OWN :Enda ettevõttes +STR_CONFIG_SETTING_COMPANIES_ALL :Igas ettevõttes STR_CONFIG_SETTING_NONE :Pole STR_CONFIG_SETTING_ORIGINAL :Originaal @@ -1232,6 +1235,8 @@ STR_CONFIG_SETTING_AUTOSLOPE :Maastikukujundu STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Lase maja- ja rööpaalust maad kujundada ilma neid eemaldamata STR_CONFIG_SETTING_CATCHMENT :Reaalsemad veekogud: {STRING} STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Erineva suurusega püüdmisala erinevat tüüpi jaamadele ja lennujaamadele. +STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Ettevõtte jaamad teenindavad ka liidetud, erapooletu jaamaga tööstuseid: {STRING} +STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Kui lubatud, saavad liidetud jaamaga tööstuseid (nagu naftaplatvormid) teenindada ka lähedalolevad ettevõttele kuuluvad jaamad. Muidu võivad neid tööstuseid teenindada vaid nendega liidetud jaamad. Lähedale ehitatud ettevõtte jaamad neid teenindada ei saa, ning liidetud jaamad ei teeninda teisi tööstuseid STR_CONFIG_SETTING_EXTRADYNAMITE :Linnateede, -sildade, -tunnelite jne lammutamine: {STRING} STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Lihtsusta linnale kuuluva taristu ja majade eemaldamist STR_CONFIG_SETTING_TRAIN_LENGTH :Rongi pikkuse ülempiir: {STRING} @@ -1269,10 +1274,10 @@ STR_CONFIG_SETTING_INDUSTRY_PLATFORM :Tasane ala ümb STR_CONFIG_SETTING_INDUSTRY_PLATFORM_HELPTEXT :Summa kui palju tasast maad on ümber tehase. See tagab et ruumi jääb saadavale ehitiste jaoks STR_CONFIG_SETTING_MULTIPINDTOWN :Samalaadsed tööstused ühes linnas: {STRING} STR_CONFIG_SETTING_MULTIPINDTOWN_HELPTEXT :Tavaliselt, linn ei taha rohkem kui ühte tööstustharu igast tüübist. See seade lubab rohkem kui ühe tööstusharu samasse linna -STR_CONFIG_SETTING_SIGNALSIDE :Signaalid on: {STRING} -STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :Vali, kus pool rada signaalid asuvad +STR_CONFIG_SETTING_SIGNALSIDE :Signaale näidatakse: {STRING} +STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :Vali kummale poole rada signaalid paigutatakse STR_CONFIG_SETTING_SIGNALSIDE_LEFT :Vasakul -STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :Sõltuvalt suunast +STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :Liikluse suunas STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :Paremal STR_CONFIG_SETTING_SHOWFINANCES :Aasta lõpul näidatakse rahavoogude aruannet: {STRING} STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :Sisse lülitamisel ilmub iga aasta lõpus rahavoogude aruanne, mis annab hea ülevaate ettevõtte rahalisest olukorrast @@ -1283,12 +1288,12 @@ STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Esialgne peatum STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :alguses STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :keskel STR_CONFIG_SETTING_STOP_LOCATION_FAR_END :lõpus -STR_CONFIG_SETTING_AUTOSCROLL :Vaate liikumine, kui hiireosuti on akna servas: {STRING} +STR_CONFIG_SETTING_AUTOSCROLL :Vaade liigub, kui hiireosuti on servas: {STRING} STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT :Sisse lülitamisel liigub vaade, kui hiireosuti on aknaserva lähedal STR_CONFIG_SETTING_AUTOSCROLL_DISABLED :Väljas -STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Peamine vaateaken, ainult täisekraan -STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Peamine vaateaken -STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Kõik vaateaknad +STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Põhivaates, ainult täisekraaniga +STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Põhivaates +STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Igas vaates STR_CONFIG_SETTING_BRIBE :Altkäemaksud kohalikele omavalitsustele: {STRING} STR_CONFIG_SETTING_BRIBE_HELPTEXT :Võimaldab linna omavalitsusele altkäemaksu pakkuda. Vahele jäämise korral võetakse ettevõttelt kuueks kuuks ära õigus tegutseda linnas STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :Ainuveoõiguste ostmine: {STRING} @@ -1317,6 +1322,7 @@ STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Sõiduki STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :Taristu hooldamine: {STRING} STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :Taristuga kaasnevad halduskulud. Kulud kasvavad taristu hulga suhtes ebaproportsionaalselt, ning mõjutavad pigem suurettevõtteid +STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :Ettevõtte esialgne värv: {STRING} STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :Vali ettevõttele esialgne värvus STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS :Aegumatud lennuväljad: {STRING} @@ -1327,9 +1333,9 @@ STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Tekita teateid STR_CONFIG_SETTING_ORDER_REVIEW :Sõiduki korralduste ülevaade: {STRING} STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Kui on aktiveeritud, siis kontrollitakse perioodiliselt sõidukitele antud käsklusi ja leitud vead raporteeritakse uudistena STR_CONFIG_SETTING_ORDER_REVIEW_OFF :Ei -STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :Jah, kuid jäta välja seisatud veovahendid -STR_CONFIG_SETTING_ORDER_REVIEW_ON :Kõikidest veovahenditest -STR_CONFIG_SETTING_WARN_INCOME_LESS :Hoiata kui rongi sissetulek on negatiivne: {STRING} +STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :V.a. seisatud sõidukid +STR_CONFIG_SETTING_ORDER_REVIEW_ON :Kõik sõidukid +STR_CONFIG_SETTING_WARN_INCOME_LESS :Hoiata, kui sõiduk on miinuses: {STRING} STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT :Kui on aktiveeritud, siis teavitatakse mängijat sõidukitest mis ei ole viimase aasta jooksul suutnud kasumit teenida STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Sõidukid ei aegu: {STRING} STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :Kui on aktiveeritud, siis jäävad kõik sõidukite tüübid igavesti avatuks @@ -1352,6 +1358,8 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL :Linna rahvaarv STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Näitab linna nimesildil rahvaarvu STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Graafikujoone laius: {STRING} STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Graafikutes kasutatava joone laius. Peenem joon on täpsem, laiem joon on paremini näha ja värvid on selgemini eristatavad +STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Näita sõidukiehitusaknas NewGRF-i nime: {STRING} +STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Lisa sõidukiehitusaknasse uus rida, mis näitab millisest NewGRF-ist sõiduk on pärit. STR_CONFIG_SETTING_LANDSCAPE :Maastik: {STRING} STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Igal maastikul on oma kaubatüübid ja nõuded linnade kasvamiseks. Täpsemaid muudatusi saab teha NewGRFi ja mänguskriptide abil. @@ -1402,9 +1410,14 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_HELPTEXT :Maa värv väik STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Roheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tumeroheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violetne -STR_CONFIG_SETTING_SMOOTH_SCROLLING :Vaade keskendatakse sujuvalt: {STRING} -STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Vaateakna asukohale keskendamise viis, kui vajutatakse väikesele kaardile, või kui vaade keskendatakse mõnele rekvisiidile. Sisse lülitades on liikumine sujuv, välja lülitades läheb vaade kohe sihtpunkti -STR_CONFIG_SETTING_MEASURE_TOOLTIP :Ehitamisel mõõtude arvesti näitamine: {STRING} +STR_CONFIG_SETTING_SCROLLMODE :Vaate liigutamine: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :RMB liigutab vaadet, osuti seisab paigal +STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :RMB liigutab kaarti, osuti seisab paigal +STR_CONFIG_SETTING_SCROLLMODE_RMB :RMB liigutab kaarti +STR_CONFIG_SETTING_SCROLLMODE_LMB :Kaarti liigutatakse vasaku hiireklahviga +STR_CONFIG_SETTING_SMOOTH_SCROLLING :Keskenda vaade sujuvalt: {STRING} +STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Mõjutab, kuidas põhivõõde liigub sihtpunkti pärast pisikaardil klõpsamist, või vaate muutmise käsu sisestamist. Sisse lüliitades liigub vaade sujuvalt, muidu hüppab vaade kohe sihtpunkti +STR_CONFIG_SETTING_MEASURE_TOOLTIP :Näita ehitustarvikute kasutamisel mõõdistamisabi: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Näitab ehitamise ajal kahe ruudu kaugus- ja kõrgusvahemikke STR_CONFIG_SETTING_LIVERIES :Ettevõtte värve näidatakse: {STRING} STR_CONFIG_SETTING_LIVERIES_HELPTEXT :Vali, kas sõiduki värv sõltub sõiduki liigist või ettevõttest @@ -1415,9 +1428,9 @@ STR_CONFIG_SETTING_PREFER_TEAMCHAT :«ENTER» avab STR_CONFIG_SETTING_PREFER_TEAMCHAT_HELPTEXT :Vahetab «ENTER» ja «Ctrl+ENTER» klahvidega ettevõttesisese ja avaliku vestluse avamise STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING :Hiirerulli otstarve: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_SCROLLING_HELPTEXT :Võimaldab vaadet liigutada kahesuunalise hiirerulliga -STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :Kaardi suurendamine -STR_CONFIG_SETTING_SCROLLWHEEL_SCROLL :Kaardil liikumine -STR_CONFIG_SETTING_SCROLLWHEEL_OFF :Väljas +STR_CONFIG_SETTING_SCROLLWHEEL_ZOOM :Suurendab kaarti +STR_CONFIG_SETTING_SCROLLWHEEL_SCROLL :Liigutab kaarti +STR_CONFIG_SETTING_SCROLLWHEEL_OFF :Puudub STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER :Hiirerulli tundlikkus: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER_HELPTEXT :Muudab hiirerulli tundlikkust STR_CONFIG_SETTING_OSK_ACTIVATION :Virtuaalne klaviatuur: {STRING} @@ -1433,7 +1446,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Command+klõps STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klõps STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Väljas -STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Akna sulgemine paremklõpsuga: {STRING} +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Aken suletakse paremklõpsuga: {STRING} STR_CONFIG_SETTING_AUTOSAVE :Välpsalvestus: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vali välpsalvestuste vaheline ajavahemik @@ -1454,8 +1467,8 @@ STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Kõik peale maa STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Kõik tõimingud STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Põhjalikku sõidukiregistrit näidatakse: {STRING} STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Lubab kasutada põhjalikke sõidukiregistreid, kus saab sõidukeid rühmitada -STR_CONFIG_SETTING_LOADING_INDICATORS :Laadimisnäidikute kasutamine: {STRING} -STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Vali, kas näidata sõiduki peale- ja mahalaadimise ajal laadimisnäidikut +STR_CONFIG_SETTING_LOADING_INDICATORS :Kasuta laadimisnäidikuid: {STRING} +STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Vali, kas koorma peale- ja mahalaadimisel näidatakse laadimisnäidikuid STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Graafik on sammudes, mitte päevades: {STRING} STR_CONFIG_SETTING_TIMETABLE_IN_TICKS_HELPTEXT :Graafikus on ajad märgitud mitte päevades, vaid sammudes STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Graafikus on saabumis- ja väljumisajad: {STRING} @@ -1463,16 +1476,18 @@ STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Sõiduki graafi STR_CONFIG_SETTING_QUICKGOTO :Sõiduki korralduste kiirloomine: {STRING} STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Sõiduki sihtide avamisel saab kohe «Mine» korraldusi anda STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :Algne rööbastee liik (mängu alustamisel/jätkamisel): {STRING} -STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Määrab mängu alguses või selle jätkamisel käibel oleva rööbastee liigi. «Esimesena saadaval» valib kõige vanema rööbastee liigi, «Viimasena saadaval» valib kõige uuema rööbastee liigi, ning «Enim kasutatud» valib kõige rohkem kasutatud rööbastee liigi -STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Esimesena saadaval -STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Viimasena saadaval +STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Määrab mängu alguses või selle jätkamisel käibel oleva rööbastee liigi. «Vanim» valib kõige vanema rööbastee liigi, «Uusim» valib kõige uuema rööbastee liigi, ning «Enim kasutatud» valib kõige rohkem kasutatud rööbastee liigi +STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Vanim +STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Uusim STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_MOST_USED :Enim kasutatud -STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Kinnise raudteelõigu näitamine: {STRING} -STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Värvib kinnise raudtee teist värvi. Lihtsustab vigade leidmist, kui rongid ei kasuta raudteelõiku -STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Ehitustarvikud jäävad kasutamisel käibele: {STRING} -STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Sildade, tunnelite jne ehitamise tarvikud on kasutamise järel veel käibel +STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Hõivatud blokkpiirkondade näitamine: {STRING} +STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Värvib hõivatud blokkpiirkonnad eri värvi, abistamaks tõrgete puhul, kus rongid ei sisene trajektoorijärgsetesse blokkidesse +STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Säilita tegev ehitustarvik pärast kasutamist: {STRING} +STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Säilita sildade, tunnelite, jms. ehitustarvikud pärast kasutamist STR_CONFIG_SETTING_EXPENSES_LAYOUT :Kulutuste rühmitamine rahavoogude aruandes: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Määrab rahavoogude aruande ülesehituse +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Rööbastee ehitamisel on signaalid isekõrvalduvad: {STRING} +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Rööbastee ehitamisel kõrvaldatakse ette jäävad signaalid automaatselt. Silmas pidada, et see võib põhjustada rongide kokkupõrkeid. STR_CONFIG_SETTING_SOUND_TICKER :Lühiteadetes: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Lühiteate ilmumisel kostub helisignaal @@ -1519,8 +1534,10 @@ STR_CONFIG_SETTING_AI_PROFILE_HARD :Keeruline STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :AI mitmikmängus: {STRING} STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Võimaldab arvutil osaleda mitmikmängudes -STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :#opcode-d ennem skripte on peatatud: {STRING} -STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maksimaalne arv arvutamise käike mida skript võib teha ühel sammul +STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :Tehete piirang skriptide peatamiseks: {STRING} +STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Suurim lubatud arv arvutustehteid, mida skript saab ühe käigu jooksul teha +STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :Mälukasutuspiirang skripti kohta: {STRING} +STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_HELPTEXT :Kui palju vahemälu võib skript tarbida enne selle sunniviisilist kõrvaldamist. Suurtel kaartidel võib olla vajalik suurendada. STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB STR_CONFIG_SETTING_SERVINT_ISPERCENT :Hooldusvälp protsentides: {STRING} @@ -1580,8 +1597,19 @@ STR_CONFIG_SETTING_NEWS_MESSAGES_FULL :Täielik STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Värvilised uudised ilmuvad aastast {STRING} STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Värviliste uudiste ilmumise algusaasta. Varasematel aastatel ilmuvad uudised must-valgelt STR_CONFIG_SETTING_STARTING_YEAR :Alustamise aeg: {STRING} +STR_CONFIG_SETTING_ENDING_YEAR :Edetabeli lõppaasta: {STRING} +STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Aasta, millal edetabeli pidamine lõppeb. Selle aasta lõpus jäädvustatakse ettevõtte punktid, ning näidatakse edetabelit, kuid mängijad saavad pärast jätkata.{}Kui see on enne algusaastat, ei näidata edetabelit kunagi. +STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} +STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Mitte kunagi +STR_CONFIG_SETTING_ECONOMY_TYPE :Majandusliik: {STRING} +STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :Sujuvas majanduses muutub toodang sagedamini, kuid vähehaaval. Külmas majanduses on toodang muutumatu ja tööstuseid ei suleta. NewGRF-iga lisatud tööstusliigid võivad seda seadistust eirata. +STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :Algupärane +STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :Sujuv +STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :Külm STR_CONFIG_SETTING_ALLOW_SHARES :Aktsiatehingud teiste ettevõtetega: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Kui on aktiveeritud siis on ettevõtte aktsiate ostmine ja müümine lubatud. Aktsiad on saadaval ainult ettevõtetel mille vanus on üle teatud piiri +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Ettevõtte vanuse alampiir aktsiakauplemiseks: {STRING} +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Määra alampiir ettevõtte vanusele, enne kui teised saavad selle aktsiaid osta ja müüa. STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Protsent tuludest mis läheb 'kanna edasi' süsteemis alumistesse lülidesse: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Protsent tuludest mis antakse edasi 'kanna edasi' süsteemidele. Lubab täpsemalt jaotada kasumit erinevate harude vahel. STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Kui lohistatakse siis paigutatakse foorid iga: {STRING} @@ -1622,9 +1650,17 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :Võimaldab ette STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :Keelatud STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :Lubatud STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :Lubatud, koos linnaskeemi valimisega +STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Kauba tekkimine linnades: {STRING} +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Kui palju kaupa toodavad majad linnades, võrreldes linnaelanike arvuga.{}Ruutfunktsioon: kaks korda suurem linn tekitab neli korda rohkem reisijaid.{}Lineaarne: kaks korda suurem linn tekitab kaks korda rohkem reisijaid. +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :Ruutfunktsioon (algupärane) +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Lineaarne STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Mängu jooksul kasvavad puud: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Juhib suvalist puude kasvu mängu jooksul. See seade võib mõjutada osade tööstuste tööd, mis sõltuvad puude kasvust (näiteks saekaater) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Kasvab, aga ei laiene {RED}(saeveski kasutamatu) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Kasvab, kuid laieneb vaid vihmametsas +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :Kasvab ja laieneb kõikjal +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Ei kasva, ei laiene {RED}(saeveski kasutamatu) STR_CONFIG_SETTING_TOOLBAR_POS :Peamine tarvikuriba paikneb: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Tarvikuriba rõhtne paiknemine ekraani ülaosas @@ -1727,7 +1763,7 @@ STR_CONFIG_SETTING_GRAPHICS :{ORANGE}Graafik STR_CONFIG_SETTING_SOUND :{ORANGE}Heliefektid STR_CONFIG_SETTING_INTERFACE :{ORANGE}Liides STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}Üldine -STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Vaateavad +STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Vaated STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Ehitus STR_CONFIG_SETTING_ADVISORS :{ORANGE}Uudised / Nõunikud STR_CONFIG_SETTING_COMPANY :{ORANGE}Ettevõte @@ -1984,6 +2020,10 @@ STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Liitu m STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Uuenda andmeid STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Serveri info värskendamine +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Otsing internetis +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Internetis avalike serverite otsimine +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Otsing LANis +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Kohtvõrgus serverite otsimine STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Sisesta server STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Sisesta loendisse uus server, milles toimuvaid mänge jälgida STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Tee server @@ -2000,9 +2040,9 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Serveril STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Määra salasõna STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Et server ei oleks avalik, kaitse oma mäng salasõnaga -STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Reklaamitav +STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Reklaami STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Valib reklaamitava (internet) või mittereklaamitava (kohtvõrk, LAN) mängu -STR_NETWORK_START_SERVER_UNADVERTISED :Jah +STR_NETWORK_START_SERVER_UNADVERTISED :Ei STR_NETWORK_START_SERVER_ADVERTISED :Jah STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} klient{P "" i} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Kliente kuni: @@ -2014,7 +2054,7 @@ STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Piirab s STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} vaatleja{P "" t} STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Vaatlejaid kuni: STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Piirab serveris olevate vaatlejate arvu -STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Räägitav keel: +STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Suhtluskeel: STR_NETWORK_START_SERVER_LANGUAGE_TOOLTIP :{BLACK}Teavitab teisi mängijaid, mis keeles serveris rääkida STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE :{BLACK}Sisesta mitmikmängu nimi @@ -2224,6 +2264,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} li STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} alustas uue ettevõtte (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} lahkus mängust ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} uus nimi on {STRING} +STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} saatis {2:CURRENCY_LONG} ettevõttele {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server sulges sessiooni STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server restardib...{}Palun oota... @@ -2591,7 +2632,7 @@ STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Ehita STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Rahasta # Industry cargoes window -STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Tööstuse {STRING} tööstuahel +STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Tööstuse {STRING} tööstusahel STR_INDUSTRY_CARGOES_CARGO_CAPTION :{WHITE}Kauba {STRING} tööstusahel STR_INDUSTRY_CARGOES_PRODUCERS :{WHITE}Tootvad tööstused STR_INDUSTRY_CARGOES_CUSTOMERS :{WHITE}Vastuvõtvad tööstused @@ -2858,8 +2899,8 @@ STR_NEWGRF_SETTINGS_CAPTION :{WHITE}NewGRF-i STR_NEWGRF_SETTINGS_INFO_TITLE :{WHITE}Põhjalikud NewGRF-i andmed STR_NEWGRF_SETTINGS_ACTIVE_LIST :{WHITE}Tegusad NewGRF failid STR_NEWGRF_SETTINGS_INACTIVE_LIST :{WHITE}Mittetegusad NewGRF failid -STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}Vali väärtus: -STR_NEWGRF_FILTER_TITLE :{ORANGE}Filtreeri sõna: +STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}Eelseadistus: +STR_NEWGRF_FILTER_TITLE :{ORANGE}Märksõna: STR_NEWGRF_SETTINGS_PRESET_LIST_TOOLTIP :{BLACK}Laadi valitud eelseadistused STR_NEWGRF_SETTINGS_PRESET_SAVE :{BLACK}Salvesta eelseadistus STR_NEWGRF_SETTINGS_PRESET_SAVE_TOOLTIP :{BLACK}Salvesta praegune loend eelseadistusena @@ -3529,7 +3570,7 @@ STR_DEPOT_ROAD_VEHICLE_SELL_TOOLTIP :{BLACK}Et müü STR_DEPOT_SHIP_SELL_TOOLTIP :{BLACK}Müügiks tiri laev siia STR_DEPOT_AIRCRAFT_SELL_TOOLTIP :{BLACK}Müümiseks tiri lennuk siia -STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP :{BLACK}Tõsta vedur siia, et kogu rong maha müüa +STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP :{BLACK}Tõsta rongi vedur siia, et müüa rong täies koosseisus STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TOOLTIP :{BLACK}Müü kõik rongid jaamast STR_DEPOT_SELL_ALL_BUTTON_ROAD_VEHICLE_TOOLTIP :{BLACK}Müü kõik autod garaažist diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 07b4df9b53..4c7a16a9d7 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -231,8 +231,8 @@ STR_LIST_FILTER_OSKTITLE :{BLACK}검색 STR_LIST_FILTER_TOOLTIP :{BLACK}검색할 키워드를 입력하세요 STR_TOOLTIP_GROUP_ORDER :{BLACK}그룹화 순서를 선택하세요. -STR_TOOLTIP_SORT_ORDER :{BLACK}정렬 방법을 선택하십시오. (내림차순/오름차순) -STR_TOOLTIP_SORT_CRITERIA :{BLACK}정렬 기준을 선택하십시오. +STR_TOOLTIP_SORT_ORDER :{BLACK}정렬 방법을 선택하세요 (내림차순/오름차순) +STR_TOOLTIP_SORT_CRITERIA :{BLACK}정렬 기준을 선택하세요 STR_TOOLTIP_FILTER_CRITERIA :{BLACK}검색 기준 선택 STR_BUTTON_SORT_BY :{BLACK}정렬 STR_BUTTON_CATCHMENT :{BLACK}역세권 @@ -863,9 +863,9 @@ STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY :{WHITE}{VEHICLE STR_NEWS_VEHICLE_IS_GETTING_OLD :{WHITE}{VEHICLE} : 차량이 낡았습니다. STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD :{WHITE}{VEHICLE} : 차량이 매우 낡았습니다. STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND :{WHITE}{VEHICLE} : 차량이 매우 낡아 교체가 시급합니다 -STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE} : 다음 목적지로 가는 경로를 찾을 수 없습니다. -STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} : 아직 다음 목적지에 도착하지 못했습니다. -STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}{VEHICLE}의 작년 이익이 {CURRENCY_LONG} 입니다. +STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE} : 다음 목적지로 가는 경로를 찾을 수 없습니다 +STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} : 아직 다음 목적지에 도착하지 못했습니다 +STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}{VEHICLE}의 작년 이익이 {CURRENCY_LONG} 입니다 STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}거리가 너무 멀어서 {VEHICLE}이 다음 목적지에 도착할 수 없습니다 STR_NEWS_ORDER_REFIT_FAILED :{WHITE}경로 상에 있던 개조에 실패하여 {VEHICLE}의 운행을 멈췄습니다. @@ -955,7 +955,7 @@ STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :좌측통행 STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :우측통행 STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}도시 이름 -STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}도시 이름 스타일을 선택하십시오. +STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}도시 이름 스타일을 선택하세요 ############ start of townname region STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH :영국 식 (기본) @@ -993,13 +993,13 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS :12개월마다 ############ end of autosave dropdown STR_GAME_OPTIONS_LANGUAGE :{BLACK}언어 -STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}사용하실 언어를 선택하세요. +STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :{BLACK}사용할 언어를 선택하세요 STR_GAME_OPTIONS_FULLSCREEN :{BLACK}전체화면 STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP :{BLACK}OpenTTD를 전체화면으로 플레이하려면 클릭하세요. STR_GAME_OPTIONS_RESOLUTION :{BLACK}화면 해상도 -STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}사용하실 화면 해상도를 선택하세요. +STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}사용할 화면 해상도를 선택하세요 STR_GAME_OPTIONS_RESOLUTION_OTHER :기타 STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}인터페이스 크기 @@ -1010,23 +1010,23 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :2배 크기 STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :4배 크기 STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}글씨 크기 -STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}인터페이스에서 사용할 글씨 크기를 선택합니다. +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}인터페이스에서 사용할 글씨 크기를 선택하세요 STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :기본 크기 STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :2배 크기 STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :4배 크기 STR_GAME_OPTIONS_BASE_GRF :{BLACK}기본 그래픽 세트 -STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}사용하실 기본 그래픽을 선택하세요. +STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}게임에 사용할 기본 그래픽 세트를 선택하세요 STR_GAME_OPTIONS_BASE_GRF_STATUS :{RED}{NUM}개 파일 손실 STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}기본 그래픽 세트에 대한 추가 정보를 봅니다. STR_GAME_OPTIONS_BASE_SFX :{BLACK}기본 효과음 세트 -STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}게임에 사용할 기본 효과음 세트를 선택하십시오. +STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}게임에 사용할 기본 효과음 세트를 선택하세요 STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}기본 효과음 세트에 대한 추가 정보를 봅니다. STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}기본 배경 음악 세트 -STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}사용하실 기본 배경 음악 세트를 선택하세요. +STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}게임에 사용할 기본 배경 음악 세트를 선택하세요 STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM}개의 파일이 손상되었습니다. STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}기본 배경 음악 세트에 대한 추가 정보를 봅니다. @@ -1189,7 +1189,7 @@ STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :이 설정을 STR_CONFIG_SETTING_DISASTERS :재앙: {STRING} STR_CONFIG_SETTING_DISASTERS_HELPTEXT :일정 구역이나 차량, 기반시설을 간혹 파괴할 수도 있는 재앙을 켜거나 끕니다. STR_CONFIG_SETTING_CITY_APPROVAL :지역 개발에 대한 도시의 태도: {STRING} -STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :회사가 유발하는 소음과 환경 파괴가 회사에 대한 도시의 평가치와 향후 해당 지역에서 건설하는 행동에 얼마나 영향을 미칠지 선택하십시오. +STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :회사가 유발하는 소음과 환경 파괴가 회사에 대한 도시의 평가치와 향후 해당 지역에서 건설하는 행동에 얼마나 영향을 미칠지 선택하세요 STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :최대 지형 높이: {STRING} STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT :지도에 생성되는 산이 가질 수 있는 최대 높이를 설정합니다. @@ -1208,9 +1208,9 @@ STR_CONFIG_SETTING_TILE_LENGTH :{COMMA}칸 STR_CONFIG_SETTING_SMOKE_AMOUNT :차량의 매연 또는 전기 스파크의 양: {STRING} STR_CONFIG_SETTING_SMOKE_AMOUNT_HELPTEXT :차량에서 연기나 전기 스파크가 얼마나 많이 일어나는지 설정합니다. STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL :열차 가속 모델: {STRING} -STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :열차 가속 물리 모델을 선택하십시오. "오리지널" 모델은 언덕을 오를 때 무조건 속력이 감소합니다. "현실적" 모델은 열차의 길이나 기관차의 견인력 등의 구성 속성에 따라 언덕과 커브에서 속력이 감소합니다. +STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL_HELPTEXT :열차 가속에 사용할 물리 모델을 선택합니다. "오리지널" 모델은 언덕을 오를 때 무조건 속력이 감소합니다. "현실적" 모델은 열차의 길이나 기관차의 견인력 등의 구성 속성에 따라 언덕과 커브에서 속력이 감소합니다. STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL :자동차/전차 가속 모델: {STRING} -STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :자동차/전차의 가속 물리 모델을 선택하십시오. "오리지널" 모델은 언덕을 오를 때 무조건 속력이 감소합니다. "현실적" 모델은 차량의 견인력 등 차량의 다양한 속성에 따라 언덕을 오를 때 속력이 감소합니다. +STR_CONFIG_SETTING_ROAD_VEHICLE_ACCELERATION_MODEL_HELPTEXT :자동차/전차의 가속 물리 모델을 선택하세요. "오리지널" 모델은 언덕을 오를 때 무조건 속력이 감소합니다. "현실적" 모델은 차량의 견인력 등 차량의 다양한 속성에 따라 언덕을 오를 때 속력이 감소합니다. STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS :경사도 설정 (열차용): {STRING} STR_CONFIG_SETTING_TRAIN_SLOPE_STEEPNESS_HELPTEXT :열차에 적용시킬 경사도를 설정합니다. 값이 높을수록 열차가 언덕을 올라가는데 더 힘이 듭니다. STR_CONFIG_SETTING_PERCENTAGE :{COMMA}% @@ -1286,7 +1286,7 @@ STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :기반시설 STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :이 설정을 켜면, 기반시설 유지비가 발생합니다. 유지비는 교통망의 규모에 비례하며 대형 회사는 소형 회사보다 많은 유지비가 들어갑니다. STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :시작시 회사 색상: {STRING} -STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :새 회사에서 사용할 색상을 선택하세요. +STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :새 회사에서 사용할 색상을 선택합니다. STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS :옛날 공항을 사라지지 않고 계속 만들 수 있게 함: {STRING} STR_CONFIG_SETTING_NEVER_EXPIRE_AIRPORTS_HELPTEXT :이 설정을 켜면, 소형 공항을 포함한 모든 공항 종류를 도입 이후에 계속 사용할 수 있게 됩니다. @@ -1347,14 +1347,14 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :매우 거칠 STR_CONFIG_SETTING_VARIETY :산세 험준도: {STRING} STR_CONFIG_SETTING_VARIETY_HELPTEXT :(천지창조 전용) 지도가 산지와 평지를 모두 갖도록 만들 것인 지를 결정합니다. 이 설정은 지형을 더 평평하게 만드므로, 다른 설정은 '산'으로 설정하시기 바랍니다. STR_CONFIG_SETTING_RIVER_AMOUNT :강의 양: {STRING} -STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :강을 얼마나 만들지 선택하십시오. +STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :강을 얼마나 만들지 선택하세요 STR_CONFIG_SETTING_TREE_PLACER :나무 배치 알고리즘: {STRING} -STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :지도의 나무 분포 형식을 선택하십시오. '오리지널'을 선택하면 나무가 고르게 분포되고, '향상됨'을 선택하면 나무가 군락을 이루게 됩니다. +STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :지도의 나무 분포 형식을 선택하세요. '오리지널'을 선택하면 나무가 고르게 분포되고, '향상됨'을 선택하면 나무가 군락을 이루게 됩니다. STR_CONFIG_SETTING_TREE_PLACER_NONE :없음 STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :오리지널 STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :향상됨 STR_CONFIG_SETTING_ROAD_SIDE :자동차 통행 방향: {STRING} -STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :통행방향을 선택하세요. +STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :통행 방향을 선택합니다 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :높이맵 회전: {STRING} STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :반시계방향 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :시계방향 @@ -1414,7 +1414,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :오른쪽 클 STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :창 내부를 오른쪽 클릭하여 창을 닫습니다. 오른쪽 클릭으로 도움말 표시 설정을 해제해야 합니다! STR_CONFIG_SETTING_AUTOSAVE :자동 저장: {STRING} -STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :게임을 자동으로 저장할 간격을 선택하십시오. +STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :게임을 자동으로 저장할 간격을 선택하세요 STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :저장 파일 이름으로 {STRING} 날짜 형식을 사용 STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT :게임 저장 파일 이름에 사용할 날짜 형식을 선택합니다. @@ -2010,7 +2010,7 @@ STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}비밀 STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}서버에 공개적으로 접근하는 것을 막고 싶을 때 비밀번호를 걸어 보호합니다. STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}공개 여부 -STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}공개된 게임(인터넷)과 비공개된 게임(LAN) 중에서 선택하십시오. +STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}공개된 게임(인터넷)과 비공개된 게임(LAN) 중에서 선택하세요 STR_NETWORK_START_SERVER_UNADVERTISED :아니요 STR_NETWORK_START_SERVER_ADVERTISED :예 STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM}명 @@ -2329,7 +2329,7 @@ STR_TRANSPARENT_INVISIBLE_TOOLTIP :{BLACK}반투 STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}화물 흐름 범례 STR_LINKGRAPH_LEGEND_ALL :{BLACK}모두 STR_LINKGRAPH_LEGEND_NONE :{BLACK}없음 -STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}표시할 회사를 선택하십시오 +STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}표시할 회사를 선택하세요 STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap @@ -2424,7 +2424,7 @@ STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}드래 # Bridge selection window STR_SELECT_RAIL_BRIDGE_CAPTION :{WHITE}철교 선택 -STR_SELECT_ROAD_BRIDGE_CAPTION :{WHITE}다리 종류를 선택하십시오 +STR_SELECT_ROAD_BRIDGE_CAPTION :{WHITE}다리 종류를 선택하세요 STR_SELECT_BRIDGE_SELECTION_TOOLTIP :{BLACK}다리 건설 - 원하는 다리 종류를 선택하세요 STR_SELECT_BRIDGE_INFO :{GOLD}{STRING},{} {VELOCITY} {WHITE}{CURRENCY_LONG} STR_SELECT_BRIDGE_SCENEDIT_INFO :{GOLD}{STRING},{} {VELOCITY} @@ -2605,7 +2605,7 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}임의 # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}새 산업시설 건설 -STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}목록에서 적당한 산업시설을 선택하십시오 +STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}목록에서 적당한 산업시설을 선택하세요 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :무작위 산업시설 건설 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}무작위로 산업시설을 건설합니다 STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}가격: {YELLOW}{CURRENCY_LONG} @@ -2848,7 +2848,7 @@ STR_SAVELOAD_OSKTITLE :{BLACK}게임 # World generation STR_MAPGEN_WORLD_GENERATION_CAPTION :{WHITE}세계 제작 STR_MAPGEN_MAPSIZE :{BLACK}지도 크기: -STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}지도의 크기를 칸 수 기준으로 선택하십시오. 사용 가능한 지도의 칸 수는 선택한 값보다 조금 적습니다 +STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}지도의 크기를 칸 수 기준으로 선택하세요. 사용 가능한 지도의 칸 수는 설정한 값보다 조금 작을 것입니다 STR_MAPGEN_BY :{BLACK}x STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}도시의 수: STR_MAPGEN_DATE :{BLACK}날짜: @@ -2973,7 +2973,7 @@ STR_NEWGRF_SETTINGS_INCOMPATIBLE :{RED}이 OpenTT # NewGRF save preset window STR_SAVE_PRESET_CAPTION :{WHITE}프리셋 저장 -STR_SAVE_PRESET_LIST_TOOLTIP :{BLACK}사용 가능한 프리셋 목록입니다. 아래에 같은 이름을 복사하려면 선택하십시오 +STR_SAVE_PRESET_LIST_TOOLTIP :{BLACK}사용 가능한 프리셋 목록입니다. 아래에 같은 이름을 복사하려면 선택하세요 STR_SAVE_PRESET_TITLE :{BLACK}프리셋의 이름을 입력하세요 STR_SAVE_PRESET_EDITBOX_TOOLTIP :{BLACK}저장할 프리셋에 지정할 이름입니다 STR_SAVE_PRESET_CANCEL :{BLACK}취소 @@ -3724,8 +3724,8 @@ STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP :{BLACK}이 열 STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES :{YELLOW}교체할 수 있는 차량 STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP :{BLACK}이 열은 교체할 수 있는 차량 목록입니다 -STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}교체할 기관차 종류를 선택하십시오 -STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}새로 교체될 기관차를 선택하십시오 +STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}교체할 기관차 종류를 선택하세요 +STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}새로 교체될 기관차를 선택하세요 STR_REPLACE_VEHICLES_START :{BLACK}차량 교체 시작 STR_REPLACE_VEHICLES_NOW :모든 차량을 지금 교체 @@ -3901,7 +3901,7 @@ STR_REFIT_NEW_CAPACITY_COST_OF_REFIT :{BLACK}변경 STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT :{BLACK}변경 수송량: {GOLD}{CARGO_LONG}{}{BLACK}개조시 회수되는 비용: {GREEN}{CURRENCY_LONG} STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT :{BLACK}변경 수송량: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}개조 비용: {RED}{CURRENCY_LONG} STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT :{BLACK}변경 수송량: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}개조시 회수되는 비용: {GREEN}{CURRENCY_LONG} -STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}개조할 차량을 선택하십시오. 마우스로 드래그하면 여러 개의 차량을 선택 가능합니다. 빈 곳을 클릭하면 전체를 선택합니다. CTRL+클릭하면 차량 전체를 선택할 수 있습니다 +STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}개조할 차량을 선택하세요. 마우스로 드래그하면 여러 개의 차량을 선택 가능합니다. 빈 곳을 클릭하면 전체를 선택합니다. CTRL+클릭하면 차량 전체를 선택할 수 있습니다 STR_REFIT_TRAIN_LIST_TOOLTIP :{BLACK}열차가 수송할 화물의 종류를 선택하세요 STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}차량이 수송할 화물의 종류를 선택하세요 @@ -3953,7 +3953,7 @@ STR_ORDER_DROP_NO_UNLOADING :화물을 하 STR_ORDER_TOOLTIP_UNLOAD :{BLACK}선택한 목적지에서 화물을 하차할 방식을 변경합니다 STR_ORDER_REFIT :{BLACK}개조 -STR_ORDER_REFIT_TOOLTIP :{BLACK}이 경로에서 열차를 어떤 화물을 받을 수 있게 개조할 것인지 선택하십시오. CTRL+클릭하면 개조 설정을 해제합니다. +STR_ORDER_REFIT_TOOLTIP :{BLACK}이 경로에서 열차를 어떤 화물을 받을 수 있게 개조할 것인지 선택하세요. CTRL+클릭하면 개조 설정을 해제합니다 STR_ORDER_REFIT_AUTO :{BLACK}개조 STR_ORDER_REFIT_AUTO_TOOLTIP :{BLACK}이 경로에서 개조할 화물의 종류를 선택하세요. CTRL+클릭하면 개조 설정을 해제합니다. 개조 기능은 개조 가능한 차량에서만 사용할 수 있습니다. STR_ORDER_DROP_REFIT_AUTO :특정 화물로 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 6674699629..a03aa41626 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -195,6 +195,7 @@ STR_COLOUR_DEFAULT :Padrão STR_UNITS_VELOCITY_IMPERIAL :{COMMA} mph STR_UNITS_VELOCITY_METRIC :{COMMA} km/h STR_UNITS_VELOCITY_SI :{COMMA} m/s +STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP} blocos / dia STR_UNITS_POWER_IMPERIAL :{COMMA}cv STR_UNITS_POWER_METRIC :{COMMA}cv @@ -235,6 +236,7 @@ STR_TOOLTIP_SORT_CRITERIA :{BLACK}Seleccio STR_TOOLTIP_FILTER_CRITERIA :{BLACK}Seleccione o critério de filtragem/procura STR_BUTTON_SORT_BY :{BLACK}Ordenar por STR_BUTTON_CATCHMENT :{BLACK}Cobertura +STR_TOOLTIP_CATCHMENT :{BLACK}Alternar exibição da área de cobertura STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Fechar janela STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Título da janela - arraste isto para mover a janela @@ -311,6 +313,8 @@ STR_SORT_BY_CARGO_CAPACITY :Capacidade de C STR_SORT_BY_RANGE :Alcance STR_SORT_BY_POPULATION :População STR_SORT_BY_RATING :Classificação +STR_SORT_BY_NUM_VEHICLES :Número de veículos +STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Lucro médio este ano # Group by options for vehicle list @@ -1435,6 +1439,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Deixar ferramen STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Manter as ferramentas de construção de pontes, túneis, etc. abertas após uso STR_CONFIG_SETTING_EXPENSES_LAYOUT :Agrupar despesas na janela de finanças da empresa: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Definir a disposição da janela de despesas da companhia +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Remova automaticamente os sinais durante a construção do trilho se os sinais estiverem no caminho. Observe que isso pode potencialmente levar a acidentes de comboio. STR_CONFIG_SETTING_SOUND_TICKER :Notícias: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Reproduzir efeito sonoro para notícias resumidas @@ -1542,8 +1547,10 @@ STR_CONFIG_SETTING_NEWS_MESSAGES_FULL :Completo STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Noticias a cores aparecem em: {STRING} STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Ano em que os anúncios de jornal começam a ser mostrados a cores. Antes deste ano, serão mostrados a preto e branco. STR_CONFIG_SETTING_STARTING_YEAR :Data de início: {STRING} +STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :A economia suave faz mudanças na produção com mais frequência e em etapas menores. Economia congelada impede mudanças de produção e fechamentos de indústrias. Esta configuração pode não ter efeito se os tipos de indústria forem fornecidos por um NewGRF. STR_CONFIG_SETTING_ALLOW_SHARES :Permite comprar acções de outras empresas: {STRING} STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :Quando activo, permite a compra e venda de acções de companhias. As acções apenas estarão disponíveis quando a companhia atinge uma determinada idade. +STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Idade mínima da empresa para negociar ações: {STRING} STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Definir a idade mínima de uma companhia a partir da qual outros jogadores poderão comprar ou vender ações da mesma. STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Percentagem do lucro do serviço a pagar em trajectos de um transporte que alimenta outro transporte: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Percentagem da receita dada a trajectos intermédios em sistemas em que um transporte alimenta outro, dando maior controlo sobre a receita @@ -1592,6 +1599,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Criação de árvores no decorrer do jogo: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Controlar o aparecimento aleatório de árvores durante o jogo. Isto poderá afectar indústrias que dependem do crescimento de árvores, como as madeireiras +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Não cresça, não espalhe {RED} (quebra a serraria) STR_CONFIG_SETTING_TOOLBAR_POS :Posição da barra de ferramentas principal: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Posição horizontal da barra de ferramentas principal no topo do ecrã @@ -1801,6 +1809,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Tem a c # Cheat window STR_CHEATS :{WHITE}Truques STR_CHEATS_TOOLTIP :{BLACK}As caixas de verificação indicam se já usou este truque antes +STR_CHEATS_NOTE :{BLACK}Nota: qualquer uso dessas configurações será registrado pelo savegame STR_CHEAT_MONEY :{LTBLUE}Aumentar dinheiro em {CURRENCY_LONG} STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Jogando como empresa: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Bulldozer mágico (destrói indústrias, objectos amovíveis etc.): {ORANGE}{STRING} @@ -1952,6 +1961,8 @@ STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Entrar n STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Renovar servidor STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Renovar a informação do servidor +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Search LAN +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK} Pesquisa de rede local para servidores STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Adicionar servidor STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adiciona um servidor à lista que será sempre verificado se existem jogos a decorrer. STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor @@ -2176,11 +2187,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Jogo ainda em p STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Jogo ainda em pausa ({STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Jogo ainda em pausa ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Jogo ainda em pausa ({STRING}, {STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Jogo ainda pausado ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Jogo a Correr ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :número de jogadores STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :a ligar clientes STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manual STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :script de jogo +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :esperando pela atualização do gráfico de links ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :a sair STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} entrou no jogo @@ -2503,6 +2516,9 @@ STR_TREES_RANDOM_TYPE :{BLACK}Árvores STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Colocar árvores de tipo aleatório. Shift alterna construir/mostrar custo estimado STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Plantar aleatoriamente STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Plantar árvores aleatoriamente no terreno +STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}Plante árvores isoladas arrastando-as pela paisagem. +STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Arvoredo +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Floresta # Land generation window (SE) STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Gerar Terreno @@ -2723,6 +2739,7 @@ STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMA STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL} fotograma/s STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL} fotograma/s STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} +STR_FRAMERATE_BYTES_WARN :{YELLOW}{BYTES} STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s ############ Leave those lines in this order!! @@ -3357,6 +3374,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Indústrias STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- Nenhuma - STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} +STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} e mais {NUM} ... STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Nomes de indústrias - clique no nome para centrar-se na indústria. Ctrl+Clique abre um novo visualizador na localização da indústria # Industry view @@ -3688,6 +3706,7 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Forçar # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK} Centralize a vista principal na localização da aeronave. Um clique duplo seguirá a aeronave na visualização principal. Ctrl + Clique abre uma nova janela de visualização na localização da aeronave STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Mandar comboio para o depósito STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Mandar veículo para o depósito @@ -3719,6 +3738,8 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Mostrar STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Mostrar detalhes do navio STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Mostrar detalhes da aeronave +STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Ação do comboio atual - clique para parar / iniciar o comboio +STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Ação atual da aeronave - clique para parar / iniciar a aeronave # Messages in the start stop button in the vehicle view @@ -4125,6 +4146,8 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}Seleccio STR_AI_LIST_CANCEL :{BLACK}Cancelar STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}Não mudar o script +STR_SCREENSHOT_SCREENSHOT :{BLACK}Captura de tela normal +STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Minimap screenshot # AI Parameters STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parâmetros @@ -4184,6 +4207,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Jogo gravado nu STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :Impossível ler ficheiro STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :Impossível escrever ficheiro STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :Falha ao verificar integridade de dados +STR_GAME_SAVELOAD_ERROR_PATCHPACK :Salvar o jogo é feito com uma versão modificada STR_GAME_SAVELOAD_NOT_AVAILABLE : STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}O jogo foi salvo numa versão sem suporte para eléctricos. Todos os elétricos foram removidos. From 5ae2c1552b33c677454eb8594ae32ae00efac6a5 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 30 Jan 2021 18:14:36 +0000 Subject: [PATCH 008/275] Update: Translations from eints estonian: 353 changes by siimsoni --- src/lang/estonian.txt | 552 +++++++++++++++++++++++++++--------------- 1 file changed, 353 insertions(+), 199 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index e800ef85a7..d9512ad231 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -46,8 +46,8 @@ STR_CARGO_PLURAL_IRON_ORE :Rauamaak STR_CARGO_PLURAL_IRON_ORE.g :Rauamaagi STR_CARGO_PLURAL_STEEL :Teras STR_CARGO_PLURAL_STEEL.g :Terase -STR_CARGO_PLURAL_VALUABLES :Väärisasjad -STR_CARGO_PLURAL_VALUABLES.g :Väärisasjade +STR_CARGO_PLURAL_VALUABLES :Väärisesemed +STR_CARGO_PLURAL_VALUABLES.g :Väärisesemete STR_CARGO_PLURAL_COPPER_ORE :Vasemaak STR_CARGO_PLURAL_COPPER_ORE.g :Vasemaagi STR_CARGO_PLURAL_MAIZE :Mais @@ -160,7 +160,7 @@ STR_QUANTITY_GRAIN :{WEIGHT_LONG} t STR_QUANTITY_WOOD :{WEIGHT_LONG} puitu STR_QUANTITY_IRON_ORE :{WEIGHT_LONG} rauamaaki STR_QUANTITY_STEEL :{WEIGHT_LONG} terast -STR_QUANTITY_VALUABLES :{COMMA} kotitäi{P s t} väärisasju +STR_QUANTITY_VALUABLES :{COMMA}{NBSP}kotitäi{P s t} väärisesemeid STR_QUANTITY_COPPER_ORE :{WEIGHT_LONG} vasemaaki STR_QUANTITY_MAIZE :{WEIGHT_LONG} maisi STR_QUANTITY_FRUIT :{WEIGHT_LONG} puuvilju @@ -251,6 +251,7 @@ STR_COLOUR_DEFAULT :Esialgne STR_UNITS_VELOCITY_IMPERIAL :{COMMA} miili tunnis STR_UNITS_VELOCITY_METRIC :{COMMA} km/h STR_UNITS_VELOCITY_SI :{COMMA} m/s +STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}ruutu/päev STR_UNITS_POWER_IMPERIAL :{COMMA}hj STR_UNITS_POWER_METRIC :{COMMA}hj @@ -282,14 +283,16 @@ STR_UNITS_HEIGHT_SI :{COMMA} m # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Märksõna: -STR_LIST_FILTER_OSKTITLE :{BLACK}Sisesta filterkirjend +STR_LIST_FILTER_OSKTITLE :{BLACK}Sisesta märksõna STR_LIST_FILTER_TOOLTIP :{BLACK}Sisesta märksõna mida loendist otsida -STR_TOOLTIP_GROUP_ORDER :{BLACK}Vali rühmitamise järjestus +STR_TOOLTIP_GROUP_ORDER :{BLACK}Vali jaotamise järjestus STR_TOOLTIP_SORT_ORDER :{BLACK}Vali järjestus (kahanev/kasvav) STR_TOOLTIP_SORT_CRITERIA :{BLACK}Vali järjestus STR_TOOLTIP_FILTER_CRITERIA :{BLACK}Vali sõelumisalused STR_BUTTON_SORT_BY :{BLACK}Järjestus: +STR_BUTTON_CATCHMENT :{BLACK}Mõjupiirkond +STR_TOOLTIP_CATCHMENT :{BLACK}Vahelda mõjuala näitamist STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Sulge aken STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Akna pealkiri. Liigutamiseks lohista seda hiirega. @@ -367,11 +370,15 @@ STR_SORT_BY_CARGO_CAPACITY :Kandevõime STR_SORT_BY_RANGE :Vahekaugus STR_SORT_BY_POPULATION :Rahvaarv STR_SORT_BY_RATING :Hinnang +STR_SORT_BY_NUM_VEHICLES :Sõidukite koguarv +STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Eelmise aasta kogukasum STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Selle aasta kogukasum STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Eelmise aasta keskmine kasum STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Selle aasta keskmine kasum # Group by options for vehicle list +STR_GROUP_BY_NONE :Puudub +STR_GROUP_BY_SHARED_ORDERS :Jagatud korraldused # Tooltips for the main toolbar STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Seiska mäng @@ -389,14 +396,15 @@ STR_TOOLBAR_TOOLTIP_DISPLAY_GOALS_LIST :{BLACK}Näita e STR_TOOLBAR_TOOLTIP_DISPLAY_GRAPHS :{BLACK}Ava graafik STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_LEAGUE :{BLACK}Ava ettevõtete edetabel STR_TOOLBAR_TOOLTIP_FUND_CONSTRUCTION_OF_NEW :{BLACK}Uue tööstuse rajamise rahastamine või tööstuste registri avamine -STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_TRAINS :{BLACK}Ava ettevõtte rongide register. Rühma- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil -STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_ROAD_VEHICLES :{BLACK}Ava ettevõtte mootorsõidukite register. Rühma- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil -STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_SHIPS :{BLACK}Ava ettevõtte laevade register. Rühma- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil -STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_AIRCRAFT :{BLACK}Ava ettevõtte õhusõidukite register. Rühma- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil +STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_TRAINS :{BLACK}Ava ettevõtte rongide register. Jaotus- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil +STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_ROAD_VEHICLES :{BLACK}Ava ettevõtte mootorsõidukite register. Jaotus- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil +STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_SHIPS :{BLACK}Ava ettevõtte laevade register. Jaotus- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil +STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_AIRCRAFT :{BLACK}Ava ettevõtte õhusõidukite register. Jaotus- ja sõidukiregistrit vahetatakse Ctrl+klõpsu abil STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN :{BLACK}Suurenda vaadet STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT :{BLACK}Vähenda vaadet STR_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Ehita raudtee STR_TOOLBAR_TOOLTIP_BUILD_ROADS :{BLACK}Ehita maantee +STR_TOOLBAR_TOOLTIP_BUILD_TRAMWAYS :{BLACK}Ehita trammiteid STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS :{BLACK}Ehita laevakai STR_TOOLBAR_TOOLTIP_BUILD_AIRPORTS :{BLACK}Ehita lennuväli STR_TOOLBAR_TOOLTIP_LANDSCAPING :{BLACK}Ava riba maastikutarvikutega, millega saab maad tõsta/langetada, puid istutada, jne. @@ -475,7 +483,7 @@ STR_SUBSIDIES_MENU_SUBSIDIES :Toetused ############ range for graph menu starts STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH :Opereerimiskasumi graafik STR_GRAPH_MENU_INCOME_GRAPH :Tulugraafik -STR_GRAPH_MENU_DELIVERED_CARGO_GRAPH :Kaubavoo graafik +STR_GRAPH_MENU_DELIVERED_CARGO_GRAPH :Äraveetud kauba graafik STR_GRAPH_MENU_PERFORMANCE_HISTORY_GRAPH :Tegevustulemuste graafik STR_GRAPH_MENU_COMPANY_VALUE_GRAPH :Firmaväärtuse graafik STR_GRAPH_MENU_CARGO_PAYMENT_RATES :Veotasude määrad @@ -632,13 +640,13 @@ STR_GRAPH_Y_LABEL_NUMBER :{TINY_FONT}{COM STR_GRAPH_OPERATING_PROFIT_CAPTION :{WHITE}Opereerimiskasumi graafik STR_GRAPH_INCOME_CAPTION :{WHITE}Tulugraafik -STR_GRAPH_CARGO_DELIVERED_CAPTION :{WHITE}Veetud veoste kogus +STR_GRAPH_CARGO_DELIVERED_CAPTION :{WHITE}Äraveetud kaubaühikute arv STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION :{WHITE}Ettevõtte tegevushinnang (suurim hinnang saab olla 1000) STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Firmaväärtus -STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Veoste hinnagraafik +STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Veotariifid STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL :{TINY_FONT}{BLACK}Päevi teel -STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Makstav summa 10 ühiku (või 10'000 liitri) veo eest iga 20 ruudu kohta +STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Tasu 10 ühiku (või 10 000 liitri) kauba äraveo eest üle 20 ruudu STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Kõik sisse STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Kõik välja STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}Näita kõiki kaubatüüpe kaubamaksumuste määrade graafikul @@ -678,7 +686,7 @@ STR_PERFORMANCE_DETAIL_STATIONS :{BLACK}Jaamad: STR_PERFORMANCE_DETAIL_MIN_PROFIT :{BLACK}Vähim kasum: STR_PERFORMANCE_DETAIL_MIN_INCOME :{BLACK}Vähim tulu: STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Suurim tulu: -STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Kohale toimetatud: +STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Äraveetud: STR_PERFORMANCE_DETAIL_CARGO :{BLACK}Veoseid: STR_PERFORMANCE_DETAIL_MONEY :{BLACK}Raha: STR_PERFORMANCE_DETAIL_LOAN :{BLACK}Laen: @@ -689,7 +697,7 @@ STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}Hiljuti STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}Madalaima tuluga sõiduki kasum (arvestatakse vaid üle kaheaastaseid sõidukeid) STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}Vähim kvartalikasum viimase 12 kvartali jooksul STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}Suurim kvartalikasum viimase 12 kvartali jooksul -STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP :{BLACK}Viimasel neljal kvartalil kohale toimetatud kaubaühikute koguarv +STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP :{BLACK}Viimasel neljal kvartalil äraveetud kaubaühikute koguarv STR_PERFORMANCE_DETAIL_CARGO_TOOLTIP :{BLACK}Viimasel kvartalil kohale toimetatud veoseliikide koguarv STR_PERFORMANCE_DETAIL_MONEY_TOOLTIP :{BLACK}Rahakogus sellel firmal pangas STR_PERFORMANCE_DETAIL_LOAN_TOOLTIP :{BLACK}Selle ettevõtte kogulaen @@ -708,6 +716,7 @@ STR_MUSIC_EFFECTS_VOLUME :{TINY_FONT}{BLA STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKGREEN}-- STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ +STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Muusikat pole saadaval STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Lugu STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Pealkiri @@ -728,11 +737,14 @@ STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE :{BLACK}Lülita STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Näita muusikalugude valimise akent # Playlist window +STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Muusikaprogramm - '{STRING}' STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Loo number STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Puhasta +STR_PLAYLIST_CHANGE_SET :{BLACK}Muuda kogu STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Tühjenda valitud programm (ainult omatehtud 1 ja omatehtud 2) +STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Vaheta muusikavalik teise paigaldatud kogumi vastu STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Vajuta loole, et seda programmi lisada (ainult omatehtud 1 ja omatehtud 2) STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Vajuta laulule, et see eemaldada praegusest progammist (Custom1 või Custom2 ainult) @@ -792,6 +804,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Konarlik maa STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Rohuväli STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Lage maa +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Vihmamets STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Põllud STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Puud STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Kivid @@ -823,6 +836,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Näita k STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Näita viimast teadet STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * SEISATUS * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * SEISATUD (transpordisõlmede graafiku uuenduse ootel) * * STR_STATUSBAR_AUTOSAVE :{RED}VÄLPSALVESTUS STR_STATUSBAR_SAVING_GAME :{RED}* * MÄNGU SALVESTAMINE * * @@ -834,13 +848,13 @@ STR_MESSAGE_NEWS_FORMAT :{STRING} - {S STR_NEWS_MESSAGE_CAPTION :{WHITE}Teade STR_NEWS_CUSTOM_ITEM :{BIG_FONT}{BLACK}{STRING} -STR_NEWS_FIRST_TRAIN_ARRIVAL :{BIG_FONT}{BLACK}Rahvas rõõmustab. . .{}{STATION} jaama saabus esimene rong! -STR_NEWS_FIRST_BUS_ARRIVAL :{BIG_FONT}{BLACK}Rahvas rõõmustab . . .{}{STATION} jaama saabus esimene buss! -STR_NEWS_FIRST_TRUCK_ARRIVAL :{BIG_FONT}{BLACK}Rahvas rõõmustab . . .{} esimene veok saabus {STATION} jaama! -STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kodanikud tähistavad . . .{}Esimene reisitramm saabus trammijaama {STATION}! -STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Kodanikud tähistavad . . .{}Esimene kaubatramm saabus trammijaama {STATION}! -STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLACK}Rahvas rõõmustab . . .{}{STATION} terminali saabus esimene laev! -STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}Rahvas rõõmustab . . .{}{STATION} terminali saabus esimene lennuk! +STR_NEWS_FIRST_TRAIN_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab. . .{}{STATION} jaama saabus esimene rong! +STR_NEWS_FIRST_BUS_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab. . .{}{STATION} jaama saabus esimene buss! +STR_NEWS_FIRST_TRUCK_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab. . .{} esimene veok saabus {STATION} jaama! +STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab . . .{}Esimene reisitramm saabus trammijaama {STATION}! +STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab . . .{}Esimene kaubatramm saabus trammijaama {STATION}! +STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab . . .{}{STATION} terminali saabus esimene laev! +STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab. . .{}{STATION} terminali saabus esimene lennuk! STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}RONGIKOKKUPÕRGE!{}{COMMA} surid tules peale kokkusõitmist STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}Rongikokkupõrge!{}Juht suri peale õnnetust tules @@ -868,6 +882,7 @@ STR_NEWS_MERGER_TAKEOVER_TITLE :{BIG_FONT}{BLAC STR_PRESIDENT_NAME_MANAGER :{BLACK}{PRESIDENT_NAME}{}(President) STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{STRING} rahastas uue linna {TOWN} rajamist! +STR_NEWS_NEW_TOWN_UNSPONSORED :{BLACK}{BIG_FONT}Uus linn nimega {TOWN} on asutatud! STR_NEWS_INDUSTRY_CONSTRUCTION :{BIG_FONT}{BLACK}Uus {STRING} on linna {TOWN} lähedal ehitamisel! STR_NEWS_INDUSTRY_PLANTED :{BIG_FONT}{BLACK}Uus {STRING} on istutatud linna {TOWN} lähedale! @@ -916,6 +931,7 @@ STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE :{BIG_FONT}{BLAC STR_NEWS_NEW_VEHICLE_TYPE :{BIG_FONT}{BLACK}{ENGINE} STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE :{BLACK}Uus {STRING} saadaval! - {ENGINE} +STR_NEWS_SHOW_VEHICLE_GROUP_TOOLTIP :{BLACK}Ava sõiduki jaole fokuseeritud jaoaken STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO :{WHITE}Jaam {STATION} ei võta enam vastu veost {STRING} STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO :{WHITE}Jaam {STATION} ei võta enam vastu veoseid {STRING}, ega {STRING} @@ -983,7 +999,10 @@ STR_GAME_OPTIONS_CURRENCY_GEL :Gruusia lari (G STR_GAME_OPTIONS_CURRENCY_IRR :Iraani rial (IRR) STR_GAME_OPTIONS_CURRENCY_RUB :Uus Vene rubla (RUB) STR_GAME_OPTIONS_CURRENCY_MXN :Mehhiko Peeso (MXN) +STR_GAME_OPTIONS_CURRENCY_NTD :Uus Taiwani dollar (NTD) +STR_GAME_OPTIONS_CURRENCY_CNY :Hiina renminbi (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kongi dollar (HKD) +STR_GAME_OPTIONS_CURRENCY_INR :India ruupia (INR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Sõidukid @@ -1184,9 +1203,9 @@ STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :Mängu seaded ( STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Mängu seaded (hoitakse salvestuses; mõjutab ainult praegust mängu) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Firma seaded (hoitakse salvestuses; mõjutab ainult uusi mänge) STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Firma seaded (hoitakse salvestuses; mõjutab ainult praegust firmat) -STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Kõiki otsingu tulemusi näeb, kui{}{SILVER}rühm {BLACK}on {WHITE}{STRING} +STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Kõiki otsingu tulemusi näeb, kui{}{SILVER}jagu {BLACK}on {WHITE}{STRING} STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}Kõiki otsingu tulemusi näeb, kui{}{SILVER}liik {BLACK}on {WHITE}Kõik seadistuste liigid -STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Kõiki otsingu tulemusi näeb, kui{}{SILVER}rühm {BLACK}on {WHITE}{STRING} {BLACK}ja {SILVER}liik {BLACK}on {WHITE}Kõik seadistuste liigid +STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Kõiki otsingu tulemusi näeb, kui{}{SILVER}jagu {BLACK}on {WHITE}{STRING} {BLACK}ja {SILVER}liik {BLACK}on {WHITE}Kõik seadistuste liigid STR_CONFIG_SETTINGS_NONE :{WHITE}- Puudub - STR_CONFIG_SETTING_OFF :Väljas @@ -1362,7 +1381,7 @@ STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Näita sõiduki STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Lisa sõidukiehitusaknasse uus rida, mis näitab millisest NewGRF-ist sõiduk on pärit. STR_CONFIG_SETTING_LANDSCAPE :Maastik: {STRING} -STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Igal maastikul on oma kaubatüübid ja nõuded linnade kasvamiseks. Täpsemaid muudatusi saab teha NewGRFi ja mänguskriptide abil. +STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Maastikud määravad põhilised mängustsenaariumid erinevate veoste ja nõuetega linnade kasvamiseks. NewGRF ja GameScript abil saab siiski täpsemalt kontrollida STR_CONFIG_SETTING_LAND_GENERATOR :Maatekituse meetod: {STRING} STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Originaalne generaator sõltub lähtegraafikast ja tekitab kindlaksmääratud maastikuvorme. TerraGenesis on Perlini müral põhinev generaator, mida saab täpsemalt seadistada STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Algupärane @@ -1411,6 +1430,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_GREEN :Roheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_DARK_GREEN :Tumeroheline STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violetne STR_CONFIG_SETTING_SCROLLMODE :Vaate liigutamine: {STRING} +STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT :Kaardil liikumise viis STR_CONFIG_SETTING_SCROLLMODE_DEFAULT :RMB liigutab vaadet, osuti seisab paigal STR_CONFIG_SETTING_SCROLLMODE_RMB_LOCKED :RMB liigutab kaarti, osuti seisab paigal STR_CONFIG_SETTING_SCROLLMODE_RMB :RMB liigutab kaarti @@ -1447,6 +1467,7 @@ STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Ctrl+klõps STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Väljas STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Aken suletakse paremklõpsuga: {STRING} +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Sulgeb akna, kui selles paremklõps teha. Lülitab välja paremklõpsuga vihjed! STR_CONFIG_SETTING_AUTOSAVE :Välpsalvestus: {STRING} STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Vali välpsalvestuste vaheline ajavahemik @@ -1466,7 +1487,7 @@ STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Kõik mitte-ehi STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Kõik peale maastikku muutvate toimingute STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Kõik tõimingud STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Põhjalikku sõidukiregistrit näidatakse: {STRING} -STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Lubab kasutada põhjalikke sõidukiregistreid, kus saab sõidukeid rühmitada +STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Laseb kasutada põhjalikke sõidukiregistreid sõidukite jaotamiseks STR_CONFIG_SETTING_LOADING_INDICATORS :Kasuta laadimisnäidikuid: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Vali, kas koorma peale- ja mahalaadimisel näidatakse laadimisnäidikuid STR_CONFIG_SETTING_TIMETABLE_IN_TICKS :Graafik on sammudes, mitte päevades: {STRING} @@ -1484,7 +1505,7 @@ STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Hõivatud blokk STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Värvib hõivatud blokkpiirkonnad eri värvi, abistamaks tõrgete puhul, kus rongid ei sisene trajektoorijärgsetesse blokkidesse STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Säilita tegev ehitustarvik pärast kasutamist: {STRING} STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Säilita sildade, tunnelite, jms. ehitustarvikud pärast kasutamist -STR_CONFIG_SETTING_EXPENSES_LAYOUT :Kulutuste rühmitamine rahavoogude aruandes: {STRING} +STR_CONFIG_SETTING_EXPENSES_LAYOUT :Kulutuste jaotamine rahavoogude aruandes: {STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Määrab rahavoogude aruande ülesehituse STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Rööbastee ehitamisel on signaalid isekõrvalduvad: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Rööbastee ehitamisel kõrvaldatakse ette jäävad signaalid automaatselt. Silmas pidada, et see võib põhjustada rongide kokkupõrkeid. @@ -1709,9 +1730,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_PAX :Reisijate jaotu STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :Kui jaamast A läheb jaama B umbes sama hulk reisijaid, kui jaamast B jaama A, siis jaotus on «sümeetriline». Kui mõlemas suunas võib liikuda ükskõik, kui palju resijaid, siis jaotus on «asümeetriline». Kui reisijate liikumist ei jaotata, siis jaotus on «väljas». STR_CONFIG_SETTING_DISTRIBUTION_MAIL :Posti jaotuse viis: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :Kui jaamast A viiakse jaama B umbes sama hulk posti, kui jaamast B jaama A, siis jaotus on «sümeetriline». Kui mõlemas suunas viiakse ükskõik, kui palju posti, siis jaotus on «asümeetriline». Kui posti liikumist ei jaotata, siis jaotus on «väljas». -STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :SOOMUSTATUD kaubarühma jaotuse viis: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Parasvöötmes on SOOMUSTATUD kaubarühm väärisasjad, lähistroopikas teemandid, ning lähisartikas kuld. Neid saab lisada NewGRF-iga. Kui jaamast A viiakse jaama B umbes sama hulk kaupa, kui jaamast B jaama A, siis jaotus on «sümeetriline». Kui mõlemas suunas viiakse ükskõik, kui palju kaupa, siis jaotus on «asümeetriline». Kui posti liikumist ei jaotata, siis jaotus on «väljas». Lähisartikas valida asümeetriline või väljas, sest pankadest kulda tagasi ei tule. Parasvöötmes ja lähistroopikas on võimalik valida ka sümeetriline, sest pangad saadavad lähtepanka väärisasju tagasi. -STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Teiste kaubarühmade jaotuse viis: {STRING} +STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :SOOMUSTATUD veoseliigi jaotuse viis: {STRING} +STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Parasvöötmes on SOOMUSTATUD veoseliik väärisesemed, lähistroopikas teemandid, ning lähisartikas kuld. Neid saab lisada NewGRF-iga. Kui jaamast A viiakse jaama B umbes sama hulk kaupa, kui jaamast B jaama A, siis jaotus on «sümeetriline». Kui mõlemas suunas viiakse ükskõik, kui palju kaupa, siis jaotus on «asümeetriline». Kui posti liikumist ei jaotata, siis jaotus on «väljas». Lähisartikas valida asümeetriline või väljas, sest pankadest kulda tagasi ei tule. Parasvöötmes ja lähistroopikas on võimalik valida ka sümeetriline, sest pangad saadavad lähtepanka väärisesemed tagasi. +STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Teiste veoseliikide jaotuse viis: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :Kui jaamast A viiakse jaama B umbes sama hulk kaupa, kui jaamast B jaama A, siis jaotus on «sümeetriline». Kui mõlemas suunas viiakse ükskõik, kui palju kaupa, siis jaotus on «asümeetriline». Kui posti liikumist ei jaotata, siis jaotus on «väljas». Tavaliselt on head valikud «asümeetriline» ja «väljas». STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Jaotuse täpsus: {STRING} STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Kõrgema väärtusega kasutatakse ahelgraafiku koostamiseks protsessorit rohkem. Kui see võtab liiga kaua, võib täheldada viivitusi. Madala väärtusega tekib ebatäpne jaotus, ning kaup ei pruugi õigesse sihtpunkti jõuda. @@ -1727,6 +1748,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Liideses näida STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Inglise mõõdustik (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Meetermõõdustik (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI-süsteem (m/s) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Mänguühikud (ruutu/päev) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Võimsusühikud: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Liideses näidatakse võimsust valitud mõõdustikus @@ -1767,7 +1789,7 @@ STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Vaated STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Ehitus STR_CONFIG_SETTING_ADVISORS :{ORANGE}Uudised / Nõunikud STR_CONFIG_SETTING_COMPANY :{ORANGE}Ettevõte -STR_CONFIG_SETTING_ACCOUNTING :{ORANGE}Raamatupidamine +STR_CONFIG_SETTING_ACCOUNTING :{ORANGE}Arveldamine STR_CONFIG_SETTING_VEHICLES :{ORANGE}Sõidukid STR_CONFIG_SETTING_VEHICLES_PHYSICS :{ORANGE}Füüsika STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}Marsruutimine @@ -1854,10 +1876,12 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Otsi all STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Ava AI/GameScripti seaded STR_INTRO_TOOLTIP_QUIT :{BLACK}Välju 'OpenTTD'st +STR_INTRO_BASESET :{BLACK}Hetkel valitud lähtegraafikakogust puudub {NUM} sprite{P "" 'i}. Kontrolli, kas lähtekogu on uuendatud. STR_INTRO_TRANSLATION :{BLACK}Puudub {NUM} tõlge{P "" t}. Aita teha OpenTTD paremaks, panusta tõlkimisega. Rohkem teavet leiad «readme.txt» failist. # Quit window STR_QUIT_CAPTION :{WHITE}Mängust väljumine +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Kas olete kindel, et soovite OpenTTD-st väljuda? STR_QUIT_YES :{BLACK}Jah STR_QUIT_NO :{BLACK}Ei @@ -1869,6 +1893,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Kas sa # Cheat window STR_CHEATS :{WHITE}Petmine STR_CHEATS_TOOLTIP :{BLACK}Märgistatud kastid näitavad et, kas sa oled varem seda pettust kasutanud +STR_CHEATS_NOTE :{BLACK}Tähelepanu: nende seadete kasutamine jäädvustub salvestatud mängu STR_CHEAT_MONEY :{LTBLUE}Suurenda raha hulka {CURRENCY_LONG} võrra STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Mängimine ettevõttena: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Võlubuldooser (eemaldab tööstused, paiksed objektid): {ORANGE}{STRING} @@ -2250,11 +2275,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Mäng on endise STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Mäng on endiselt seisatud ({STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Mäng on endiselt seisatud ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Mäng on endiselt peatatud ({STRING}, {STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Mäng on endiselt seisatud ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Mäng jätkub ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :pole piisavalt mängijaid STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :klientide ühendamine STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manuaalne STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :mängu skript +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :transpordisõlmede graafiku uuenduse ootel ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :lahkub STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} liitus mänguga @@ -2267,6 +2294,7 @@ STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} uu STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} saatis {2:CURRENCY_LONG} ettevõttele {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server sulges sessiooni STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server restardib...{}Palun oota... +STR_NETWORK_MESSAGE_KICKED :*** {STRING} visati välja. Põhjendus: ({STRING}) # Content downloading window STR_CONTENT_TITLE :{WHITE}Aineste allalaadimine @@ -2359,6 +2387,7 @@ STR_LINKGRAPH_LEGEND_CAPTION :{BLACK}Kaubavoo STR_LINKGRAPH_LEGEND_ALL :{BLACK}Kõik STR_LINKGRAPH_LEGEND_NONE :{BLACK}Mitte ükski STR_LINKGRAPH_LEGEND_SELECT_COMPANIES :{BLACK}Vali näitamiseks ettevõtted +STR_LINKGRAPH_LEGEND_COMPANY_TOOLTIP :{BLACK}{STRING}{}{COMPANY} # Linkgraph legend window and linkgraph legend in smallmap STR_LINKGRAPH_LEGEND_UNUSED :{TINY_FONT}{BLACK}ei kasutata @@ -2382,6 +2411,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Liida te STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Ehita eraldi teemärgis # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Välja lülitatud, sest ükski saadaval sõiduk ei sobi selle infrastruktuuriga # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Rööbasteede ehitamine @@ -2485,8 +2515,11 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}Ehita tu STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}Ehita trammitunnel. Shift valib ehitamise/hinna kuvamise režiimi STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}Lülitu maanteede ehitamise ja lammutamise vahel STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}Lülitu trammitee ehitamise ja lammutamise vahel +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}Muuda/uuenda teeliiki. Shift vaheldab ehitamist/eeldatavat maksumust +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}Vaheta/uuenda trammiliiki. Shift-nupuga vahelduvad ehitamine ja eeldatav hind STR_ROAD_NAME_ROAD :Sõidutee +STR_ROAD_NAME_TRAM :Trammitee # Road depot construction window STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION :{WHITE}Depoo suund @@ -2574,6 +2607,12 @@ STR_TREES_RANDOM_TYPE :{BLACK}Suvalise STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Istutab suvalisi puid. Shift valib ehitamise/hinna kuvamise režiimi STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Suvalised puud STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Istutab puid suvaliselt üle kogu maa-ala +STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Tavaline +STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}Istuta üksikuid puid lohistades selleks üle maastiku. +STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Metsatukk +STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}Istuta väikeseid metsi selleks üle maastiku lohistades +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Mets +STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Istuta suuri metsi selleks üle maastiku lohistades. # Land generation window (SE) STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Maa tekitamine @@ -2650,6 +2689,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Vali tö # Land area window STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Maa-ala andmed +STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}Keskenda vaade ruudu asukohale. Ctrl+klõps avab asukohas uue vaate STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}Tühjendamise hind: {LTBLUE}N/A STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Tühjendamise hind: {RED}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Tühjendamise tulu: {LTBLUE}{CURRENCY_LONG} @@ -2663,16 +2703,19 @@ STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :puudub STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Koordinaadid: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING}) STR_LAND_AREA_INFORMATION_BUILD_DATE :{BLACK}Ehitatud: {LTBLUE}{DATE_LONG} STR_LAND_AREA_INFORMATION_STATION_CLASS :{BLACK}Jaama liik: {LTBLUE}{STRING} -STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Jaama rühm: {LTBLUE}{STRING} +STR_LAND_AREA_INFORMATION_STATION_TYPE :{BLACK}Jaama liik: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_CLASS :{BLACK}Lennujaama liik: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORT_NAME :{BLACK}Lennujaama nimi: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME :{BLACK}Lennujaama osa nimi: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Vastuvõetavad veosed: {LTBLUE} STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING}) +STR_LANG_AREA_INFORMATION_RAIL_TYPE :{BLACK}Rööpa liik: {LTBLUE}{STRING} +STR_LANG_AREA_INFORMATION_ROAD_TYPE :{BLACK}Teeliik: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}Trammi tüüp: {LTBLUE}{STRING} STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Raudtee kiiruspiirang: {LTBLUE}{VELOCITY} STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Lubatud piirkiirus: {LTBLUE}{VELOCITY} +STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}Trammi kiiruspiirang: {LTBLUE}{VELOCITY} # Description of land area of different tiles STR_LAI_CLEAR_DESCRIPTION_ROCKS :Kaljud @@ -2773,26 +2816,61 @@ STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD # Framerate display window STR_FRAMERATE_CAPTION :{WHITE}Kaadrisagedus +STR_FRAMERATE_CAPTION_SMALL :{STRING}{WHITE} ({DECIMAL}x) +STR_FRAMERATE_RATE_GAMELOOP :{BLACK} Simuleerimissagedus: {STRING} STR_FRAMERATE_RATE_GAMELOOP_TOOLTIP :{BLACK}Simuleeritud mänguhetkede arv sekundis. +STR_FRAMERATE_RATE_BLITTER :{BLACK}Graafika kaadrisagedus: {STRING} STR_FRAMERATE_RATE_BLITTER_TOOLTIP :{BLACK}Renderdatud videokaadrite arv sekundis. +STR_FRAMERATE_SPEED_FACTOR :{BLACK}Mängu kiiruskordaja hetkel: {DECIMAL}x +STR_FRAMERATE_SPEED_FACTOR_TOOLTIP :{BLACK}Kui kiiresti mäng jookseb võrreldes eeldatava kiirusega tavapärase simuleerimiskiiruse juures +STR_FRAMERATE_CURRENT :{WHITE}Hetkel STR_FRAMERATE_AVERAGE :{WHITE}Keskmine +STR_FRAMERATE_MEMORYUSE :{WHITE}Mälu +STR_FRAMERATE_DATA_POINTS :{BLACK}Andmed põhinevad {COMMA} mõõtmisel STR_FRAMERATE_MS_GOOD :{LTBLUE}{DECIMAL} ms STR_FRAMERATE_MS_WARN :{YELLOW}{DECIMAL} ms STR_FRAMERATE_MS_BAD :{RED}{DECIMAL} ms STR_FRAMERATE_FPS_GOOD :{LTBLUE}{DECIMAL} kaadrit/s STR_FRAMERATE_FPS_WARN :{YELLOW}{DECIMAL} kaadrit/s STR_FRAMERATE_FPS_BAD :{RED}{DECIMAL} kaadrit/s +STR_FRAMERATE_BYTES_GOOD :{LTBLUE}{BYTES} +STR_FRAMERATE_BYTES_WARN :{YELLOW}{BYTES} +STR_FRAMERATE_BYTES_BAD :{RED}{BYTES} STR_FRAMERATE_GRAPH_MILLISECONDS :{TINY_FONT}{COMMA} ms +STR_FRAMERATE_GRAPH_SECONDS :{TINY_FONT}{COMMA} s ############ Leave those lines in this order!! STR_FRAMERATE_GAMELOOP :{BLACK}Mängutsükli lõppkokkuvõte: +STR_FRAMERATE_GL_ECONOMY :{BLACK} Veoste käsitlemine: +STR_FRAMERATE_GL_TRAINS :{BLACK} Rongide sammud: +STR_FRAMERATE_GL_ROADVEHS :{BLACK} Maanteesõiduki sammud: +STR_FRAMERATE_GL_SHIPS :{BLACK} Laevade sammud: STR_FRAMERATE_GL_AIRCRAFT :{BLACK} Õhusõiduki sammud: +STR_FRAMERATE_GL_LANDSCAPE :{BLACK} Maailma sammud: STR_FRAMERATE_GL_LINKGRAPH :{BLACK} Ahelgraafiku viide: STR_FRAMERATE_DRAWING :{BLACK}Graafika renderdamine: +STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK} Maalmavaated: STR_FRAMERATE_VIDEO :{BLACK}Videoväljund: +STR_FRAMERATE_SOUND :{BLACK}Helide segamine: +STR_FRAMERATE_ALLSCRIPTS :{BLACK} GS/AI kokku: +STR_FRAMERATE_GAMESCRIPT :{BLACK} GameScript: +STR_FRAMERATE_AI :{BLACK} AI {NUM} {STRING} ############ End of leave-in-this-order ############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GAMELOOP :Mängutsükkel +STR_FRAMETIME_CAPTION_GL_ECONOMY :Veoste käsitlemine +STR_FRAMETIME_CAPTION_GL_TRAINS :Rongi sammud +STR_FRAMETIME_CAPTION_GL_ROADVEHS :Maanteesõidukite sammud +STR_FRAMETIME_CAPTION_GL_SHIPS :Laeva sammud STR_FRAMETIME_CAPTION_GL_AIRCRAFT :Õhusõiduki sammud +STR_FRAMETIME_CAPTION_GL_LANDSCAPE :Maailma sammud +STR_FRAMETIME_CAPTION_GL_LINKGRAPH :Transpordisõlmede graafiku viivitus STR_FRAMETIME_CAPTION_DRAWING :Graafika renderdamine +STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Maailmavaate renderdamine +STR_FRAMETIME_CAPTION_VIDEO :Videoväljund +STR_FRAMETIME_CAPTION_SOUND :Helide segamine +STR_FRAMETIME_CAPTION_ALLSCRIPTS :GS/AI skriptide üldarv +STR_FRAMETIME_CAPTION_GAMESCRIPT :GameScript +STR_FRAMETIME_CAPTION_AI :AI {NUM} {STRING} ############ End of leave-in-this-order @@ -2819,6 +2897,8 @@ STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}Andmed p STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} STR_SAVELOAD_FILTER_TITLE :{BLACK}Märksõna: +STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Ülekirjuta fail +STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Kas oled kindel, et soovid olemasoleva faili üle kirjutada? STR_SAVELOAD_OSKTITLE :{BLACK}Sisesta salvestatavale mängule nimi @@ -2937,7 +3017,11 @@ STR_NEWGRF_SETTINGS_MIN_VERSION :{BLACK}Min. üh STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING} STR_NEWGRF_SETTINGS_PALETTE :{BLACK}Palett: {SILVER}{STRING} STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :Vaikimisi (D) +STR_NEWGRF_SETTINGS_PALETTE_DEFAULT_32BPP :Vaikimisi (D) / 32 bpp +STR_NEWGRF_SETTINGS_PALETTE_LEGACY :Pärand (W) +STR_NEWGRF_SETTINGS_PALETTE_LEGACY_32BPP :Pärand (W) / 32 bpp STR_NEWGRF_SETTINGS_PARAMETER :{BLACK}Parameetrid: {SILVER}{STRING} +STR_NEWGRF_SETTINGS_PARAMETER_NONE :Puudub STR_NEWGRF_SETTINGS_NO_INFO :{BLACK}Andmed puuduvad STR_NEWGRF_SETTINGS_NOT_FOUND :{RED}Sobivat faili ei leitud @@ -3018,6 +3102,8 @@ STR_NEWGRF_ERROR_READ_BOUNDS :Loe pseudo-spri STR_NEWGRF_ERROR_GRM_FAILED :Soovitud GRFi ressursid ei ole saadaval (sprite {3:NUM}) STR_NEWGRF_ERROR_FORCEFULLY_DISABLED :{1:STRING} blokeeriti {STRING} poolt STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT :«Sprite» paigutus kõlbmatus vormis («sprite» {3:NUM}) +STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG :Liiga palju elemente omaduse väärtuse loendis (sprite {3:NUM}, omadus {4:HEX}) +STR_NEWGRF_ERROR_INDPROD_CALLBACK :Vigane tööstustoodangu callback (sprite {3:NUM}, "{2:STRING}") # NewGRF related 'general' warnings STR_NEWGRF_POPUP_CAUTION_CAPTION :{WHITE}Ettevaatust! @@ -3049,6 +3135,7 @@ STR_NEWGRF_BUGGY :{WHITE}NewGRF ' STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Veose/ümberseadistamise teave sõidukil '{1:ENGINE}' erineb ehitamisaegsest ostunimekirjast. Seetõttu võib uuendamisel või asendamisel ümberseadistamine ebaõnnestuda STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' põhjustas toodangu tagasikutsumises lõpmatu korduse STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT :{WHITE}Tagasikutse «{1:HEX}» tulemus «{2:HEX}» on kõlbmatu +STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' vastas vigase veoseliigiga toodangu callback'is asukohas {2:HEX} # 'User removed essential NewGRFs'-placeholders for stuff without specs STR_NEWGRF_INVALID_CARGO : @@ -3073,6 +3160,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Lülita # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}Sildi muutmine +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Keskenda põhivaade sildi asukohale. Ctrl+klõps avab sildi asukohas uue vaate STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Mine järgmise märgi juurde STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Mine eelmise märgi juurde @@ -3090,13 +3178,13 @@ STR_TOWN_POPULATION :{BLACK}Maailma STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Linn) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Rahvaarv: {ORANGE}{COMMA}{BLACK} Ehitisi: {ORANGE}{COMMA} -STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} eelmisel kuul: {ORANGE}{COMMA}{BLACK} Suurim: {ORANGE}{COMMA} +STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} eelmisel kuul: {ORANGE}{COMMA}{BLACK} Kuni: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Veoseid linna kasvamiseks: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} vajalik STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} on talvel vajalik -STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL :{ORANGE}{STRING}{GREEN} kohale toimetatud +STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL :{ORANGE}{STRING}{GREEN} äraveetud STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{RED} (ikka veel vaja) -STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{GREEN} (kohale toimetatud) +STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{GREEN} (äraveetud) STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}Linn kasvab {ORANGE}{COMMA}{BLACK} päevaga STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Linn kasvab iga {ORANGE}{COMMA}{BLACK} päeva tagant (rahastatud) STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Linn {RED}ei{BLACK} kasva @@ -3104,17 +3192,18 @@ STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Mürapii STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Vaate viimine linnale STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Omavalitsus STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Näita teavet kohaliku omavalitsuse kohta -STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Linna nime muutmine +STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Muuda linna nime STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Laienda STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Linna suuruse suurendamine STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Kustuta STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Hävita see linn täielikult -STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Linna nime vahetamine +STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Ümbernimeta linn # Town local authority window STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} kohalik omavalitsus +STR_LOCAL_AUTHORITY_ZONE :{BLACK}Ala STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Näita kohaliku omavalitsuse haldusala STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Ettevõtete hinnangud: STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING} @@ -3144,6 +3233,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW} Linna # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} eesmärgid STR_GOALS_SPECTATOR_CAPTION :{WHITE}Üldeesmärgid +STR_GOALS_SPECTATOR :Üleilmsed eesmärgid STR_GOALS_GLOBAL_TITLE :{BLACK}Üldised eesmärgid: STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_NONE :{ORANGE}- Mitte ühtegi - @@ -3154,10 +3244,10 @@ STR_GOALS_COMPANY_TITLE :{BLACK}Ettevõt STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klõpsa eesmärgil, et liigutada vaateaken tööstuse/linna/ruudu asukohale. Ctrl+klõps avab uue vaateakna tööstuse/linna/ruudu asukohas # Goal question window -STR_GOAL_QUESTION_CAPTION_QUESTION :Küsimus -STR_GOAL_QUESTION_CAPTION_INFORMATION :Teave -STR_GOAL_QUESTION_CAPTION_WARNING :Hoiatus -STR_GOAL_QUESTION_CAPTION_ERROR :Viga +STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}Küsimus +STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}Teave +STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}Hoiatus +STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}Viga ############ Start of Goal Question button list STR_GOAL_QUESTION_BUTTON_CANCEL :Tühista @@ -3192,6 +3282,7 @@ STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Vajuta p # Story book window STR_STORY_BOOK_CAPTION :{WHITE}«{COMPANY}» juturaamat STR_STORY_BOOK_SPECTATOR_CAPTION :{WHITE}Üldjuturaamat +STR_STORY_BOOK_SPECTATOR :Üleilmne juturaamat STR_STORY_BOOK_TITLE :{YELLOW}{STRING} STR_STORY_BOOK_GENERIC_PAGE_ITEM :Lehekülg {NUM} STR_STORY_BOOK_SEL_PAGE_TOOLTIP :{BLACK}Vali lehekülg rippmenüüst. @@ -3230,7 +3321,7 @@ STR_STATION_VIEW_RATINGS_TOOLTIP :{BLACK}Näita j STR_STATION_VIEW_SUPPLY_RATINGS_TITLE :{BLACK}Tarne kuus ja kohalik hinnang: STR_STATION_VIEW_CARGO_SUPPLY_RATING :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%) -STR_STATION_VIEW_GROUP :{BLACK}Rühmitusalus +STR_STATION_VIEW_GROUP :{BLACK}Jaotusalus STR_STATION_VIEW_WAITING_STATION :Jaam: ootel STR_STATION_VIEW_WAITING_AMOUNT :Summa: ootel STR_STATION_VIEW_PLANNED_STATION :Jaam: eeldatav @@ -3246,12 +3337,12 @@ STR_STATION_VIEW_VIA_HERE :{GREEN}{CARGO_S STR_STATION_VIEW_TO_HERE :{GREEN}{CARGO_SHORT} siia jaama STR_STATION_VIEW_NONSTOP :{YELLOW}{CARGO_SHORT} ilma peatumata -STR_STATION_VIEW_GROUP_S_V_D :Lähe-Läbi-Siht -STR_STATION_VIEW_GROUP_S_D_V :Lähe-Siht-Läbi -STR_STATION_VIEW_GROUP_V_S_D :Läbi-Lähe-Siht -STR_STATION_VIEW_GROUP_V_D_S :Läbi-Siht-Lähe -STR_STATION_VIEW_GROUP_D_S_V :Siht-Lähe-Läbi -STR_STATION_VIEW_GROUP_D_V_S :Siht-Läbi-Lähe +STR_STATION_VIEW_GROUP_S_V_D :Algus-, vahe- ja sihtpunkt +STR_STATION_VIEW_GROUP_S_D_V :Algus-, siht- ja vahepunkt +STR_STATION_VIEW_GROUP_V_S_D :Vahe-, algus- ja sihtpunkt +STR_STATION_VIEW_GROUP_V_D_S :Vahe-, siht- ja alguspunkt +STR_STATION_VIEW_GROUP_D_S_V :Siht-, algus- ja vahepunkt +STR_STATION_VIEW_GROUP_D_V_S :Siht-, vahe- ja alguspunkt ############ range for rating starts STR_CARGO_RATING_APPALLING :Kohutav @@ -3272,7 +3363,7 @@ STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP :{BLACK}Näita k STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP :{BLACK}Näita kõiki lennukeid, mille sõidugraafik sisaldab seda lennujaama STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP :{BLACK}Näita kõiki laevu, mille sõidugraafik sisaldab seda sadamat -STR_STATION_VIEW_RENAME_STATION_CAPTION :Jaama nime vahetamine +STR_STATION_VIEW_RENAME_STATION_CAPTION :Ümbernimeta jaam/laadimisala STR_STATION_VIEW_CLOSE_AIRPORT :{BLACK}Sulge lennujaam STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Keela lennukite maandumine selles lennujaamas @@ -3308,11 +3399,11 @@ STR_FINANCES_POSITIVE_INCOME :{BLACK}+{CURREN STR_FINANCES_TOTAL_CAPTION :{WHITE}Kokku: STR_FINANCES_BANK_BALANCE_TITLE :{WHITE}Kontojääk STR_FINANCES_LOAN_TITLE :{WHITE}Laen -STR_FINANCES_MAX_LOAN :{WHITE}Laenupiir: {BLACK}{CURRENCY_LONG} +STR_FINANCES_MAX_LOAN :{WHITE}Laenulimiit: {BLACK}{CURRENCY_LONG} STR_FINANCES_TOTAL_CURRENCY :{BLACK}{CURRENCY_LONG} STR_FINANCES_BORROW_BUTTON :{BLACK}Laena {CURRENCY_LONG} STR_FINANCES_BORROW_TOOLTIP :{BLACK}Laena raha -STR_FINANCES_REPAY_BUTTON :{BLACK}Tagasta {CURRENCY_LONG} +STR_FINANCES_REPAY_BUTTON :{BLACK}Tagasimakse {CURRENCY_LONG} STR_FINANCES_REPAY_TOOLTIP :{BLACK}Maksa laen osaliselt tagasi STR_FINANCES_INFRASTRUCTURE_BUTTON :{BLACK}Taristu @@ -3346,6 +3437,8 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Liiguta STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Ehita ettevõtte peakorter mujale 1% firmaväärtuse tasu eest. Shift+klõps näitab toimingu eeldatavat maksumust STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Täpsustused STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Vaata täpset taristu hulka +STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Saada raha +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Saada sellele ettevõttele raha STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}Uus nägu STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Vali presidendile uus nägu @@ -3363,6 +3456,7 @@ STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}Müü 25 STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :Ettevõtte nimi STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :Presidendi nimi +STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION :Sisesta saadetav rahasumma STR_BUY_COMPANY_MESSAGE :{WHITE}Otsime ettevõtet, kes võtaks meie firma üle.{}{}Kas soovite osta ettevõtte {COMPANY} {CURRENCY_LONG} eest? @@ -3371,6 +3465,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE} {COMPAN STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}Raudtee tükid: STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}Signaalid STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}Tee tükid: +STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}Trammiosad: STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}Veekogu ruudud: STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}Kanalid STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}Jaamad: @@ -3381,8 +3476,17 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC # Industry directory STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Tööstused STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- Puudub - +STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} ({COMMA}% äraveetud){BLACK} STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY} +STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE}{INDUSTRY} {STRING}, {STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PROD3 :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} +STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} ja veel {NUM}... STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Tööstuste nimed - klõpsates keskendatakse vaade tööstusele. Ctrl+klõps avab uue vaate ettevõtte asukohast +STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Vastuvõetud veosed: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Toodetud veosed: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :Kõik veoseliigid +STR_INDUSTRY_DIRECTORY_FILTER_NONE :Puudub # Industry view STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY} @@ -3393,9 +3497,12 @@ STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Tootlikk STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}Tööstus teatab kohesest sulgemisest! STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}Vajab: {YELLOW}{STRING}{STRING} +STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}Toodab: {YELLOW}{STRING}{STRING} STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRING} STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Nõuab: +STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} +STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} ootel{STRING} STR_CONFIG_GAME_PRODUCTION :{WHITE}Tootlikuse muutmine (kaheksaga jaguv, kuni 2040) STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Muuda tootlikkuse taset (protsent, kuni 800%) @@ -3440,17 +3547,19 @@ STR_GROUP_ALL_ROAD_VEHICLES :Kõik mootorsõ STR_GROUP_ALL_SHIPS :Kõik laevad STR_GROUP_ALL_AIRCRAFTS :Kõik lennukid -STR_GROUP_DEFAULT_TRAINS :Rühmitamata rongid -STR_GROUP_DEFAULT_ROAD_VEHICLES :Rühmitamata sõidukid -STR_GROUP_DEFAULT_SHIPS :Rühmitamata laevad -STR_GROUP_DEFAULT_AIRCRAFTS :Rühmitamata õhusõidukid +STR_GROUP_DEFAULT_TRAINS :Jaotamata rongid +STR_GROUP_DEFAULT_ROAD_VEHICLES :Jaotamata maanteesõidukid +STR_GROUP_DEFAULT_SHIPS :Jaotamata laevad +STR_GROUP_DEFAULT_AIRCRAFTS :Jaotamata õhusõidukid +STR_GROUP_COUNT_WITH_SUBGROUP :{TINY_FONT}{COMMA} (+{COMMA}) -STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Rühm - Klõpsa rühmal, et kõiki seal olevaid sõidukeid järjestada -STR_GROUP_CREATE_TOOLTIP :{BLACK}Klõpsa rühma loomiseks -STR_GROUP_DELETE_TOOLTIP :{BLACK}Eemalda valitud rühm -STR_GROUP_RENAME_TOOLTIP :{BLACK}Valitud rühma nime vahetamine -STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klõpsa, et seda rühma üldise automaatse asenduse eest kaitsta +STR_GROUPS_CLICK_ON_GROUP_FOR_TOOLTIP :{BLACK}Jagu - jaol klõpsates loetletakse kõik jakku kuuluvad sõidukit. Jagusid lohistades saab luua hierarhia. +STR_GROUP_CREATE_TOOLTIP :{BLACK}Klõpsa jao loomiseks +STR_GROUP_DELETE_TOOLTIP :{BLACK}Eemalda valitud jagu +STR_GROUP_RENAME_TOOLTIP :{BLACK}Ümbernimeta valitud jagu +STR_GROUP_LIVERY_TOOLTIP :{BLACK}Muuda valitud jao värvistikku +STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Klõpsa, et kaitsta seda jagu globaalse automaatasenduse eest STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Kustuta Grupp STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Kas oled kindel, et tahad kustutada selle grupi ja kõik järglased? @@ -3458,11 +3567,11 @@ STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Kas oled STR_GROUP_ADD_SHARED_VEHICLE :Kõik jagatud sõidukid STR_GROUP_REMOVE_ALL_VEHICLES :Eemalda kõik sõidukid -STR_GROUP_RENAME_CAPTION :{BLACK}Rühma nime vahetamine +STR_GROUP_RENAME_CAPTION :{BLACK}Ümbernimeta jagu STR_GROUP_PROFIT_THIS_YEAR :Selle aasta kasum: STR_GROUP_PROFIT_LAST_YEAR :Eelmise aasta kasum: -STR_GROUP_OCCUPANCY :Kasutuses: +STR_GROUP_OCCUPANCY :Koormatus: STR_GROUP_OCCUPANCY_VALUE :{NUM}% # Build vehicle window @@ -3472,14 +3581,17 @@ STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :Uus monorelsss STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :Uus magnethõljuksõiduk STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :Uued mootorsõidukid +STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :Uued trammid ############ range for vehicle availability starts STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :Rööbassõidukid +STR_BUY_VEHICLE_ROAD_VEHICLE_ALL_CAPTION :Uued maanteesõidukid STR_BUY_VEHICLE_SHIP_CAPTION :Uued laevad STR_BUY_VEHICLE_AIRCRAFT_CAPTION :Uus lennuk ############ range for vehicle availability ends STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}Hind: {GOLD}{CURRENCY_LONG}{BLACK} Tühimass: {GOLD}{WEIGHT_SHORT} +STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}Maksumus: {GOLD}{CURRENCY_LONG}{BLACK} (Ümberseadistamise maksumus: {GOLD}{CURRENCY_LONG}{BLACK}) Mass: {GOLD}{WEIGHT_SHORT} STR_PURCHASE_INFO_SPEED_POWER :{BLACK}Tippkiirus: {GOLD}{VELOCITY}{BLACK} Võimsus: {GOLD}{POWER} STR_PURCHASE_INFO_SPEED :{BLACK}Tippkiirus: {GOLD}{VELOCITY} STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}Kiirus ookeanil: {GOLD}{VELOCITY} @@ -3490,6 +3602,7 @@ STR_PURCHASE_INFO_REFITTABLE :(ümberseadista STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Kujundatud: {GOLD}{NUM}{BLACK} Vanus: {GOLD}{COMMA} aasta{P "" t} STR_PURCHASE_INFO_RELIABILITY :{BLACK}Parim tehnoseisund: {GOLD}{COMMA}% STR_PURCHASE_INFO_COST :{BLACK}Hind: {GOLD}{CURRENCY_LONG} +STR_PURCHASE_INFO_COST_REFIT :{BLACK}Maksumus: {GOLD}{CURRENCY_LONG}{BLACK} (Ümberseadistamise maksumus: {GOLD}{CURRENCY_LONG}{BLACK}) STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Mass: {GOLD}{WEIGHT_SHORT} {WEIGHT_SHORT}) STR_PURCHASE_INFO_COST_SPEED :{BLACK}Hind: {GOLD}{CURRENCY_LONG}{BLACK} Tippkiirus: {GOLD}{VELOCITY} STR_PURCHASE_INFO_COST_REFIT_SPEED :{BLACK}Hind: {GOLD}{CURRENCY_LONG}{BLACK} (Ümberseadistamise maksumus: {GOLD}{CURRENCY_LONG}{BLACK}) Kiirus: {GOLD}{VELOCITY} @@ -3497,9 +3610,11 @@ STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Kandevõ STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Kiirendavad vagunid: {GOLD}+{POWER}{BLACK} Mass: {GOLD}+{WEIGHT_SHORT} STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Ümberseadistatav: {GOLD}{STRING} STR_PURCHASE_INFO_ALL_TYPES :Kõik kaubatüübid +STR_PURCHASE_INFO_NONE :Puudub STR_PURCHASE_INFO_ALL_BUT :Kõik, välja arvatud {CARGO_LIST} STR_PURCHASE_INFO_MAX_TE :{BLACK}Suurim veojõud: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Tegevusradius: {GOLD}{COMMA} ruutu +STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Õhusõiduki liik: {GOLD}{STRING} STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Nimekiri raudteesõidukitest - andmete saamiseks klõpsa raudteesõidukile STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Mootorsõidukite nimekiri - andmete saamiseks klõpsa sõidukile @@ -3511,23 +3626,30 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}Ehita ve STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}Ehita laev STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}Ehita lennuk -STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Osta ja seadista lennuk ümber +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Osta ja ümberseadista sõiduk +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Osta ja ümberseadista sõiduk +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Osta ja ümberseadista laev +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Osta ja ümberseadista lennuk STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Osta valitud raudteesõiduk. Shift+klõpsuga kuvatakse eeldatav ostuhind STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Osta valitud mootorsõiduk. Shift+klõpsuga kuvatakse eeldatav ostuhind STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Osta valitud laev. Shift+klõpsuga kuvatakse eeldatav ostuhind STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}Osta valitud õhusõiduk. Shift+klõpsuga kuvatakse eeldatav ostuhind +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Osta ja ümberseadista valitud rööbassõiduk. Shift+klõps näitab eeldatava maksumuse ilma ostu sooritamata +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Osta ja ümberseadista valitud maanteesõiduk. Shift+klõps näitab eeldatava maksumuse ilma ostu sooritamata +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Osta ja ümberseadista valitud laev. Shift+klõps näitab eeldatava maksumuse ilma ostu sooritamata +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Osta ja ümberseadista valitud lennuk. Shift+klõps näitab eeldatava maksumuse ilma ostu sooritamata -STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Nimevahetus -STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}Nimevahetus -STR_BUY_VEHICLE_SHIP_RENAME_BUTTON :{BLACK}Nimevahetus -STR_BUY_VEHICLE_AIRCRAFT_RENAME_BUTTON :{BLACK}Nimevahetus +STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Ümbernimeta +STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}Ümbernimeta +STR_BUY_VEHICLE_SHIP_RENAME_BUTTON :{BLACK}Ümbernimeta +STR_BUY_VEHICLE_AIRCRAFT_RENAME_BUTTON :{BLACK}Ümbernimeta -STR_BUY_VEHICLE_TRAIN_RENAME_TOOLTIP :{BLACK}Muuda raudteesõiduki tüübinime -STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_TOOLTIP :{BLACK}Muuda mootorsõiduki tüübinime -STR_BUY_VEHICLE_SHIP_RENAME_TOOLTIP :{BLACK}Laeva tüübinime muutmine -STR_BUY_VEHICLE_AIRCRAFT_RENAME_TOOLTIP :{BLACK}Lennuki tüübinime muutmine +STR_BUY_VEHICLE_TRAIN_RENAME_TOOLTIP :{BLACK}Ümbernimeta rööbassõiduki liik +STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_TOOLTIP :{BLACK}Ümbernimeta maanteesõiduki liik +STR_BUY_VEHICLE_SHIP_RENAME_TOOLTIP :{BLACK}Ümbernimeta laeva liik +STR_BUY_VEHICLE_AIRCRAFT_RENAME_TOOLTIP :{BLACK}Ümbernimeta õhusõiduki liik STR_BUY_VEHICLE_TRAIN_HIDE_TOGGLE_BUTTON :{BLACK}Peida STR_BUY_VEHICLE_ROAD_VEHICLE_HIDE_TOGGLE_BUTTON :{BLACK}Peida @@ -3544,16 +3666,16 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}Sätesta STR_BUY_VEHICLE_SHIP_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}Sätesta laevatüübi peitmine/kuvamine STR_BUY_VEHICLE_AIRCRAFT_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}Sätesta lennukitüübi peitmine/kuvamine -STR_QUERY_RENAME_TRAIN_TYPE_CAPTION :{WHITE}Vaheta rongivaguni tüübinime -STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}Vaheta mootorsõiduki tüübinime -STR_QUERY_RENAME_SHIP_TYPE_CAPTION :{WHITE}Laeva tüübinime vahetamine -STR_QUERY_RENAME_AIRCRAFT_TYPE_CAPTION :{WHITE}Lennuki tüübinime vahetamine +STR_QUERY_RENAME_TRAIN_TYPE_CAPTION :{WHITE}Ümbernimeta rööbassõiduki liik +STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}Ümbernimeta maanteesõiduki liik +STR_QUERY_RENAME_SHIP_TYPE_CAPTION :{WHITE}Ümbernimeta laeva liik +STR_QUERY_RENAME_AIRCRAFT_TYPE_CAPTION :{WHITE}Ümbernimeta õhusõiduki liik # Depot window STR_DEPOT_CAPTION :{WHITE}{DEPOT} STR_DEPOT_RENAME_TOOLTIP :{BLACK}Muuda depoo nime -STR_DEPOT_RENAME_DEPOT_CAPTION :Muuda depoo nime +STR_DEPOT_RENAME_DEPOT_CAPTION :Ümbernimeta depoo STR_DEPOT_NO_ENGINE :{BLACK}- STR_DEPOT_VEHICLE_TOOLTIP :{BLACK}{ENGINE}{STRING} @@ -3626,30 +3748,33 @@ STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}Sa oled # Engine preview window STR_ENGINE_PREVIEW_CAPTION :{WHITE}Teade veovahendite tootjalt -STR_ENGINE_PREVIEW_MESSAGE :{GOLD}Me töötasime välja uue {STRING}. Kas te oleksite huvitatud selle ainuõiguslikust katsetamisest järgneva aasta jooksul, et me saaksime jälgida kuidas see toimib? +STR_ENGINE_PREVIEW_MESSAGE :{GOLD}Me töötasime välja uue {STRING}. Kas te oleksite huvitatud selle ainuõiguslikust katsetamisest ühe aasta jooksul, et me saaksime seda enne turule laskmist jälgida? -STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :raudteevedur -STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :monorelssvedur -STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :magnethõljukvedur +STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :raudteeveduri +STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE :elektrirongivedur +STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :monorelssveduri +STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :magnethõljukveduri -STR_ENGINE_PREVIEW_ROAD_VEHICLE :mootorsõiduk +STR_ENGINE_PREVIEW_ROAD_VEHICLE :mootorsõiduki +STR_ENGINE_PREVIEW_TRAM_VEHICLE :tramm -STR_ENGINE_PREVIEW_AIRCRAFT :lennuk -STR_ENGINE_PREVIEW_SHIP :laev +STR_ENGINE_PREVIEW_AIRCRAFT :lennuki +STR_ENGINE_PREVIEW_SHIP :laeva STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Hind: {CURRENCY_LONG} Tühimass: {WEIGHT_SHORT}{}Tippkiirus: {VELOCITY} Võimsus: {POWER}{}Käituskulud: {CURRENCY_LONG}/aastas{}Kandevõime: {CARGO_LONG} STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Hind: {CURRENCY_LONG} Tühimass: {WEIGHT_SHORT}{}Kiirus: {VELOCITY} Võimsus: {POWER} Veojõud: {6:FORCE}{}Käituskulud: {4:CURRENCY_LONG}/aasta{}Mahutavus: {5:CARGO_LONG} STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Hind: {CURRENCY_LONG} Tippkiirus: {VELOCITY}{}Kandevõime: {CARGO_LONG}{}Käituskulud: {CURRENCY_LONG}/a +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Maksumus: {CURRENCY_LONG} Tippkiirus: {VELOCITY}{}Õhusõiduki liik: {STRING}{}Mahutavus: {CARGO_LONG}, {CARGO_LONG}{}Käituskulud: {CURRENCY_LONG}/aasta STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Hind: {CURRENCY_LONG} Tippkiirus: {VELOCITY}{}Lennuki tüüp: {STRING}{}kandevõime: {CARGO_LONG}{}Käitluskulud: {CURRENCY_LONG}/a STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Hind: {CURRENCY_LONG} Tippkiirus: {VELOCITY}{}Lennuki tüüp: {STRING} Lennukaugus: {COMMA} ruutu{}Kandevõime: {CARGO_LONG}, {CARGO_LONG}{}Käituskulud: {CURRENCY_LONG}/a STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Hind: {CURRENCY_LONG} Tippkiirus: {VELOCITY}{}Lennuki tüüp: {STRING} Lennukaugus: {COMMA} ruutu{}Kandevõime: {CARGO_LONG}{}Käituskulud: {CURRENCY_LONG}/a # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Asenda {STRING} - {STRING} -STR_REPLACE_VEHICLE_TRAIN :Rong -STR_REPLACE_VEHICLE_ROAD_VEHICLE :Sõiduk -STR_REPLACE_VEHICLE_SHIP :Laev -STR_REPLACE_VEHICLE_AIRCRAFT :Õhusõiduk +STR_REPLACE_VEHICLE_TRAIN :ronge +STR_REPLACE_VEHICLE_ROAD_VEHICLE :maanteesõidukeid +STR_REPLACE_VEHICLE_SHIP :laevu +STR_REPLACE_VEHICLE_AIRCRAFT :õhusõidukeid STR_REPLACE_VEHICLE_VEHICLES_IN_USE :{YELLOW}Kasutuses sõidukid STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP :{BLACK}Tulp sõidukitega, mida omad @@ -3659,21 +3784,24 @@ STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP :{BLACK}Tulp sõ STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}Vali asendatav veduritüüp STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}Vali uus vedur, millega sa soovid vasakult valitud vedurit asendada. -STR_REPLACE_VEHICLES_START :{BLACK}Alusta sõidukite vahetamist +STR_REPLACE_VEHICLES_START :{BLACK}Alusta sõidukite asendamist STR_REPLACE_VEHICLES_NOW :Asenda kohe kõik sõidukid STR_REPLACE_VEHICLES_WHEN_OLD :Asenda ainult vanu sõidukeid STR_REPLACE_HELP_START_BUTTON :{BLACK}Vajuta vasakul asuva veduri asendamiseks paremal valitud veduriga STR_REPLACE_NOT_REPLACING :{BLACK}Ei asenda praegu -STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED :{BLACK}Ühtegi veovahendit pole valitud +STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED :{BLACK}Ühtegi sõidukit pole valitud STR_REPLACE_REPLACING_WHEN_OLD :{ENGINE} kui vana -STR_REPLACE_VEHICLES_STOP :{BLACK}Lõpeta Sõidukite Asendamine +STR_REPLACE_VEHICLES_STOP :{BLACK}Lõpeta sõidukite asendamine STR_REPLACE_HELP_STOP_BUTTON :{BLACK}Vajuta lõpetamaks vasakult valitud veduri asendust STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK}Vaheta aken mootori ja vaguni asendamise aknate vahel STR_REPLACE_ENGINES :Vedurid -STR_REPLACE_WAGONS :Vaguneid +STR_REPLACE_WAGONS :Vagunid +STR_REPLACE_ALL_RAILTYPE :Kõik rööbassõidukid +STR_REPLACE_ALL_ROADTYPE :Kõik maanteesõidukid STR_REPLACE_HELP_RAILTYPE :{BLACK}Vali rööbasteetüüp mille vedureid sa soovid asendada +STR_REPLACE_HELP_ROADTYPE :{BLACK}Vali teeliik, mille vedureid vahetada STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Näitab mis veduriga soovitakse vasakult valitud vedurit asendada, kui üldse STR_REPLACE_RAIL_VEHICLES :Raudteesõidukid STR_REPLACE_ELRAIL_VEHICLES :Elektrirongid @@ -3681,13 +3809,18 @@ STR_REPLACE_MONORAIL_VEHICLES :Monorelssveerem STR_REPLACE_MAGLEV_VEHICLES :Magnethõljukveerem STR_REPLACE_ROAD_VEHICLES :Maanteesõidukid +STR_REPLACE_TRAM_VEHICLES :Trammid -STR_REPLACE_REMOVE_WAGON :{BLACK}Vagunite eemaldus: {ORANGE}{STRING} -STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Sunni automaatset asendust hoidma rongi pikkust selleks (eest alustades) veeremit eemaldades, juhul kui uus vagun muudaks rongi pikemaks. +STR_REPLACE_REMOVE_WAGON :{BLACK}Vagunite kõrvaldamine: {ORANGE}{STRING} +STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Automaatne asendamine hoiab rongi pikkuse samana, vajadusel kõrvaldab vaguneid (alates esiotsast), kui muidu rongikoosseis suureneks # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Keskenda vaade rongi asukohale. Tõpeltklõpsuga jälitatakse rongi põhivaates. Ctrl+klõps avab rongi asukohas uue vaate +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Keskenda põhivaade sõiduki asukohale. Topeltklõpsuga jälitatakse sõidukit põhivaates. Ctrl+klõps avab sõiduki asukohas uue vaate +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Keskenda põhivaade laeva asukohale. Topeltklõpsuga jälitatakse laeva põhivaates. Ctrl+klõps avab laeva asukohas uue vaate +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Keskenda vaade õhusõiduki asukohale.Topeltklõps jälitab õhusõidukit põhivaates. Ctrl+klõps avab õhusõiduki asukohas uue vaate. STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Saada rong depoosse STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Saada sõiduk garaaži. Ctrl+klõps, et ainult teenindada @@ -3701,10 +3834,10 @@ STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Ostab sa STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}Sunni rongi signaale eirama -STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP :{BLACK}Rongi seadistamine mõne teise laadungi vedamiseks -STR_VEHICLE_VIEW_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}Seadista mootorsõidukit kandmaks teist tüüpi veost -STR_VEHICLE_VIEW_SHIP_REFIT_TOOLTIP :{BLACK}Seadista kaubalaev teisele veosele -STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Seadista lennuk teistsuguse kauba kandmiseks ümber +STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP :{BLACK}Ümberseadista rong muu veoseliigi jaoks +STR_VEHICLE_VIEW_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}Ümberseadista maanteesõiduk muu veoseliigi jaoks +STR_VEHICLE_VIEW_SHIP_REFIT_TOOLTIP :{BLACK}Ümberseadista laev muu veoseliigi jaoks +STR_VEHICLE_VIEW_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Ümberseadista õhusõiduk muu veoseliigi jaoks STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP :{BLACK}Pööra rong ümber STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP :{BLACK}Sunni veovahendit ümber pöörama @@ -3719,7 +3852,12 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Näita m STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Näita laeva täpsustusi STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Näita lennuki täpsustusi +STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Valitud rongi tegevus - klõpsa rongi käivitamiseks/peatamiseks +STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Valitud sõiduki tegevus - klõpsa sõiduki käivatamiseks/peatamiseks +STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Valitud laeva tegevus - klõpsa laeva käivitamiseks/peatamiseks +STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Valitud lennuki tegevus - klõpsa lennuki käivitamiseks/peatamiseks +STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Keskenda põhivaade korralduse sihtpunktile. Ctrl+klõps avab korralduse sihtpunktis uue vaate # Messages in the start stop button in the vehicle view STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Veose ümberlaadimine @@ -3748,10 +3886,10 @@ STR_VEHICLE_COMMAND_STARTED :{GREEN}Started STR_VEHICLE_DETAILS_CAPTION :{WHITE}{VEHICLE} (täpsustused) STR_VEHICLE_NAME_BUTTON :{BLACK}Nimi -STR_VEHICLE_DETAILS_TRAIN_RENAME :{BLACK}Rongi nimi -STR_VEHICLE_DETAILS_ROAD_VEHICLE_RENAME :{BLACK}Nimeta mootorsõidukit -STR_VEHICLE_DETAILS_SHIP_RENAME :{BLACK}Anna laevale nimi -STR_VEHICLE_DETAILS_AIRCRAFT_RENAME :{BLACK}Nimeta lennuk ümber +STR_VEHICLE_DETAILS_TRAIN_RENAME :{BLACK}Nimeta rong +STR_VEHICLE_DETAILS_ROAD_VEHICLE_RENAME :{BLACK}Nimeta maanteesõiduk +STR_VEHICLE_DETAILS_SHIP_RENAME :{BLACK}Nimeta laev +STR_VEHICLE_DETAILS_AIRCRAFT_RENAME :{BLACK}Nimeta õhusõiduk STR_VEHICLE_INFO_AGE_RUNNING_COST_YR :{BLACK}Vanus: {LTBLUE}{STRING}{BLACK} Käituskulud: {LTBLUE}{CURRENCY_LONG}/a # The next two need to stay in this order @@ -3760,6 +3898,7 @@ STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} aa STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Tippkiirus: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}Tippkiirus: {LTBLUE}{VELOCITY} {BLACK}Lennuki tüüp: {LTBLUE}{STRING} +STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}Tippkiirus: {LTBLUE}{VELOCITY} {BLACK}Õhusõiduki liik: {LTBLUE}{STRING} {BLACK}Lennuulatus: {LTBLUE}{COMMA} ruutu STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Tühimass: {LTBLUE}{WEIGHT_SHORT} {BLACK}Võimsus: {LTBLUE}{POWER}{BLACK} Tippkiirus: {LTBLUE}{VELOCITY} STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Tühimass: {LTBLUE}{WEIGHT_SHORT} {BLACK}Võimsus: {LTBLUE}{POWER}{BLACK} Tippkiirus: {LTBLUE}{VELOCITY} {BLACK}Veojõud: {LTBLUE}{FORCE} @@ -3784,10 +3923,10 @@ STR_VEHICLE_DETAILS_DEFAULT :Esialgne STR_VEHICLE_DETAILS_DAYS :Päevad STR_VEHICLE_DETAILS_PERCENT :Protsendid -STR_QUERY_RENAME_TRAIN_CAPTION :{WHITE}Anna rongile nimi -STR_QUERY_RENAME_ROAD_VEHICLE_CAPTION :{WHITE}Nimeta mootorsõiduk ümber -STR_QUERY_RENAME_SHIP_CAPTION :{WHITE}Anna laevale nimi -STR_QUERY_RENAME_AIRCRAFT_CAPTION :{WHITE}Anna lennukile nimi +STR_QUERY_RENAME_TRAIN_CAPTION :{WHITE}Nimeta rong +STR_QUERY_RENAME_ROAD_VEHICLE_CAPTION :{WHITE}Nimeta maanteesõiduk +STR_QUERY_RENAME_SHIP_CAPTION :{WHITE}Nimeta laev +STR_QUERY_RENAME_AIRCRAFT_CAPTION :{WHITE}Nimeta lennuk # Extra buttons for train details windows STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE :{LTBLUE}{ENGINE}{BLACK} Ehitatud: {LTBLUE}{NUM}{BLACK} Väärtus: {LTBLUE}{CURRENCY_LONG} @@ -3807,34 +3946,34 @@ STR_VEHICLE_DETAIL_TAB_INFORMATION :{BLACK}Andmed STR_VEHICLE_DETAILS_TRAIN_INFORMATION_TOOLTIP :{BLACK}Näita täpsutusi rongivagunite kohta STR_VEHICLE_DETAIL_TAB_CAPACITIES :{BLACK}Kandevõimed STR_VEHICLE_DETAILS_TRAIN_CAPACITIES_TOOLTIP :{BLACK}Näita iga rongivaguni kandevõimet -STR_VEHICLE_DETAIL_TAB_TOTAL_CARGO :{BLACK}Veoseid kokku +STR_VEHICLE_DETAIL_TAB_TOTAL_CARGO :{BLACK}Veoste üldarv STR_VEHICLE_DETAILS_TRAIN_TOTAL_CARGO_TOOLTIP :{BLACK}Näita kogu rongi mahtu, jagatud veoseliigi järgi STR_VEHICLE_DETAILS_TRAIN_ARTICULATED_RV_CAPACITY :{BLACK}Kandevõime: {LTBLUE} # Vehicle refit -STR_REFIT_CAPTION :{WHITE}{VEHICLE} (Seadista ümber) +STR_REFIT_CAPTION :{WHITE}{VEHICLE} (Ümberseadista) STR_REFIT_TITLE :{GOLD}Vali veetav veoseliik: STR_REFIT_NEW_CAPACITY_COST_OF_REFIT :{BLACK}Uus kandevõime: {GOLD}{CARGO_LONG}{}{BLACK}Laeva ümberseadistamise hind: {RED}{CURRENCY_LONG} -STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT :{BLACK}Uus mahtuvus: {GOLD}{CARGO_LONG}{}{BLACK}Sissetulek veoseliigi muutusest: {GREEN}{CURRENCY_LONG} +STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT :{BLACK}Uus mahtuvus: {GOLD}{CARGO_LONG}{}{BLACK}Ümberseadistamise tulu: {GREEN}{CURRENCY_LONG} STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT :{BLACK}Uus kandevõime: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}Ümberseadistamise maksumus: {RED}{CURRENCY_LONG} -STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT :{BLACK}Uus mahtuvus: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}Sissetulek veoseliigi muutusest: {GREEN}{CURRENCY_LONG} +STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT :{BLACK}Uus mahtuvus: {GOLD}{CARGO_LONG}, {GOLD}{CARGO_LONG}{}{BLACK}Ümberseadistamise tulu: {GREEN}{CURRENCY_LONG} STR_REFIT_SELECT_VEHICLES_TOOLTIP :{BLACK}Vali ümberseadistatavad sõidukid. Hiirega lohistades saab valida mitu sõidukit. Klõpsates tühjal kohal valitakse terve sõiduk. Ctrl+klõps valib sõiduki ja temale järgneva keti STR_REFIT_TRAIN_LIST_TOOLTIP :{BLACK}Vali rongi veetav veoseliik STR_REFIT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Vali maanteesõiduki veetav veoseliik STR_REFIT_SHIP_LIST_TOOLTIP :{BLACK}Vali kaubalaeva veetav veoseliik -STR_REFIT_AIRCRAFT_LIST_TOOLTIP :{BLACK}Vali lennuki veetav veoseliik +STR_REFIT_AIRCRAFT_LIST_TOOLTIP :{BLACK}Vali õhusõiduki veetav veoseliik -STR_REFIT_TRAIN_REFIT_BUTTON :{BLACK}Seadista ümber -STR_REFIT_ROAD_VEHICLE_REFIT_BUTTON :{BLACK}Muuda mootorsõiduki seadistust -STR_REFIT_SHIP_REFIT_BUTTON :{BLACK}Seadista laev ümber -STR_REFIT_AIRCRAFT_REFIT_BUTTON :{BLACK}Seadista lennuk ümber +STR_REFIT_TRAIN_REFIT_BUTTON :{BLACK}Ümberseadista +STR_REFIT_ROAD_VEHICLE_REFIT_BUTTON :{BLACK}Ümberseadista maanteesõiduk +STR_REFIT_SHIP_REFIT_BUTTON :{BLACK}Ümberseadista laev +STR_REFIT_AIRCRAFT_REFIT_BUTTON :{BLACK}Ümberseadista õhusõiduk -STR_REFIT_TRAIN_REFIT_TOOLTIP :{BLACK}Rongi ümberseadistamine valitud laadungi vedamiseks -STR_REFIT_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}Seadista mootorsõidukit kandma valitud veotüüpi -STR_REFIT_SHIP_REFIT_TOOLTIP :{BLACK}Seadista laev ümber valitud kaubatüübi jaoks -STR_REFIT_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Seadista lennuk ümber, et kanda valitud kaubatüüpi +STR_REFIT_TRAIN_REFIT_TOOLTIP :{BLACK}Ümberseadista rong valitud veoseliigi jaoks +STR_REFIT_ROAD_VEHICLE_REFIT_TOOLTIP :{BLACK}Ümberseadista maantesõiduk valitud veoseliigi jaoks +STR_REFIT_SHIP_REFIT_TOOLTIP :{BLACK}Ümberseadista laev valitud veoseliigi jaoks +STR_REFIT_AIRCRAFT_REFIT_TOOLTIP :{BLACK}Ümberseadista õhusõiduk valitud veoseliigi jaoks # Order view STR_ORDERS_CAPTION :{WHITE}{VEHICLE} (korraldused) @@ -3850,36 +3989,36 @@ STR_ORDERS_END_OF_SHARED_ORDERS :- - Jagatud kor # Order bottom buttons STR_ORDER_NON_STOP :{BLACK}Vahepeatusteta -STR_ORDER_GO_TO :Mine -STR_ORDER_GO_NON_STOP_TO :Mine peatumata -STR_ORDER_GO_VIA :Mine läbi -STR_ORDER_GO_NON_STOP_VIA :Mine peatumata läbi +STR_ORDER_GO_TO :Siht +STR_ORDER_GO_NON_STOP_TO :Siht vahepeatusteta +STR_ORDER_GO_VIA :Siht läbi +STR_ORDER_GO_NON_STOP_VIA :Siht peatumata läbi STR_ORDER_TOOLTIP_NON_STOP :{BLACK}Valitud korralduse peatumisprotseduuri muutmine -STR_ORDER_TOGGLE_FULL_LOAD :{BLACK}Laadi üks täis +STR_ORDER_TOGGLE_FULL_LOAD :{BLACK}Täislaadi üks veos STR_ORDER_DROP_LOAD_IF_POSSIBLE :Laadi peale -STR_ORDER_DROP_FULL_LOAD_ALL :Laadi kõik kaubad täis -STR_ORDER_DROP_FULL_LOAD_ANY :Laadi üks kaup täis -STR_ORDER_DROP_NO_LOADING :Mitte laadida +STR_ORDER_DROP_FULL_LOAD_ALL :Täislaadi kõik veosed +STR_ORDER_DROP_FULL_LOAD_ANY :Täislaadi üks veos +STR_ORDER_DROP_NO_LOADING :Ei laadi STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}Valitud korralduse pealelaadimisprotseduuri muutmine -STR_ORDER_TOGGLE_UNLOAD :{BLACK}Laadi kõik maha -STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :Laadi tühjaks nõudlusel -STR_ORDER_DROP_UNLOAD :Laadi tühjaks -STR_ORDER_DROP_TRANSFER :Laadi ümber -STR_ORDER_DROP_NO_UNLOADING :Mitte maha laadida +STR_ORDER_TOGGLE_UNLOAD :{BLACK}Mahalaadi kõik +STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :Mahalaadi nõudlusel +STR_ORDER_DROP_UNLOAD :Mahalaadi kõik +STR_ORDER_DROP_TRANSFER :Ümberlaadi +STR_ORDER_DROP_NO_UNLOADING :Ei mahalaadi STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Valitud korralduse mahalaadimisprotseduuri muutmine -STR_ORDER_REFIT :{BLACK}Taasseadista -STR_ORDER_REFIT_TOOLTIP :{BLACK}Vali, millist laadungit ümber seadistada selles järjestuses. Ümberseadistuse käsu eemaldamiseks hoia klõpsamise ajal all Control nuppu -STR_ORDER_REFIT_AUTO :{BLACK}Automaatne ümberseadistamine -STR_ORDER_REFIT_AUTO_TOOLTIP :{BLACK}Vali kauba tüüp millele peaks automaatse ümberseadistamisega üle minema. Ctrl-klõps eemaldab valiku. Automaatne ümberseadistamine saab toimuda ainult siis kui sõiduk seda lubab. +STR_ORDER_REFIT :{BLACK}Ümberseadista +STR_ORDER_REFIT_TOOLTIP :{BLACK}Vali, mis veoseliigile ümberseadistada. Ctrl+klõps kõrvaldab ümberseadistamise korralduse +STR_ORDER_REFIT_AUTO :{BLACK}Ümberseadista jaamas +STR_ORDER_REFIT_AUTO_TOOLTIP :{BLACK}Vali, millisele veoseliigile ümberseadistada. Ctrl-klõps eemaldab ümberseadistamise korralduse. Jaamas ümberseadistamine toimub ainult, kui sõiduk võimaldab STR_ORDER_DROP_REFIT_AUTO :Fikseeritud kaubatüüp STR_ORDER_DROP_REFIT_AUTO_ANY :Võimalikud kaubad STR_ORDER_SERVICE :{BLACK}Hooldus -STR_ORDER_DROP_GO_ALWAYS_DEPOT :Alati mine -STR_ORDER_DROP_SERVICE_DEPOT :Vajadusel hoolda +STR_ORDER_DROP_GO_ALWAYS_DEPOT :Alati +STR_ORDER_DROP_SERVICE_DEPOT :Vajadusel STR_ORDER_DROP_HALT_DEPOT :Peatu STR_ORDER_SERVICE_TOOLTIP :{BLACK}Jäta see käsk vahele, kui hooldust ei vajata @@ -3893,6 +4032,7 @@ STR_ORDER_CONDITIONAL_AGE :Vanus (aastates STR_ORDER_CONDITIONAL_REQUIRES_SERVICE :Vajab hooldust STR_ORDER_CONDITIONAL_UNCONDITIONALLY :Alati STR_ORDER_CONDITIONAL_REMAINING_LIFETIME :Amortiseerumiseni (aastaid) +STR_ORDER_CONDITIONAL_MAX_RELIABILITY :Kõrgeim tehnoseisund STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP :{BLACK}Kuidas sõiduki andmeid antud väärtusega võrreldakse STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS :on võrdne @@ -3916,18 +4056,18 @@ STR_ORDERS_DELETE_ALL_TOOLTIP :{BLACK}Eemalda STR_ORDERS_STOP_SHARING_BUTTON :{BLACK}Lõpeta jagamine STR_ORDERS_STOP_SHARING_TOOLTIP :{BLACK}Lõpeta korralduste jagamine. Ctrl+klõps eemaldab kõik selle sõiduki korraldused -STR_ORDERS_GO_TO_BUTTON :{BLACK}Mine -STR_ORDER_GO_TO_NEAREST_DEPOT :Mine lähimasse depoosse -STR_ORDER_GO_TO_NEAREST_HANGAR :Mine lähimasse angaari +STR_ORDERS_GO_TO_BUTTON :{BLACK}Siht +STR_ORDER_GO_TO_NEAREST_DEPOT :Siht lähim depoo +STR_ORDER_GO_TO_NEAREST_HANGAR :Siht lähim angaar STR_ORDER_CONDITIONAL :Korralduste tinglik vahelejätmine -STR_ORDER_SHARE :Jaga korraldusi +STR_ORDER_SHARE :Korralduste jagamine STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Lisa valitud käsu ette uus korraldus, või kui korraldust ei ole valitud, siis nimekirja lõppu. «Ctrl» määrab jaama puhul korralduseks «peale laadida üks kaup», meldepunkti puhul «peatuseta» ja depoo puhul «hooldus». «Jaga korraldusi» või «Ctrl» klahv lubab sellel sõidukil jagada korraldusi valitud sõidukiga. Klõpsates teisel sõidukil, dubleeritakse selle korraldused STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP :{BLACK}Näita kõiki sama sõidugraafikuga mootorsõidukeid # String parts to build the order string -STR_ORDER_GO_TO_WAYPOINT :Läbi punkti {WAYPOINT} -STR_ORDER_GO_NON_STOP_TO_WAYPOINT :Läbi peatumata punkti{WAYPOINT} +STR_ORDER_GO_TO_WAYPOINT :Siht läbida {WAYPOINT} +STR_ORDER_GO_NON_STOP_TO_WAYPOINT :Siht peatumata läbida {WAYPOINT} STR_ORDER_SERVICE_AT :Hooldus STR_ORDER_SERVICE_NON_STOP_AT :Hooldus ilma peatumata @@ -3940,42 +4080,43 @@ STR_ORDER_SHIP_DEPOT :laevaremonditeh STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT :{STRING} {STRING} {STRING} STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT} -STR_ORDER_REFIT_ORDER :(Taasseadista {STRING}) -STR_ORDER_REFIT_STOP_ORDER :(Seadista ümber {STRING} jaoks ja peatu) +STR_ORDER_REFIT_ORDER :(Ümberseadista: {STRING}) +STR_ORDER_REFIT_STOP_ORDER :(Ümberseadista: {STRING}, peatu) STR_ORDER_STOP_ORDER :(Peatu) STR_ORDER_GO_TO_STATION :{STRING} {STATION} {STRING} +STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(Ei saa jaama kasutada){POP_COLOUR} {STRING} {STATION} {STRING} STR_ORDER_IMPLICIT :(Automaatne) -STR_ORDER_FULL_LOAD :(Laadida kõik kaubad täis) -STR_ORDER_FULL_LOAD_ANY :(Laadida üks kaup täis) -STR_ORDER_NO_LOAD :(Mitte laadida) -STR_ORDER_UNLOAD :(Laadida tühjaks ja laadida peale) -STR_ORDER_UNLOAD_FULL_LOAD :(Laadida tühjaks ja laadida kõik kaubad täis) -STR_ORDER_UNLOAD_FULL_LOAD_ANY :(Laadida tühjaks ja laadida üks kaup täis) -STR_ORDER_UNLOAD_NO_LOAD :(Laadida tühjaks ja peale mitte laadida) -STR_ORDER_TRANSFER :(Laadida ümber ja laadida peale) -STR_ORDER_TRANSFER_FULL_LOAD :(Laadida ümber ja laadida kõik kaubad täis) -STR_ORDER_TRANSFER_FULL_LOAD_ANY :(Laadida ümber ja laadida üks kaup täis) -STR_ORDER_TRANSFER_NO_LOAD :(Laadida ümber ja peale mitte laadida) -STR_ORDER_NO_UNLOAD :(Maha mitte laadida ja laadida peale) -STR_ORDER_NO_UNLOAD_FULL_LOAD :(Maha mitte laadida ja laadida kõik kaubad täis) -STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(Maha mitte laadida ja laadida üks kaup täis) -STR_ORDER_NO_UNLOAD_NO_LOAD :(Maha ei laadita ja peale ei laadita) +STR_ORDER_FULL_LOAD :(Täislaadi kõik) +STR_ORDER_FULL_LOAD_ANY :(Täislaadi üks veos) +STR_ORDER_NO_LOAD :(Ei laadi) +STR_ORDER_UNLOAD :(Mahalaadi, laadi) +STR_ORDER_UNLOAD_FULL_LOAD :(Mahalaadi, täislaadi kõik) +STR_ORDER_UNLOAD_FULL_LOAD_ANY :(Mahalaadi, täislaadi üks) +STR_ORDER_UNLOAD_NO_LOAD :(Mahalaadi, jäta tühjaks) +STR_ORDER_TRANSFER :(Ümberlaadi, laadi) +STR_ORDER_TRANSFER_FULL_LOAD :(Ümberlaadi, täislaadi kõik) +STR_ORDER_TRANSFER_FULL_LOAD_ANY :(Ümberlaadi, täislaadi üks) +STR_ORDER_TRANSFER_NO_LOAD :(Ümberlaadi, jäta tühjaks) +STR_ORDER_NO_UNLOAD :(Ei mahalaadi, laadi) +STR_ORDER_NO_UNLOAD_FULL_LOAD :(Ei mahalaadi, täislaadi kõik) +STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(Ei mahalaadi, täislaadi üks) +STR_ORDER_NO_UNLOAD_NO_LOAD :(Ei mahalaadi, ei laadi) -STR_ORDER_AUTO_REFIT :(Automaatne ümberseadistus tüüpile {STRING}) -STR_ORDER_FULL_LOAD_REFIT :(Laadida kõik kaubad täis ja seadistada kaubale {STRING}) -STR_ORDER_FULL_LOAD_ANY_REFIT :(Laadida üks kaup täis ja seadistada kaubale {STRING}) -STR_ORDER_UNLOAD_REFIT :(Laadida tühjaks, laadida peale ja seadistada kaubale {STRING}) -STR_ORDER_UNLOAD_FULL_LOAD_REFIT :(Laadida tühjaks, laadida kõik kaubad täis ja seadistada kaubale {STRING}) -STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :(Laadida tühjaks, laadida üks kaup täis ja seadistada kaubale {STRING}) -STR_ORDER_TRANSFER_REFIT :(Laadida ümber, laadida peale ja seadistada kaubale {STRING}) -STR_ORDER_TRANSFER_FULL_LOAD_REFIT :(Laadida ümber, laadida kõik kaubad täis ja seadistada kaubale {STRING}) -STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :(Laadida ümber, laadida üks kaup täis ja seadistada kaubale {STRING}) -STR_ORDER_NO_UNLOAD_REFIT :(Maha mitte laadida, laadida peale ja seadistada kaubale {STRING}) -STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :(Maha mitte laadida, laadida kõik kaubad täis ja seadistada kaubale {STRING}) -STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :(Maha mitte laadida, laadida üks kaup täis ja seadistada kaubale {STRING}) +STR_ORDER_AUTO_REFIT :(Ümberseadistamine: {STRING}) +STR_ORDER_FULL_LOAD_REFIT :(Täislaadi kõik, ümberseadista: {STRING}) +STR_ORDER_FULL_LOAD_ANY_REFIT :(Täislaadi üks veos, ümberseadista: {STRING}) +STR_ORDER_UNLOAD_REFIT :(Mahalaadi, laadi, ümberseadista: {STRING}) +STR_ORDER_UNLOAD_FULL_LOAD_REFIT :(Mahalaadi, täislaadi kõik, ümberseadista: {STRING}) +STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :(Mahalaadi, täislaadi üks, ümberlaadi: {STRING}) +STR_ORDER_TRANSFER_REFIT :(Ümberlaadi, laadi, ümberseadista: {STRING}) +STR_ORDER_TRANSFER_FULL_LOAD_REFIT :(Ümberlaadi, täislaadi kõik, ümberseadista: {STRING}) +STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :(Ümberlaadi, täislaadi üks, ümberseadista: {STRING}) +STR_ORDER_NO_UNLOAD_REFIT :(Ei mahalaadi, laadi veos, ümberseadista: {STRING}) +STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :(Ei mahalaadi, täislaadi kõik, ümberseadista: {STRING}) +STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :(Ei mahalaadi, täislaadi üks, ümberseadista: {STRING}) STR_ORDER_AUTO_REFIT_ANY :võimalikud kaubad @@ -4190,6 +4331,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Salvestus on te STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :Fail pole loetav STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :Faili ei saanud kirjutada STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :Andmeterviklikkuse kontrolli ei läbitud +STR_GAME_SAVELOAD_ERROR_PATCHPACK :Mäng on salvestatud muudetud versiooniga STR_GAME_SAVELOAD_NOT_AVAILABLE : STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}Mäng on salvestatud osas, kus trammid ei olnud toetatud. Kõik trammid on eemaldatud @@ -4270,6 +4412,7 @@ STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... pole STR_ERROR_CURRENCY_REQUIRED :{WHITE}... vajad {CURRENCY_LONG} STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Ei saa laenu tagasi maksta... STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Ei saa anda raha, mis on laenatud pangast. +STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Ei saa sellele ettevõttele raha saata... STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Ettevõtet ei saa osta... STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Ettevõtte peakorterit ei saa ehitada... STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Selle ettevõtte aktsiatest ei saa 25% osta... @@ -4278,7 +4421,7 @@ STR_ERROR_PROTECTED :{WHITE}See ette # Town related errors STR_ERROR_CAN_T_GENERATE_TOWN :{WHITE}Ei saa ühtegi linna ehitada... -STR_ERROR_CAN_T_RENAME_TOWN :{WHITE}Linna nime ei saa vahetada... +STR_ERROR_CAN_T_RENAME_TOWN :{WHITE}Ei saa linna ümbernimetada... STR_ERROR_CAN_T_FOUND_TOWN_HERE :{WHITE}Siia ei saa linna ehitada... STR_ERROR_CAN_T_EXPAND_TOWN :{WHITE}Linna ei saa laiendada... STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... liiga lähedal kaardi servale @@ -4329,7 +4472,7 @@ STR_ERROR_TOO_MANY_BUS_STOPS :{WHITE}Liiga pa STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Liiga palju laadimisplatvorme STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Liiga lähedal teisele dokile STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Liiga lähedal teisele lennuväljale -STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Jaama nime ei saa vahetada... +STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Ei saa jaama ümbernimetada... STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... see tee on omatud linna poolt STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... tee on vales suunas STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... nurgad ei saa läbisõidupeatustes olla @@ -4372,7 +4515,7 @@ STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Siia ei STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Trammidepood ei saa siia rajada STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Laevaremonditehast ei saa siia ehitada... -STR_ERROR_CAN_T_RENAME_DEPOT :{WHITE}Ei saa muuta depoo nime... +STR_ERROR_CAN_T_RENAME_DEPOT :{WHITE}Ei saa depood ümbernimetada... STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}... peab olema depoos peatatud STR_ERROR_ROAD_VEHICLE_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}... peab garaažis peatatud olema @@ -4396,6 +4539,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Vale depootüü STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} on pärast asendamist liiga pikk STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}Automaatse asendamise/uuendamise reegleid ei ole rakendatud STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(rahalimiit) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}Uus sõiduk ei saa vedada {STRING} +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}Uus sõiduk ei saa ümberseadistada korralduses {NUM} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Teostamatu rööbasteede kooslus @@ -4404,6 +4549,7 @@ STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Sobiv ro STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Rööbastee tuleb eelnevalt lammutada STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Läbipääsmatu või ühesuunaline maantee STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Ülesõidukohad on selle raudteetüübi puhul keelatud +STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}See teeliik ei luba tasaseid ristmikke STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Siia ei saa signaale rajada... STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Siia ei saa raudteed ehitada... STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Siit ei saa raudteed lammutada... @@ -4423,6 +4569,11 @@ STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Siinset STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Siinset trammiteed ei saa lammutada... STR_ERROR_THERE_IS_NO_ROAD :{WHITE}... siin pole autoteed STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}... siin pole trammiteed +STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Siin ei saa teeliiki ümber muuta... +STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Siin ei saa trammiliiki ümber muuta... +STR_ERROR_NO_SUITABLE_ROAD :{WHITE}Puudub sobilik tee +STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}Puudub sobiv trammitee +STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... mitteühilduv trammitee # Waterway construction errors STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Siia ei saa kanaleid ehitada... @@ -4471,13 +4622,14 @@ STR_ERROR_CAN_T_PURCHASE_THIS_LAND :{WHITE}Seda maa STR_ERROR_YOU_ALREADY_OWN_IT :{WHITE}... see on juba sinu oma! # Group related errors -STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Ei saa rühma luua... -STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Seda rühma ei saa eemaldada... -STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Rühma nime ei saa vahetada... -STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Ülemrühma ei saa määrata... -STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Ei saa kõiki sõidukeid sellest rühmast eemaldada... -STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Antud sõidukit ei saa sellesse rühma lisada... -STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Jagatud sõidukeid ei saa rühma lisada... +STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Ei saa jagu luua... +STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Seda jagu ei saa kõrvaldada... +STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Ei saa jagu ümbernimetada... +STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Ülemjagu ei saa määrata... +STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}... jaotuste hierarhias ei tohi olla ringseoseid +STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Ei saa kõiki sõidukeid sellest jaost kõrvaldada... +STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Antud sõidukit ei saa sellesse jakku lisada... +STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Jagatud sõidukeid ei saa jakku lisada... # Generic vehicle errors STR_ERROR_TRAIN_IN_THE_WAY :{WHITE}Rong on ees @@ -4485,15 +4637,15 @@ STR_ERROR_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Mootors STR_ERROR_SHIP_IN_THE_WAY :{WHITE}Laev on ees STR_ERROR_AIRCRAFT_IN_THE_WAY :{WHITE}Lennuk on teel -STR_ERROR_CAN_T_REFIT_TRAIN :{WHITE}Ei ole võimalik ümber seadistada... -STR_ERROR_CAN_T_REFIT_ROAD_VEHICLE :{WHITE}Mootorsõiduki seadistust ei saa ümber muuta -STR_ERROR_CAN_T_REFIT_SHIP :{WHITE}Ei saa laeva ümber seadistada... -STR_ERROR_CAN_T_REFIT_AIRCRAFT :{WHITE}Ei saa lennukit ümber seadistada... +STR_ERROR_CAN_T_REFIT_TRAIN :{WHITE}Ei saa rongi ümberseadistada... +STR_ERROR_CAN_T_REFIT_ROAD_VEHICLE :{WHITE}Ei saa maanteesõidukit ümberseadistada... +STR_ERROR_CAN_T_REFIT_SHIP :{WHITE}Ei saa laeva ümberseadistada... +STR_ERROR_CAN_T_REFIT_AIRCRAFT :{WHITE}Ei saa õhusõidukit ümberseadistada... -STR_ERROR_CAN_T_RENAME_TRAIN :{WHITE}Ei saa nimetada rongi... -STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Ei saa maanteveokit ümber nimetada... -STR_ERROR_CAN_T_RENAME_SHIP :{WHITE}Ei saa laeva ümber nimetada... -STR_ERROR_CAN_T_RENAME_AIRCRAFT :{WHITE}Ei saa lennukile nime anda +STR_ERROR_CAN_T_RENAME_TRAIN :{WHITE}Ei saa rongi ümbernimetada... +STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Ei saa maanteesõidukit ümbernimetada... +STR_ERROR_CAN_T_RENAME_SHIP :{WHITE}Ei saa laeva ümbernimetada... +STR_ERROR_CAN_T_RENAME_AIRCRAFT :{WHITE}Ei saa õhusõidukit ümbernimetada... STR_ERROR_CAN_T_STOP_START_TRAIN :{WHITE}Ei saa peatada/startida rongi... STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Ei saa veokit peatada, ega startida... @@ -4510,10 +4662,10 @@ STR_ERROR_CAN_T_BUY_ROAD_VEHICLE :{WHITE}Mootors STR_ERROR_CAN_T_BUY_SHIP :{WHITE}Laeva ei saa osta... STR_ERROR_CAN_T_BUY_AIRCRAFT :{WHITE}Lennukit ei saa osta... -STR_ERROR_CAN_T_RENAME_TRAIN_TYPE :{WHITE}Raudteesõiduki tüübinime ei saa vahetada... -STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Mootorsõiduki tüübinime ei saa vahetada... -STR_ERROR_CAN_T_RENAME_SHIP_TYPE :{WHITE}Laeva tüübinime ei saa vahetada... -STR_ERROR_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Lennuki tüübinime ei saa vahetada... +STR_ERROR_CAN_T_RENAME_TRAIN_TYPE :{WHITE}Ei saa rööbassõiduki liiki ümbernimetada... +STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Ei saa maanteesõiduki liiki ümbernimetada... +STR_ERROR_CAN_T_RENAME_SHIP_TYPE :{WHITE}Ei saa laevaliiki ümbernimetada... +STR_ERROR_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Ei saa õhusõiduki liiki ümbernimetada... STR_ERROR_CAN_T_SELL_TRAIN :{WHITE}Rööbassõidukit ei saa müüa... STR_ERROR_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Ei saa veokit müüa... @@ -4586,6 +4738,7 @@ STR_BASESOUNDS_WIN_DESCRIPTION :Algse Transport STR_BASESOUNDS_NONE_DESCRIPTION :Helikogu ilma helideta. STR_BASEMUSIC_WIN_DESCRIPTION :Algse Transport Tycoon Deluxe Windowsi versiooni muusika. STR_BASEMUSIC_DOS_DESCRIPTION :Algse Transport Tycoon Deluxe DOSi versiooni muusika. +STR_BASEMUSIC_TTO_DESCRIPTION :Algupärase Transport Tycooni (Original/World Editor) DOS-versiooni muusika. STR_BASEMUSIC_NONE_DESCRIPTION :Muusikakogu ilma muusikata. ##id 0x2000 @@ -4669,10 +4822,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :suhkrukaevandus ##id 0x6000 STR_SV_EMPTY : STR_SV_UNNAMED :Nimetu -STR_SV_TRAIN_NAME :Rong {COMMA} -STR_SV_ROAD_VEHICLE_NAME :Mootorsõiduk {COMMA} -STR_SV_SHIP_NAME :Laev {COMMA} -STR_SV_AIRCRAFT_NAME :Õhusõiduk {COMMA} +STR_SV_TRAIN_NAME :Rong #{COMMA} +STR_SV_ROAD_VEHICLE_NAME :Mootorsõiduk #{COMMA} +STR_SV_SHIP_NAME :Laev #{COMMA} +STR_SV_AIRCRAFT_NAME :Õhusõiduk #{COMMA} STR_SV_STNAME :{STRING} STR_SV_STNAME_NORTH :Põhja {STRING} @@ -4973,7 +5126,8 @@ STR_FORMAT_DATE_ISO :{2:NUM}-{1:STRI STR_FORMAT_BUOY_NAME :{TOWN} Poi STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Poi nr. {COMMA} STR_FORMAT_COMPANY_NUM :(Ettevõte {COMMA}) -STR_FORMAT_GROUP_NAME :Rühm {COMMA} +STR_FORMAT_GROUP_NAME :Jagu {COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN} meldepunkt STR_FORMAT_WAYPOINT_NAME_SERIAL :Meldepunkt {TOWN} #{COMMA} From a52d716c88925a6a55f91276c9b4007cdb9b6795 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 16 Jan 2021 14:55:26 +0100 Subject: [PATCH 009/275] Codechange: [SDL2] remove include-protection This is already done by CMake: if SDL2 is not detected, this file is not included. --- src/video/sdl2_v.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index ede8a84860..9192083999 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -7,8 +7,6 @@ /** @file sdl2_v.cpp Implementation of the SDL2 video driver. */ -#ifdef WITH_SDL2 - #include "../stdafx.h" #include "../openttd.h" #include "../gfx_func.h" @@ -962,5 +960,3 @@ Dimension VideoDriver_SDL::GetScreenSize() const return { static_cast(mode.w), static_cast(mode.h) }; } - -#endif /* WITH_SDL2 */ From 6916fc76bd3f2ababefaace061b62a7aeaa4f419 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 16 Jan 2021 15:09:04 +0100 Subject: [PATCH 010/275] Codechange: [SDL2] reworked FindResolutions to be more like the rest There was no default resolution fallback, and the code was different from the win32 driver. It is now named the same and much more similar. --- src/video/sdl2_v.cpp | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 9192083999..f4ea0dddb4 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -201,26 +201,38 @@ static void DrawSurfaceToScreenThread() } } -static void GetVideoModes() -{ - int modes = SDL_GetNumDisplayModes(0); - if (modes == 0) usererror("sdl: no modes available"); +static const Dimension default_resolutions[] = { + { 640, 480 }, + { 800, 600 }, + { 1024, 768 }, + { 1152, 864 }, + { 1280, 800 }, + { 1280, 960 }, + { 1280, 1024 }, + { 1400, 1050 }, + { 1600, 1200 }, + { 1680, 1050 }, + { 1920, 1200 } +}; +static void FindResolutions() +{ _resolutions.clear(); - SDL_DisplayMode mode; - for (int i = 0; i < modes; i++) { + for (int i = 0; i < SDL_GetNumDisplayModes(0); i++) { + SDL_DisplayMode mode; SDL_GetDisplayMode(0, i, &mode); - uint w = mode.w; - uint h = mode.h; - - if (w < 640 || h < 480) continue; // reject too small resolutions - - if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(w, h)) != _resolutions.end()) continue; - _resolutions.emplace_back(w, h); + if (mode.w < 640 || mode.h < 480) continue; + if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(mode.w, mode.h)) != _resolutions.end()) continue; + _resolutions.emplace_back(mode.w, mode.h); } - if (_resolutions.empty()) usererror("No usable screen resolutions found!\n"); + + /* We have found no resolutions, show the default list */ + if (_resolutions.empty()) { + _resolutions.assign(std::begin(default_resolutions), std::end(default_resolutions)); + } + SortResolutions(); } @@ -696,7 +708,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm) this->UpdateAutoResolution(); - GetVideoModes(); + FindResolutions(); + if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height, false)) { return SDL_GetError(); } From f31b65825f160032451e743c044b9ac0027a8172 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 16 Jan 2021 15:25:01 +0100 Subject: [PATCH 011/275] Codechange: [SDL2] Move FindStartupDisplay to its own function --- src/video/sdl2_v.cpp | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index f4ea0dddb4..251a6513f6 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -258,6 +258,27 @@ static void GetAvailableVideoMode(uint *w, uint *h) *h = _resolutions[best].height; } +static uint FindStartupDisplay(uint startup_display) +{ + int num_displays = SDL_GetNumVideoDisplays(); + + /* If the user indicated a valid monitor, use that. */ + if (IsInsideBS(startup_display, 0, num_displays)) return startup_display; + + /* Mouse position decides which display to use. */ + int mx, my; + SDL_GetGlobalMouseState(&mx, &my); + for (int display = 0; display < num_displays; ++display) { + SDL_Rect r; + if (SDL_GetDisplayBounds(display, &r) == 0 && IsInsideBS(mx, r.x, r.w) && IsInsideBS(my, r.y, r.h)) { + DEBUG(driver, 1, "SDL2: Mouse is at (%d, %d), use display %d (%d, %d, %d, %d)", mx, my, display, r.x, r.y, r.w, r.h); + return display; + } + } + + return 0; +} + bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) { SDL_Surface *newscreen; @@ -689,27 +710,12 @@ const char *VideoDriver_SDL::Start(const StringList &parm) } if (ret_code < 0) return SDL_GetError(); - this->startup_display = GetDriverParamInt(parm, "display", -1); - int num_displays = SDL_GetNumVideoDisplays(); - if (!IsInsideBS(this->startup_display, 0, num_displays)) { - /* Mouse position decides which display to use */ - int mx, my; - SDL_GetGlobalMouseState(&mx, &my); - this->startup_display = 0; // used when mouse is on no screen... - for (int display = 0; display < num_displays; ++display) { - SDL_Rect r; - if (SDL_GetDisplayBounds(display, &r) == 0 && IsInsideBS(mx, r.x, r.w) && IsInsideBS(my, r.y, r.h)) { - DEBUG(driver, 1, "SDL2: Mouse is at (%d, %d), use display %d (%d, %d, %d, %d)", mx, my, display, r.x, r.y, r.w, r.h); - this->startup_display = display; - break; - } - } - } - this->UpdateAutoResolution(); FindResolutions(); + this->startup_display = FindStartupDisplay(GetDriverParamInt(parm, "display", -1)); + if (!CreateMainSurface(_cur_resolution.width, _cur_resolution.height, false)) { return SDL_GetError(); } From 678031f9b3f3dd56e6a40d08bdd74578f48a471d Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 16 Jan 2021 16:27:13 +0100 Subject: [PATCH 012/275] Codechange: [SDL2] Only set _cur_palette, never _local_palette --- src/video/sdl2_v.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 251a6513f6..a16061d5f5 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -128,9 +128,9 @@ static void UpdatePalette(bool init = false) static void InitPalette() { + _cur_palette.first_dirty = 0; + _cur_palette.count_dirty = 256; _local_palette = _cur_palette; - _local_palette.first_dirty = 0; - _local_palette.count_dirty = 256; UpdatePalette(true); } From e41ec5b42eef7121f07a802178855b3854d857ee Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 11:28:13 +0100 Subject: [PATCH 013/275] Codechange: [SDL2] Minor code cleanup to remove silly variable --- src/video/sdl2_v.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index a16061d5f5..ce1917ccc6 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -375,13 +375,10 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) * appropriate event to know this. */ if (_fullscreen) _cursor.in_window = true; - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - blitter->PostResize(); + BlitterFactory::GetCurrentBlitter()->PostResize(); InitPalette(); - GameSizeChanged(); - return true; } From 8de325f2567bd47ed6546a15c084449d4f585f3e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 16 Jan 2021 17:38:43 +0100 Subject: [PATCH 014/275] Codechange: [SDL2] Only prepare "caption" if you are going to us it --- src/video/sdl2_v.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index ce1917ccc6..33c2b96b18 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -282,7 +282,6 @@ static uint FindStartupDisplay(uint startup_display) bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) { SDL_Surface *newscreen; - char caption[50]; int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); GetAvailableVideoMode(&w, &h); @@ -292,8 +291,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) /* Free any previously allocated shadow surface */ if (_sdl_surface != nullptr && _sdl_surface != _sdl_realscreen) SDL_FreeSurface(_sdl_surface); - seprintf(caption, lastof(caption), "OpenTTD %s", _openttd_revision); - if (_sdl_window == nullptr) { Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; @@ -307,6 +304,9 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) x = r.x + std::max(0, r.w - static_cast(w)) / 2; y = r.y + std::max(0, r.h - static_cast(h)) / 4; // decent desktops have taskbars at the bottom } + + char caption[50]; + seprintf(caption, lastof(caption), "OpenTTD %s", _openttd_revision); _sdl_window = SDL_CreateWindow( caption, x, y, From 8c37e5c5261bd624eabfa02a36ba41ffe6535b50 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 11:43:46 +0100 Subject: [PATCH 015/275] Codechange: [SDL2] reworked the different surfaces to make it more readable --- src/video/sdl2_v.cpp | 59 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 33c2b96b18..cb9105357a 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -35,7 +35,8 @@ static FVideoDriver_SDL iFVideoDriver_SDL; static SDL_Window *_sdl_window; static SDL_Surface *_sdl_surface; -static SDL_Surface *_sdl_realscreen; +static SDL_Surface *_sdl_rgb_surface; +static SDL_Surface *_sdl_real_surface; /** Whether the drawing is/may be done in a separate thread. */ static bool _draw_threaded; @@ -86,7 +87,7 @@ static void UpdatePalette(bool init = false) SDL_SetPaletteColors(_sdl_palette, pal, _local_palette.first_dirty, _local_palette.count_dirty); SDL_SetSurfacePalette(_sdl_surface, _sdl_palette); - if (_sdl_surface != _sdl_realscreen && init) { + if (_sdl_surface != _sdl_real_surface && init) { /* When using a shadow surface, also set our palette on the real screen. This lets SDL * allocate as many colors (or approximations) as * possible, instead of using only the default SDL @@ -107,10 +108,10 @@ static void UpdatePalette(bool init = false) * palette change and the blitting below, so we only set * the real palette during initialisation. */ - SDL_SetSurfacePalette(_sdl_realscreen, _sdl_palette); + SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette); } - if (_sdl_surface != _sdl_realscreen && !init) { + if (_sdl_surface != _sdl_real_surface && !init) { /* We're not using real hardware palette, but are letting SDL * approximate the palette during shadow -> screen copy. To * change the palette, we need to recopy the entire screen. @@ -121,7 +122,7 @@ static void UpdatePalette(bool init = false) * best mapping of shadow palette colors to real palette * colors from scratch. */ - SDL_BlitSurface(_sdl_surface, nullptr, _sdl_realscreen, nullptr); + SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr); SDL_UpdateWindowSurface(_sdl_window); } } @@ -168,15 +169,15 @@ static void DrawSurfaceToScreen() _num_dirty_rects = 0; if (n > MAX_DIRTY_RECTS) { - if (_sdl_surface != _sdl_realscreen) { - SDL_BlitSurface(_sdl_surface, nullptr, _sdl_realscreen, nullptr); + if (_sdl_surface != _sdl_real_surface) { + SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr); } SDL_UpdateWindowSurface(_sdl_window); } else { - if (_sdl_surface != _sdl_realscreen) { + if (_sdl_surface != _sdl_real_surface) { for (int i = 0; i < n; i++) { - SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_realscreen, &_dirty_rects[i]); + SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_real_surface, &_dirty_rects[i]); } } @@ -281,16 +282,12 @@ static uint FindStartupDisplay(uint startup_display) bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) { - SDL_Surface *newscreen; int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); GetAvailableVideoMode(&w, &h); DEBUG(driver, 1, "SDL2: using mode %ux%ux%d", w, h, bpp); - /* Free any previously allocated shadow surface */ - if (_sdl_surface != nullptr && _sdl_surface != _sdl_realscreen) SDL_FreeSurface(_sdl_surface); - if (_sdl_window == nullptr) { Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; @@ -335,40 +332,46 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) if (resize) SDL_SetWindowSize(_sdl_window, w, h); - newscreen = SDL_GetWindowSurface(_sdl_window); - if (newscreen == NULL) { + _sdl_real_surface = SDL_GetWindowSurface(_sdl_window); + if (_sdl_real_surface == nullptr) { DEBUG(driver, 0, "SDL2: Couldn't get window surface: %s", SDL_GetError()); return false; } - _sdl_realscreen = newscreen; + /* Free any previously allocated rgb surface. */ + if (_sdl_rgb_surface != nullptr) { + SDL_FreeSurface(_sdl_rgb_surface); + _sdl_rgb_surface = nullptr; + } if (bpp == 8) { - newscreen = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0); + _sdl_rgb_surface = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0); - if (newscreen == nullptr) { + if (_sdl_rgb_surface == nullptr) { DEBUG(driver, 0, "SDL2: Couldn't allocate shadow surface: %s", SDL_GetError()); return false; } + + _sdl_surface = _sdl_rgb_surface; + } else { + _sdl_surface = _sdl_real_surface; } if (_sdl_palette == nullptr) { _sdl_palette = SDL_AllocPalette(256); - } - - if (_sdl_palette == nullptr) { - DEBUG(driver, 0, "SDL_AllocPalette() failed: %s", SDL_GetError()); - return false; + if (_sdl_palette == nullptr) { + DEBUG(driver, 0, "SDL_AllocPalette() failed: %s", SDL_GetError()); + return false; + } } /* Delay drawing for this cycle; the next cycle will redraw the whole screen */ _num_dirty_rects = 0; - _screen.width = newscreen->w; - _screen.height = newscreen->h; - _screen.pitch = newscreen->pitch / (bpp / 8); - _screen.dst_ptr = newscreen->pixels; - _sdl_surface = newscreen; + _screen.width = _sdl_surface->w; + _screen.height = _sdl_surface->h; + _screen.pitch = _sdl_surface->pitch / (bpp / 8); + _screen.dst_ptr = _sdl_surface->pixels; /* When in full screen, we will always have the mouse cursor * within the window, even though SDL does not give us the From 19345908cba1bf12a138162b18d6db39662cb762 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 11:54:36 +0100 Subject: [PATCH 016/275] Codechange: [SDL2] Split away CreateMainWindow from CreateMainSurface This makes the code a bit more readable, as both intentions are more clear, and there is less nesting in the main function. --- src/video/sdl2_v.cpp | 91 +++++++++++++++++++++++--------------------- src/video/sdl2_v.h | 1 + 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index cb9105357a..e4518d5b37 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -280,56 +280,61 @@ static uint FindStartupDisplay(uint startup_display) return 0; } +bool VideoDriver_SDL::CreateMainWindow(uint w, uint h) +{ + if (_sdl_window != nullptr) return true; + + Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; + + if (_fullscreen) { + flags |= SDL_WINDOW_FULLSCREEN; + } + + int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; + SDL_Rect r; + if (SDL_GetDisplayBounds(this->startup_display, &r) == 0) { + x = r.x + std::max(0, r.w - static_cast(w)) / 2; + y = r.y + std::max(0, r.h - static_cast(h)) / 4; // decent desktops have taskbars at the bottom + } + + char caption[50]; + seprintf(caption, lastof(caption), "OpenTTD %s", _openttd_revision); + _sdl_window = SDL_CreateWindow( + caption, + x, y, + w, h, + flags); + + if (_sdl_window == nullptr) { + DEBUG(driver, 0, "SDL2: Couldn't allocate a window to draw on"); + return false; + } + + std::string icon_path = FioFindFullPath(BASESET_DIR, "openttd.32.bmp"); + if (!icon_path.empty()) { + /* Give the application an icon */ + SDL_Surface *icon = SDL_LoadBMP(icon_path.c_str()); + if (icon != nullptr) { + /* Get the colourkey, which will be magenta */ + uint32 rgbmap = SDL_MapRGB(icon->format, 255, 0, 255); + + SDL_SetColorKey(icon, SDL_TRUE, rgbmap); + SDL_SetWindowIcon(_sdl_window, icon); + SDL_FreeSurface(icon); + } + } + + return true; +} + bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) { int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); GetAvailableVideoMode(&w, &h); - DEBUG(driver, 1, "SDL2: using mode %ux%ux%d", w, h, bpp); - if (_sdl_window == nullptr) { - Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; - - if (_fullscreen) { - flags |= SDL_WINDOW_FULLSCREEN; - } - - int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; - SDL_Rect r; - if (SDL_GetDisplayBounds(this->startup_display, &r) == 0) { - x = r.x + std::max(0, r.w - static_cast(w)) / 2; - y = r.y + std::max(0, r.h - static_cast(h)) / 4; // decent desktops have taskbars at the bottom - } - - char caption[50]; - seprintf(caption, lastof(caption), "OpenTTD %s", _openttd_revision); - _sdl_window = SDL_CreateWindow( - caption, - x, y, - w, h, - flags); - - if (_sdl_window == nullptr) { - DEBUG(driver, 0, "SDL2: Couldn't allocate a window to draw on"); - return false; - } - - std::string icon_path = FioFindFullPath(BASESET_DIR, "openttd.32.bmp"); - if (!icon_path.empty()) { - /* Give the application an icon */ - SDL_Surface *icon = SDL_LoadBMP(icon_path.c_str()); - if (icon != nullptr) { - /* Get the colourkey, which will be magenta */ - uint32 rgbmap = SDL_MapRGB(icon->format, 255, 0, 255); - - SDL_SetColorKey(icon, SDL_TRUE, rgbmap); - SDL_SetWindowIcon(_sdl_window, icon); - SDL_FreeSurface(icon); - } - } - } - + if (!this->CreateMainWindow(w, h)) return false; if (resize) SDL_SetWindowSize(_sdl_window, w, h); _sdl_real_surface = SDL_GetWindowSurface(_sdl_window); diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h index de10543b5d..a723256743 100644 --- a/src/video/sdl2_v.h +++ b/src/video/sdl2_v.h @@ -49,6 +49,7 @@ private: void LoopOnce(); void MainLoopCleanup(); bool CreateMainSurface(uint w, uint h, bool resize); + bool CreateMainWindow(uint w, uint h); #ifdef __EMSCRIPTEN__ /* Convert a constant pointer back to a non-constant pointer to a member function. */ From eb80fefd1db73dcc2cfd9439749dfaea42dee89f Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 11:56:26 +0100 Subject: [PATCH 017/275] Fix: [SDL2] Display why SDL_CreateWindow() failed in case it does All SDL_NNN errors print SDL_GetError, except for this one place. --- src/video/sdl2_v.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index e4518d5b37..61edea6e00 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -306,7 +306,7 @@ bool VideoDriver_SDL::CreateMainWindow(uint w, uint h) flags); if (_sdl_window == nullptr) { - DEBUG(driver, 0, "SDL2: Couldn't allocate a window to draw on"); + DEBUG(driver, 0, "SDL2: Couldn't allocate a window to draw on: %s", SDL_GetError()); return false; } From 30e69c518bc928bd0907c7bd8eac5f00c400f863 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 12:08:37 +0100 Subject: [PATCH 018/275] Codechange: [SDL2] Rework how palette is updated It now follows more what the Win32 driver does, and has far less exceptions and special casing. MakePalette creates the Palette and prepares surface. UpdatePalette updates the Palette. CheckPaletteAnim checks if UpdatePalette needs to be called and marks the whole screen dirty so DrawSurfaceToScreen will do a full redraw. --- src/video/sdl2_v.cpp | 79 +++++++++++++++++--------------------------- src/video/sdl2_v.h | 1 + 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 61edea6e00..28ce0f880d 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -73,7 +73,7 @@ void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) _num_dirty_rects++; } -static void UpdatePalette(bool init = false) +static void UpdatePalette() { SDL_Color pal[256]; @@ -86,8 +86,19 @@ static void UpdatePalette(bool init = false) SDL_SetPaletteColors(_sdl_palette, pal, _local_palette.first_dirty, _local_palette.count_dirty); SDL_SetSurfacePalette(_sdl_surface, _sdl_palette); +} - if (_sdl_surface != _sdl_real_surface && init) { +static void MakePalette() +{ + if (_sdl_palette == nullptr) { + _sdl_palette = SDL_AllocPalette(256); + if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError()); + } + + _local_palette = _cur_palette; + UpdatePalette(); + + if (_sdl_surface != _sdl_real_surface) { /* When using a shadow surface, also set our palette on the real screen. This lets SDL * allocate as many colors (or approximations) as * possible, instead of using only the default SDL @@ -110,33 +121,22 @@ static void UpdatePalette(bool init = false) */ SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette); } - - if (_sdl_surface != _sdl_real_surface && !init) { - /* We're not using real hardware palette, but are letting SDL - * approximate the palette during shadow -> screen copy. To - * change the palette, we need to recopy the entire screen. - * - * Note that this operation can slow down the rendering - * considerably, especially since changing the shadow - * palette will need the next blit to re-detect the - * best mapping of shadow palette colors to real palette - * colors from scratch. - */ - SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr); - SDL_UpdateWindowSurface(_sdl_window); - } } -static void InitPalette() +void VideoDriver_SDL::CheckPaletteAnim() { - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; + if (_cur_palette.count_dirty == 0) return; + _local_palette = _cur_palette; - UpdatePalette(true); + this->MakeDirty(0, 0, _screen.width, _screen.height); } -static void CheckPaletteAnim() +static void DrawSurfaceToScreen() { + PerformanceMeasurer framerate(PFE_VIDEO); + + if (_num_dirty_rects == 0) return; + if (_cur_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); @@ -157,18 +157,8 @@ static void CheckPaletteAnim() } _cur_palette.count_dirty = 0; } -} -static void DrawSurfaceToScreen() -{ - PerformanceMeasurer framerate(PFE_VIDEO); - - int n = _num_dirty_rects; - if (n == 0) return; - - _num_dirty_rects = 0; - - if (n > MAX_DIRTY_RECTS) { + if (_num_dirty_rects > MAX_DIRTY_RECTS) { if (_sdl_surface != _sdl_real_surface) { SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr); } @@ -176,13 +166,15 @@ static void DrawSurfaceToScreen() SDL_UpdateWindowSurface(_sdl_window); } else { if (_sdl_surface != _sdl_real_surface) { - for (int i = 0; i < n; i++) { + for (int i = 0; i < _num_dirty_rects; i++) { SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_real_surface, &_dirty_rects[i]); } } - SDL_UpdateWindowSurfaceRects(_sdl_window, _dirty_rects, n); + SDL_UpdateWindowSurfaceRects(_sdl_window, _dirty_rects, _num_dirty_rects); } + + _num_dirty_rects = 0; } static void DrawSurfaceToScreenThread() @@ -195,7 +187,6 @@ static void DrawSurfaceToScreenThread() _draw_signal->wait(*_draw_mutex); while (_draw_continue) { - CheckPaletteAnim(); /* Then just draw and wait till we stop */ DrawSurfaceToScreen(); _draw_signal->wait(lock); @@ -362,14 +353,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) _sdl_surface = _sdl_real_surface; } - if (_sdl_palette == nullptr) { - _sdl_palette = SDL_AllocPalette(256); - if (_sdl_palette == nullptr) { - DEBUG(driver, 0, "SDL_AllocPalette() failed: %s", SDL_GetError()); - return false; - } - } - /* Delay drawing for this cycle; the next cycle will redraw the whole screen */ _num_dirty_rects = 0; @@ -378,6 +361,8 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) _screen.pitch = _sdl_surface->pitch / (bpp / 8); _screen.dst_ptr = _sdl_surface->pixels; + MakePalette(); + /* When in full screen, we will always have the mouse cursor * within the window, even though SDL does not give us the * appropriate event to know this. */ @@ -385,7 +370,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) BlitterFactory::GetCurrentBlitter()->PostResize(); - InitPalette(); GameSizeChanged(); return true; } @@ -813,7 +797,7 @@ void VideoDriver_SDL::LoopOnce() if (_draw_mutex != nullptr) draw_lock.lock(); UpdateWindows(); - _local_palette = _cur_palette; + this->CheckPaletteAnim(); } else { /* Release the thread while sleeping */ if (_draw_mutex != nullptr) { @@ -837,7 +821,6 @@ void VideoDriver_SDL::LoopOnce() _draw_signal->notify_one(); } else { /* Oh, we didn't have threads, then just draw unthreaded */ - CheckPaletteAnim(); DrawSurfaceToScreen(); } } @@ -848,7 +831,7 @@ void VideoDriver_SDL::MainLoop() last_cur_ticks = cur_ticks; next_tick = cur_ticks + MILLISECONDS_PER_TICK; - CheckPaletteAnim(); + this->CheckPaletteAnim(); if (_draw_threaded) { /* Initialise the mutex first, because that's the thing we *need* diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h index a723256743..d1c4d957ca 100644 --- a/src/video/sdl2_v.h +++ b/src/video/sdl2_v.h @@ -50,6 +50,7 @@ private: void MainLoopCleanup(); bool CreateMainSurface(uint w, uint h, bool resize); bool CreateMainWindow(uint w, uint h); + void CheckPaletteAnim(); #ifdef __EMSCRIPTEN__ /* Convert a constant pointer back to a non-constant pointer to a member function. */ From 0e54c32452767edb46dc442ae1b88468494c6662 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 24 Jan 2021 12:23:09 +0100 Subject: [PATCH 019/275] Codechange: [SDL2] Use MakeDirty() to force a redraw The original code is "strictly correct", but just reads really weird, and we use MakeDirty() in several other places instead too. --- src/video/sdl2_v.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 28ce0f880d..aa7a23c728 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -655,7 +655,7 @@ int VideoDriver_SDL::PollEvent() case SDL_WINDOWEVENT: { if (ev.window.event == SDL_WINDOWEVENT_EXPOSED) { // Force a redraw of the entire screen. - _num_dirty_rects = MAX_DIRTY_RECTS + 1; + this->MakeDirty(0, 0, _screen.width, _screen.height); } else if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { int w = std::max(ev.window.data1, 64); int h = std::max(ev.window.data2, 64); From 1dda7d6486decf558d2ef848af3c22ee945801e6 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 31 Jan 2021 04:04:22 -0500 Subject: [PATCH 020/275] Fix: don't walk out of the map when trying to build tunnels (#8600) --- src/town_cmd.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index e87c4437f5..1aadd5927b 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1256,6 +1256,7 @@ static bool GrowTownWithTunnel(const Town* t, const TileIndex tile, const DiagDi /* Only tunnel under a mountain if the slope is continuous for at least 4 tiles. We want tunneling to be a last resort for large hills. */ TileIndex slope_tile = tile; for (uint8 tiles = 0; tiles < 4; tiles++) { + if (!IsValidTile(slope_tile)) return false; slope = GetTileSlope(slope_tile); if (slope != InclinedSlope(tunnel_dir) && !IsSteepSlope(slope) && !IsSlopeWithOneCornerRaised(slope)) return false; slope_tile += delta; From 7fbf705c41b2c902e5b2fa3f16cae421e42800b2 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 31 Jan 2021 10:36:07 +0100 Subject: [PATCH 021/275] Fix 2db88953: default Network Server List sorter put compatible servers in wrong order (#8626) If a server is compatible, it falls back to sorting by clients. This used to be in reverse, so full servers are on top. With the codechange commit, this was removed by accident, and as such empty servers were on top. This is silly. --- src/network/network_gui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index a2c2cac196..42915c410e 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -330,10 +330,9 @@ protected: if (r == 0) r = b->info.compatible - a->info.compatible; /* Passworded servers should be below unpassworded servers */ if (r == 0) r = a->info.use_password - b->info.use_password; - /* Finally sort on the number of clients of the server */ - if (r == 0) return NGameClientSorter(a, b); - return r < 0; + /* Finally sort on the number of clients of the server in reverse order. */ + return (r != 0) ? r < 0: !NGameClientSorter(a, b); } /** Sort the server list */ From 76a279ef685c8d9710450a413c8e80ebd5731c82 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 31 Jan 2021 09:27:17 -0500 Subject: [PATCH 022/275] Fix: [Emscripten] Pin Dockerfile to emsdk:2.0.10 to prevent patch failure (#8628) --- os/emscripten/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/emscripten/Dockerfile b/os/emscripten/Dockerfile index 1278a088ff..5184af6432 100644 --- a/os/emscripten/Dockerfile +++ b/os/emscripten/Dockerfile @@ -1,4 +1,4 @@ -FROM emscripten/emsdk +FROM emscripten/emsdk:2.0.10 COPY emsdk-liblzma.patch / RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch From 069fb5425302edc93a77ca54b3665a7102747f5a Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 31 Jan 2021 18:14:37 +0000 Subject: [PATCH 023/275] Update: Translations from eints estonian: 17 changes by siimsoni german: 410 changes by Wuzzy2 --- src/lang/estonian.txt | 34 +- src/lang/german.txt | 820 +++++++++++++++++++++--------------------- 2 files changed, 427 insertions(+), 427 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index d9512ad231..0761d8695d 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -645,7 +645,7 @@ STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION :{WHITE}Ettevõt STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Firmaväärtus STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Veotariifid -STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL :{TINY_FONT}{BLACK}Päevi teel +STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL :{TINY_FONT}{BLACK}Teelolekuaeg päevades STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Tasu 10 ühiku (või 10 000 liitri) kauba äraveo eest üle 20 ruudu STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Kõik sisse STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Kõik välja @@ -857,7 +857,7 @@ STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLAC STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}Rahvas tervitab. . .{}{STATION} terminali saabus esimene lennuk! STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}RONGIKOKKUPÕRGE!{}{COMMA} surid tules peale kokkusõitmist -STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}Rongikokkupõrge!{}Juht suri peale õnnetust tules +STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}Rongikokkupõrge!{}Juht hukkus kokkupõrgest põhjustatud tulekeras STR_NEWS_ROAD_VEHICLE_CRASH :{BIG_FONT}{BLACK}Mootorsõiduki kokkupõrge rongiga!{}{COMMA} inimest suri õnnetuses STR_NEWS_AIRCRAFT_CRASH :{BIG_FONT}{BLACK}Lennuõnnetus!{}{COMMA} hukkus tules. {STATION} suletud. STR_NEWS_PLANE_CRASH_OUT_OF_FUEL :{BIG_FONT}{BLACK}Lennuõnnetus!{}Lennukil lõppes kütus, {COMMA} surid tules! @@ -2226,7 +2226,7 @@ STR_NETWORK_ERROR_LOSTCONNECTION :{WHITE}Mitmikm STR_NETWORK_ERROR_SAVEGAMEERROR :{WHITE}Salvestatud mängu laadimine ebaõnnestus STR_NETWORK_ERROR_SERVER_START :{WHITE}Ei saa uut serverit alustada STR_NETWORK_ERROR_CLIENT_START :{WHITE}Ei õnnestu ühendada -STR_NETWORK_ERROR_TIMEOUT :{WHITE}#{NUM}. ühendus aegus +STR_NETWORK_ERROR_TIMEOUT :{WHITE}Ühendus nr {NUM} aegus STR_NETWORK_ERROR_SERVER_ERROR :{WHITE}Tekkis protokolliviga ja ühendus katkes STR_NETWORK_ERROR_WRONG_REVISION :{WHITE}Kliendi osa ei vasta serveri osaga STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Vale salasõna @@ -2288,7 +2288,7 @@ STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} li STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} liitus mänguga ({2:NUM}. klient) STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} liitus {2:NUM}. ettevõttega STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} liitus vaatlejatega -STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} alustas uue ettevõtte (#{2:NUM}) +STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} alustas uue ettevõtte (nr {2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} lahkus mängust ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} uus nimi on {STRING} STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} saatis {2:CURRENCY_LONG} ettevõttele {1:STRING} @@ -3387,7 +3387,7 @@ STR_FINANCES_SECTION_TRAIN_RUNNING_COSTS :{GOLD}Rongide k STR_FINANCES_SECTION_ROAD_VEHICLE_RUNNING_COSTS :{GOLD}Mootorsõidukite käituskulud STR_FINANCES_SECTION_AIRCRAFT_RUNNING_COSTS :{GOLD}Õhusõidukite käituskulud STR_FINANCES_SECTION_SHIP_RUNNING_COSTS :{GOLD}Laevade käituskulud -STR_FINANCES_SECTION_PROPERTY_MAINTENANCE :{GOLD}Taristu hooldamine +STR_FINANCES_SECTION_PROPERTY_MAINTENANCE :{GOLD}Omandi korrashoid STR_FINANCES_SECTION_TRAIN_INCOME :{GOLD}Rongide tulud STR_FINANCES_SECTION_ROAD_VEHICLE_INCOME :{GOLD}Mootorsõidukite tulud STR_FINANCES_SECTION_AIRCRAFT_INCOME :{GOLD}Õhusõidukite tulud @@ -3871,7 +3871,7 @@ STR_VEHICLE_STATUS_TRAIN_STUCK :{ORANGE}Vaba ra STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR :{ORANGE}Liiga pikk vahemaa järgmise sihtpunktini STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL :{LTBLUE}Siht: {STATION}, {VELOCITY} -STR_VEHICLE_STATUS_NO_ORDERS_VEL :{LTBLUE}Sihita, {VELOCITY} +STR_VEHICLE_STATUS_NO_ORDERS_VEL :{LTBLUE}Sihitu, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL :{LTBLUE}Suundub {WAYPOINT}, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL :{ORANGE}Suundub {DEPOT}, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL :{LTBLUE}Teenus kohas {DEPOT}, {VELOCITY} @@ -4007,7 +4007,7 @@ STR_ORDER_DROP_UNLOAD_IF_ACCEPTED :Mahalaadi nõud STR_ORDER_DROP_UNLOAD :Mahalaadi kõik STR_ORDER_DROP_TRANSFER :Ümberlaadi STR_ORDER_DROP_NO_UNLOADING :Ei mahalaadi -STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Valitud korralduse mahalaadimisprotseduuri muutmine +STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Valitud korralduse tühjendusprotseduuri muutmine STR_ORDER_REFIT :{BLACK}Ümberseadista STR_ORDER_REFIT_TOOLTIP :{BLACK}Vali, mis veoseliigile ümberseadistada. Ctrl+klõps kõrvaldab ümberseadistamise korralduse @@ -4074,9 +4074,9 @@ STR_ORDER_SERVICE_NON_STOP_AT :Hooldus ilma pe STR_ORDER_NEAREST_DEPOT :lähim STR_ORDER_NEAREST_HANGAR :lähim angaar -STR_ORDER_TRAIN_DEPOT :rongidepoos -STR_ORDER_ROAD_VEHICLE_DEPOT :sõidukidepoos -STR_ORDER_SHIP_DEPOT :laevaremonditehases +STR_ORDER_TRAIN_DEPOT :rongidepoo +STR_ORDER_ROAD_VEHICLE_DEPOT :maanteesõidukidepoo +STR_ORDER_SHIP_DEPOT :laevaremonditehas STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT :{STRING} {STRING} {STRING} STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT} @@ -4175,7 +4175,7 @@ STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Tühista STR_TIMETABLE_CHANGE_SPEED :{BLACK}Muuda kiiruspiirangut STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Muuda märgitud korralduse kiiruspiirangut -STR_TIMETABLE_CLEAR_SPEED :{BLACK}Tühjenda kiiruselimiit +STR_TIMETABLE_CLEAR_SPEED :{BLACK}Kustuta kiiruspiirang STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Eemalda märgitud korralduse kiiruspiirang STR_TIMETABLE_RESET_LATENESS :{BLACK}Tühista hilinemisarvesti @@ -4202,7 +4202,7 @@ STR_DATE_YEAR_TOOLTIP :{BLACK}Vali aas # AI debug window -STR_AI_DEBUG :{WHITE}Arvutivea otsing +STR_AI_DEBUG :{WHITE}AI/GameScripti debugimine STR_AI_DEBUG_NAME_AND_VERSION :{BLACK}{STRING} (ver{NUM}) STR_AI_DEBUG_NAME_TOOLTIP :{BLACK}Skripti nimi STR_AI_DEBUG_SETTINGS :{BLACK}Seaded @@ -5127,17 +5127,17 @@ STR_FORMAT_BUOY_NAME :{TOWN} Poi STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Poi nr. {COMMA} STR_FORMAT_COMPANY_NUM :(Ettevõte {COMMA}) STR_FORMAT_GROUP_NAME :Jagu {COMMA} -STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} nr {COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN} meldepunkt -STR_FORMAT_WAYPOINT_NAME_SERIAL :Meldepunkt {TOWN} #{COMMA} +STR_FORMAT_WAYPOINT_NAME_SERIAL :Meldepunkt {TOWN} nr {COMMA} STR_FORMAT_DEPOT_NAME_TRAIN :{TOWN} Rongi depoo -STR_FORMAT_DEPOT_NAME_TRAIN_SERIAL :{TOWN} Rongi depoo #{COMMA} +STR_FORMAT_DEPOT_NAME_TRAIN_SERIAL :{TOWN} Rongi depoo nr {COMMA} STR_FORMAT_DEPOT_NAME_ROAD_VEHICLE :{TOWN} Teesõidukite depoo -STR_FORMAT_DEPOT_NAME_ROAD_VEHICLE_SERIAL :{TOWN} Teesõidukite depoo #{COMMA} +STR_FORMAT_DEPOT_NAME_ROAD_VEHICLE_SERIAL :{TOWN} Teesõidukite depoo nr {COMMA} STR_FORMAT_DEPOT_NAME_SHIP :{TOWN} Laeva depoo -STR_FORMAT_DEPOT_NAME_SHIP_SERIAL :{TOWN} Laeva depoo #{COMMA} +STR_FORMAT_DEPOT_NAME_SHIP_SERIAL :{TOWN} Laeva depoo nr {COMMA} STR_FORMAT_DEPOT_NAME_AIRCRAFT :{STATION} Hangaar STR_UNKNOWN_STATION :tundmatu jaam diff --git a/src/lang/german.txt b/src/lang/german.txt index 30abbbb445..4cde7ed7c1 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -248,7 +248,7 @@ STR_TOOLTIP_RESIZE :{BLACK}Klicken STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Zwischen Fenstergrößen umschalten STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST :{BLACK}Bildlaufleiste: In der Liste auf- und abwärts blättern STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST :{BLACK}Bildlaufleiste: In der Liste nach links und rechts blättern -STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}Gebäude etc. von einem Planquadrat abreißen. Strg wählt ein diagonales Gebiet aus. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}Gebäude etc. von einem Planquadrat abreißen. Strg wählt ein diagonales Gebiet aus. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um # Show engines button STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN :{BLACK}Alle einblenden @@ -370,9 +370,9 @@ STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}Städte STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}Industrie errichten STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}Straße bauen STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}Straßenbahngleise bauen -STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}Bäume pflanzen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}Bäume pflanzen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}Schild aufstellen -STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Objekt platzieren. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Objekt platzieren. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um ############ range for SE file menu starts STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO :Szenario speichern @@ -394,7 +394,7 @@ STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Städtenamen an STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Stationsnamen anzeigen STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Wegpunktnamen anzeigen STR_SETTINGS_MENU_SIGNS_DISPLAYED :Schilder anzeigen -STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :Fremde Stationsnamen & Schilder zeigen +STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :Fremde Stationsnamen u. Schilder zeigen STR_SETTINGS_MENU_FULL_ANIMATION :Vollständige Animation STR_SETTINGS_MENU_FULL_DETAIL :Vollständige Detailansicht STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS :Transparenz für Gebäude @@ -485,7 +485,7 @@ STR_NEWS_MENU_DELETE_ALL_MESSAGES :Alle Nachrichte STR_ABOUT_MENU_LAND_BLOCK_INFO :Gebietsinformationen STR_ABOUT_MENU_SEPARATOR : STR_ABOUT_MENU_TOGGLE_CONSOLE :Konsole öffnen/schließen -STR_ABOUT_MENU_AI_DEBUG :KI / Skript-Debug +STR_ABOUT_MENU_AI_DEBUG :KI-/Skript-Debug STR_ABOUT_MENU_SCREENSHOT :Screenshot (Standard: Strg+S) STR_ABOUT_MENU_SHOW_FRAMERATE :Bildwiederholrate anzeigen STR_ABOUT_MENU_ABOUT_OPENTTD :Über OpenTTD @@ -661,8 +661,8 @@ STR_MUSIC_TRACK_NONE :{TINY_FONT}{DKG STR_MUSIC_TRACK_DIGIT :{TINY_FONT}{DKGREEN}{ZEROFILL_NUM} STR_MUSIC_TITLE_NONE :{TINY_FONT}{DKGREEN}------ STR_MUSIC_TITLE_NOMUSIC :{TINY_FONT}{DKGREEN}Keine Musik verfügbar -STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}"{STRING}" -STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Track +STR_MUSIC_TITLE_NAME :{TINY_FONT}{DKGREEN}„{STRING}“ +STR_MUSIC_TRACK :{TINY_FONT}{BLACK}Titel STR_MUSIC_XTITLE :{TINY_FONT}{BLACK}Titel STR_MUSIC_SHUFFLE :{TINY_FONT}{BLACK}Mischen STR_MUSIC_PROGRAM :{TINY_FONT}{BLACK}Programm @@ -682,15 +682,15 @@ STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION :{BLACK}Zeige Mu # Playlist window STR_PLAYLIST_MUSIC_SELECTION_SETNAME :{WHITE}Musikprogramm - „{STRING}“ -STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} "{STRING}" -STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Track Inhalt -STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - '{STRING}' +STR_PLAYLIST_TRACK_NAME :{TINY_FONT}{LTBLUE}{ZEROFILL_NUM} „{STRING}“ +STR_PLAYLIST_TRACK_INDEX :{TINY_FONT}{BLACK}Titelindex +STR_PLAYLIST_PROGRAM :{TINY_FONT}{BLACK}Programm - „{STRING}“ STR_PLAYLIST_CLEAR :{TINY_FONT}{BLACK}Bereinigen STR_PLAYLIST_CHANGE_SET :{BLACK}Set ändern STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1 :{BLACK}Lösche laufendes Programm (nur für Benutzerdefiniert 1 und 2) STR_PLAYLIST_TOOLTIP_CHANGE_SET :{BLACK}Ein anderes Musik-Set auswählen) -STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klicke auf einen Musiktitel, um ihn in das laufende Programm zu übernehmen (nur für Benutzerdefiniert 1 und 2) -STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Klicke auf einen Musiktitel, um ihn aus der aktuellen Liste zu entfernen (nur für Benutzerdefiniert 1 und 2) +STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Klicken Sie auf einen Musiktitel, um ihn in das laufende Programm zu übernehmen (nur für Benutzerdefiniert 1 und 2) +STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Klicken Sie auf einen Musiktitel, um ihn aus der aktuellen Liste zu entfernen (nur für Benutzerdefiniert 1 und 2) # Highscore window STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Beste Firmen, die {NUM} erreichten @@ -865,7 +865,7 @@ STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD :{WHITE}{VEHICLE STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND :{WHITE}{VEHICLE} wird sehr alt und sollte dringend ersetzt werden STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE} findet keinen Weg zum Vorankommen STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} hat sich verirrt -STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}Der Ertrag von {VEHICLE} lag im letzten Jahr bei {CURRENCY_LONG} +STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}Der Ertrag von {VEHICLE} lag im letzten Jahr bei{}{CURRENCY_LONG} STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} kann sein Ziel nicht erreichen, da es außer Reichweite liegt STR_NEWS_ORDER_REFIT_FAILED :{WHITE}Umrüstung fehlgeschlagen bei {VEHICLE} @@ -907,7 +907,7 @@ STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Währung STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Währung auswählen ############ start of currency region -STR_GAME_OPTIONS_CURRENCY_GBP :Englische Pfund (GBP) +STR_GAME_OPTIONS_CURRENCY_GBP :Britische Pfund (GBP) STR_GAME_OPTIONS_CURRENCY_USD :US-Dollar (USD) STR_GAME_OPTIONS_CURRENCY_EUR :Euro (EUR) STR_GAME_OPTIONS_CURRENCY_JPY :Japanische Yen (JPY) @@ -918,7 +918,7 @@ STR_GAME_OPTIONS_CURRENCY_CZK :Tschechische Kr STR_GAME_OPTIONS_CURRENCY_DEM :Deutsche Mark (DEM) STR_GAME_OPTIONS_CURRENCY_DKK :Dänische Kronen (DKK) STR_GAME_OPTIONS_CURRENCY_ESP :Spanische Peseten (ESP) -STR_GAME_OPTIONS_CURRENCY_FIM :Finnische Mark(FIM) +STR_GAME_OPTIONS_CURRENCY_FIM :Finnische Mark (FIM) STR_GAME_OPTIONS_CURRENCY_FRF :Französische Francs (FRF) STR_GAME_OPTIONS_CURRENCY_GRD :Griechische Drachmen (GRD) STR_GAME_OPTIONS_CURRENCY_HUF :Ungarische Forint (HUF) @@ -938,10 +938,10 @@ STR_GAME_OPTIONS_CURRENCY_EEK :Estnische Krone STR_GAME_OPTIONS_CURRENCY_LTL :Litauische Litas (LTL) STR_GAME_OPTIONS_CURRENCY_KRW :Südkoreanischer Won (KRW) STR_GAME_OPTIONS_CURRENCY_ZAR :Südafrikanischer Rand (ZAR) -STR_GAME_OPTIONS_CURRENCY_CUSTOM :Eigene... +STR_GAME_OPTIONS_CURRENCY_CUSTOM :Eigene ... STR_GAME_OPTIONS_CURRENCY_GEL :Georgischer Lari (GEL) STR_GAME_OPTIONS_CURRENCY_IRR :Iranischer Rial (IRR) -STR_GAME_OPTIONS_CURRENCY_RUB :Russische Rubel (RUB) +STR_GAME_OPTIONS_CURRENCY_RUB :Neue Russische Rubel (RUB) STR_GAME_OPTIONS_CURRENCY_MXN :Mexikanischer Peso (MXN) STR_GAME_OPTIONS_CURRENCY_NTD :Neuer Taiwan-Dollar (NTD) STR_GAME_OPTIONS_CURRENCY_CNY :Chinesischer Yuan (CNY) @@ -1125,11 +1125,11 @@ STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Alles ei STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(keine Erklärung verfügbar) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Standardwert: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Art der Einstellung: {ORANGE}{STRING} -STR_CONFIG_SETTING_TYPE_CLIENT :Nutzer-Einstellung (nicht in Spielständen gespeichert; beeinflußt alle Spiele) -STR_CONFIG_SETTING_TYPE_GAME_MENU :Karten-Einstellung (in Spielständen gespeichert; beeinflußt nur neue Spiele) -STR_CONFIG_SETTING_TYPE_GAME_INGAME :Karten-Einstellung (im Spielstand gespeichert; beeinflußt nur aktuelles Spiel) -STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Firmen-Einstellung (in Spielständen gespeichert; beeinflußt nur neue Spiele) -STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Firmen-Einstellung (im Spielstand gespeichert; beeinflußt nur aktuelle Firma) +STR_CONFIG_SETTING_TYPE_CLIENT :Nutzer-Einstellung (nicht in Spielständen gespeichert; beeinflusst alle Spiele) +STR_CONFIG_SETTING_TYPE_GAME_MENU :Karten-Einstellung (in Spielständen gespeichert; beeinflusst nur neue Spiele) +STR_CONFIG_SETTING_TYPE_GAME_INGAME :Karten-Einstellung (im Spielstand gespeichert; beeinflusst nur aktuelles Spiel) +STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Firmen-Einstellung (in Spielständen gespeichert; beeinflusst nur neue Spiele) +STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Firmen-Einstellung (im Spielstand gespeichert; beeinflusst nur aktuelle Firma) STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategorie: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Art: @@ -1142,11 +1142,11 @@ STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Einstellungen m STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT :{BLACK}Schränkt die Liste auf bestimme Einstellungs-Typen ein STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL :Alle Einstellungen -STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT :Nutzer-Einstellungen (nicht in Spielständen gespeichert; beeinflußt alle Spiele) -STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :Spiel-spezifische Einstellungen (im Spielstand gespeichert; beeinflußt nur neue Spiele) -STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Spiel-spezifische Einstellungen (im Spielstand gespeichert; beeinflußt nur aktuelles Spiel) -STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Firmeneinstellungen (im Spielstand gesichert; beeinflußt nur neue Spiele) -STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Firmeneinstellungen (im Spielstand gesichert; beeinflußt nur die aktuelle Firma) +STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT :Nutzer-Einstellungen (nicht in Spielständen gespeichert; beeinflusst alle Spiele) +STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :Spiel-spezifische Einstellungen (im Spielstand gespeichert; beeinflusst nur neue Spiele) +STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Spiel-spezifische Einstellungen (im Spielstand gespeichert; beeinflusst nur aktuelles Spiel) +STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Firmeneinstellungen (im Spielstand gesichert; beeinflusst nur neue Spiele) +STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Firmeneinstellungen (im Spielstand gesichert; beeinflusst nur die aktuelle Firma) STR_CONFIG_SETTING_CATEGORY_HIDES :{BLACK}Um alle Suchergebnisse anzuzeigen, setze{}{SILVER}Kategorie {BLACK}auf {WHITE}{STRING} STR_CONFIG_SETTING_TYPE_HIDES :{BLACK}Um alle Suchergebnisse anzuzeigen, setze{}{SILVER}Typ {BLACK}auf {WHITE}Alle Arten von Einstellungen STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Zeige alle Suchergebnisse an indem{}{SILVER}Kategorie {BLACK}auf {WHITE}{STRING} {BLACK}und {SILVER}Art {BLACK}auf {WHITE}Alle Arten von Einstellungen @@ -1171,13 +1171,13 @@ STR_CONFIG_SETTING_HORIZONTAL_POS_RIGHT :Rechts STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN :Kreditlimit bei Spielbeginn: {STRING} STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN_HELPTEXT :Maximaler Kredit für eine Firma (ohne Berücksichtigung der Inflation) STR_CONFIG_SETTING_INTEREST_RATE :Zinssatz: {STRING} -STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Zinssatz für Kredite; beeinflußt auch die Inflation, falls aktiv +STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Zinssatz für Kredite; beeinflusst auch die Inflation, falls aktiv STR_CONFIG_SETTING_RUNNING_COSTS :Betriebskosten: {STRING} STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Stellt die Höhe der Unterhalts- und Betriebskosten für Fahrzeuge und Infrastruktur ein STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Baugeschwindigkeit: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Begrenzt der eingestellten Baugeschwindigkeit entsprechend die Anzahl der Bau-Aktionen der KIs STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Fahrzeugpannen: {STRING} -STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Einstellen wie oft unzureichend gewartete Fahrzeuge Pannen haben können +STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Einstellen, wie oft unzureichend gewartete Fahrzeuge Pannen haben können STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subventions-Multiplikator: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Einstellen, wieviel für subventionierte Verbindungen gezahlt wird STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Baukosten: {STRING} @@ -1195,7 +1195,7 @@ STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :Maximale Höhe STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT :Setze die maximal erlaubte Höhe für Berge auf der Karte STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Die maximale Höhe der Karte kann nicht auf diesen Wert gesetzt werden. Mindestens ein Berg auf der Karte ist höher. STR_CONFIG_SETTING_AUTOSLOPE :Landschaftsbau unter Gebäuden, Gleisen, usw. erlauben: {STRING} -STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Erlaube Erdbauarbeiten unter Gebäuden oder Infrastruktur ohne sie zu entfernen +STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Erlaube Erdbauarbeiten unter Gebäuden oder Infrastruktur, ohne sie zu entfernen STR_CONFIG_SETTING_CATCHMENT :Verschiedene Stationstypen haben unterschiedlich große Einzugsgebiete: {STRING} STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Wird diese Option eingeschaltet, besitzen unterschiedliche Stationsarten bzw. Flughäfen unterschiedlich große Einzugsgebiete STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Firmenstationen können Industrien mit integrierter Haltestelle bedienen: {STRING} @@ -1281,7 +1281,7 @@ STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :Bus- und Lkw-Ha STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :Erlaubt die Errichtung von Bus- und Lkw-Haltestellen auf städtischen Straßen STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :Bus- und Lkw-Haltestellen auf Straßen von Mitbewerbern erlauben: {STRING} STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :Erlaube die Errichtung von Bus- und Lkw-Haltestellen auf Straßen, die Mitbewerbern gehören -STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Diese Einstellung kann nicht geändert werden solange Fahrzeuge im Spiel sind +STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Diese Einstellung kann nicht geändert werden, solange Fahrzeuge im Spiel sind STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :Instandhaltung der Infrastruktur: {STRING} STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :Unterhaltskosten für Infrastruktur einschalten. Die Unterhaltskosten wachsen mit zunehmender Netzwerkgröße überproportional an, so dass sie größere Firmen stärker belasten als kleinere @@ -1301,7 +1301,7 @@ STR_CONFIG_SETTING_ORDER_REVIEW_ON :Für alle Fahrz STR_CONFIG_SETTING_WARN_INCOME_LESS :Warnen, wenn Einnahmen eines Fahrzeuges negativ sind: {STRING} STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT :Zeige Nachrichten, wenn ein Fahrzeug im letzten Kalenderjahr keinen Gewinn erwirtschaftet hat STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Fahrzeuge veralten nie: {STRING} -STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :Erlaube, dass Fahrzeuge nach ihrem Einführungsdatum ewig verfügbar bleiben +STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :Erlauben, dass Fahrzeuge nach ihrem Einführungsdatum ewig verfügbar bleiben STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Fahrzeuge automatisch erneuern, wenn sie alt werden: {STRING} STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :Erneuere Fahrzeuge automatisch gemäß der Regeln für Erneuerung, wenn sie ihr Maximalalter erreicht haben. STR_CONFIG_SETTING_AUTORENEW_MONTHS :Automatisches Erneuern, wenn das Fahrzeug {STRING} dem Maximalalter @@ -1311,7 +1311,7 @@ STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :{COMMA} Monat{P STR_CONFIG_SETTING_AUTORENEW_MONEY :Minimaler Kontostand für automatisches Erneuern: {STRING} STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Geldbetrag, der nach der automatischen Ersetzung eines Fahrzeuges mindestens noch übrig bleiben muss. Ansonsten findet keine automatische Ersetzung statt STR_CONFIG_SETTING_ERRMSG_DURATION :Anzeigedauer für Fehlermeldungen: {STRING} -STR_CONFIG_SETTING_ERRMSG_DURATION_HELPTEXT :Anzeigedauer für Fehlermeldungen in einem roten Fenster. Bedenke, dass einige (kritische) Fehlermeldungen nicht automatisch nach dieser Dauer geschlossen werden sondern manuell geschlossen werden müssen +STR_CONFIG_SETTING_ERRMSG_DURATION_HELPTEXT :Anzeigedauer für Fehlermeldungen in einem roten Fenster. Bedenken Sie, dass einige (kritische) Fehlermeldungen nicht automatisch nach dieser Dauer geschlossen werden, sondern manuell geschlossen werden müssen STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE :{COMMA} Sekunde{P 0 "" n} STR_CONFIG_SETTING_HOVER_DELAY :Zeige kurzen Hilfetext: {STRING} STR_CONFIG_SETTING_HOVER_DELAY_HELPTEXT :Einstellen, wie lange man zum Aufruf von Hilfetexten zur Erklärung der Funktionen im Spiel mit dem Mauszeiger über der gewünschten Stelle stehenbleiben muss. Alternativ werden die Hilfetexte bei einem Rechtsklick sofort angezeigt, wenn dieser Wert auf 0 gesetzt wird. @@ -1327,7 +1327,7 @@ STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Eine Textzeile STR_CONFIG_SETTING_LANDSCAPE :Landschaftstyp: {STRING} STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Landschaftstypen definieren grundlegende Spielszenarien mit verschiedenen Frachtarten und Bedingungen für das Wachstum von Städten. Mit NewGRFs und Spielskripten können diese allerdings genauer angepasst werden STR_CONFIG_SETTING_LAND_GENERATOR :Algorithmus zur Landschaftserzeugung: {STRING} -STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Der orginale Generator hängt von den verwendeten Basisgrafiken ab und setzt vorgefertigte Landschaftsformen zusammen. terraGenesis ist ein auf Perlinrauschen basierter Generator mit erweiterten Einstellmöglichkeiten +STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :Der orginale Generator hängt von den verwendeten Basisgrafiken ab und setzt vorgefertigte Landschaftsformen zusammen. TerraGenesis ist ein auf Perlinrauschen basierter Generator mit erweiterten Einstellmöglichkeiten STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Original STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Landschaftstyp: {STRING} @@ -1359,7 +1359,7 @@ STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Drehung der Rel STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Nach links STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Nach rechts STR_CONFIG_SETTING_SE_FLAT_WORLD_HEIGHT :Höhenstufe des Spielfeldes in einem flachen Szenario: {STRING} -STR_CONFIG_SETTING_EDGES_NOT_EMPTY :{WHITE}Ein oder mehrere Felder am nördlichen Spielfeldrand sind nicht leer +STR_CONFIG_SETTING_EDGES_NOT_EMPTY :{WHITE}Eines oder mehrere Felder am nördlichen Spielfeldrand sind nicht leer STR_CONFIG_SETTING_EDGES_NOT_WATER :{WHITE}Eines oder mehrere Felder am Spielfeldrand sind nicht Wasser STR_CONFIG_SETTING_STATION_SPREAD :Maximale Stationsgröße: {STRING} @@ -1398,38 +1398,38 @@ STR_CONFIG_SETTING_SCROLLWHEEL_OFF :Aus STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER :Mausradgeschwindigkeit auf dem Spielfeld: {STRING} STR_CONFIG_SETTING_SCROLLWHEEL_MULTIPLIER_HELPTEXT :Lege die Empfindlichkeit des Mausrads beim Scrollen fest STR_CONFIG_SETTING_OSK_ACTIVATION :Bildschirmtastatur: {STRING} -STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT :Wählen der Methode, um die On-Screen-Tastatur für die Texteingabe in Eingabefeldern bei der Verwendung von Zeigegeräten zu aktivieren. Dieses ist für kleine Geräte ohne tatsächliche Tastatur gedacht +STR_CONFIG_SETTING_OSK_ACTIVATION_HELPTEXT :Wählen der Methode, um die Bildschirmtastatur für die Texteingabe in Eingabefeldern bei der Verwendung von Zeigegeräten zu aktivieren. Dieses ist für kleine Geräte ohne tatsächliche Tastatur gedacht STR_CONFIG_SETTING_OSK_ACTIVATION_DISABLED :Deaktiviert -STR_CONFIG_SETTING_OSK_ACTIVATION_DOUBLE_CLICK :Doppel-Klick -STR_CONFIG_SETTING_OSK_ACTIVATION_SINGLE_CLICK_FOCUS :Einfach-Klick (wenn hervorgehoben) -STR_CONFIG_SETTING_OSK_ACTIVATION_SINGLE_CLICK :Einfach-Klick (sofort) +STR_CONFIG_SETTING_OSK_ACTIVATION_DOUBLE_CLICK :Doppelklick +STR_CONFIG_SETTING_OSK_ACTIVATION_SINGLE_CLICK_FOCUS :Ein Klick (wenn hervorgehoben) +STR_CONFIG_SETTING_OSK_ACTIVATION_SINGLE_CLICK :Ein Klick (sofort) STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU :Rechtsklick-Emulation: {STRING} STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_HELPTEXT :Lege die Methode, die rechte Maustaste zu emulieren, fest -STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Kommando+Klick +STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_COMMAND :Befehlstaste+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_CONTROL :Strg+Klick STR_CONFIG_SETTING_RIGHT_MOUSE_BTN_EMU_OFF :Aus STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE :Fenster mit Rechtsklick schließen: {STRING} -STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Schließt ein Fenster mittels Rechts-Klick. Schaltet Tooltip mit Rechts-Klick ab! +STR_CONFIG_SETTING_RIGHT_MOUSE_WND_CLOSE_HELPTEXT :Schließt ein Fenster mittels Rechtsklick. Schaltet Tooltip mit Rechtsklick ab! -STR_CONFIG_SETTING_AUTOSAVE :Autosave: {STRING} -STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Wähle das Interval zwischen automatischen Speicherungen +STR_CONFIG_SETTING_AUTOSAVE :Autosicherung: {STRING} +STR_CONFIG_SETTING_AUTOSAVE_HELPTEXT :Interval zwischen automatischen Speicherungen wählen -STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Verwende {STRING} Datumsformat beim Benennen der Spielstände -STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT :Lege das Datumsformat für Spielstandsdateien fest -STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG :langes (25. Dez 2008) -STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_SHORT :kurzes (25-12-2008) -STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_ISO :ISO (2008-12-25) +STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES :Datumsformat für Spielstandsnamen: {STRING} +STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_HELPTEXT :Das Datumsformat für Spielstandsdateien festlegen +STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG :lang (31. Dez 2008) +STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_SHORT :kurz (31.12.2008) +STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_ISO :ISO (2008-12-31) STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME :Automatische Pause bei Spielstart: {STRING} STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Starte ein Spiel im Pausenmodus; dies erlaubt vor Spielstart, die Karte ausführlich zu betrachten. -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Erlauben während angehaltenen Spiels: {STRING} +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Während der Pause {STRING} erlauben STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Lege fest, welche Tätigkeiten im Pausenmodus durchgeführt werden dürfen -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Keine Tätigkeiten -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Alle Tätigkeiten, die keine Bautätigkeiten sind -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Alle Tätigkeiten außer Landschaftsbau -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Alle Tätigkeiten +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :keine Tätigkeiten +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :alle Tätigkeiten, die keine Bautätigkeiten sind, +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :alle Tätigkeiten außer Landschaftsbau +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :alle Tätigkeiten STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Erweiterte Fahrzeugliste benutzen: {STRING} STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Nutze erweiterte Fahrzeuglisten für die Gruppierung von Fahrzeugen STR_CONFIG_SETTING_LOADING_INDICATORS :Ladestandanzeiger verwenden: {STRING} @@ -1446,13 +1446,13 @@ STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :Erster verfügb STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Letzter verfügbarer STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_MOST_USED :Meistbenutzter STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Reservierte Gleise hervorheben: {STRING} -STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Hebt reservierte Fahrabschnitte hervor, um bei der Problemanalyse zu helfen, wenn Züge die Einfahrt in Pfad-basierte Streckenabschnitte verweigern +STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Hebt reservierte Fahrabschnitte hervor, um bei der Problemanalyse zu helfen, wenn Züge die Einfahrt in pfadbasierte Streckenabschnitte verweigern STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Belasse Bauwerkzeuge aktiv nach Benutzung: {STRING} STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Die Bauwerkzeuge für Brücken, Tunnel, etc. nach Benutzung weiter aktiviert lassen STR_CONFIG_SETTING_EXPENSES_LAYOUT :Zwischensummen für Kategorien bei Firmenausgaben:{STRING} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Lege das Layout für das Fenster mit den Firmenausgaben fest STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Automatische Entfernung von Signalen während der Errichtung von Bahntrassen: {STRING} -STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatische Entfernung von Signalen während der Errichtung der Bahntrasse, wenn diese sich im Weg befinden.Hinweis: Dies kann zu Unfällen führen! +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatische Entfernung von Signalen während der Errichtung der Bahntrasse, wenn diese sich im Weg befinden. Hinweis: Dies kann zu Unfällen führen! STR_CONFIG_SETTING_SOUND_TICKER :Nachrichtenticker: {STRING} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Soundeffekte für Kurzfassungen von Nachrichten abspielen (Ticker) @@ -1501,7 +1501,7 @@ STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :KI im Mehrspiel STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Erlaube die Teilnahme von Computerspielern im Mehrspielermodus STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :Rechenoperationen, bevor das Skript angehalten wird: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maximale Anzahl Rechenschritte, die ein Skript in einer Runde zur Verfügung hat -STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :Maximaler Arbeitsspeicher pro Script: {STRING} +STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :Maximaler Arbeitsspeicher pro Skript: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_HELPTEXT :Wie viel Arbeitsspeicher ein Script maximal benutzen darf bevor es terminiert wird. Diese Wert muss eventuell vergrößert werden für größere Maps. STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY_VALUE :{COMMA} MiB @@ -1545,7 +1545,7 @@ STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_OTHER_HELPTEXT :Zeitung anzeige STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_UNSERVED :Produktionsänderungen anderer Industrien: {STRING} STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_UNSERVED_HELPTEXT :Zeitung anzeigen, wenn die Produktion von Industrien sich ändert, die von keiner Firma bedient werden STR_CONFIG_SETTING_NEWS_ADVICE :Rat / Informationen zu Fahrzeugen der Firma: {STRING} -STR_CONFIG_SETTING_NEWS_ADVICE_HELPTEXT :Nachrichten anzeigen, wenn Fahrzeuge Aufmerksamkeit benötigen (wie fehlerhafte Aufträge, mangelnde Wartung,...) +STR_CONFIG_SETTING_NEWS_ADVICE_HELPTEXT :Nachrichten anzeigen, wenn Fahrzeuge Aufmerksamkeit benötigen STR_CONFIG_SETTING_NEWS_NEW_VEHICLES :Neue Fahrzeuge: {STRING} STR_CONFIG_SETTING_NEWS_NEW_VEHICLES_HELPTEXT :Zeitung anzeigen, wenn neue Fahrzeugtypen verfügbar werden STR_CONFIG_SETTING_NEWS_CHANGES_ACCEPTANCE :Änderungen angenommener Fracht: {STRING} @@ -1563,7 +1563,7 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Farbige Nachric STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Jahr in dem die Zeitung in Farbe herausgebracht wird. Vor diesem Jahr erscheint sie in Schwarz-Weiß-Druck STR_CONFIG_SETTING_STARTING_YEAR :Startdatum: {STRING} STR_CONFIG_SETTING_ENDING_YEAR :Beurteilungsjahr der Firma: {STRING} -STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Jahr in dem das Spiel zwecks Beurteilung endet. Am Ende diesen Jahres wird die Punktezahl der Firma ermittelt und die Bestenliste wird angezeigt, es kann danach aber noch weitergespielt werden.{}Wenn dieser Wert kleiner als das Anfangsjahr ist, wird die Bestenliste nie angezeigt. +STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Jahr, in dem das Spiel zwecks Beurteilung endet. Am Ende diesen Jahres wird die Punktezahl der Firma ermittelt und die Bestenliste wird angezeigt, es kann danach aber noch weitergespielt werden.{}Wenn dieser Wert kleiner als das Anfangsjahr ist, wird die Bestenliste nie angezeigt. STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM} STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Nie STR_CONFIG_SETTING_ECONOMY_TYPE :Wirtschaftstyp: {STRING} @@ -1578,7 +1578,7 @@ STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT :Setze das minim STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Prozentsatz des Profits für Teilstrecken: {STRING} STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Um das Einkommen der einzelnen Fahrzeuge einer Lieferkette ungefähr abschätzen zu können, wird vom Transporterlös bei Ablieferung einer Fracht der gewählte Prozentsatz den Zulieferfahrzeugen zugeschlagen STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Signalabstand beim Ziehen: {STRING} -STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Lege den Abstand fest, in dem Signale auf Gleisen bis zum nächsten Hindernis (Signal, Weiche) gebaut werden, wenn sie gezogen werden +STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Abstand festlegen, in dem Signale auf Gleisen bis zum nächsten Hindernis (Signal, Weiche) gebaut werden, wenn sie gezogen werden STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE :{COMMA} Feld{P 0 "" er} STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE :Signalabstand nach Lücken (durch Tunnel, Brücken) nicht verkürzen : {STRING} STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE_HELPTEXT :Lege das Verhalten beim Bau von Signalen mit Strg+Ziehen fest. Wenn eingeschaltet, werden Signale immer im ausgewählten Signalabstand gebaut. Kann ein Signal wegen einer Brücke oder eines Tunnels nicht gebaut werden, wird es ausgelassen. Ist diese Option ausgeschaltet, wird das Signal in diesem Fall nicht ausgelassen, sondern vor die Brücke bzw. den Tunnel gesetzt. Allerdings verschiebt sich dadurch die Position der folgenden Signale, was bei zweigleisigen Strecken dazu führen kann, dass die Signale nicht auf gleicher Höhe gesetzt werden. @@ -1675,7 +1675,7 @@ STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :„Symmetrisch STR_CONFIG_SETTING_DISTRIBUTION_MAIL :Verteilungsschema für Post: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :„Symmetrisch“ heißt, dass etwa die selbe Menge Post von einer Station A zu einer anderen Station B geschickt wird, wie von B nach A. „Asymmetrisch“ heißt, dass Post in beliebigen Mengen hin- und her geschickt werden kann. „Manuell“ heißt, dass keine automatische Verteilung der Post stattfindet. STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :Verteilungsschema für Wertsachen: {STRING} -STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Werttransporte umfassen Wertsachen im gemäßigten, Diamanten im subtropischen und Gold im subarktischen Klima. NewGRFs könnte dies ändern. „Symmetrisch“ bedeutet, dass etwa dieselbe Anzahl von Station A nach Station B transportiert wird wie umgekehrt von B nach A. „Asymmetrisch“ bedeutet, dass eine unteschiedliche Menge in die jeweiligen Richtungen gesendet wird. „Manuell“ bedeudeutet, dass keine automatische Verteilung stattfindet. Es wird die Einstellung „asymmetrisch“ oder „manuell“ im subarktischen Gebiet empfohlen, da Banken kein Gold bzw. Diamanten zu den Minen senden. Für das gemäßigte und subtropische Klima kann die Einstellung „symmetrisch“ genommen werden, da Banken Wertsachen untereinander versenden. +STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Werttransporte umfassen Wertsachen im gemäßigten, Diamanten im subtropischen und Gold im subarktischen Klima. NewGRFs könnten dies ändern. „Symmetrisch“ bedeutet, dass etwa dieselbe Anzahl von Station A nach Station B transportiert wird wie umgekehrt von B nach A. „Asymmetrisch“ bedeutet, dass eine unterschiedliche Menge in die jeweiligen Richtungen gesendet wird. „Manuell“ bedeutet, dass keine automatische Verteilung stattfindet. Es wird die Einstellung „asymmetrisch“ oder „manuell“ im subarktischen Gebiet empfohlen, da Banken kein Gold bzw. Diamanten zu den Minen senden. Für das gemäßigte und subtropische Klima kann die Einstellung „symmetrisch“ genommen werden, da Banken Wertsachen untereinander versenden. STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Verteilungsschema für sonstige Frachtarten: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :„Symmetrisch“ heißt, dass etwa die selbe Menge Waren von einer Station A zu einer anderen Station B geschickt wird, wie von B nach A. „Asymmetrisch“ heißt, dass Waren in beliebigen Mengen hin- und her geschickt werden können. „Manuell“ heißt, dass keine automatische Verteilung der Waren stattfindet. Hier sollte fast immer „asymmetrisch“ oder „manuell“ gewählt werden. STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Genauigkeit für die Berechnung der Warenverteilung: {STRING} @@ -1688,14 +1688,14 @@ STR_CONFIG_SETTING_SHORT_PATH_SATURATION :Auslastung der STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT :Häufig gibt es mehrere Verbindungen um von einer Station zu einer anderen zu kommen. Zuerst wird der Algorithmus die kürzesten Verbindungen auslasten, dann die längeren usw. Wenn alle Verbindungen ausgelastet sind, verteilt er die verbliebene Nachfrage gleichmäßig. Diese Einstellung besagt, ab welcher Auslastung eine Verbinudng als „voll“ gilt und der Algorithmus in der ersten Runde die nächst längere wählt. Da die Kapazität der Verbindungen geschätzt wird, ist es sinnvoll, hier weniger als 100% anzugeben, um etwas „Luft“ für Fehlschätzungen zu lassen. STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY :Geschwindigkeitseinheit: {STRING} -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Immer wenn die Geschwindigkeit angezeigt wird, zeige sie in den gewählten Einheiten +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Immer wenn die Geschwindigkeit angezeigt wird, sie in den gewählten Einheiten anzeigen STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metrisch (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Spieleinheiten (Spielfeldkacheln/Tag) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Leistungseinheit von Fahrzeugen: {STRING} -STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Immer wenn die Leistung eins Fahrzeugs angezeigt wird, zeige es in den gewählten Einheiten +STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Immer wenn die Leistung eins Fahrzeugs angezeigt wird, sie in den gewählten Einheiten anzeigen STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_IMPERIAL :Imperial (hp) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_METRIC :Metrisch (PS) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_SI :SI (kW) @@ -1707,19 +1707,19 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_METRIC :Metrisch (t/Ton STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_SI :SI (kg) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME :Volumeneinheit: {STRING} -STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_HELPTEXT :Immer wenn Volumina angezeigt werden, zeige sie in den gewählten Einheiten +STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_HELPTEXT :Immer wenn Volumina angezeigt werden, sie in den gewählten Einheiten anzeigen STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_IMPERIAL :Imperial (gal) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_METRIC :Metrisch (l) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_SI :SI (m³) STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE :Einheit für Zugkraft: {STRING} -STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_HELPTEXT :Immer wenn die Zugkraft angezeigt wird, zeige sie in den gewählten Einheiten an +STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_HELPTEXT :Immer wenn die Zugkraft angezeigt wird, sie in den gewählten Einheiten anzeigen STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_IMPERIAL :Imperial (lbf) STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_METRIC :Metrisch (kp) STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Höheneinheiten: {STRING} -STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Immer wenn Höhen angezeigt werden, zeige sie in den gewählten Einheiten an +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Immer wenn Höhen angezeigt werden, sie in den gewählten Einheiten anzeigen STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisch (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -1751,11 +1751,11 @@ STR_CONFIG_SETTING_AI_NPC :{ORANGE}Compute STR_CONFIG_SETTING_PATHFINDER_NPF :NPF STR_CONFIG_SETTING_PATHFINDER_YAPF_RECOMMENDED :YAPF {BLUE}(empfohlen) -STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS :Pathfinder für Züge: {STRING} +STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS :Pfadsucher für Züge: {STRING} STR_CONFIG_SETTING_PATHFINDER_FOR_TRAINS_HELPTEXT :Pfadsuch-Algorithmus für Züge -STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES :Pathfinder für Straßenfahrzeuge: {STRING} +STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES :Pfadsucher für Straßenfahrzeuge: {STRING} STR_CONFIG_SETTING_PATHFINDER_FOR_ROAD_VEHICLES_HELPTEXT :Pfadsuch-Algorithmus für Straßenfahrzeuge -STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS :Pathfinder für Schiffe: {STRING} +STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS :Pfadsucher für Schiffe: {STRING} STR_CONFIG_SETTING_PATHFINDER_FOR_SHIPS_HELPTEXT :Pfadsuch-Algorithmus für Schiffe STR_CONFIG_SETTING_REVERSE_AT_SIGNALS :Automatisches Umdrehen an Signalen: {STRING} STR_CONFIG_SETTING_REVERSE_AT_SIGNALS_HELPTEXT :Erlaube Zügen, an Signalen umzudrehen, wenn sie dort zu lange gewartet haben @@ -1780,7 +1780,7 @@ STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND :{WHITE}... igno STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND :{WHITE}... ignoriere Basissounds „{STRING}“: nicht gefunden STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND :{WHITE}... ignoriere Musikset „{STRING}“: nicht gefunden STR_CONFIG_ERROR_OUT_OF_MEMORY :{WHITE}Zu wenig Arbeitsspeicher -STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Reservieren von {BYTES} des Spritecaches fehlgeschlagen. Der Spritecache wurde auf {BYTES} verkleinert. Dies wird die Performance von OpenTTD verschlechtern. Um den Speicherbedarf zu verringern, kann man versuchen, 32bpp - Grafiken auszuschalten und/oder den Zoom-Level zu begrenzen +STR_CONFIG_ERROR_SPRITECACHE_TOO_BIG :{WHITE}Reservieren von {BYTES} des Spritecaches fehlgeschlagen. Der Spritecache wurde auf {BYTES} verkleinert. Dies wird die Performance von OpenTTD verschlechtern. Um den Speicherbedarf zu verringern, kann man versuchen, 32bpp-Grafiken auszuschalten und/oder den Zoom-Level zu begrenzen # Intro window STR_INTRO_CAPTION :{WHITE}OpenTTD {REV} @@ -1820,8 +1820,8 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Prüfe, STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Zeige KI- und Skripteinstellungen STR_INTRO_TOOLTIP_QUIT :{BLACK}OpenTTD beenden -STR_INTRO_BASESET :{BLACK}Den momentan ausgewählten Basisgrafiken fehl{P 0 "t" "en"} {NUM} Sprite{P 0 "" "s"}. Bitte überprüfe, ob es Updates für die Basisgrafiken gibt. -STR_INTRO_TRANSLATION :{BLACK}Dieser Übersetzung fehl{P 0 t en} {NUM} String{P "" s}. Bitte hilf, OpenTTD zu verbessern und melde Dich als Übersetzer an. Siehe readme.txt für weitere Details. +STR_INTRO_BASESET :{BLACK}Den momentan ausgewählten Basisgrafiken fehl{P 0 "t" "en"} {NUM} Sprite{P 0 "" "s"}. Bitte überprüfen, ob es Updates für die Basisgrafiken gibt. +STR_INTRO_TRANSLATION :{BLACK}Dieser Übersetzung fehl{P 0 t en} {NUM} String{P "" s}. Bitte helfen Sie, OpenTTD zu verbessern und melden Sie sich als Übersetzer an. Siehe readme.txt für weitere Details. # Quit window STR_QUIT_CAPTION :{WHITE}Verlassen @@ -1861,9 +1861,9 @@ STR_LIVERY_TRAIN_TOOLTIP :{BLACK}Zugfarbs STR_LIVERY_ROAD_VEHICLE_TOOLTIP :{BLACK}Fahrzeugfarbschema anzeigen STR_LIVERY_SHIP_TOOLTIP :{BLACK}Schiffsfarbschema anzeigen STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Flugzeugfarbschema anzeigen -STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Wähle die Hauptfarbe für das gewählte Schema aus. Strg+Klick wählt diese Farbe für jedes Schema -STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Wähle die Nebenfarbe für das ausgewählte Schema. Strg+Klick wählt diese Farbe für jedes Schema. -STR_LIVERY_PANEL_TOOLTIP :{BLACK}Wähle ein Farbschema oder mehrere Farbschemata mittels Strg+Klick aus, um diese zu ändern. Klicke in das Kästchen, um ein Schema zu aktivieren +STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Die Hauptfarbe für das gewählte Schema auswählen. Strg+Klick wählt diese Farbe für jedes Schema +STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Die Nebenfarbe für das ausgewählte Schema auswählen. Strg+Klick wählt diese Farbe für jedes Schema +STR_LIVERY_PANEL_TOOLTIP :{BLACK}Farbschema oder mehrere Farbschemata mittels Strg+Klick auswählen, um diese zu ändern. In das Kästchen klicken, um ein Schema zu aktivieren STR_LIVERY_DEFAULT :Standardlackierung STR_LIVERY_STEAM :Dampflok @@ -2291,18 +2291,18 @@ STR_CONTENT_TYPE_HEIGHTMAP :{G=w}Reliefkart STR_CONTENT_TYPE_BASE_SOUNDS :Basissound STR_CONTENT_TYPE_BASE_MUSIC :Basismusik STR_CONTENT_TYPE_GAME_SCRIPT :Skript -STR_CONTENT_TYPE_GS_LIBRARY :Skript - Bibliothek +STR_CONTENT_TYPE_GS_LIBRARY :Skript-Bibliothek # Content downloading progress window -STR_CONTENT_DOWNLOAD_TITLE :{WHITE}Lade Erweiterungen herunter... -STR_CONTENT_DOWNLOAD_INITIALISE :{WHITE}Fordere Dateien an... +STR_CONTENT_DOWNLOAD_TITLE :{WHITE}Lade Erweiterungen herunter ... +STR_CONTENT_DOWNLOAD_INITIALISE :{WHITE}Fordere Dateien an ... STR_CONTENT_DOWNLOAD_FILE :{WHITE}Lade momentan herunter: {STRING} ({NUM} von {NUM}) STR_CONTENT_DOWNLOAD_COMPLETE :{WHITE}Alle Dateien heruntergeladen STR_CONTENT_DOWNLOAD_PROGRESS_SIZE :{WHITE}{BYTES} von {BYTES} heruntergeladen ({NUM} %) # Content downloading error messages -STR_CONTENT_ERROR_COULD_NOT_CONNECT :{WHITE}Kann keine Verbindung mit dem Server für Online-Erweiterungen herstellen... -STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD :{WHITE}Herunterladen fehlgeschlagen... +STR_CONTENT_ERROR_COULD_NOT_CONNECT :{WHITE}Kann keine Verbindung mit dem Server für Online-Erweiterungen herstellen ... +STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD :{WHITE}Herunterladen fehlgeschlagen ... STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_CONNECTION_LOST :{WHITE}... Verbindung verloren STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE :{WHITE}... kann Datei nicht schreiben STR_CONTENT_ERROR_COULD_NOT_EXTRACT :{WHITE}Kann heruntergeladene Datei nicht entpacken @@ -2362,16 +2362,16 @@ STR_RAIL_TOOLBAR_ELRAIL_CONSTRUCTION_CAPTION :Bau elektrifizi STR_RAIL_TOOLBAR_MONORAIL_CONSTRUCTION_CAPTION :Einschienenbahnbau STR_RAIL_TOOLBAR_MAGLEV_CONSTRUCTION_CAPTION :Magnetschwebebahnbau -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Gleise legen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}Gleise legen mit automatischer Wahl der Ausrichtung. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Zugdepot bauen (zum Kauf und zur Wartung von Zügen). Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}Wegpunkt (auf vorhandenem Gleis) bauen. Strg+Klick, um Wegpunkte zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}Bahnhof bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}Signale errichten. Strg+Klick wechselt zwischen Formsignal-/Signaltypen{}Klicken und Ziehen, um mehrere Signale entlang einer geraden Strecke zu bauen. Strg halten, um bis zur nächsten Kreuzung zu bauen{}Strg+Klick auf die Schaltfläche zeigt das Signal-Menü. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}Eisenbahnbrücke bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}Eisenbahntunnel bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Gleise legen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_AUTORAIL :{BLACK}Gleise legen mit automatischer Wahl der Ausrichtung. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_TRAIN_DEPOT_FOR_BUILDING :{BLACK}Zugdepot bauen (zum Kauf und zur Wartung von Zügen). Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL_TO_WAYPOINT :{BLACK}Wegpunkt (auf vorhandenem Gleis) bauen. Strg+Klick, um Wegpunkte zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_STATION :{BLACK}Bahnhof bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_SIGNALS :{BLACK}Signale errichten. Strg+Klick wechselt zwischen Formsignal-/Signaltypen{}Klicken und Ziehen, um mehrere Signale entlang einer geraden Strecke zu bauen. Strg halten, um bis zur nächsten Kreuzung zu bauen{}Strg+Klick auf die Schaltfläche zeigt das Signal-Menü. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_BRIDGE :{BLACK}Eisenbahnbrücke bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TUNNEL :{BLACK}Eisenbahntunnel bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_RAIL_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR :{BLACK}Umschalter für Bau/Abriss mit aktuellem Bauwerkzeug. Strg+Klick um die Gleise von Wegpunkten und Bahnhöfen ebenfalls zu entfernen -STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}Gleistyp in den ausgewählten umwandeln. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_RAIL_TOOLBAR_TOOLTIP_CONVERT_RAIL :{BLACK}Gleistyp in den ausgewählten umwandeln. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_RAIL_NAME_RAILROAD :Schienen STR_RAIL_NAME_ELRAIL :Elektrifizierte Schienen @@ -2417,7 +2417,7 @@ STR_BUILD_SIGNAL_ELECTRIC_EXIT_TOOLTIP :{BLACK}Ausfahrs STR_BUILD_SIGNAL_ELECTRIC_COMBO_TOOLTIP :{BLACK}Kombinationssignal (Lichtsignal){}Das Kombinationssignal ist gleichzeitig Aus- und Einfahrsignal. Somit werden umfangreiche Signalverschaltungen möglich STR_BUILD_SIGNAL_ELECTRIC_PBS_TOOLTIP :{BLACK}Pfadsignal (Lichtsignal){}Erlaubt mehreren Zügen gleichzeitig, einen Signalbereich zu befahren, sofern sie separate Gleisabschnitte belegen können. Normale Pfadsignale können von hinten durchfahren werden STR_BUILD_SIGNAL_ELECTRIC_PBS_OWAY_TOOLTIP :{BLACK}Einseitiges Pfadsignal (Lichtsignal):{}Erlaubt mehreren Zügen, einen Signalbereich zu befahren, sofern sie separate Gleisabschnitte belegen können. Einseitige Pfadsignale können nicht von hinten durchfahren werden -STR_BUILD_SIGNAL_CONVERT_TOOLTIP :{BLACK}Signalumbau{}Wenn ausgewählt, werden bestehende Signale durch Anklicken zum ausgewählten Signaltyp umgebaut. Strg+Klick ändert die bestehende Bauform. Shift+Klick zeigt Kostenvoranschlag +STR_BUILD_SIGNAL_CONVERT_TOOLTIP :{BLACK}Signalumbau{}Wenn ausgewählt, werden bestehende Signale durch Anklicken zum ausgewählten Signaltyp umgebaut. Strg+Klick ändert die bestehende Bauform. Umschalt+Klick zeigt Kostenvoranschlag STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}Signalabstand beim automatischen Bau durch Ziehen STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_DECREASE_TOOLTIP :{BLACK}Signalabstand verringern STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_INCREASE_TOOLTIP :{BLACK}Signalabstand erhöhen @@ -2441,25 +2441,25 @@ STR_BRIDGE_TUBULAR_SILICON :Siliziumrundbr # Road construction toolbar STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION :{WHITE}Straßenbau STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION :{WHITE}Straßenbahn bauen -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION :{BLACK}Straße bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}Straßenbahngleis bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}Straße mit automatischer Wahl der Ausrichtung bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}Straßenbahngleis mit automatischer Wahl der Ausrichtung bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Fahrzeugdepot bauen (zum Kauf und zur Wartung von Fahrzeugen benötigt). Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}Straßenbahndepot bauen (zum Kauf und zur Wartung von Straßenbahnen benötigt). Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION :{BLACK}Bushaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION :{BLACK}Straßenbahnhaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY :{BLACK}Lkw-Ladeplatz bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION :{BLACK}Güterstraßenbahnhaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_SECTION :{BLACK}Straße bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION :{BLACK}Straßenbahngleis bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}Straße mit automatischer Wahl der Ausrichtung bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}Straßenbahngleis mit automatischer Wahl der Ausrichtung bauen. Strg halten, um zwischen Bauen und Entfernen umzuschalten. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Fahrzeugdepot bauen (zum Kauf und zur Wartung von Fahrzeugen benötigt). Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}Straßenbahndepot bauen (zum Kauf und zur Wartung von Straßenbahnen benötigt). Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION :{BLACK}Bushaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION :{BLACK}Straßenbahnhaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY :{BLACK}Lkw-Ladeplatz bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION :{BLACK}Güterstraßenbahnhaltestelle bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_ONE_WAY_ROAD :{BLACK}Einbahnstraßenbau ein/aus -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE :{BLACK}Straßenbrücke bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE :{BLACK}Straßenbahnbrücke bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}Straßentunnel bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}Straßenbahntunnel bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_BRIDGE :{BLACK}Straßenbrücke bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE :{BLACK}Straßenbahnbrücke bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}Straßentunnel bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}Straßenbahntunnel bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}Zwischen Bau und Abriss der Straße umschalten STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}Zwischen Bau und Abriss von Straßenbahngleisen umschalten -STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}Straßentyp in den ausgewählten umwandeln. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}Straßenbahntyp in den ausgewählten umwandeln. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}Straßentyp in den ausgewählten umwandeln. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}Straßenbahntyp in den ausgewählten umwandeln. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_ROAD_NAME_ROAD :Straße STR_ROAD_NAME_TRAM :Straßenbahngleis @@ -2483,12 +2483,12 @@ STR_STATION_BUILD_CARGO_TRAM_ORIENTATION_TOOLTIP :{BLACK}Ausricht # Waterways toolbar (last two for SE only) STR_WATERWAYS_TOOLBAR_CAPTION :{WHITE}Wasserstraßenbau STR_WATERWAYS_TOOLBAR_CAPTION_SE :{WHITE}Wasserstraßen -STR_WATERWAYS_TOOLBAR_BUILD_CANALS_TOOLTIP :{BLACK}Kanal bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_WATERWAYS_TOOLBAR_BUILD_LOCKS_TOOLTIP :{BLACK}Schleuse bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_WATERWAYS_TOOLBAR_BUILD_DEPOT_TOOLTIP :{BLACK}Werft bauen (für den Kauf und die Wartung von Schiffen benötigt). Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Hafen bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Positionsboje, wird als Wegpunkt benötigt. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Aquädukt bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUILD_CANALS_TOOLTIP :{BLACK}Kanal bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUILD_LOCKS_TOOLTIP :{BLACK}Schleuse bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUILD_DEPOT_TOOLTIP :{BLACK}Werft bauen (für den Kauf und die Wartung von Schiffen benötigt). Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Hafen bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Positionsboje, wird als Wegpunkt benötigt. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Aquädukt bauen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Wasser erzeugen.{}Baut einen Kanal. Auf Meereshöhe wird bei gedrückter Strg-Taste ein Wasserfeld erzeugt, welches umliegendes Land flutet STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Flüsse platzieren @@ -2501,7 +2501,7 @@ STR_STATION_BUILD_DOCK_CAPTION :{WHITE}Hafen # Airport toolbar STR_TOOLBAR_AIRCRAFT_CAPTION :{WHITE}Flughäfen -STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP :{BLACK}Flughafen bauen. Strg+Klick, um Stationen zu verbinden. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_TOOLBAR_AIRCRAFT_BUILD_AIRPORT_TOOLTIP :{BLACK}Flughafen bauen. Strg+Klick, um Stationen zu verbinden. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um # Airport construction window STR_STATION_BUILD_AIRPORT_CAPTION :{WHITE}Flughafen bauen @@ -2528,14 +2528,14 @@ STR_STATION_BUILD_NOISE :{BLACK}Lärmbel # Landscaping toolbar STR_LANDSCAPING_TOOLBAR :{WHITE}Landschaftsbau -STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}Land absenken. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}Land anheben. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}Höhe ausgleichen. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Land für künftige Nutzung kaufen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}Land absenken. Durch Ziehen wird die erste ausgewählte Ecke abgesenkt und der ausgewählte Bereich auf die neue Eckhöhe gebracht. Strg wählt das Gebiet diagonal. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}Land anheben. Durch Ziehen wird die erste ausgewählte Ecke angehoben und der ausgewählte Bereich auf die neue Eckhöhe gebracht. Strg wählt das Gebiet diagonal. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}Höhe ausgleichen. Strg wählt das Gebiet diagonal. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um +STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Land für künftige Nutzung kaufen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}Objektauswahl -STR_OBJECT_BUILD_TOOLTIP :{BLACK}Objektauswahl - Auf das gewünschte Objekt klicken, um es zu bauen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_OBJECT_BUILD_TOOLTIP :{BLACK}Zu bauendes Objekt auswählen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_OBJECT_BUILD_CLASS_TOOLTIP :{BLACK}Objektklasse auswählen STR_OBJECT_BUILD_PREVIEW_TOOLTIP :{BLACK}Vorschau des Objekts STR_OBJECT_BUILD_SIZE :{BLACK}Größe: {GOLD}{NUM} × {NUM} Felder @@ -2545,9 +2545,9 @@ STR_OBJECT_CLASS_TRNS :Sendemasten # Tree planting window (last eight for SE only) STR_PLANT_TREE_CAPTION :{WHITE}Bäume -STR_PLANT_TREE_TOOLTIP :{BLACK}Wähle die zu pflanzende Baumart. Wenn auf dem Feld schon ein Baum steht, wird eine zufällige Baumart gepflanzt +STR_PLANT_TREE_TOOLTIP :{BLACK}Die zu pflanzende Baumart wählen. Wenn auf dem Feld schon ein Baum steht, wird eine zufällige Baumart gepflanzt STR_TREES_RANDOM_TYPE :{BLACK}Zufällige Baumart -STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Zufällige Baumart pflanzen. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Zufällige Baumart pflanzen. Umschalt schaltet zwischen Bauen und Kostenvoranschlag um STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Zufällige Bäume STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Bäume zufällig über die Landschaft verteilen STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Normal @@ -2574,7 +2574,7 @@ STR_RESET_LANDSCAPE_CONFIRMATION_TEXT :{WHITE}Soll wir # Town generation window (SE) STR_FOUND_TOWN_CAPTION :{WHITE}Stadt gründen STR_FOUND_TOWN_NEW_TOWN_BUTTON :{BLACK}Neue Stadt -STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Neue Stadt gründen. Shift+Klick zeigt einen Kostenvoranschlag +STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Neue Stadt gründen. Umschalt+Klick zeigt einen Kostenvoranschlag STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Zufällige Stadt STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Stadt an zufälligem Ort gründen STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Viele zufällige Städte @@ -2753,7 +2753,7 @@ STR_LAI_OBJECT_DESCRIPTION_COMPANY_OWNED_LAND :Firmeneigenes G # About OpenTTD window STR_ABOUT_OPENTTD :{WHITE}OpenTTD -STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Transport Tycoon-Urheberrecht {COPYRIGHT} 1995 Chris Sawyer, alle Rechte vorbehalten +STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Ursprüngliches Copyright {COPYRIGHT} 1995 Chris Sawyer, alle Rechte vorbehalten STR_ABOUT_VERSION :{BLACK}OpenTTD-Version {REV} STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT} 2002-{STRING} OpenTTD-Team @@ -2795,7 +2795,7 @@ STR_FRAMERATE_DRAWING_VIEWPORTS :{BLACK}Kartenan STR_FRAMERATE_VIDEO :{BLACK}Videoausgabe: STR_FRAMERATE_SOUND :{BLACK}Sound-Abmischung: STR_FRAMERATE_ALLSCRIPTS :{BLACK} GS/AI-Skripte gesamt: -STR_FRAMERATE_GAMESCRIPT :{BLACK} Script: +STR_FRAMERATE_GAMESCRIPT :{BLACK} Skript: STR_FRAMERATE_AI :{BLACK} KI {NUM} {STRING} ############ End of leave-in-this-order ############ Leave those lines in this order!! @@ -2811,7 +2811,7 @@ STR_FRAMETIME_CAPTION_DRAWING :Grafik-Renderin STR_FRAMETIME_CAPTION_DRAWING_VIEWPORTS :Karten-Rendering STR_FRAMETIME_CAPTION_VIDEO :Videoausgabe STR_FRAMETIME_CAPTION_SOUND :Sound-Abmischung -STR_FRAMETIME_CAPTION_ALLSCRIPTS :GS/AI-Skripte gesamt +STR_FRAMETIME_CAPTION_ALLSCRIPTS :GS-/KI-Skripte gesamt STR_FRAMETIME_CAPTION_GAMESCRIPT :Spielskript STR_FRAMETIME_CAPTION_AI :KI {NUM} {STRING} ############ End of leave-in-this-order @@ -2901,7 +2901,7 @@ STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Flachlan STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Flachlandhöhe ändern # Map generation progress -STR_GENERATION_WORLD :{WHITE}Spielfeld wird generiert... +STR_GENERATION_WORLD :{WHITE}Spielfeld wird generiert ... STR_GENERATION_ABORT :{BLACK}Abbrechen STR_GENERATION_ABORT_CAPTION :{WHITE}Spielfeldgenerierung abbrechen STR_GENERATION_ABORT_MESSAGE :{YELLOW}Soll die Spielfeldgenerierung wirklich abgebrochen werden? @@ -3010,11 +3010,11 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Gehe zum STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Vorheriges Sprite STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Gehe zum vorherigen normalen Sprite und überspringe alle Pseudo-, Recolour- und Schriftsprites (springt ggf. vom letzten bis zum ersten Sprite) STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Darstellung des aktuellen Sprites. Die Ausrichtung wird beim Zeichnen des Sprites ignoriert -STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Bewege die Sprites und ändere dadurch die X- und Y-Offsets. Drücke Strg+Click um die Sprites 8 Blöcke weit zu bewegen. +STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Bewege die Sprites und ändere dadurch die X- und Y-Offsets. Strg+Klick um die Sprites 8 Blöcke weit zu bewegen. STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Setze zurück -STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Setze die aktuelle Verschiebung zurück. -STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}X offset: {NUM}, Y offset: {NUM} (Absolut) -STR_SPRITE_ALIGNER_OFFSETS_REL :{BLACK}X offset: {NUM}, Y offset: {NUM} (Relativ) +STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Setze die aktuellen relativen Versätze zurück +STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}X-Versatz: {NUM}, Y-Versatz: {NUM} (Absolut) +STR_SPRITE_ALIGNER_OFFSETS_REL :{BLACK}X-Versatz: {NUM}, Y-Versatz: {NUM} (Relativ) STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}Sprite auswählen STR_SPRITE_ALIGNER_PICKER_TOOLTIP :{BLACK}Wähle ein Sprite vom Bildschirm aus @@ -3113,7 +3113,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Text fü STR_TOWN_DIRECTORY_CAPTION :{WHITE}Städte STR_TOWN_DIRECTORY_NONE :{ORANGE}- Keine - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Großstadt){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Städtenamen - Klick auf den Namen zentriert Hauptansicht auf die Stadt. Strg+Klick öffnet neue Zusatzansicht zentriert auf die Stadt STR_TOWN_POPULATION :{BLACK}Weltbevölkerung: {COMMA} @@ -3377,7 +3377,7 @@ STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP :{BLACK}Firmensi STR_COMPANY_VIEW_VIEW_HQ_BUTTON :{BLACK}Firmensitz STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP :{BLACK}Firmensitz anzeigen STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Verlegen -STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Errichte Firmensitz für 1% des Firmenwertes an anderer Stelle neu. Shift+Klick zeigt einen Kostenvoranschlag +STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Errichte Firmensitz für 1% des Firmenwertes an anderer Stelle neu. Umschalt+Klick zeigt einen Kostenvoranschlag STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Details STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Detaillierte Informationen zur Infrastruktur dieser Firma anzeigen STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Verschenke Geld @@ -3394,8 +3394,8 @@ STR_COMPANY_VIEW_PRESIDENT_NAME_TOOLTIP :{BLACK}Managern STR_COMPANY_VIEW_BUY_SHARE_BUTTON :{BLACK}25% der Aktien der Firma kaufen STR_COMPANY_VIEW_SELL_SHARE_BUTTON :{BLACK}25% der Aktien der Firma verkaufen -STR_COMPANY_VIEW_BUY_SHARE_TOOLTIP :{BLACK}25% der Aktien dieser Firma kaufen. Shift+Klick zeigt einen Kostenvoranschlag -STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}25% der Aktien dieser Firma verkaufen. Shift+Klick zeigt eine Gewinnschätzung +STR_COMPANY_VIEW_BUY_SHARE_TOOLTIP :{BLACK}25% der Aktien dieser Firma kaufen. Umschalt+Klick zeigt einen Kostenvoranschlag +STR_COMPANY_VIEW_SELL_SHARE_TOOLTIP :{BLACK}25% der Aktien dieser Firma verkaufen. Umschalt+Klick zeigt eine Gewinnschätzung STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION :Firmenname STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION :Name des Managers @@ -3408,7 +3408,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}Infrastr STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}Schienenfelder: STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}Signale STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}Straßenfelder: -STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}Straßenbahnfelder +STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}Straßenbahnfelder: STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}Wasserfelder: STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}Kanäle STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}Stationen: @@ -3424,10 +3424,10 @@ STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUST STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING} STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE}{INDUSTRY} {STRING}, {STRING} STR_INDUSTRY_DIRECTORY_ITEM_PROD3 :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} -STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} und {NUM} weitere... +STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} und {NUM} weitere ... STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Industrienamen - Klick auf den Namen zentriert Hauptansicht auf die Industrie. Strg+Klick öffnet neue Zusatzansicht zentriert auf die Industrie -STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Angenommene Frachtarten: {SILVER}{STRING} -STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Produzierte Güter: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Angenommene Fracht: {SILVER}{STRING} +STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Produzierte Fracht: {SILVER}{STRING} STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :Alle Frachtarten STR_INDUSTRY_DIRECTORY_FILTER_NONE :Keine @@ -3443,7 +3443,7 @@ STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}Benötig STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}Produziert: {YELLOW}{STRING}{STRING} STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRING} -STR_INDUSTRY_VIEW_REQUIRES :{BLACK}benötigt: +STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Benötigt: STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} wartend{STRING} @@ -3559,10 +3559,10 @@ STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Zug STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Reichweite: {GOLD}{COMMA} Felder STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Flugzeugtyp: {GOLD}{STRING} -STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Schienenfahrzeugsliste - Einzelheiten durch Anklicken des Fahrzeuges. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Fahrzeugtyps -STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Straßenfahrzeugsliste - Klicke auf ein Fahrzeug für Einzelheiten. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Fahrzeugtyps -STR_BUY_VEHICLE_SHIP_LIST_TOOLTIP :{BLACK}Schiffsliste - für Einzelheiten auf das Schiff klicken. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Schiffstyps -STR_BUY_VEHICLE_AIRCRAFT_LIST_TOOLTIP :{BLACK}Flugzeugliste - Klick auf das Flugzeug zeigt weitere Einzelheiten an. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Fahrzeugtyps +STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Schienenfahrzeugsliste. Einzelheiten durch Anklicken des Fahrzeuges. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Fahrzeugtyps +STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Straßenfahrzeugsliste. Für Einzelheiten auf ein Fahrzeug klicken. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Fahrzeugtyps +STR_BUY_VEHICLE_SHIP_LIST_TOOLTIP :{BLACK}Schiffsliste. Für Einzelheiten auf das Schiff klicken. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Schiffstyps +STR_BUY_VEHICLE_AIRCRAFT_LIST_TOOLTIP :{BLACK}Flugzeugliste. Klick auf das Flugzeug zeigt weitere Einzelheiten an. Strg+Klick schaltet um zwischen Verstecken und Zeigen des Flugzeugtyps STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_BUTTON :{BLACK}Fahrzeug kaufen STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_BUTTON :{BLACK}Fahrzeug kaufen @@ -3575,14 +3575,14 @@ STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Schiff k STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :Flugzeug kaufen und umrüsten STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Fahrzeug kaufen. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Fahrzeug kaufen. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Schiff kaufen. Shift+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Fahrzeug kaufen. Umschalt+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Schiff kaufen. Umschalt+Klick zeigt einen Kostenvoranschlag STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}Augewähltes Flugzeug kaufen. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :Ausgewähltes Fahrzeug kaufen und umrüsten. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Straßenfahrzeug kaufen und umrüsten. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Schiff kaufen und umrüsten. Shift+Klick zeigt einen Kostenvoranschlag -STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Flugzeug kaufen und umrüsten. Shift+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Fahrzeug kaufen und umrüsten. Umschalt+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Straßenfahrzeug kaufen und umrüsten. Umschalt+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Schiff kaufen und umrüsten. Umschalt+Klick zeigt einen Kostenvoranschlag +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Ausgewähltes Flugzeug kaufen und umrüsten. Umschalt+Klick zeigt einen Kostenvoranschlag STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Umbenennen STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}Umbenennen @@ -3625,14 +3625,14 @@ STR_DEPOT_VEHICLE_TOOLTIP :{BLACK}{ENGINE} STR_DEPOT_VEHICLE_TOOLTIP_CHAIN :{BLACK}{NUM} Fahrzeug{P "" e}{STRING} STR_DEPOT_VEHICLE_TOOLTIP_CARGO :{}{CARGO_LONG} ({CARGO_SHORT}) -STR_DEPOT_TRAIN_LIST_TOOLTIP :{BLACK}Züge - Fahrzeug ziehen, um es an-/abzukoppeln. Rechts-Klick für Fahrzeuginformationen, Rechts-Klick für Einzelheiten. Strg, um die jeweilige Funktion für das gesamte Gespann auszuführen -STR_DEPOT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Straßenfahrzeuge - Rechts-Klick für Einzelheiten -STR_DEPOT_SHIP_LIST_TOOLTIP :{BLACK}Schiffe - Rechts-Klick für Einzelheiten -STR_DEPOT_AIRCRAFT_LIST_TOOLTIP :{BLACK}Flugzeuge - Rechts-Klick für Einzelheiten +STR_DEPOT_TRAIN_LIST_TOOLTIP :{BLACK}Züge - Fahrzeug ziehen, um es an-/abzukoppeln. Rechtsklick für Fahrzeuginformationen, Rechtsklick für Einzelheiten. Strg, um die jeweilige Funktion für das gesamte Gespann auszuführen +STR_DEPOT_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Straßenfahrzeuge - Rechtsklick für Einzelheiten +STR_DEPOT_SHIP_LIST_TOOLTIP :{BLACK}Schiffe - Rechtsklick für Einzelheiten +STR_DEPOT_AIRCRAFT_LIST_TOOLTIP :{BLACK}Flugzeuge - Rechtsklick für Einzelheiten STR_DEPOT_TRAIN_SELL_TOOLTIP :{BLACK}Schienenfahrzeug hierher ziehen, um es zu verkaufen -STR_DEPOT_ROAD_VEHICLE_SELL_TOOLTIP :{BLACK}Ziehe Straßenfahrzeug hierher, um es zu verkaufen -STR_DEPOT_SHIP_SELL_TOOLTIP :{BLACK}Ziehe Schiff hierher, um es zu verkaufen +STR_DEPOT_ROAD_VEHICLE_SELL_TOOLTIP :{BLACK}Straßenfahrzeug hierher ziehen, um es zu verkaufen +STR_DEPOT_SHIP_SELL_TOOLTIP :{BLACK}Schiff hierher ziehen, um es zu verkaufen STR_DEPOT_AIRCRAFT_SELL_TOOLTIP :{BLACK}Zum Verkauf des Flugzeuges hierher ziehen STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP :{BLACK}Lok hierher ziehen, um den ganzen Zug zu verkaufen @@ -3662,10 +3662,10 @@ STR_DEPOT_CLONE_ROAD_VEHICLE :{BLACK}Fahrzeug STR_DEPOT_CLONE_SHIP :{BLACK}Schiff kopieren STR_DEPOT_CLONE_AIRCRAFT :{BLACK}Flugzeug kopieren -STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Kauft eine Kopie des Zuges mit allen Wagons. Klicke diese Schaltfläche und dann auf einen Zug innerhalb oder außerhalb des Depots. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_DEPOT_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Kauft eine Kopie des Fahrzeuges. Klicke auf diese Schaltfläche und dann auf ein Fahrzeug innerhalb oder außerhalb des Depots. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Kauft eine Kopie des Schiffes. Klicke diese Schaltfläche und dann auf eine Schiff innerhalb oder außerhalb der Werft. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Kauft eine Kopie des Flugzeuges. Klicke auf diese Schaltfläche und dann auf ein Flugzeug innerhalb oder außerhalb des Hangars. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_DEPOT_CLONE_TRAIN_DEPOT_INFO :{BLACK}Kauft eine Kopie des Zuges mit allen Wagons. Klicken Sie auf diese Schaltfläche und dann auf einen Zug innerhalb oder außerhalb des Depots. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_DEPOT_CLONE_ROAD_VEHICLE_DEPOT_INFO :{BLACK}Kauft eine Kopie des Fahrzeuges. Klicken Sie auf diese Schaltfläche und dann auf ein Fahrzeug innerhalb oder außerhalb des Depots. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Kauft eine Kopie des Schiffes. Klicken Sie auf diese Schaltfläche und dann auf eine Schiff innerhalb oder außerhalb der Werft. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Kauft eine Kopie des Flugzeuges. Klicken Sie auf diese Schaltfläche und dann auf ein Flugzeug innerhalb oder außerhalb des Hangars. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um STR_DEPOT_TRAIN_LOCATION_TOOLTIP :{BLACK}Hauptansicht zum Zugdepot scrollen. Strg+Klick öffnet neue Zusatzansicht beim Zugdepot STR_DEPOT_ROAD_VEHICLE_LOCATION_TOOLTIP :{BLACK}Hauptansicht zum Fahrzeugdepot scrollen. Strg+Klick öffnet neue Zusatzansicht beim Fahrzeugdepot @@ -3705,12 +3705,12 @@ STR_ENGINE_PREVIEW_AIRCRAFT :{G=n}Flugzeug STR_ENGINE_PREVIEW_SHIP :{G=n}Schiff STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Kosten: {CURRENCY_LONG} Gewicht: {WEIGHT_SHORT}{}Geschwindigk.: {VELOCITY} Leistung: {POWER}{}Betriebskosten: {CURRENCY_LONG} pro Jahr{}Kapazität: {CARGO_LONG} -STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Preis: {CURRENCY_LONG} Gewicht: {WEIGHT_SHORT}{}Max. Geschwindigkeit: {VELOCITY} Leistung: {POWER} Max. Zugkraft: {6:FORCE}{}Betriebskosten: {4:CURRENCY_LONG}/yr{}Kapazität: {5:CARGO_LONG} +STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Preis: {CURRENCY_LONG} Gewicht: {WEIGHT_SHORT}{}Max. Geschwindigkeit: {VELOCITY} Leistung: {POWER} Max. Zugkraft: {6:FORCE}{}Betriebskosten: {4:CURRENCY_LONG}/Jahr{}Kapazität: {5:CARGO_LONG} STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Preis: {CURRENCY_LONG} Höchstgeschw.: {VELOCITY}{}Kapazität: {CARGO_LONG}{}Betriebskosten: {CURRENCY_LONG}/Jahr STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING}{}Kapazität: {CARGO_LONG}, {CARGO_LONG}{}Betriebskosten: {CURRENCY_LONG}/Jahr STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING}{}Kapazität: {CARGO_LONG}{}Betriebskosten: {CURRENCY_LONG}/Jahr -STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING} Reichweite: {COMMA} Felder{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Betriebskosten: {CURRENCY_LONG}/Jahr -STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING} Reichweite: {COMMA} tiles{}Kapazität: {CARGO_LONG}{}Laufende Kosten: {CURRENCY_LONG}/yr +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING} Reichweite: {COMMA} Felder{}Kapazität: {CARGO_LONG}, {CARGO_LONG}{}Betriebskosten: {CURRENCY_LONG}/Jahr +STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Kosten: {CURRENCY_LONG} Max. Geschw.: {VELOCITY}{}Flugzeugtyp: {STRING} Reichweite: {COMMA} tiles{}Kapazität: {CARGO_LONG}{}Laufende Kosten: {CURRENCY_LONG}/Jahr # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}{STRING} ersetzen - {STRING} @@ -3747,7 +3747,7 @@ STR_REPLACE_HELP_RAILTYPE :{BLACK}Gleistyp STR_REPLACE_HELP_ROADTYPE :{BLACK}Straßentyp auswählen, für den Fahrzeuge ersetzt werden sollen STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Hier wird angezeigt, gegen welches Fahrzeug das auf der linken Seite gewählte ersetzt wird STR_REPLACE_RAIL_VEHICLES :Schienenfahrzeuge -STR_REPLACE_ELRAIL_VEHICLES :elektrische Schienenfahrzeuge +STR_REPLACE_ELRAIL_VEHICLES :Elektrische Schienenfahrzeuge STR_REPLACE_MONORAIL_VEHICLES :Einschienenbahn STR_REPLACE_MAGLEV_VEHICLES :Magnetschwebebahn @@ -3770,10 +3770,10 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Das Fahr STR_VEHICLE_VIEW_SHIP_SEND_TO_DEPOT_TOOLTIP :{BLACK}Das Schiff zur Werft schicken. Strg+Klick, um dort nur Wartung durchzuführen STR_VEHICLE_VIEW_AIRCRAFT_SEND_TO_DEPOT_TOOLTIP :{BLACK}Das Flugzeug in den Hangar schicken. Strg+Klick, um dort nur Wartung durchzuführen -STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Kauft eine Kopie des Zuges mit allen Waggons. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Kauft eine Kopie des Fahrzeuges. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Kauft eine Kopie des Schiffes. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um -STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Kauft eine Kopie des Flugzeuges. Strg+Klick erzeugt gemeinsamen Fahrplan. Shift schaltet zwischen Bauen und Kostenvoranschlag um +STR_VEHICLE_VIEW_CLONE_TRAIN_INFO :{BLACK}Kauft eine Kopie des Zuges mit allen Waggons. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_VEHICLE_VIEW_CLONE_ROAD_VEHICLE_INFO :{BLACK}Kauft eine Kopie des Fahrzeuges. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_VEHICLE_VIEW_CLONE_SHIP_INFO :{BLACK}Kauft eine Kopie des Schiffes. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um +STR_VEHICLE_VIEW_CLONE_AIRCRAFT_INFO :{BLACK}Kauft eine Kopie des Flugzeuges. Strg+Klick erzeugt gemeinsamen Fahrplan. Umschalt+Klick schaltet zwischen Bauen und Kostenvoranschlag um STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP :{BLACK}Zug zur Weiterfahrt zwingen, ohne das Signal zu beachten @@ -3861,7 +3861,7 @@ STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Wartungs STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Wartungsintervall um 10 erhöhen. Strg+Klick erhöht um 5 STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Wartungsintervall um 10 verringern. Strg+Klick verringert um 5 -STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP :{BLACK}Art des Service-Intervalls ändern +STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP :{BLACK}Art des Wartungsintervalls ändern STR_VEHICLE_DETAILS_DEFAULT :Standard STR_VEHICLE_DETAILS_DAYS :Tage STR_VEHICLE_DETAILS_PERCENT :Prozent @@ -4172,14 +4172,14 @@ STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}Debugfe STR_AI_CONFIG_CAPTION :{WHITE}KI / Skripte einstellen STR_AI_CONFIG_GAMELIST_TOOLTIP :{BLACK}Das Skript, das im nächsten Spiel geladen wird STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}Die KIs, die im nächsten Spiel geladen werden -STR_AI_CONFIG_HUMAN_PLAYER :menschlicher Spieler +STR_AI_CONFIG_HUMAN_PLAYER :Menschlicher Spieler STR_AI_CONFIG_RANDOM_AI :Zufällige KI STR_AI_CONFIG_NONE :- -STR_AI_CONFIG_MOVE_UP :{BLACK}Nach oben bewegen -STR_AI_CONFIG_MOVE_UP_TOOLTIP :{BLACK}Die ausgewählte KI in der Liste nach oben bewegen -STR_AI_CONFIG_MOVE_DOWN :{BLACK}Nach unten bewegen -STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Die ausgewählte KI in der Liste nach unten bewegen +STR_AI_CONFIG_MOVE_UP :{BLACK}Nach oben verschieben +STR_AI_CONFIG_MOVE_UP_TOOLTIP :{BLACK}Die ausgewählte KI in der Liste nach oben verschieben +STR_AI_CONFIG_MOVE_DOWN :{BLACK}Nach unten verschieben +STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Die ausgewählte KI in der Liste nach unten verschieben STR_AI_CONFIG_GAMESCRIPT :{SILVER}Skript STR_AI_CONFIG_AI :{SILVER}KIs @@ -4207,7 +4207,7 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}Ausgewä STR_AI_LIST_CANCEL :{BLACK}Abbrechen STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}Skript nicht wechseln -STR_SCREENSHOT_CAPTION :{WHITE}Sreenshot erzeugen +STR_SCREENSHOT_CAPTION :{WHITE}Screenshot erzeugen STR_SCREENSHOT_SCREENSHOT :{BLACK}Normaler Screenshot STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}Screenshot auf der größten Zoomstufe STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT :{BLACK}Screenshot auf der Standard-Zoomstufe @@ -4222,7 +4222,7 @@ STR_AI_SETTINGS_CAPTION_GAMESCRIPT :Skript STR_AI_SETTINGS_CLOSE :{BLACK}Schließen STR_AI_SETTINGS_RESET :{BLACK}Zurücksetzen STR_AI_SETTINGS_SETTING :{STRING}: {ORANGE}{STRING} -STR_AI_SETTINGS_START_DELAY :Wartezeit in Tagen zwischen dem Starten dieser KI und dem der vorherigen : {ORANGE}{STRING} +STR_AI_SETTINGS_START_DELAY :Wartezeit in Tagen zwischen dem Starten dieser KI und dem der vorherigen: {ORANGE}{STRING} # Textfile window @@ -4253,10 +4253,10 @@ STR_INCOME_FLOAT_INCOME_SMALL :{TINY_FONT}{GRE STR_INCOME_FLOAT_INCOME :{GREEN}Einnahmen: {CURRENCY_LONG} STR_FEEDER_TINY :{TINY_FONT}{YELLOW}Umladen: {CURRENCY_LONG} STR_FEEDER :{YELLOW}Umladen: {CURRENCY_LONG} -STR_FEEDER_INCOME_TINY :{TINY_FONT}{YELLOW}Transfer: {CURRENCY_LONG}{WHITE} / {GREEN}Einnahmen: {CURRENCY_LONG} -STR_FEEDER_INCOME :{YELLOW}Transfer: {CURRENCY_LONG}{WHITE} / {GREEN}Einnahmen: {CURRENCY_LONG} -STR_FEEDER_COST_TINY :{TINY_FONT}{YELLOW}Transfer: {CURRENCY_LONG}{WHITE} / {RED}Kosten: {CURRENCY_LONG} -STR_FEEDER_COST :{YELLOW}Transfer: {CURRENCY_LONG}{WHITE} / {RED}Kosten: {CURRENCY_LONG} +STR_FEEDER_INCOME_TINY :{TINY_FONT}{YELLOW}Umladen: {CURRENCY_LONG}{WHITE} / {GREEN}Einnahmen: {CURRENCY_LONG} +STR_FEEDER_INCOME :{YELLOW}Umladen: {CURRENCY_LONG}{WHITE} / {GREEN}Einnahmen: {CURRENCY_LONG} +STR_FEEDER_COST_TINY :{TINY_FONT}{YELLOW}Umladen: {CURRENCY_LONG}{WHITE} / {RED}Kosten: {CURRENCY_LONG} +STR_FEEDER_COST :{YELLOW}Umladen: {CURRENCY_LONG}{WHITE} / {RED}Kosten: {CURRENCY_LONG} STR_MESSAGE_ESTIMATED_COST :{WHITE}Geschätzte Kosten: {CURRENCY_LONG} STR_MESSAGE_ESTIMATED_INCOME :{WHITE}Geschätzte Einnahmen: {CURRENCY_LONG} @@ -4278,7 +4278,7 @@ STR_GAME_SAVELOAD_NOT_AVAILABLE :Umgebung->Städte eingestellt werden STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Straßenarbeiten sind im Gange -STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Stadt kann nicht gelöscht werden...{}Eine Station oder ein Depot bezieht sich auf diese Stadt oder ein Feld im städtischen Besitz kann nicht entfernt werden. +STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Stadt kann nicht gelöscht werden ...{}Eine Station oder ein Depot bezieht sich auf diese Stadt oder ein Feld im städtischen Besitz kann nicht entfernt werden. STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... es gibt keinen geeigneten Standort für die Statue im Zentrum dieser Stadt # Industry related errors STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... zu viele Industrien -STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Industrie kann nicht erzeugt werden... -STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} kann hier nicht gebaut werden... -STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Industrie kann hier nicht gebaut werden... +STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Industrie kann nicht erzeugt werden ... +STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Industrie kann hier nicht gebaut werden ... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... zu nah an einer anderen Industrie STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... erst muss eine Stadt gegründet werden STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... pro Stadt nur einmal erlaubt @@ -4398,37 +4398,37 @@ STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Es konnt STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Karteneinstellungen ändern, um eine bessere Karte zu erzeugen # Station construction related errors -STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Bahnhof kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Bushaltestelle kann nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Lkw-Ladeplatz kann nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Straßenbahnhaltestelle kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Güterverladestelle kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Hafen kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Flughafen kann hier nicht gebaut werden... +STR_ERROR_CAN_T_BUILD_RAILROAD_STATION :{WHITE}Bahnhof kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Bushaltestelle kann nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Lkw-Ladeplatz kann nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Straßenbahnhaltestelle kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Güterverladestelle kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Hafen kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Flughafen kann hier nicht gebaut werden ... STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grenzt an mehr als eine vorhandene Station -STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}...Station ist zu groß +STR_ERROR_STATION_TOO_SPREAD_OUT :{WHITE}... Station ist zu groß STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Zu viele Stationen im Umkreis STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Zu viele Bahnsteigteile STR_ERROR_TOO_MANY_BUS_STOPS :{WHITE}Zu viele Bushaltestellen STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Zu viele Lkw-Ladeplätze STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Zu dicht an einem anderen Hafen STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Zu dicht an einem anderen Flughafen -STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Station kann nicht umbenannt werden... +STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Station kann nicht umbenannt werden ... STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... diese Straße ist in kommunaler Trägerschaft STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... Straße verläuft in die falsche Richtung STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... Bus- und Lkw-Haltestellen können nicht um die Kurve gehen STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... Bus- und Lkw-Haltestellen können keine Abzweigung haben # Station destruction related errors -STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Dieser Teil der Station kann nicht entfernt werden... +STR_ERROR_CAN_T_REMOVE_PART_OF_STATION :{WHITE}Dieser Teil der Station kann nicht entfernt werden ... STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST :{WHITE}Bahnhof muss erst abgerissen werden -STR_ERROR_CAN_T_REMOVE_BUS_STATION :{WHITE}Bushaltestelle kann nicht entfernt werden... -STR_ERROR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}LKW-Ladestelle kann nicht entfernt werden... -STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION :{WHITE}Straßenbahnhaltestelle kann nicht entfernt werden... -STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION :{WHITE}Güterverladestelle kann nicht entfernt werden... +STR_ERROR_CAN_T_REMOVE_BUS_STATION :{WHITE}Bushaltestelle kann nicht entfernt werden ... +STR_ERROR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}Lkw-Ladestelle kann nicht entfernt werden ... +STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION :{WHITE}Straßenbahnhaltestelle kann nicht entfernt werden ... +STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION :{WHITE}Güterverladestelle kann nicht entfernt werden ... STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST :{WHITE}Haltestelle muss erst entfernt werden -STR_ERROR_THERE_IS_NO_STATION :{WHITE}...hier ist keine Station +STR_ERROR_THERE_IS_NO_STATION :{WHITE}... hier ist keine Station STR_ERROR_MUST_DEMOLISH_RAILROAD :{WHITE}Bahnhof muss erst abgerissen werden STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST :{WHITE}Bushaltestelle muss erst abgerissen werden @@ -4442,35 +4442,35 @@ STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Flughafe STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grenzt an mehr als einen vorhandenen Wegpunkt STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Zu nahe an einem anderen Wegpunkt -STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Wegpunkt kann hier nicht gebaut werden... -STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Boje kann hier nicht platziert werden... -STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Wegpunktname kann nicht geändert werden... +STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Wegpunkt kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Boje kann hier nicht platziert werden ... +STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Wegpunktname kann nicht geändert werden ... -STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}Wegpunkt kann hier nicht entfernt werden... +STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}Wegpunkt kann hier nicht entfernt werden ... STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Wegpunkt muss erst abgerissen werden STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... Boje ist im Weg STR_ERROR_BUOY_IS_IN_USE :{WHITE}... Boje wird von einer anderen Firma benutzt! # Depot related errors -STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Zugdepot kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Fahrzeugdepot kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Straßenbahndepot kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Werft kann hier nicht gebaut werden... +STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Zugdepot kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Fahrzeugdepot kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Straßenbahndepot kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Werft kann hier nicht gebaut werden ... -STR_ERROR_CAN_T_RENAME_DEPOT :{WHITE}Depot kann nicht umbenannt werden... +STR_ERROR_CAN_T_RENAME_DEPOT :{WHITE}Depot kann nicht umbenannt werden ... -STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}...der Zug muss dazu im Depot halten -STR_ERROR_ROAD_VEHICLE_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}...das Straßenfahrzeug muss dazu in einem Depot halten -STR_ERROR_SHIP_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}...das Schiff muss dazu in der Werft halten -STR_ERROR_AIRCRAFT_MUST_BE_STOPPED_INSIDE_HANGAR :{WHITE}...das Flugzeug muss dazu im Hangar halten +STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}... der Zug muss dazu im Depot halten +STR_ERROR_ROAD_VEHICLE_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}... das Straßenfahrzeug muss dazu in einem Depot halten +STR_ERROR_SHIP_MUST_BE_STOPPED_INSIDE_DEPOT :{WHITE}... das Schiff muss dazu in der Werft halten +STR_ERROR_AIRCRAFT_MUST_BE_STOPPED_INSIDE_HANGAR :{WHITE}... das Flugzeug muss dazu im Hangar halten STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT :{WHITE}Züge können nur verändert werden, wenn sie im Depot halten STR_ERROR_TRAIN_TOO_LONG :{WHITE}Zug zu lang -STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE :{WHITE}Fahrzeug kann nicht umgedreht werden... +STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE :{WHITE}Fahrzeug kann nicht umgedreht werden ... STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS :{WHITE}Fahrzeuge, die aus mehreren Einheiten bestehen, können nicht umgedreht werden STR_ERROR_INCOMPATIBLE_RAIL_TYPES :inkompatible Gleistypen -STR_ERROR_CAN_T_MOVE_VEHICLE :{WHITE}Fahrzeug kann nicht bewegt werden... +STR_ERROR_CAN_T_MOVE_VEHICLE :{WHITE}Fahrzeug kann nicht bewegt werden ... STR_ERROR_REAR_ENGINE_FOLLOW_FRONT :{WHITE}Hintere Lok folgt immer der vorderen Lok STR_ERROR_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Weg zum Depot kann nicht gefunden werden STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Fahrzeugdepot unauffindbar @@ -4486,56 +4486,56 @@ STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}Neues Fa # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Unmögliche Gleisverbindung -STR_ERROR_MUST_REMOVE_SIGNALS_FIRST :{WHITE}Signal muß zuerst entfernt werden +STR_ERROR_MUST_REMOVE_SIGNALS_FIRST :{WHITE}Signal muss zuerst entfernt werden STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}Keine geeigneten Gleise STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Gleise müssen erst abgerissen werden STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Einbahnstraße oder blockierter Weg STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Bahnübergänge sind für diesen Schienentyp nicht erlaubt STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Bahnübergänge sind für diesen Straßentyp nicht erlaubt -STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Signal kann hier nicht aufgestellt werden... -STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Gleise können hier nicht verlegt werden... -STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Gleise können nicht abgerissen werden... -STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Signale können hier nicht entfernt werden... -STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Kann Signaltyp hier nicht ändern... +STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Signal kann hier nicht aufgestellt werden ... +STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Gleise können hier nicht verlegt werden ... +STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Gleise können nicht abgerissen werden ... +STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Signale können hier nicht entfernt werden ... +STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Kann Signaltyp hier nicht ändern ... STR_ERROR_THERE_IS_NO_RAILROAD_TRACK :{WHITE}... hier ist kein Gleis STR_ERROR_THERE_ARE_NO_SIGNALS :{WHITE}... hier sind keine Signale -STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Gleistyp kann hier nicht geändert werden... +STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Gleistyp kann hier nicht geändert werden ... # Road construction errors STR_ERROR_MUST_REMOVE_ROAD_FIRST :{WHITE}Straße muss erst entfernt werden STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION :{WHITE}... Einbahnstraßen können keine Abzweigung haben -STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Straße kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Straßenbahngleise können hier nicht gebaut werden... -STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Diese Straße kann nicht entfernt werden... -STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Straßenbahngleise können hier nicht entfernt werden... -STR_ERROR_THERE_IS_NO_ROAD :{WHITE}...hier ist keine Straße -STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}...hier ist kein Straßenbahngleis -STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Straßentyp kann hier nicht geändert werden... -STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Straßenbahngleistyp kann hier nicht geändert werden... +STR_ERROR_CAN_T_BUILD_ROAD_HERE :{WHITE}Straße kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE :{WHITE}Straßenbahngleise können hier nicht gebaut werden ... +STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Diese Straße kann nicht entfernt werden ... +STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Straßenbahngleise können hier nicht entfernt werden ... +STR_ERROR_THERE_IS_NO_ROAD :{WHITE}... hier ist keine Straße +STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}... hier ist kein Straßenbahngleis +STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Straßentyp kann hier nicht geändert werden ... +STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Straßenbahngleistyp kann hier nicht geändert werden ... STR_ERROR_NO_SUITABLE_ROAD :{WHITE}Keine geeignete Straße STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}Keine geeigneten Straßenbahnschienen STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... inkompatible Straßenbahngleise # Waterway construction errors -STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Kanal kann hier nicht gebaut werden... -STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Schleuse kann hier nicht gebaut werden... -STR_ERROR_CAN_T_PLACE_RIVERS :{WHITE}Flüsse können hier nicht platziert werden... +STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Kanal kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_BUILD_LOCKS :{WHITE}Schleuse kann hier nicht gebaut werden ... +STR_ERROR_CAN_T_PLACE_RIVERS :{WHITE}Flüsse können hier nicht platziert werden ... STR_ERROR_MUST_BE_BUILT_ON_WATER :{WHITE}... muss auf Wasser gebaut werden STR_ERROR_CAN_T_BUILD_ON_WATER :{WHITE}... kann nicht auf Wasser gebaut werden STR_ERROR_CAN_T_BUILD_ON_SEA :{WHITE}... kann nicht auf offener See errichtet werden STR_ERROR_CAN_T_BUILD_ON_CANAL :{WHITE}... kann nicht auf Kanal errichtet werden -STR_ERROR_CAN_T_BUILD_ON_RIVER :{WHITE}... kann nicht auf Fluß errichtet werden +STR_ERROR_CAN_T_BUILD_ON_RIVER :{WHITE}... kann nicht auf Fluss errichtet werden STR_ERROR_MUST_DEMOLISH_CANAL_FIRST :{WHITE}Kanal muss erst abgerissen werden -STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Aquädukt kann hier nicht gebaut werden... +STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Aquädukt kann hier nicht gebaut werden ... # Tree related errors STR_ERROR_TREE_ALREADY_HERE :{WHITE}... hier sind bereits Bäume STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE :{WHITE}... falsches Gelände für die Baumart -STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Baum kann hier nicht gepflanzt werden... +STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Baum kann hier nicht gepflanzt werden ... # Bridge related errors -STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Brücke kann hier nicht gebaut werden... +STR_ERROR_CAN_T_BUILD_BRIDGE_HERE :{WHITE}Brücke kann hier nicht gebaut werden ... STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST :{WHITE}Die Brücke muss erst abgerissen werden STR_ERROR_CAN_T_START_AND_END_ON :{WHITE}Anfang und Ende können nicht im selben Feld liegen STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT :{WHITE}Brückenköpfe nicht auf der selben Höhe @@ -4547,7 +4547,7 @@ STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... Brü STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Die Brücke würde außerhalb der Karte enden # Tunnel related errors -STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tunnel kann hier nicht gebaut werden... +STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tunnel kann hier nicht gebaut werden ... STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL :{WHITE}Platz ist nicht für einen Tunnel geeignet STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST :{WHITE}Der Tunnel muss zuerst abgerissen werden STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY :{WHITE}Ein anderer Tunnel ist im Weg @@ -4557,21 +4557,21 @@ STR_ERROR_TUNNEL_TOO_LONG :{WHITE}... Tunn # Object related errors STR_ERROR_TOO_MANY_OBJECTS :{WHITE}... zu viele Objekte -STR_ERROR_CAN_T_BUILD_OBJECT :{WHITE}Objekt kann nicht gebaut werden... -STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Gegenstand im Weg +STR_ERROR_CAN_T_BUILD_OBJECT :{WHITE}Objekt kann nicht gebaut werden ... +STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Objekt im Weg STR_ERROR_COMPANY_HEADQUARTERS_IN :{WHITE}... Firmensitz ist im Weg -STR_ERROR_CAN_T_PURCHASE_THIS_LAND :{WHITE}Das Land kann nicht erworben werden... +STR_ERROR_CAN_T_PURCHASE_THIS_LAND :{WHITE}Das Land kann nicht erworben werden ... STR_ERROR_YOU_ALREADY_OWN_IT :{WHITE}... ist bereits im Besitz der eigenen Firma! # Group related errors -STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Gruppe kann nicht erstellt werden... -STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Gruppe kann nicht gelöscht werden... -STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Gruppe kann nicht umbenannt werden... -STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Übergeordnete Gruppe kann nicht gesetzt werden... +STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Gruppe kann nicht erstellt werden ... +STR_ERROR_GROUP_CAN_T_DELETE :{WHITE}Gruppe kann nicht gelöscht werden ... +STR_ERROR_GROUP_CAN_T_RENAME :{WHITE}Gruppe kann nicht umbenannt werden ... +STR_ERROR_GROUP_CAN_T_SET_PARENT :{WHITE}Übergeordnete Gruppe kann nicht gesetzt werden ... STR_ERROR_GROUP_CAN_T_SET_PARENT_RECURSION :{WHITE}... Schleifen sind in der Gruppenhierarchie nicht erlaubt -STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Entfernen aller Fahrzeuge dieser Gruppe nicht möglich... -STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Fahrzeug kann nicht zu dieser Gruppe hinzugefügt werden... -STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Fahrzeuge mit gemeinsamen Fahrplan können nicht zur Gruppe hinzugefügt werden... +STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES :{WHITE}Entfernen aller Fahrzeuge dieser Gruppe nicht möglich ... +STR_ERROR_GROUP_CAN_T_ADD_VEHICLE :{WHITE}Fahrzeug kann nicht zu dieser Gruppe hinzugefügt werden ... +STR_ERROR_GROUP_CAN_T_ADD_SHARED_VEHICLE :{WHITE}Fahrzeuge mit gemeinsamen Fahrplan können nicht zur Gruppe hinzugefügt werden ... # Generic vehicle errors STR_ERROR_TRAIN_IN_THE_WAY :{WHITE}Zug ist im Weg @@ -4579,40 +4579,40 @@ STR_ERROR_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Fahrzeug STR_ERROR_SHIP_IN_THE_WAY :{WHITE}Schiff ist im Weg STR_ERROR_AIRCRAFT_IN_THE_WAY :{WHITE}Flugzeug ist auf dem Weg -STR_ERROR_CAN_T_REFIT_TRAIN :{WHITE}Zug kann nicht umgerüstet werden... -STR_ERROR_CAN_T_REFIT_ROAD_VEHICLE :{WHITE}Straßenfahrzeug kann nicht umgerüstet werden... -STR_ERROR_CAN_T_REFIT_SHIP :{WHITE}Schiff kann nicht umgerüstet werden... +STR_ERROR_CAN_T_REFIT_TRAIN :{WHITE}Zug kann nicht umgerüstet werden ... +STR_ERROR_CAN_T_REFIT_ROAD_VEHICLE :{WHITE}Straßenfahrzeug kann nicht umgerüstet werden ... +STR_ERROR_CAN_T_REFIT_SHIP :{WHITE}Schiff kann nicht umgerüstet werden ... STR_ERROR_CAN_T_REFIT_AIRCRAFT :{WHITE}Flugzeug kann nicht umgerüstet werden... -STR_ERROR_CAN_T_RENAME_TRAIN :{WHITE}Zug kann nicht benannt werden... -STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht benannt werden... -STR_ERROR_CAN_T_RENAME_SHIP :{WHITE}Schiff kann nicht benannt werden... -STR_ERROR_CAN_T_RENAME_AIRCRAFT :{WHITE}Flugzeug kann nicht benannt werden... +STR_ERROR_CAN_T_RENAME_TRAIN :{WHITE}Zug kann nicht benannt werden ... +STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht benannt werden ... +STR_ERROR_CAN_T_RENAME_SHIP :{WHITE}Schiff kann nicht benannt werden ... +STR_ERROR_CAN_T_RENAME_AIRCRAFT :{WHITE}Flugzeug kann nicht benannt werden ... STR_ERROR_CAN_T_STOP_START_TRAIN :{WHITE}Zug kann nicht angehalten{} oder losgeschickt werden ... -STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht angehalten{} oder losgeschickt werden... -STR_ERROR_CAN_T_STOP_START_SHIP :{WHITE}Schiff kann nicht angehalten{} oder losgeschickt werden... -STR_ERROR_CAN_T_STOP_START_AIRCRAFT :{WHITE}Flugzeug kann nicht angehalten{} oder losgeschickt werden... +STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht angehalten{} oder losgeschickt werden ... +STR_ERROR_CAN_T_STOP_START_SHIP :{WHITE}Schiff kann nicht angehalten{} oder losgeschickt werden ... +STR_ERROR_CAN_T_STOP_START_AIRCRAFT :{WHITE}Flugzeug kann nicht angehalten{} oder losgeschickt werden ... -STR_ERROR_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Zug kann nicht ins Depot geschickt werden... -STR_ERROR_CAN_T_SEND_ROAD_VEHICLE_TO_DEPOT :{WHITE}Fahrzeug kann nicht ins Depot geschickt werden... -STR_ERROR_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Schiff kann nicht in die Werft geschickt werden... -STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR :{WHITE}Flugzeug kann nicht in den Hangar geschickt werden... +STR_ERROR_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Zug kann nicht ins Depot geschickt werden ... +STR_ERROR_CAN_T_SEND_ROAD_VEHICLE_TO_DEPOT :{WHITE}Fahrzeug kann nicht ins Depot geschickt werden ... +STR_ERROR_CAN_T_SEND_SHIP_TO_DEPOT :{WHITE}Schiff kann nicht in die Werft geschickt werden ... +STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR :{WHITE}Flugzeug kann nicht in den Hangar geschickt werden ... -STR_ERROR_CAN_T_BUY_TRAIN :{WHITE}Schienenfahrzeug kann nicht gekauft werden... -STR_ERROR_CAN_T_BUY_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht gekauft werden... -STR_ERROR_CAN_T_BUY_SHIP :{WHITE}Schiff kann nicht gekauft werden... -STR_ERROR_CAN_T_BUY_AIRCRAFT :{WHITE}Flugzeug kann nicht gekauft werden... +STR_ERROR_CAN_T_BUY_TRAIN :{WHITE}Schienenfahrzeug kann nicht gekauft werden ... +STR_ERROR_CAN_T_BUY_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht gekauft werden ... +STR_ERROR_CAN_T_BUY_SHIP :{WHITE}Schiff kann nicht gekauft werden ... +STR_ERROR_CAN_T_BUY_AIRCRAFT :{WHITE}Flugzeug kann nicht gekauft werden ... -STR_ERROR_CAN_T_RENAME_TRAIN_TYPE :{WHITE}Zugtyp kann nicht umbenannt werden... -STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Fahrzeug kann nicht umbenannt werden... -STR_ERROR_CAN_T_RENAME_SHIP_TYPE :{WHITE}Schiffstyp kann nicht umbenannt werden... -STR_ERROR_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Flugzeug kann nicht umbenannt werden... +STR_ERROR_CAN_T_RENAME_TRAIN_TYPE :{WHITE}Zugtyp kann nicht umbenannt werden ... +STR_ERROR_CAN_T_RENAME_ROAD_VEHICLE_TYPE :{WHITE}Fahrzeug kann nicht umbenannt werden ... +STR_ERROR_CAN_T_RENAME_SHIP_TYPE :{WHITE}Schiffstyp kann nicht umbenannt werden ... +STR_ERROR_CAN_T_RENAME_AIRCRAFT_TYPE :{WHITE}Flugzeug kann nicht umbenannt werden ... -STR_ERROR_CAN_T_SELL_TRAIN :{WHITE}Schienenfahrzeug kann nicht verkauft werden... -STR_ERROR_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht verkauft werden... -STR_ERROR_CAN_T_SELL_SHIP :{WHITE}Schiff kann nicht verkauft werden... -STR_ERROR_CAN_T_SELL_AIRCRAFT :{WHITE}Flugzeug kann nicht verkauft werden... +STR_ERROR_CAN_T_SELL_TRAIN :{WHITE}Schienenfahrzeug kann nicht verkauft werden ... +STR_ERROR_CAN_T_SELL_ROAD_VEHICLE :{WHITE}Fahrzeug kann nicht verkauft werden ... +STR_ERROR_CAN_T_SELL_SHIP :{WHITE}Schiff kann nicht verkauft werden ... +STR_ERROR_CAN_T_SELL_AIRCRAFT :{WHITE}Flugzeug kann nicht verkauft werden ... STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE :{WHITE}Fahrzeug nicht verfügbar STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE :{WHITE}Fahrzeug nicht verfügbar @@ -4620,7 +4620,7 @@ STR_ERROR_SHIP_NOT_AVAILABLE :{WHITE}Schiff n STR_ERROR_AIRCRAFT_NOT_AVAILABLE :{WHITE}Flugzeug nicht verfügbar STR_ERROR_TOO_MANY_VEHICLES_IN_GAME :{WHITE}Zu viele Fahrzeuge im Spiel -STR_ERROR_CAN_T_CHANGE_SERVICING :{WHITE}Das Wartungsintervall kann nicht geändert werden... +STR_ERROR_CAN_T_CHANGE_SERVICING :{WHITE}Das Wartungsintervall kann nicht geändert werden ... STR_ERROR_VEHICLE_IS_DESTROYED :{WHITE}... Fahrzeug ist zerstört @@ -4630,42 +4630,42 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}Noch kei STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Ein neues Spiel nach {DATE_SHORT} beginnen oder ein NewGRF-Fahrzeugset mit früher verfügbaren Fahrzeugen verwenden # Specific vehicle errors -STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Der Zug kann das Signal nicht gefahrlos passieren... -STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Die Zugbewegung kann nicht umgekehrt werden... +STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Der Zug kann das Signal nicht gefahrlos passieren ... +STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Die Zugbewegung kann nicht umgekehrt werden ... STR_ERROR_TRAIN_START_NO_POWER :Der Zug hat keine Antriebsenergie -STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Das Fahrzeug kann nicht wenden... +STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Das Fahrzeug kann nicht wenden ... STR_ERROR_AIRCRAFT_IS_IN_FLIGHT :{WHITE}Das Flugzeug ist in der Luft # Order related errors STR_ERROR_NO_MORE_SPACE_FOR_ORDERS :{WHITE}Kein Platz für weitere Aufträge STR_ERROR_TOO_MANY_ORDERS :{WHITE}Zu viele Aufträge -STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}Neuer Auftrag kann nicht hinzugefügt werden... -STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}Auftrag kann nicht gelöscht werden... -STR_ERROR_CAN_T_MODIFY_THIS_ORDER :{WHITE}Auftrag kann nicht bearbeitet werden... -STR_ERROR_CAN_T_MOVE_THIS_ORDER :{WHITE}Auftrag kann nicht verschoben werden... -STR_ERROR_CAN_T_SKIP_ORDER :{WHITE}Auftrag kann nicht ausgelassen werden... -STR_ERROR_CAN_T_SKIP_TO_ORDER :{WHITE}Springen zum ausgewählten Auftrag nicht möglich... +STR_ERROR_CAN_T_INSERT_NEW_ORDER :{WHITE}Neuer Auftrag kann nicht hinzugefügt werden ... +STR_ERROR_CAN_T_DELETE_THIS_ORDER :{WHITE}Auftrag kann nicht gelöscht werden ... +STR_ERROR_CAN_T_MODIFY_THIS_ORDER :{WHITE}Auftrag kann nicht bearbeitet werden ... +STR_ERROR_CAN_T_MOVE_THIS_ORDER :{WHITE}Auftrag kann nicht verschoben werden ... +STR_ERROR_CAN_T_SKIP_ORDER :{WHITE}Auftrag kann nicht ausgelassen werden ... +STR_ERROR_CAN_T_SKIP_TO_ORDER :{WHITE}Springen zum ausgewählten Auftrag nicht möglich ... STR_ERROR_CAN_T_COPY_SHARE_ORDER :{WHITE}... Fahrzeug kann nicht alle Stationen erreichen STR_ERROR_CAN_T_ADD_ORDER :{WHITE}... Fahrzeug kann diese Station nicht erreichen STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... ein Fahrzeug, welches diesen gemeinsamen Fahrplan nutzt, kann die Station nicht erreichen -STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Fehler beim Erstellen eines gemeinsam genutzten Fahrplans... +STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Fehler beim Erstellen eines gemeinsam genutzten Fahrplans ... STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Gemeinsame Aufträge können nicht aufgehoben werden... -STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Fahrplan kann nicht kopiert werden... +STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Fahrplan kann nicht kopiert werden ... STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... zu weit vom vorherigen Bestimmungsort entfernt STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... Luftfahrzeug hat zu geringe Reichweite # Timetable related errors -STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Fahrplan kann nicht erstellt werden... +STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Fahrplan kann nicht erstellt werden ... STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Fahrzeuge halten nur an Stationen STR_ERROR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}Das Fahrzeug hält nicht an dieser Station # Sign related errors STR_ERROR_TOO_MANY_SIGNS :{WHITE}... zu viele Schilder -STR_ERROR_CAN_T_PLACE_SIGN_HERE :{WHITE}Schild kann hier nicht aufgestellt werden... -STR_ERROR_CAN_T_CHANGE_SIGN_NAME :{WHITE}Schildtext kann nicht geändert werden... +STR_ERROR_CAN_T_PLACE_SIGN_HERE :{WHITE}Schild kann hier nicht aufgestellt werden ... +STR_ERROR_CAN_T_CHANGE_SIGN_NAME :{WHITE}Schildtext kann nicht geändert werden ... STR_ERROR_CAN_T_DELETE_SIGN :{WHITE}Kann Schild nicht löschen... # Translatable comment for OpenTTD's desktop shortcut @@ -4790,7 +4790,7 @@ STR_SV_STNAME_BUOY :{STRING} STR_SV_STNAME_WAYPOINT :{STRING} ##id 0x6020 STR_SV_STNAME_ANNEXE :{STRING} Anbau -STR_SV_STNAME_SIDINGS :{STRING} Nebengleis +STR_SV_STNAME_SIDINGS :{STRING} Seite STR_SV_STNAME_BRANCH :{STRING} Abzweig STR_SV_STNAME_UPPER :Ober-{STRING} STR_SV_STNAME_LOWER :Unter-{STRING} @@ -4885,10 +4885,10 @@ STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_TOY_VAN :Spielwarentrans STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_BATTERY_TRUCK :Batterietransporter STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_FIZZY_DRINK_TRUCK :Limonadetransporter STR_VEHICLE_NAME_TRAIN_WAGON_MONORAIL_PLASTIC_TRUCK :Plastikwaggon -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV1_LEVIATHAN_ELECTRIC :Lev1 „Leviathan“ (elektrisch) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 „Cyclops“ (elektrisch) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV3_PEGASUS_ELECTRIC :Lev3 „Pegasus“ (elektrisch) -STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV4_CHIMAERA_ELECTRIC :Lev4 „Chimaera“ (elektrisch) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV1_LEVIATHAN_ELECTRIC :Lev1 „Leviathan“ (Elektrisch) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV2_CYCLOPS_ELECTRIC :Lev2 „Cyclops“ (Elektrisch) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV3_PEGASUS_ELECTRIC :Lev3 „Pegasus“ (Elektrisch) +STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_LEV4_CHIMAERA_ELECTRIC :Lev4 „Chimaera“ (Elektrisch) STR_VEHICLE_NAME_TRAIN_ENGINE_MAGLEV_WIZZOWOW_ROCKETEER :Wizzowow Rocketeer STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PASSENGER_CAR :Passagierwaggon STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_MAIL_VAN :Postwaggon @@ -4917,105 +4917,105 @@ STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_TOY_VAN :Spielwarentrans STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_BATTERY_TRUCK :Batterielaster STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_FIZZY_DRINK_TRUCK :Limonadetransporter STR_VEHICLE_NAME_TRAIN_WAGON_MAGLEV_PLASTIC_TRUCK :Plastikwaggon -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_REGAL_BUS :MPS Regal Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_HEREFORD_LEOPARD_BUS :Hereford Leopard Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_BUS :Foster Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_MKII_SUPERBUS :Foster MkII Superbus -STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKI_BUS :Ploddyphut MkI Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKII_BUS :Ploddyphut MkII Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKIII_BUS :Ploddyphut MkIII Bus -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_COAL_TRUCK :Balogh Kohlelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_COAL_TRUCK :Uhl Kohlelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_DW_COAL_TRUCK :DW Kohlelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_MAIL_TRUCK :MPS Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_REYNARD_MAIL_TRUCK :Reynard Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_MAIL_TRUCK :Perry Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_MAIL_TRUCK :MightyMover Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_MAIL_TRUCK :Powernaught Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_MAIL_TRUCK :Wizzowow Postwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_WITCOMBE_OIL_TANKER :Witcombe Öltanker -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_OIL_TANKER :Foster Öltanker -STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_OIL_TANKER :Perry Öltanker -STR_VEHICLE_NAME_ROAD_VEHICLE_TALBOTT_LIVESTOCK_VAN :Talbott Viehtransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_LIVESTOCK_VAN :Uhl Viehtransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_LIVESTOCK_VAN :Foster Viehtransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_GOODS_TRUCK :Balogh Gütertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_CRAIGHEAD_GOODS_TRUCK :Craighead Gütertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_GOODS_TRUCK :Goss Gütertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_HEREFORD_GRAIN_TRUCK :Hereford Getreidetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_THOMAS_GRAIN_TRUCK :Thomas Getreidetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_GRAIN_TRUCK :Goss Getreidetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_WITCOMBE_WOOD_TRUCK :Witcombe Holzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_WOOD_TRUCK :Foster Holzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MORELAND_WOOD_TRUCK :Moreland Holzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_IRON_ORE_TRUCK :MPS Eisenerzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_IRON_ORE_TRUCK :Uhl Eisenerzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_CHIPPY_IRON_ORE_TRUCK :Chippy Eisenerzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_STEEL_TRUCK :Balogh Stahltransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_STEEL_TRUCK :Uhl Stahltransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_KELLING_STEEL_TRUCK :Kelling Stahltransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_ARMORED_TRUCK :Balogh Sicherheitstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_ARMORED_TRUCK :Uhl Sicherheitstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_ARMORED_TRUCK :Foster Sicherheitstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_FOOD_VAN :Foster Nahrungstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_FOOD_VAN :Perry Nahrungstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_CHIPPY_FOOD_VAN :Chippy Nahrungstransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_PAPER_TRUCK :Uhl Papierlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_PAPER_TRUCK :Balogh Papierlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_PAPER_TRUCK :MPS Papierlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_COPPER_ORE_TRUCK :MPS Kupfererzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_COPPER_ORE_TRUCK :Uhl Kupfererzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_COPPER_ORE_TRUCK :Goss Kupfererzlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_WATER_TANKER :Uhl Wassertankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_WATER_TANKER :Balogh Wassertankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_WATER_TANKER :MPS Wassertankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_FRUIT_TRUCK :Balogh Früchtetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_FRUIT_TRUCK :Uhl Früchtetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_KELLING_FRUIT_TRUCK :Kelling Früchtetransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_RUBBER_TRUCK :Balogh Kautschuklaster -STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_RUBBER_TRUCK :Uhl Kautschuklaster -STR_VEHICLE_NAME_ROAD_VEHICLE_RMT_RUBBER_TRUCK :RMT Kautschuklaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover Zuckertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_SUGAR_TRUCK :Powernaught Zuckertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_SUGAR_TRUCK :Wizzowow Zuckertransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_COLA_TRUCK :MightyMover Cola-Tankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_COLA_TRUCK :Powernaught Cola-Tankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_COLA_TRUCK :Wizzowow Cola-Tankwagen -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_COTTON_CANDY :MightyMover Zuckerwattelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_COTTON_CANDY :Powernaught Zuckerwattelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow Zuckerwattelaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover Karamelllaster -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_TOFFEE_TRUCK :Powernaught Karamelllaster -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_TOFFEE_TRUCK :Wizzowow Karamelllaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_TOY_VAN :MightyMover Spielwarentransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_TOY_VAN :Powernaught Spielwarentransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_REGAL_BUS :MPS-Regal-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_HEREFORD_LEOPARD_BUS :Hereford-Leopard-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_BUS :Foster-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_MKII_SUPERBUS :Foster-MkII-Superbus +STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKI_BUS :Ploddyphut-MkI-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKII_BUS :Ploddyphut-MkII-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_PLODDYPHUT_MKIII_BUS :Ploddyphut-MkIII-Bus +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_COAL_TRUCK :Balogh-Kohlelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_COAL_TRUCK :Uhl-Kohlelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_DW_COAL_TRUCK :DW-Kohlelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_MAIL_TRUCK :MPS-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_REYNARD_MAIL_TRUCK :Reynard-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_MAIL_TRUCK :Perry-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_MAIL_TRUCK :MightyMover-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_MAIL_TRUCK :Powernaught-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_MAIL_TRUCK :Wizzowow-Postwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_WITCOMBE_OIL_TANKER :Witcombe-Öltanker +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_OIL_TANKER :Foster-Öltanker +STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_OIL_TANKER :Perry-Öltanker +STR_VEHICLE_NAME_ROAD_VEHICLE_TALBOTT_LIVESTOCK_VAN :Talbott-Viehtransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_LIVESTOCK_VAN :Uhl-Viehtransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_LIVESTOCK_VAN :Foster-Viehtransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_GOODS_TRUCK :Balogh-Gütertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_CRAIGHEAD_GOODS_TRUCK :Craighead-Gütertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_GOODS_TRUCK :Goss-Gütertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_HEREFORD_GRAIN_TRUCK :Hereford-Getreidetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_THOMAS_GRAIN_TRUCK :Thomas-Getreidetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_GRAIN_TRUCK :Goss-Getreidetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_WITCOMBE_WOOD_TRUCK :Witcombe-Holzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_WOOD_TRUCK :Foster-Holzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MORELAND_WOOD_TRUCK :Moreland-Holzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_IRON_ORE_TRUCK :MPS-Eisenerzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_IRON_ORE_TRUCK :Uhl-Eisenerzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_CHIPPY_IRON_ORE_TRUCK :Chippy-Eisenerzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_STEEL_TRUCK :Balogh-Stahltransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_STEEL_TRUCK :Uhl-Stahltransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_KELLING_STEEL_TRUCK :Kelling-Stahltransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_ARMORED_TRUCK :Balogh-Sicherheitstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_ARMORED_TRUCK :Uhl-Sicherheitstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_ARMORED_TRUCK :Foster-Sicherheitstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_FOSTER_FOOD_VAN :Foster-Nahrungstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_PERRY_FOOD_VAN :Perry-Nahrungstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_CHIPPY_FOOD_VAN :Chippy-Nahrungstransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_PAPER_TRUCK :Uhl-Papierlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_PAPER_TRUCK :Balogh-Papierlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_PAPER_TRUCK :MPS-Papierlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_COPPER_ORE_TRUCK :MPS-Kupfererzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_COPPER_ORE_TRUCK :Uhl-Kupfererzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_GOSS_COPPER_ORE_TRUCK :Goss-Kupfererzlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_WATER_TANKER :Uhl-Wassertankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_WATER_TANKER :Balogh-Wassertankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_WATER_TANKER :MPS-Wassertankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_FRUIT_TRUCK :Balogh-Früchtetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_FRUIT_TRUCK :Uhl-Früchtetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_KELLING_FRUIT_TRUCK :Kelling-Früchtetransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_BALOGH_RUBBER_TRUCK :Balogh-Kautschuklaster +STR_VEHICLE_NAME_ROAD_VEHICLE_UHL_RUBBER_TRUCK :Uhl-Kautschuklaster +STR_VEHICLE_NAME_ROAD_VEHICLE_RMT_RUBBER_TRUCK :RMT-Kautschuklaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_SUGAR_TRUCK :MightyMover-Zuckertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_SUGAR_TRUCK :Powernaught-Zuckertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_SUGAR_TRUCK :Wizzowow-Zuckertransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_COLA_TRUCK :MightyMover-Cola-Tankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_COLA_TRUCK :Powernaught-Cola-Tankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_COLA_TRUCK :Wizzowow-Cola-Tankwagen +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_COTTON_CANDY :MightyMover-Zuckerwattelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_COTTON_CANDY :Powernaught-Zuckerwattelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_COTTON_CANDY_TRUCK :Wizzowow-Zuckerwattelaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_TOFFEE_TRUCK :MightyMover-Karamelllaster +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_TOFFEE_TRUCK :Powernaught-Karamelllaster +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_TOFFEE_TRUCK :Wizzowow-Karamelllaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_TOY_VAN :MightyMover-Spielwarentransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_TOY_VAN :Powernaught-Spielwarentransporter STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_TOY_VAN :Wizzowow Spielwarentransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_CANDY_TRUCK :MightyMover Bonbontransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_CANDY_TRUCK :Powernaught Bonbontransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_CANDY_TRUCK :Wizzowow Bonbontransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_BATTERY_TRUCK :MightyMover Batterielaster -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_BATTERY_TRUCK :Powernaught Batterielaster -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_BATTERY_TRUCK :Wizzowow Batterielaster -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_FIZZY_DRINK :MightyMover Limonadentanker -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_FIZZY_DRINK :Powernaught Limonadentanker -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow Limonadentanker -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover Plastiktransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_PLASTIC_TRUCK :Powernaught Plastiktransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_PLASTIC_TRUCK :Wizzowow Plastiktransporter -STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover Luftblasenlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_BUBBLE_TRUCK :Powernaught Luftblasenlaster -STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_BUBBLE_TRUCK :Wizzowow Luftblasenlaster -STR_VEHICLE_NAME_SHIP_MPS_OIL_TANKER :MPS Öltanker -STR_VEHICLE_NAME_SHIP_CS_INC_OIL_TANKER :CS-Inc. Öltanker -STR_VEHICLE_NAME_SHIP_MPS_PASSENGER_FERRY :MPS Passagierschiff -STR_VEHICLE_NAME_SHIP_FFP_PASSENGER_FERRY :FFP Passagierschiff -STR_VEHICLE_NAME_SHIP_BAKEWELL_300_HOVERCRAFT :Bakewell 300 Luftkissenboot -STR_VEHICLE_NAME_SHIP_CHUGGER_CHUG_PASSENGER :Chugger-Chug Passagierschiff -STR_VEHICLE_NAME_SHIP_SHIVERSHAKE_PASSENGER_FERRY :Shivershake Passagierschiff -STR_VEHICLE_NAME_SHIP_YATE_CARGO_SHIP :Yate Frachter -STR_VEHICLE_NAME_SHIP_BAKEWELL_CARGO_SHIP :Bakewell Frachter -STR_VEHICLE_NAME_SHIP_MIGHTYMOVER_CARGO_SHIP :MightyMover Frachter -STR_VEHICLE_NAME_SHIP_POWERNAUT_CARGO_SHIP :Powernaut Frachter +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_CANDY_TRUCK :MightyMover-Bonbontransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_CANDY_TRUCK :Powernaught-Bonbontransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_CANDY_TRUCK :Wizzowow-Bonbontransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_BATTERY_TRUCK :MightyMover-Batterielaster +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_BATTERY_TRUCK :Powernaught-Batterielaster +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_BATTERY_TRUCK :Wizzowow-Batterielaster +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_FIZZY_DRINK :MightyMover-Limonadentanker +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_FIZZY_DRINK :Powernaught-Limonadentanker +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_FIZZY_DRINK_TRUCK :Wizzowow-Limonadentanker +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_PLASTIC_TRUCK :MightyMover-Plastiktransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_PLASTIC_TRUCK :Powernaught-Plastiktransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_PLASTIC_TRUCK :Wizzowow-Plastiktransporter +STR_VEHICLE_NAME_ROAD_VEHICLE_MIGHTYMOVER_BUBBLE_TRUCK :MightyMover-Luftblasenlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_POWERNAUGHT_BUBBLE_TRUCK :Powernaught-Luftblasenlaster +STR_VEHICLE_NAME_ROAD_VEHICLE_WIZZOWOW_BUBBLE_TRUCK :Wizzowow-Luftblasenlaster +STR_VEHICLE_NAME_SHIP_MPS_OIL_TANKER :MPS-Öltanker +STR_VEHICLE_NAME_SHIP_CS_INC_OIL_TANKER :CS-Inc.-Öltanker +STR_VEHICLE_NAME_SHIP_MPS_PASSENGER_FERRY :MPS-Passagierschiff +STR_VEHICLE_NAME_SHIP_FFP_PASSENGER_FERRY :FFP-Passagierschiff +STR_VEHICLE_NAME_SHIP_BAKEWELL_300_HOVERCRAFT :Bakewell-300-Luftkissenboot +STR_VEHICLE_NAME_SHIP_CHUGGER_CHUG_PASSENGER :Chugger-Chug-Passagierschiff +STR_VEHICLE_NAME_SHIP_SHIVERSHAKE_PASSENGER_FERRY :Shivershake-Passagierschiff +STR_VEHICLE_NAME_SHIP_YATE_CARGO_SHIP :Yate-Frachter +STR_VEHICLE_NAME_SHIP_BAKEWELL_CARGO_SHIP :Bakewell-Frachter +STR_VEHICLE_NAME_SHIP_MIGHTYMOVER_CARGO_SHIP :MightyMover-Frachter +STR_VEHICLE_NAME_SHIP_POWERNAUT_CARGO_SHIP :Powernaut-Frachter STR_VEHICLE_NAME_AIRCRAFT_SAMPSON_U52 :Sampson U52 STR_VEHICLE_NAME_AIRCRAFT_COLEMAN_COUNT :Coleman Count STR_VEHICLE_NAME_AIRCRAFT_FFP_DART :FFP Dart @@ -5054,13 +5054,13 @@ STR_VEHICLE_NAME_AIRCRAFT_PLODDYPHUT_500 :Ploddyphut 500 STR_VEHICLE_NAME_AIRCRAFT_FLASHBANG_X1 :Flashbang X1 STR_VEHICLE_NAME_AIRCRAFT_JUGGERPLANE_M1 :Juggerplane M1 STR_VEHICLE_NAME_AIRCRAFT_FLASHBANG_WIZZER :Flashbang Wizzer -STR_VEHICLE_NAME_AIRCRAFT_TRICARIO_HELICOPTER :Tricario Hubschrauber -STR_VEHICLE_NAME_AIRCRAFT_GURU_X2_HELICOPTER :Guru X2 Hubschrauber -STR_VEHICLE_NAME_AIRCRAFT_POWERNAUT_HELICOPTER :Powernaut Hubschrauber +STR_VEHICLE_NAME_AIRCRAFT_TRICARIO_HELICOPTER :Tricario-Hubschrauber +STR_VEHICLE_NAME_AIRCRAFT_GURU_X2_HELICOPTER :Guru-X2-Hubschrauber +STR_VEHICLE_NAME_AIRCRAFT_POWERNAUT_HELICOPTER :Powernaut-Hubschrauber ##id 0x8800 # Formatting of some strings -STR_FORMAT_DATE_TINY :{STRING}-{STRING}-{NUM} +STR_FORMAT_DATE_TINY :{STRING}.{STRING}.{NUM} STR_FORMAT_DATE_SHORT :{STRING} {NUM} STR_FORMAT_DATE_LONG :{STRING} {STRING} {NUM} STR_FORMAT_DATE_ISO :{2:NUM}-{1:STRING}-{0:STRING} From 696b6990eafd00e0d947814b98fafa0d27b1e4ee Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 1 Feb 2021 18:17:06 +0000 Subject: [PATCH 024/275] Update: Translations from eints estonian: 110 changes by siimsoni --- src/lang/estonian.txt | 220 +++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 0761d8695d..87ac6c8692 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -386,7 +386,7 @@ STR_TOOLBAR_TOOLTIP_FORWARD :{BLACK}Kiirenda STR_TOOLBAR_TOOLTIP_OPTIONS :{BLACK}Seadistus STR_TOOLBAR_TOOLTIP_SAVE_GAME_ABANDON_GAME :{BLACK}Mängu salvestamine/jätkamine, mängust lahkumine, väljumine STR_TOOLBAR_TOOLTIP_DISPLAY_MAP :{BLACK}Ava kaart, vaateaken või siltide loend -STR_TOOLBAR_TOOLTIP_DISPLAY_TOWN_DIRECTORY :{BLACK}Ava linnade register +STR_TOOLBAR_TOOLTIP_DISPLAY_TOWN_DIRECTORY :{BLACK}Ava asustuste register STR_TOOLBAR_TOOLTIP_DISPLAY_SUBSIDIES :{BLACK}Ava toetuste loend STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_STATIONS :{BLACK}Avab ettevõtte jaamade registri STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_FINANCES :{BLACK}Ava ettevõtte rahavoogude aruanne @@ -420,9 +420,9 @@ STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR :{YELLOW}Stsenaa STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD :{BLACK}Alguse liigutamine 1 aasta võrra tagasi STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD :{BLACK}Alguse liigutamine 1 aasta võrra edasi STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE :{BLACK}Alustamise aasta valikuks klõpsi siin -STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Ava kaart, linnade register +STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY :{BLACK}Ava kaart, asustuste register STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}Maastiku tekitamine -STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}Linnade tekitamine +STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}Asustuste tekitamine STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}Tööstuste tekitamine STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}Maanteede ehitamine STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}Trammiteede ehitamine @@ -446,7 +446,7 @@ STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE :Seaded STR_SETTINGS_MENU_SCRIPT_SETTINGS :AI/GameScripti seaded STR_SETTINGS_MENU_NEWGRF_SETTINGS :NewGRF-i seadistus STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Läbipaistvuse seadistus -STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Näidatavad linnanimed +STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Näidatavad asustuste nimed STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Näidatavad jaamanimed STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Näidatavad meldepunktid STR_SETTINGS_MENU_SIGNS_DISPLAYED :Näidatavad sildid @@ -472,8 +472,8 @@ STR_MAP_MENU_LINGRAPH_LEGEND :Kaubavoo legend STR_MAP_MENU_SIGN_LIST :Siltide register ############ range for town menu starts -STR_TOWN_MENU_TOWN_DIRECTORY :Linnade register -STR_TOWN_MENU_FOUND_TOWN :Raja linn +STR_TOWN_MENU_TOWN_DIRECTORY :Asustuste register +STR_TOWN_MENU_FOUND_TOWN :Raja asustus ############ range ends here ############ range for subsidies menu starts @@ -810,12 +810,12 @@ STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Kivid STR_SMALLMAP_LEGENDA_WATER :{TINY_FONT}{BLACK}Vesi STR_SMALLMAP_LEGENDA_NO_OWNER :{TINY_FONT}{BLACK}Omanikuta -STR_SMALLMAP_LEGENDA_TOWNS :{TINY_FONT}{BLACK}Linnad +STR_SMALLMAP_LEGENDA_TOWNS :{TINY_FONT}{BLACK}Asustused STR_SMALLMAP_LEGENDA_INDUSTRIES :{TINY_FONT}{BLACK}Tööstused STR_SMALLMAP_LEGENDA_DESERT :{TINY_FONT}{BLACK}Kõrb STR_SMALLMAP_LEGENDA_SNOW :{TINY_FONT}{BLACK}Lumi -STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Linnanimede sisse- ja välja lülitamine +STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF :{BLACK}Asustuste nimede sisse- ja välja lülitamine STR_SMALLMAP_CENTER :{BLACK}Näita väikekaardil praegust asukohta STR_SMALLMAP_INDUSTRY :{TINY_FONT}{STRING} ({NUM}) STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} @@ -867,7 +867,7 @@ STR_NEWS_DISASTER_SMALL_UFO :{BIG_FONT}{BLAC STR_NEWS_DISASTER_AIRPLANE_OIL_REFINERY :{BIG_FONT}{BLACK}Naftatöötlustehase plahvatus {TOWN} lähedal! STR_NEWS_DISASTER_HELICOPTER_FACTORY :{BIG_FONT}{BLACK}Tehas purunes teadmata põhjustel {TOWN} lähedal! STR_NEWS_DISASTER_BIG_UFO :{BIG_FONT}{BLACK}'UFO' maandus {TOWN} lähedal! -STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE :{BIG_FONT}{BLACK}Söekaevanduse vajumine jättis endast linna {TOWN} lähedal purustused! +STR_NEWS_DISASTER_COAL_MINE_SUBSIDENCE :{BIG_FONT}{BLACK}Söekaevanduse vajumine jättis endast asustuse {TOWN} lähedal purustused! STR_NEWS_DISASTER_FLOOD_VEHICLE :{BIG_FONT}{BLACK}Üleujutused!{}Vähemalt {COMMA} kadunut arvatakse surnuks peale olulist üleujutust! STR_NEWS_COMPANY_IN_TROUBLE_TITLE :{BIG_FONT}{BLACK}Ettevõttel on probleeme! @@ -877,15 +877,15 @@ STR_NEWS_COMPANY_MERGER_DESCRIPTION :{BIG_FONT}{BLAC STR_NEWS_COMPANY_BANKRUPT_TITLE :{BIG_FONT}{BLACK}Pankrot! STR_NEWS_COMPANY_BANKRUPT_DESCRIPTION :{BIG_FONT}{BLACK}{STRING} suleti asutajate poolt ja kõik varad müüakse maha! STR_NEWS_COMPANY_LAUNCH_TITLE :{BIG_FONT}{BLACK}Loodi uus ettevõte! -STR_NEWS_COMPANY_LAUNCH_DESCRIPTION :{BIG_FONT}{BLACK}Ettevõte {STRING} alustas linna {TOWN} lähedal ehitustöid! +STR_NEWS_COMPANY_LAUNCH_DESCRIPTION :{BIG_FONT}{BLACK}Ettevõte {STRING} alustas asustuse {TOWN} lähedal ehitustöid! STR_NEWS_MERGER_TAKEOVER_TITLE :{BIG_FONT}{BLACK}{STRING} võeti üle ettevõtte {STRING} poolt! STR_PRESIDENT_NAME_MANAGER :{BLACK}{PRESIDENT_NAME}{}(President) -STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{STRING} rahastas uue linna {TOWN} rajamist! +STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{STRING} rahastas uue asustuse {TOWN} rajamist! STR_NEWS_NEW_TOWN_UNSPONSORED :{BLACK}{BIG_FONT}Uus linn nimega {TOWN} on asutatud! -STR_NEWS_INDUSTRY_CONSTRUCTION :{BIG_FONT}{BLACK}Uus {STRING} on linna {TOWN} lähedal ehitamisel! -STR_NEWS_INDUSTRY_PLANTED :{BIG_FONT}{BLACK}Uus {STRING} on istutatud linna {TOWN} lähedale! +STR_NEWS_INDUSTRY_CONSTRUCTION :{BIG_FONT}{BLACK}Uus {STRING} on asustuse {TOWN} lähedal ehitamisel! +STR_NEWS_INDUSTRY_PLANTED :{BIG_FONT}{BLACK}Uus {STRING} on istutatud asustuse {TOWN} lähedale! STR_NEWS_INDUSTRY_CLOSURE_GENERAL :{BIG_FONT}{BLACK}{STRING} juhtkond teatab sulgemisest! STR_NEWS_INDUSTRY_CLOSURE_SUPPLY_PROBLEMS :{BIG_FONT}{BLACK}{STRING} teatab sulgemisest varustusprobleemide tõttu! @@ -940,15 +940,15 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Jaam {ST STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Toetuse pakkumine lõppes:{}{}{STRING.g} kohast {STRING} kohta {STRING} veoste eest ei maksta enam toetusi STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Toetuse maksmise aeg sai läbi:{}{}{STRING}kohast {STRING} kohta {STRING} eest ei maksta enam edaspidi toetust -STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Veoteenusele pakutakse toetust:{}{}{STRING.g}veo eest linnast {STRING} linna {STRING}. Esimesele teenusepakkujale makstakse aasta läbi toetusi! +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Veoteenusele pakutakse toetust:{}{}{STRING.g}veo eest asustusest {STRING} asustusse {STRING}. Esimesele teenusepakkujale makstakse aasta läbi toetusi! STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal 50% rohkem! STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal kahekordselt! STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal kolmekordselt! STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Teenusetoetust makstakse ettevõttele {STRING}!{}{}{STRING} kohast {STRING} kohta {STRING} teenuse eest makstakse järgmisel aastal neljakordselt! -STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Liikluskaos linnas {TOWN}!{}{}Ettevõtte {STRING} poolt rahastatud teedeehitus tekitab 6 kuu jooksul maanteedel liiklushäireid! +STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Liikluskaos asustuses {TOWN}!{}{}Ettevõtte {STRING} poolt rahastatud teede ümberehitus tekitab 6 kuu jooksul maanteedel liiklushäireid! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transpordimonopol! -STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLACK}Kohalik linnavõim{TOWN} allkirjastab lepingu {STRING} transpordi ainuõiguseks üheks aastaks! +STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLACK}Asustuse {TOWN} omavalitsus allkirjastab lepingu {STRING} veoste ainuõiguseks üheks aastaks! # Extra view window STR_EXTRA_VIEWPORT_TITLE :{WHITE}Vaateaken {COMMA} @@ -1010,8 +1010,8 @@ STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_TOOLTIP :{BLACK}Vali, ku STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Vasakpoolne liiklus STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :Parempoolne liiklus -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Linnanimed -STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Vali linnanimede stiil +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}Asulate nimed +STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}Vali asulanimede stiil ############ start of townname region STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH :Inglise (originaalne) @@ -1244,7 +1244,7 @@ STR_CONFIG_SETTING_TRAIN_REVERSING :Keela rongide STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :Kui on aktiveeritud, siis ei pööra rongid vahejaamades ringi isegi siis kui ringi pööramisel oleks teekond järgmisse sihtpunkti lühem STR_CONFIG_SETTING_DISASTERS :Katastroofid: {STRING} STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Lülita sisse/välja katastroofid, mis aeg-ajalt hävitavad sõidukeid ja taristut -STR_CONFIG_SETTING_CITY_APPROVAL :Linnavalitusese suhtumine pinnase restruktureerimisse: {STRING} +STR_CONFIG_SETTING_CITY_APPROVAL :Astuse omavalitsuse suhtumine pinnase restruktureerimisse: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Vali kui suurt mõju tekitavad müra ning keskkonna muudatused ettevõtte mainele ja edasistele ehitustoimingutele antud piirkonnas STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :Maksimaalne mägede kõrgus: {STRING} @@ -1256,8 +1256,8 @@ STR_CONFIG_SETTING_CATCHMENT :Reaalsemad veek STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Erineva suurusega püüdmisala erinevat tüüpi jaamadele ja lennujaamadele. STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Ettevõtte jaamad teenindavad ka liidetud, erapooletu jaamaga tööstuseid: {STRING} STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Kui lubatud, saavad liidetud jaamaga tööstuseid (nagu naftaplatvormid) teenindada ka lähedalolevad ettevõttele kuuluvad jaamad. Muidu võivad neid tööstuseid teenindada vaid nendega liidetud jaamad. Lähedale ehitatud ettevõtte jaamad neid teenindada ei saa, ning liidetud jaamad ei teeninda teisi tööstuseid -STR_CONFIG_SETTING_EXTRADYNAMITE :Linnateede, -sildade, -tunnelite jne lammutamine: {STRING} -STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Lihtsusta linnale kuuluva taristu ja majade eemaldamist +STR_CONFIG_SETTING_EXTRADYNAMITE :Asulateede, -sildade, -tunnelite jne lammutamine: {STRING} +STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Lihtsusta asulatele kuuluva taristu ja hoonete eemaldamist STR_CONFIG_SETTING_TRAIN_LENGTH :Rongi pikkuse ülempiir: {STRING} STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Määrab rongide pikkuse ülempiiri STR_CONFIG_SETTING_TILE_LENGTH :{COMMA} ruut{P 0 "" u} @@ -1291,8 +1291,8 @@ STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL :Nagu kõik tö STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :Uuringutega STR_CONFIG_SETTING_INDUSTRY_PLATFORM :Tasane ala ümber tehaste: {STRING} STR_CONFIG_SETTING_INDUSTRY_PLATFORM_HELPTEXT :Summa kui palju tasast maad on ümber tehase. See tagab et ruumi jääb saadavale ehitiste jaoks -STR_CONFIG_SETTING_MULTIPINDTOWN :Samalaadsed tööstused ühes linnas: {STRING} -STR_CONFIG_SETTING_MULTIPINDTOWN_HELPTEXT :Tavaliselt, linn ei taha rohkem kui ühte tööstustharu igast tüübist. See seade lubab rohkem kui ühe tööstusharu samasse linna +STR_CONFIG_SETTING_MULTIPINDTOWN :Mitu samalaadset tööstust ühe asula piires: {STRING} +STR_CONFIG_SETTING_MULTIPINDTOWN_HELPTEXT :Tavaliselt asula ei taha rohkem kui ühte tööstustharu igast liigist. Selle seadega lubatakse rohkem kui üks samalaadne tööstus ühe asula piires STR_CONFIG_SETTING_SIGNALSIDE :Signaale näidatakse: {STRING} STR_CONFIG_SETTING_SIGNALSIDE_HELPTEXT :Vali kummale poole rada signaalid paigutatakse STR_CONFIG_SETTING_SIGNALSIDE_LEFT :Vasakul @@ -1314,13 +1314,13 @@ STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Põhivaates, ai STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Põhivaates STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Igas vaates STR_CONFIG_SETTING_BRIBE :Altkäemaksud kohalikele omavalitsustele: {STRING} -STR_CONFIG_SETTING_BRIBE_HELPTEXT :Võimaldab linna omavalitsusele altkäemaksu pakkuda. Vahele jäämise korral võetakse ettevõttelt kuueks kuuks ära õigus tegutseda linnas +STR_CONFIG_SETTING_BRIBE_HELPTEXT :Võimaldab asulate omavalitsustele altkäemaksu pakkuda. Tabamise korral võetakse ettevõttelt kuueks kuuks ära õigus asulas tegutseda STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :Ainuveoõiguste ostmine: {STRING} -STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :Kui ettevõte ostab linnalt kaubaveo ainuõiguse, siis teised ettevõtted ei saa üks aasta uusi kaupu ega reisijaid +STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :Kui ettevõte ostab asulalt kaubaveo ainuõiguse, siis teised ettevõtted ei saa üks aasta uusi kaupu ega reisijaid STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :Luba ehitiste rahastamine: {STRING} -STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Võimaldab ettevõttel linna kinnisvaraehitust rahastada +STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Võimaldab ettevõttel asulate kinnisvaraehitust rahastada STR_CONFIG_SETTING_ALLOW_FUND_ROAD :Kohaliku omavalitsuse teede rekonstrueerimise rahastamine: {STRING} -STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Võimaldab ettevõtetel linna tee-ehitustöid rahastada, šaboteerides sellega autode kaubavedu +STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Võimaldab ettevõtetel asulate tee-ehitustöid rahastada, šaboteerides sellega autode kaubavedu STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Raha saatmine teistele ettevõtetele: {STRING} STR_CONFIG_SETTING_ALLOW_GIVE_MONEY_HELPTEXT :Luba mitmikmängus kanda raha erinevate ettevõtete vahel STR_CONFIG_SETTING_FREIGHT_TRAINS :Raskete rongide simuleerimiseks kasutatav raskustegur: {STRING} @@ -1333,8 +1333,8 @@ STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :Määrab lennu STR_CONFIG_SETTING_PLANE_CRASHES_NONE :Ei STR_CONFIG_SETTING_PLANE_CRASHES_REDUCED :Vähem STR_CONFIG_SETTING_PLANE_CRASHES_NORMAL :Keskmiselt -STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :Läbisõidupeatused linnateedel: {STRING} -STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :Lubab linnale kuuluvatel teedel ehitada läbisõidupeatuseid +STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :Läbisõidupeatused asulate kuuluvatel teedel: {STRING} +STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :Lubab asulatele kuuluvatele teedele ehitada läbisõidupeatuseid STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :Läbisõidupeatused konkurentide teedel: {STRING} STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :Lubab teisele ettevõttele kuulaval teel ehitada läbisõidupeatuseid STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Sõidukite olemasolul ei saa seda seadet muuta @@ -1373,8 +1373,8 @@ STR_CONFIG_SETTING_HOVER_DELAY :Vihjeid näidat STR_CONFIG_SETTING_HOVER_DELAY_HELPTEXT :Viivitus, kui kaua peab hiirega liidese osale osutama, enne kui selle kohta vihjet näidatakse. On ka võimalik vihjeid parema hiireklõpsuga näidata STR_CONFIG_SETTING_HOVER_DELAY_VALUE :{COMMA} sekundilist osutamist STR_CONFIG_SETTING_HOVER_DELAY_DISABLED :Paremklõpsu -STR_CONFIG_SETTING_POPULATION_IN_LABEL :Linna rahvaarv nimesildil: {STRING} -STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Näitab linna nimesildil rahvaarvu +STR_CONFIG_SETTING_POPULATION_IN_LABEL :Asula rahvaarv nimesildil: {STRING} +STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Näitab asula nimesildil rahvaarvu STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Graafikujoone laius: {STRING} STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Graafikutes kasutatava joone laius. Peenem joon on täpsem, laiem joon on paremini näha ja värvid on selgemini eristatavad STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Näita sõidukiehitusaknas NewGRF-i nime: {STRING} @@ -1393,7 +1393,7 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Määrab, kui p STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Maksimaalne kaugus kaardi servast naftatöötlustehase jaoks: {STRING} STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Naftatöötlemistehased ehitatakse ainult kaardi piirile, see on rannikul saartega mängitaval kaardil. STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Lumepiiri kõrgus: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Määra, millisel kõrgusel algab sub-arktiline maastik. Lumi mõjutab ka tööstuste loomist ja linna kasvamise tingimusi +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Määra, millisel kõrgusel algab sub-arktiline maastik. Lumi mõjutab ka tööstuste loomist ja asulate kasvamise nõudeid STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Maastiku järskus (ainult TerraGenesis) : {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesis only) Vali mägede tihedus: Laugetel maastikel on vähem, laiema ulatusega mägesid. Mägistel maastikel on palju mägesid, mis võivad näha välja samasugused STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Väga lauge @@ -1525,7 +1525,7 @@ STR_CONFIG_SETTING_SOUND_DISASTER_HELPTEXT :Õnnetustes ja STR_CONFIG_SETTING_SOUND_VEHICLE :Sõidukitel: {STRING} STR_CONFIG_SETTING_SOUND_VEHICLE_HELPTEXT :Kostuvad sõidukite helid STR_CONFIG_SETTING_SOUND_AMBIENT :Taustahelid: {STRING} -STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :Maastikult, tööstustest ja linnadest kostuvad taustahelid +STR_CONFIG_SETTING_SOUND_AMBIENT_HELPTEXT :Maastikult, tööstustest ja asulatest kostuvad taustahelid STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING :Sobivate sõidukite puudumisel on taristu ehitamine keelatud: {STRING} STR_CONFIG_SETTING_DISABLE_UNSUITABLE_BUILDING_HELPTEXT :Sisse lülitamisel on taristu ehitamine võimalik ainult juhul, kui sellega seonduvad sõidukid on juba saadaval. Väldib mõttetut raha ja aja kulu, kui ehitatakse taristu, mida ei saa kasutada @@ -1653,26 +1653,26 @@ STR_CONFIG_SETTING_CYCLE_SIGNAL_NORMAL :Ainult tavaline STR_CONFIG_SETTING_CYCLE_SIGNAL_PBS :Ainult täiustatud STR_CONFIG_SETTING_CYCLE_SIGNAL_ALL :Kõik -STR_CONFIG_SETTING_TOWN_LAYOUT :Uute linnade tänavaplaneering: {STRING} -STR_CONFIG_SETTING_TOWN_LAYOUT_HELPTEXT :Teedevõrgu paigutus linnades +STR_CONFIG_SETTING_TOWN_LAYOUT :Uute asulate teeplaneering: {STRING} +STR_CONFIG_SETTING_TOWN_LAYOUT_HELPTEXT :Teedevõrgu paigutus asulates STR_CONFIG_SETTING_TOWN_LAYOUT_DEFAULT :Esialgne STR_CONFIG_SETTING_TOWN_LAYOUT_BETTER_ROADS :Paremad teed STR_CONFIG_SETTING_TOWN_LAYOUT_2X2_GRID :2x2 võrgustik STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :3x3 võrgustik STR_CONFIG_SETTING_TOWN_LAYOUT_RANDOM :Suvaline -STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :Linnapoolne teedeehitus: {STRING} -STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :Luba linnadel ehitada teid, et soodustada kasvu. Lülita välja, et keelata linnadel rajada teid -STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :Linnadel on lubatud ehitada ülesõidukohti: {STRING} -STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :Selle seade sisse lülitamine lubab linnadel ehitada ülesõidukohti -STR_CONFIG_SETTING_NOISE_LEVEL :Lennujaamade mürapiirangud linnades: {STRING} -STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT :Kui seade ei ole sisse lülitatud, siis igasse linna on lubatud ehitada kuni kaks lennuvälja. Kui see seade on lubatud, siis lennuväljade arvu ülempiiri määrab linna müratundlikkus, mis sõltub rahvaarvust ja lennuvälja suurusest ja kaugusest -STR_CONFIG_SETTING_TOWN_FOUNDING :Linnade rajamine keset mängu: {STRING} -STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :Võimaldab ettevõttel uusi linnu rajada +STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :Asulatel on lubatud teederajamine: {STRING} +STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :Luba asulatele teederajamine, et soodustada kasvu. Lülita välja, et keelata asulatele teederajamine +STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :Asulatel on lubatud ehitada ülesõidukohti: {STRING} +STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :Selle seade sisse lülitamine lubab asulatel ehitada ülesõidukohti +STR_CONFIG_SETTING_NOISE_LEVEL :Lennujaamade mürapiirangud asulates: {STRING} +STR_CONFIG_SETTING_NOISE_LEVEL_HELPTEXT :Kui seade ei ole sisse lülitatud, siis igasse asulasse on lubatud ehitada kuni kaks lennuvälja. Kui see seade on lubatud, siis lennuväljade arvu ülempiiri määrab asustuse müratundlikkus, mis sõltub rahvaarvust ja lennuvälja suurusest ja kaugusest +STR_CONFIG_SETTING_TOWN_FOUNDING :Asulate rajamine keset mängu: {STRING} +STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :Võimaldab ettevõttel uusi asulaid rajada STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :Keelatud STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :Lubatud -STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :Lubatud, koos linnaskeemi valimisega -STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Kauba tekkimine linnades: {STRING} -STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Kui palju kaupa toodavad majad linnades, võrreldes linnaelanike arvuga.{}Ruutfunktsioon: kaks korda suurem linn tekitab neli korda rohkem reisijaid.{}Lineaarne: kaks korda suurem linn tekitab kaks korda rohkem reisijaid. +STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :Lubatud, koos asulaskeemi valimisega +STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Kauba tekkimine asulates: {STRING} +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Kui palju kaupa toodavad majad asulates, võrreldes elanike arvuga.{}Ruutfunktsioon: kaks korda suurem asula tekitab neli korda rohkem reisijaid.{}Lineaarne: kaks korda suurem asula tekitab kaks korda rohkem reisijaid. STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :Ruutfunktsioon (algupärane) STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Lineaarne @@ -1705,18 +1705,18 @@ STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :Tavaline STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X :2x STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X :4x STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8x -STR_CONFIG_SETTING_TOWN_GROWTH :Linna kasvutempo: {STRING} -STR_CONFIG_SETTING_TOWN_GROWTH_HELPTEXT :Linna kasvamise kiirus +STR_CONFIG_SETTING_TOWN_GROWTH :Asulate kasvutempo: {STRING} +STR_CONFIG_SETTING_TOWN_GROWTH_HELPTEXT :Asulate kasvutempo STR_CONFIG_SETTING_TOWN_GROWTH_NONE :Pole STR_CONFIG_SETTING_TOWN_GROWTH_SLOW :Aeglane STR_CONFIG_SETTING_TOWN_GROWTH_NORMAL :Normaalne STR_CONFIG_SETTING_TOWN_GROWTH_FAST :Kiire STR_CONFIG_SETTING_TOWN_GROWTH_VERY_FAST :Väga Kiire -STR_CONFIG_SETTING_LARGER_TOWNS :Proportsioon asulatest millest kasvavad linnad: {STRING} +STR_CONFIG_SETTING_LARGER_TOWNS :Linnadeks kasvavate asulate osakaal: {STRING} STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :Asulate arv mis kasvavad tulevikus linnadeks, elik asulate arv mis on alguses suuremad ja kasvavad kiiremini kui ülejäänud asulad STR_CONFIG_SETTING_LARGER_TOWNS_VALUE :1 iga {COMMA} kohta STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :Mitte ühtegi -STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Algne linnade suurustegur: {STRING} +STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Algne linnade suuruskordaja: {STRING} STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Keskmine linna suurus võrreldes tavalise asulaga mängu alguses STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Jaotusgraafikuid uuendatakse igal {STRING}. päeval @@ -1797,8 +1797,8 @@ STR_CONFIG_SETTING_LIMITATIONS :{ORANGE}Piirang STR_CONFIG_SETTING_ACCIDENTS :{ORANGE}Katastroofid / Õnnetused STR_CONFIG_SETTING_GENWORLD :{ORANGE}Maailma tekitamine STR_CONFIG_SETTING_ENVIRONMENT :{ORANGE}Keskkond -STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES :{ORANGE}Linnavõimud -STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}Linnad +STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES :{ORANGE}Omavalitsus +STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}Asulad STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES :{ORANGE}Tööstused STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST :{ORANGE}Kaubajaotus STR_CONFIG_SETTING_AI :{ORANGE}Konkurendid @@ -2629,31 +2629,31 @@ STR_QUERY_RESET_LANDSCAPE_CAPTION :{WHITE}Nulli ma STR_RESET_LANDSCAPE_CONFIRMATION_TEXT :{WHITE}Kas oled kindel, et tahad lammutada kõik mängija omandid? # Town generation window (SE) -STR_FOUND_TOWN_CAPTION :{WHITE}Linnade tekitamine -STR_FOUND_TOWN_NEW_TOWN_BUTTON :{BLACK}Uus linn -STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Ehita uus linn. Shift+klõpsuga kuvatakse eeldatav maksumus -STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Suvaline linn -STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Ehita linn suvalisse kohta -STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Palju suvalisi linnu -STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Kaardi katmine suvaliselt asetatud linnadega +STR_FOUND_TOWN_CAPTION :{WHITE}Asulate tekitamine +STR_FOUND_TOWN_NEW_TOWN_BUTTON :{BLACK}Uus asula +STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Raja uus asula. Shift+klõpsuga kuvatakse eeldatav maksumus +STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Suvaline asula +STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Raja asula suvalisse kohta +STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Palju suvalisi asulaid +STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Kaardi katmine suvaliselt paigutatud asulatega -STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Linnanimi: -STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Sisesta linnanimi -STR_FOUND_TOWN_NAME_EDITOR_HELP :{BLACK}Klõpsa linnale nime andmiseks +STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Asula nimi: +STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Sisesta asula nimi +STR_FOUND_TOWN_NAME_EDITOR_HELP :{BLACK}Klõpsa asulale nime andmiseks STR_FOUND_TOWN_NAME_RANDOM_BUTTON :{BLACK}Suvaline nimi STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP :{BLACK}Loo suvaline nimi -STR_FOUND_TOWN_INITIAL_SIZE_TITLE :{YELLOW}Linna suurus: +STR_FOUND_TOWN_INITIAL_SIZE_TITLE :{YELLOW}Asula suurus: STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON :{BLACK}Väike STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON :{BLACK}Keskmine STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON :{BLACK}Suur STR_FOUND_TOWN_SIZE_RANDOM :{BLACK}Suvaline -STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Vali linna suurus +STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Vali asula suurus STR_FOUND_TOWN_CITY :{BLACK}Linn -STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Suuremad linnad kasvavad kiiremini kui väikesed{}Sõltuvalt seadetest on need ka alguses suuremad +STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Linnad kasvavad kiiremini, kui tavalised asulad{}Sõltuvalt seadetest on need ka alguses suuremad -STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Linna teeplaneering -STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT :{BLACK}Vali linnas kasutatav teeplaneering +STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Asula teeplaneering +STR_FOUND_TOWN_SELECT_TOWN_ROAD_LAYOUT :{BLACK}Vali selle asula teeplaneering STR_FOUND_TOWN_SELECT_LAYOUT_ORIGINAL :{BLACK}Algne STR_FOUND_TOWN_SELECT_LAYOUT_BETTER_ROADS :{BLACK}Paremad teed STR_FOUND_TOWN_SELECT_LAYOUT_2X2_GRID :{BLACK}2x2 ruudustik @@ -2907,7 +2907,7 @@ STR_MAPGEN_WORLD_GENERATION_CAPTION :{WHITE}Maailma STR_MAPGEN_MAPSIZE :{BLACK}Kaardi mõõtmed: STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}Määrab maakaardi mõõtmed ruutudes. Ruute, mida saab kasutada, on pisut vähem STR_MAPGEN_BY :{BLACK}* -STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Linnade sagedus: +STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Asustusi: STR_MAPGEN_DATE :{BLACK}Algus: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Tööstuste sagedus: STR_MAPGEN_MAX_HEIGHTLEVEL :{BLACK}Maksimaalne kaardi kõrgus: @@ -3167,11 +3167,11 @@ STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Mine eel STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Sisesta sildile nimi # Town directory window -STR_TOWN_DIRECTORY_CAPTION :{WHITE}Linnad +STR_TOWN_DIRECTORY_CAPTION :{WHITE}Asustused STR_TOWN_DIRECTORY_NONE :{ORANGE}- Puudub - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Linn){BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Linnanimed - vajuta linnanimele, et viia vaade linnale. Ctrl+klõps avab uue vaate linna asukohast +STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Astuste nimed - vajuta nimele, et viia vaade asustusele. Ctrl+klõps avab uue vaate linna asukohas STR_TOWN_POPULATION :{BLACK}Maailma rahvastik: {COMMA} # Town view window @@ -3179,25 +3179,25 @@ STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN} STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (Linn) STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Rahvaarv: {ORANGE}{COMMA}{BLACK} Ehitisi: {ORANGE}{COMMA} STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} eelmisel kuul: {ORANGE}{COMMA}{BLACK} Kuni: {ORANGE}{COMMA} -STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Veoseid linna kasvamiseks: +STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Asula kasvuks nõutud veosed: STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} vajalik STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} on talvel vajalik STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL :{ORANGE}{STRING}{GREEN} äraveetud STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{RED} (ikka veel vaja) STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{GREEN} (äraveetud) -STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}Linn kasvab {ORANGE}{COMMA}{BLACK} päevaga -STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Linn kasvab iga {ORANGE}{COMMA}{BLACK} päeva tagant (rahastatud) -STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Linn {RED}ei{BLACK} kasva -STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Mürapiirang linnas: {ORANGE}{COMMA}{BLACK} suurim: {ORANGE}{COMMA} -STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Vaate viimine linnale +STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}Asustus kasvab iga {ORANGE}{COMMA}{NBSP}päev{P "" a} +STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Asustus kasvab iga {ORANGE}{COMMA}{BLACK}{NBSP}päev{P "" a} (rahastatud) +STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Asustus {RED}ei{BLACK} kasva +STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Mürapiirang asustuses: {ORANGE}{COMMA}{BLACK} suurim: {ORANGE}{COMMA} +STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Keskenda vaade asustusele. Ctrl+klõps avab asustuse kohal uue vaate STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Omavalitsus STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Näita teavet kohaliku omavalitsuse kohta STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Muuda linna nime STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Laienda -STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Linna suuruse suurendamine +STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Asustuse suurendamine STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Kustuta -STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Hävita see linn täielikult +STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Hävita see asustus täielikult STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Ümbernimeta linn @@ -3208,7 +3208,7 @@ STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Näita k STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Ettevõtete hinnangud: STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING} STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}Pakutavad toimingud: -STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP :{BLACK}Nimekiri asjadest, mida saab siin linnas teha - klõpsa esemel, et saada rohkem andmeid +STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP :{BLACK}Nimekiri asjadest, mida saab selles asulas teha - täpsustused esemele klõpsatel STR_LOCAL_AUTHORITY_DO_IT_BUTTON :{BLACK}Soorita toiming STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP :{BLACK}Soorita ülalpool valitud toiming @@ -3221,14 +3221,14 @@ STR_LOCAL_AUTHORITY_ACTION_NEW_BUILDINGS :Rahasta uute ho STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :Osta monopoolsed veoõigused STR_LOCAL_AUTHORITY_ACTION_BRIBE :Paku kohalikule omavalitsusele altkäemaksu -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW} Pisikese kohaliku reklaamikampaania korraldamine meelitab rohkem reisijaid ja kaupu sinu veoteenuseid kasutama.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW} Keskmise reklaamikampaania korraldamine, et meelitada rohkem reisijaid ja kaupu sinu teenuste juurede.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW} Suure reklaamikampaania korraldamine, et meelitada rohkem reisijaid ja kaupu sinu teenuste juurede.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW} Teehoiutööde rahastamine. Põhjustab linnatänavatel tõsiseid liiklusprobleeme kuni 6 kuuks.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW} Oma ettevõtte auks kuju ehitamine.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW} Uute ärihoonete ehitamise rahastamine selles linnas.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW} Üheks aastaks monopoolsete veoõiguste ostmine selles linnas. Linna omavalitsus lubab reisijate ja kauba veoks kasutada ainult sinu jaamasid.{} Hind: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW} Linna omavalitusele ettevõtte hinnangu tõstmise eesmärgil altkäemaksu pakkumine. Vahele jäädes tuleb trahvi maksta.{} Hind: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW} Pisikese kohaliku reklaamikampaania korraldamine meelitab rohkem reisijaid ja kaupu sinu veoteenuseid kasutama.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW} Keskmise reklaamikampaania korraldamine, et meelitada rohkem reisijaid ja kaupu sinu teenuste juurede.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW} Suure reklaamikampaania korraldamine, et meelitada rohkem reisijaid ja kaupu sinu teenuste juurede.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW} Linna teedevõrgu ümberehituse rahastamine. Põhjustab liikluses tõsiseid häireid kuni 6 kuuks.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW} Oma ettevõtte auks kuju ehitamine.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW} Uute ärihoonete ehitamise rahastamine selles asulas.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW} Üheks aastaks monopoolsete veoõiguste ostmine selles asulas. Asula omavalitsus lubab reisijate ja kauba veoks kasutada ainult sinu jaamasid.{} Maksumus: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW} Kohalikule omavalitusele ettevõtte hinnangu tõstmise eesmärgil altkäemaksu pakkumine. Vahele jäädes tuleb trahvi maksta.{} Maksumus: {CURRENCY_LONG} # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} eesmärgid @@ -3241,7 +3241,7 @@ STR_GOALS_SPECTATOR_NONE :{ORANGE}- Kehte STR_GOALS_PROGRESS :{ORANGE}{STRING} STR_GOALS_PROGRESS_COMPLETE :{GREEN}{STRING} STR_GOALS_COMPANY_TITLE :{BLACK}Ettevõtte eesmärgid: -STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klõpsa eesmärgil, et liigutada vaateaken tööstuse/linna/ruudu asukohale. Ctrl+klõps avab uue vaateakna tööstuse/linna/ruudu asukohas +STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Klõpsa eesmärgil, et liigutada vaateaken tööstuse/asula/ruudu asukohale. Ctrl+klõps avab uue vaateakna tööstuse/asula/ruudu asukohas # Goal question window STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}Küsimus @@ -3277,7 +3277,7 @@ STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING STR_SUBSIDIES_NONE :{ORANGE}Mitte ühtegi STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Juba toetatavad veoteenused: STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} kohast {STRING} kohta {STRING}{YELLOW} ({COMPANY}{YELLOW}, kuni {DATE_SHORT}) -STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Vajuta pakkumisele, et näha linna või tööstuse asukohta. Ctrl+klõps avab uue vaate ettevõtte/linna asukohast +STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Vajuta pakkumisele, et keskendada vaade tööstusele/asustusele. Ctrl+klõps avab uue vaate ettevõtte/asustuse asukohas # Story book window STR_STORY_BOOK_CAPTION :{WHITE}«{COMPANY}» juturaamat @@ -3313,8 +3313,8 @@ STR_STATION_VIEW_ACCEPTS_BUTTON :{BLACK}Võtab v STR_STATION_VIEW_ACCEPTS_TOOLTIP :{BLACK}Näita vastuvõetavate veoste nimistut STR_STATION_VIEW_ACCEPTS_CARGO :{BLACK}Võtab vastu: {WHITE}{CARGO_LIST} -STR_STATION_VIEW_EXCLUSIVE_RIGHTS_SELF :{BLACK}Antud jaamal on eksklusiivsed transpordiõigused selles linnas. -STR_STATION_VIEW_EXCLUSIVE_RIGHTS_COMPANY :{YELLOW}{COMPANY}{BLACK} ostis eksklusiivsed transpordiõigused antud linnas. +STR_STATION_VIEW_EXCLUSIVE_RIGHTS_SELF :{BLACK}Sellel jaamal on asulas vedude ainuõigus. +STR_STATION_VIEW_EXCLUSIVE_RIGHTS_COMPANY :{YELLOW}{COMPANY}{BLACK} ostis vedude ainuõiguse selles asustuses. STR_STATION_VIEW_RATINGS_BUTTON :{BLACK}Hinnangud STR_STATION_VIEW_RATINGS_TOOLTIP :{BLACK}Näita jaamahinnangut @@ -3874,7 +3874,7 @@ STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL :{LTBLUE}Siht: { STR_VEHICLE_STATUS_NO_ORDERS_VEL :{LTBLUE}Sihitu, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL :{LTBLUE}Suundub {WAYPOINT}, {VELOCITY} STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL :{ORANGE}Suundub {DEPOT}, {VELOCITY} -STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL :{LTBLUE}Teenus kohas {DEPOT}, {VELOCITY} +STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL :{LTBLUE}Järelevaatus: {DEPOT}, {VELOCITY} # Vehicle stopped/started animations STR_VEHICLE_COMMAND_STOPPED_SMALL :{TINY_FONT}{RED}peatatud @@ -4336,8 +4336,8 @@ STR_GAME_SAVELOAD_NOT_AVAILABLE :Majandus->Linnad +STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Asula ei ehita teid. Teedeehituse lubamiseks Põhjalik seadistus->Majandus->Asulad STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Teede ehitamine -STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Seda linna ei saa kustutada...{}Jaam või depoo viitab linnale või mõnd linna omanduses olevat tükki ei saa kustutada -STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... linnakeskuses ei leidu kujule sobivat kohta +STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Seda asulat ei saa kõrvaldada...{}Jaam või depoo viitab asulale, või asulale kuuluvat ruutu ei saa kõrvaldada +STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... asula keskuses ei leidu kujule sobivat kohta # Industry related errors STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... liiga palju tööstuseid @@ -4439,13 +4439,13 @@ STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Tööstu STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} ei saa siia ehitada... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Seda tüüpi tööstust ei saa siia ehitada... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... liiga lähedal mõnele teisele tööstusele -STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... enne pead linna ehitama -STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... iga linna kohta lubatud ainult üks -STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... saab ainult ehitada linna, mille rahvastikuarv ületab 1200 +STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... enne pead asula rajama +STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... iga asula kohta lubatud ainult üks +STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... saab ainult ehitada asulatesse, mille elanikearv ületab 1200 STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... saab ehitada ainult vihmametsadesse STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}... saab ehitada ainult kõrbesse -STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}... saab ainult linnadesse ehitada -STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER :{WHITE}... saab ainult linna keskpunkti lähedale ehitada +STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}... saab ainult asulatesse ehitada (majade asemele) +STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER :{WHITE}... saab ainult asulekeskuste lähedale ehitada STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS :{WHITE}... saab ainult madalatele aladele ehitada STR_ERROR_CAN_ONLY_BE_POSITIONED :{WHITE}... saab ainult ehitada kaardi serva STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... metsa saab istutada ainult lumepiirist kõrgemale @@ -4473,7 +4473,7 @@ STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Liiga pa STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Liiga lähedal teisele dokile STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Liiga lähedal teisele lennuväljale STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Ei saa jaama ümbernimetada... -STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... see tee on omatud linna poolt +STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... see on asulale kuuluv tee STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... tee on vales suunas STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... nurgad ei saa läbisõidupeatustes olla STR_ERROR_DRIVE_THROUGH_JUNCTION :{WHITE}... ristmikud ei saa olla läbisõidupeatustes @@ -4748,7 +4748,7 @@ STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_1 :Büroohoone STR_TOWN_BUILDING_NAME_SMALL_BLOCK_OF_FLATS_1 :Väike kortermaja STR_TOWN_BUILDING_NAME_CHURCH_1 :Kirik STR_TOWN_BUILDING_NAME_LARGE_OFFICE_BLOCK_1 :Suur büroohoone -STR_TOWN_BUILDING_NAME_TOWN_HOUSES_1 :Linna majad +STR_TOWN_BUILDING_NAME_TOWN_HOUSES_1 :Asustuse majad STR_TOWN_BUILDING_NAME_HOTEL_1 :Hotell STR_TOWN_BUILDING_NAME_STATUE_1 :Kuju STR_TOWN_BUILDING_NAME_FOUNTAIN_1 :Purskkaev From 144991990ed35c97d02e221240e8f4e48704faac Mon Sep 17 00:00:00 2001 From: glx22 Date: Tue, 2 Feb 2021 00:18:20 +0100 Subject: [PATCH 025/275] Fix: [CMake] Language files should depend on english.txt --- src/lang/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/lang/CMakeLists.txt b/src/lang/CMakeLists.txt index 75d06f530a..f3aedca4b4 100644 --- a/src/lang/CMakeLists.txt +++ b/src/lang/CMakeLists.txt @@ -1,4 +1,9 @@ +set(MASTER_LANG_FILE + ${CMAKE_CURRENT_SOURCE_DIR}/english.txt +) + set(LANG_SOURCE_FILES + ${MASTER_LANG_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/afrikaans.txt ${CMAKE_CURRENT_SOURCE_DIR}/arabic_egypt.txt ${CMAKE_CURRENT_SOURCE_DIR}/basque.txt @@ -10,7 +15,6 @@ set(LANG_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/czech.txt ${CMAKE_CURRENT_SOURCE_DIR}/danish.txt ${CMAKE_CURRENT_SOURCE_DIR}/dutch.txt - ${CMAKE_CURRENT_SOURCE_DIR}/english.txt ${CMAKE_CURRENT_SOURCE_DIR}/english_AU.txt ${CMAKE_CURRENT_SOURCE_DIR}/english_US.txt ${CMAKE_CURRENT_SOURCE_DIR}/esperanto.txt @@ -75,7 +79,7 @@ foreach(LANG_SOURCE_FILE IN LISTS LANG_SOURCE_FILES) -s ${CMAKE_CURRENT_SOURCE_DIR} -d ${LANG_BINARY_DIR} ${LANG_SOURCE_FILE} - DEPENDS strgen + DEPENDS strgen ${MASTER_LANG_FILE} MAIN_DEPENDENCY ${LANG_SOURCE_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Compiling language ${LANG_SOURCE_FILE_NAME_WE}" @@ -103,7 +107,7 @@ add_custom_command_timestamp(OUTPUT ${TABLE_BINARY_DIR}/strings.h COMMAND strgen -s ${CMAKE_CURRENT_SOURCE_DIR} -d ${TABLE_BINARY_DIR} - DEPENDS strgen ${LANG_SOURCE_FILES} + DEPENDS strgen ${MASTER_LANG_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating table/strings.h" ) From 5b3fe4ae2741ef014b1a41a21c146d56c7408d6e Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 2 Feb 2021 18:17:17 +0000 Subject: [PATCH 026/275] Update: Translations from eints german: 4 changes by Wuzzy2 --- src/lang/german.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/german.txt b/src/lang/german.txt index 4cde7ed7c1..c030b91aed 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -3321,7 +3321,7 @@ STR_BUOY_VIEW_CHANGE_BUOY_NAME :{BLACK}Namen de STR_EDIT_WAYPOINT_NAME :{WHITE}Namen des Wegpunkts ändern # Finances window -STR_FINANCES_CAPTION :{WHITE}{COMPANY} Finanzen {BLACK}{COMPANY_NUM} +STR_FINANCES_CAPTION :{WHITE}{COMPANY} - Finanzen {BLACK}{COMPANY_NUM} STR_FINANCES_EXPENDITURE_INCOME_TITLE :{WHITE}Ausgaben / Einnahmen STR_FINANCES_YEAR :{WHITE}{NUM} STR_FINANCES_SECTION_CONSTRUCTION :{GOLD}Baukosten @@ -3512,8 +3512,8 @@ STR_GROUP_REMOVE_ALL_VEHICLES :Liste leeren STR_GROUP_RENAME_CAPTION :{BLACK}Gruppe umbenennen -STR_GROUP_PROFIT_THIS_YEAR :Gewinn in diesem Jahr: -STR_GROUP_PROFIT_LAST_YEAR :Gewinn im letzten Jahr: +STR_GROUP_PROFIT_THIS_YEAR :Gewinn dieses Jahr: +STR_GROUP_PROFIT_LAST_YEAR :Gewinn letztes Jahr: STR_GROUP_OCCUPANCY :Aktuelle Nutzung: STR_GROUP_OCCUPANCY_VALUE :{NUM}% @@ -4227,7 +4227,7 @@ STR_AI_SETTINGS_START_DELAY :Wartezeit in Ta # Textfile window STR_TEXTFILE_README_CAPTION :{WHITE}{STRING}-Liesmich von {STRING} -STR_TEXTFILE_CHANGELOG_CAPTION :{WHITE}{STRING} Änderungen von {STRING} +STR_TEXTFILE_CHANGELOG_CAPTION :{WHITE}{STRING}-Änderungen von {STRING} STR_TEXTFILE_LICENCE_CAPTION :{WHITE}{STRING}-Lizenz von {STRING} STR_TEXTFILE_WRAP_TEXT :{WHITE}Text umbrechen STR_TEXTFILE_WRAP_TEXT_TOOLTIP :{BLACK}Text des Fensters so umbrechen, dass es ohne Scrollen hineinpasst From a4035af3375825ae277f1363c5d814ee55b92d7c Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Fri, 5 Feb 2021 10:00:36 +0000 Subject: [PATCH 027/275] Codechange: Apply coding style (#8640) * Fix: Missing or needed spaces * Codechange: Remove space * Codechange: Remove space * Codechange: More missing spaces * Codechange: Missing spaces * Codechange: Remove space * Codechange: Remove space --- src/console_cmds.cpp | 8 ++++---- src/fontcache.cpp | 2 +- src/group_gui.cpp | 6 +++--- src/network/network_gui.cpp | 2 +- src/station_cmd.cpp | 6 +++--- src/town_cmd.cpp | 4 ++-- src/tree_cmd.cpp | 2 +- src/vehicle.cpp | 2 +- src/vehicle_gui.cpp | 1 - src/video/sdl2_v.cpp | 10 +++++----- src/viewport.cpp | 4 ++-- src/viewport_sprite_sorter_sse4.cpp | 4 ++-- 12 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 7dbd5658ce..905a41c3e7 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1255,7 +1255,7 @@ DEF_CONSOLE_CMD(ConReloadAI) } /* First kill the company of the AI, then start a new one. This should start the current AI again */ - DoCommandP(0, CCA_DELETE | company_id << 16 | CRR_MANUAL << 24, 0,CMD_COMPANY_CTRL); + DoCommandP(0, CCA_DELETE | company_id << 16 | CRR_MANUAL << 24, 0, CMD_COMPANY_CTRL); DoCommandP(0, CCA_NEW_AI | company_id << 16, 0, CMD_COMPANY_CTRL); IConsolePrint(CC_DEFAULT, "AI reloaded."); @@ -2136,7 +2136,7 @@ static void ConDumpRoadTypes() grfs.emplace(grfid, grf); } IConsolePrintF(CC_DEFAULT, " %02u %s %c%c%c%c, Flags: %c%c%c%c%c, GRF: %08X, %s", - (uint) rt, + (uint)rt, RoadTypeIsTram(rt) ? "Tram" : "Road", rti->label >> 24, rti->label >> 16, rti->label >> 8, rti->label, HasBit(rti->flags, ROTF_CATENARY) ? 'c' : '-', @@ -2174,7 +2174,7 @@ static void ConDumpRailTypes() grfs.emplace(grfid, grf); } IConsolePrintF(CC_DEFAULT, " %02u %c%c%c%c, Flags: %c%c%c%c%c%c, GRF: %08X, %s", - (uint) rt, + (uint)rt, rti->label >> 24, rti->label >> 16, rti->label >> 8, rti->label, HasBit(rti->flags, RTF_CATENARY) ? 'c' : '-', HasBit(rti->flags, RTF_NO_LEVEL_CROSSING) ? 'l' : '-', @@ -2217,7 +2217,7 @@ static void ConDumpCargoTypes() grfs.emplace(grfid, grf); } IConsolePrintF(CC_DEFAULT, " %02u Bit: %2u, Label: %c%c%c%c, Callback mask: 0x%02X, Cargo class: %c%c%c%c%c%c%c%c%c%c%c, GRF: %08X, %s", - (uint) i, + (uint)i, spec->bitnum, spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label, spec->callback_mask, diff --git a/src/fontcache.cpp b/src/fontcache.cpp index ec336612a4..0b2764aabf 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -1008,7 +1008,7 @@ static void LoadWin32Font(FontSize fs) if (fontPath[0] != 0) { if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { /* Try a nice little undocumented function first for getting the internal font name. - * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ + * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ typedef BOOL(WINAPI * PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); #ifdef UNICODE static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(_T("Gdi32")), "GetFontResourceInfoW"); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 2ab2a5b51a..e711201a68 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -741,9 +741,9 @@ public: assert(vehgroup.NumVehicles() > 0); v = vehgroup.vehicles_begin[0]; /* - No VehicleClicked(v) support for now, because don't want - to enable any contextual actions except perhaps clicking/ctrl-clicking to clone orders. - */ + * No VehicleClicked(v) support for now, because don't want + * to enable any contextual actions except perhaps clicking/ctrl-clicking to clone orders. + */ break; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 42915c410e..eb7ff78b26 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -332,7 +332,7 @@ protected: if (r == 0) r = a->info.use_password - b->info.use_password; /* Finally sort on the number of clients of the server in reverse order. */ - return (r != 0) ? r < 0: !NGameClientSorter(a, b); + return (r != 0) ? r < 0 : !NGameClientSorter(a, b); } /** Sort the server list */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 7bd124f065..4077a7b8c6 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -4036,7 +4036,7 @@ uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, Sourc first_station = st; continue; } - if (used_stations.empty()) { + if (used_stations.empty()) { used_stations.reserve(2); used_stations.emplace_back(std::make_pair(first_station, 0)); } @@ -4081,9 +4081,9 @@ uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, Sourc moving += p.second; } - /* If there is some cargo left due to rounding issues distribute it among the best rated stations. */ + /* If there is some cargo left due to rounding issues distribute it among the best rated stations. */ if (amount > moving) { - std::sort(used_stations.begin(), used_stations.end(), [type] (const StationInfo &a, const StationInfo &b) { + std::sort(used_stations.begin(), used_stations.end(), [type](const StationInfo &a, const StationInfo &b) { return b.first->goods[type].rating < a.first->goods[type].rating; }); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 1aadd5927b..c2d148a1a3 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1117,7 +1117,7 @@ static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd) * @param road_dir The direction of the road * @return true if the road can be continued, else false */ -static bool CanRoadContinueIntoNextTile(const Town* t, const TileIndex tile, const DiagDirection road_dir) +static bool CanRoadContinueIntoNextTile(const Town *t, const TileIndex tile, const DiagDirection road_dir) { const int delta = TileOffsByDiagDir(road_dir); // +1 tile in the direction of the road TileIndex next_tile = tile + delta; // The tile beyond which must be connectable to the target tile @@ -1236,7 +1236,7 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi * @param tunnel_dir The valid direction in which to grow a tunnel * @return true if a tunnel has been built, else false */ -static bool GrowTownWithTunnel(const Town* t, const TileIndex tile, const DiagDirection tunnel_dir) +static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDirection tunnel_dir) { assert(tunnel_dir < DIAGDIR_END); diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index f4610b5699..dee79e1b72 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -762,7 +762,7 @@ static void TileLoop_Trees(TileIndex tile) break; case 6: // final stage of tree destruction - if (!CanPlantExtraTrees(tile)) { + if (!CanPlantExtraTrees(tile)) { /* if trees can't spread just plant a new one to prevent deforestation */ SetTreeGrowth(tile, 0); } else if (GetTreeCount(tile) > 1) { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 21d02f1816..3bec190804 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1179,7 +1179,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) t <= v->coord.bottom && r >= v->coord.left && b >= v->coord.top) DoDrawVehicle(v); - } + } v = v->hash_viewport_next; } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 66db4f6e8c..d28849ebdc 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1575,7 +1575,6 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int } case GB_SHARED_ORDERS: - assert(vehgroup.NumVehicles() > 0); for (int i = 0; i < static_cast(vehgroup.NumVehicles()); ++i) { diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index aa7a23c728..66e6586fdc 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -524,7 +524,7 @@ static uint ConvertSdlKeycodeIntoMy(SDL_Keycode kc) } /* check scancode for BACKQUOTE key, because we want the key left - of "1", not anything else (on non-US keyboards) */ + * of "1", not anything else (on non-US keyboards) */ SDL_Scancode sc = SDL_GetScancodeFromKey(kc); if (sc == SDL_SCANCODE_GRAVE) key = WKC_BACKQUOTE; @@ -542,10 +542,10 @@ int VideoDriver_SDL::PollEvent() #ifdef __EMSCRIPTEN__ if (_cursor_new_in_window) { /* The cursor just moved into the window; this means we don't - * know the absolutely position yet to move relative from. - * Before this time, SDL didn't know it either, and this is - * why we postpone it till now. Update the absolute position - * for this once, and work relative after. */ + * know the absolutely position yet to move relative from. + * Before this time, SDL didn't know it either, and this is + * why we postpone it till now. Update the absolute position + * for this once, and work relative after. */ _cursor.pos.x = ev.motion.x; _cursor.pos.y = ev.motion.y; _cursor.dirty = true; diff --git a/src/viewport.cpp b/src/viewport.cpp index 44ff37c741..822b0db9c2 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1527,7 +1527,7 @@ static void ViewportSortParentSprites(ParentSpriteToSortVector *psdv) sprite_list.sort(); - std::vector preceding; // Temporarily stores sprites that precede current and their position in the list + std::vector preceding; // Temporarily stores sprites that precede current and their position in the list auto preceding_prev = sprite_list.begin(); // Store iterator in case we need to delete a single preciding sprite auto out = psdv->begin(); // Iterator to output sorted sprites @@ -1606,7 +1606,7 @@ static void ViewportSortParentSprites(ParentSpriteToSortVector *psdv) /* Sort all preceding sprites by order and assign new orders in reverse (as original sorter did). */ std::sort(preceding.begin(), preceding.end(), [](const ParentSpriteToDraw *a, const ParentSpriteToDraw *b) { - return a->order > b->order; + return a->order > b->order; }); s->order = ORDER_COMPARED; diff --git a/src/viewport_sprite_sorter_sse4.cpp b/src/viewport_sprite_sorter_sse4.cpp index ae51218181..f3747b89b2 100644 --- a/src/viewport_sprite_sorter_sse4.cpp +++ b/src/viewport_sprite_sorter_sse4.cpp @@ -55,7 +55,7 @@ void ViewportSortParentSpritesSSE41(ParentSpriteToSortVector *psdv) sprite_list.sort(); - std::vector preceding; // Temporarily stores sprites that precede current and their position in the list + std::vector preceding; // Temporarily stores sprites that precede current and their position in the list auto preceding_prev = sprite_list.begin(); // Store iterator in case we need to delete a single preciding sprite auto out = psdv->begin(); // Iterator to output sorted sprites @@ -151,7 +151,7 @@ void ViewportSortParentSpritesSSE41(ParentSpriteToSortVector *psdv) /* Sort all preceding sprites by order and assign new orders in reverse (as original sorter did). */ std::sort(preceding.begin(), preceding.end(), [](const ParentSpriteToDraw *a, const ParentSpriteToDraw *b) { - return a->order > b->order; + return a->order > b->order; }); s->order = ORDER_COMPARED; From 05df7996a4c8039db0785a7e22fe8db59bcc7513 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 5 Feb 2021 12:31:27 +0100 Subject: [PATCH 028/275] Feature: [Actions / CMake] support for generic linux builds (#8641) These bundles can be opened on any "modern" Linux machine with a driver that SDL2 supports. Machines needs at least glibc 2.15, which was released 10 years ago. It is build with CentOS 7 as base, and only assumes the following libraries are available on the system: - libc - libdl - libgcc_s - libpthread - librt - libstdc++ All other libraries the game depends on are bundled together with the game, so users don't need any library installed to use this bundle. The downside of course is that this increases the binary size a bit: 30 MiB of libraries are in this bundle. RPATH is used to make ld-linux find the folder libraries are stored in; however, system libraries are always used before these, in the assumption libraries on the user system are more up-to-date. Using -DOPTION_PACKAGE_DEPENDENCIES=ON switches on packaging of libraries in the "lib" folder. This requires CMake 3.16 to be installed; otherwise it will fail. --- .github/workflows/release.yml | 91 ++++++++++++++++++++++++++++++++++- CMakeLists.txt | 21 ++++++++ cmake/InstallAndPackage.cmake | 39 +++++++++++++-- cmake/Options.cmake | 5 +- 4 files changed, 149 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4003787fc5..1faaacfb3c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -265,7 +265,93 @@ jobs: retention-days: 5 linux: - name: Linux + name: Linux (Generic) + needs: source + + runs-on: ubuntu-20.04 + container: + # manylinux2014 is based on CentOS 7, but already has a lot of things + # installed and preconfigured. It makes it easier to build OpenTTD. + image: quay.io/pypa/manylinux2014_x86_64 + + steps: + - name: Download source + uses: actions/download-artifact@v2 + with: + name: internal-source + + - name: Unpack source + run: | + tar -xf source.tar.gz --strip-components=1 + + - name: Install dependencies + run: | + echo "::group::Install dependencies" + yum install -y \ + fontconfig-devel \ + freetype-devel \ + libicu-devel \ + libpng-devel \ + libpng-devel \ + lzo-devel \ + SDL2-devel \ + wget \ + xz-devel \ + zlib-devel \ + # EOF + echo "::endgroup::" + + # The yum variant of fluidsynth depends on all possible audio drivers. + # This is not really useful for us, as that would require a user to + # have them all before he can start OpenTTD. Instead, compile a + # version that can only use SDL2. As OpenTTD does sound via SDL2, + # this simply means we either have sound and music, or have none. + echo "::group::Install fluidsynth" + wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz + tar xf v2.1.6.tar.gz + ( + cd fluidsynth-2.1.6 + mkdir build + cd build + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr + make -j$(nproc) + make install + ) + echo "::endgroup::" + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build + run: | + mkdir -p build + cd build + + echo "::group::CMake" + cmake ${GITHUB_WORKSPACE} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DOPTION_PACKAGE_DEPENDENCIES=ON \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + make -j$(nproc) package + echo "::endgroup::" + + # Remove the sha256 files CPack generates; we will do this ourself at + # the end of this workflow. + rm -f bundles/*.sha256 + + - name: Store bundles + uses: actions/upload-artifact@v2 + with: + name: openttd-linux-generic + path: build/bundles + retention-days: 5 + + linux-distro: + name: Linux (Distros) needs: source if: needs.source.outputs.is_tag == 'true' @@ -633,6 +719,7 @@ jobs: - source - docs - linux + - linux-distro - macos - windows @@ -641,7 +728,7 @@ jobs: # "always()" is important here, it is the keyword to use to stop skipping # this job if any dependency is skipped. It looks a bit silly, but it is # how GitHub Actions work ;) - if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && (needs.linux.result == 'success' || needs.linux.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success' + if: always() && needs.source.result == 'success' && needs.docs.result == 'success' && needs.linux.result == 'success' && (needs.linux-distro.result == 'success' || needs.linux-distro.result == 'skipped') && needs.macos.result == 'success' && needs.windows.result == 'success' runs-on: ubuntu-20.04 diff --git a/CMakeLists.txt b/CMakeLists.txt index d273937a31..1ac5be5bee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,6 +167,27 @@ if(APPLE) endif() endif() +if(OPTION_PACKAGE_DEPENDENCIES) + if(NOT UNIX) + message(FATAL_ERROR "Can only package dependencies on Linux") + endif() + if(OPTION_INSTALL_FHS) + message(FATAL_ERROR "Cannot install in FHS folders when we are packaging dependencies") + endif() + if(${CMAKE_VERSION} VERSION_LESS "3.16.0") + message(FATAL_ERROR "OPTION_PACKAGE_DEPENDENCIES can only work with CMake 3.16+; you are using ${CMAKE_VERSION}") + endif() + + # If we are packaging dependencies, we do two things: + # 1) set the RPATH to include $ORIGIN/lib; $ORIGIN (that literal string) + # is a Linux indicator for "path where application is". In CMake, we + # have to do this before add_executable() is executed. + # 2) copy the libraries that we compile against to the "lib" folder. + # This is done in InstallAndPackage.cmake. + set(CMAKE_INSTALL_RPATH "\$ORIGIN/lib") + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) +endif() + include(SourceList) # Needed by rev.cpp diff --git a/cmake/InstallAndPackage.cmake b/cmake/InstallAndPackage.cmake index b54c8131ac..5c56d2d6d5 100644 --- a/cmake/InstallAndPackage.cmake +++ b/cmake/InstallAndPackage.cmake @@ -123,8 +123,12 @@ elseif(UNIX) # With FHS, we can create deb/rpm/... Without it, they would be horribly broken # and not work. The other way around is also true; with FHS they are not # usable, and only flat formats work. - if(NOT OPTION_INSTALL_FHS) + if(OPTION_PACKAGE_DEPENDENCIES) set(CPACK_GENERATOR "TXZ") + set(PLATFORM "generic") + elseif(NOT OPTION_INSTALL_FHS) + set(CPACK_GENERATOR "TXZ") + set(PLATFORM "unknown") else() find_program(LSB_RELEASE_EXEC lsb_release) execute_process(COMMAND ${LSB_RELEASE_EXEC} -is @@ -149,7 +153,7 @@ elseif(UNIX) string(REGEX MATCH "ID=(.*)" _ ${OS_RELEASE_CONTENTS}) set(DISTRO_ID ${CMAKE_MATCH_1}) if(DISTRO_ID STREQUAL "arch") - set(PLATFORM "generic") + set(PLATFORM "arch") set(CPACK_GENERATOR "TXZ") else() set(UNSUPPORTED_PLATFORM_NAME "Linux distribution '${DISTRO_ID}' from /etc/os-release") @@ -163,12 +167,39 @@ elseif(UNIX) set(CPACK_GENERATOR "TXZ") message(WARNING "Unknown ${UNSUPPORTED_PLATFORM_NAME} found for packaging; can only pack to a txz. Please consider creating a Pull Request to add support for this distribution.") endif() - - set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-linux-${PLATFORM}-${CPACK_SYSTEM_NAME}") endif() + set(CPACK_PACKAGE_FILE_NAME "openttd-#CPACK_PACKAGE_VERSION#-linux-${PLATFORM}-${CPACK_SYSTEM_NAME}") + else() message(FATAL_ERROR "Unknown OS found for packaging; please consider creating a Pull Request to add support for this OS.") endif() include(CPack) + +if(OPTION_PACKAGE_DEPENDENCIES) + # Install all dependencies we can resolve, with the exception of ones that + # every Linux machine should have. This should make this build as generic + # as possible, where it runs on any machine with the same or newer libc + # than the one this is compiled with. + # We copy these libraries into lib/ folder, so they can be found on game + # startup. See comment in root CMakeLists.txt for how this works exactly. + install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR DEPENDENCIES + UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPENDENCIES + EXECUTABLES openttd + POST_EXCLUDE_REGEXES "ld-linux|libc.so|libdl.so|libm.so|libgcc_s.so|libpthread.so|librt.so|libstdc...so") + file(INSTALL + DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" + FILES ${DEPENDENCIES} + FOLLOW_SYMLINK_CHAIN) + + # This should not be possible, but error out when a dependency cannot + # be resolved. + list(LENGTH UNRESOLVED_DEPENDENCIES UNRESOLVED_LENGTH) + if(${UNRESOLVED_LENGTH} GREATER 0) + message(FATAL_ERROR "Unresolved dependencies: ${UNRESOLVED_DEPENDENCIES}") + endif() + ]]) +endif() diff --git a/cmake/Options.cmake b/cmake/Options.cmake index c94a193b32..42d1127906 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -44,7 +44,9 @@ endfunction() # set_options() # function(set_options) - if(UNIX AND NOT APPLE) + option(OPTION_PACKAGE_DEPENDENCIES "Copy dependencies into lib/ for easy packaging (Linux only)" OFF) + + if(UNIX AND NOT APPLE AND NOT OPTION_PACKAGE_DEPENDENCIES) set(DEFAULT_OPTION_INSTALL_FHS ON) else() set(DEFAULT_OPTION_INSTALL_FHS OFF) @@ -76,6 +78,7 @@ endfunction() # show_options() # function(show_options) + message(STATUS "Option Package Dependencies - ${OPTION_PACKAGE_DEPENDENCIES}") message(STATUS "Option Dedicated - ${OPTION_DEDICATED}") message(STATUS "Option Install FHS - ${OPTION_INSTALL_FHS}") message(STATUS "Option Use assert - ${OPTION_USE_ASSERTS}") From a667ed945f928a605a7e4c636d62d47eeb8dc6aa Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 5 Feb 2021 20:58:15 +0100 Subject: [PATCH 029/275] Add: [Actions] Automatically upload releases to Steam (#8644) --- .github/workflows/release.yml | 79 ++++++++++++++++++++++++++++++++++- os/steam/release.vdf | 57 +++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 os/steam/release.vdf diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1faaacfb3c..d759d10e34 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -714,7 +714,7 @@ jobs: retention-days: 5 upload: - name: Upload + name: Upload (AWS) needs: - source - docs @@ -772,3 +772,80 @@ jobs: repository: OpenTTD/workflows event-type: ${{ needs.source.outputs.trigger_type }} client-payload: '{"version": "${{ needs.source.outputs.version }}", "folder": "${{ needs.source.outputs.folder }}"}' + + upload-steam: + name: Upload (Steam) + needs: + - source + - linux + - macos + - windows + + if: needs.source.outputs.trigger_type == 'new-master' || needs.source.outputs.trigger_type == 'new-tag' + + runs-on: ubuntu-20.04 + + steps: + - name: Download all bundles + uses: actions/download-artifact@v2 + + - name: Setup steamcmd + uses: CyberAndrii/setup-steamcmd@v1 + + - name: Generate Steam auth code + id: steam-totp + uses: CyberAndrii/steam-totp@v1 + with: + shared_secret: ${{ secrets.STEAM_SHARED_SECRET }} + + - name: Upload to Steam + run: | + echo "::group::Extracting source" + mkdir source + ( + cd source + tar -xf ../internal-source/source.tar.gz --strip-components=1 + ) + echo "::endgroup::" + + mkdir steam + ( + cd steam + + echo "::group::Prepare Win32" + unzip ../openttd-windows-x86/openttd-*-windows-win32.zip + mv openttd-*-windows-win32 steam-win32 + echo "::endgroup::" + + echo "::group::Prepare Win64" + unzip ../openttd-windows-x64/openttd-*-windows-win64.zip + mv openttd-*-windows-win64 steam-win64 + echo "::endgroup::" + + echo "::group::Prepare macOS" + mkdir steam-macos + ( + cd steam-macos + unzip ../../openttd-macos-universal/openttd-*-macos-universal.zip + ) + echo "::endgroup::" + + echo "::group::Prepare Linux" + tar xvf ../openttd-linux-generic/openttd-*-linux-generic-amd64.tar.xz + mv openttd-*-linux-generic-amd64 steam-linux + echo "::endgroup::" + + echo "::group::Preparing build file" + if [ "${{ needs.source.outputs.trigger_type }}" = "new-tag" ]; then + BRANCH="testing" + else + BRANCH="nightly" + fi + cat ../source/os/steam/release.vdf | sed 's/@@DESCRIPTION@@/openttd-${{ needs.source.outputs.version }}/;s/@@BRANCH@@/'${BRANCH}'/' > release.vdf + cat release.vdf + echo "::endgroup::" + + echo "::group::Upload to Steam" + steamcmd +login ${{ secrets.STEAM_USERNAME }} ${{ secrets.STEAM_PASSWORD }} ${{ steps.steam-totp.outputs.code }} +run_app_build $(pwd)/release.vdf +quit + echo "::endgroup::" + ) diff --git a/os/steam/release.vdf b/os/steam/release.vdf new file mode 100644 index 0000000000..ab549c3886 --- /dev/null +++ b/os/steam/release.vdf @@ -0,0 +1,57 @@ +"AppBuild" +{ + "AppID" "1536610" + "Desc" "@@DESCRIPTION@@" + + "SetLive" "@@BRANCH@@" + + "ContentRoot" "./" + "BuildOutput" "build/" + + "Depots" + { + "1536613" + { + "ContentRoot" "./steam-win32" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + } + + "1536612" + { + "ContentRoot" "./steam-win64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + } + + "1536614" + { + "ContentRoot" "./steam-macos" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + } + + "1536615" + { + "ContentRoot" "./steam-linux" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + } + } +} From 99448eedca8f3759b8de44c356f3947dbd6e448b Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 5 Feb 2021 22:31:33 +0100 Subject: [PATCH 030/275] Fix: [CMake] os/windows/openttd.manifest is not a generated file --- CMakeLists.txt | 5 +++++ cmake/CompileFlags.cmake | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ac5be5bee..2fb7a2309a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,6 +201,11 @@ add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES}) set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}") # All other files are added via target_sources() +if(MSVC) + # Add DPI manifest to project; other WIN32 targets get this via ottdres.rc + target_sources(openttd PRIVATE "${CMAKE_SOURCE_DIR}/os/windows/openttd.manifest") +endif() + add_subdirectory(${CMAKE_SOURCE_DIR}/src) add_subdirectory(${CMAKE_SOURCE_DIR}/media/baseset) diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index 772041a42c..f4047b8396 100644 --- a/cmake/CompileFlags.cmake +++ b/cmake/CompileFlags.cmake @@ -27,9 +27,6 @@ macro(compile_flags) # Enable multi-threaded compilation. add_compile_options(/MP) endif() - - # Add DPI manifest to project; other WIN32 targets get this via ottdres.rc - list(APPEND GENERATED_SOURCE_FILES "${CMAKE_SOURCE_DIR}/os/windows/openttd.manifest") endif() # Add some -D flags for Debug builds. We cannot use add_definitions(), because From 4f0692c437c7c89b38134255a5b7aea9f0378c19 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 5 Feb 2021 23:56:44 +0100 Subject: [PATCH 031/275] Codechange: [Actions] Document better why we build our own fluidsynth (#8646) nielsmh nicely correct us in #8641, pointing out the old comment is not telling a complete truth. The result is the same, but it is better to not mislead future-us. --- .github/workflows/release.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d759d10e34..63af9ff872 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -301,11 +301,13 @@ jobs: # EOF echo "::endgroup::" - # The yum variant of fluidsynth depends on all possible audio drivers. - # This is not really useful for us, as that would require a user to - # have them all before he can start OpenTTD. Instead, compile a - # version that can only use SDL2. As OpenTTD does sound via SDL2, - # this simply means we either have sound and music, or have none. + # The yum variant of fluidsynth depends on all possible audio drivers, + # like jack, ALSA, pulseaudio, etc. This is not really useful for us, + # as we route the output of fluidsynth back via our sound driver, and + # as such do not use these audio driver outputs at all. So instead, + # we compile fluidsynth ourselves, with as little dependencies as + # possible. This currently means it picks up SDL2, but this is fine, + # as we need SDL2 anyway. echo "::group::Install fluidsynth" wget https://github.com/FluidSynth/fluidsynth/archive/v2.1.6.tar.gz tar xf v2.1.6.tar.gz From 2c9084d48cf1a3ad3c5f8d3bcad83c396e8d29fd Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 6 Feb 2021 14:09:45 +0100 Subject: [PATCH 032/275] Fix #8029: [SDL2] disable draw-thread on wayland SDL video driver (#8648) When the wayland SDL video driver is used, an EGL context is created in the main thread. It is not allowed to update this context from another thread, which is exactly what our draw-thread is trying. The other solution would be to move all of SDL into the draw-thread, but that would introduce a whole scala of different problems. The wayland SDL backend is significantly faster than the X11 SDL backend, but there is a performance hit nevertheless. --- src/video/sdl2_v.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 66e6586fdc..fd6cf6c112 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -715,6 +715,17 @@ const char *VideoDriver_SDL::Start(const StringList &parm) MarkWholeScreenDirty(); _draw_threaded = !GetDriverParamBool(parm, "no_threads") && !GetDriverParamBool(parm, "no_thread"); + /* Wayland SDL video driver uses EGL to render the game. SDL created the + * EGL context from the main-thread, and with EGL you are not allowed to + * draw in another thread than the context was created. The function of + * _draw_threaded is to do exactly this: draw in another thread than the + * window was created, and as such, this fails on Wayland SDL video + * driver. So, we disable threading by default if Wayland SDL video + * driver is detected. + */ + if (strcmp(dname, "wayland") == 0) { + _draw_threaded = false; + } SDL_StopTextInput(); this->edit_box_focused = false; From 9322b40df1bf0987a440404fbb2c72dfb4410ba3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 7 Feb 2021 12:54:02 +0100 Subject: [PATCH 033/275] Fix: [CMake] our allegro drivers use v4, so skip v5 if found (#8653) On some distros allegro v5 is called allegro-5, but on some others it is not. So this should fix for all distros that allegro v5 is not being picked up, and only v4 is. --- cmake/FindAllegro.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindAllegro.cmake b/cmake/FindAllegro.cmake index 3c90d2c4e7..5d873dd3e1 100644 --- a/cmake/FindAllegro.cmake +++ b/cmake/FindAllegro.cmake @@ -31,7 +31,7 @@ The following cache variables may also be set: #]=======================================================================] find_package(PkgConfig QUIET) -pkg_check_modules(PC_Allegro QUIET allegro) +pkg_check_modules(PC_Allegro QUIET allegro<5) find_path(Allegro_INCLUDE_DIR NAMES allegro.h From 2a6da319b2578944b2ac6b1a267bf880e5c4d34c Mon Sep 17 00:00:00 2001 From: Matt Kimber Date: Sun, 7 Feb 2021 15:15:46 +0000 Subject: [PATCH 034/275] Fix 0125892: Don't crash when towns upgrade road tiles during expansion (#8651) --- src/road_cmd.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index c94beb0b16..b476416899 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -2291,7 +2291,7 @@ static bool CanConvertUnownedRoadType(Owner owner, RoadTramType rtt) } /** - * Convert the ownership of the RoadType of the tile if applyable + * Convert the ownership of the RoadType of the tile if applicable * @param tile the tile of which convert ownership * @param num_pieces the count of the roadbits to assign to the new owner * @param owner the current owner of the RoadType @@ -2428,11 +2428,9 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 cost.AddCost(num_pieces * RoadConvertCost(from_type, to_type)); if (flags & DC_EXEC) { // we can safely convert, too - /* Update the company infrastructure counters. */ + /* Call ConvertRoadTypeOwner() to update the company infrastructure counters. */ if (owner == _current_company) { - Company * c = Company::Get(_current_company); - c->infrastructure.road[from_type] -= num_pieces; - c->infrastructure.road[to_type] += num_pieces; + ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type); } /* Perform the conversion */ From f7ac2969ef4eae88ef61ec095b0ad081e79168aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 7 Feb 2021 16:19:30 +0100 Subject: [PATCH 035/275] Fix: [CMake] Restore 'games' as default install bindir (#8629) --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fb7a2309a..be544316dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,10 +23,13 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) # Use GNUInstallDirs to allow customisation -# but set our own default data dir +# but set our own default data and bin dir if(NOT CMAKE_INSTALL_DATADIR) set(CMAKE_INSTALL_DATADIR "share/games") endif() +if(NOT CMAKE_INSTALL_BINDIR) + set(CMAKE_INSTALL_BINDIR "games") +endif() include(GNUInstallDirs) include(Options) From b927da73c1c2e354731b410e02f4b98b1b311ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 7 Feb 2021 16:20:26 +0100 Subject: [PATCH 036/275] Fix 81d335b081: Use non-pulsating red highlight for coverage (#8622) --- src/viewport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index 822b0db9c2..2a3f9b32de 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1030,7 +1030,7 @@ static void DrawTileHighlightType(const TileInfo *ti, TileHighlightType tht) case THT_NONE: break; case THT_WHITE: DrawTileSelectionRect(ti, PAL_NONE); break; case THT_BLUE: DrawTileSelectionRect(ti, PALETTE_SEL_TILE_BLUE); break; - case THT_RED: DrawTileSelectionRect(ti, PALETTE_TILE_RED_PULSATING); break; + case THT_RED: DrawTileSelectionRect(ti, PALETTE_SEL_TILE_RED); break; } } From 2cbfcd232758967fa84794967d71d9584ec799ec Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 5 Feb 2021 02:00:36 +0100 Subject: [PATCH 037/275] Change: [CMake] Bump minimum version to 3.9 --- CMakeLists.txt | 11 +++-------- cmake/FindICU.cmake | 5 +++++ src/settingsgen/CMakeLists.txt | 2 +- src/strgen/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be544316dd..8fbf3507d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.9) if(NOT BINARY_NAME) set(BINARY_NAME openttd) @@ -143,13 +143,8 @@ find_package(Xaudio2) find_package(Grfcodec) -# IPO is only properly supported from CMake 3.9. Despite the fact we are -# CMake 3.5, still enable IPO if we detect we are 3.9+. -if(POLICY CMP0069) - cmake_policy(SET CMP0069 NEW) - include(CheckIPOSupported) - check_ipo_supported(RESULT IPO_FOUND) -endif() +include(CheckIPOSupported) +check_ipo_supported(RESULT IPO_FOUND) show_options() diff --git a/cmake/FindICU.cmake b/cmake/FindICU.cmake index b110dbf404..d12f36b0ad 100644 --- a/cmake/FindICU.cmake +++ b/cmake/FindICU.cmake @@ -1,3 +1,8 @@ +# CMake provides a FindICU module since version 3.7. +# But it doesn't use pkgconfig, doesn't set expected variables, +# And it returns incomplete dependencies if only some modules are searched. + + #[=======================================================================[.rst: FindICU ------- diff --git a/src/settingsgen/CMakeLists.txt b/src/settingsgen/CMakeLists.txt index 69b2092017..43d5284e62 100644 --- a/src/settingsgen/CMakeLists.txt +++ b/src/settingsgen/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.9) if (NOT HOST_BINARY_DIR) project(settingsgen) diff --git a/src/strgen/CMakeLists.txt b/src/strgen/CMakeLists.txt index 08c1223350..490f675f2e 100644 --- a/src/strgen/CMakeLists.txt +++ b/src/strgen/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.9) if (NOT HOST_BINARY_DIR) project(strgen) From af0acc9a75c4399d5aa330a811e0706be20b5995 Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 5 Feb 2021 16:10:42 +0100 Subject: [PATCH 038/275] Update: Specify CMake minimum version in COMPILING.md Also give some hints for MSVC users. --- COMPILING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/COMPILING.md b/COMPILING.md index 145b244753..5e642dc874 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -57,6 +57,9 @@ To install both the x64 (64bit) and x86 (32bit) variants (though only one is nec ``` You can open the folder (as a CMake project). CMake will be detected, and you can compile from there. +If libraries are installed but not found, you need to set VCPKG_TARGET_TRIPLET in CMake parameters. +For Visual Studio 2017 you also need to set CMAKE_TOOLCHAIN_FILE. +(Typical values are shown in the MSVC project file command line example) Alternatively, you can create a MSVC project file via CMake. For this either download CMake from https://cmake.org/download/ or use the version @@ -73,6 +76,7 @@ in the build folder are MSVC project files. MSVC can rebuild the project files himself via the `ZERO_CHECK` project. ## All other platforms +Minimum required version of CMake is 3.9. ```bash mkdir build From da4c404f3d9be98427d292dd2dd707573aa4a68f Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Mon, 8 Feb 2021 15:39:53 +0000 Subject: [PATCH 039/275] Fix: [Actions] Use same vcpkg commit for CI on macOS as release builds --- .github/workflows/ci-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 8b9a160d96..9833d5e512 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -159,7 +159,8 @@ jobs: uses: lukka/run-vcpkg@v6 with: vcpkgDirectory: '/usr/local/share/vcpkg' - doNotUpdateVcpkg: true + doNotUpdateVcpkg: false + vcpkgGitCommitId: 2a42024b53ebb512fb5dd63c523338bf26c8489c vcpkgArguments: 'freetype liblzma lzo' vcpkgTriplet: '${{ matrix.arch }}-osx' From ac2b5e57cf2805eb24370b664380322d62a04eff Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 8 Feb 2021 19:07:34 +0100 Subject: [PATCH 040/275] Fix: mention our websites with https:// (instead of http://) (#8657) It is 2021. Nobody should advertise http anymore. Not even us. --- src/misc_gui.cpp | 2 +- src/network/network_content_gui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e5da5f3a12..9d0259b3be 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -510,7 +510,7 @@ struct AboutWindow : public Window { void SetStringParameters(int widget) const override { - if (widget == WID_A_WEBSITE) SetDParamStr(0, "Website: http://www.openttd.org"); + if (widget == WID_A_WEBSITE) SetDParamStr(0, "Website: https://www.openttd.org"); if (widget == WID_A_COPYRIGHT) SetDParamStr(0, _openttd_revision_year); } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 06e57a2ac2..13e162b07a 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -325,7 +325,7 @@ class NetworkContentListWindow : public Window, ContentCallback { char url[1024]; const char *last = lastof(url); - char *pos = strecpy(url, "http://grfsearch.openttd.org/?", last); + char *pos = strecpy(url, "https://grfsearch.openttd.org/?", last); if (this->auto_select) { pos = strecpy(pos, "do=searchgrfid&q=", last); From 6c8f2227cdc01c978ec1cbf08a93925e148175b8 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 8 Feb 2021 13:18:30 -0500 Subject: [PATCH 041/275] Fix: [Emscripten] open links in browser (#8655) --- os/emscripten/pre.js | 28 ++++++++++++++++++++++++++++ src/os/unix/unix.cpp | 12 +++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/os/emscripten/pre.js b/os/emscripten/pre.js index 5cbd899e04..1563e4f95b 100644 --- a/os/emscripten/pre.js +++ b/os/emscripten/pre.js @@ -71,6 +71,34 @@ Module.preRun.push(function() { * add_server("localhost", 3979); */ } + var leftButtonDown = false; + document.addEventListener("mousedown", e => { + if (e.button == 0) { + leftButtonDown = true; + } + }); + document.addEventListener("mouseup", e => { + if (e.button == 0) { + leftButtonDown = false; + } + }); + window.openttd_open_url = function(url, url_len) { + const url_string = UTF8ToString(url, url_len); + function openWindow() { + document.removeEventListener("mouseup", openWindow); + window.open(url_string, '_blank'); + } + /* Trying to open the URL while the mouse is down results in the button getting stuck, so wait for the + * mouse to be released before opening it. However, when OpenTTD is lagging, the mouse can get released + * before the button click even registers, so check for that, and open the URL immediately if that's the + * case. */ + if (leftButtonDown) { + document.addEventListener("mouseup", openWindow); + } else { + openWindow(); + } + } + /* https://github.com/emscripten-core/emscripten/pull/12995 implements this * properly. Till that time, we use a polyfill. */ SOCKFS.websocket_sock_ops.createPeer_ = SOCKFS.websocket_sock_ops.createPeer; diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 4b94539b03..9ef2bc386d 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -28,6 +28,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +# include +#endif + #ifdef __APPLE__ # include #elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__) @@ -288,7 +292,13 @@ bool GetClipboardContents(char *buffer, const char *last) #endif -#ifndef __APPLE__ +#if defined(__EMSCRIPTEN__) +void OSOpenBrowser(const char *url) +{ + /* Implementation in pre.js */ + EM_ASM({ if(window["openttd_open_url"]) window.openttd_open_url($0, $1) }, url, strlen(url)); +} +#elif !defined( __APPLE__) void OSOpenBrowser(const char *url) { pid_t child_pid = fork(); From 395e015282279e95910128ebcd221879a22f9421 Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Sat, 30 Jan 2021 09:36:20 +0000 Subject: [PATCH 042/275] Change: Convert .md to .rtf for Windows/Mac packages --- .github/workflows/release.yml | 12 ++++++++++++ CMakeLists.txt | 4 ++++ cmake/FindPandoc.cmake | 3 +++ cmake/InstallAndPackage.cmake | 9 ++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 cmake/FindPandoc.cmake diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 63af9ff872..07feba9186 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -461,6 +461,13 @@ jobs: run: | tar -xf source.tar.gz --strip-components=1 + - name: Install dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + run: | + brew install pandoc + # The following step can be removed when the build VM is updated with a revision of # vcpkg dating from roughly 01/01/2021 or later. At that point, `doNotUpdateVcpkg` # can be set to `true` and the `vcpkgGitCommitId` can be removed. @@ -638,6 +645,11 @@ jobs: run: | tar -xf source.tar.gz --strip-components=1 + - name: Install dependencies + shell: bash + run: | + choco install pandoc + # "restore-cache" which is done by "run-vcpkg" uses Windows tar. # A git clone on windows marks a few files as read-only; when Windows tar # tries to extract the cache over this folder, it fails, despite the files diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fbf3507d0..c5d7ac1137 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -337,4 +337,8 @@ endif() include(CreateRegression) create_regression() +if(APPLE OR WIN32) + find_package(Pandoc) +endif() + include(InstallAndPackage) diff --git a/cmake/FindPandoc.cmake b/cmake/FindPandoc.cmake new file mode 100644 index 0000000000..3a42851dd7 --- /dev/null +++ b/cmake/FindPandoc.cmake @@ -0,0 +1,3 @@ +if(NOT EXISTS ${PANDOC_EXECUTABLE}) + find_program(PANDOC_EXECUTABLE pandoc) +endif() diff --git a/cmake/InstallAndPackage.cmake b/cmake/InstallAndPackage.cmake index 5c56d2d6d5..5fd17cb037 100644 --- a/cmake/InstallAndPackage.cmake +++ b/cmake/InstallAndPackage.cmake @@ -95,7 +95,14 @@ set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.openttd.org/") set(CPACK_PACKAGE_CONTACT "OpenTTD ") set(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenTTD") set(CPACK_PACKAGE_CHECKSUM "SHA256") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING.md") + +if((APPLE OR WIN32) AND EXISTS ${PANDOC_EXECUTABLE}) + execute_process(COMMAND ${PANDOC_EXECUTABLE} "${CMAKE_SOURCE_DIR}/COPYING.md" -s -o "${CMAKE_BINARY_DIR}/COPYING.rtf") + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/COPYING.rtf") +else() + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING.md") +endif() + set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") set(CPACK_MONOLITHIC_INSTALL YES) set(CPACK_PACKAGE_EXECUTABLES "openttd;OpenTTD") From f1f281b318dc562d5741b55ff25198f3f1602312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Tue, 9 Feb 2021 21:21:57 +0100 Subject: [PATCH 043/275] Fix: [Win32] Set minimum resolution for timers to 1ms. (#8660) --- src/os/windows/crashlog_win.cpp | 4 ++++ src/os/windows/win32.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 872e472d5e..b5916dd261 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "../../safeguards.h" @@ -540,6 +541,9 @@ void *_safe_esp = nullptr; static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) { + /* Restore system timer resolution. */ + timeEndPeriod(1); + /* Disable our event loop. */ SetWindowLongPtr(GetActiveWindow(), GWLP_WNDPROC, (LONG_PTR)&DefWindowProc); diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 6576ea20d7..8783b3762d 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -18,6 +18,7 @@ #define NO_SHOBJIDL_SORTDIRECTION // Avoid multiple definition of SORT_ASCENDING #include /* SHGetFolderPath */ #include +#include #include "win32.h" #include "../../fios.h" #include "../../core/alloc_func.hpp" @@ -413,6 +414,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi int argc; char *argv[64]; // max 64 command line arguments + /* Set system timer resolution to 1ms. */ + timeBeginPeriod(1); + CrashLog::InitialiseCrashLog(); #if defined(UNICODE) @@ -440,6 +444,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi for (int i = 0; i < argc; i++) ValidateString(argv[i]); openttd_main(argc, argv); + + /* Restore system timer resolution. */ + timeEndPeriod(1); + free(cmdline); return 0; } From 83ddb1501fe059241ef11e88f14bcfb1dafa9b72 Mon Sep 17 00:00:00 2001 From: Kuhnovic <68320206+Kuhnovic@users.noreply.github.com> Date: Wed, 10 Feb 2021 16:35:50 +0100 Subject: [PATCH 044/275] Feature: Remove all industries button in scenario editor (#8550) --- src/industry_gui.cpp | 85 +++++++++++++++++++++++++++-------- src/lang/english.txt | 8 +++- src/widgets/industry_widget.h | 13 +++--- 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 58f4a6097a..f3d61ec6d6 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -37,6 +37,7 @@ #include "smallmap_gui.h" #include "widgets/dropdown_type.h" #include "widgets/industry_widget.h" +#include "clear_map.h" #include "table/strings.h" @@ -244,6 +245,14 @@ static const NWidgetPart _nested_build_industry_widgets[] = { NWidget(WWT_DEFSIZEBOX, COLOUR_DARK_GREEN), NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN), EndContainer(), + NWidget(NWID_SELECTION, COLOUR_DARK_GREEN, WID_DPI_SCENARIO_EDITOR_PANE), + NWidget(NWID_VERTICAL), + NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET), SetMinimalSize(0, 12), SetFill(1, 0), SetResize(1, 0), + SetDataTip(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET), SetMinimalSize(0, 12), SetFill(1, 0), SetResize(1, 0), + SetDataTip(STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES, STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP), + EndContainer(), + EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_MATRIX, COLOUR_DARK_GREEN, WID_DPI_MATRIX_WIDGET), SetMatrixDataTip(1, 0, STR_FUND_INDUSTRY_SELECTION_TOOLTIP), SetFill(1, 0), SetResize(1, 1), SetScrollbar(WID_DPI_SCROLLBAR), NWidget(NWID_VSCROLLBAR, COLOUR_DARK_GREEN, WID_DPI_SCROLLBAR), @@ -289,11 +298,6 @@ class BuildIndustryWindow : public Window { this->enabled[i] = false; } - if (_game_mode == GM_EDITOR) { // give room for the Many Random "button" - this->index[this->count] = INVALID_INDUSTRYTYPE; - this->enabled[this->count] = true; - this->count++; - } /* Fill the arrays with industries. * The tests performed after the enabled allow to load the industries * In the same way they are inserted by grf (if any) @@ -392,6 +396,13 @@ public: this->FinishInitNested(0); this->SetButtons(); + + /* Show scenario editor tools in editor. */ + if (_game_mode != GM_EDITOR) { + auto *se_tools = this->GetWidget(WID_DPI_SCENARIO_EDITOR_PANE); + se_tools->SetDisplayedPlane(SZSP_HORIZONTAL); + this->ReInit(); + } } void OnInit() override @@ -578,9 +589,53 @@ public: } } + static void AskManyRandomIndustriesCallback(Window *w, bool confirmed) + { + if (!confirmed) return; + + if (Town::GetNumItems() == 0) { + ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_INDUSTRIES, STR_ERROR_MUST_FOUND_TOWN_FIRST, WL_INFO); + } else { + extern void GenerateIndustries(); + _generating_world = true; + GenerateIndustries(); + _generating_world = false; + } + } + + static void AskRemoveAllIndustriesCallback(Window *w, bool confirmed) + { + if (!confirmed) return; + + for (Industry* industry : Industry::Iterate()) delete industry; + + /* Clear farmland. */ + for (TileIndex tile = 0; tile < MapSize(); tile++) { + if (IsTileType(tile, MP_CLEAR) && GetRawClearGround(tile) == CLEAR_FIELDS) { + MakeClear(tile, CLEAR_GRASS, 3); + } + } + + MarkWholeScreenDirty(); + } + void OnClick(Point pt, int widget, int click_count) override { switch (widget) { + case WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET: { + assert(_game_mode == GM_EDITOR); + this->HandleButtonClick(WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET); + ShowQuery(STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY, nullptr, AskManyRandomIndustriesCallback); + break; + } + + case WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET: { + assert(_game_mode == GM_EDITOR); + this->HandleButtonClick(WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET); + ShowQuery(STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION, STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY, nullptr, AskRemoveAllIndustriesCallback); + break; + } + case WID_DPI_MATRIX_WIDGET: { int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_DPI_MATRIX_WIDGET); if (y < this->count) { // Is it within the boundaries of available data? @@ -610,22 +665,14 @@ public: break; case WID_DPI_FUND_WIDGET: { - if (this->selected_type == INVALID_INDUSTRYTYPE) { - this->HandleButtonClick(WID_DPI_FUND_WIDGET); - - if (Town::GetNumItems() == 0) { - ShowErrorMessage(STR_ERROR_CAN_T_GENERATE_INDUSTRIES, STR_ERROR_MUST_FOUND_TOWN_FIRST, WL_INFO); + if (this->selected_type != INVALID_INDUSTRYTYPE) + { + if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) { + DoCommandP(0, this->selected_type, InteractiveRandom(), CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY)); + this->HandleButtonClick(WID_DPI_FUND_WIDGET); } else { - extern void GenerateIndustries(); - _generating_world = true; - GenerateIndustries(); - _generating_world = false; + HandlePlacePushButton(this, WID_DPI_FUND_WIDGET, SPR_CURSOR_INDUSTRY, HT_RECT); } - } else if (_game_mode != GM_EDITOR && _settings_game.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) { - DoCommandP(0, this->selected_type, InteractiveRandom(), CMD_BUILD_INDUSTRY | CMD_MSG(STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY)); - this->HandleButtonClick(WID_DPI_FUND_WIDGET); - } else { - HandlePlacePushButton(this, WID_DPI_FUND_WIDGET, SPR_CURSOR_INDUSTRY, HT_RECT); } break; } diff --git a/src/lang/english.txt b/src/lang/english.txt index dc184aa317..567d238203 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2605,12 +2605,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Random # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Fund new industry STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Choose the appropriate industry from this list -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Many random industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Create random industries STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Cover the map with randomly placed industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Create random industries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Are you sure you want to create many random industries? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Cost: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospect STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Build STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Fund +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Remove all industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Remove all industries currently present on the map +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Remove all industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Are you sure you want to remove all industries? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Industry chain for {STRING} industry diff --git a/src/widgets/industry_widget.h b/src/widgets/industry_widget.h index e9fb2b1148..5e3a656c1f 100644 --- a/src/widgets/industry_widget.h +++ b/src/widgets/industry_widget.h @@ -12,11 +12,14 @@ /** Widgets of the #BuildIndustryWindow class. */ enum DynamicPlaceIndustriesWidgets { - WID_DPI_MATRIX_WIDGET, ///< Matrix of the industries. - WID_DPI_SCROLLBAR, ///< Scrollbar of the matrix. - WID_DPI_INFOPANEL, ///< Info panel about the industry. - WID_DPI_DISPLAY_WIDGET, ///< Display chain button. - WID_DPI_FUND_WIDGET, ///< Fund button. + WID_DPI_SCENARIO_EDITOR_PANE, ///< Pane containing SE-only widgets. + WID_DPI_REMOVE_ALL_INDUSTRIES_WIDGET, ///< Remove all industries button. + WID_DPI_CREATE_RANDOM_INDUSTRIES_WIDGET, ///< Create random industries button. + WID_DPI_MATRIX_WIDGET, ///< Matrix of the industries. + WID_DPI_SCROLLBAR, ///< Scrollbar of the matrix. + WID_DPI_INFOPANEL, ///< Info panel about the industry. + WID_DPI_DISPLAY_WIDGET, ///< Display chain button. + WID_DPI_FUND_WIDGET, ///< Fund button. }; /** Widgets of the #IndustryViewWindow class. */ From 64e2d6b6720ae16ba17a6b730e0319d267e07756 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 11 Feb 2021 19:01:10 +0000 Subject: [PATCH 045/275] Update: Translations from eints korean: 7 changes by telk5093 russian: 11 changes by Ln-Wolf finnish: 7 changes by hpiirai --- src/lang/finnish.txt | 8 +++++++- src/lang/korean.txt | 8 +++++++- src/lang/russian.txt | 16 +++++++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index d5f5dab40b..3fc54c1d49 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -2605,12 +2605,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Sattuman # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Rakenna uutta teollisuutta STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Valitse tehdas listasta -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Monta satunnaista teollisuusaluetta +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Luo satunnaisia tuotantolaitoksia STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Sijoita teollisuuslaitokset satunnaisesti +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Luo satunnaista teollisuutta +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Oletko varma, että haluat luoda monta satunnaista tuotantolaitosta? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Kustannus: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Koekaivaus STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Rakenna STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Perusta +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Poista kaikki tuotantolaitokset +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Poista kaikki kartalla olevat tuotantolaitokset +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Poista kaikki tuotantolaitokset +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Oletko varma, että haluat poistaa kaikki tuotantolaitokset? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Teollisuusketju teollisuudelle {STRING} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 4c7a16a9d7..202a28ff2f 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2606,12 +2606,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}임의 # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}새 산업시설 건설 STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}목록에서 적당한 산업시설을 선택하세요 -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :무작위 산업시설 건설 +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}무작위 산업시설 건설 STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}무작위로 산업시설을 건설합니다 +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}무작위 산업시설 건설 +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}정말 산업시설을 무작위로 건설하시겠습니까? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}가격: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}답사 STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}건설 STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}투자 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}모든 산업시설 제거 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}현재 지도 상에 있는 모든 산업시설을 제거합니다 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}모든 산업시설 제거 +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}정말 모든 산업시설을 제거하시겠습니까? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}{STRING}{G 0 "과" "와"} 관련된 산업시설 연계도 diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 4e380c1f12..9fdbe0a493 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2756,8 +2756,8 @@ STR_FOUND_TOWN_NEW_TOWN_BUTTON :{BLACK}Новы STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Построить новый город. Shift+щелчок - оценка стоимости основания. STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Случайный город STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Создать город в случайном месте -STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Много случайных городов -STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Случайно разместить на карте города +STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Множество различных городов +STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Разместить на карте различные города случайным образом STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Название города: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Введите название города @@ -2784,13 +2784,19 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Случ # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Создать новое предприятие -STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Выберите тип производства из списка -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Много предприятий -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Случайно разместить предприятия на карте +STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Выберите тип предприятия из списка +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Множество различных предприятий +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Разместить на карте различные предприятия случайным образом +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Множество различных предприятий +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Разместить на карте различные предприятия случайным образом? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Цена: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Разведать STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Построить STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Профинансировать +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Убрать все предприятия +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Убрать все предприятия с карты +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Убрать все предприятия +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Убрать все предприятия с карты? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Цепочка грузоперевозок для {STRING.gen} From 569ce6c7b43be52911d1a56ed43b890f5cc2d765 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 11 Feb 2021 09:35:42 +0100 Subject: [PATCH 046/275] Fix 30e69c51: palette was not marked dirty when creating a new This means the code depended that the caller did this for us before MakePalette() is executed, which is neither a requirement nor a promise the code makes. --- src/video/sdl2_v.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index fd6cf6c112..e24b31db58 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -95,6 +95,8 @@ static void MakePalette() if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError()); } + _cur_palette.first_dirty = 0; + _cur_palette.count_dirty = 256; _local_palette = _cur_palette; UpdatePalette(); From 2bbef6b5cf86dac53461e10c5720a05c579304d3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 11 Feb 2021 09:51:07 +0100 Subject: [PATCH 047/275] Codechange: [SDL2] Name paint function Paint(), like other drivers do This reduces confusion when reading different drivers. --- src/video/sdl2_v.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index e24b31db58..798f40a596 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -133,7 +133,7 @@ void VideoDriver_SDL::CheckPaletteAnim() this->MakeDirty(0, 0, _screen.width, _screen.height); } -static void DrawSurfaceToScreen() +static void Paint() { PerformanceMeasurer framerate(PFE_VIDEO); @@ -179,7 +179,7 @@ static void DrawSurfaceToScreen() _num_dirty_rects = 0; } -static void DrawSurfaceToScreenThread() +static void PaintThread() { /* First tell the main thread we're started */ std::unique_lock lock(*_draw_mutex); @@ -190,7 +190,7 @@ static void DrawSurfaceToScreenThread() while (_draw_continue) { /* Then just draw and wait till we stop */ - DrawSurfaceToScreen(); + Paint(); _draw_signal->wait(lock); } } @@ -834,7 +834,7 @@ void VideoDriver_SDL::LoopOnce() _draw_signal->notify_one(); } else { /* Oh, we didn't have threads, then just draw unthreaded */ - DrawSurfaceToScreen(); + Paint(); } } @@ -857,7 +857,7 @@ void VideoDriver_SDL::MainLoop() _draw_signal = new std::condition_variable_any(); _draw_continue = true; - _draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &DrawSurfaceToScreenThread); + _draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &PaintThread); /* Free the mutex if we won't be able to use it. */ if (!_draw_threaded) { From 2e1535389ac97c28ff2a4ea4fc82d057ba98aeed Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 11 Feb 2021 11:19:05 +0100 Subject: [PATCH 048/275] Codechange: [SDL2] Don't use globals if we can do with locals --- src/video/sdl2_v.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 798f40a596..49e8b42078 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -58,10 +58,6 @@ static bool _cursor_new_in_window = false; static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; static int _num_dirty_rects; -/* Size of window */ -static int _window_size_w; -static int _window_size_h; - void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) { if (_num_dirty_rects < MAX_DIRTY_RECTS) { @@ -929,9 +925,11 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen) std::unique_lock lock; if (_draw_mutex != nullptr) lock = std::unique_lock(*_draw_mutex); + int w, h; + /* Remember current window size */ if (fullscreen) { - SDL_GetWindowSize(_sdl_window, &_window_size_w, &_window_size_h); + SDL_GetWindowSize(_sdl_window, &w, &h); /* Find fullscreen window size */ SDL_DisplayMode dm; @@ -947,7 +945,7 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen) if (ret == 0) { /* Switching resolution succeeded, set fullscreen value of window. */ _fullscreen = fullscreen; - if (!fullscreen) SDL_SetWindowSize(_sdl_window, _window_size_w, _window_size_h); + if (!fullscreen) SDL_SetWindowSize(_sdl_window, w, h); } else { DEBUG(driver, 0, "SDL_SetWindowFullscreen() failed: %s", SDL_GetError()); } From 52317bb7df6d153ec332e5403ef75cb7bc86b8f6 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 11 Feb 2021 11:19:33 +0100 Subject: [PATCH 049/275] Change: [SDL2] Remove unneeded delay of redrawing the screen In testing, I could find no reason why this statement is here. The comment is rather unclear (it states what it does, but not why it would be needed). This line of code was introduced with f4f40448, which gives no further insight on why it would be needed to have it here. As such, let's remove it and see if anyone else reports any problems with it. If so, this commit can be reverted and a more clear comment should be added what this line of code is dealing with (the WHY, not the WHAT). --- src/video/sdl2_v.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 49e8b42078..6beeeac5c8 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -351,9 +351,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) _sdl_surface = _sdl_real_surface; } - /* Delay drawing for this cycle; the next cycle will redraw the whole screen */ - _num_dirty_rects = 0; - _screen.width = _sdl_surface->w; _screen.height = _sdl_surface->h; _screen.pitch = _sdl_surface->pitch / (bpp / 8); From fa0704138d2396875422960be6a3f1e7b6ab1341 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 12 Feb 2021 19:00:59 +0000 Subject: [PATCH 050/275] Update: Translations from eints spanish (mexican): 7 changes by absay dutch: 7 changes by Afoklala french: 7 changes by arikover --- src/lang/dutch.txt | 8 +++++++- src/lang/french.txt | 8 +++++++- src/lang/spanish_MX.txt | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 8adce96d86..fc8fafc207 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -2605,12 +2605,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Willekeu # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Nieuwe industrie financieren STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Kiest de gewenste industrie in de lijst -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Veel willekeurige industrieën +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Willekeurige industrieën maken STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Bedek de kaart met willekeurig geplaatste industrieën +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Willekeurige industrieën maken +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Weet je zeker dat je veel willekeurige industrieën wilt hebben? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Kosten: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Onderzoeken STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Bouw STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Betaal +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Alle industrieën verwijderen +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Alle industrieën op de kaart verwijderen +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Alle industrieën verwijderen +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Weet je zeker dat je alle industrieën wilt verwijderen? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Industrieketen voor {STRING} industrie diff --git a/src/lang/french.txt b/src/lang/french.txt index de7734ad5b..868063acb8 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -2606,12 +2606,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Aléatoi # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Financer une nouvelle industrie STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Choisir l'industrie appropriée dans cette liste -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Beaucoup d'industries au hasard +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Créer des industries au hasard STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Couvrir la carte d'industries placées au hasard +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Créer des industries au hasard +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Êtes-vous sûr de vouloir créer beaucoup d'industries au hasard{NBSP}? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Prix{NBSP}: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospecter STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Construire STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Fonder +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Enlever toutes les industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Enlève toutes les industries présentes sur la carte +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Enlever toutes les industries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Êtes-vous sûr de vouloir enlever toutes les industries{NBSP}? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Chaîne industrielle pour l'industrie «{NBSP}{STRING}{NBSP}» diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 434a01acc0..e05d0d1393 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -2606,12 +2606,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Aleatori # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Fundación de una nueva industria STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Elegir de la lista la industria adecuada -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Muchas industrias al azar +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Crear industrias al azar STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Cubrir el mapa con industrias colocadas al azar +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Crear industrias al azar +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}¿Seguro de crear muchas industrias al azar? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Costo: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospección STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Construir STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Fundar +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Eliminar todas las industrias +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Eliminar todas las industrias que haya en el mapa +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Eliminar todas las industrias +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}¿Seguro de eliminar todas las industrias? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Cadena industrial para la industria de {STRING} From 3ac43582c2a24238c0725524e7965f110451b643 Mon Sep 17 00:00:00 2001 From: "Johannes E. Krause" Date: Mon, 25 Jan 2021 17:29:09 +0100 Subject: [PATCH 051/275] Codechange: [NewGRF] Make it more explicit which parts of the TTD vehicle structure (var 80+) are not implemented --- src/newgrf_engine.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index d67a5c118c..ee14098c28 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -761,16 +761,29 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, } } - /* General vehicle properties */ + /* + * General vehicle properties + * + * Some parts of the TTD Vehicle structure are omitted for various reasons + * (see http://marcin.ttdpatch.net/sv1codec/TTD-locations.html#_VehicleArray) + */ switch (variable - 0x80) { case 0x00: return v->type + 0x10; case 0x01: return MapOldSubType(v); + case 0x02: break; // not implemented + case 0x03: break; // not implemented case 0x04: return v->index; case 0x05: return GB(v->index, 8, 8); + case 0x06: break; // not implemented + case 0x07: break; // not implemented + case 0x08: break; // not implemented + case 0x09: break; // not implemented case 0x0A: return v->current_order.MapOldOrder(); case 0x0B: return v->current_order.GetDestination(); case 0x0C: return v->GetNumOrders(); case 0x0D: return v->cur_real_order_index; + case 0x0E: break; // not implemented + case 0x0F: break; // not implemented case 0x10: case 0x11: { uint ticks; @@ -811,14 +824,31 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, case 0x1D: return GB(v->y_pos, 8, 8); case 0x1E: return v->z_pos; case 0x1F: return object->info_view ? DIR_W : v->direction; + case 0x20: break; // not implemented + case 0x21: break; // not implemented + case 0x22: break; // not implemented + case 0x23: break; // not implemented + case 0x24: break; // not implemented + case 0x25: break; // not implemented + case 0x26: break; // not implemented + case 0x27: break; // not implemented case 0x28: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs. case 0x29: return 0; // cur_image is a potential desyncer due to Action1 in static NewGRFs. + case 0x2A: break; // not implemented + case 0x2B: break; // not implemented + case 0x2C: break; // not implemented + case 0x2D: break; // not implemented + case 0x2E: break; // not implemented + case 0x2F: break; // not implemented + case 0x30: break; // not implemented + case 0x31: break; // not implemented case 0x32: return v->vehstatus; case 0x33: return 0; // non-existent high byte of vehstatus case 0x34: return v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed; case 0x35: return GB(v->type == VEH_AIRCRAFT ? (v->cur_speed * 10) / 128 : v->cur_speed, 8, 8); case 0x36: return v->subspeed; case 0x37: return v->acceleration; + case 0x38: break; // not implemented case 0x39: return v->cargo_type; case 0x3A: return v->cargo_cap; case 0x3B: return GB(v->cargo_cap, 8, 8); @@ -856,13 +886,43 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, case 0x58: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 16, 16); case 0x59: return GB(ClampToI32(v->GetDisplayProfitLastYear()), 24, 8); case 0x5A: return v->Next() == nullptr ? INVALID_VEHICLE : v->Next()->index; + case 0x5B: break; // not implemented case 0x5C: return ClampToI32(v->value); case 0x5D: return GB(ClampToI32(v->value), 8, 24); case 0x5E: return GB(ClampToI32(v->value), 16, 16); case 0x5F: return GB(ClampToI32(v->value), 24, 8); + case 0x60: break; // not implemented + case 0x61: break; // not implemented + case 0x62: break; // vehicle specific, see below + case 0x63: break; // not implemented + case 0x64: break; // vehicle specific, see below + case 0x65: break; // vehicle specific, see below + case 0x66: break; // vehicle specific, see below + case 0x67: break; // vehicle specific, see below + case 0x68: break; // vehicle specific, see below + case 0x69: break; // vehicle specific, see below + case 0x6A: break; // not implemented + case 0x6B: break; // not implemented + case 0x6C: break; // not implemented + case 0x6D: break; // not implemented + case 0x6E: break; // not implemented + case 0x6F: break; // not implemented + case 0x70: break; // not implemented + case 0x71: break; // not implemented case 0x72: return v->cargo_subtype; + case 0x73: break; // vehicle specific, see below + case 0x74: break; // vehicle specific, see below + case 0x75: break; // vehicle specific, see below + case 0x76: break; // vehicle specific, see below + case 0x77: break; // vehicle specific, see below + case 0x78: break; // not implemented + case 0x79: break; // not implemented case 0x7A: return v->random_bits; case 0x7B: return v->waiting_triggers; + case 0x7C: break; // vehicle specific, see below + case 0x7D: break; // vehicle specific, see below + case 0x7E: break; // not implemented + case 0x7F: break; // vehicle specific, see below } /* Vehicle specific properties */ From 5a4d5f03b088a29ca33b52354369d68c6f0b04ee Mon Sep 17 00:00:00 2001 From: glx22 Date: Sun, 24 Jan 2021 18:16:33 +0100 Subject: [PATCH 052/275] Codechange: Implement a constructor for CurrencySpec --- src/currency.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/currency.h b/src/currency.h index c4c3db0249..0bad4a0a1e 100644 --- a/src/currency.h +++ b/src/currency.h @@ -11,6 +11,7 @@ #define CURRENCY_H #include "date_type.h" +#include "string_func.h" #include "strings_type.h" static const int CF_NOEURO = 0; ///< Currency never switches to the Euro (as far as known). @@ -83,6 +84,15 @@ struct CurrencySpec { */ byte symbol_pos; StringID name; + + CurrencySpec() = default; + + CurrencySpec(uint16 rate, const char *separator, Year to_euro, const char *prefix, const char *suffix, byte symbol_pos, StringID name) : rate(rate), to_euro(to_euro), symbol_pos(symbol_pos), name(name) + { + strecpy(this->separator, separator, lastof(this->separator)); + strecpy(this->prefix, prefix, lastof(this->prefix)); + strecpy(this->suffix, suffix, lastof(this->suffix)); + } }; extern CurrencySpec _currency_specs[CURRENCY_END]; From f181037bede9dd41b845a3a6e4c4ce6eaf57fe3d Mon Sep 17 00:00:00 2001 From: glx22 Date: Mon, 25 Jan 2021 19:28:23 +0100 Subject: [PATCH 053/275] Change: [Actions] Also run CI for VS2017 --- .github/workflows/ci-build.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 9833d5e512..029c0416e9 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -211,11 +211,10 @@ jobs: strategy: fail-fast: false matrix: - include: - - arch: x86 - - arch: x64 + os: [windows-latest, windows-2016] + arch: [x86, x64] - runs-on: windows-latest + runs-on: ${{ matrix.os }} steps: - name: Checkout From 348f322df1274405d37fae3ae0aeeb7ba46fa90f Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 13 Feb 2021 18:38:32 +0100 Subject: [PATCH 054/275] Fix f1f281b31: [Win32] MinGW doesn't know timeapi.h --- src/os/windows/crashlog_win.cpp | 2 +- src/os/windows/win32.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index b5916dd261..4529491bd7 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -20,8 +20,8 @@ #include "../../video/video_driver.hpp" #include +#include #include -#include #include "../../safeguards.h" diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 8783b3762d..650413d023 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -14,11 +14,11 @@ #include "../../fileio_func.h" #include #include +#include #include #define NO_SHOBJIDL_SORTDIRECTION // Avoid multiple definition of SORT_ASCENDING #include /* SHGetFolderPath */ #include -#include #include "win32.h" #include "../../fios.h" #include "../../core/alloc_func.hpp" From d9df20d102c68cf7e2d7655b1006a868f5538d68 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sat, 13 Feb 2021 17:26:55 +0000 Subject: [PATCH 055/275] Change: Use a more specific error message when attempting to bulldoze your own HQ --- src/object_cmd.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 943d89322c..7a2ff26524 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -497,7 +497,10 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags) return_cmd_error(STR_ERROR_OWNED_BY); } else if ((spec->flags & OBJECT_FLAG_CANNOT_REMOVE) != 0 && (spec->flags & OBJECT_FLAG_AUTOREMOVE) == 0) { /* In the game editor or with cheats we can remove, otherwise we can't. */ - if (!_cheats.magic_bulldozer.value) return CMD_ERROR; + if (!_cheats.magic_bulldozer.value) { + if (type == OBJECT_HQ) return_cmd_error(STR_ERROR_COMPANY_HEADQUARTERS_IN); + return CMD_ERROR; + } /* Removing with the cheat costs more in TTDPatch / the specs. */ cost.MultiplyCost(25); From 36ab9c64efe8097b652d5fdee29dc8794a8a1b38 Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Mon, 18 Jan 2021 15:54:57 +0000 Subject: [PATCH 056/275] Fix: Desert/rainforest data coordinate 'y' is off by 1 when their 'x' coordinate is negative --- src/table/genland.h | 136 ++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/table/genland.h b/src/table/genland.h index 53801e2f68..7bc6294ec7 100644 --- a/src/table/genland.h +++ b/src/table/genland.h @@ -10,121 +10,121 @@ #define M(x, y) {x, y} static const TileIndexDiffC _make_desert_or_rainforest_data[] = { - M(-5, -6), - M(-4, -6), - M(-3, -6), - M(-2, -6), - M(-1, -6), + M(-5, -5), + M(-4, -5), + M(-3, -5), + M(-2, -5), + M(-1, -5), M( 0, -5), M( 1, -5), M( 2, -5), M( 3, -5), M( 4, -5), M( 5, -5), - M(-5, -5), - M(-4, -5), - M(-3, -5), - M(-2, -5), - M(-1, -5), + M(-5, -4), + M(-4, -4), + M(-3, -4), + M(-2, -4), + M(-1, -4), M( 0, -4), M( 1, -4), M( 2, -4), M( 3, -4), M( 4, -4), M( 5, -4), - M(-5, -4), - M(-4, -4), - M(-3, -4), - M(-2, -4), - M(-1, -4), + M(-5, -3), + M(-4, -3), + M(-3, -3), + M(-2, -3), + M(-1, -3), M( 0, -3), M( 1, -3), M( 2, -3), M( 3, -3), M( 4, -3), M( 5, -3), - M(-5, -3), - M(-4, -3), - M(-3, -3), - M(-2, -3), - M(-1, -3), + M(-5, -2), + M(-4, -2), + M(-3, -2), + M(-2, -2), + M(-1, -2), M( 0, -2), M( 1, -2), M( 2, -2), M( 3, -2), M( 4, -2), M( 5, -2), - M(-5, -2), - M(-4, -2), - M(-3, -2), - M(-2, -2), - M(-1, -2), + M(-5, -1), + M(-4, -1), + M(-3, -1), + M(-2, -1), + M(-1, -1), M( 0, -1), M( 1, -1), M( 2, -1), M( 3, -1), M( 4, -1), M( 5, -1), - M(-5, -1), - M(-4, -1), - M(-3, -1), - M(-2, -1), - M(-1, -1), + M(-5, 0), + M(-4, 0), + M(-3, 0), + M(-2, 0), + M(-1, 0), M( 0, 0), M( 1, 0), M( 2, 0), M( 3, 0), M( 4, 0), M( 5, 0), - M(-5, 0), - M(-4, 0), - M(-3, 0), - M(-2, 0), - M(-1, 0), + M(-5, 1), + M(-4, 1), + M(-3, 1), + M(-2, 1), + M(-1, 1), M( 0, 1), M( 1, 1), M( 2, 1), M( 3, 1), M( 4, 1), M( 5, 1), - M(-5, 1), - M(-4, 1), - M(-3, 1), - M(-2, 1), - M(-1, 1), + M(-5, 2), + M(-4, 2), + M(-3, 2), + M(-2, 2), + M(-1, 2), M( 0, 2), M( 1, 2), M( 2, 2), M( 3, 2), M( 4, 2), M( 5, 2), - M(-5, 2), - M(-4, 2), - M(-3, 2), - M(-2, 2), - M(-1, 2), + M(-5, 3), + M(-4, 3), + M(-3, 3), + M(-2, 3), + M(-1, 3), M( 0, 3), M( 1, 3), M( 2, 3), M( 3, 3), M( 4, 3), M( 5, 3), - M(-5, 3), - M(-4, 3), - M(-3, 3), - M(-2, 3), - M(-1, 3), + M(-5, 4), + M(-4, 4), + M(-3, 4), + M(-2, 4), + M(-1, 4), M( 0, 4), M( 1, 4), M( 2, 4), M( 3, 4), M( 4, 4), M( 5, 4), - M(-5, 4), - M(-4, 4), - M(-3, 4), - M(-2, 4), - M(-1, 4), + M(-5, 5), + M(-4, 5), + M(-3, 5), + M(-2, 5), + M(-1, 5), M( 0, 5), M( 1, 5), M( 2, 5), @@ -132,31 +132,31 @@ static const TileIndexDiffC _make_desert_or_rainforest_data[] = { M( 4, 5), M( 5, 5), M( 6, -3), - M(-6, -4), - M(-3, 5), - M(-3, -7), - M( 6, -2), M(-6, -3), - M(-2, 5), - M(-2, -7), - M( 6, -1), + M(-3, 6), + M(-3, -6), + M( 6, -2), M(-6, -2), - M(-1, 5), - M(-1, -7), - M( 6, 0), + M(-2, 6), + M(-2, -6), + M( 6, -1), M(-6, -1), + M(-1, 6), + M(-1, -6), + M( 6, 0), + M(-6, 0), M( 0, 6), M( 0, -6), M( 6, 1), - M(-6, 0), + M(-6, 1), M( 1, 6), M( 1, -6), M( 6, 2), - M(-6, 1), + M(-6, 2), M( 2, 6), M( 2, -6), M( 6, 3), - M(-6, 2), + M(-6, 3), M( 3, 6), M( 3, -6) }; From 0f621b4956b82313923ef28233cf52919f70eca3 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 13 Feb 2021 18:59:59 +0000 Subject: [PATCH 057/275] Update: Translations from eints portuguese (brazilian): 36 changes by AKANexus --- src/lang/brazilian_portuguese.txt | 51 ++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 43f1fe0738..ad0c7afad6 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -740,6 +740,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Terreno Irregular STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Gramado STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Terreno Descoberto +STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Floresta Tropical STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Campos STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Árvores STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Rochas @@ -1607,6 +1608,7 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Posicionamento de árvores: {STRING} STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Controla o nascimento aleatório de árvores durante o jogo. Isso pode afetar indústrias que dependem do crescimento de árvores, como serrarias STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Crescer sem espalhar {RED}(afeta serrarias) +STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Não crescer, não espalhar {RED}(afeta serrarias) STR_CONFIG_SETTING_TOOLBAR_POS :Posição da barra de ferramentas principal: {STRING} STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Posição horizontal da barra de ferramentas principal no topo da tela @@ -1673,6 +1675,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Sempre que uma STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Métrico (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Unidades de jogo (quadr./dia) STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Unidade de potência veicular: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Sempre que a potência de um veículo for exibida na interface de usuário, será exibida na unidade selecionada @@ -1805,12 +1808,13 @@ STR_INTRO_TRANSLATION :{BLACK}Faltam { # Quit window STR_QUIT_CAPTION :{WHITE}Sair +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Tem a certeza que quer sair do OpenTTD? STR_QUIT_YES :{BLACK}Sim STR_QUIT_NO :{BLACK}Não # Abandon game STR_ABANDON_GAME_CAPTION :{WHITE}Abandonar jogo -STR_ABANDON_GAME_QUERY :{YELLOW}Você tem certeza que deseja abandonar este jogo? +STR_ABANDON_GAME_QUERY :{YELLOW}Você tem certeza que quer abandonar este jogo? STR_ABANDON_SCENARIO_QUERY :{YELLOW}Você tem certeza que quer abandonar este cenário? # Cheat window @@ -1968,6 +1972,7 @@ STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Atualiza STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Atualiza as informações sobre o servidor STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Procurar na internet +STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Buscar na LAN STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Adicionar servidor STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adiciona um servidor à lista que será sempre verificada se existem jogos ocorrendo STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Iniciar servidor @@ -2198,6 +2203,7 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :número de joga STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :clientes conectando-se STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manual STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :{G=m}script do jogo +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :aguardando atualização do gráfico de links ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :saindo STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} entrou no jogo @@ -2326,6 +2332,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Unir pon STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Construir um ponto de controle separado # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Desativado pois não há nenhum veículo disponível para essa infraestrutura # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Construir ferrovias @@ -2521,6 +2528,10 @@ STR_TREES_RANDOM_TYPE :{BLACK}Árvores STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Plantar árvores de tipo aleatório, Shift alterna entre construção/preço estimado STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Plantar Aleatoriamente STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Planta árvores aleatoriamente pelo terreno +STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Normal +STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Bosque +STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}Planta pequenas florestas ao arrastar pelo terreno. +STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Floresta STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Planta florestas grandes ao arrastar pelo terreno. # Land generation window (SE) @@ -2532,10 +2543,10 @@ STR_TERRAFORM_TOOLTIP_DECREASE_SIZE_OF_LAND_AREA :{BLACK}Diminui STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND :{BLACK}Gera terreno aleatório STR_TERRAFORM_SE_NEW_WORLD :{BLACK}Criar novo cenário STR_TERRAFORM_RESET_LANDSCAPE :{BLACK}Limpar terreno -STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP :{BLACK}Remover todas as propriedades da companhia do mapa +STR_TERRAFORM_RESET_LANDSCAPE_TOOLTIP :{BLACK}Remove todas as propriedades da empresa do mapa STR_QUERY_RESET_LANDSCAPE_CAPTION :{WHITE}Limpar Terreno -STR_RESET_LANDSCAPE_CONFIRMATION_TEXT :{WHITE}Tem certeza que deseja remover todas as propriedades da companhia? +STR_RESET_LANDSCAPE_CONFIRMATION_TEXT :{WHITE}Tem certeza que quer remover todas as propriedades da empresa? # Town generation window (SE) STR_FOUND_TOWN_CAPTION :{WHITE}Gerar Cidades @@ -2574,10 +2585,14 @@ STR_FUND_INDUSTRY_CAPTION :{WHITE}Financia STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Escolha a indústria apropriada STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Várias indústrias aleatórias STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Cobrir o mapa com indústrias colocadas aleatoriamente +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Criar indústrias aleatórias +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Você tem certeza que quer criar várias indústrias aleatoriamente? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Custo: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prosperir STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Construir STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Fundar +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Remover todas as indústrias +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Remover todas as indústrias # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Cadeia de indústrias para a indústria: {STRING} @@ -3068,6 +3083,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Ativa/De # Sign window STR_EDIT_SIGN_CAPTION :{WHITE}Editar texto da placa +STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Centraliza janela no local da placa. Ctrl+Clique abre uma nova janela no local da placa STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Próxima Placa STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Placa anterior @@ -3279,7 +3295,7 @@ STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Impedir STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT} STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centrar visão no local do ponto de caminho. Ctrl+Clique abre uma nova janela no local do ponto de caminho STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Renomear ponto de controle -STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centrar visão no local da bóia. Ctrl+Clique abre uma nova janela no local da bóia +STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centraliza janela no local da bóia. Ctrl+Clique abre uma nova janela no local da bóia STR_BUOY_VIEW_CHANGE_BUOY_NAME :{BLACK}Renomear bóia STR_EDIT_WAYPOINT_NAME :{WHITE}Editar nome do ponto de controle @@ -3344,6 +3360,7 @@ STR_COMPANY_VIEW_RELOCATE_HQ :{BLACK}Mover se STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Reconstruir sede da empresa em outro local por 1% do valor da empresa. Shift+Clique mostra o preço estimado sem reconstruir a sede STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Detalhes STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}Ver informações detalhadas de infraestrutura +STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Dá dinheiro a essa empresa STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}Novo Rosto STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Selecionar novo rosto para o presidente @@ -3466,7 +3483,7 @@ STR_GROUP_LIVERY_TOOLTIP :{BLACK}Alterar STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para excluir esse grupo da substituição automática STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Remover grupo -STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Tem certeza que deseja remover esse grupo e seus descendentes? +STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Tem certeza que quer remover esse grupo e seus descendentes? STR_GROUP_ADD_SHARED_VEHICLE :Adicionar veículos compartilhados STR_GROUP_REMOVE_ALL_VEHICLES :Remover todos os veículos @@ -3531,19 +3548,19 @@ STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_BUTTON :{BLACK}Comprar STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_BUTTON :{BLACK}Comprar Aeronave STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Comprar e reequipar veículo -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Comprar e Trocar Veículos +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Comprar e Reequipar Veículo STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Comprar e Repor Navio STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}Comprar e reequipar aeronaves -STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Compra o veículo ferroviário selecionado. Shift+Clique mostra preço estimado sem a compra -STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Compra o veículo selecionado. Shift+Clique mostra preço estimado sem a compra +STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}Compra o veículo ferroviário selecionado. Shift+Clique mostra preço estimado +STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}Compra o veículo selecionado. Shift+Clique mostra preço estimado STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}Compra a embarcação selecionada. Shift+Clique mostra preço estimado sem a compra STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}Compra a aeronave selecionada. Shift+Clique mostra o preço estimado sem a compra -STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Compre e troque o trem destacado. Shift+Click mostra os custos estimados sem comprar +STR_BUY_VEHICLE_TRAIN_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Compra e troque o trem destacado. Shift+Click mostra o custo estimado STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Compre e troque o veículo terrestre destacado. Shift+Clique mostra o custo estimado sem comprá-lo -STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :Compre e reponha o navio em destaque. Shift+Clique mostra o custo estimado sem comprar -STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Comprar e repor a aeronave destacada. Shift+Clique mostra o custo estimado sem comprar +STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_TOOLTIP :Compre e reequipa o navio selecionado. Shift+Clique mostra o custo estimado +STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_TOOLTIP :{BLACK}Compra e reequipa a aeronave selecionada. Shift+Clique mostra o custo estimado STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON :{BLACK}Renomear STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_BUTTON :{BLACK}Renomear @@ -3629,9 +3646,9 @@ STR_DEPOT_CLONE_SHIP_DEPOT_INFO :{BLACK}Isso ir STR_DEPOT_CLONE_AIRCRAFT_INFO_HANGAR_WINDOW :{BLACK}Isso irá comprar uma cópia de uma aeronave. Clique nesse botão e depois em uma aeronave dentro ou fora do hangar. Ctrl+Clique compartilhará as ordens. Shift+Clique mostra o preço estimado sem a compra STR_DEPOT_TRAIN_LOCATION_TOOLTIP :{BLACK}Centrar visão no local de um depósito ferroviário. Ctrl+Clique abre uma nova janela no local do depósito de trem -STR_DEPOT_ROAD_VEHICLE_LOCATION_TOOLTIP :{BLACK}Centralizar visualização na localização da garagem. Ctrl+Clique abre uma nova janela de visualização -STR_DEPOT_SHIP_LOCATION_TOOLTIP :{BLACK}Centrar visão no local do depósito naval. Ctrl+Clique abre uma nova janela no local do depósito naval -STR_DEPOT_AIRCRAFT_LOCATION_TOOLTIP :{BLACK}Centrar visão no local do hangar. Ctrl+Clique abre uma nova janela no local do hangar +STR_DEPOT_ROAD_VEHICLE_LOCATION_TOOLTIP :{BLACK}Centraliza a janela na localização da garagem. Ctrl+Clique abre uma nova janela na localização da garagem. +STR_DEPOT_SHIP_LOCATION_TOOLTIP :{BLACK}Centraliza visão no local do depósito naval. Ctrl+Clique abre uma nova janela no local do depósito naval +STR_DEPOT_AIRCRAFT_LOCATION_TOOLTIP :{BLACK}Centraliza a janela no local do hangar. Ctrl+Clique abre uma nova janela no local do hangar STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TOOLTIP :{BLACK}Obtém uma lista de todos os trens com este depósito em suas ordens STR_DEPOT_VEHICLE_ORDER_LIST_ROAD_VEHICLE_TOOLTIP :{BLACK}Obtém uma lista de todos os automóveis com esta garagem em suas ordens @@ -3721,6 +3738,9 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Faz auto # Vehicle view STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE} +STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Centraliza a janela na localização do veículo. Clique duplo para seguir o veículo. Ctrl+Clique abre uma nova janela na localização do veículo. +STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Centraliza a janela na localização do navio. Clique duplo para seguir o navio. Ctrl+Clique para abrir uma nova janela na localização do navio. +STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Centraliza a janela na localização da aeronave. Clique duplo para seguir a aeronave. Ctrl+Clique abre uma nova janela na localização da aeronave. STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar trem para o depósito STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Enviar veículo para a garagem. CTRL+clique irá apenas reparar @@ -4333,7 +4353,7 @@ STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... muit STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... deve construir uma cidade antes STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... só é permitido uma por cidade STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... só pode ser construído em cidades com pelo menos 1200 habitantes -STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... só pode ser construído em zonas florestais +STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... só pode ser construído em florestas tropicais STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT :{WHITE}... só pode ser construído em áreas desérticas STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS :{WHITE}... só se pode ser construído em cidades (substituindo casas) STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER :{WHITE}... só pode ser construído próximo aos centros de cidades @@ -4430,6 +4450,7 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Tipo de depósi STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} fica grande demais para ser substituído STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}Regras de autosubstituição/renovação não estão ativadas STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(limite de dinheiro) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}Novo veículo não pode ser reequipado na ordem {NUM} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Impossível combinação de linhas From 9c9292949fa4d699c58d40abcac563a86df239dd Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 14 Dec 2020 00:11:39 +0100 Subject: [PATCH 058/275] Codechange: Don't use cpp_offsetof in the TTO/TTD savegame loader. Many of the member variables that are used in the oldloader are inside types that are not standard layout types. Using pointer arithmetics to determine addresses of members inside types that are not standard layout is generally undefined behaviour. If we'd use C++17, it is conditionally supported, which means each compiler may or may not support it. And even then using it for individual array elements is syntactically not supported the the standard offsetof function. --- src/saveload/oldloader.cpp | 12 +++++------- src/saveload/oldloader.h | 17 +++++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp index 42970c9a2f..6bc07ad27a 100644 --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -108,8 +108,6 @@ byte ReadByte(LoadgameState *ls) */ bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks) { - byte *base_ptr = (byte*)base; - for (const OldChunks *chunk = chunks; chunk->type != OC_END; chunk++) { if (((chunk->type & OC_TTD) && _savegame_type == SGT_TTO) || ((chunk->type & OC_TTO) && _savegame_type != SGT_TTO)) { @@ -134,8 +132,8 @@ bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks) break; case OC_ASSERT: - DEBUG(oldloader, 4, "Assert point: 0x%X / 0x%X", ls->total_read, chunk->offset + _bump_assert_value); - if (ls->total_read != chunk->offset + _bump_assert_value) throw std::exception(); + DEBUG(oldloader, 4, "Assert point: 0x%X / 0x%X", ls->total_read, (uint)(size_t)chunk->ptr + _bump_assert_value); + if (ls->total_read != (size_t)chunk->ptr + _bump_assert_value) throw std::exception(); default: break; } } else { @@ -153,10 +151,10 @@ bool LoadChunk(LoadgameState *ls, void *base, const OldChunks *chunks) } /* When both pointers are nullptr, we are just skipping data */ - if (base_ptr == nullptr && chunk->ptr == nullptr) continue; + if (base == nullptr && chunk->ptr == nullptr) continue; - /* Writing to the var: bits 8 to 15 have the VAR type */ - if (chunk->ptr == nullptr) ptr = base_ptr + chunk->offset; + /* Chunk refers to a struct member, get address in base. */ + if (chunk->ptr == nullptr) ptr = (byte *)chunk->offset(base); /* Write the data */ switch (GetOldChunkVarType(chunk->type)) { diff --git a/src/saveload/oldloader.h b/src/saveload/oldloader.h index 1600a9ac22..6879192ecd 100644 --- a/src/saveload/oldloader.h +++ b/src/saveload/oldloader.h @@ -82,13 +82,14 @@ enum OldChunkType { DECLARE_ENUM_AS_BIT_SET(OldChunkType) typedef bool OldChunkProc(LoadgameState *ls, int num); +typedef void *OffsetProc(void *base); struct OldChunks { OldChunkType type; ///< Type of field uint32 amount; ///< Amount of fields - void *ptr; ///< Pointer where to save the data (may only be set if offset is 0) - uint offset; ///< Offset from basepointer (may only be set if ptr is nullptr) + void *ptr; ///< Pointer where to save the data (takes precedence over #offset) + OffsetProc *offset; ///< Pointer to function that returns the actual memory address of a member (ignored if #ptr is not nullptr) OldChunkProc *proc; ///< Pointer to function that is called with OC_CHUNK }; @@ -123,12 +124,12 @@ static inline uint32 ReadUint32(LoadgameState *ls) * - OCL_CHUNK: load another proc to load a part of the savegame, 'amount' times * - OCL_ASSERT: to check if we are really at the place we expect to be.. because old savegames are too binary to be sure ;) */ -#define OCL_SVAR(type, base, offset) { type, 1, nullptr, (uint)cpp_offsetof(base, offset), nullptr } -#define OCL_VAR(type, amount, pointer) { type, amount, pointer, 0, nullptr } -#define OCL_END() { OC_END, 0, nullptr, 0, nullptr } -#define OCL_CNULL(type, amount) { OC_NULL | type, amount, nullptr, 0, nullptr } -#define OCL_CCHUNK(type, amount, proc) { OC_CHUNK | type, amount, nullptr, 0, proc } -#define OCL_ASSERT(type, size) { OC_ASSERT | type, 1, nullptr, size, nullptr } +#define OCL_SVAR(type, base, offset) { type, 1, nullptr, [] (void *b) -> void * { return std::addressof(static_cast(b)->offset); }, nullptr } +#define OCL_VAR(type, amount, pointer) { type, amount, pointer, nullptr, nullptr } +#define OCL_END() { OC_END, 0, nullptr, nullptr, nullptr } +#define OCL_CNULL(type, amount) { OC_NULL | type, amount, nullptr, nullptr, nullptr } +#define OCL_CCHUNK(type, amount, proc) { OC_CHUNK | type, amount, nullptr, nullptr, proc } +#define OCL_ASSERT(type, size) { OC_ASSERT | type, 1, (void *)(size_t)size, nullptr, nullptr } #define OCL_NULL(amount) OCL_CNULL((OldChunkType)0, amount) #define OCL_CHUNK(amount, proc) OCL_CCHUNK((OldChunkType)0, amount, proc) From 7845434270524d4c777a6711d2e17ac89eeeeb89 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 14 Dec 2020 00:14:37 +0100 Subject: [PATCH 059/275] Codechange: Don't use cpp_offsetof in the save/load code. Many of the member variables that are used in save/load are inside types that are not standard layout types. Using pointer arithmetics to determine addresses of members inside types that are not standard layout is generally undefined behaviour. If we'd use C++17, it is conditionally supported, which means each compiler may or may not support it. And even then using it for individual array elements is syntactically not supported the the standard offsetof function. Unfortunately, the trickery employed for saving linkgraph settings causes quite some clutter in the settings ini files. --- src/saveload/linkgraph_sl.cpp | 28 ++++++----- src/saveload/saveload.h | 84 +++++++++++++++------------------ src/table/company_settings.ini | 5 +- src/table/currency_settings.ini | 7 +-- src/table/gameopt_settings.ini | 13 ++--- src/table/misc_settings.ini | 15 +++--- src/table/settings.h.preamble | 84 ++++++++++++++++----------------- src/table/settings.ini | 44 ++++++++++++----- src/table/win32_settings.ini | 5 +- src/table/window_settings.ini | 5 +- 10 files changed, 155 insertions(+), 135 deletions(-) diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index aa3a2ff4b8..a597edfc43 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -53,11 +53,23 @@ const SaveLoad *GetLinkGraphJobDesc() static std::vector saveloads; static const char *prefix = "linkgraph."; + static const SaveLoad job_desc[] = { + SLE_VAR(LinkGraphJob, join_date, SLE_INT32), + SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16), + SLE_END() + }; + + /* The member offset arithmetic below is only valid if the types in question + * are standard layout types. Otherwise, it would be undefined behaviour. */ + static_assert(std::is_standard_layout::value, "LinkGraphSettings needs to be a standard layout type"); + + /* We store the offset of each member of the #LinkGraphSettings in the + * extra data of the saveload struct. Use it together with the address + * of the settings struct inside the job to find the final memory address. */ + static SaveLoadAddrProc * const proc = [](void *b, size_t extra) -> void * { return const_cast(static_cast(reinterpret_cast(std::addressof(static_cast(b)->settings)) + extra)); }; + /* Build the SaveLoad array on first call and don't touch it later on */ if (saveloads.size() == 0) { - size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph); - size_t offset_component = cpp_offsetof(LinkGraphJob, settings); - size_t prefixlen = strlen(prefix); int setting = 0; @@ -65,20 +77,12 @@ const SaveLoad *GetLinkGraphJobDesc() while (desc->save.cmd != SL_END) { if (desc->desc.name != nullptr && strncmp(desc->desc.name, prefix, prefixlen) == 0) { SaveLoad sl = desc->save; - char *&address = reinterpret_cast(sl.address); - address -= offset_gamesettings; - address += offset_component; + sl.address_proc = proc; saveloads.push_back(sl); } desc = GetSettingDescription(++setting); } - const SaveLoad job_desc[] = { - SLE_VAR(LinkGraphJob, join_date, SLE_INT32), - SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16), - SLE_END() - }; - int i = 0; do { saveloads.push_back(job_desc[i++]); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index ac4658455c..7f4f0d287c 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -385,10 +385,6 @@ struct ChunkHandler { uint32 flags; ///< Flags of the chunk. @see ChunkType }; -struct NullStruct { - byte null; -}; - /** Type of reference (#SLE_REF, #SLE_CONDREF). */ enum SLRefType { REF_ORDER = 0, ///< Load/save a reference to an order. @@ -499,7 +495,7 @@ enum VarTypes { typedef uint32 VarType; /** Type of data saved. */ -enum SaveLoadTypes { +enum SaveLoadType : byte { SL_VAR = 0, ///< Save/load a variable. SL_REF = 1, ///< Save/load a reference. SL_ARR = 2, ///< Save/load an array. @@ -514,22 +510,18 @@ enum SaveLoadTypes { SL_END = 15 }; -typedef byte SaveLoadType; ///< Save/load type. @see SaveLoadTypes +typedef void *SaveLoadAddrProc(void *base, size_t extra); /** SaveLoad type struct. Do NOT use this directly but use the SLE_ macros defined just below! */ struct SaveLoad { - bool global; ///< should we load a global variable or a non-global one SaveLoadType cmd; ///< the action to take with the saved/loaded type, All types need different action VarType conv; ///< type of the variable to be saved, int uint16 length; ///< (conditional) length of the variable (eg. arrays) (max array size is 65536 elements) - SaveLoadVersion version_from; ///< save/load the variable starting from this savegame version - SaveLoadVersion version_to; ///< save/load the variable until this savegame version - /* NOTE: This element either denotes the address of the variable for a global - * variable, or the offset within a struct which is then bound to a variable - * during runtime. Decision on which one to use is controlled by the function - * that is called to save it. address: global=true, offset: global=false */ - void *address; ///< address of variable OR offset of variable in the struct (max offset is 65536) - size_t size; ///< the sizeof size. + SaveLoadVersion version_from; ///< save/load the variable starting from this savegame version + SaveLoadVersion version_to; ///< save/load the variable until this savegame version + size_t size; ///< the sizeof size. + SaveLoadAddrProc *address_proc; ///< callback proc the get the actual variable address in memory + size_t extra_data; ///< extra data for the callback proc }; /** Same as #SaveLoad but global variables are used (for better readability); */ @@ -543,9 +535,10 @@ typedef SaveLoad SaveLoadGlobVarList; * @param type Storage of the data in memory and in the savegame. * @param from First savegame version that has the field. * @param to Last savegame version that has the field. + * @param extra Extra data to pass to the address callback function. * @note In general, it is better to use one of the SLE_* macros below. */ -#define SLE_GENERAL(cmd, base, variable, type, length, from, to) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable), cpp_sizeof(base, variable)} +#define SLE_GENERAL(cmd, base, variable, type, length, from, to, extra) {cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast(static_cast(std::addressof(static_cast(b)->variable))); }, extra} /** * Storage of a variable in some savegame versions. @@ -555,7 +548,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the field. * @param to Last savegame version that has the field. */ -#define SLE_CONDVAR(base, variable, type, from, to) SLE_GENERAL(SL_VAR, base, variable, type, 0, from, to) +#define SLE_CONDVAR(base, variable, type, from, to) SLE_GENERAL(SL_VAR, base, variable, type, 0, from, to, 0) /** * Storage of a reference in some savegame versions. @@ -565,7 +558,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the field. * @param to Last savegame version that has the field. */ -#define SLE_CONDREF(base, variable, type, from, to) SLE_GENERAL(SL_REF, base, variable, type, 0, from, to) +#define SLE_CONDREF(base, variable, type, from, to) SLE_GENERAL(SL_REF, base, variable, type, 0, from, to, 0) /** * Storage of an array in some savegame versions. @@ -576,7 +569,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the array. * @param to Last savegame version that has the array. */ -#define SLE_CONDARR(base, variable, type, length, from, to) SLE_GENERAL(SL_ARR, base, variable, type, length, from, to) +#define SLE_CONDARR(base, variable, type, length, from, to) SLE_GENERAL(SL_ARR, base, variable, type, length, from, to, 0) /** * Storage of a string in some savegame versions. @@ -587,7 +580,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the string. * @param to Last savegame version that has the string. */ -#define SLE_CONDSTR(base, variable, type, length, from, to) SLE_GENERAL(SL_STR, base, variable, type, length, from, to) +#define SLE_CONDSTR(base, variable, type, length, from, to) SLE_GENERAL(SL_STR, base, variable, type, length, from, to, 0) /** * Storage of a \c std::string in some savegame versions. @@ -597,7 +590,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the string. * @param to Last savegame version that has the string. */ -#define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to) +#define SLE_CONDSSTR(base, variable, type, from, to) SLE_GENERAL(SL_STDSTR, base, variable, type, 0, from, to, 0) /** * Storage of a list in some savegame versions. @@ -607,7 +600,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLE_CONDLST(base, variable, type, from, to) SLE_GENERAL(SL_LST, base, variable, type, 0, from, to) +#define SLE_CONDLST(base, variable, type, from, to) SLE_GENERAL(SL_LST, base, variable, type, 0, from, to, 0) /** * Storage of a deque in some savegame versions. @@ -617,7 +610,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLE_CONDDEQUE(base, variable, type, from, to) SLE_GENERAL(SL_DEQUE, base, variable, type, 0, from, to) +#define SLE_CONDDEQUE(base, variable, type, from, to) SLE_GENERAL(SL_DEQUE, base, variable, type, 0, from, to, 0) /** * Storage of a variable in every version of a savegame. @@ -681,16 +674,16 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLE_CONDNULL(length, from, to) SLE_CONDARR(NullStruct, null, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to) +#define SLE_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, 0, nullptr, 0} /** Translate values ingame to different values in the savegame and vv. */ -#define SLE_WRITEBYTE(base, variable) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION) +#define SLE_WRITEBYTE(base, variable) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0) -#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, nullptr, 0} -#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, nullptr, 0} +#define SLE_VEH_INCLUDE() {SL_VEH_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0, [] (void *b, size_t) { return b; }, 0} +#define SLE_ST_INCLUDE() {SL_ST_INCLUDE, 0, 0, SL_MIN_VERSION, SL_MAX_VERSION, 0, [] (void *b, size_t) { return b; }, 0} /** End marker of a struct/class save or load. */ -#define SLE_END() {false, SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, nullptr, 0} +#define SLE_END() {SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, 0, nullptr, 0} /** * Storage of global simple variables, references (pointers), and arrays. @@ -699,9 +692,10 @@ typedef SaveLoad SaveLoadGlobVarList; * @param type Storage of the data in memory and in the savegame. * @param from First savegame version that has the field. * @param to Last savegame version that has the field. + * @param extra Extra data to pass to the address callback function. * @note In general, it is better to use one of the SLEG_* macros below. */ -#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable, sizeof(variable)} +#define SLEG_GENERAL(cmd, variable, type, length, from, to, extra) {cmd, type, length, from, to, sizeof(variable), [] (void *, size_t) -> void * { return static_cast(std::addressof(variable)); }, extra} /** * Storage of a global variable in some savegame versions. @@ -710,7 +704,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the field. * @param to Last savegame version that has the field. */ -#define SLEG_CONDVAR(variable, type, from, to) SLEG_GENERAL(SL_VAR, variable, type, 0, from, to) +#define SLEG_CONDVAR(variable, type, from, to) SLEG_GENERAL(SL_VAR, variable, type, 0, from, to, 0) /** * Storage of a global reference in some savegame versions. @@ -719,7 +713,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the field. * @param to Last savegame version that has the field. */ -#define SLEG_CONDREF(variable, type, from, to) SLEG_GENERAL(SL_REF, variable, type, 0, from, to) +#define SLEG_CONDREF(variable, type, from, to) SLEG_GENERAL(SL_REF, variable, type, 0, from, to, 0) /** * Storage of a global array in some savegame versions. @@ -729,7 +723,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the array. * @param to Last savegame version that has the array. */ -#define SLEG_CONDARR(variable, type, length, from, to) SLEG_GENERAL(SL_ARR, variable, type, length, from, to) +#define SLEG_CONDARR(variable, type, length, from, to) SLEG_GENERAL(SL_ARR, variable, type, length, from, to, 0) /** * Storage of a global string in some savegame versions. @@ -739,7 +733,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the string. * @param to Last savegame version that has the string. */ -#define SLEG_CONDSTR(variable, type, length, from, to) SLEG_GENERAL(SL_STR, variable, type, length, from, to) +#define SLEG_CONDSTR(variable, type, length, from, to) SLEG_GENERAL(SL_STR, variable, type, length, from, to, 0) /** * Storage of a global \c std::string in some savegame versions. @@ -748,7 +742,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the string. * @param to Last savegame version that has the string. */ -#define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to) +#define SLEG_CONDSSTR(variable, type, from, to) SLEG_GENERAL(SL_STDSTR, variable, type, 0, from, to, 0) /** * Storage of a global list in some savegame versions. @@ -757,7 +751,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLEG_CONDLST(variable, type, from, to) SLEG_GENERAL(SL_LST, variable, type, 0, from, to) +#define SLEG_CONDLST(variable, type, from, to) SLEG_GENERAL(SL_LST, variable, type, 0, from, to, 0) /** * Storage of a global variable in every savegame version. @@ -807,10 +801,10 @@ typedef SaveLoad SaveLoadGlobVarList; * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)nullptr} +#define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, 0, nullptr, 0} /** End marker of global variables save or load. */ -#define SLEG_END() {true, SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, nullptr, 0} +#define SLEG_END() {SL_END, 0, 0, SL_MIN_VERSION, SL_MIN_VERSION, 0, nullptr, 0} /** * Checks whether the savegame is below \a major.\a minor. @@ -886,25 +880,21 @@ static inline bool IsNumericType(VarType conv) } /** - * Get the address of the variable. Which one to pick depends on the object - * pointer. If it is nullptr we are dealing with global variables so the address - * is taken. If non-null only the offset is stored in the union and we need - * to add this to the address of the object + * Get the address of the variable. Null-variables don't have an address, + * everything else has a callback function that returns the address based + * on the saveload data and the current object for non-globals. */ static inline void *GetVariableAddress(const void *object, const SaveLoad *sld) { - /* Entry is a global address. */ - if (sld->global) return sld->address; - /* Entry is a null-variable, mostly used to read old savegames etc. */ if (GetVarMemType(sld->conv) == SLE_VAR_NULL) { - assert(sld->address == nullptr); + assert(sld->address_proc == nullptr); return nullptr; } /* Everything else should be a non-null pointer. */ - assert(object != nullptr); - return const_cast((const byte *)object + (ptrdiff_t)sld->address); + assert(sld->address_proc != nullptr); + return sld->address_proc(const_cast(object), sld->extra_data); } int64 ReadValue(const void *ptr, VarType conv); diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index 8f9bee3bfe..1be7ccbc23 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -16,8 +16,8 @@ static const SettingDesc _company_settings[] = { [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_END = SDT_END() [defaults] @@ -32,6 +32,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 34199501f3..f6c7c8612c 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -9,9 +9,9 @@ static const SettingDesc _currency_settings[] = { [post-amble] }; [templates] -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_CHR = SDT_CHR($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_CHR = SDT_CHR($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_END = SDT_END() [defaults] @@ -26,6 +26,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 08253be93c..8e5da277f4 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -37,13 +37,13 @@ static const SettingDesc _gameopt_settings[] = { [post-amble] }; [templates] -SDTG_GENERAL = SDTG_GENERAL($name, $sdt_cmd, $sle_cmd, $type, $flags, $guiflags, $var, $length, $def, $min, $max, $interval, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDTG_GENERAL = SDTG_GENERAL($name, $sdt_cmd, $sle_cmd, $type, $flags, $guiflags, $var, $length, $def, $min, $max, $interval, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_NULL = SDT_NULL($length, $from, $to), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_END = SDT_END() [defaults] @@ -58,6 +58,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 167f8441c2..d46ebe9bb4 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -13,13 +13,13 @@ static const SettingDescGlobVarList _misc_settings[] = { [post-amble] }; [templates] -SDTG_LIST = SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_STR = SDTG_STR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDTG_LIST = SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_STR = SDTG_STR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDTG_END = SDTG_END() [defaults] @@ -34,6 +34,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index 3d372c2452..f1facaaf09 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -61,29 +61,29 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for global variables */ -#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to)} +#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extra)\ + {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat), SLEG_GENERAL(sle_cmd, var, type | flags, length, from, to, extra)} -#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_STR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTG_STR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_SSTR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTG_SSTR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat) +#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat) +#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat, extra) #define SDTG_NULL(length, from, to)\ {{"", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLEG_NULL(length, from, to)} @@ -92,48 +92,48 @@ static size_t ConvertLandscape(const char *value); /* Macros for various objects to go in the configuration file. * This section is for structures where their various members are saved */ -#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat)\ - {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to)} +#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extra)\ + {NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat), SLE_GENERAL(sle_cmd, base, var, type | flags, length, from, to, extra)} -#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra) -#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra) -#define SDT_LIST(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_LIST(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra) -#define SDT_STR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_STR(base, var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, sizeof(((base*)8)->var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra) -#define SDT_CHR(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDT_GENERAL(#var, SDT_STRING, SL_VAR, SLE_CHAR, flags, guiflags, base, var, 1, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_CHR(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_STRING, SL_VAR, SLE_CHAR, flags, guiflags, base, var, 1, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extra) -#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat)\ - SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, load, from, to, cat) +#define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra)\ + SDT_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, load, from, to, cat, extra) -#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat)\ - SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, nullptr, from, to, cat) +#define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra)\ + SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, nullptr, from, to, cat, extra) #define SDT_NULL(length, from, to)\ {{"", nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLE_CONDNULL(length, from, to)} -#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTC_LIST(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTC_LIST(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTC_STR(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat) +#define SDTC_STR(var, type, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, sizeof(_settings_client.var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extra) -#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat)\ - SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat) +#define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, cat, extra)\ + SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extra) #define SDT_END() {{nullptr, nullptr, SDT_NUMX, SGF_NONE, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLE_END()} diff --git a/src/table/settings.ini b/src/table/settings.ini index eebb23f7e9..2e085058f2 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -62,18 +62,18 @@ const SettingDesc _settings[] = { [post-amble] }; [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTC_STR = SDTC_STR( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat), -SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_STR = SDTC_STR( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_VAR = SDTC_VAR( $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra), +SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_NULL = SDT_NULL($length, $from, $to), SDT_END = SDT_END() @@ -89,6 +89,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 @@ -644,6 +645,7 @@ interval = 2 str = STR_CONFIG_SETTING_LINKGRAPH_INTERVAL strval = STR_JUST_COMMA strhelp = STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT +extra = offsetof(LinkGraphSettings, recalc_interval) [SDT_VAR] base = GameSettings @@ -657,6 +659,8 @@ interval = 1 str = STR_CONFIG_SETTING_LINKGRAPH_TIME strval = STR_JUST_COMMA strhelp = STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT +extra = offsetof(LinkGraphSettings, recalc_time) + [SDT_VAR] base = GameSettings @@ -671,6 +675,8 @@ interval = 1 str = STR_CONFIG_SETTING_DISTRIBUTION_PAX strval = STR_CONFIG_SETTING_DISTRIBUTION_MANUAL strhelp = STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT +extra = offsetof(LinkGraphSettings, distribution_pax) + [SDT_VAR] base = GameSettings @@ -685,6 +691,8 @@ interval = 1 str = STR_CONFIG_SETTING_DISTRIBUTION_MAIL strval = STR_CONFIG_SETTING_DISTRIBUTION_MANUAL strhelp = STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT +extra = offsetof(LinkGraphSettings, distribution_mail) + [SDT_VAR] base = GameSettings @@ -699,6 +707,8 @@ interval = 1 str = STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED strval = STR_CONFIG_SETTING_DISTRIBUTION_MANUAL strhelp = STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT +extra = offsetof(LinkGraphSettings, distribution_armoured) + [SDT_VAR] base = GameSettings @@ -713,6 +723,8 @@ interval = 1 str = STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT strval = STR_CONFIG_SETTING_DISTRIBUTION_MANUAL strhelp = STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT +extra = offsetof(LinkGraphSettings, distribution_default) + [SDT_VAR] base = GameSettings @@ -726,6 +738,8 @@ interval = 1 str = STR_CONFIG_SETTING_LINKGRAPH_ACCURACY strval = STR_JUST_COMMA strhelp = STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT +extra = offsetof(LinkGraphSettings, accuracy) + [SDT_VAR] base = GameSettings @@ -739,6 +753,8 @@ interval = 5 str = STR_CONFIG_SETTING_DEMAND_DISTANCE strval = STR_CONFIG_SETTING_PERCENTAGE strhelp = STR_CONFIG_SETTING_DEMAND_DISTANCE_HELPTEXT +extra = offsetof(LinkGraphSettings, demand_distance) + [SDT_VAR] base = GameSettings @@ -752,6 +768,8 @@ interval = 5 str = STR_CONFIG_SETTING_DEMAND_SIZE strval = STR_CONFIG_SETTING_PERCENTAGE strhelp = STR_CONFIG_SETTING_DEMAND_SIZE_HELPTEXT +extra = offsetof(LinkGraphSettings, demand_size) + [SDT_VAR] base = GameSettings @@ -765,6 +783,8 @@ interval = 5 str = STR_CONFIG_SETTING_SHORT_PATH_SATURATION strval = STR_CONFIG_SETTING_PERCENTAGE strhelp = STR_CONFIG_SETTING_SHORT_PATH_SATURATION_HELPTEXT +extra = offsetof(LinkGraphSettings, short_path_saturation) + ; Vehicles diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini index c7915e32bd..d1cc72dd77 100644 --- a/src/table/win32_settings.ini +++ b/src/table/win32_settings.ini @@ -15,8 +15,8 @@ static const SettingDescGlobVarList _win32_settings[] = { }; #endif /* _WIN32 */ [templates] -SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDTG_END = SDTG_END() [defaults] @@ -31,6 +31,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 diff --git a/src/table/window_settings.ini b/src/table/window_settings.ini index fc0c57b39e..524e02fdfa 100644 --- a/src/table/window_settings.ini +++ b/src/table/window_settings.ini @@ -10,8 +10,8 @@ static const SettingDesc _window_settings[] = { [post-amble] }; [templates] -SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat), -SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat), +SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDT_END = SDT_END() [defaults] @@ -27,6 +27,7 @@ load = nullptr from = SL_MIN_VERSION to = SL_MAX_VERSION cat = SC_ADVANCED +extra = 0 From 84636fc2af4dfc77b43479909273ebadb4f9b7cb Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 14 Dec 2020 00:22:04 +0100 Subject: [PATCH 060/275] Codechange: Remove all remaining uses of cpp_offset. --- src/newgrf_debug_gui.cpp | 24 +++++++++++++----------- src/stdafx.h | 7 +------ src/table/newgrf_debug_data.h | 4 ++-- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index da3ddff0aa..f82f4d93b3 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -79,12 +79,14 @@ enum NIType { NIT_CARGO, ///< The property is a cargo }; +typedef const void *NIOffsetProc(const void *b); + /** Representation of the data from a NewGRF property. */ struct NIProperty { - const char *name; ///< A (human readable) name for the property - ptrdiff_t offset; ///< Offset of the variable in the class - byte read_size; ///< Number of bytes (i.e. byte, word, dword etc) - byte prop; ///< The number of the property + const char *name; ///< A (human readable) name for the property + NIOffsetProc *offset_proc; ///< Callback proc to get the actual variable address in memory + byte read_size; ///< Number of bytes (i.e. byte, word, dword etc) + byte prop; ///< The number of the property byte type; }; @@ -94,11 +96,11 @@ struct NIProperty { * information on when they actually apply. */ struct NICallback { - const char *name; ///< The human readable name of the callback - ptrdiff_t offset; ///< Offset of the variable in the class - byte read_size; ///< The number of bytes (i.e. byte, word, dword etc) to read - byte cb_bit; ///< The bit that needs to be set for this callback to be enabled - uint16 cb_id; ///< The number of the callback + const char *name; ///< The human readable name of the callback + NIOffsetProc *offset_proc; ///< Callback proc to get the actual variable address in memory + byte read_size; ///< The number of bytes (i.e. byte, word, dword etc) to read + byte cb_bit; ///< The bit that needs to be set for this callback to be enabled + uint16 cb_id; ///< The number of the callback }; /** Mask to show no bit needs to be enabled for the callback. */ static const int CBM_NO_BIT = UINT8_MAX; @@ -491,7 +493,7 @@ struct NewGRFInspectWindow : Window { if (nif->properties != nullptr) { this->DrawString(r, i++, "Properties:"); for (const NIProperty *nip = nif->properties; nip->name != nullptr; nip++) { - const void *ptr = (const byte *)base + nip->offset; + const void *ptr = nip->offset_proc(base); uint value; switch (nip->read_size) { case 1: value = *(const uint8 *)ptr; break; @@ -525,7 +527,7 @@ struct NewGRFInspectWindow : Window { this->DrawString(r, i++, "Callbacks:"); for (const NICallback *nic = nif->callbacks; nic->name != nullptr; nic++) { if (nic->cb_bit != CBM_NO_BIT) { - const void *ptr = (const byte *)base_spec + nic->offset; + const void *ptr = nic->offset_proc(base_spec); uint value; switch (nic->read_size) { case 1: value = *(const uint8 *)ptr; break; diff --git a/src/stdafx.h b/src/stdafx.h index e5cb9205ff..7ee3ce2041 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -392,18 +392,13 @@ static_assert(SIZE_MAX >= UINT32_MAX); */ #define lastof(x) (&x[lengthof(x) - 1]) -#define cpp_offsetof(s, m) (((size_t)&reinterpret_cast((((s*)(char*)8)->m))) - 8) -#if !defined(offsetof) -# define offsetof(s, m) cpp_offsetof(s, m) -#endif /* offsetof */ - /** * Gets the size of a variable within a class. * @param base The class the variable is in. * @param variable The variable to get the size of. * @return the size of the variable */ -#define cpp_sizeof(base, variable) (sizeof(((base*)8)->variable)) +#define cpp_sizeof(base, variable) (sizeof(std::declval().variable)) /** * Gets the length of an array variable within a class. diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index e31d093385..e35b2eecbf 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -12,11 +12,11 @@ #include "../newgrf_roadtype.h" /* Helper for filling property tables */ -#define NIP(prop, base, variable, type, name) { name, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), prop, type } +#define NIP(prop, base, variable, type, name) { name, [] (const void *b) -> const void * { return std::addressof(static_cast(b)->variable); }, cpp_sizeof(base, variable), prop, type } #define NIP_END() { nullptr, 0, 0, 0, 0 } /* Helper for filling callback tables */ -#define NIC(cb_id, base, variable, bit) { #cb_id, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), bit, cb_id } +#define NIC(cb_id, base, variable, bit) { #cb_id, [] (const void *b) -> const void * { return std::addressof(static_cast(b)->variable); }, cpp_sizeof(base, variable), bit, cb_id } #define NIC_END() { nullptr, 0, 0, 0, 0 } /* Helper for filling variable tables */ From 2b0200d4297a67916cf3b955adc474e88e327cf0 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 4 Jan 2021 15:20:34 +0100 Subject: [PATCH 061/275] Codechange: OS-specific data for font search is not used outside of searching. --- src/fontcache.h | 2 +- src/fontdetection.cpp | 4 +--- src/strings.cpp | 4 ---- src/textfile_gui.cpp | 1 - 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/fontcache.h b/src/fontcache.h index 716b3e7d77..4c44876da1 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -217,7 +217,7 @@ struct FreeTypeSubSetting { uint size; ///< The (requested) size of the font. bool aa; ///< Whether to do anti aliasing or not. - const void *os_handle = nullptr; ///< Optional native OS font info. + const void *os_handle = nullptr; ///< Optional native OS font info. Only valid during font search. }; /** Settings for the freetype fonts. */ diff --git a/src/fontdetection.cpp b/src/fontdetection.cpp index 570e1aa068..dfb27a35de 100644 --- a/src/fontdetection.cpp +++ b/src/fontdetection.cpp @@ -344,9 +344,7 @@ static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXT const char *english_name = font_name; #endif /* WITH_FREETYPE */ - PLOGFONT os_data = MallocT(1); - *os_data = logfont->elfLogFont; - info->callback->SetFontNames(info->settings, font_name, os_data); + info->callback->SetFontNames(info->settings, font_name, &logfont->elfLogFont); if (info->callback->FindMissingGlyphs()) return 1; DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name); return 0; // stop enumerating diff --git a/src/strings.cpp b/src/strings.cpp index fa039fdb97..1d6fca8b6f 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2078,7 +2078,6 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher { strecpy(settings->medium.font, font_name, lastof(settings->medium.font)); strecpy(settings->large.font, font_name, lastof(settings->large.font)); - free(settings->medium.os_handle); // Only free one, they are all the same pointer. settings->small.os_handle = os_data; settings->medium.os_handle = os_data; settings->large.os_handle = os_data; @@ -2116,9 +2115,6 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) bad_font = !SetFallbackFont(&_freetype, _langpack.langpack->isocode, _langpack.langpack->winlangid, searcher); - free(_freetype.mono.os_handle); - free(_freetype.medium.os_handle); - memcpy(&_freetype, &backup, sizeof(backup)); if (!bad_font) { diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index b83e38187f..fd544f5fc4 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -196,7 +196,6 @@ void TextfileWindow::SetupScrollbars() { #if defined(WITH_FREETYPE) || defined(_WIN32) strecpy(settings->mono.font, font_name, lastof(settings->mono.font)); - free(settings->mono.os_handle); settings->mono.os_handle = os_data; #endif } From 5ad16409847a17534389054a1b7f5fb83703fb4d Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 6 Jan 2021 22:56:44 +0100 Subject: [PATCH 062/275] Codechange: Make OS font handle of the FontCache read-only. --- src/fontcache.cpp | 2 +- src/fontcache.h | 2 +- src/os/windows/string_uniscribe.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 0b2764aabf..9cdc0b9755 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -756,7 +756,7 @@ public: virtual GlyphID MapCharToGlyph(WChar key); virtual const char *GetFontName() { return WIDE_TO_MB(this->logfont.lfFaceName); } virtual bool IsBuiltInFont() { return false; } - virtual void *GetOSHandle() { return &this->logfont; } + virtual const void *GetOSHandle() { return &this->logfont; } }; diff --git a/src/fontcache.h b/src/fontcache.h index 4c44876da1..fac08a3537 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -127,7 +127,7 @@ public: * Get the native OS font handle, if there is one. * @return Opaque OS font handle. */ - virtual void *GetOSHandle() + virtual const void *GetOSHandle() { return nullptr; } diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp index ad37548662..6c0a9366e9 100644 --- a/src/os/windows/string_uniscribe.cpp +++ b/src/os/windows/string_uniscribe.cpp @@ -144,7 +144,7 @@ void UniscribeResetScriptCache(FontSize size) /** Load the matching native Windows font. */ static HFONT HFontFromFont(Font *font) { - if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect((PLOGFONT)font->fc->GetOSHandle()); + if (font->fc->GetOSHandle() != nullptr) return CreateFontIndirect((const PLOGFONT)font->fc->GetOSHandle()); LOGFONT logfont; ZeroMemory(&logfont, sizeof(LOGFONT)); From c6af8f16f63d878371d1a823c12fbf21423505b5 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 17:34:22 +0100 Subject: [PATCH 063/275] Codechange: [Win32] Move Win32-specific font code to a seperate file. --- src/CMakeLists.txt | 1 + src/fontcache.cpp | 393 +------------------- src/fontcache.h | 7 +- src/fontcache_internal.h | 76 ++++ src/fontdetection.cpp | 361 +----------------- src/fontdetection.h | 5 +- src/os/windows/CMakeLists.txt | 2 + src/os/windows/font_win32.cpp | 675 ++++++++++++++++++++++++++++++++++ src/os/windows/font_win32.h | 42 +++ 9 files changed, 818 insertions(+), 744 deletions(-) create mode 100644 src/fontcache_internal.h create mode 100644 src/os/windows/font_win32.cpp create mode 100644 src/os/windows/font_win32.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbe66b7645..d451ae8da6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -155,6 +155,7 @@ add_files( fios_gui.cpp fontcache.cpp fontcache.h + fontcache_internal.h fontdetection.cpp fontdetection.h framerate_gui.cpp diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 9cdc0b9755..6cc25154f8 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "fontcache.h" +#include "fontcache_internal.h" #include "fontdetection.h" #include "blitter/factory.hpp" #include "core/math_func.hpp" @@ -31,6 +32,8 @@ static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter. static const int _default_font_height[FS_END] = {10, 6, 18, 10}; static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8}; +FreeTypeSettings _freetype; + /** * Create a new font cache. * @param fs The size of the font. @@ -52,6 +55,11 @@ FontCache::~FontCache() Layouter::ResetFontCache(this->fs); } +int FontCache::GetDefaultFontHeight(FontSize fs) +{ + return _default_font_height[fs]; +} + /** * Get height of a character for a given font size. @@ -199,65 +207,6 @@ bool SpriteFontCache::GetDrawGlyphShadow() #if defined(WITH_FREETYPE) || defined(_WIN32) -FreeTypeSettings _freetype; - -static const int MAX_FONT_SIZE = 72; ///< Maximum font size. - -static const byte FACE_COLOUR = 1; -static const byte SHADOW_COLOUR = 2; - -/** Font cache for fonts that are based on a TrueType font. */ -class TrueTypeFontCache : public FontCache { -protected: - int req_size; ///< Requested font size. - int used_size; ///< Used font size. - - typedef SmallMap > FontTable; ///< Table with font table cache - FontTable font_tables; ///< Cached font tables. - - /** Container for information about a glyph. */ - struct GlyphEntry { - Sprite *sprite; ///< The loaded sprite. - byte width; ///< The width of the glyph. - bool duplicate; ///< Whether this glyph entry is a duplicate, i.e. may this be freed? - }; - - /** - * The glyph cache. This is structured to reduce memory consumption. - * 1) There is a 'segment' table for each font size. - * 2) Each segment table is a discrete block of characters. - * 3) Each block contains 256 (aligned) characters sequential characters. - * - * The cache is accessed in the following way: - * For character 0x0041 ('A'): glyph_to_sprite[0x00][0x41] - * For character 0x20AC (Euro): glyph_to_sprite[0x20][0xAC] - * - * Currently only 256 segments are allocated, "limiting" us to 65536 characters. - * This can be simply changed in the two functions Get & SetGlyphPtr. - */ - GlyphEntry **glyph_to_sprite; - - GlyphEntry *GetGlyphPtr(GlyphID key); - void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false); - - virtual const void *InternalGetFontTable(uint32 tag, size_t &length) = 0; - virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0; - -public: - TrueTypeFontCache(FontSize fs, int pixels); - virtual ~TrueTypeFontCache(); - virtual int GetFontSize() const { return this->used_size; } - virtual SpriteID GetUnicodeGlyph(WChar key) { return this->parent->GetUnicodeGlyph(key); } - virtual void SetUnicodeGlyph(WChar key, SpriteID sprite) { this->parent->SetUnicodeGlyph(key, sprite); } - virtual void InitializeUnicodeGlyphMap() { this->parent->InitializeUnicodeGlyphMap(); } - virtual const Sprite *GetGlyph(GlyphID key); - virtual const void *GetFontTable(uint32 tag, size_t &length); - virtual void ClearFontCache(); - virtual uint GetGlyphWidth(GlyphID key); - virtual bool GetDrawGlyphShadow(); - virtual bool IsBuiltInFont() { return false; } -}; - /** * Create a new TrueTypeFontCache. * @param fs The font size that is going to be cached. @@ -329,7 +278,7 @@ void TrueTypeFontCache::SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool d this->glyph_to_sprite[GB(key, 8, 8)][GB(key, 0, 8)].duplicate = duplicate; } -static void *AllocateFont(size_t size) +void *AllocateFont(size_t size) { return MallocT(size); } @@ -731,330 +680,7 @@ const void *FreeTypeFontCache::InternalGetFontTable(uint32 tag, size_t &length) #elif defined(_WIN32) -#include "os/windows/win32.h" -#ifndef ANTIALIASED_QUALITY -#define ANTIALIASED_QUALITY 4 -#endif -/** Font cache for fonts that are based on a Win32 font. */ -class Win32FontCache : public TrueTypeFontCache { -private: - LOGFONT logfont; ///< Logical font information for selecting the font face. - HFONT font = nullptr; ///< The font face associated with this font. - HDC dc = nullptr; ///< Cached GDI device context. - HGDIOBJ old_font; ///< Old font selected into the GDI context. - SIZE glyph_size; ///< Maximum size of regular glyphs. - - void SetFontSize(FontSize fs, int pixels); - virtual const void *InternalGetFontTable(uint32 tag, size_t &length); - virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa); - -public: - Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels); - ~Win32FontCache(); - virtual void ClearFontCache(); - virtual GlyphID MapCharToGlyph(WChar key); - virtual const char *GetFontName() { return WIDE_TO_MB(this->logfont.lfFaceName); } - virtual bool IsBuiltInFont() { return false; } - virtual const void *GetOSHandle() { return &this->logfont; } -}; - - -/** - * Create a new Win32FontCache. - * @param fs The font size that is going to be cached. - * @param logfont The font that has to be loaded. - * @param pixels The number of pixels this font should be high. - */ -Win32FontCache::Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels) : TrueTypeFontCache(fs, pixels), logfont(logfont) -{ - this->dc = CreateCompatibleDC(nullptr); - this->SetFontSize(fs, pixels); -} - -Win32FontCache::~Win32FontCache() -{ - this->ClearFontCache(); - DeleteDC(this->dc); - DeleteObject(this->font); -} - -void Win32FontCache::SetFontSize(FontSize fs, int pixels) -{ - if (pixels == 0) { - /* Try to determine a good height based on the minimal height recommended by the font. */ - int scaled_height = ScaleFontTrad(_default_font_height[this->fs]); - pixels = scaled_height; - - HFONT temp = CreateFontIndirect(&this->logfont); - if (temp != nullptr) { - HGDIOBJ old = SelectObject(this->dc, temp); - - UINT size = GetOutlineTextMetrics(this->dc, 0, nullptr); - LPOUTLINETEXTMETRIC otm = (LPOUTLINETEXTMETRIC)AllocaM(BYTE, size); - GetOutlineTextMetrics(this->dc, size, otm); - - /* Font height is minimum height plus the difference between the default - * height for this font size and the small size. */ - int diff = scaled_height - ScaleFontTrad(_default_font_height[FS_SMALL]); - pixels = Clamp(std::min(otm->otmusMinimumPPEM, 20u) + diff, scaled_height, MAX_FONT_SIZE); - - SelectObject(dc, old); - DeleteObject(temp); - } - } else { - pixels = ScaleFontTrad(pixels); - } - this->used_size = pixels; - - /* Create GDI font handle. */ - this->logfont.lfHeight = -pixels; - this->logfont.lfWidth = 0; - this->logfont.lfOutPrecision = ANTIALIASED_QUALITY; - - if (this->font != nullptr) { - SelectObject(dc, this->old_font); - DeleteObject(this->font); - } - this->font = CreateFontIndirect(&this->logfont); - this->old_font = SelectObject(this->dc, this->font); - - /* Query the font metrics we needed. */ - UINT otmSize = GetOutlineTextMetrics(this->dc, 0, nullptr); - POUTLINETEXTMETRIC otm = (POUTLINETEXTMETRIC)AllocaM(BYTE, otmSize); - GetOutlineTextMetrics(this->dc, otmSize, otm); - - this->units_per_em = otm->otmEMSquare; - this->ascender = otm->otmTextMetrics.tmAscent; - this->descender = otm->otmTextMetrics.tmDescent; - this->height = this->ascender + this->descender; - this->glyph_size.cx = otm->otmTextMetrics.tmMaxCharWidth; - this->glyph_size.cy = otm->otmTextMetrics.tmHeight; - - DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPTSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)), pixels); -} - -/** - * Reset cached glyphs. - */ -void Win32FontCache::ClearFontCache() -{ - /* GUI scaling might have changed, determine font size anew if it was automatically selected. */ - if (this->font != nullptr) this->SetFontSize(this->fs, this->req_size); - - this->TrueTypeFontCache::ClearFontCache(); -} - -/* virtual */ const Sprite *Win32FontCache::InternalGetGlyph(GlyphID key, bool aa) -{ - GLYPHMETRICS gm; - MAT2 mat = { {0, 1}, {0, 0}, {0, 0}, {0, 1} }; - - /* Make a guess for the needed memory size. */ - DWORD size = this->glyph_size.cy * Align(aa ? this->glyph_size.cx : std::max(this->glyph_size.cx / 8l, 1l), 4); // Bitmap data is DWORD-aligned rows. - byte *bmp = AllocaM(byte, size); - size = GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, size, bmp, &mat); - - if (size == GDI_ERROR) { - /* No dice with the guess. First query size of needed glyph memory, then allocate the - * memory and query again. This dance is necessary as some glyphs will only render with - * the exact matching size; e.g. the space glyph has no pixels and must be requested - * with size == 0, anything else fails. Unfortunately, a failed call doesn't return any - * info about the size and thus the triple GetGlyphOutline()-call. */ - size = GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, 0, nullptr, &mat); - if (size == GDI_ERROR) usererror("Unable to render font glyph"); - bmp = AllocaM(byte, size); - GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, size, bmp, &mat); - } - - /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel. */ - uint width = std::max(1U, (uint)gm.gmBlackBoxX + (this->fs == FS_NORMAL)); - uint height = std::max(1U, (uint)gm.gmBlackBoxY + (this->fs == FS_NORMAL)); - - /* Limit glyph size to prevent overflows later on. */ - if (width > 256 || height > 256) usererror("Font glyph is too large"); - - /* GDI has rendered the glyph, now we allocate a sprite and copy the image into it. */ - SpriteLoader::Sprite sprite; - sprite.AllocateData(ZOOM_LVL_NORMAL, width * height); - sprite.type = ST_FONT; - sprite.width = width; - sprite.height = height; - sprite.x_offs = gm.gmptGlyphOrigin.x; - sprite.y_offs = this->ascender - gm.gmptGlyphOrigin.y; - - if (size > 0) { - /* All pixel data returned by GDI is in the form of DWORD-aligned rows. - * For a non anti-aliased glyph, the returned bitmap has one bit per pixel. - * For anti-aliased rendering, GDI uses the strange value range of 0 to 64, - * inclusively. To map this to 0 to 255, we shift left by two and then - * subtract one. */ - uint pitch = Align(aa ? gm.gmBlackBoxX : std::max(gm.gmBlackBoxX / 8u, 1u), 4); - - /* Draw shadow for medium size. */ - if (this->fs == FS_NORMAL && !aa) { - for (uint y = 0; y < gm.gmBlackBoxY; y++) { - for (uint x = 0; x < gm.gmBlackBoxX; x++) { - if (aa ? (bmp[x + y * pitch] > 0) : HasBit(bmp[(x / 8) + y * pitch], 7 - (x % 8))) { - sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR; - sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? (bmp[x + y * pitch] << 2) - 1 : 0xFF; - } - } - } - } - - for (uint y = 0; y < gm.gmBlackBoxY; y++) { - for (uint x = 0; x < gm.gmBlackBoxX; x++) { - if (aa ? (bmp[x + y * pitch] > 0) : HasBit(bmp[(x / 8) + y * pitch], 7 - (x % 8))) { - sprite.data[x + y * sprite.width].m = FACE_COLOUR; - sprite.data[x + y * sprite.width].a = aa ? (bmp[x + y * pitch] << 2) - 1 : 0xFF; - } - } - } - } - - GlyphEntry new_glyph; - new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(&sprite, AllocateFont); - new_glyph.width = gm.gmCellIncX; - - this->SetGlyphPtr(key, &new_glyph); - - return new_glyph.sprite; -} - -/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(WChar key) -{ - assert(IsPrintable(key)); - - if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { - return this->parent->MapCharToGlyph(key); - } - - /* Convert characters outside of the BMP into surrogate pairs. */ - WCHAR chars[2]; - if (key >= 0x010000U) { - chars[0] = (WCHAR)(((key - 0x010000U) >> 10) + 0xD800); - chars[1] = (WCHAR)(((key - 0x010000U) & 0x3FF) + 0xDC00); - } else { - chars[0] = (WCHAR)(key & 0xFFFF); - } - - WORD glyphs[2] = {0, 0}; - GetGlyphIndicesW(this->dc, chars, key >= 0x010000U ? 2 : 1, glyphs, GGI_MARK_NONEXISTING_GLYPHS); - - return glyphs[0] != 0xFFFF ? glyphs[0] : 0; -} - -/* virtual */ const void *Win32FontCache::InternalGetFontTable(uint32 tag, size_t &length) -{ - DWORD len = GetFontData(this->dc, tag, 0, nullptr, 0); - - void *result = nullptr; - if (len != GDI_ERROR && len > 0) { - result = MallocT(len); - GetFontData(this->dc, tag, 0, result, len); - } - - length = len; - return result; -} - -/** - * Loads the GDI font. - * If a GDI font description is present, e.g. from the automatic font - * fallback search, use it. Otherwise, try to resolve it by font name. - * @param fs The font size to load. - */ -static void LoadWin32Font(FontSize fs) -{ - static const char *SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; - - FreeTypeSubSetting *settings = nullptr; - switch (fs) { - default: NOT_REACHED(); - case FS_SMALL: settings = &_freetype.small; break; - case FS_NORMAL: settings = &_freetype.medium; break; - case FS_LARGE: settings = &_freetype.large; break; - case FS_MONO: settings = &_freetype.mono; break; - } - - if (StrEmpty(settings->font)) return; - - LOGFONT logfont; - MemSetT(&logfont, 0); - logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH; - logfont.lfCharSet = DEFAULT_CHARSET; - logfont.lfOutPrecision = OUT_OUTLINE_PRECIS; - logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - - if (settings->os_handle != nullptr) { - logfont = *(const LOGFONT *)settings->os_handle; - } else if (strchr(settings->font, '.') != nullptr) { - /* Might be a font file name, try load it. */ - - TCHAR fontPath[MAX_PATH] = {}; - - /* See if this is an absolute path. */ - if (FileExists(settings->font)) { - convert_to_fs(settings->font, fontPath, lengthof(fontPath), false); - } else { - /* Scan the search-paths to see if it can be found. */ - std::string full_font = FioFindFullPath(BASE_DIR, settings->font); - if (!full_font.empty()) { - convert_to_fs(full_font.c_str(), fontPath, lengthof(fontPath), false); - } - } - - if (fontPath[0] != 0) { - if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { - /* Try a nice little undocumented function first for getting the internal font name. - * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ - typedef BOOL(WINAPI * PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); -#ifdef UNICODE - static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(_T("Gdi32")), "GetFontResourceInfoW"); -#else - static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(_T("Gdi32")), "GetFontResourceInfoA"); -#endif - - if (GetFontResourceInfo != nullptr) { - /* Try to query an array of LOGFONTs that describe the file. */ - DWORD len = 0; - if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) { - LOGFONT *buf = (LOGFONT *)AllocaM(byte, len); - if (GetFontResourceInfo(fontPath, &len, buf, 2)) { - logfont = *buf; // Just use first entry. - } - } - } - - /* No dice yet. Use the file name as the font face name, hoping it matches. */ - if (logfont.lfFaceName[0] == 0) { - TCHAR fname[_MAX_FNAME]; - _tsplitpath(fontPath, nullptr, nullptr, fname, nullptr); - - _tcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE); - logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr || strcasestr(settings->font, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. - } - } else { - ShowInfoF("Unable to load file '%s' for %s font, using default windows font selection instead", settings->font, SIZE_TO_NAME[fs]); - } - } - } - - if (logfont.lfFaceName[0] == 0) { - logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. - convert_to_fs(settings->font, logfont.lfFaceName, lengthof(logfont.lfFaceName), false); - } - - HFONT font = CreateFontIndirect(&logfont); - if (font == nullptr) { - ShowInfoF("Unable to use '%s' for %s font, Win32 reported error 0x%lX, using sprite font instead", settings->font, SIZE_TO_NAME[fs], GetLastError()); - return; - } - DeleteObject(font); - - new Win32FontCache(fs, logfont, settings->size); -} #endif /* WITH_FREETYPE */ @@ -1075,6 +701,7 @@ void InitFreeType(bool monospace) #ifdef WITH_FREETYPE LoadFreeTypeFont(fs); #elif defined(_WIN32) + extern void LoadWin32Font(FontSize fs); LoadWin32Font(fs); #endif } diff --git a/src/fontcache.h b/src/fontcache.h index fac08a3537..4b26af8713 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -28,6 +28,9 @@ protected: int ascender; ///< The ascender value of the font. int descender; ///< The descender value of the font. int units_per_em; ///< The units per EM value of the font. + + static int GetDefaultFontHeight(FontSize fs); + public: FontCache(FontSize fs); virtual ~FontCache(); @@ -209,8 +212,6 @@ static inline bool GetDrawGlyphShadow(FontSize size) return FontCache::Get(size)->GetDrawGlyphShadow(); } -#if defined(WITH_FREETYPE) || defined(_WIN32) - /** Settings for a single freetype font. */ struct FreeTypeSubSetting { char font[MAX_PATH]; ///< The name of the font, or path to the font. @@ -230,8 +231,6 @@ struct FreeTypeSettings { extern FreeTypeSettings _freetype; -#endif /* defined(WITH_FREETYPE) || defined(_WIN32) */ - void InitFreeType(bool monospace); void UninitFreeType(); diff --git a/src/fontcache_internal.h b/src/fontcache_internal.h new file mode 100644 index 0000000000..09e676234f --- /dev/null +++ b/src/fontcache_internal.h @@ -0,0 +1,76 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file fontcache_internal.h Support types and functions for platform-specific font support. */ + +#ifndef FONTCACHE_INTERNAL_H +#define FONTCACHE_INTERNAL_H + +#include "core/smallmap_type.hpp" +#include "fontcache.h" + + +static const int MAX_FONT_SIZE = 72; ///< Maximum font size. + +static const byte FACE_COLOUR = 1; +static const byte SHADOW_COLOUR = 2; + +/** Font cache for fonts that are based on a TrueType font. */ +class TrueTypeFontCache : public FontCache { +protected: + int req_size; ///< Requested font size. + int used_size; ///< Used font size. + + typedef SmallMap > FontTable; ///< Table with font table cache + FontTable font_tables; ///< Cached font tables. + + /** Container for information about a glyph. */ + struct GlyphEntry { + Sprite *sprite; ///< The loaded sprite. + byte width; ///< The width of the glyph. + bool duplicate; ///< Whether this glyph entry is a duplicate, i.e. may this be freed? + }; + + /** + * The glyph cache. This is structured to reduce memory consumption. + * 1) There is a 'segment' table for each font size. + * 2) Each segment table is a discrete block of characters. + * 3) Each block contains 256 (aligned) characters sequential characters. + * + * The cache is accessed in the following way: + * For character 0x0041 ('A'): glyph_to_sprite[0x00][0x41] + * For character 0x20AC (Euro): glyph_to_sprite[0x20][0xAC] + * + * Currently only 256 segments are allocated, "limiting" us to 65536 characters. + * This can be simply changed in the two functions Get & SetGlyphPtr. + */ + GlyphEntry **glyph_to_sprite; + + GlyphEntry *GetGlyphPtr(GlyphID key); + void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false); + + virtual const void *InternalGetFontTable(uint32 tag, size_t &length) = 0; + virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0; + +public: + TrueTypeFontCache(FontSize fs, int pixels); + virtual ~TrueTypeFontCache(); + int GetFontSize() const override { return this->used_size; } + SpriteID GetUnicodeGlyph(WChar key) override { return this->parent->GetUnicodeGlyph(key); } + void SetUnicodeGlyph(WChar key, SpriteID sprite) override { this->parent->SetUnicodeGlyph(key, sprite); } + void InitializeUnicodeGlyphMap() override { this->parent->InitializeUnicodeGlyphMap(); } + const Sprite *GetGlyph(GlyphID key) override; + const void *GetFontTable(uint32 tag, size_t &length) override; + void ClearFontCache() override; + uint GetGlyphWidth(GlyphID key) override; + bool GetDrawGlyphShadow() override; + bool IsBuiltInFont() override { return false; } +}; + +void *AllocateFont(size_t size); + +#endif /* FONTCACHE_INTERNAL_H */ diff --git a/src/fontdetection.cpp b/src/fontdetection.cpp index dfb27a35de..ca9f620b9b 100644 --- a/src/fontdetection.cpp +++ b/src/fontdetection.cpp @@ -24,357 +24,7 @@ extern FT_Library _library; * If no appropriate font is found, the function returns an error */ -/* ======================================================================================== - * Windows support - * ======================================================================================== */ - -#ifdef _WIN32 -#include "core/alloc_func.hpp" -#include "core/math_func.hpp" -#include -#include /* SHGetFolderPath */ -#include "os/windows/win32.h" - -#include "safeguards.h" - -#ifdef WITH_FREETYPE -/** - * Get the short DOS 8.3 format for paths. - * FreeType doesn't support Unicode filenames and Windows' fopen (as used - * by FreeType) doesn't support UTF-8 filenames. So we have to convert the - * filename into something that isn't UTF-8 but represents the Unicode file - * name. This is the short DOS 8.3 format. This does not contain any - * characters that fopen doesn't support. - * @param long_path the path in system encoding. - * @return the short path in ANSI (ASCII). - */ -const char *GetShortPath(const TCHAR *long_path) -{ - static char short_path[MAX_PATH]; -#ifdef UNICODE - WCHAR short_path_w[MAX_PATH]; - GetShortPathName(long_path, short_path_w, lengthof(short_path_w)); - WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, lengthof(short_path), nullptr, nullptr); -#else - /* Technically not needed, but do it for consistency. */ - GetShortPathName(long_path, short_path, lengthof(short_path)); -#endif - return short_path; -} - -/* Get the font file to be loaded into Freetype by looping the registry - * location where windows lists all installed fonts. Not very nice, will - * surely break if the registry path changes, but it works. Much better - * solution would be to use CreateFont, and extract the font data from it - * by GetFontData. The problem with this is that the font file needs to be - * kept in memory then until the font is no longer needed. This could mean - * an additional memory usage of 30MB (just for fonts!) when using an eastern - * font for all font sizes */ -#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" -#define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts" -FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) -{ - FT_Error err = FT_Err_Cannot_Open_Resource; - HKEY hKey; - LONG ret; - TCHAR vbuffer[MAX_PATH], dbuffer[256]; - TCHAR *pathbuf; - const char *font_path; - uint index; - size_t path_len; - - /* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the - * "Windows NT" key, on Windows 9x in the Windows key. To save us having - * to retrieve the windows version, we'll just query both */ - ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey); - if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey); - - if (ret != ERROR_SUCCESS) { - DEBUG(freetype, 0, "Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts"); - return err; - } - - /* Convert font name to file system encoding. */ - TCHAR *font_namep = _tcsdup(OTTD2FS(font_name)); - - for (index = 0;; index++) { - TCHAR *s; - DWORD vbuflen = lengthof(vbuffer); - DWORD dbuflen = lengthof(dbuffer); - - ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, nullptr, nullptr, (byte*)dbuffer, &dbuflen); - if (ret != ERROR_SUCCESS) goto registry_no_font_found; - - /* The font names in the registry are of the following 3 forms: - * - ADMUI3.fon - * - Book Antiqua Bold (TrueType) - * - Batang & BatangChe & Gungsuh & GungsuhChe (TrueType) - * We will strip the font-type '()' if any and work with the font name - * itself, which must match exactly; if... - * TTC files, font files which contain more than one font are separated - * by '&'. Our best bet will be to do substr match for the fontname - * and then let FreeType figure out which index to load */ - s = _tcschr(vbuffer, _T('(')); - if (s != nullptr) s[-1] = '\0'; - - if (_tcschr(vbuffer, _T('&')) == nullptr) { - if (_tcsicmp(vbuffer, font_namep) == 0) break; - } else { - if (_tcsstr(vbuffer, font_namep) != nullptr) break; - } - } - - if (!SUCCEEDED(OTTDSHGetFolderPath(nullptr, CSIDL_FONTS, nullptr, SHGFP_TYPE_CURRENT, vbuffer))) { - DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory"); - goto folder_error; - } - - /* Some fonts are contained in .ttc files, TrueType Collection fonts. These - * contain multiple fonts inside this single file. GetFontData however - * returns the whole file, so we need to check each font inside to get the - * proper font. */ - path_len = _tcslen(vbuffer) + _tcslen(dbuffer) + 2; // '\' and terminating nul. - pathbuf = AllocaM(TCHAR, path_len); - _sntprintf(pathbuf, path_len, _T("%s\\%s"), vbuffer, dbuffer); - - /* Convert the path into something that FreeType understands. */ - font_path = GetShortPath(pathbuf); - - index = 0; - do { - err = FT_New_Face(_library, font_path, index, face); - if (err != FT_Err_Ok) break; - - if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break; - /* Try english name if font name failed */ - if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) break; - err = FT_Err_Cannot_Open_Resource; - - } while ((FT_Long)++index != (*face)->num_faces); - - -folder_error: -registry_no_font_found: - free(font_namep); - RegCloseKey(hKey); - return err; -} - -/** - * Fonts can have localised names and when the system locale is the same as - * one of those localised names Windows will always return that localised name - * instead of allowing to get the non-localised (English US) name of the font. - * This will later on give problems as freetype uses the non-localised name of - * the font and we need to compare based on that name. - * Windows furthermore DOES NOT have an API to get the non-localised name nor - * can we override the system locale. This means that we have to actually read - * the font itself to gather the font name we want. - * Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx - * @param logfont the font information to get the english name of. - * @return the English name (if it could be found). - */ -static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont) -{ - static char font_name[MAX_PATH]; - const char *ret_font_name = nullptr; - uint pos = 0; - HDC dc; - HGDIOBJ oldfont; - byte *buf; - DWORD dw; - uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset; - - HFONT font = CreateFontIndirect(&logfont->elfLogFont); - if (font == nullptr) goto err1; - - dc = GetDC(nullptr); - oldfont = SelectObject(dc, font); - dw = GetFontData(dc, 'eman', 0, nullptr, 0); - if (dw == GDI_ERROR) goto err2; - - buf = MallocT(dw); - dw = GetFontData(dc, 'eman', 0, buf, dw); - if (dw == GDI_ERROR) goto err3; - - format = buf[pos++] << 8; - format += buf[pos++]; - assert(format == 0); - count = buf[pos++] << 8; - count += buf[pos++]; - stringOffset = buf[pos++] << 8; - stringOffset += buf[pos++]; - for (uint i = 0; i < count; i++) { - platformId = buf[pos++] << 8; - platformId += buf[pos++]; - encodingId = buf[pos++] << 8; - encodingId += buf[pos++]; - languageId = buf[pos++] << 8; - languageId += buf[pos++]; - nameId = buf[pos++] << 8; - nameId += buf[pos++]; - if (nameId != 1) { - pos += 4; // skip length and offset - continue; - } - length = buf[pos++] << 8; - length += buf[pos++]; - offset = buf[pos++] << 8; - offset += buf[pos++]; - - /* Don't buffer overflow */ - length = std::min(length, MAX_PATH - 1); - for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j]; - font_name[length] = '\0'; - - if ((platformId == 1 && languageId == 0) || // Macintosh English - (platformId == 3 && languageId == 0x0409)) { // Microsoft English (US) - ret_font_name = font_name; - break; - } - } - -err3: - free(buf); -err2: - SelectObject(dc, oldfont); - ReleaseDC(nullptr, dc); - DeleteObject(font); -err1: - return ret_font_name == nullptr ? WIDE_TO_MB((const TCHAR*)logfont->elfFullName) : ret_font_name; -} -#endif /* WITH_FREETYPE */ - -class FontList { -protected: - TCHAR **fonts; - uint items; - uint capacity; - -public: - FontList() : fonts(nullptr), items(0), capacity(0) { }; - - ~FontList() { - if (this->fonts == nullptr) return; - - for (uint i = 0; i < this->items; i++) { - free(this->fonts[i]); - } - - free(this->fonts); - } - - bool Add(const TCHAR *font) { - for (uint i = 0; i < this->items; i++) { - if (_tcscmp(this->fonts[i], font) == 0) return false; - } - - if (this->items == this->capacity) { - this->capacity += 10; - this->fonts = ReallocT(this->fonts, this->capacity); - } - - this->fonts[this->items++] = _tcsdup(font); - - return true; - } -}; - -struct EFCParam { - FreeTypeSettings *settings; - LOCALESIGNATURE locale; - MissingGlyphSearcher *callback; - FontList fonts; -}; - -static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam) -{ - EFCParam *info = (EFCParam *)lParam; - - /* Skip duplicates */ - if (!info->fonts.Add((const TCHAR*)logfont->elfFullName)) return 1; - /* Only use TrueType fonts */ - if (!(type & TRUETYPE_FONTTYPE)) return 1; - /* Don't use SYMBOL fonts */ - if (logfont->elfLogFont.lfCharSet == SYMBOL_CHARSET) return 1; - /* Use monospaced fonts when asked for it. */ - if (info->callback->Monospace() && (logfont->elfLogFont.lfPitchAndFamily & (FF_MODERN | FIXED_PITCH)) != (FF_MODERN | FIXED_PITCH)) return 1; - - /* The font has to have at least one of the supported locales to be usable. */ - if ((metric->ntmFontSig.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (metric->ntmFontSig.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) { - /* On win9x metric->ntmFontSig seems to contain garbage. */ - FONTSIGNATURE fs; - memset(&fs, 0, sizeof(fs)); - HFONT font = CreateFontIndirect(&logfont->elfLogFont); - if (font != nullptr) { - HDC dc = GetDC(nullptr); - HGDIOBJ oldfont = SelectObject(dc, font); - GetTextCharsetInfo(dc, &fs, 0); - SelectObject(dc, oldfont); - ReleaseDC(nullptr, dc); - DeleteObject(font); - } - if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) return 1; - } - - char font_name[MAX_PATH]; - convert_from_fs((const TCHAR *)logfont->elfFullName, font_name, lengthof(font_name)); - -#ifdef WITH_FREETYPE - /* Add english name after font name */ - const char *english_name = GetEnglishFontName(logfont); - strecpy(font_name + strlen(font_name) + 1, english_name, lastof(font_name)); - - /* Check whether we can actually load the font. */ - bool ft_init = _library != nullptr; - bool found = false; - FT_Face face; - /* Init FreeType if needed. */ - if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName(font_name, &face) == FT_Err_Ok) { - FT_Done_Face(face); - found = true; - } - if (!ft_init) { - /* Uninit FreeType if we did the init. */ - FT_Done_FreeType(_library); - _library = nullptr; - } - - if (!found) return 1; -#else - const char *english_name = font_name; -#endif /* WITH_FREETYPE */ - - info->callback->SetFontNames(info->settings, font_name, &logfont->elfLogFont); - if (info->callback->FindMissingGlyphs()) return 1; - DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name); - return 0; // stop enumerating -} - -bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) -{ - DEBUG(freetype, 1, "Trying fallback fonts"); - EFCParam langInfo; - if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, sizeof(langInfo.locale) / sizeof(TCHAR)) == 0) { - /* Invalid langid or some other mysterious error, can't determine fallback font. */ - DEBUG(freetype, 1, "Can't get locale info for fallback font (langid=0x%x)", winlangid); - return false; - } - langInfo.settings = settings; - langInfo.callback = callback; - - LOGFONT font; - /* Enumerate all fonts. */ - font.lfCharSet = DEFAULT_CHARSET; - font.lfFaceName[0] = '\0'; - font.lfPitchAndFamily = 0; - - HDC dc = GetDC(nullptr); - int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0); - ReleaseDC(nullptr, dc); - return ret == 0; -} - -#elif defined(__APPLE__) /* end ifdef Win32 */ +#if defined(__APPLE__) /* ======================================================================================== * OSX support * ======================================================================================== */ @@ -643,10 +293,15 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i FcFini(); return ret; } +#endif /* end ifdef WITH_FONTCONFIG */ -#else /* without WITH_FONTCONFIG */ +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) + +#ifdef WITH_FREETYPE FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;} +#endif /* WITH_FREETYPE */ + bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; } -#endif /* WITH_FONTCONFIG */ +#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) */ #endif /* WITH_FREETYPE */ diff --git a/src/fontdetection.h b/src/fontdetection.h index 70b2fe236e..9cf39d2b07 100644 --- a/src/fontdetection.h +++ b/src/fontdetection.h @@ -27,7 +27,6 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face); #endif /* WITH_FREETYPE */ -#if defined(WITH_FREETYPE) || defined(_WIN32) /** * We would like to have a fallback font as the current one * doesn't contain all characters we need. @@ -38,8 +37,6 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face); * @param callback The function to call to check for missing glyphs. * @return true if a font has been set, false otherwise. */ -bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, class MissingGlyphSearcher *callback); - -#endif /* defined(WITH_FREETYPE) || defined(WIN32)*/ +bool SetFallbackFont(struct FreeTypeSettings *settings, const char *language_isocode, int winlangid, class MissingGlyphSearcher *callback); #endif diff --git a/src/os/windows/CMakeLists.txt b/src/os/windows/CMakeLists.txt index 19d1bd46e3..8ac2de7acc 100644 --- a/src/os/windows/CMakeLists.txt +++ b/src/os/windows/CMakeLists.txt @@ -1,5 +1,7 @@ add_files( crashlog_win.cpp + font_win32.cpp + font_win32.h string_uniscribe.cpp string_uniscribe.h win32.cpp diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp new file mode 100644 index 0000000000..4bcbb145d9 --- /dev/null +++ b/src/os/windows/font_win32.cpp @@ -0,0 +1,675 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file font_win32.cpp Functions related to font handling on Win32. */ + +#include "../../stdafx.h" +#include "../../debug.h" +#include "font_win32.h" +#include "../../blitter/factory.hpp" +#include "../../core/alloc_func.hpp" +#include "../../core/math_func.hpp" +#include "../../fileio_func.h" +#include "../../fontdetection.h" +#include "../../fontcache.h" +#include "../../string_func.h" +#include "../../strings_func.h" +#include "../../zoom_func.h" + +#include "../../table/control_codes.h" + +#include +#include /* SHGetFolderPath */ +#include "os/windows/win32.h" +#undef small // Say what, Windows? + +#include "safeguards.h" + +#ifdef WITH_FREETYPE + +#include +#include FT_FREETYPE_H + +extern FT_Library _library; + +/** + * Get the short DOS 8.3 format for paths. + * FreeType doesn't support Unicode filenames and Windows' fopen (as used + * by FreeType) doesn't support UTF-8 filenames. So we have to convert the + * filename into something that isn't UTF-8 but represents the Unicode file + * name. This is the short DOS 8.3 format. This does not contain any + * characters that fopen doesn't support. + * @param long_path the path in system encoding. + * @return the short path in ANSI (ASCII). + */ +static const char *GetShortPath(const TCHAR *long_path) +{ + static char short_path[MAX_PATH]; +#ifdef UNICODE + WCHAR short_path_w[MAX_PATH]; + GetShortPathName(long_path, short_path_w, lengthof(short_path_w)); + WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, lengthof(short_path), nullptr, nullptr); +#else + /* Technically not needed, but do it for consistency. */ + GetShortPathName(long_path, short_path, lengthof(short_path)); +#endif + return short_path; +} + +/* Get the font file to be loaded into Freetype by looping the registry + * location where windows lists all installed fonts. Not very nice, will + * surely break if the registry path changes, but it works. Much better + * solution would be to use CreateFont, and extract the font data from it + * by GetFontData. The problem with this is that the font file needs to be + * kept in memory then until the font is no longer needed. This could mean + * an additional memory usage of 30MB (just for fonts!) when using an eastern + * font for all font sizes */ +#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" +#define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts" +FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) +{ + FT_Error err = FT_Err_Cannot_Open_Resource; + HKEY hKey; + LONG ret; + TCHAR vbuffer[MAX_PATH], dbuffer[256]; + TCHAR *pathbuf; + const char *font_path; + uint index; + size_t path_len; + + /* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the + * "Windows NT" key, on Windows 9x in the Windows key. To save us having + * to retrieve the windows version, we'll just query both */ + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey); + if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey); + + if (ret != ERROR_SUCCESS) { + DEBUG(freetype, 0, "Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts"); + return err; + } + + /* Convert font name to file system encoding. */ + TCHAR *font_namep = _tcsdup(OTTD2FS(font_name)); + + for (index = 0;; index++) { + TCHAR *s; + DWORD vbuflen = lengthof(vbuffer); + DWORD dbuflen = lengthof(dbuffer); + + ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, nullptr, nullptr, (byte *)dbuffer, &dbuflen); + if (ret != ERROR_SUCCESS) goto registry_no_font_found; + + /* The font names in the registry are of the following 3 forms: + * - ADMUI3.fon + * - Book Antiqua Bold (TrueType) + * - Batang & BatangChe & Gungsuh & GungsuhChe (TrueType) + * We will strip the font-type '()' if any and work with the font name + * itself, which must match exactly; if... + * TTC files, font files which contain more than one font are separated + * by '&'. Our best bet will be to do substr match for the fontname + * and then let FreeType figure out which index to load */ + s = _tcschr(vbuffer, _T('(')); + if (s != nullptr) s[-1] = '\0'; + + if (_tcschr(vbuffer, _T('&')) == nullptr) { + if (_tcsicmp(vbuffer, font_namep) == 0) break; + } else { + if (_tcsstr(vbuffer, font_namep) != nullptr) break; + } + } + + if (!SUCCEEDED(OTTDSHGetFolderPath(nullptr, CSIDL_FONTS, nullptr, SHGFP_TYPE_CURRENT, vbuffer))) { + DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory"); + goto folder_error; + } + + /* Some fonts are contained in .ttc files, TrueType Collection fonts. These + * contain multiple fonts inside this single file. GetFontData however + * returns the whole file, so we need to check each font inside to get the + * proper font. */ + path_len = _tcslen(vbuffer) + _tcslen(dbuffer) + 2; // '\' and terminating nul. + pathbuf = AllocaM(TCHAR, path_len); + _sntprintf(pathbuf, path_len, _T("%s\\%s"), vbuffer, dbuffer); + + /* Convert the path into something that FreeType understands. */ + font_path = GetShortPath(pathbuf); + + index = 0; + do { + err = FT_New_Face(_library, font_path, index, face); + if (err != FT_Err_Ok) break; + + if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break; + /* Try english name if font name failed */ + if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) break; + err = FT_Err_Cannot_Open_Resource; + + } while ((FT_Long)++index != (*face)->num_faces); + + +folder_error: +registry_no_font_found: + free(font_namep); + RegCloseKey(hKey); + return err; +} + +/** + * Fonts can have localised names and when the system locale is the same as + * one of those localised names Windows will always return that localised name + * instead of allowing to get the non-localised (English US) name of the font. + * This will later on give problems as freetype uses the non-localised name of + * the font and we need to compare based on that name. + * Windows furthermore DOES NOT have an API to get the non-localised name nor + * can we override the system locale. This means that we have to actually read + * the font itself to gather the font name we want. + * Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx + * @param logfont the font information to get the english name of. + * @return the English name (if it could be found). + */ +static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont) +{ + static char font_name[MAX_PATH]; + const char *ret_font_name = nullptr; + uint pos = 0; + HDC dc; + HGDIOBJ oldfont; + byte *buf; + DWORD dw; + uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset; + + HFONT font = CreateFontIndirect(&logfont->elfLogFont); + if (font == nullptr) goto err1; + + dc = GetDC(nullptr); + oldfont = SelectObject(dc, font); + dw = GetFontData(dc, 'eman', 0, nullptr, 0); + if (dw == GDI_ERROR) goto err2; + + buf = MallocT(dw); + dw = GetFontData(dc, 'eman', 0, buf, dw); + if (dw == GDI_ERROR) goto err3; + + format = buf[pos++] << 8; + format += buf[pos++]; + assert(format == 0); + count = buf[pos++] << 8; + count += buf[pos++]; + stringOffset = buf[pos++] << 8; + stringOffset += buf[pos++]; + for (uint i = 0; i < count; i++) { + platformId = buf[pos++] << 8; + platformId += buf[pos++]; + encodingId = buf[pos++] << 8; + encodingId += buf[pos++]; + languageId = buf[pos++] << 8; + languageId += buf[pos++]; + nameId = buf[pos++] << 8; + nameId += buf[pos++]; + if (nameId != 1) { + pos += 4; // skip length and offset + continue; + } + length = buf[pos++] << 8; + length += buf[pos++]; + offset = buf[pos++] << 8; + offset += buf[pos++]; + + /* Don't buffer overflow */ + length = std::min(length, MAX_PATH - 1); + for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j]; + font_name[length] = '\0'; + + if ((platformId == 1 && languageId == 0) || // Macintosh English + (platformId == 3 && languageId == 0x0409)) { // Microsoft English (US) + ret_font_name = font_name; + break; + } + } + +err3: + free(buf); +err2: + SelectObject(dc, oldfont); + ReleaseDC(nullptr, dc); + DeleteObject(font); +err1: + return ret_font_name == nullptr ? WIDE_TO_MB((const TCHAR *)logfont->elfFullName) : ret_font_name; +} +#endif /* WITH_FREETYPE */ + +class FontList { +protected: + TCHAR **fonts; + uint items; + uint capacity; + +public: + FontList() : fonts(nullptr), items(0), capacity(0) { }; + + ~FontList() { + if (this->fonts == nullptr) return; + + for (uint i = 0; i < this->items; i++) { + free(this->fonts[i]); + } + + free(this->fonts); + } + + bool Add(const TCHAR *font) { + for (uint i = 0; i < this->items; i++) { + if (_tcscmp(this->fonts[i], font) == 0) return false; + } + + if (this->items == this->capacity) { + this->capacity += 10; + this->fonts = ReallocT(this->fonts, this->capacity); + } + + this->fonts[this->items++] = _tcsdup(font); + + return true; + } +}; + +struct EFCParam { + FreeTypeSettings *settings; + LOCALESIGNATURE locale; + MissingGlyphSearcher *callback; + FontList fonts; +}; + +static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam) +{ + EFCParam *info = (EFCParam *)lParam; + + /* Skip duplicates */ + if (!info->fonts.Add((const TCHAR *)logfont->elfFullName)) return 1; + /* Only use TrueType fonts */ + if (!(type & TRUETYPE_FONTTYPE)) return 1; + /* Don't use SYMBOL fonts */ + if (logfont->elfLogFont.lfCharSet == SYMBOL_CHARSET) return 1; + /* Use monospaced fonts when asked for it. */ + if (info->callback->Monospace() && (logfont->elfLogFont.lfPitchAndFamily & (FF_MODERN | FIXED_PITCH)) != (FF_MODERN | FIXED_PITCH)) return 1; + + /* The font has to have at least one of the supported locales to be usable. */ + if ((metric->ntmFontSig.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (metric->ntmFontSig.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) { + /* On win9x metric->ntmFontSig seems to contain garbage. */ + FONTSIGNATURE fs; + memset(&fs, 0, sizeof(fs)); + HFONT font = CreateFontIndirect(&logfont->elfLogFont); + if (font != nullptr) { + HDC dc = GetDC(nullptr); + HGDIOBJ oldfont = SelectObject(dc, font); + GetTextCharsetInfo(dc, &fs, 0); + SelectObject(dc, oldfont); + ReleaseDC(nullptr, dc); + DeleteObject(font); + } + if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) return 1; + } + + char font_name[MAX_PATH]; + convert_from_fs((const TCHAR *)logfont->elfFullName, font_name, lengthof(font_name)); + +#ifdef WITH_FREETYPE + /* Add english name after font name */ + const char *english_name = GetEnglishFontName(logfont); + strecpy(font_name + strlen(font_name) + 1, english_name, lastof(font_name)); + + /* Check whether we can actually load the font. */ + bool ft_init = _library != nullptr; + bool found = false; + FT_Face face; + /* Init FreeType if needed. */ + if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName(font_name, &face) == FT_Err_Ok) { + FT_Done_Face(face); + found = true; + } + if (!ft_init) { + /* Uninit FreeType if we did the init. */ + FT_Done_FreeType(_library); + _library = nullptr; + } + + if (!found) return 1; +#else + const char *english_name = font_name; +#endif /* WITH_FREETYPE */ + + info->callback->SetFontNames(info->settings, font_name, &logfont->elfLogFont); + if (info->callback->FindMissingGlyphs()) return 1; + DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name); + return 0; // stop enumerating +} + +bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) +{ + DEBUG(freetype, 1, "Trying fallback fonts"); + EFCParam langInfo; + if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, sizeof(langInfo.locale) / sizeof(TCHAR)) == 0) { + /* Invalid langid or some other mysterious error, can't determine fallback font. */ + DEBUG(freetype, 1, "Can't get locale info for fallback font (langid=0x%x)", winlangid); + return false; + } + langInfo.settings = settings; + langInfo.callback = callback; + + LOGFONT font; + /* Enumerate all fonts. */ + font.lfCharSet = DEFAULT_CHARSET; + font.lfFaceName[0] = '\0'; + font.lfPitchAndFamily = 0; + + HDC dc = GetDC(nullptr); + int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0); + ReleaseDC(nullptr, dc); + return ret == 0; +} + + +#ifndef ANTIALIASED_QUALITY +#define ANTIALIASED_QUALITY 4 +#endif + +/** + * Create a new Win32FontCache. + * @param fs The font size that is going to be cached. + * @param logfont The font that has to be loaded. + * @param pixels The number of pixels this font should be high. + */ +Win32FontCache::Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels) : TrueTypeFontCache(fs, pixels), logfont(logfont) +{ + this->dc = CreateCompatibleDC(nullptr); + this->SetFontSize(fs, pixels); +} + +Win32FontCache::~Win32FontCache() +{ + this->ClearFontCache(); + DeleteDC(this->dc); + DeleteObject(this->font); +} + +void Win32FontCache::SetFontSize(FontSize fs, int pixels) +{ + if (pixels == 0) { + /* Try to determine a good height based on the minimal height recommended by the font. */ + int scaled_height = ScaleFontTrad(this->GetDefaultFontHeight(this->fs)); + pixels = scaled_height; + + HFONT temp = CreateFontIndirect(&this->logfont); + if (temp != nullptr) { + HGDIOBJ old = SelectObject(this->dc, temp); + + UINT size = GetOutlineTextMetrics(this->dc, 0, nullptr); + LPOUTLINETEXTMETRIC otm = (LPOUTLINETEXTMETRIC)AllocaM(BYTE, size); + GetOutlineTextMetrics(this->dc, size, otm); + + /* Font height is minimum height plus the difference between the default + * height for this font size and the small size. */ + int diff = scaled_height - ScaleFontTrad(this->GetDefaultFontHeight(FS_SMALL)); + pixels = Clamp(std::min(otm->otmusMinimumPPEM, 20u) + diff, scaled_height, MAX_FONT_SIZE); + + SelectObject(dc, old); + DeleteObject(temp); + } + } else { + pixels = ScaleFontTrad(pixels); + } + this->used_size = pixels; + + /* Create GDI font handle. */ + this->logfont.lfHeight = -pixels; + this->logfont.lfWidth = 0; + this->logfont.lfOutPrecision = ANTIALIASED_QUALITY; + + if (this->font != nullptr) { + SelectObject(dc, this->old_font); + DeleteObject(this->font); + } + this->font = CreateFontIndirect(&this->logfont); + this->old_font = SelectObject(this->dc, this->font); + + /* Query the font metrics we needed. */ + UINT otmSize = GetOutlineTextMetrics(this->dc, 0, nullptr); + POUTLINETEXTMETRIC otm = (POUTLINETEXTMETRIC)AllocaM(BYTE, otmSize); + GetOutlineTextMetrics(this->dc, otmSize, otm); + + this->units_per_em = otm->otmEMSquare; + this->ascender = otm->otmTextMetrics.tmAscent; + this->descender = otm->otmTextMetrics.tmDescent; + this->height = this->ascender + this->descender; + this->glyph_size.cx = otm->otmTextMetrics.tmMaxCharWidth; + this->glyph_size.cy = otm->otmTextMetrics.tmHeight; + + DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPTSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)), pixels); +} + +/** + * Reset cached glyphs. + */ +void Win32FontCache::ClearFontCache() +{ + /* GUI scaling might have changed, determine font size anew if it was automatically selected. */ + if (this->font != nullptr) this->SetFontSize(this->fs, this->req_size); + + this->TrueTypeFontCache::ClearFontCache(); +} + +/* virtual */ const Sprite *Win32FontCache::InternalGetGlyph(GlyphID key, bool aa) +{ + GLYPHMETRICS gm; + MAT2 mat = { {0, 1}, {0, 0}, {0, 0}, {0, 1} }; + + /* Make a guess for the needed memory size. */ + DWORD size = this->glyph_size.cy * Align(aa ? this->glyph_size.cx : std::max(this->glyph_size.cx / 8l, 1l), 4); // Bitmap data is DWORD-aligned rows. + byte *bmp = AllocaM(byte, size); + size = GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, size, bmp, &mat); + + if (size == GDI_ERROR) { + /* No dice with the guess. First query size of needed glyph memory, then allocate the + * memory and query again. This dance is necessary as some glyphs will only render with + * the exact matching size; e.g. the space glyph has no pixels and must be requested + * with size == 0, anything else fails. Unfortunately, a failed call doesn't return any + * info about the size and thus the triple GetGlyphOutline()-call. */ + size = GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, 0, nullptr, &mat); + if (size == GDI_ERROR) usererror("Unable to render font glyph"); + bmp = AllocaM(byte, size); + GetGlyphOutline(this->dc, key, GGO_GLYPH_INDEX | (aa ? GGO_GRAY8_BITMAP : GGO_BITMAP), &gm, size, bmp, &mat); + } + + /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel. */ + uint width = std::max(1U, (uint)gm.gmBlackBoxX + (this->fs == FS_NORMAL)); + uint height = std::max(1U, (uint)gm.gmBlackBoxY + (this->fs == FS_NORMAL)); + + /* Limit glyph size to prevent overflows later on. */ + if (width > 256 || height > 256) usererror("Font glyph is too large"); + + /* GDI has rendered the glyph, now we allocate a sprite and copy the image into it. */ + SpriteLoader::Sprite sprite; + sprite.AllocateData(ZOOM_LVL_NORMAL, width * height); + sprite.type = ST_FONT; + sprite.width = width; + sprite.height = height; + sprite.x_offs = gm.gmptGlyphOrigin.x; + sprite.y_offs = this->ascender - gm.gmptGlyphOrigin.y; + + if (size > 0) { + /* All pixel data returned by GDI is in the form of DWORD-aligned rows. + * For a non anti-aliased glyph, the returned bitmap has one bit per pixel. + * For anti-aliased rendering, GDI uses the strange value range of 0 to 64, + * inclusively. To map this to 0 to 255, we shift left by two and then + * subtract one. */ + uint pitch = Align(aa ? gm.gmBlackBoxX : std::max(gm.gmBlackBoxX / 8u, 1u), 4); + + /* Draw shadow for medium size. */ + if (this->fs == FS_NORMAL && !aa) { + for (uint y = 0; y < gm.gmBlackBoxY; y++) { + for (uint x = 0; x < gm.gmBlackBoxX; x++) { + if (aa ? (bmp[x + y * pitch] > 0) : HasBit(bmp[(x / 8) + y * pitch], 7 - (x % 8))) { + sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR; + sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? (bmp[x + y * pitch] << 2) - 1 : 0xFF; + } + } + } + } + + for (uint y = 0; y < gm.gmBlackBoxY; y++) { + for (uint x = 0; x < gm.gmBlackBoxX; x++) { + if (aa ? (bmp[x + y * pitch] > 0) : HasBit(bmp[(x / 8) + y * pitch], 7 - (x % 8))) { + sprite.data[x + y * sprite.width].m = FACE_COLOUR; + sprite.data[x + y * sprite.width].a = aa ? (bmp[x + y * pitch] << 2) - 1 : 0xFF; + } + } + } + } + + GlyphEntry new_glyph; + new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(&sprite, AllocateFont); + new_glyph.width = gm.gmCellIncX; + + this->SetGlyphPtr(key, &new_glyph); + + return new_glyph.sprite; +} + +/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(WChar key) +{ + assert(IsPrintable(key)); + + if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { + return this->parent->MapCharToGlyph(key); + } + + /* Convert characters outside of the BMP into surrogate pairs. */ + WCHAR chars[2]; + if (key >= 0x010000U) { + chars[0] = (WCHAR)(((key - 0x010000U) >> 10) + 0xD800); + chars[1] = (WCHAR)(((key - 0x010000U) & 0x3FF) + 0xDC00); + } else { + chars[0] = (WCHAR)(key & 0xFFFF); + } + + WORD glyphs[2] = { 0, 0 }; + GetGlyphIndicesW(this->dc, chars, key >= 0x010000U ? 2 : 1, glyphs, GGI_MARK_NONEXISTING_GLYPHS); + + return glyphs[0] != 0xFFFF ? glyphs[0] : 0; +} + +/* virtual */ const void *Win32FontCache::InternalGetFontTable(uint32 tag, size_t &length) +{ + DWORD len = GetFontData(this->dc, tag, 0, nullptr, 0); + + void *result = nullptr; + if (len != GDI_ERROR && len > 0) { + result = MallocT(len); + GetFontData(this->dc, tag, 0, result, len); + } + + length = len; + return result; +} + + +/** + * Loads the GDI font. + * If a GDI font description is present, e.g. from the automatic font + * fallback search, use it. Otherwise, try to resolve it by font name. + * @param fs The font size to load. + */ +void LoadWin32Font(FontSize fs) +{ + static const char *SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; + + FreeTypeSubSetting *settings = nullptr; + switch (fs) { + case FS_SMALL: settings = &_freetype.small; break; + case FS_NORMAL: settings = &_freetype.medium; break; + case FS_LARGE: settings = &_freetype.large; break; + case FS_MONO: settings = &_freetype.mono; break; + default: NOT_REACHED(); + } + + if (StrEmpty(settings->font)) return; + + LOGFONT logfont; + MemSetT(&logfont, 0); + logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH; + logfont.lfCharSet = DEFAULT_CHARSET; + logfont.lfOutPrecision = OUT_OUTLINE_PRECIS; + logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + + if (settings->os_handle != nullptr) { + logfont = *(const LOGFONT *)settings->os_handle; + } else if (strchr(settings->font, '.') != nullptr) { + /* Might be a font file name, try load it. */ + + TCHAR fontPath[MAX_PATH] = {}; + + /* See if this is an absolute path. */ + if (FileExists(settings->font)) { + convert_to_fs(settings->font, fontPath, lengthof(fontPath), false); + } else { + /* Scan the search-paths to see if it can be found. */ + std::string full_font = FioFindFullPath(BASE_DIR, settings->font); + if (!full_font.empty()) { + convert_to_fs(full_font.c_str(), fontPath, lengthof(fontPath), false); + } + } + + if (fontPath[0] != 0) { + if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) { + /* Try a nice little undocumented function first for getting the internal font name. + * Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */ + typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD); +#ifdef UNICODE + static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(_T("Gdi32")), "GetFontResourceInfoW"); +#else + static PFNGETFONTRESOURCEINFO GetFontResourceInfo = (PFNGETFONTRESOURCEINFO)GetProcAddress(GetModuleHandle(_T("Gdi32")), "GetFontResourceInfoA"); +#endif + + if (GetFontResourceInfo != nullptr) { + /* Try to query an array of LOGFONTs that describe the file. */ + DWORD len = 0; + if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) { + LOGFONT *buf = (LOGFONT *)AllocaM(byte, len); + if (GetFontResourceInfo(fontPath, &len, buf, 2)) { + logfont = *buf; // Just use first entry. + } + } + } + + /* No dice yet. Use the file name as the font face name, hoping it matches. */ + if (logfont.lfFaceName[0] == 0) { + TCHAR fname[_MAX_FNAME]; + _tsplitpath(fontPath, nullptr, nullptr, fname, nullptr); + + _tcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE); + logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr || strcasestr(settings->font, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. + } + } else { + ShowInfoF("Unable to load file '%s' for %s font, using default windows font selection instead", settings->font, SIZE_TO_NAME[fs]); + } + } + } + + if (logfont.lfFaceName[0] == 0) { + logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. + convert_to_fs(settings->font, logfont.lfFaceName, lengthof(logfont.lfFaceName), false); + } + + HFONT font = CreateFontIndirect(&logfont); + if (font == nullptr) { + ShowInfoF("Unable to use '%s' for %s font, Win32 reported error 0x%lX, using sprite font instead", settings->font, SIZE_TO_NAME[fs], GetLastError()); + return; + } + DeleteObject(font); + + new Win32FontCache(fs, logfont, settings->size); +} diff --git a/src/os/windows/font_win32.h b/src/os/windows/font_win32.h new file mode 100644 index 0000000000..9a552125fd --- /dev/null +++ b/src/os/windows/font_win32.h @@ -0,0 +1,42 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file font_win32.h Functions related to font handling on Win32. */ + +#ifndef FONT_WIN32_H +#define FONT_WIN32_H + +#include "../../fontcache_internal.h" +#include "win32.h" + +/** Font cache for fonts that are based on a Win32 font. */ +class Win32FontCache : public TrueTypeFontCache { +private: + LOGFONT logfont; ///< Logical font information for selecting the font face. + HFONT font = nullptr; ///< The font face associated with this font. + HDC dc = nullptr; ///< Cached GDI device context. + HGDIOBJ old_font; ///< Old font selected into the GDI context. + SIZE glyph_size; ///< Maximum size of regular glyphs. + + void SetFontSize(FontSize fs, int pixels); + +protected: + const void *InternalGetFontTable(uint32 tag, size_t &length) override; + const Sprite *InternalGetGlyph(GlyphID key, bool aa) override; + +public: + Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels); + ~Win32FontCache(); + void ClearFontCache() override; + GlyphID MapCharToGlyph(WChar key) override; + const char *GetFontName() override { return WIDE_TO_MB(this->logfont.lfFaceName); } + const void *GetOSHandle() override { return &this->logfont; } +}; + +void LoadWin32Font(FontSize fs); + +#endif /* FONT_WIN32_H */ From f2294851e6b468ba49b108a26e75b98a63a7c05c Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 17:46:05 +0100 Subject: [PATCH 064/275] Codechange: [OSX] Move OSX-specific font code to a separate file. --- src/fontdetection.cpp | 121 +----------------------------- src/os/macosx/CMakeLists.txt | 1 + src/os/macosx/font_osx.cpp | 138 +++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 120 deletions(-) create mode 100644 src/os/macosx/font_osx.cpp diff --git a/src/fontdetection.cpp b/src/fontdetection.cpp index ca9f620b9b..50bd274ed5 100644 --- a/src/fontdetection.cpp +++ b/src/fontdetection.cpp @@ -24,126 +24,7 @@ extern FT_Library _library; * If no appropriate font is found, the function returns an error */ -#if defined(__APPLE__) -/* ======================================================================================== - * OSX support - * ======================================================================================== */ - -#include "os/macosx/macos.h" - -#include "safeguards.h" - -FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) -{ - FT_Error err = FT_Err_Cannot_Open_Resource; - - /* Get font reference from name. */ - UInt8 file_path[PATH_MAX]; - OSStatus os_err = -1; - CFAutoRelease name(CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8)); - - /* Simply creating the font using CTFontCreateWithNameAndSize will *always* return - * something, no matter the name. As such, we can't use it to check for existence. - * We instead query the list of all font descriptors that match the given name which - * does not do this stupid name fallback. */ - CFAutoRelease name_desc(CTFontDescriptorCreateWithNameAndSize(name.get(), 0.0)); - CFAutoRelease mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontNameAttribute)), 1, &kCFTypeSetCallBacks)); - CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(name_desc.get(), mandatory_attribs.get())); - - /* Loop over all matches until we can get a path for one of them. */ - for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()) && os_err != noErr; i++) { - CFAutoRelease font(CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i), 0.0, nullptr)); - CFAutoRelease fontURL((CFURLRef)CTFontCopyAttribute(font.get(), kCTFontURLAttribute)); - if (CFURLGetFileSystemRepresentation(fontURL.get(), true, file_path, lengthof(file_path))) os_err = noErr; - } - - if (os_err == noErr) { - DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path); - err = FT_New_Face(_library, (const char *)file_path, 0, face); - } - - return err; -} - -bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) -{ - /* Determine fallback font using CoreText. This uses the language isocode - * to find a suitable font. CoreText is available from 10.5 onwards. */ - char lang[16]; - if (strcmp(language_isocode, "zh_TW") == 0) { - /* Traditional Chinese */ - strecpy(lang, "zh-Hant", lastof(lang)); - } else if (strcmp(language_isocode, "zh_CN") == 0) { - /* Simplified Chinese */ - strecpy(lang, "zh-Hans", lastof(lang)); - } else { - /* Just copy the first part of the isocode. */ - strecpy(lang, language_isocode, lastof(lang)); - char *sep = strchr(lang, '_'); - if (sep != nullptr) *sep = '\0'; - } - - /* Create a font descriptor matching the wanted language and latin (english) glyphs. - * Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */ - CFStringRef lang_codes[2]; - lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8); - lang_codes[1] = CFSTR("en"); - CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks); - CFAutoRelease lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontLanguagesAttribute)), (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - CFAutoRelease lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get())); - CFRelease(lang_arr); - CFRelease(lang_codes[0]); - - /* Get array of all font descriptors for the wanted language. */ - CFAutoRelease mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontLanguagesAttribute)), 1, &kCFTypeSetCallBacks)); - CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get())); - - bool result = false; - for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) { - CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i); - - /* Get font traits. */ - CFAutoRelease traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)); - CTFontSymbolicTraits symbolic_traits; - CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); - - /* Skip symbol fonts and vertical fonts. */ - if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; - /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ - if (symbolic_traits & kCTFontBoldTrait) continue; - /* Select monospaced fonts if asked for. */ - if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; - - /* Get font name. */ - char name[128]; - CFAutoRelease font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute)); - CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8); - - /* There are some special fonts starting with an '.' and the last - * resort font that aren't usable. Skip them. */ - if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; - - /* Save result. */ - callback->SetFontNames(settings, name); - if (!callback->FindMissingGlyphs()) { - DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); - result = true; - break; - } - } - - if (!result) { - /* For some OS versions, the font 'Arial Unicode MS' does not report all languages it - * supports. If we didn't find any other font, just try it, maybe we get lucky. */ - callback->SetFontNames(settings, "Arial Unicode MS"); - result = !callback->FindMissingGlyphs(); - } - - callback->FindMissingGlyphs(); - return result; -} - -#elif defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */ +#if defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */ #include diff --git a/src/os/macosx/CMakeLists.txt b/src/os/macosx/CMakeLists.txt index e6b6c237b0..31f6af7d49 100644 --- a/src/os/macosx/CMakeLists.txt +++ b/src/os/macosx/CMakeLists.txt @@ -1,5 +1,6 @@ add_files( crashlog_osx.cpp + font_osx.cpp macos.h macos.mm osx_stdafx.h diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp new file mode 100644 index 0000000000..f9436312b5 --- /dev/null +++ b/src/os/macosx/font_osx.cpp @@ -0,0 +1,138 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file font_osx.cpp Functions related to font handling on MacOS. */ + +#include "../../stdafx.h" +#include "../../debug.h" +#include "../../fontdetection.h" +#include "../../string_func.h" +#include "../../strings_func.h" +#include "macos.h" + +#include "safeguards.h" + +#ifdef WITH_FREETYPE + +#include +#include FT_FREETYPE_H + +extern FT_Library _library; + + +FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) +{ + FT_Error err = FT_Err_Cannot_Open_Resource; + + /* Get font reference from name. */ + UInt8 file_path[PATH_MAX]; + OSStatus os_err = -1; + CFAutoRelease name(CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8)); + + /* Simply creating the font using CTFontCreateWithNameAndSize will *always* return + * something, no matter the name. As such, we can't use it to check for existence. + * We instead query the list of all font descriptors that match the given name which + * does not do this stupid name fallback. */ + CFAutoRelease name_desc(CTFontDescriptorCreateWithNameAndSize(name.get(), 0.0)); + CFAutoRelease mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontNameAttribute)), 1, &kCFTypeSetCallBacks)); + CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(name_desc.get(), mandatory_attribs.get())); + + /* Loop over all matches until we can get a path for one of them. */ + for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()) && os_err != noErr; i++) { + CFAutoRelease font(CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i), 0.0, nullptr)); + CFAutoRelease fontURL((CFURLRef)CTFontCopyAttribute(font.get(), kCTFontURLAttribute)); + if (CFURLGetFileSystemRepresentation(fontURL.get(), true, file_path, lengthof(file_path))) os_err = noErr; + } + + if (os_err == noErr) { + DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path); + err = FT_New_Face(_library, (const char *)file_path, 0, face); + } + + return err; +} + +#endif /* WITH_FREETYPE */ + + +bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) +{ + /* Determine fallback font using CoreText. This uses the language isocode + * to find a suitable font. CoreText is available from 10.5 onwards. */ + char lang[16]; + if (strcmp(language_isocode, "zh_TW") == 0) { + /* Traditional Chinese */ + strecpy(lang, "zh-Hant", lastof(lang)); + } else if (strcmp(language_isocode, "zh_CN") == 0) { + /* Simplified Chinese */ + strecpy(lang, "zh-Hans", lastof(lang)); + } else { + /* Just copy the first part of the isocode. */ + strecpy(lang, language_isocode, lastof(lang)); + char *sep = strchr(lang, '_'); + if (sep != nullptr) *sep = '\0'; + } + + /* Create a font descriptor matching the wanted language and latin (english) glyphs. + * Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */ + CFStringRef lang_codes[2]; + lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8); + lang_codes[1] = CFSTR("en"); + CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks); + CFAutoRelease lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontLanguagesAttribute)), (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CFAutoRelease lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get())); + CFRelease(lang_arr); + CFRelease(lang_codes[0]); + + /* Get array of all font descriptors for the wanted language. */ + CFAutoRelease mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontLanguagesAttribute)), 1, &kCFTypeSetCallBacks)); + CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get())); + + bool result = false; + for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) { + CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i); + + /* Get font traits. */ + CFAutoRelease traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)); + CTFontSymbolicTraits symbolic_traits; + CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); + + /* Skip symbol fonts and vertical fonts. */ + if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; + /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ + if (symbolic_traits & kCTFontBoldTrait) continue; + /* Select monospaced fonts if asked for. */ + if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; + + /* Get font name. */ + char name[128]; + CFAutoRelease font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute)); + CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8); + + /* There are some special fonts starting with an '.' and the last + * resort font that aren't usable. Skip them. */ + if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; + + /* Save result. */ + callback->SetFontNames(settings, name); + if (!callback->FindMissingGlyphs()) { + DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); + result = true; + break; + } + } + + if (!result) { + /* For some OS versions, the font 'Arial Unicode MS' does not report all languages it + * supports. If we didn't find any other font, just try it, maybe we get lucky. */ + callback->SetFontNames(settings, "Arial Unicode MS"); + result = !callback->FindMissingGlyphs(); + } + + callback->FindMissingGlyphs(); + return result; +} From 63ed3f3575ade286782f56c249bcd2478e656adc Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 17:53:41 +0100 Subject: [PATCH 065/275] Codechange: Move Fontconfig-specific code to a seperate file. --- src/CMakeLists.txt | 1 - src/fontcache.cpp | 15 ++-- src/os/unix/CMakeLists.txt | 5 ++ .../unix/font_unix.cpp} | 71 +++++++------------ 4 files changed, 41 insertions(+), 51 deletions(-) rename src/{fontdetection.cpp => os/unix/font_unix.cpp} (71%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d451ae8da6..e0af799994 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -156,7 +156,6 @@ add_files( fontcache.cpp fontcache.h fontcache_internal.h - fontdetection.cpp fontdetection.h framerate_gui.cpp framerate_type.h diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 6cc25154f8..6a0b500d86 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -205,7 +205,6 @@ bool SpriteFontCache::GetDrawGlyphShadow() /* static */ FontCache *FontCache::caches[FS_END] = { new SpriteFontCache(FS_NORMAL), new SpriteFontCache(FS_SMALL), new SpriteFontCache(FS_LARGE), new SpriteFontCache(FS_MONO) }; -#if defined(WITH_FREETYPE) || defined(_WIN32) /** * Create a new TrueTypeFontCache. @@ -678,13 +677,8 @@ const void *FreeTypeFontCache::InternalGetFontTable(uint32 tag, size_t &length) return result; } -#elif defined(_WIN32) - - - #endif /* WITH_FREETYPE */ -#endif /* defined(WITH_FREETYPE) || defined(_WIN32) */ /** * (Re)initialize the freetype related things, i.e. load the non-sprite fonts. @@ -722,3 +716,12 @@ void UninitFreeType() _library = nullptr; #endif /* WITH_FREETYPE */ } + +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) + +#ifdef WITH_FREETYPE +FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) { return FT_Err_Cannot_Open_Resource; } +#endif /* WITH_FREETYPE */ + +bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; } +#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) */ diff --git a/src/os/unix/CMakeLists.txt b/src/os/unix/CMakeLists.txt index b548d3bb21..8e74f96643 100644 --- a/src/os/unix/CMakeLists.txt +++ b/src/os/unix/CMakeLists.txt @@ -7,3 +7,8 @@ add_files( unix.cpp CONDITION UNIX AND NOT OPTION_OS2 ) + +add_files( + font_unix.cpp + CONDITION Fontconfig_FOUND +) diff --git a/src/fontdetection.cpp b/src/os/unix/font_unix.cpp similarity index 71% rename from src/fontdetection.cpp rename to src/os/unix/font_unix.cpp index 50bd274ed5..b607db8f8a 100644 --- a/src/fontdetection.cpp +++ b/src/os/unix/font_unix.cpp @@ -5,34 +5,26 @@ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . */ -/** @file fontdetection.cpp Detection of the right font. */ +/** @file font_unix.cpp Functions related to font handling on Unix/Fontconfig. */ -#if defined(WITH_FREETYPE) || defined(_WIN32) - -#include "stdafx.h" -#include "debug.h" -#include "fontdetection.h" -#include "string_func.h" -#include "strings_func.h" - -#ifdef WITH_FREETYPE -extern FT_Library _library; -#endif /* WITH_FREETYPE */ - -/** - * Get the font loaded into a Freetype face by using a font-name. - * If no appropriate font is found, the function returns an error - */ - -#if defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */ +#include "../../stdafx.h" +#include "../../debug.h" +#include "../../fontdetection.h" +#include "../../string_func.h" +#include "../../strings_func.h" #include #include "safeguards.h" -/* ======================================================================================== - * FontConfig (unix) support - * ======================================================================================== */ +#ifdef WITH_FREETYPE + +#include +#include FT_FREETYPE_H + +extern FT_Library _library; + + FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) { FT_Error err = FT_Err_Cannot_Open_Resource; @@ -57,8 +49,8 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) } /* Resolve the name and populate the information structure */ - pat = FcNameParse((FcChar8*)font_family); - if (font_style != nullptr) FcPatternAddString(pat, FC_STYLE, (FcChar8*)font_style); + pat = FcNameParse((FcChar8 *)font_family); + if (font_style != nullptr) FcPatternAddString(pat, FC_STYLE, (FcChar8 *)font_style); FcConfigSubstitute(0, pat, FcMatchPattern); FcDefaultSubstitute(pat); fs = FcFontSetCreate(); @@ -73,17 +65,17 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) { /* Try the new filename */ - if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch && - FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch && - FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch) { + if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch && + FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch && + FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch) { /* The correct style? */ - if (font_style != nullptr && strcasecmp(font_style, (char*)style) != 0) continue; + if (font_style != nullptr && strcasecmp(font_style, (char *)style) != 0) continue; /* Font config takes the best shot, which, if the family name is spelled * wrongly a 'random' font, so check whether the family name is the * same as the supplied name */ - if (strcasecmp(font_family, (char*)family) == 0) { + if (strcasecmp(font_family, (char *)family) == 0) { err = FT_New_Face(_library, (char *)file, 0, face); } } @@ -99,6 +91,9 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) return err; } +#endif /* WITH_FREETYPE */ + + bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { if (!FcInit()) return false; @@ -114,7 +109,7 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i if (split != nullptr) *split = '\0'; /* First create a pattern to match the wanted language. */ - FcPattern *pat = FcNameParse((FcChar8*)lang); + FcPattern *pat = FcNameParse((FcChar8 *)lang); /* We only want to know the filename. */ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, nullptr); /* Get the list of filenames matching the wanted language. */ @@ -150,14 +145,14 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i FcPatternGetInteger(font, FC_WEIGHT, 0, &value); if (value <= best_weight) continue; - callback->SetFontNames(settings, (const char*)file); + callback->SetFontNames(settings, (const char *)file); bool missing = callback->FindMissingGlyphs(); DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no"); if (!missing) { best_weight = value; - best_font = (const char *)file; + best_font = (const char *)file; } } @@ -174,15 +169,3 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i FcFini(); return ret; } -#endif /* end ifdef WITH_FONTCONFIG */ - -#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) - -#ifdef WITH_FREETYPE -FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;} -#endif /* WITH_FREETYPE */ - -bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; } -#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) */ - -#endif /* WITH_FREETYPE */ From 4db7837d0671c228303c76f5979bbeb89c600634 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 9 Jan 2021 18:43:12 +0100 Subject: [PATCH 066/275] Codechange: [OSX] There is only one subdriver left, remove virtual dispatch. --- src/video/cocoa/cocoa_v.h | 76 +++++++++++++------------- src/video/cocoa/cocoa_v.mm | 100 ++++------------------------------- src/video/cocoa/cocoa_wnd.h | 14 ++--- src/video/cocoa/cocoa_wnd.mm | 6 +-- 4 files changed, 58 insertions(+), 138 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 54ff53d156..2aca2034eb 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -86,12 +86,22 @@ public: }; -/** - * Generic display driver for cocoa - * On grounds to not duplicate some code, it contains a few variables - * which are not used by all device drivers. - */ -class CocoaSubdriver { + +class WindowQuartzSubdriver { +private: + /** + * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. + * + * @param left The x coord for the left edge of the box to blit. + * @param top The y coord for the top edge of the box to blit. + * @param right The x coord for the right edge of the box to blit. + * @param bottom The y coord for the bottom edge of the box to blit. + */ + void BlitIndexedToView32(int left, int top, int right, int bottom); + + void GetDeviceInfo(); + bool SetVideoMode(int width, int height, int bpp); + public: int device_width; ///< Width of device in pixel int device_height; ///< Height of device in pixel @@ -104,8 +114,6 @@ public: int buffer_depth; ///< Colour depth of used frame buffer void *pixel_buffer; ///< used for direct pixel access void *window_buffer; ///< Colour translation from palette to screen - CGColorSpaceRef color_space; //< Window color space - id window; ///< Pointer to window object # define MAX_DIRTY_RECTS 100 Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles @@ -115,20 +123,18 @@ public: bool active; ///< Whether the window is visible bool setup; + id window; ///< Pointer to window object id cocoaview; ///< Pointer to view object + CGColorSpaceRef color_space; ///< Window color space + CGContextRef cgcontext; ///< Context reference for Quartz subdriver - /* Separate driver vars for Quarz - * Needed here in order to avoid much code duplication */ - CGContextRef cgcontext; ///< Context reference for Quartz subdriver - - /* Driver methods */ - /** Initialize driver */ - virtual ~CocoaSubdriver() {} + WindowQuartzSubdriver(); + ~WindowQuartzSubdriver(); /** Draw window * @param force_update Whether to redraw unconditionally */ - virtual void Draw(bool force_update = false) = 0; + void Draw(bool force_update = false); /** Mark dirty a screen region * @param left x-coordinate of left border @@ -136,77 +142,73 @@ public: * @param width width or dirty rectangle * @param height height of dirty rectangle */ - virtual void MakeDirty(int left, int top, int width, int height) = 0; + void MakeDirty(int left, int top, int width, int height); /** Update the palette */ - virtual void UpdatePalette(uint first_color, uint num_colors) = 0; + void UpdatePalette(uint first_color, uint num_colors); - virtual uint ListModes(OTTD_Point *modes, uint max_modes) = 0; + uint ListModes(OTTD_Point *modes, uint max_modes); /** Change window resolution * @param w New window width * @param h New window height * @return Whether change was successful */ - virtual bool ChangeResolution(int w, int h, int bpp) = 0; + bool ChangeResolution(int w, int h, int bpp); /** Are we in fullscreen mode * @return whether fullscreen mode is currently used */ - virtual bool IsFullscreen() = 0; + bool IsFullscreen(); /** Toggle between fullscreen and windowed mode * @return whether switch was successful */ - virtual bool ToggleFullscreen(bool fullscreen) { return false; }; + bool ToggleFullscreen(bool fullscreen); /** Return the width of the current view * @return width of the current view */ - virtual int GetWidth() = 0; + int GetWidth() { return window_width; } /** Return the height of the current view * @return height of the current view */ - virtual int GetHeight() = 0; + int GetHeight() { return window_height; } /** Return the current pixel buffer * @return pixelbuffer */ - virtual void *GetPixelBuffer() = 0; + void *GetPixelBuffer() { return buffer_depth == 8 ? pixel_buffer : window_buffer; } /** Convert local coordinate to window server (CoreGraphics) coordinate * @param p local coordinates * @return window driver coordinates */ - virtual CGPoint PrivateLocalToCG(NSPoint *p) = 0; + CGPoint PrivateLocalToCG(NSPoint *p); /** Return the mouse location * @param event UI event * @return mouse location as NSPoint */ - virtual NSPoint GetMouseLocation(NSEvent *event) = 0; + NSPoint GetMouseLocation(NSEvent *event); /** Return whether the mouse is within our view * @param pt Mouse coordinates * @return Whether mouse coordinates are within view */ - virtual bool MouseIsInsideView(NSPoint *pt) = 0; + bool MouseIsInsideView(NSPoint *pt); - /** Return whether the window is active (visible) - * @return whether the window is visible or not - */ - virtual bool IsActive() = 0; + /** Return whether the window is active (visible) */ + bool IsActive() { return active; } - /** Whether the window was successfully resized + /** Resize the window. * @return whether the window was successfully resized */ - virtual bool WindowResized() { return false; }; + bool WindowResized(); }; -extern CocoaSubdriver *_cocoa_subdriver; - -CocoaSubdriver *QZ_CreateWindowQuartzSubdriver(int width, int height, int bpp); +extern WindowQuartzSubdriver *_cocoa_subdriver; uint QZ_ListModes(OTTD_Point *modes, uint max_modes, CGDirectDisplayID display_id, int display_depth); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index f09920fe20..5da0f55e31 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -56,7 +56,7 @@ #endif bool _cocoa_video_started = false; -CocoaSubdriver *_cocoa_subdriver = NULL; +WindowQuartzSubdriver *_cocoa_subdriver = NULL; static bool ModeSorter(const OTTD_Point &p1, const OTTD_Point &p2) @@ -143,32 +143,6 @@ static void QZ_UpdateVideoModes() } } -/** - * Find a suitable cocoa subdriver. - * - * @param width Width of display area. - * @param height Height of display area. - * @param bpp Colour depth of display area. - * @param fullscreen Whether a fullscreen mode is requested. - * @param fallback Whether we look for a fallback driver. - * @return Pointer to window subdriver. - */ -static CocoaSubdriver *QZ_CreateSubdriver(int width, int height, int bpp, bool fullscreen, bool fallback) -{ - CocoaSubdriver *ret = QZ_CreateWindowQuartzSubdriver(width, height, bpp); - if (ret != nullptr && fullscreen) ret->ToggleFullscreen(fullscreen); - - if (ret != nullptr) return ret; - if (!fallback) return nullptr; - - /* Try again in 640x480 windowed */ - DEBUG(driver, 0, "Setting video mode failed, falling back to 640x480 windowed mode."); - ret = QZ_CreateWindowQuartzSubdriver(640, 480, bpp); - if (ret != nullptr) return ret; - - return nullptr; -} - static FVideoDriver_Cocoa iFVideoDriver_Cocoa; @@ -182,7 +156,7 @@ void VideoDriver_Cocoa::Stop() CocoaExitApplication(); delete _cocoa_subdriver; - _cocoa_subdriver = NULL; + _cocoa_subdriver = nullptr; _cocoa_video_started = false; } @@ -198,7 +172,7 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) _cocoa_video_started = true; /* Don't create a window or enter fullscreen if we're just going to show a dialog. */ - if (!CocoaSetupApplication()) return NULL; + if (!CocoaSetupApplication()) return nullptr; this->UpdateAutoResolution(); @@ -212,12 +186,14 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) return "The cocoa quartz subdriver only supports 8 and 32 bpp."; } - _cocoa_subdriver = QZ_CreateSubdriver(width, height, bpp, _fullscreen, true); - if (_cocoa_subdriver == NULL) { + _cocoa_subdriver = new WindowQuartzSubdriver(); + if (!_cocoa_subdriver->ChangeResolution(width, height, bpp)) { Stop(); return "Could not create subdriver"; } + if (_fullscreen) _cocoa_subdriver->ToggleFullscreen(_fullscreen); + this->GameSizeChanged(); QZ_UpdateVideoModes(); @@ -340,59 +316,14 @@ class WindowQuartzSubdriver; /* Subclass of OTTD_CocoaView to fix Quartz rendering */ @interface OTTD_QuartzView : OTTD_CocoaView -- (void)setDriver:(WindowQuartzSubdriver*)drv; +- (void)setDriver:(WindowQuartzSubdriver *)drv; - (void)drawRect:(NSRect)invalidRect; @end -class WindowQuartzSubdriver : public CocoaSubdriver { -private: - /** - * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. - * - * @param left The x coord for the left edge of the box to blit. - * @param top The y coord for the top edge of the box to blit. - * @param right The x coord for the right edge of the box to blit. - * @param bottom The y coord for the bottom edge of the box to blit. - */ - void BlitIndexedToView32(int left, int top, int right, int bottom); - - virtual void GetDeviceInfo(); - virtual bool SetVideoMode(int width, int height, int bpp); - -public: - WindowQuartzSubdriver(); - virtual ~WindowQuartzSubdriver(); - - virtual void Draw(bool force_update); - virtual void MakeDirty(int left, int top, int width, int height); - virtual void UpdatePalette(uint first_color, uint num_colors); - - virtual uint ListModes(OTTD_Point *modes, uint max_modes); - - virtual bool ChangeResolution(int w, int h, int bpp); - - virtual bool IsFullscreen(); - virtual bool ToggleFullscreen(bool fullscreen); /* Full screen mode on OSX 10.7 */ - - virtual int GetWidth() { return window_width; } - virtual int GetHeight() { return window_height; } - virtual void *GetPixelBuffer() { return buffer_depth == 8 ? pixel_buffer : window_buffer; } - - /* Convert local coordinate to window server (CoreGraphics) coordinate */ - virtual CGPoint PrivateLocalToCG(NSPoint *p); - - virtual NSPoint GetMouseLocation(NSEvent *event); - virtual bool MouseIsInsideView(NSPoint *pt); - - virtual bool IsActive() { return active; } - - bool WindowResized(); -}; - @implementation OTTD_QuartzView -- (void)setDriver:(WindowQuartzSubdriver*)drv +- (void)setDriver:(WindowQuartzSubdriver *)drv { driver = drv; } @@ -850,17 +781,4 @@ bool WindowQuartzSubdriver::WindowResized() return true; } - -CocoaSubdriver *QZ_CreateWindowQuartzSubdriver(int width, int height, int bpp) -{ - WindowQuartzSubdriver *ret = new WindowQuartzSubdriver(); - - if (!ret->ChangeResolution(width, height, bpp)) { - delete ret; - return NULL; - } - - return ret; -} - #endif /* WITH_COCOA */ diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index f2890ec0f0..837532e9e0 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -12,7 +12,7 @@ #import -class CocoaSubdriver; +class WindowQuartzSubdriver; extern NSString *OTTDMainLaunchGameEngine; @@ -23,10 +23,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSWindow to cater our special needs */ @interface OTTD_CocoaWindow : NSWindow { - CocoaSubdriver *driver; + WindowQuartzSubdriver *driver; } -- (void)setDriver:(CocoaSubdriver*)drv; +- (void)setDriver:(WindowQuartzSubdriver *)drv; - (void)miniaturize:(id)sender; - (void)display; @@ -39,10 +39,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSView to fix Quartz rendering and mouse awareness */ @interface OTTD_CocoaView : NSView { - CocoaSubdriver *driver; + WindowQuartzSubdriver *driver; NSTrackingRectTag trackingtag; } -- (void)setDriver:(CocoaSubdriver*)drv; +- (void)setDriver:(WindowQuartzSubdriver *)drv; - (void)drawRect:(NSRect)rect; - (BOOL)isOpaque; - (BOOL)acceptsFirstResponder; @@ -59,10 +59,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Delegate for our NSWindow to send ask for quit on close */ @interface OTTD_CocoaWindowDelegate : NSObject { - CocoaSubdriver *driver; + WindowQuartzSubdriver *driver; } -- (void)setDriver:(CocoaSubdriver*)drv; +- (void)setDriver:(WindowQuartzSubdriver *)drv; - (BOOL)windowShouldClose:(id)sender; - (void)windowDidEnterFullScreen:(NSNotification *)aNotification; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 8c16dd1ef6..256565b2b8 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -282,7 +282,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @implementation OTTD_CocoaWindow -- (void)setDriver:(CocoaSubdriver*)drv +- (void)setDriver:(WindowQuartzSubdriver *)drv { driver = drv; } @@ -404,7 +404,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) /** * Initialize the driver */ -- (void)setDriver:(CocoaSubdriver*)drv +- (void)setDriver:(WindowQuartzSubdriver *)drv { driver = drv; } @@ -810,7 +810,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) @implementation OTTD_CocoaWindowDelegate /** Initialize the video driver */ -- (void)setDriver:(CocoaSubdriver*)drv +- (void)setDriver:(WindowQuartzSubdriver *)drv { driver = drv; } From e6bea3961fa2245c6bc7bb268f9c9bffd4c22fff Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 10 Jan 2021 22:27:31 +0100 Subject: [PATCH 067/275] Change: [OSX] Replace screen resolution list with suggested window sizes. We never change the real screen resolution on OSX. As such, offering a list of resolutions is pointless. Instead of that, offer the user a list of commonly used window sizes up to the current screen size. --- src/video/cocoa/cocoa_v.h | 3 +- src/video/cocoa/cocoa_v.mm | 117 +++++++++++-------------------------- 2 files changed, 34 insertions(+), 86 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 2aca2034eb..a52cbb06e2 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -77,6 +77,7 @@ private: friend class WindowQuartzSubdriver; void GameSizeChanged(); + void UpdateVideoModes(); }; class FVideoDriver_Cocoa : public DriverFactoryBase { @@ -210,6 +211,4 @@ public: extern WindowQuartzSubdriver *_cocoa_subdriver; -uint QZ_ListModes(OTTD_Point *modes, uint max_modes, CGDirectDisplayID display_id, int display_depth); - #endif /* VIDEO_COCOA_H */ diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 5da0f55e31..77dbbd21f0 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -37,7 +37,6 @@ #include "../../core/math_func.hpp" #include "../../framerate_type.h" -#include #import /* for MAXPATHLEN */ /** @@ -59,87 +58,41 @@ bool _cocoa_video_started = false; WindowQuartzSubdriver *_cocoa_subdriver = NULL; -static bool ModeSorter(const OTTD_Point &p1, const OTTD_Point &p2) -{ - if (p1.x < p2.x) return true; - if (p1.x > p2.x) return false; - if (p1.y < p2.y) return true; - if (p1.y > p2.y) return false; - return false; -} - -static void QZ_GetDisplayModeInfo(CFArrayRef modes, CFIndex i, int &bpp, uint16 &width, uint16 &height) -{ - CGDisplayModeRef mode = static_cast(const_cast(CFArrayGetValueAtIndex(modes, i))); - - width = (uint16)CGDisplayModeGetWidth(mode); - height = (uint16)CGDisplayModeGetHeight(mode); - -#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11) - /* Extract bit depth from mode string. */ - CFAutoRelease pixEnc(CGDisplayModeCopyPixelEncoding(mode)); - if (CFStringCompare(pixEnc.get(), CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 32; - if (CFStringCompare(pixEnc.get(), CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 16; - if (CFStringCompare(pixEnc.get(), CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) bpp = 8; -#else - /* CGDisplayModeCopyPixelEncoding is deprecated on OSX 10.11+, but there are no 8 bpp modes anyway... */ - bpp = 32; -#endif -} - -uint QZ_ListModes(OTTD_Point *modes, uint max_modes, CGDirectDisplayID display_id, int device_depth) -{ - CFAutoRelease mode_list(CGDisplayCopyAllDisplayModes(display_id, nullptr)); - CFIndex num_modes = CFArrayGetCount(mode_list.get()); - - /* Build list of modes with the requested bpp */ - uint count = 0; - for (CFIndex i = 0; i < num_modes && count < max_modes; i++) { - int bpp; - uint16 width, height; - - QZ_GetDisplayModeInfo(mode_list.get(), i, bpp, width, height); - - if (bpp != device_depth) continue; - - /* Check if mode is already in the list */ - bool hasMode = false; - for (uint i = 0; i < count; i++) { - if (modes[i].x == width && modes[i].y == height) { - hasMode = true; - break; - } - } - - if (hasMode) continue; - - /* Add mode to the list */ - modes[count].x = width; - modes[count].y = height; - count++; - } - - /* Sort list smallest to largest */ - std::sort(modes, modes + count, ModeSorter); - - return count; -} +/** List of common display/window sizes. */ +static const Dimension _default_resolutions[] = { + { 640, 480 }, + { 800, 600 }, + { 1024, 768 }, + { 1152, 864 }, + { 1280, 800 }, + { 1280, 960 }, + { 1280, 1024 }, + { 1400, 1050 }, + { 1600, 1200 }, + { 1680, 1050 }, + { 1920, 1200 }, + { 2560, 1440 } +}; /** * Update the video modus. - * - * @pre _cocoa_subdriver != NULL */ -static void QZ_UpdateVideoModes() +void VideoDriver_Cocoa::UpdateVideoModes() { - assert(_cocoa_subdriver != NULL); - - OTTD_Point modes[32]; - uint count = _cocoa_subdriver->ListModes(modes, lengthof(modes)); - _resolutions.clear(); - for (uint i = 0; i < count; i++) { - _resolutions.emplace_back(modes[i].x, modes[i].y); + + if (_cocoa_subdriver != nullptr && _cocoa_subdriver->IsFullscreen()) { + /* Full screen, there is only one possible resolution. */ + NSSize screen = [ [ _cocoa_subdriver->window screen ] frame ].size; + _resolutions.emplace_back((uint)screen.width, (uint)screen.height); + } else { + /* Windowed; offer a selection of common window sizes up until the + * maximum usable screen space. This excludes the menu and dock areas. */ + NSSize maxSize = [ [ NSScreen mainScreen] visibleFrame ].size; + for (const auto &d : _default_resolutions) { + if (d.width < maxSize.width && d.height < maxSize.height) _resolutions.push_back(d); + } + _resolutions.emplace_back((uint)maxSize.width, (uint)maxSize.height); } } @@ -195,7 +148,7 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) if (_fullscreen) _cocoa_subdriver->ToggleFullscreen(_fullscreen); this->GameSizeChanged(); - QZ_UpdateVideoModes(); + this->UpdateVideoModes(); return NULL; } @@ -242,7 +195,6 @@ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) bool ret = _cocoa_subdriver->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth()); this->GameSizeChanged(); - QZ_UpdateVideoModes(); return ret; } @@ -257,7 +209,9 @@ bool VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) { assert(_cocoa_subdriver != NULL); - return _cocoa_subdriver->ToggleFullscreen(full_screen); + bool res = _cocoa_subdriver->ToggleFullscreen(full_screen); + this->UpdateVideoModes(); + return res; } /** @@ -668,11 +622,6 @@ void WindowQuartzSubdriver::UpdatePalette(uint first_color, uint num_colors) this->num_dirty_rects = MAX_DIRTY_RECTS; } -uint WindowQuartzSubdriver::ListModes(OTTD_Point *modes, uint max_modes) -{ - return QZ_ListModes(modes, max_modes, kCGDirectMainDisplay, this->buffer_depth); -} - bool WindowQuartzSubdriver::ChangeResolution(int w, int h, int bpp) { int old_width = this->window_width; From 88f6c7a9f353c3e78f30ddeaaeef91694af4d189 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 22 Jan 2021 22:29:46 +0100 Subject: [PATCH 068/275] Codechange: [OSX] Fold remaining Cocoa video subdriver into the main driver. --- src/video/cocoa/cocoa_v.h | 128 ++++++++----------- src/video/cocoa/cocoa_v.mm | 235 +++++++++++++++++------------------ src/video/cocoa/cocoa_wnd.h | 14 +-- src/video/cocoa/cocoa_wnd.mm | 10 +- src/video/cocoa/event.mm | 102 ++++++--------- 5 files changed, 210 insertions(+), 279 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index a52cbb06e2..adeadd3bef 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -18,9 +18,37 @@ extern bool _cocoa_video_started; class VideoDriver_Cocoa : public VideoDriver { private: - Dimension orig_res; ///< Saved window size for non-fullscreen mode. + Dimension orig_res; ///< Saved window size for non-fullscreen mode. + + int device_width; ///< Width of device in pixel + int device_height; ///< Height of device in pixel + int device_depth; ///< Colour depth of device in bit + + int window_width; ///< Current window width in pixel + int window_height; ///< Current window height in pixel + int window_pitch; + + int buffer_depth; ///< Colour depth of used frame buffer + void *pixel_buffer; ///< used for direct pixel access + void *window_buffer; ///< Colour translation from palette to screen + +# define MAX_DIRTY_RECTS 100 + Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles + int num_dirty_rects = MAX_DIRTY_RECTS; ///< Number of dirty rectangles + uint32 palette[256]; ///< Colour Palette public: + bool active; ///< Whether the window is visible + bool setup; + + id window; ///< Pointer to window object + id cocoaview; ///< Pointer to view object + CGColorSpaceRef color_space; ///< Window color space + CGContextRef cgcontext; ///< Context reference for Quartz subdriver + +public: + VideoDriver_Cocoa(); + const char *Start(const StringList ¶m) override; /** Stop the video driver */ @@ -70,26 +98,28 @@ public: /** Main game loop. */ void GameLoop(); // In event.mm. + /** Resize the window. + * @return whether the window was successfully resized + */ + bool WindowResized(); + + /** Convert local coordinate to window server (CoreGraphics) coordinate + * @param p local coordinates + * @return window driver coordinates + */ + CGPoint PrivateLocalToCG(NSPoint *p); + protected: Dimension GetScreenSize() const override; private: - friend class WindowQuartzSubdriver; + bool PollEvent(); // In event.mm. + void MouseMovedEvent(int x, int y); // In event.mm. + void WarpCursor(int x, int y); // In event.mm. void GameSizeChanged(); void UpdateVideoModes(); -}; -class FVideoDriver_Cocoa : public DriverFactoryBase { -public: - FVideoDriver_Cocoa() : DriverFactoryBase(Driver::DT_VIDEO, 10, "cocoa", "Cocoa Video Driver") {} - Driver *CreateInstance() const override { return new VideoDriver_Cocoa(); } -}; - - - -class WindowQuartzSubdriver { -private: /** * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. * @@ -103,48 +133,11 @@ private: void GetDeviceInfo(); bool SetVideoMode(int width, int height, int bpp); -public: - int device_width; ///< Width of device in pixel - int device_height; ///< Height of device in pixel - int device_depth; ///< Colour depth of device in bit - - int window_width; ///< Current window width in pixel - int window_height; ///< Current window height in pixel - int window_pitch; - - int buffer_depth; ///< Colour depth of used frame buffer - void *pixel_buffer; ///< used for direct pixel access - void *window_buffer; ///< Colour translation from palette to screen - -# define MAX_DIRTY_RECTS 100 - Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles - int num_dirty_rects; ///< Number of dirty rectangles - uint32 palette[256]; ///< Colour Palette - - bool active; ///< Whether the window is visible - bool setup; - - id window; ///< Pointer to window object - id cocoaview; ///< Pointer to view object - CGColorSpaceRef color_space; ///< Window color space - CGContextRef cgcontext; ///< Context reference for Quartz subdriver - - WindowQuartzSubdriver(); - ~WindowQuartzSubdriver(); - /** Draw window * @param force_update Whether to redraw unconditionally */ void Draw(bool force_update = false); - /** Mark dirty a screen region - * @param left x-coordinate of left border - * @param top y-coordinate of top border - * @param width width or dirty rectangle - * @param height height of dirty rectangle - */ - void MakeDirty(int left, int top, int width, int height); - /** Update the palette */ void UpdatePalette(uint first_color, uint num_colors); @@ -162,32 +155,11 @@ public: */ bool IsFullscreen(); - /** Toggle between fullscreen and windowed mode - * @return whether switch was successful - */ - bool ToggleFullscreen(bool fullscreen); - - /** Return the width of the current view - * @return width of the current view - */ - int GetWidth() { return window_width; } - - /** Return the height of the current view - * @return height of the current view - */ - int GetHeight() { return window_height; } - /** Return the current pixel buffer * @return pixelbuffer */ void *GetPixelBuffer() { return buffer_depth == 8 ? pixel_buffer : window_buffer; } - /** Convert local coordinate to window server (CoreGraphics) coordinate - * @param p local coordinates - * @return window driver coordinates - */ - CGPoint PrivateLocalToCG(NSPoint *p); - /** Return the mouse location * @param event UI event * @return mouse location as NSPoint @@ -200,15 +172,13 @@ public: */ bool MouseIsInsideView(NSPoint *pt); - /** Return whether the window is active (visible) */ - bool IsActive() { return active; } - - /** Resize the window. - * @return whether the window was successfully resized - */ - bool WindowResized(); + void CheckPaletteAnim(); }; -extern WindowQuartzSubdriver *_cocoa_subdriver; +class FVideoDriver_Cocoa : public DriverFactoryBase { +public: + FVideoDriver_Cocoa() : DriverFactoryBase(Driver::DT_VIDEO, 10, "cocoa", "Cocoa Video Driver") {} + Driver *CreateInstance() const override { return new VideoDriver_Cocoa(); } +}; #endif /* VIDEO_COCOA_H */ diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 77dbbd21f0..9d1fe37820 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -55,7 +55,6 @@ #endif bool _cocoa_video_started = false; -WindowQuartzSubdriver *_cocoa_subdriver = NULL; /** List of common display/window sizes. */ @@ -74,31 +73,28 @@ static const Dimension _default_resolutions[] = { { 2560, 1440 } }; -/** - * Update the video modus. - */ -void VideoDriver_Cocoa::UpdateVideoModes() -{ - _resolutions.clear(); - - if (_cocoa_subdriver != nullptr && _cocoa_subdriver->IsFullscreen()) { - /* Full screen, there is only one possible resolution. */ - NSSize screen = [ [ _cocoa_subdriver->window screen ] frame ].size; - _resolutions.emplace_back((uint)screen.width, (uint)screen.height); - } else { - /* Windowed; offer a selection of common window sizes up until the - * maximum usable screen space. This excludes the menu and dock areas. */ - NSSize maxSize = [ [ NSScreen mainScreen] visibleFrame ].size; - for (const auto &d : _default_resolutions) { - if (d.width < maxSize.width && d.height < maxSize.height) _resolutions.push_back(d); - } - _resolutions.emplace_back((uint)maxSize.width, (uint)maxSize.height); - } -} - - static FVideoDriver_Cocoa iFVideoDriver_Cocoa; + +VideoDriver_Cocoa::VideoDriver_Cocoa() +{ + this->window_width = 0; + this->window_height = 0; + this->buffer_depth = 0; + this->window_buffer = nullptr; + this->pixel_buffer = nullptr; + this->active = false; + this->setup = false; + + this->window = nil; + this->cocoaview = nil; + + this->color_space = nullptr; + this->cgcontext = nullptr; + + this->num_dirty_rects = MAX_DIRTY_RECTS; +} + /** * Stop the cocoa video subdriver. */ @@ -108,8 +104,14 @@ void VideoDriver_Cocoa::Stop() CocoaExitApplication(); - delete _cocoa_subdriver; - _cocoa_subdriver = nullptr; + /* Release window mode resources */ + if (this->window != nil) [ this->window close ]; + + CGContextRelease(this->cgcontext); + + CGColorSpaceRelease(this->color_space); + free(this->window_buffer); + free(this->pixel_buffer); _cocoa_video_started = false; } @@ -139,18 +141,17 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) return "The cocoa quartz subdriver only supports 8 and 32 bpp."; } - _cocoa_subdriver = new WindowQuartzSubdriver(); - if (!_cocoa_subdriver->ChangeResolution(width, height, bpp)) { + if (!this->ChangeResolution(width, height, bpp)) { Stop(); return "Could not create subdriver"; } - if (_fullscreen) _cocoa_subdriver->ToggleFullscreen(_fullscreen); + if (_fullscreen) this->ToggleFullscreen(_fullscreen); this->GameSizeChanged(); this->UpdateVideoModes(); - return NULL; + return nullptr; } /** @@ -163,9 +164,13 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) */ void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height) { - assert(_cocoa_subdriver != NULL); - - _cocoa_subdriver->MakeDirty(left, top, width, height); + if (this->num_dirty_rects < MAX_DIRTY_RECTS) { + dirty_rects[this->num_dirty_rects].left = left; + dirty_rects[this->num_dirty_rects].top = top; + dirty_rects[this->num_dirty_rects].right = left + width; + dirty_rects[this->num_dirty_rects].bottom = top + height; + } + this->num_dirty_rects++; } /** @@ -190,12 +195,8 @@ void VideoDriver_Cocoa::MainLoop() */ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) { - assert(_cocoa_subdriver != NULL); - - bool ret = _cocoa_subdriver->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth()); - + bool ret = this->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth()); this->GameSizeChanged(); - return ret; } @@ -207,11 +208,15 @@ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) */ bool VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) { - assert(_cocoa_subdriver != NULL); + if (this->IsFullscreen() == full_screen) return true; - bool res = _cocoa_subdriver->ToggleFullscreen(full_screen); - this->UpdateVideoModes(); - return res; + if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) { + [ this->window performSelector:@selector(toggleFullScreen:) withObject:this->window ]; + this->UpdateVideoModes(); + return true; + } + + return false; } /** @@ -229,7 +234,7 @@ bool VideoDriver_Cocoa::AfterBlitterChange() */ void VideoDriver_Cocoa::EditBoxLostFocus() { - if (_cocoa_subdriver != NULL) [ [ _cocoa_subdriver->cocoaview inputContext ] discardMarkedText ]; + [ [ this->cocoaview inputContext ] discardMarkedText ]; /* Clear any marked string from the current edit box. */ HandleTextInput(NULL, true); } @@ -248,16 +253,14 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const */ void VideoDriver_Cocoa::GameSizeChanged() { - if (_cocoa_subdriver == nullptr) return; - /* Tell the game that the resolution has changed */ - _screen.width = _cocoa_subdriver->GetWidth(); - _screen.height = _cocoa_subdriver->GetHeight(); - _screen.pitch = _cocoa_subdriver->GetWidth(); - _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer(); + _screen.width = this->window_width; + _screen.height = this->window_height; + _screen.pitch = this->window_width; + _screen.dst_ptr = this->GetPixelBuffer(); /* Store old window size if we entered fullscreen mode. */ - bool fullscreen = _cocoa_subdriver->IsFullscreen(); + bool fullscreen = this->IsFullscreen(); if (fullscreen && !_fullscreen) this->orig_res = _cur_resolution; _fullscreen = fullscreen; @@ -266,18 +269,16 @@ void VideoDriver_Cocoa::GameSizeChanged() ::GameSizeChanged(); } -class WindowQuartzSubdriver; - /* Subclass of OTTD_CocoaView to fix Quartz rendering */ @interface OTTD_QuartzView : OTTD_CocoaView -- (void)setDriver:(WindowQuartzSubdriver *)drv; +- (void)setDriver:(VideoDriver_Cocoa *)drv; - (void)drawRect:(NSRect)invalidRect; @end @implementation OTTD_QuartzView -- (void)setDriver:(WindowQuartzSubdriver *)drv +- (void)setDriver:(VideoDriver_Cocoa *)drv { driver = drv; } @@ -360,7 +361,29 @@ class WindowQuartzSubdriver; @end -void WindowQuartzSubdriver::GetDeviceInfo() +/** + * Update the video modus. + */ +void VideoDriver_Cocoa::UpdateVideoModes() +{ + _resolutions.clear(); + + if (this->IsFullscreen()) { + /* Full screen, there is only one possible resolution. */ + NSSize screen = [ [ this->window screen ] frame ].size; + _resolutions.emplace_back((uint)screen.width, (uint)screen.height); + } else { + /* Windowed; offer a selection of common window sizes up until the + * maximum usable screen space. This excludes the menu and dock areas. */ + NSSize maxSize = [ [ NSScreen mainScreen] visibleFrame ].size; + for (const auto &d : _default_resolutions) { + if (d.width < maxSize.width && d.height < maxSize.height) _resolutions.push_back(d); + } + _resolutions.emplace_back((uint)maxSize.width, (uint)maxSize.height); + } +} + +void VideoDriver_Cocoa::GetDeviceInfo() { /* Initialize the video settings; this data persists between mode switches * and gather some information that is useful to know about the display */ @@ -375,27 +398,12 @@ void WindowQuartzSubdriver::GetDeviceInfo() CGDisplayModeRelease(cur_mode); } -bool WindowQuartzSubdriver::IsFullscreen() +bool VideoDriver_Cocoa::IsFullscreen() { return this->window != nil && ([ this->window styleMask ] & NSWindowStyleMaskFullScreen) != 0; } -/** Switch to full screen mode on OSX 10.7 - * @return Whether we switched to full screen - */ -bool WindowQuartzSubdriver::ToggleFullscreen(bool fullscreen) -{ - if (this->IsFullscreen() == fullscreen) return true; - - if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) { - [ this->window performSelector:@selector(toggleFullScreen:) withObject:this->window ]; - return true; - } - - return false; -} - -bool WindowQuartzSubdriver::SetVideoMode(int width, int height, int bpp) +bool VideoDriver_Cocoa::SetVideoMode(int width, int height, int bpp) { this->setup = true; this->GetDeviceInfo(); @@ -508,7 +516,7 @@ bool WindowQuartzSubdriver::SetVideoMode(int width, int height, int bpp) return ret; } -void WindowQuartzSubdriver::BlitIndexedToView32(int left, int top, int right, int bottom) +void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bottom) { const uint32 *pal = this->palette; const uint8 *src = (uint8*)this->pixel_buffer; @@ -524,37 +532,7 @@ void WindowQuartzSubdriver::BlitIndexedToView32(int left, int top, int right, in } -WindowQuartzSubdriver::WindowQuartzSubdriver() -{ - this->window_width = 0; - this->window_height = 0; - this->buffer_depth = 0; - this->window_buffer = NULL; - this->pixel_buffer = NULL; - this->active = false; - this->setup = false; - - this->window = nil; - this->cocoaview = nil; - - this->cgcontext = NULL; - - this->num_dirty_rects = MAX_DIRTY_RECTS; -} - -WindowQuartzSubdriver::~WindowQuartzSubdriver() -{ - /* Release window mode resources */ - if (this->window != nil) [ this->window close ]; - - CGContextRelease(this->cgcontext); - - CGColorSpaceRelease(this->color_space); - free(this->window_buffer); - free(this->pixel_buffer); -} - -void WindowQuartzSubdriver::Draw(bool force_update) +void VideoDriver_Cocoa::Draw(bool force_update) { PerformanceMeasurer framerate(PFE_VIDEO); @@ -596,18 +574,7 @@ void WindowQuartzSubdriver::Draw(bool force_update) this->num_dirty_rects = 0; } -void WindowQuartzSubdriver::MakeDirty(int left, int top, int width, int height) -{ - if (this->num_dirty_rects < MAX_DIRTY_RECTS) { - dirty_rects[this->num_dirty_rects].left = left; - dirty_rects[this->num_dirty_rects].top = top; - dirty_rects[this->num_dirty_rects].right = left + width; - dirty_rects[this->num_dirty_rects].bottom = top + height; - } - this->num_dirty_rects++; -} - -void WindowQuartzSubdriver::UpdatePalette(uint first_color, uint num_colors) +void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) { if (this->buffer_depth != 8) return; @@ -622,7 +589,7 @@ void WindowQuartzSubdriver::UpdatePalette(uint first_color, uint num_colors) this->num_dirty_rects = MAX_DIRTY_RECTS; } -bool WindowQuartzSubdriver::ChangeResolution(int w, int h, int bpp) +bool VideoDriver_Cocoa::ChangeResolution(int w, int h, int bpp) { int old_width = this->window_width; int old_height = this->window_height; @@ -635,7 +602,7 @@ bool WindowQuartzSubdriver::ChangeResolution(int w, int h, int bpp) } /* Convert local coordinate to window server (CoreGraphics) coordinate */ -CGPoint WindowQuartzSubdriver::PrivateLocalToCG(NSPoint *p) +CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) { p->y = this->window_height - p->y; @@ -651,7 +618,7 @@ CGPoint WindowQuartzSubdriver::PrivateLocalToCG(NSPoint *p) return cgp; } -NSPoint WindowQuartzSubdriver::GetMouseLocation(NSEvent *event) +NSPoint VideoDriver_Cocoa::GetMouseLocation(NSEvent *event) { NSPoint pt; @@ -666,7 +633,7 @@ NSPoint WindowQuartzSubdriver::GetMouseLocation(NSEvent *event) return pt; } -bool WindowQuartzSubdriver::MouseIsInsideView(NSPoint *pt) +bool VideoDriver_Cocoa::MouseIsInsideView(NSPoint *pt) { return [ cocoaview mouse:*pt inRect:[ this->cocoaview bounds ] ]; } @@ -682,7 +649,7 @@ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height) } } -bool WindowQuartzSubdriver::WindowResized() +bool VideoDriver_Cocoa::WindowResized() { if (this->window == nil || this->cocoaview == nil) return true; @@ -722,7 +689,7 @@ bool WindowQuartzSubdriver::WindowResized() } } - static_cast(VideoDriver::GetInstance())->GameSizeChanged(); + this->GameSizeChanged(); /* Redraw screen */ this->num_dirty_rects = MAX_DIRTY_RECTS; @@ -730,4 +697,28 @@ bool WindowQuartzSubdriver::WindowResized() return true; } +void VideoDriver_Cocoa::CheckPaletteAnim() +{ + if (_cur_palette.count_dirty != 0) { + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + this->UpdatePalette(_cur_palette.first_dirty, _cur_palette.count_dirty); + break; + + case Blitter::PALETTE_ANIMATION_BLITTER: + blitter->PaletteAnimate(_cur_palette); + break; + + case Blitter::PALETTE_ANIMATION_NONE: + break; + + default: + NOT_REACHED(); + } + _cur_palette.count_dirty = 0; + } +} + #endif /* WITH_COCOA */ diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 837532e9e0..35dcaa7c07 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -12,7 +12,7 @@ #import -class WindowQuartzSubdriver; +class VideoDriver_Cocoa; extern NSString *OTTDMainLaunchGameEngine; @@ -23,10 +23,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSWindow to cater our special needs */ @interface OTTD_CocoaWindow : NSWindow { - WindowQuartzSubdriver *driver; + VideoDriver_Cocoa *driver; } -- (void)setDriver:(WindowQuartzSubdriver *)drv; +- (void)setDriver:(VideoDriver_Cocoa *)drv; - (void)miniaturize:(id)sender; - (void)display; @@ -39,10 +39,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSView to fix Quartz rendering and mouse awareness */ @interface OTTD_CocoaView : NSView { - WindowQuartzSubdriver *driver; + VideoDriver_Cocoa *driver; NSTrackingRectTag trackingtag; } -- (void)setDriver:(WindowQuartzSubdriver *)drv; +- (void)setDriver:(VideoDriver_Cocoa *)drv; - (void)drawRect:(NSRect)rect; - (BOOL)isOpaque; - (BOOL)acceptsFirstResponder; @@ -59,10 +59,10 @@ extern NSString *OTTDMainLaunchGameEngine; /** Delegate for our NSWindow to send ask for quit on close */ @interface OTTD_CocoaWindowDelegate : NSObject { - WindowQuartzSubdriver *driver; + VideoDriver_Cocoa *driver; } -- (void)setDriver:(WindowQuartzSubdriver *)drv; +- (void)setDriver:(VideoDriver_Cocoa *)drv; - (BOOL)windowShouldClose:(id)sender; - (void)windowDidEnterFullScreen:(NSNotification *)aNotification; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 256565b2b8..ff222ea425 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -70,7 +70,7 @@ static OTTDMain *_ottd_main; - (void)launchGameEngine: (NSNotification*) note { /* Setup cursor for the current _game_mode. */ - [ _cocoa_subdriver->cocoaview resetCursorRects ]; + [ static_cast(VideoDriver::GetInstance())->cocoaview resetCursorRects ]; /* Hand off to main application code. */ static_cast(VideoDriver::GetInstance())->GameLoop(); @@ -282,7 +282,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @implementation OTTD_CocoaWindow -- (void)setDriver:(WindowQuartzSubdriver *)drv +- (void)setDriver:(VideoDriver_Cocoa *)drv { driver = drv; } @@ -404,7 +404,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) /** * Initialize the driver */ -- (void)setDriver:(WindowQuartzSubdriver *)drv +- (void)setDriver:(VideoDriver_Cocoa *)drv { driver = drv; } @@ -491,7 +491,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) */ - (void)mouseExited:(NSEvent *)theEvent { - if (_cocoa_subdriver != NULL) UndrawMouseCursor(); + if (driver->window != nil) UndrawMouseCursor(); _cursor.in_window = false; } @@ -810,7 +810,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) @implementation OTTD_CocoaWindowDelegate /** Initialize the video driver */ -- (void)setDriver:(WindowQuartzSubdriver *)drv +- (void)setDriver:(VideoDriver_Cocoa *)drv { driver = drv; } diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 8a43945f5d..86ffd9145a 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -73,15 +73,13 @@ static uint32 GetTick() return tim.tv_usec / 1000 + tim.tv_sec * 1000; } -static void QZ_WarpCursor(int x, int y) +void VideoDriver_Cocoa::WarpCursor(int x, int y) { - assert(_cocoa_subdriver != NULL); - /* Only allow warping when in foreground */ if (![ NSApp isActive ]) return; NSPoint p = NSMakePoint(x, y); - CGPoint cgp = _cocoa_subdriver->PrivateLocalToCG(&p); + CGPoint cgp = this->PrivateLocalToCG(&p); /* Do the actual warp */ CGWarpMouseCursorPosition(cgp); @@ -90,32 +88,6 @@ static void QZ_WarpCursor(int x, int y) } -static void QZ_CheckPaletteAnim() -{ - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - _cocoa_subdriver->UpdatePalette(_cur_palette.first_dirty, _cur_palette.count_dirty); - break; - - case Blitter::PALETTE_ANIMATION_BLITTER: - blitter->PaletteAnimate(_cur_palette); - break; - - case Blitter::PALETTE_ANIMATION_NONE: - break; - - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; - } -} - - - struct VkMapping { unsigned short vk_from; byte map_to; @@ -343,10 +315,10 @@ static void QZ_DoUnsidedModifiers(unsigned int newMods) _current_mods = newMods; } -static void QZ_MouseMovedEvent(int x, int y) +void VideoDriver_Cocoa::MouseMovedEvent(int x, int y) { if (_cursor.UpdateCursorPosition(x, y, false)) { - QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y); + this->WarpCursor(_cursor.pos.x, _cursor.pos.y); } HandleMouseEvents(); } @@ -380,10 +352,8 @@ static void QZ_MouseButtonEvent(int button, BOOL down) -static bool QZ_PollEvent() +bool VideoDriver_Cocoa::PollEvent() { - assert(_cocoa_subdriver != NULL); - #ifdef _DEBUG uint32 et0 = GetTick(); #endif @@ -395,7 +365,7 @@ static bool QZ_PollEvent() #endif if (event == nil) return false; - if (!_cocoa_subdriver->IsActive()) { + if (!this->active) { [ NSApp sendEvent:event ]; return true; } @@ -408,18 +378,18 @@ static bool QZ_PollEvent() case NSMouseMoved: case NSOtherMouseDragged: case NSLeftMouseDragged: - pt = _cocoa_subdriver->GetMouseLocation(event); - if (!_cocoa_subdriver->MouseIsInsideView(&pt) && !_emulating_right_button) { + pt = this->GetMouseLocation(event); + if (!this->MouseIsInsideView(&pt) && !_emulating_right_button) { [ NSApp sendEvent:event ]; break; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); break; case NSRightMouseDragged: - pt = _cocoa_subdriver->GetMouseLocation(event); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + pt = this->GetMouseLocation(event); + this->MouseMovedEvent((int)pt.x, (int)pt.y); break; case NSLeftMouseDown: @@ -428,13 +398,13 @@ static bool QZ_PollEvent() if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; - pt = _cocoa_subdriver->GetMouseLocation(event); + pt = this->GetMouseLocation(event); - if (!([ event modifierFlags ] & keymask) || !_cocoa_subdriver->MouseIsInsideView(&pt)) { + if (!([ event modifierFlags ] & keymask) || !this->MouseIsInsideView(&pt)) { [ NSApp sendEvent:event ]; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); /* Right mouse button emulation */ if ([ event modifierFlags ] & keymask) { @@ -448,9 +418,9 @@ static bool QZ_PollEvent() case NSLeftMouseUp: [ NSApp sendEvent:event ]; - pt = _cocoa_subdriver->GetMouseLocation(event); + pt = this->GetMouseLocation(event); - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); /* Right mouse button emulation */ if (_emulating_right_button) { @@ -462,24 +432,24 @@ static bool QZ_PollEvent() break; case NSRightMouseDown: - pt = _cocoa_subdriver->GetMouseLocation(event); - if (!_cocoa_subdriver->MouseIsInsideView(&pt)) { + pt = this->GetMouseLocation(event); + if (!this->MouseIsInsideView(&pt)) { [ NSApp sendEvent:event ]; break; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); QZ_MouseButtonEvent(1, YES); break; case NSRightMouseUp: - pt = _cocoa_subdriver->GetMouseLocation(event); - if (!_cocoa_subdriver->MouseIsInsideView(&pt)) { + pt = this->GetMouseLocation(event); + if (!this->MouseIsInsideView(&pt)) { [ NSApp sendEvent:event ]; break; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); QZ_MouseButtonEvent(1, NO); break; @@ -492,7 +462,7 @@ static bool QZ_PollEvent() break; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); QZ_MouseButtonEvent([ event buttonNumber ], YES); break; @@ -503,7 +473,7 @@ static bool QZ_PollEvent() break; } - QZ_MouseMovedEvent((int)pt.x, (int)pt.y); + this->MouseMovedEvent((int)pt.x, (int)pt.y); QZ_MouseButtonEvent([ event buttonNumber ], NO); break; #endif @@ -524,7 +494,7 @@ static bool QZ_PollEvent() unsigned short unicode = [ chars length ] > 0 ? [ chars characterAtIndex:0 ] : 0; if (EditBoxInGlobalFocus()) { if (QZ_KeyEvent([ event keyCode ], unicode, YES)) { - [ _cocoa_subdriver->cocoaview interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; + [ this->cocoaview interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; } } else { QZ_KeyEvent([ event keyCode ], unicode, YES); @@ -629,32 +599,32 @@ void VideoDriver_Cocoa::GameLoop() #endif DisplaySplashImage(); - QZ_CheckPaletteAnim(); - _cocoa_subdriver->Draw(true); + this->CheckPaletteAnim(); + this->Draw(true); CSleep(1); for (int i = 0; i < 2; i++) ::GameLoop(); UpdateWindows(); - QZ_CheckPaletteAnim(); - _cocoa_subdriver->Draw(); + this->CheckPaletteAnim(); + this->Draw(); CSleep(1); /* Set the proper OpenTTD palette which got spoilt by the splash * image when using 8bpp blitter */ GfxInitPalettes(); - QZ_CheckPaletteAnim(); - _cocoa_subdriver->Draw(true); + this->CheckPaletteAnim(); + this->Draw(true); for (;;) { uint32 prev_cur_ticks = cur_ticks; // to check for wrapping InteractiveRandom(); // randomness - while (QZ_PollEvent()) {} + while (this->PollEvent()) {} if (_exit_game) { /* Restore saved resolution if in fullscreen mode. */ - if (_cocoa_subdriver->IsFullscreen()) _cur_resolution = this->orig_res; + if (this->IsFullscreen()) _cur_resolution = this->orig_res; break; } @@ -685,8 +655,8 @@ void VideoDriver_Cocoa::GameLoop() ::GameLoop(); UpdateWindows(); - QZ_CheckPaletteAnim(); - _cocoa_subdriver->Draw(); + this->CheckPaletteAnim(); + this->Draw(); } else { #ifdef _DEBUG uint32 st0 = GetTick(); @@ -697,7 +667,7 @@ void VideoDriver_Cocoa::GameLoop() #endif NetworkDrawChatMessage(); DrawMouseCursor(); - _cocoa_subdriver->Draw(); + this->Draw(); } } From 13134f9d64fb873ab1ee0cca2cc4c4fa3c64a44a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 11 Feb 2021 22:54:43 +0100 Subject: [PATCH 069/275] Codechange: [OSX] Replace #define with modern code. --- src/video/cocoa/cocoa_v.h | 5 +++-- src/video/cocoa/cocoa_v.mm | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index adeadd3bef..70adb18b5c 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -32,9 +32,10 @@ private: void *pixel_buffer; ///< used for direct pixel access void *window_buffer; ///< Colour translation from palette to screen -# define MAX_DIRTY_RECTS 100 + static const int MAX_DIRTY_RECTS = 100; + Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles - int num_dirty_rects = MAX_DIRTY_RECTS; ///< Number of dirty rectangles + uint num_dirty_rects; ///< Number of dirty rectangles uint32 palette[256]; ///< Colour Palette public: diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 9d1fe37820..9e52cce01f 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -92,7 +92,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa() this->color_space = nullptr; this->cgcontext = nullptr; - this->num_dirty_rects = MAX_DIRTY_RECTS; + this->num_dirty_rects = lengthof(this->dirty_rects); } /** @@ -164,7 +164,7 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) */ void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height) { - if (this->num_dirty_rects < MAX_DIRTY_RECTS) { + if (this->num_dirty_rects < lengthof(this->dirty_rects)) { dirty_rects[this->num_dirty_rects].left = left; dirty_rects[this->num_dirty_rects].top = top; dirty_rects[this->num_dirty_rects].right = left + width; @@ -539,7 +539,7 @@ void VideoDriver_Cocoa::Draw(bool force_update) /* Check if we need to do anything */ if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return; - if (this->num_dirty_rects >= MAX_DIRTY_RECTS) { + if (this->num_dirty_rects >= lengthof(this->dirty_rects)) { this->num_dirty_rects = 1; this->dirty_rects[0].left = 0; this->dirty_rects[0].top = 0; @@ -548,7 +548,7 @@ void VideoDriver_Cocoa::Draw(bool force_update) } /* Build the region of dirty rectangles */ - for (int i = 0; i < this->num_dirty_rects; i++) { + for (uint i = 0; i < this->num_dirty_rects; i++) { /* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */ if (this->buffer_depth == 8) { BlitIndexedToView32( @@ -586,7 +586,7 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) this->palette[i] = clr; } - this->num_dirty_rects = MAX_DIRTY_RECTS; + this->num_dirty_rects = lengthof(this->dirty_rects); } bool VideoDriver_Cocoa::ChangeResolution(int w, int h, int bpp) @@ -692,7 +692,7 @@ bool VideoDriver_Cocoa::WindowResized() this->GameSizeChanged(); /* Redraw screen */ - this->num_dirty_rects = MAX_DIRTY_RECTS; + this->num_dirty_rects = lengthof(this->dirty_rects); return true; } From 8ced72ab10b12a33ef5e71f8b346f63a0db0f862 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 24 Jan 2021 13:12:55 +0100 Subject: [PATCH 070/275] Codechange: [OSX] Inline some functions that are used in only one place. --- src/video/cocoa/cocoa_v.h | 15 --------------- src/video/cocoa/cocoa_v.mm | 32 ++++++++++++++------------------ src/video/cocoa/event.mm | 26 +++++++++----------------- 3 files changed, 23 insertions(+), 50 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 70adb18b5c..bae0f52898 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -22,7 +22,6 @@ private: int device_width; ///< Width of device in pixel int device_height; ///< Height of device in pixel - int device_depth; ///< Colour depth of device in bit int window_width; ///< Current window width in pixel int window_height; ///< Current window height in pixel @@ -142,25 +141,11 @@ private: /** Update the palette */ void UpdatePalette(uint first_color, uint num_colors); - uint ListModes(OTTD_Point *modes, uint max_modes); - - /** Change window resolution - * @param w New window width - * @param h New window height - * @return Whether change was successful - */ - bool ChangeResolution(int w, int h, int bpp); - /** Are we in fullscreen mode * @return whether fullscreen mode is currently used */ bool IsFullscreen(); - /** Return the current pixel buffer - * @return pixelbuffer - */ - void *GetPixelBuffer() { return buffer_depth == 8 ? pixel_buffer : window_buffer; } - /** Return the mouse location * @param event UI event * @return mouse location as NSPoint diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 9e52cce01f..3350e32b8c 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -141,7 +141,7 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) return "The cocoa quartz subdriver only supports 8 and 32 bpp."; } - if (!this->ChangeResolution(width, height, bpp)) { + if (!this->SetVideoMode(width, height, bpp)) { Stop(); return "Could not create subdriver"; } @@ -195,9 +195,17 @@ void VideoDriver_Cocoa::MainLoop() */ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) { - bool ret = this->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth()); - this->GameSizeChanged(); - return ret; + int old_width = this->window_width; + int old_height = this->window_height; + int old_bpp = this->buffer_depth; + + if (this->SetVideoMode(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth())) { + this->GameSizeChanged(); + return true; + } + + if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height, old_bpp); + return false; } /** @@ -257,7 +265,7 @@ void VideoDriver_Cocoa::GameSizeChanged() _screen.width = this->window_width; _screen.height = this->window_height; _screen.pitch = this->window_width; - _screen.dst_ptr = this->GetPixelBuffer(); + _screen.dst_ptr = this->buffer_depth == 8 ? this->pixel_buffer : this->window_buffer; /* Store old window size if we entered fullscreen mode. */ bool fullscreen = this->IsFullscreen(); @@ -508,7 +516,7 @@ bool VideoDriver_Cocoa::SetVideoMode(int width, int height, int bpp) if (this->color_space == nullptr) this->color_space = CGColorSpaceCreateDeviceRGB(); if (this->color_space == nullptr) error("Could not get a valid colour space for drawing."); - bool ret = WindowResized(); + bool ret = this->WindowResized(); this->UpdatePalette(0, 256); this->setup = false; @@ -589,18 +597,6 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) this->num_dirty_rects = lengthof(this->dirty_rects); } -bool VideoDriver_Cocoa::ChangeResolution(int w, int h, int bpp) -{ - int old_width = this->window_width; - int old_height = this->window_height; - int old_bpp = this->buffer_depth; - - if (this->SetVideoMode(w, h, bpp)) return true; - if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height, old_bpp); - - return false; -} - /* Convert local coordinate to window server (CoreGraphics) coordinate */ CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) { diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 86ffd9145a..858cd51ad5 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -73,21 +73,6 @@ static uint32 GetTick() return tim.tv_usec / 1000 + tim.tv_sec * 1000; } -void VideoDriver_Cocoa::WarpCursor(int x, int y) -{ - /* Only allow warping when in foreground */ - if (![ NSApp isActive ]) return; - - NSPoint p = NSMakePoint(x, y); - CGPoint cgp = this->PrivateLocalToCG(&p); - - /* Do the actual warp */ - CGWarpMouseCursorPosition(cgp); - /* this is the magic call that fixes cursor "freezing" after warp */ - CGAssociateMouseAndMouseCursorPosition(true); -} - - struct VkMapping { unsigned short vk_from; byte map_to; @@ -317,8 +302,15 @@ static void QZ_DoUnsidedModifiers(unsigned int newMods) void VideoDriver_Cocoa::MouseMovedEvent(int x, int y) { - if (_cursor.UpdateCursorPosition(x, y, false)) { - this->WarpCursor(_cursor.pos.x, _cursor.pos.y); + if (_cursor.UpdateCursorPosition(x, y, false) && [ NSApp isActive ]) { + /* Warping cursor when in foreground */ + NSPoint p = NSMakePoint(_cursor.pos.x, _cursor.pos.y); + CGPoint cgp = this->PrivateLocalToCG(&p); + + /* Do the actual warp */ + CGWarpMouseCursorPosition(cgp); + /* this is the magic call that fixes cursor "freezing" after warp */ + CGAssociateMouseAndMouseCursorPosition(true); } HandleMouseEvents(); } From 0eff7de6594b0b0cb451a992287239b04eb66fc4 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 24 Jan 2021 13:13:25 +0100 Subject: [PATCH 071/275] Cleanup: [OSX] Doxygen comment style in video driver. --- src/video/cocoa/cocoa_v.h | 92 ++++++-------------------------------- src/video/cocoa/cocoa_v.mm | 37 ++++++++++++++- 2 files changed, 48 insertions(+), 81 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index bae0f52898..f9920c20e4 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -50,47 +50,18 @@ public: VideoDriver_Cocoa(); const char *Start(const StringList ¶m) override; - - /** Stop the video driver */ void Stop() override; - - /** Mark dirty a screen region - * @param left x-coordinate of left border - * @param top y-coordinate of top border - * @param width width or dirty rectangle - * @param height height of dirty rectangle - */ - void MakeDirty(int left, int top, int width, int height) override; - - /** Programme main loop */ void MainLoop() override; - /** Change window resolution - * @param w New window width - * @param h New window height - * @return Whether change was successful - */ - bool ChangeResolution(int w, int h) override; - - /** Set a new window mode - * @param fullscreen Whether to set fullscreen mode or not - * @return Whether changing the screen mode was successful - */ - bool ToggleFullscreen(bool fullscreen) override; - - /** Callback invoked after the blitter was changed. - * @return True if no error. - */ + void MakeDirty(int left, int top, int width, int height) override; bool AfterBlitterChange() override; - /** - * An edit box lost the input focus. Abort character compositing if necessary. - */ + bool ChangeResolution(int w, int h) override; + bool ToggleFullscreen(bool fullscreen) override; + void EditBoxLostFocus() override; - /** Return driver name - * @return driver name - */ + /** Return driver name */ const char *GetName() const override { return "cocoa"; } /* --- The following methods should be private, but can't be due to Obj-C limitations. --- */ @@ -98,67 +69,30 @@ public: /** Main game loop. */ void GameLoop(); // In event.mm. - /** Resize the window. - * @return whether the window was successfully resized - */ bool WindowResized(); - /** Convert local coordinate to window server (CoreGraphics) coordinate - * @param p local coordinates - * @return window driver coordinates - */ - CGPoint PrivateLocalToCG(NSPoint *p); - protected: Dimension GetScreenSize() const override; private: + NSPoint GetMouseLocation(NSEvent *event); + bool MouseIsInsideView(NSPoint *pt); + CGPoint PrivateLocalToCG(NSPoint *p); bool PollEvent(); // In event.mm. void MouseMovedEvent(int x, int y); // In event.mm. - void WarpCursor(int x, int y); // In event.mm. + bool IsFullscreen(); void GameSizeChanged(); + void UpdateVideoModes(); - - /** - * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. - * - * @param left The x coord for the left edge of the box to blit. - * @param top The y coord for the top edge of the box to blit. - * @param right The x coord for the right edge of the box to blit. - * @param bottom The y coord for the bottom edge of the box to blit. - */ - void BlitIndexedToView32(int left, int top, int right, int bottom); - void GetDeviceInfo(); bool SetVideoMode(int width, int height, int bpp); - /** Draw window - * @param force_update Whether to redraw unconditionally - */ - void Draw(bool force_update = false); - - /** Update the palette */ void UpdatePalette(uint first_color, uint num_colors); - - /** Are we in fullscreen mode - * @return whether fullscreen mode is currently used - */ - bool IsFullscreen(); - - /** Return the mouse location - * @param event UI event - * @return mouse location as NSPoint - */ - NSPoint GetMouseLocation(NSEvent *event); - - /** Return whether the mouse is within our view - * @param pt Mouse coordinates - * @return Whether mouse coordinates are within view - */ - bool MouseIsInsideView(NSPoint *pt); - void CheckPaletteAnim(); + + void Draw(bool force_update = false); + void BlitIndexedToView32(int left, int top, int right, int bottom); }; class FVideoDriver_Cocoa : public DriverFactoryBase { diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 3350e32b8c..2525af1d45 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -406,6 +406,10 @@ void VideoDriver_Cocoa::GetDeviceInfo() CGDisplayModeRelease(cur_mode); } +/** + * Are we in fullscreen mode + * @return whether fullscreen mode is currently used + */ bool VideoDriver_Cocoa::IsFullscreen() { return this->window != nil && ([ this->window styleMask ] & NSWindowStyleMaskFullScreen) != 0; @@ -524,6 +528,14 @@ bool VideoDriver_Cocoa::SetVideoMode(int width, int height, int bpp) return ret; } +/** + * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. + * + * @param left The x coord for the left edge of the box to blit. + * @param top The y coord for the top edge of the box to blit. + * @param right The x coord for the right edge of the box to blit. + * @param bottom The y coord for the bottom edge of the box to blit. + */ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bottom) { const uint32 *pal = this->palette; @@ -539,7 +551,9 @@ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bo } } - +/** Draw window + * @param force_update Whether to redraw unconditionally + */ void VideoDriver_Cocoa::Draw(bool force_update) { PerformanceMeasurer framerate(PFE_VIDEO); @@ -582,6 +596,7 @@ void VideoDriver_Cocoa::Draw(bool force_update) this->num_dirty_rects = 0; } +/** Update the palette */ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) { if (this->buffer_depth != 8) return; @@ -597,7 +612,11 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) this->num_dirty_rects = lengthof(this->dirty_rects); } -/* Convert local coordinate to window server (CoreGraphics) coordinate */ +/** + * Convert local coordinate to window server (CoreGraphics) coordinate + * @param p local coordinates + * @return window driver coordinates + */ CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) { @@ -614,6 +633,11 @@ CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) return cgp; } +/** + * Return the mouse location + * @param event UI event + * @return mouse location as NSPoint + */ NSPoint VideoDriver_Cocoa::GetMouseLocation(NSEvent *event) { NSPoint pt; @@ -629,6 +653,11 @@ NSPoint VideoDriver_Cocoa::GetMouseLocation(NSEvent *event) return pt; } +/** + * Return whether the mouse is within our view + * @param pt Mouse coordinates + * @return Whether mouse coordinates are within view + */ bool VideoDriver_Cocoa::MouseIsInsideView(NSPoint *pt) { return [ cocoaview mouse:*pt inRect:[ this->cocoaview bounds ] ]; @@ -645,6 +674,10 @@ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height) } } +/** + * Resize the window. + * @return whether the window was successfully resized + */ bool VideoDriver_Cocoa::WindowResized() { if (this->window == nil || this->cocoaview == nil) return true; From 8aaf4ea0987a361e5d4f7b690544ee9119746660 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 30 Jan 2021 19:13:29 +0100 Subject: [PATCH 072/275] Codechange: [OSX] Split Window and back buffer creation in Cocoa video driver. --- src/video/cocoa/cocoa_v.h | 13 +- src/video/cocoa/cocoa_v.mm | 257 +++++++++++++++-------------------- src/video/cocoa/cocoa_wnd.h | 7 +- src/video/cocoa/cocoa_wnd.mm | 31 +++-- 4 files changed, 134 insertions(+), 174 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index f9920c20e4..0961e1660d 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -16,13 +16,12 @@ extern bool _cocoa_video_started; +@class OTTD_CocoaWindowDelegate; + class VideoDriver_Cocoa : public VideoDriver { private: Dimension orig_res; ///< Saved window size for non-fullscreen mode. - int device_width; ///< Width of device in pixel - int device_height; ///< Height of device in pixel - int window_width; ///< Current window width in pixel int window_height; ///< Current window height in pixel int window_pitch; @@ -46,6 +45,8 @@ public: CGColorSpaceRef color_space; ///< Window color space CGContextRef cgcontext; ///< Context reference for Quartz subdriver + OTTD_CocoaWindowDelegate *delegate; //!< Window delegate object + public: VideoDriver_Cocoa(); @@ -69,7 +70,7 @@ public: /** Main game loop. */ void GameLoop(); // In event.mm. - bool WindowResized(); + void AllocateBackingStore(); protected: Dimension GetScreenSize() const override; @@ -85,8 +86,8 @@ private: void GameSizeChanged(); void UpdateVideoModes(); - void GetDeviceInfo(); - bool SetVideoMode(int width, int height, int bpp); + + bool MakeWindow(int width, int height); void UpdatePalette(uint first_color, uint num_colors); void CheckPaletteAnim(); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 2525af1d45..7f1e10bfe4 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -76,6 +76,12 @@ static const Dimension _default_resolutions[] = { static FVideoDriver_Cocoa iFVideoDriver_Cocoa; +/* Subclass of OTTD_CocoaView to fix Quartz rendering */ +@interface OTTD_QuartzView : OTTD_CocoaView +- (void)drawRect:(NSRect)invalidRect; +@end + + VideoDriver_Cocoa::VideoDriver_Cocoa() { this->window_width = 0; @@ -88,6 +94,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa() this->window = nil; this->cocoaview = nil; + this->delegate = nil; this->color_space = nullptr; this->cgcontext = nullptr; @@ -106,10 +113,12 @@ void VideoDriver_Cocoa::Stop() /* Release window mode resources */ if (this->window != nil) [ this->window close ]; + [ this->cocoaview release ]; + [ this->delegate release ]; CGContextRelease(this->cgcontext); - CGColorSpaceRelease(this->color_space); + free(this->window_buffer); free(this->pixel_buffer); @@ -130,23 +139,21 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) if (!CocoaSetupApplication()) return nullptr; this->UpdateAutoResolution(); - this->orig_res = _cur_resolution; - int width = _cur_resolution.width; - int height = _cur_resolution.height; - int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); + int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); if (bpp != 8 && bpp != 32) { Stop(); return "The cocoa quartz subdriver only supports 8 and 32 bpp."; } - if (!this->SetVideoMode(width, height, bpp)) { + bool fullscreen = _fullscreen; + if (!this->MakeWindow(_cur_resolution.width, _cur_resolution.height)) { Stop(); - return "Could not create subdriver"; + return "Could not create window"; } - if (_fullscreen) this->ToggleFullscreen(_fullscreen); + if (fullscreen) this->ToggleFullscreen(fullscreen); this->GameSizeChanged(); this->UpdateVideoModes(); @@ -195,17 +202,29 @@ void VideoDriver_Cocoa::MainLoop() */ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) { - int old_width = this->window_width; - int old_height = this->window_height; - int old_bpp = this->buffer_depth; + NSSize screen_size = [ [ NSScreen mainScreen ] frame ].size; + w = std::min(w, (int)screen_size.width); + h = std::min(h, (int)screen_size.height); - if (this->SetVideoMode(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth())) { - this->GameSizeChanged(); - return true; + NSRect contentRect = NSMakeRect(0, 0, w, h); + [ this->window setContentSize:contentRect.size ]; + + /* Ensure frame height - title bar height >= view height */ + float content_height = [ this->window contentRectForFrameRect:[ this->window frame ] ].size.height; + contentRect.size.height = Clamp(h, 0, (int)content_height); + + if (this->cocoaview != nil) { + h = (int)contentRect.size.height; + [ this->cocoaview setFrameSize:contentRect.size ]; } - if (old_width != 0 && old_height != 0) this->SetVideoMode(old_width, old_height, old_bpp); - return false; + this->window_width = w; + this->window_height = h; + + [ (OTTD_CocoaWindow *)this->window center ]; + this->AllocateBackingStore(); + + return true; } /** @@ -234,7 +253,9 @@ bool VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) */ bool VideoDriver_Cocoa::AfterBlitterChange() { - return this->ChangeResolution(_screen.width, _screen.height); + this->ChangeResolution(_screen.width, _screen.height); + this->UpdatePalette(0, 256); + return true; } /** @@ -256,6 +277,15 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const return { static_cast(NSWidth(frame)), static_cast(NSHeight(frame)) }; } +/** + * Are we in fullscreen mode + * @return whether fullscreen mode is currently used + */ +bool VideoDriver_Cocoa::IsFullscreen() +{ + return this->window != nil && ([ this->window styleMask ] & NSWindowStyleMaskFullScreen) != 0; +} + /** * Handle a change of the display area. */ @@ -277,19 +307,10 @@ void VideoDriver_Cocoa::GameSizeChanged() ::GameSizeChanged(); } -/* Subclass of OTTD_CocoaView to fix Quartz rendering */ -@interface OTTD_QuartzView : OTTD_CocoaView -- (void)setDriver:(VideoDriver_Cocoa *)drv; -- (void)drawRect:(NSRect)invalidRect; -@end @implementation OTTD_QuartzView -- (void)setDriver:(VideoDriver_Cocoa *)drv -{ - driver = drv; -} - (void)drawRect:(NSRect)invalidRect { if (driver->cgcontext == NULL) return; @@ -391,141 +412,85 @@ void VideoDriver_Cocoa::UpdateVideoModes() } } -void VideoDriver_Cocoa::GetDeviceInfo() -{ - /* Initialize the video settings; this data persists between mode switches - * and gather some information that is useful to know about the display */ - - /* Use the new API when compiling for OSX 10.6 or later */ - CGDisplayModeRef cur_mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); - if (cur_mode == NULL) { return; } - - this->device_width = CGDisplayModeGetWidth(cur_mode); - this->device_height = CGDisplayModeGetHeight(cur_mode); - - CGDisplayModeRelease(cur_mode); -} - /** - * Are we in fullscreen mode - * @return whether fullscreen mode is currently used + * Build window and view with a given size. + * @param width Window width. + * @param height Window height. */ -bool VideoDriver_Cocoa::IsFullscreen() -{ - return this->window != nil && ([ this->window styleMask ] & NSWindowStyleMaskFullScreen) != 0; -} - -bool VideoDriver_Cocoa::SetVideoMode(int width, int height, int bpp) +bool VideoDriver_Cocoa::MakeWindow(int width, int height) { this->setup = true; - this->GetDeviceInfo(); - if (width > this->device_width) width = this->device_width; - if (height > this->device_height) height = this->device_height; + NSSize screen_size = [ [ NSScreen mainScreen ] frame ].size; + if (width > screen_size.width) width = screen_size.width; + if (height > screen_size.height) height = screen_size.height; NSRect contentRect = NSMakeRect(0, 0, width, height); - /* Check if we should recreate the window */ + /* Create main window. */ + unsigned int style = NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask; + this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO ]; if (this->window == nil) { - OTTD_CocoaWindowDelegate *delegate; + DEBUG(driver, 0, "Could not create the Cocoa window."); + this->setup = false; + return false; + } + [ this->window setDriver:this ]; - /* Set the window style */ - unsigned int style = NSTitledWindowMask; - style |= (NSMiniaturizableWindowMask | NSClosableWindowMask); - style |= NSResizableWindowMask; + /* Add built in full-screen support when available (OS X 10.7 and higher) + * This code actually compiles for 10.5 and later, but only makes sense in conjunction + * with the quartz fullscreen support as found only in 10.7 and later + */ + if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) { + NSWindowCollectionBehavior behavior = [ this->window collectionBehavior ]; + behavior |= NSWindowCollectionBehaviorFullScreenPrimary; + [ this->window setCollectionBehavior:behavior ]; - /* Manually create a window, avoids having a nib file resource */ - this->window = [ [ OTTD_CocoaWindow alloc ] - initWithContentRect:contentRect - styleMask:style - backing:NSBackingStoreBuffered - defer:NO ]; - - if (this->window == nil) { - DEBUG(driver, 0, "Could not create the Cocoa window."); - this->setup = false; - return false; - } - - /* Add built in full-screen support when available (OS X 10.7 and higher) - * This code actually compiles for 10.5 and later, but only makes sense in conjunction - * with the quartz fullscreen support as found only in 10.7 and later - */ - if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) { - NSWindowCollectionBehavior behavior = [ this->window collectionBehavior ]; - behavior |= NSWindowCollectionBehaviorFullScreenPrimary; - [ this->window setCollectionBehavior:behavior ]; - - NSButton* fullscreenButton = [ this->window standardWindowButton:NSWindowFullScreenButton ]; - [ fullscreenButton setAction:@selector(toggleFullScreen:) ]; - [ fullscreenButton setTarget:this->window ]; - } - - [ this->window setDriver:this ]; - - char caption[50]; - snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); - NSString *nsscaption = [ [ NSString alloc ] initWithUTF8String:caption ]; - [ this->window setTitle:nsscaption ]; - [ this->window setMiniwindowTitle:nsscaption ]; - [ nsscaption release ]; - - [ this->window setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; - - [ this->window setAcceptsMouseMovedEvents:YES ]; - [ this->window setViewsNeedDisplay:NO ]; - - delegate = [ [ OTTD_CocoaWindowDelegate alloc ] init ]; - [ delegate setDriver:this ]; - [ this->window setDelegate:[ delegate autorelease ] ]; - } else { - /* We already have a window, just change its size */ - [ this->window setContentSize:contentRect.size ]; - - /* Ensure frame height - title bar height >= view height */ - float content_height = [ this->window contentRectForFrameRect:[ this->window frame ] ].size.height; - contentRect.size.height = Clamp(height, 0, (int)content_height); - - if (this->cocoaview != nil) { - height = (int)contentRect.size.height; - [ this->cocoaview setFrameSize:contentRect.size ]; - } + NSButton* fullscreenButton = [ this->window standardWindowButton:NSWindowFullScreenButton ]; + [ fullscreenButton setAction:@selector(toggleFullScreen:) ]; + [ fullscreenButton setTarget:this->window ]; } - this->window_width = width; - this->window_height = height; - this->buffer_depth = bpp; + char caption[50]; + snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); + NSString *nsscaption = [ [ NSString alloc ] initWithUTF8String:caption ]; + [ this->window setTitle:nsscaption ]; + [ this->window setMiniwindowTitle:nsscaption ]; + [ nsscaption release ]; + [ this->window setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; + + this->delegate = [ [ OTTD_CocoaWindowDelegate alloc ] initWithDriver:this ]; + [ this->window setDelegate:this->delegate ]; + + [ this->window setAcceptsMouseMovedEvents:YES ]; + [ this->window setViewsNeedDisplay:NO ]; [ (OTTD_CocoaWindow *)this->window center ]; + [ this->window makeKeyAndOrderFront:nil ]; - /* Only recreate the view if it doesn't already exist */ + /* Create content view. */ + this->cocoaview = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->window contentRectForFrameRect:[ this->window frame ] ] andDriver:this ]; if (this->cocoaview == nil) { - this->cocoaview = [ [ OTTD_QuartzView alloc ] initWithFrame:contentRect ]; - if (this->cocoaview == nil) { - DEBUG(driver, 0, "Could not create the Quartz view."); - this->setup = false; - return false; - } - - [ this->cocoaview setDriver:this ]; - - [ (NSView*)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; - [ this->window setContentView:cocoaview ]; - [ this->cocoaview release ]; - [ this->window makeKeyAndOrderFront:nil ]; + DEBUG(driver, 0, "Could not create the Quartz view."); + this->setup = false; + return false; } + [ (NSView*)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; + [ this->window setContentView:cocoaview ]; + [ this->window setColorSpace:[ NSColorSpace sRGBColorSpace ] ]; + CGColorSpaceRelease(this->color_space); this->color_space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); if (this->color_space == nullptr) this->color_space = CGColorSpaceCreateDeviceRGB(); if (this->color_space == nullptr) error("Could not get a valid colour space for drawing."); - bool ret = this->WindowResized(); - this->UpdatePalette(0, 256); - this->setup = false; - return ret; + this->UpdatePalette(0, 256); + this->AllocateBackingStore(); + + return true; } /** @@ -624,7 +589,7 @@ CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) *p = [ this->cocoaview convertPoint:*p toView:nil ]; *p = [ this->window convertRectToScreen:NSMakeRect(p->x, p->y, 0, 0) ].origin; - p->y = this->device_height - p->y; + p->y = NSScreen.screens[0].frame.size.height - p->y; CGPoint cgp; cgp.x = p->x; @@ -674,18 +639,16 @@ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height) } } -/** - * Resize the window. - * @return whether the window was successfully resized - */ -bool VideoDriver_Cocoa::WindowResized() +/** Resize the window. */ +void VideoDriver_Cocoa::AllocateBackingStore() { - if (this->window == nil || this->cocoaview == nil) return true; + if (this->window == nil || this->cocoaview == nil || this->setup) return; NSRect newframe = [ this->cocoaview frame ]; this->window_width = (int)newframe.size.width; this->window_height = (int)newframe.size.height; + this->buffer_depth = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); /* Create Core Graphics Context */ free(this->window_buffer); @@ -712,18 +675,12 @@ bool VideoDriver_Cocoa::WindowResized() if (this->buffer_depth == 8) { free(this->pixel_buffer); this->pixel_buffer = malloc(this->window_width * this->window_height); - if (this->pixel_buffer == NULL) { - DEBUG(driver, 0, "Failed to allocate pixel buffer"); - return false; - } + if (this->pixel_buffer == nullptr) usererror("Out of memory allocating pixel buffer"); } - this->GameSizeChanged(); - /* Redraw screen */ this->num_dirty_rects = lengthof(this->dirty_rects); - - return true; + this->GameSizeChanged(); } void VideoDriver_Cocoa::CheckPaletteAnim() diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 35dcaa7c07..96834d9047 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -42,7 +42,7 @@ extern NSString *OTTDMainLaunchGameEngine; VideoDriver_Cocoa *driver; NSTrackingRectTag trackingtag; } -- (void)setDriver:(VideoDriver_Cocoa *)drv; +- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; - (void)drawRect:(NSRect)rect; - (BOOL)isOpaque; - (BOOL)acceptsFirstResponder; @@ -61,12 +61,11 @@ extern NSString *OTTDMainLaunchGameEngine; { VideoDriver_Cocoa *driver; } - -- (void)setDriver:(VideoDriver_Cocoa *)drv; +- (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv; - (BOOL)windowShouldClose:(id)sender; - (void)windowDidEnterFullScreen:(NSNotification *)aNotification; -- (void)windowDidChangeScreenProfile:(NSNotification *)aNotification; +- (void)windowDidChangeBackingProperties:(NSNotification *)notification; - (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions; @end diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index ff222ea425..80c2e2e215 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -324,10 +324,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel { [ super setFrame:frameRect display:flag ]; - /* Don't do anything if the window is currently being created */ - if (driver->setup) return; - - if (!driver->WindowResized()) error("Cocoa: Failed to resize window."); + driver->AllocateBackingStore(); } /** * Handle hiding of the application @@ -401,12 +398,13 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) } @implementation OTTD_CocoaView -/** - * Initialize the driver - */ -- (void)setDriver:(VideoDriver_Cocoa *)drv + +- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv { - driver = drv; + if (self = [ super initWithFrame:frameRect ]) { + self->driver = drv; + } + return self; } /** * Define the opaqueness of the window / screen @@ -810,9 +808,12 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) @implementation OTTD_CocoaWindowDelegate /** Initialize the video driver */ -- (void)setDriver:(VideoDriver_Cocoa *)drv +- (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv { - driver = drv; + if (self = [ super init ]) { + self->driver = drv; + } + return self; } /** Handle closure requests */ - (BOOL)windowShouldClose:(id)sender @@ -854,10 +855,11 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) [ e release ]; } } -/** The colour profile of the screen the window is on changed. */ -- (void)windowDidChangeScreenProfile:(NSNotification *)aNotification +/** Screen the window is on changed. */ +- (void)windowDidChangeBackingProperties:(NSNotification *)notification { - if (!driver->setup) driver->WindowResized(); + /* Reallocate screen buffer if necessary. */ + driver->AllocateBackingStore(); } /** Presentation options to use for fullsreen mode. */ @@ -867,4 +869,5 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) } @end + #endif /* WITH_COCOA */ From 60f30036f1338b6fba8a0c23d7a8b70eab697644 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 01:51:38 +0100 Subject: [PATCH 073/275] Codechange: [OSX] Drain autoreleased objects in each game loop cycle. --- src/video/cocoa/cocoa_wnd.mm | 19 ++++++---- src/video/cocoa/event.mm | 73 +++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 80c2e2e215..e7c916443b 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -203,6 +203,7 @@ bool CocoaSetupApplication() } /* Become the front process, important when start from the command line. */ + [ [ NSApplication sharedApplication ] setActivationPolicy:NSApplicationActivationPolicyRegular ]; [ [ NSApplication sharedApplication ] activateIgnoringOtherApps:YES ]; /* Set up the menubar */ @@ -247,15 +248,17 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel return; } - NSAlert *alert = [ [ NSAlert alloc ] init ]; - [ alert setAlertStyle: NSCriticalAlertStyle ]; - [ alert setMessageText:[ NSString stringWithUTF8String:title ] ]; - [ alert setInformativeText:[ NSString stringWithUTF8String:message ] ]; - [ alert addButtonWithTitle: [ NSString stringWithUTF8String:buttonLabel ] ]; - [ alert runModal ]; - [ alert release ]; + @autoreleasepool { + NSAlert *alert = [ [ NSAlert alloc ] init ]; + [ alert setAlertStyle: NSCriticalAlertStyle ]; + [ alert setMessageText:[ NSString stringWithUTF8String:title ] ]; + [ alert setInformativeText:[ NSString stringWithUTF8String:message ] ]; + [ alert addButtonWithTitle: [ NSString stringWithUTF8String:buttonLabel ] ]; + [ alert runModal ]; + [ alert release ]; + } - if (!wasstarted && VideoDriver::GetInstance() != NULL) VideoDriver::GetInstance()->Stop(); + if (!wasstarted && VideoDriver::GetInstance() != nullptr) VideoDriver::GetInstance()->Stop(); _cocoa_video_dialog = false; } diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 858cd51ad5..00559e6bce 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -609,57 +609,60 @@ void VideoDriver_Cocoa::GameLoop() this->Draw(true); for (;;) { - uint32 prev_cur_ticks = cur_ticks; // to check for wrapping - InteractiveRandom(); // randomness + @autoreleasepool { - while (this->PollEvent()) {} + uint32 prev_cur_ticks = cur_ticks; // to check for wrapping + InteractiveRandom(); // randomness - if (_exit_game) { - /* Restore saved resolution if in fullscreen mode. */ - if (this->IsFullscreen()) _cur_resolution = this->orig_res; - break; - } + while (this->PollEvent()) {} + + if (_exit_game) { + /* Restore saved resolution if in fullscreen mode. */ + if (this->IsFullscreen()) _cur_resolution = this->orig_res; + break; + } #if defined(_DEBUG) - if (_current_mods & NSShiftKeyMask) + if (_current_mods & NSShiftKeyMask) #else - if (_tab_is_down) + if (_tab_is_down) #endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } + { + if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; + } else if (_fast_forward & 2) { + _fast_forward = 0; + } - cur_ticks = GetTick(); - if (cur_ticks >= next_tick || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { - _realtime_tick += cur_ticks - last_cur_ticks; - last_cur_ticks = cur_ticks; - next_tick = cur_ticks + MILLISECONDS_PER_TICK; + cur_ticks = GetTick(); + if (cur_ticks >= next_tick || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { + _realtime_tick += cur_ticks - last_cur_ticks; + last_cur_ticks = cur_ticks; + next_tick = cur_ticks + MILLISECONDS_PER_TICK; - bool old_ctrl_pressed = _ctrl_pressed; + bool old_ctrl_pressed = _ctrl_pressed; - _ctrl_pressed = !!(_current_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); - _shift_pressed = !!(_current_mods & NSShiftKeyMask); + _ctrl_pressed = !!(_current_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); + _shift_pressed = !!(_current_mods & NSShiftKeyMask); - if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); + if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); - ::GameLoop(); + ::GameLoop(); - UpdateWindows(); - this->CheckPaletteAnim(); - this->Draw(); - } else { + UpdateWindows(); + this->CheckPaletteAnim(); + this->Draw(); + } else { #ifdef _DEBUG - uint32 st0 = GetTick(); + uint32 st0 = GetTick(); #endif - CSleep(1); + CSleep(1); #ifdef _DEBUG - st += GetTick() - st0; + st += GetTick() - st0; #endif - NetworkDrawChatMessage(); - DrawMouseCursor(); - this->Draw(); + NetworkDrawChatMessage(); + DrawMouseCursor(); + this->Draw(); + } } } From 42af13c141eb74f63e58827f8a33e7f66d7d829a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 31 Jan 2021 18:58:23 +0100 Subject: [PATCH 074/275] Codechange: [OSX] Split drawing into its own subview. This allows the drawing backend code to be independent of any event or command handling. --- src/video/cocoa/cocoa_v.mm | 53 ++++++++++-- src/video/cocoa/cocoa_wnd.h | 19 +---- src/video/cocoa/cocoa_wnd.mm | 159 +++++++++++++++++------------------ 3 files changed, 126 insertions(+), 105 deletions(-) diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 7f1e10bfe4..ef30519ea6 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -77,7 +77,11 @@ static FVideoDriver_Cocoa iFVideoDriver_Cocoa; /* Subclass of OTTD_CocoaView to fix Quartz rendering */ -@interface OTTD_QuartzView : OTTD_CocoaView +@interface OTTD_QuartzView : NSView { + VideoDriver_Cocoa *driver; +} +- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; + - (void)drawRect:(NSRect)invalidRect; @end @@ -311,6 +315,28 @@ void VideoDriver_Cocoa::GameSizeChanged() @implementation OTTD_QuartzView +- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv +{ + if (self = [ super initWithFrame:frameRect ]) { + self->driver = drv; + } + return self; +} + +- (BOOL)acceptsFirstResponder +{ + return NO; +} + +/** + * Define the opaqueness of the window / screen + * @return opaqueness of window / screen + */ +- (BOOL)isOpaque +{ + return YES; +} + - (void)drawRect:(NSRect)invalidRect { if (driver->cgcontext == NULL) return; @@ -429,13 +455,12 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) /* Create main window. */ unsigned int style = NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask; - this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO ]; + this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO driver:this ]; if (this->window == nil) { DEBUG(driver, 0, "Could not create the Cocoa window."); this->setup = false; return false; } - [ this->window setDriver:this ]; /* Add built in full-screen support when available (OS X 10.7 and higher) * This code actually compiles for 10.5 and later, but only makes sense in conjunction @@ -468,16 +493,28 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) [ (OTTD_CocoaWindow *)this->window center ]; [ this->window makeKeyAndOrderFront:nil ]; - /* Create content view. */ - this->cocoaview = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->window contentRectForFrameRect:[ this->window frame ] ] andDriver:this ]; + /* Create wrapper view for text input. */ + NSRect view_frame = [ this->window contentRectForFrameRect:[ this->window frame ] ]; + this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame andDriver:this ]; if (this->cocoaview == nil) { - DEBUG(driver, 0, "Could not create the Quartz view."); + DEBUG(driver, 0, "Could not create the text wrapper view."); this->setup = false; return false; } + [ (NSView *)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; - [ (NSView*)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; - [ this->window setContentView:cocoaview ]; + /* Create content view. */ + NSView *draw_view = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->cocoaview bounds ] andDriver:this ]; + if (draw_view == nil) { + DEBUG(driver, 0, "Could not create the drawing view."); + this->setup = false; + return false; + } + [ draw_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; + + [ this->window setContentView:this->cocoaview ]; + [ this->cocoaview addSubview:draw_view ]; + [ draw_view release ]; [ this->window setColorSpace:[ NSColorSpace sRGBColorSpace ] ]; CGColorSpaceRelease(this->color_space); diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 96834d9047..744a657861 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -22,31 +22,23 @@ extern NSString *OTTDMainLaunchGameEngine; @end /** Subclass of NSWindow to cater our special needs */ -@interface OTTD_CocoaWindow : NSWindow { - VideoDriver_Cocoa *driver; -} - -- (void)setDriver:(VideoDriver_Cocoa *)drv; +@interface OTTD_CocoaWindow : NSWindow +- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv; - (void)miniaturize:(id)sender; - (void)display; - (void)setFrame:(NSRect)frameRect display:(BOOL)flag; - (void)appDidHide:(NSNotification*)note; - (void)appDidUnhide:(NSNotification*)note; -- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; @end /** Subclass of NSView to fix Quartz rendering and mouse awareness */ -@interface OTTD_CocoaView : NSView -{ +@interface OTTD_CocoaView : NSView { VideoDriver_Cocoa *driver; - NSTrackingRectTag trackingtag; } - (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; -- (void)drawRect:(NSRect)rect; -- (BOOL)isOpaque; + - (BOOL)acceptsFirstResponder; -- (BOOL)becomeFirstResponder; - (void)setTrackingRect; - (void)clearTrackingRect; - (void)resetCursorRects; @@ -58,9 +50,6 @@ extern NSString *OTTDMainLaunchGameEngine; /** Delegate for our NSWindow to send ask for quit on close */ @interface OTTD_CocoaWindowDelegate : NSObject -{ - VideoDriver_Cocoa *driver; -} - (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv; - (BOOL)windowShouldClose:(id)sender; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index e7c916443b..ac6d35dd21 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -48,6 +48,46 @@ NSString *OTTDMainLaunchGameEngine = @"ottdmain_launch_game_engine"; static bool _cocoa_video_dialog = false; static OTTDMain *_ottd_main; + +/** + * Count the number of UTF-16 code points in a range of an UTF-8 string. + * @param from Start of the range. + * @param to End of the range. + * @return Number of UTF-16 code points in the range. + */ +static NSUInteger CountUtf16Units(const char *from, const char *to) +{ + NSUInteger i = 0; + + while (from < to) { + WChar c; + size_t len = Utf8Decode(&c, from); + i += len < 4 ? 1 : 2; // Watch for surrogate pairs. + from += len; + } + + return i; +} + +/** + * Advance an UTF-8 string by a number of equivalent UTF-16 code points. + * @param str UTF-8 string. + * @param count Number of UTF-16 code points to advance the string by. + * @return Advanced string pointer. + */ +static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) +{ + for (NSUInteger i = 0; i < count && *str != '\0'; ) { + WChar c; + size_t len = Utf8Decode(&c, str); + i += len < 4 ? 1 : 2; // Watch for surrogates. + str += len; + } + + return str; +} + + /** * The main class of the application, the application's delegate. */ @@ -69,11 +109,13 @@ static OTTDMain *_ottd_main; */ - (void)launchGameEngine: (NSNotification*) note { + auto *drv = static_cast(VideoDriver::GetInstance()); + /* Setup cursor for the current _game_mode. */ - [ static_cast(VideoDriver::GetInstance())->cocoaview resetCursorRects ]; + [ drv->window invalidateCursorRectsForView:[ drv->window contentView ] ]; /* Hand off to main application code. */ - static_cast(VideoDriver::GetInstance())->GameLoop(); + drv->GameLoop(); /* We are done, thank you for playing. */ [ self performSelectorOnMainThread:@selector(stopEngine) withObject:nil waitUntilDone:FALSE ]; @@ -283,12 +325,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } @end -@implementation OTTD_CocoaWindow - -- (void)setDriver:(VideoDriver_Cocoa *)drv -{ - driver = drv; +@implementation OTTD_CocoaWindow { + VideoDriver_Cocoa *driver; } + /** * Minimize the window */ @@ -346,62 +386,28 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel /** * Initialize event system for the application rectangle */ -- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag +- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv { - /* Make our window subclass receive these application notifications */ - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; + if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { + /* Make our window subclass receive these application notifications */ + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; - return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; + self->driver = drv; + } + + return self; } @end - - -/** - * Count the number of UTF-16 code points in a range of an UTF-8 string. - * @param from Start of the range. - * @param to End of the range. - * @return Number of UTF-16 code points in the range. - */ -static NSUInteger CountUtf16Units(const char *from, const char *to) -{ - NSUInteger i = 0; - - while (from < to) { - WChar c; - size_t len = Utf8Decode(&c, from); - i += len < 4 ? 1 : 2; // Watch for surrogate pairs. - from += len; - } - - return i; +@implementation OTTD_CocoaView { + NSTrackingRectTag trackingtag; } -/** - * Advance an UTF-8 string by a number of equivalent UTF-16 code points. - * @param str UTF-8 string. - * @param count Number of UTF-16 code points to advance the string by. - * @return Advanced string pointer. - */ -static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) -{ - for (NSUInteger i = 0; i < count && *str != '\0'; ) { - WChar c; - size_t len = Utf8Decode(&c, str); - i += len < 4 ? 1 : 2; // Watch for surrogates. - str += len; - } - - return str; -} - -@implementation OTTD_CocoaView - - (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv { if (self = [ super initWithFrame:frameRect ]) { @@ -409,22 +415,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) } return self; } -/** - * Define the opaqueness of the window / screen - * @return opaqueness of window / screen - */ -- (BOOL)isOpaque -{ - return YES; -} -/** - * Draws a rectangle on the screen. - * It's overwritten by the individual drivers but must be defined - */ -- (void)drawRect:(NSRect)invalidRect -{ - return; -} + /** * Allow to handle events */ @@ -432,13 +423,15 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) { return YES; } -/** - * Actually handle events - */ -- (BOOL)becomeFirstResponder + +- (void)setNeedsDisplayInRect:(NSRect)invalidRect { - return YES; + /* Drawing is handled by our sub-views. Just pass it along. */ + for ( NSView *v in [ self subviews ]) { + [ v setNeedsDisplayInRect:[ v convertRect:invalidRect fromView:self ] ]; + } } + /** * Define the rectangle where we draw our application window */ @@ -556,7 +549,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) /** Unmark the current marked text. */ - (void)unmarkText { - HandleTextInput(NULL, true); + HandleTextInput(nullptr, true); } /** Get the caret position. */ @@ -575,7 +568,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) size_t mark_len; const char *mark = _focused_window->GetMarkedText(&mark_len); - if (mark != NULL) { + if (mark != nullptr) { NSUInteger start = CountUtf16Units(_focused_window->GetFocusedText(), mark); NSUInteger len = CountUtf16Units(mark, mark + mark_len); @@ -591,7 +584,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) if (!EditBoxInGlobalFocus()) return NO; size_t len; - return _focused_window->GetMarkedText(&len) != NULL; + return _focused_window->GetMarkedText(&len) != nullptr; } /** Get a string corresponding to the given range. */ @@ -602,7 +595,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) NSString *s = [ NSString stringWithUTF8String:_focused_window->GetFocusedText() ]; NSRange valid_range = NSIntersectionRange(NSMakeRange(0, [ s length ]), theRange); - if (actualRange != NULL) *actualRange = valid_range; + if (actualRange != nullptr) *actualRange = valid_range; if (valid_range.length == 0) return nil; return [ [ [ NSAttributedString alloc ] initWithString:[ s substringWithRange:valid_range ] ] autorelease ]; @@ -611,7 +604,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) /** Get a string corresponding to the given range. */ - (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange { - return [ self attributedSubstringForProposedRange:theRange actualRange:NULL ]; + return [ self attributedSubstringForProposedRange:theRange actualRange:nil ]; } /** Get the current edit box string. */ @@ -632,7 +625,7 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) Point pt = { (int)view_pt.x, (int)[ self frame ].size.height - (int)view_pt.y }; const char *ch = _focused_window->GetTextCharacterAtPosition(pt); - if (ch == NULL) return NSNotFound; + if (ch == nullptr) return NSNotFound; return CountUtf16Units(_focused_window->GetFocusedText(), ch); } @@ -808,8 +801,10 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) @end +@implementation OTTD_CocoaWindowDelegate { + VideoDriver_Cocoa *driver; +} -@implementation OTTD_CocoaWindowDelegate /** Initialize the video driver */ - (instancetype)initWithDriver:(VideoDriver_Cocoa *)drv { From 965ce1294726427bf31da33bb5c7650773f8aada Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 3 Feb 2021 22:43:06 +0100 Subject: [PATCH 075/275] Codechange: [OSX] Use newer mouse tracking API. --- src/video/cocoa/cocoa_v.mm | 2 +- src/video/cocoa/cocoa_wnd.h | 16 +----- src/video/cocoa/cocoa_wnd.mm | 101 +++++++++++++---------------------- 3 files changed, 40 insertions(+), 79 deletions(-) diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index ef30519ea6..185f28c84e 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -495,7 +495,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) /* Create wrapper view for text input. */ NSRect view_frame = [ this->window contentRectForFrameRect:[ this->window frame ] ]; - this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame andDriver:this ]; + this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame ]; if (this->cocoaview == nil) { DEBUG(driver, 0, "Could not create the text wrapper view."); this->setup = false; diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 744a657861..449b457af1 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -32,20 +32,8 @@ extern NSString *OTTDMainLaunchGameEngine; - (void)appDidUnhide:(NSNotification*)note; @end -/** Subclass of NSView to fix Quartz rendering and mouse awareness */ -@interface OTTD_CocoaView : NSView { - VideoDriver_Cocoa *driver; -} -- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; - -- (BOOL)acceptsFirstResponder; -- (void)setTrackingRect; -- (void)clearTrackingRect; -- (void)resetCursorRects; -- (void)viewWillMoveToWindow:(NSWindow *)win; -- (void)viewDidMoveToWindow; -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; +/** Subclass of NSView to support mouse awareness and text input. */ +@interface OTTD_CocoaView : NSView @end /** Delegate for our NSWindow to send ask for quit on close */ diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index ac6d35dd21..8f72836cca 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -112,7 +112,9 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) auto *drv = static_cast(VideoDriver::GetInstance()); /* Setup cursor for the current _game_mode. */ - [ drv->window invalidateCursorRectsForView:[ drv->window contentView ] ]; + NSEvent *e = [ [ NSEvent alloc ] init ]; + [ drv->cocoaview cursorUpdate:e ]; + [ e release ]; /* Hand off to main application code. */ drv->GameLoop(); @@ -329,6 +331,25 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel VideoDriver_Cocoa *driver; } +/** + * Initialize event system for the application rectangle + */ +- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv +{ + if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { + /* Make our window subclass receive these application notifications */ + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; + + self->driver = drv; + } + + return self; +} + /** * Minimize the window */ @@ -383,38 +404,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel { driver->active = true; } -/** - * Initialize event system for the application rectangle - */ -- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv -{ - if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { - /* Make our window subclass receive these application notifications */ - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; - - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; - - self->driver = drv; - } - - return self; -} @end -@implementation OTTD_CocoaView { - NSTrackingRectTag trackingtag; -} - -- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv -{ - if (self = [ super initWithFrame:frameRect ]) { - self->driver = drv; - } - return self; -} +@implementation OTTD_CocoaView /** * Allow to handle events @@ -432,46 +425,26 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } } -/** - * Define the rectangle where we draw our application window - */ -- (void)setTrackingRect +/** Update mouse cursor to use for this view. */ +- (void)cursorUpdate:(NSEvent *)event { - NSPoint loc = [ self convertPoint:[ [ self window ] mouseLocationOutsideOfEventStream ] fromView:nil ]; - BOOL inside = ([ self hitTest:loc ]==self); - if (inside) [ [ self window ] makeFirstResponder:self ]; - trackingtag = [ self addTrackingRect:[ self visibleRect ] owner:self userData:nil assumeInside:inside ]; + [ (_game_mode == GM_BOOTSTRAP ? [ NSCursor arrowCursor ] : [ NSCursor clearCocoaCursor ]) set ]; } -/** - * Return responsibility for the application window to system - */ -- (void)clearTrackingRect -{ - [ self removeTrackingRect:trackingtag ]; -} -/** - * Declare responsibility for the cursor within our application rect - */ -- (void)resetCursorRects -{ - [ super resetCursorRects ]; - [ self clearTrackingRect ]; - [ self setTrackingRect ]; - [ self addCursorRect:[ self bounds ] cursor:(_game_mode == GM_BOOTSTRAP ? [ NSCursor arrowCursor ] : [ NSCursor clearCocoaCursor ]) ]; -} -/** - * Prepare for moving the application window - */ + - (void)viewWillMoveToWindow:(NSWindow *)win { - if (!win && [ self window ]) [ self clearTrackingRect ]; + for (NSTrackingArea *a in [ self trackingAreas ]) { + [ self removeTrackingArea:a ]; + } } -/** - * Restore our responsibility for our application window after moving - */ + - (void)viewDidMoveToWindow { - if ([ self window ]) [ self setTrackingRect ]; + /* Install mouse tracking area. */ + NSTrackingAreaOptions track_opt = NSTrackingInVisibleRect | NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | NSTrackingCursorUpdate; + NSTrackingArea *track = [ [ NSTrackingArea alloc ] initWithRect:[ self bounds ] options:track_opt owner:self userInfo:nil ]; + [ self addTrackingArea:track ]; + [ track release ]; } /** * Make OpenTTD aware that it has control over the mouse @@ -485,7 +458,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel */ - (void)mouseExited:(NSEvent *)theEvent { - if (driver->window != nil) UndrawMouseCursor(); + if ([ self window ] != nil) UndrawMouseCursor(); _cursor.in_window = false; } From bd42fc94cc1dc064d0c20cfa4fad108dc64931c6 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 00:23:29 +0100 Subject: [PATCH 076/275] Codechange: [OSX] Move some things from video driver to our NSView. --- src/video/cocoa/cocoa_v.h | 6 +- src/video/cocoa/cocoa_v.mm | 221 ++++++++++++++++------------------- src/video/cocoa/cocoa_wnd.mm | 10 ++ 3 files changed, 116 insertions(+), 121 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 0961e1660d..4c53cdb8fa 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -17,6 +17,8 @@ extern bool _cocoa_video_started; @class OTTD_CocoaWindowDelegate; +@class OTTD_CocoaWindow; +@class OTTD_CocoaView; class VideoDriver_Cocoa : public VideoDriver { private: @@ -40,8 +42,8 @@ public: bool active; ///< Whether the window is visible bool setup; - id window; ///< Pointer to window object - id cocoaview; ///< Pointer to view object + OTTD_CocoaWindow *window; ///< Pointer to window object + OTTD_CocoaView *cocoaview; ///< Pointer to view object CGColorSpaceRef color_space; ///< Window color space CGContextRef cgcontext; ///< Context reference for Quartz subdriver diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 185f28c84e..88f461234f 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -26,7 +26,6 @@ #include "../../openttd.h" #include "../../debug.h" -#include "../../rev.h" #include "../../core/geometry_type.hpp" #include "cocoa_v.h" #include "cocoa_wnd.h" @@ -311,111 +310,6 @@ void VideoDriver_Cocoa::GameSizeChanged() ::GameSizeChanged(); } - - -@implementation OTTD_QuartzView - -- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv -{ - if (self = [ super initWithFrame:frameRect ]) { - self->driver = drv; - } - return self; -} - -- (BOOL)acceptsFirstResponder -{ - return NO; -} - -/** - * Define the opaqueness of the window / screen - * @return opaqueness of window / screen - */ -- (BOOL)isOpaque -{ - return YES; -} - -- (void)drawRect:(NSRect)invalidRect -{ - if (driver->cgcontext == NULL) return; - - CGContextRef viewContext = (CGContextRef)[ [ NSGraphicsContext currentContext ] graphicsPort ]; - CGContextSetShouldAntialias(viewContext, FALSE); - CGContextSetInterpolationQuality(viewContext, kCGInterpolationNone); - - /* The obtained 'rect' is actually a union of all dirty rects, let's ask for an explicit list of rects instead */ - const NSRect *dirtyRects; - NSInteger dirtyRectCount; - [ self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount ]; - - /* We need an Image in order to do blitting, but as we don't touch the context between this call and drawing no copying will actually be done here */ - CGImageRef fullImage = CGBitmapContextCreateImage(driver->cgcontext); - - /* Calculate total area we are blitting */ - uint32 blitArea = 0; - for (int n = 0; n < dirtyRectCount; n++) { - blitArea += (uint32)(dirtyRects[n].size.width * dirtyRects[n].size.height); - } - - /* - * This might be completely stupid, but in my extremely subjective opinion it feels faster - * The point is, if we're blitting less than 50% of the dirty rect union then it's still a good idea to blit each dirty - * rect separately but if we blit more than that, it's just cheaper to blit the entire union in one pass. - * Feel free to remove or find an even better value than 50% ... / blackis - */ - NSRect frameRect = [ self frame ]; - if (blitArea / (float)(invalidRect.size.width * invalidRect.size.height) > 0.5f) { - NSRect rect = invalidRect; - CGRect clipRect; - CGRect blitRect; - - blitRect.origin.x = rect.origin.x; - blitRect.origin.y = rect.origin.y; - blitRect.size.width = rect.size.width; - blitRect.size.height = rect.size.height; - - clipRect.origin.x = rect.origin.x; - clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; - - clipRect.size.width = rect.size.width; - clipRect.size.height = rect.size.height; - - /* Blit dirty part of image */ - CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); - CGContextDrawImage(viewContext, blitRect, clippedImage); - CGImageRelease(clippedImage); - } else { - for (int n = 0; n < dirtyRectCount; n++) { - NSRect rect = dirtyRects[n]; - CGRect clipRect; - CGRect blitRect; - - blitRect.origin.x = rect.origin.x; - blitRect.origin.y = rect.origin.y; - blitRect.size.width = rect.size.width; - blitRect.size.height = rect.size.height; - - clipRect.origin.x = rect.origin.x; - clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; - - clipRect.size.width = rect.size.width; - clipRect.size.height = rect.size.height; - - /* Blit dirty part of image */ - CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); - CGContextDrawImage(viewContext, blitRect, clippedImage); - CGImageRelease(clippedImage); - } - } - - CGImageRelease(fullImage); -} - -@end - - /** * Update the video modus. */ @@ -476,21 +370,10 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) [ fullscreenButton setTarget:this->window ]; } - char caption[50]; - snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision); - NSString *nsscaption = [ [ NSString alloc ] initWithUTF8String:caption ]; - [ this->window setTitle:nsscaption ]; - [ this->window setMiniwindowTitle:nsscaption ]; - [ nsscaption release ]; - - [ this->window setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; - this->delegate = [ [ OTTD_CocoaWindowDelegate alloc ] initWithDriver:this ]; [ this->window setDelegate:this->delegate ]; - [ this->window setAcceptsMouseMovedEvents:YES ]; - [ this->window setViewsNeedDisplay:NO ]; - [ (OTTD_CocoaWindow *)this->window center ]; + [ this->window center ]; [ this->window makeKeyAndOrderFront:nil ]; /* Create wrapper view for text input. */ @@ -501,7 +384,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) this->setup = false; return false; } - [ (NSView *)this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; + [ this->cocoaview setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; /* Create content view. */ NSView *draw_view = [ [ OTTD_QuartzView alloc ] initWithFrame:[ this->cocoaview bounds ] andDriver:this ]; @@ -744,4 +627,104 @@ void VideoDriver_Cocoa::CheckPaletteAnim() } } + +@implementation OTTD_QuartzView + +- (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv +{ + if (self = [ super initWithFrame:frameRect ]) { + self->driver = drv; + } + return self; +} + +- (BOOL)acceptsFirstResponder +{ + return NO; +} + +- (BOOL)isOpaque +{ + return YES; +} + +- (void)drawRect:(NSRect)invalidRect +{ + if (driver->cgcontext == nullptr) return; + + NSGraphicsContext *ctx = [ NSGraphicsContext currentContext ]; + CGContextRef viewContext = [ ctx respondsToSelector:@selector(CGContext) ] ? [ ctx CGContext ] : (CGContextRef)[ ctx graphicsPort ]; + CGContextSetShouldAntialias(viewContext, FALSE); + CGContextSetInterpolationQuality(viewContext, kCGInterpolationNone); + + /* The obtained 'rect' is actually a union of all dirty rects, let's ask for an explicit list of rects instead */ + const NSRect *dirtyRects; + NSInteger dirtyRectCount; + [ self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount ]; + + /* We need an Image in order to do blitting, but as we don't touch the context between this call and drawing no copying will actually be done here */ + CGImageRef fullImage = CGBitmapContextCreateImage(driver->cgcontext); + + /* Calculate total area we are blitting */ + uint32 blitArea = 0; + for (int n = 0; n < dirtyRectCount; n++) { + blitArea += (uint32)(dirtyRects[n].size.width * dirtyRects[n].size.height); + } + + /* + * This might be completely stupid, but in my extremely subjective opinion it feels faster + * The point is, if we're blitting less than 50% of the dirty rect union then it's still a good idea to blit each dirty + * rect separately but if we blit more than that, it's just cheaper to blit the entire union in one pass. + * Feel free to remove or find an even better value than 50% ... / blackis + */ + NSRect frameRect = [ self frame ]; + if (blitArea / (float)(invalidRect.size.width * invalidRect.size.height) > 0.5f) { + NSRect rect = invalidRect; + CGRect clipRect; + CGRect blitRect; + + blitRect.origin.x = rect.origin.x; + blitRect.origin.y = rect.origin.y; + blitRect.size.width = rect.size.width; + blitRect.size.height = rect.size.height; + + clipRect.origin.x = rect.origin.x; + clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; + + clipRect.size.width = rect.size.width; + clipRect.size.height = rect.size.height; + + /* Blit dirty part of image */ + CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); + CGContextDrawImage(viewContext, blitRect, clippedImage); + CGImageRelease(clippedImage); + } else { + for (int n = 0; n < dirtyRectCount; n++) { + NSRect rect = dirtyRects[n]; + CGRect clipRect; + CGRect blitRect; + + blitRect.origin.x = rect.origin.x; + blitRect.origin.y = rect.origin.y; + blitRect.size.width = rect.size.width; + blitRect.size.height = rect.size.height; + + clipRect.origin.x = rect.origin.x; + clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; + + clipRect.size.width = rect.size.width; + clipRect.size.height = rect.size.height; + + /* Blit dirty part of image */ + CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); + CGContextDrawImage(viewContext, blitRect, clippedImage); + CGImageRelease(clippedImage); + } + } + + CGImageRelease(fullImage); +} + +@end + #endif /* WITH_COCOA */ diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 8f72836cca..dd1d269f8d 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -24,6 +24,7 @@ #include "../../openttd.h" #include "../../debug.h" +#include "../../rev.h" #include "cocoa_v.h" #include "cocoa_wnd.h" #include "../../string_func.h" @@ -345,6 +346,15 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; self->driver = drv; + + [ self setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; + [ self setAcceptsMouseMovedEvents:YES ]; + + std::string caption = std::string{"OpenTTD "} + _openttd_revision; + NSString *nsscaption = [ [ NSString alloc ] initWithUTF8String:caption.c_str() ]; + [ self setTitle:nsscaption ]; + [ self setMiniwindowTitle:nsscaption ]; + [ nsscaption release ]; } return self; From f4bd54fedd40806ff34d884c0fa17e0b7403ede1 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 02:49:09 +0100 Subject: [PATCH 077/275] Codechange: [OSX] Move mouse event handling to our NSView. --- src/video/cocoa/cocoa_v.h | 4 - src/video/cocoa/cocoa_v.mm | 52 +-------- src/video/cocoa/cocoa_wnd.h | 8 ++ src/video/cocoa/cocoa_wnd.mm | 147 +++++++++++++++++++++++- src/video/cocoa/event.mm | 214 +---------------------------------- 5 files changed, 154 insertions(+), 271 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 4c53cdb8fa..0112f57515 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -78,11 +78,7 @@ protected: Dimension GetScreenSize() const override; private: - NSPoint GetMouseLocation(NSEvent *event); - bool MouseIsInsideView(NSPoint *pt); - CGPoint PrivateLocalToCG(NSPoint *p); bool PollEvent(); // In event.mm. - void MouseMovedEvent(int x, int y); // In event.mm. bool IsFullscreen(); void GameSizeChanged(); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 88f461234f..07640a0f83 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -397,6 +397,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) [ this->window setContentView:this->cocoaview ]; [ this->cocoaview addSubview:draw_view ]; + [ this->window makeFirstResponder:this->cocoaview ]; [ draw_view release ]; [ this->window setColorSpace:[ NSColorSpace sRGBColorSpace ] ]; @@ -497,57 +498,6 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) this->num_dirty_rects = lengthof(this->dirty_rects); } -/** - * Convert local coordinate to window server (CoreGraphics) coordinate - * @param p local coordinates - * @return window driver coordinates - */ -CGPoint VideoDriver_Cocoa::PrivateLocalToCG(NSPoint *p) -{ - - p->y = this->window_height - p->y; - *p = [ this->cocoaview convertPoint:*p toView:nil ]; - *p = [ this->window convertRectToScreen:NSMakeRect(p->x, p->y, 0, 0) ].origin; - - p->y = NSScreen.screens[0].frame.size.height - p->y; - - CGPoint cgp; - cgp.x = p->x; - cgp.y = p->y; - - return cgp; -} - -/** - * Return the mouse location - * @param event UI event - * @return mouse location as NSPoint - */ -NSPoint VideoDriver_Cocoa::GetMouseLocation(NSEvent *event) -{ - NSPoint pt; - - if ( [ event window ] == nil) { - pt = [ this->cocoaview convertPoint:[ [ this->cocoaview window ] convertRectFromScreen:NSMakeRect([ event locationInWindow ].x, [ event locationInWindow ].y, 0, 0) ].origin fromView:nil ]; - } else { - pt = [ event locationInWindow ]; - } - - pt.y = this->window_height - pt.y; - - return pt; -} - -/** - * Return whether the mouse is within our view - * @param pt Mouse coordinates - * @return Whether mouse coordinates are within view - */ -bool VideoDriver_Cocoa::MouseIsInsideView(NSPoint *pt) -{ - return [ cocoaview mouse:*pt inRect:[ this->cocoaview bounds ] ]; -} - /** Clear buffer to opaque black. */ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height) { diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 449b457af1..98ed7df7ec 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -14,6 +14,13 @@ class VideoDriver_Cocoa; +/* Right Mouse Button Emulation enum */ +enum RightMouseButtonEmulationState { + RMBE_COMMAND = 0, + RMBE_CONTROL = 1, + RMBE_OFF = 2, +}; + extern NSString *OTTDMainLaunchGameEngine; /** Category of NSCursor to allow cursor showing/hiding */ @@ -34,6 +41,7 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSView to support mouse awareness and text input. */ @interface OTTD_CocoaView : NSView +- (NSPoint)mousePositionFromEvent:(NSEvent *)e; @end /** Delegate for our NSWindow to send ask for quit on close */ diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index dd1d269f8d..e9ea697057 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -27,6 +27,7 @@ #include "../../rev.h" #include "cocoa_v.h" #include "cocoa_wnd.h" +#include "../../settings_type.h" #include "../../string_func.h" #include "../../gfx_func.h" #include "../../window_func.h" @@ -348,7 +349,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel self->driver = drv; [ self setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; - [ self setAcceptsMouseMovedEvents:YES ]; std::string caption = std::string{"OpenTTD "} + _openttd_revision; NSString *nsscaption = [ [ NSString alloc ] initWithUTF8String:caption.c_str() ]; @@ -417,7 +417,9 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @end -@implementation OTTD_CocoaView +@implementation OTTD_CocoaView { + float _current_magnification; +} /** * Allow to handle events @@ -451,7 +453,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (void)viewDidMoveToWindow { /* Install mouse tracking area. */ - NSTrackingAreaOptions track_opt = NSTrackingInVisibleRect | NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | NSTrackingCursorUpdate; + NSTrackingAreaOptions track_opt = NSTrackingInVisibleRect | NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate; NSTrackingArea *track = [ [ NSTrackingArea alloc ] initWithRect:[ self bounds ] options:track_opt owner:self userInfo:nil ]; [ self addTrackingArea:track ]; [ track release ]; @@ -472,6 +474,145 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel _cursor.in_window = false; } +/** + * Return the mouse location + * @param event UI event + * @return mouse location as NSPoint + */ +- (NSPoint)mousePositionFromEvent:(NSEvent *)e +{ + NSPoint pt = e.locationInWindow; + if ([ e window ] == nil) pt = [ self.window convertRectFromScreen:NSMakeRect(pt.x, pt.y, 0, 0) ].origin; + pt = [ self convertPoint:pt fromView:nil ]; + + pt.y = self.bounds.size.height - pt.y; + + return pt; +} + +- (void)internalMouseMoveEvent:(NSEvent *)event +{ + NSPoint pt = [ self mousePositionFromEvent:event ]; + + if (_cursor.UpdateCursorPosition(pt.x, pt.y, false) && [ NSApp isActive ]) { + /* Warping cursor when in foreground */ + NSPoint warp = [ self convertPoint:NSMakePoint(_cursor.pos.x, self.bounds.size.height - _cursor.pos.y) toView:nil ]; + warp = [ self.window convertRectToScreen:NSMakeRect(warp.x, warp.y, 0, 0) ].origin; + warp.y = NSScreen.screens[0].frame.size.height - warp.y; + + /* Do the actual warp */ + CGWarpMouseCursorPosition(NSPointToCGPoint(warp)); + /* this is the magic call that fixes cursor "freezing" after warp */ + CGAssociateMouseAndMouseCursorPosition(true); + } + HandleMouseEvents(); +} + +- (BOOL)emulateRightButton:(NSEvent *)event +{ + uint32 keymask = 0; + if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; + if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; + + return (event.modifierFlags & keymask) != 0; +} + +- (void)mouseMoved:(NSEvent *)event +{ + [ self internalMouseMoveEvent:event ]; +} + +- (void)mouseDragged:(NSEvent *)event +{ + [ self internalMouseMoveEvent:event ]; +} +- (void)mouseDown:(NSEvent *)event +{ + if ([ self emulateRightButton:event ]) { + [ self rightMouseDown:event ]; + } else { + _left_button_down = true; + [ self internalMouseMoveEvent:event ]; + } +} +- (void)mouseUp:(NSEvent *)event +{ + if ([ self emulateRightButton:event ]) { + [ self rightMouseUp:event ]; + } else { + _left_button_down = false; + _left_button_clicked = false; + [ self internalMouseMoveEvent:event ]; + } +} + +- (void)rightMouseDragged:(NSEvent *)event +{ + [ self internalMouseMoveEvent:event ]; +} +- (void)rightMouseDown:(NSEvent *)event +{ + _right_button_down = true; + _right_button_clicked = true; + [ self internalMouseMoveEvent:event ]; +} +- (void)rightMouseUp:(NSEvent *)event +{ + _right_button_down = false; + [ self internalMouseMoveEvent:event ]; +} + +- (void)scrollWheel:(NSEvent *)event +{ + if ([ event deltaY ] > 0.0) { /* Scroll up */ + _cursor.wheel--; + } else if ([ event deltaY ] < 0.0) { /* Scroll down */ + _cursor.wheel++; + } /* else: deltaY was 0.0 and we don't want to do anything */ + + /* Update the scroll count for 2D scrolling */ + CGFloat deltaX; + CGFloat deltaY; + + /* Use precise scrolling-specific deltas if they're supported. */ + if ([ event respondsToSelector:@selector(hasPreciseScrollingDeltas) ]) { + /* No precise deltas indicates a scroll wheel is being used, so we don't want 2D scrolling. */ + if (![ event hasPreciseScrollingDeltas ]) return; + + deltaX = [ event scrollingDeltaX ] * 0.5f; + deltaY = [ event scrollingDeltaY ] * 0.5f; + } else { + deltaX = [ event deltaX ] * 5; + deltaY = [ event deltaY ] * 5; + } + + _cursor.h_wheel -= (int)(deltaX * _settings_client.gui.scrollwheel_multiplier); + _cursor.v_wheel -= (int)(deltaY * _settings_client.gui.scrollwheel_multiplier); +} + +- (void)magnifyWithEvent:(NSEvent *)event +{ + /* Pinch open or close gesture. */ + self->_current_magnification += [ event magnification ] * 5.0f; + + while (self->_current_magnification >= 1.0f) { + self->_current_magnification -= 1.0f; + _cursor.wheel--; + HandleMouseEvents(); + } + while (self->_current_magnification <= -1.0f) { + self->_current_magnification += 1.0f; + _cursor.wheel++; + HandleMouseEvents(); + } +} + +- (void)endGestureWithEvent:(NSEvent *)event +{ + /* Gesture ended. */ + self->_current_magnification = 0.0f; +} + /** Insert the given text at the given range. */ - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 00559e6bce..d6c4e5552c 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -27,6 +27,7 @@ #include "../../settings_type.h" #include "../../core/geometry_type.hpp" #include "cocoa_v.h" +#include "cocoa_wnd.h" #include "cocoa_keys.h" #include "../../blitter/factory.hpp" #include "../../gfx_func.h" @@ -48,18 +49,8 @@ */ -/* Right Mouse Button Emulation enum */ -enum RightMouseButtonEmulationState { - RMBE_COMMAND, - RMBE_CONTROL, - RMBE_OFF, -}; - - static unsigned int _current_mods; static bool _tab_is_down; -static bool _emulating_right_button; -static float _current_magnification; #ifdef _DEBUG static uint32 _tEvent; #endif @@ -300,47 +291,6 @@ static void QZ_DoUnsidedModifiers(unsigned int newMods) _current_mods = newMods; } -void VideoDriver_Cocoa::MouseMovedEvent(int x, int y) -{ - if (_cursor.UpdateCursorPosition(x, y, false) && [ NSApp isActive ]) { - /* Warping cursor when in foreground */ - NSPoint p = NSMakePoint(_cursor.pos.x, _cursor.pos.y); - CGPoint cgp = this->PrivateLocalToCG(&p); - - /* Do the actual warp */ - CGWarpMouseCursorPosition(cgp); - /* this is the magic call that fixes cursor "freezing" after warp */ - CGAssociateMouseAndMouseCursorPosition(true); - } - HandleMouseEvents(); -} - - -static void QZ_MouseButtonEvent(int button, BOOL down) -{ - switch (button) { - case 0: - if (down) { - _left_button_down = true; - } else { - _left_button_down = false; - _left_button_clicked = false; - } - HandleMouseEvents(); - break; - - case 1: - if (down) { - _right_button_down = true; - _right_button_clicked = true; - } else { - _right_button_down = false; - } - HandleMouseEvents(); - break; - } -} - @@ -365,111 +315,7 @@ bool VideoDriver_Cocoa::PollEvent() QZ_DoUnsidedModifiers( [ event modifierFlags ] ); NSString *chars; - NSPoint pt; switch ([ event type ]) { - case NSMouseMoved: - case NSOtherMouseDragged: - case NSLeftMouseDragged: - pt = this->GetMouseLocation(event); - if (!this->MouseIsInsideView(&pt) && !_emulating_right_button) { - [ NSApp sendEvent:event ]; - break; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - break; - - case NSRightMouseDragged: - pt = this->GetMouseLocation(event); - this->MouseMovedEvent((int)pt.x, (int)pt.y); - break; - - case NSLeftMouseDown: - { - uint32 keymask = 0; - if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; - if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; - - pt = this->GetMouseLocation(event); - - if (!([ event modifierFlags ] & keymask) || !this->MouseIsInsideView(&pt)) { - [ NSApp sendEvent:event ]; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - - /* Right mouse button emulation */ - if ([ event modifierFlags ] & keymask) { - _emulating_right_button = true; - QZ_MouseButtonEvent(1, YES); - } else { - QZ_MouseButtonEvent(0, YES); - } - break; - } - case NSLeftMouseUp: - [ NSApp sendEvent:event ]; - - pt = this->GetMouseLocation(event); - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - - /* Right mouse button emulation */ - if (_emulating_right_button) { - _emulating_right_button = false; - QZ_MouseButtonEvent(1, NO); - } else { - QZ_MouseButtonEvent(0, NO); - } - break; - - case NSRightMouseDown: - pt = this->GetMouseLocation(event); - if (!this->MouseIsInsideView(&pt)) { - [ NSApp sendEvent:event ]; - break; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent(1, YES); - break; - - case NSRightMouseUp: - pt = this->GetMouseLocation(event); - if (!this->MouseIsInsideView(&pt)) { - [ NSApp sendEvent:event ]; - break; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent(1, NO); - break; - -#if 0 - /* This is not needed since openttd currently only use two buttons */ - case NSOtherMouseDown: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - [ NSApp sendEvent:event ]; - break; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent([ event buttonNumber ], YES); - break; - - case NSOtherMouseUp: - pt = QZ_GetMouseLocation(event); - if (!QZ_MouseIsInsideView(&pt)) { - [ NSApp sendEvent:event ]; - break; - } - - this->MouseMovedEvent((int)pt.x, (int)pt.y); - QZ_MouseButtonEvent([ event buttonNumber ], NO); - break; -#endif - case NSKeyDown: { /* Quit, hide and minimize */ switch ([ event keyCode ]) { @@ -513,64 +359,6 @@ bool VideoDriver_Cocoa::PollEvent() QZ_KeyEvent([ event keyCode ], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO); break; - case NSScrollWheel: - if ([ event deltaY ] > 0.0) { /* Scroll up */ - _cursor.wheel--; - } else if ([ event deltaY ] < 0.0) { /* Scroll down */ - _cursor.wheel++; - } /* else: deltaY was 0.0 and we don't want to do anything */ - - /* Update the scroll count for 2D scrolling */ - CGFloat deltaX; - CGFloat deltaY; - - /* Use precise scrolling-specific deltas if they're supported. */ - if ([event respondsToSelector:@selector(hasPreciseScrollingDeltas)]) { - /* No precise deltas indicates a scroll wheel is being used, so we don't want 2D scrolling. */ - if (![ event hasPreciseScrollingDeltas ]) break; - - deltaX = [ event scrollingDeltaX ] * 0.5f; - deltaY = [ event scrollingDeltaY ] * 0.5f; - } else { - deltaX = [ event deltaX ] * 5; - deltaY = [ event deltaY ] * 5; - } - - _cursor.h_wheel -= (int)(deltaX * _settings_client.gui.scrollwheel_multiplier); - _cursor.v_wheel -= (int)(deltaY * _settings_client.gui.scrollwheel_multiplier); - - break; - - case NSEventTypeMagnify: - /* Pinch open or close gesture. */ - _current_magnification += [ event magnification ] * 5.0f; - - while (_current_magnification >= 1.0f) { - _current_magnification -= 1.0f; - _cursor.wheel--; - HandleMouseEvents(); - } - while (_current_magnification <= -1.0f) { - _current_magnification += 1.0f; - _cursor.wheel++; - HandleMouseEvents(); - } - break; - - case NSEventTypeEndGesture: - /* Gesture ended. */ - _current_magnification = 0.0f; - break; - - case NSCursorUpdate: - case NSMouseEntered: - case NSMouseExited: - /* Catch these events if the cursor is dragging. During dragging, we reset - * the mouse position programmatically, which would trigger OS X to show - * the default arrow cursor if the events are propagated. */ - if (_cursor.fix_at) break; - FALLTHROUGH; - default: [ NSApp sendEvent:event ]; } From 063b90b97db14e19a339a3970eb33c6ba6e6d37f Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 20:03:33 +0100 Subject: [PATCH 078/275] Codechange: [OSX] Move key event handling to our view. --- src/video/cocoa/cocoa_keys.h | 122 ++++++++++++++ src/video/cocoa/cocoa_wnd.mm | 173 ++++++++++++++++++++ src/video/cocoa/event.mm | 297 +---------------------------------- 3 files changed, 302 insertions(+), 290 deletions(-) diff --git a/src/video/cocoa/cocoa_keys.h b/src/video/cocoa/cocoa_keys.h index def145d242..e09fe3c8a7 100644 --- a/src/video/cocoa/cocoa_keys.h +++ b/src/video/cocoa/cocoa_keys.h @@ -131,4 +131,126 @@ #define QZ_IBOOK_DOWN 0x3D #define QZ_IBOOK_UP 0x3E + +struct VkMapping { + unsigned short vk_from; + byte map_to; +}; + +#define AS(x, z) {x, z} + +static const VkMapping _vk_mapping[] = { + AS(QZ_BACKQUOTE, WKC_BACKQUOTE), // key left of '1' + AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode + + /* Pageup stuff + up/down */ + AS(QZ_PAGEUP, WKC_PAGEUP), + AS(QZ_PAGEDOWN, WKC_PAGEDOWN), + + AS(QZ_UP, WKC_UP), + AS(QZ_DOWN, WKC_DOWN), + AS(QZ_LEFT, WKC_LEFT), + AS(QZ_RIGHT, WKC_RIGHT), + + AS(QZ_HOME, WKC_HOME), + AS(QZ_END, WKC_END), + + AS(QZ_INSERT, WKC_INSERT), + AS(QZ_DELETE, WKC_DELETE), + + /* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */ + AS(QZ_a, 'A'), + AS(QZ_b, 'B'), + AS(QZ_c, 'C'), + AS(QZ_d, 'D'), + AS(QZ_e, 'E'), + AS(QZ_f, 'F'), + AS(QZ_g, 'G'), + AS(QZ_h, 'H'), + AS(QZ_i, 'I'), + AS(QZ_j, 'J'), + AS(QZ_k, 'K'), + AS(QZ_l, 'L'), + AS(QZ_m, 'M'), + AS(QZ_n, 'N'), + AS(QZ_o, 'O'), + AS(QZ_p, 'P'), + AS(QZ_q, 'Q'), + AS(QZ_r, 'R'), + AS(QZ_s, 'S'), + AS(QZ_t, 'T'), + AS(QZ_u, 'U'), + AS(QZ_v, 'V'), + AS(QZ_w, 'W'), + AS(QZ_x, 'X'), + AS(QZ_y, 'Y'), + AS(QZ_z, 'Z'), + /* Same thing for digits */ + AS(QZ_0, '0'), + AS(QZ_1, '1'), + AS(QZ_2, '2'), + AS(QZ_3, '3'), + AS(QZ_4, '4'), + AS(QZ_5, '5'), + AS(QZ_6, '6'), + AS(QZ_7, '7'), + AS(QZ_8, '8'), + AS(QZ_9, '9'), + + AS(QZ_ESCAPE, WKC_ESC), + AS(QZ_PAUSE, WKC_PAUSE), + AS(QZ_BACKSPACE, WKC_BACKSPACE), + + AS(QZ_SPACE, WKC_SPACE), + AS(QZ_RETURN, WKC_RETURN), + AS(QZ_TAB, WKC_TAB), + + /* Function keys */ + AS(QZ_F1, WKC_F1), + AS(QZ_F2, WKC_F2), + AS(QZ_F3, WKC_F3), + AS(QZ_F4, WKC_F4), + AS(QZ_F5, WKC_F5), + AS(QZ_F6, WKC_F6), + AS(QZ_F7, WKC_F7), + AS(QZ_F8, WKC_F8), + AS(QZ_F9, WKC_F9), + AS(QZ_F10, WKC_F10), + AS(QZ_F11, WKC_F11), + AS(QZ_F12, WKC_F12), + + /* Numeric part */ + AS(QZ_KP0, '0'), + AS(QZ_KP1, '1'), + AS(QZ_KP2, '2'), + AS(QZ_KP3, '3'), + AS(QZ_KP4, '4'), + AS(QZ_KP5, '5'), + AS(QZ_KP6, '6'), + AS(QZ_KP7, '7'), + AS(QZ_KP8, '8'), + AS(QZ_KP9, '9'), + AS(QZ_KP_DIVIDE, WKC_NUM_DIV), + AS(QZ_KP_MULTIPLY, WKC_NUM_MUL), + AS(QZ_KP_MINUS, WKC_NUM_MINUS), + AS(QZ_KP_PLUS, WKC_NUM_PLUS), + AS(QZ_KP_ENTER, WKC_NUM_ENTER), + AS(QZ_KP_PERIOD, WKC_NUM_DECIMAL), + + /* Other non-letter keys */ + AS(QZ_SLASH, WKC_SLASH), + AS(QZ_SEMICOLON, WKC_SEMICOLON), + AS(QZ_EQUALS, WKC_EQUALS), + AS(QZ_LEFTBRACKET, WKC_L_BRACKET), + AS(QZ_BACKSLASH, WKC_BACKSLASH), + AS(QZ_RIGHTBRACKET, WKC_R_BRACKET), + + AS(QZ_QUOTE, WKC_SINGLEQUOTE), + AS(QZ_COMMA, WKC_COMMA), + AS(QZ_MINUS, WKC_MINUS), + AS(QZ_PERIOD, WKC_PERIOD) +}; + +#undef AS + #endif diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index e9ea697057..2755b26ff4 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -34,6 +34,10 @@ #include "../../window_gui.h" +/* Table data for key mapping. */ +#include "cocoa_keys.h" + + /** * Important notice regarding all modifications!!!!!!! * There are certain limitations because the file is objective C++. @@ -47,6 +51,8 @@ NSString *OTTDMainLaunchGameEngine = @"ottdmain_launch_game_engine"; +bool _tab_is_down; + static bool _cocoa_video_dialog = false; static OTTDMain *_ottd_main; @@ -89,6 +95,31 @@ static const char *Utf8AdvanceByUtf16Units(const char *str, NSUInteger count) return str; } +/** + * Convert a NSString to an UTF-32 encoded string. + * @param s String to convert. + * @return Vector of UTF-32 characters. + */ +static std::vector NSStringToUTF32(NSString *s) +{ + std::vector unicode_str; + + unichar lead = 0; + for (NSUInteger i = 0; i < s.length; i++) { + unichar c = [ s characterAtIndex:i ]; + if (Utf16IsLeadSurrogate(c)) { + lead = c; + continue; + } else if (Utf16IsTrailSurrogate(c)) { + if (lead != 0) unicode_str.push_back(Utf16DecodeSurrogate(lead, c)); + } else { + unicode_str.push_back(c); + } + } + + return unicode_str; +} + /** * The main class of the application, the application's delegate. @@ -419,6 +450,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @implementation OTTD_CocoaView { float _current_magnification; + NSUInteger _current_mods; } /** @@ -614,6 +646,147 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } +- (BOOL)internalHandleKeycode:(unsigned short)keycode unicode:(WChar)unicode pressed:(BOOL)down modifiers:(NSUInteger)modifiers +{ + switch (keycode) { + case QZ_UP: SB(_dirkeys, 1, 1, down); break; + case QZ_DOWN: SB(_dirkeys, 3, 1, down); break; + case QZ_LEFT: SB(_dirkeys, 0, 1, down); break; + case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break; + + case QZ_TAB: _tab_is_down = down; break; + + case QZ_RETURN: + case QZ_f: + if (down && (modifiers & NSCommandKeyMask)) { + VideoDriver::GetInstance()->ToggleFullscreen(!_fullscreen); + } + break; + + case QZ_v: + if (down && EditBoxInGlobalFocus() && (modifiers & (NSCommandKeyMask | NSControlKeyMask))) { + HandleKeypress(WKC_CTRL | 'V', unicode); + } + break; + case QZ_u: + if (down && EditBoxInGlobalFocus() && (modifiers & (NSCommandKeyMask | NSControlKeyMask))) { + HandleKeypress(WKC_CTRL | 'U', unicode); + } + break; + } + + BOOL interpret_keys = YES; + if (down) { + /* Map keycode to OTTD code. */ + auto vk = std::find_if(std::begin(_vk_mapping), std::end(_vk_mapping), [=](const VkMapping &m) { return m.vk_from == keycode; }); + uint32 pressed_key = vk != std::end(_vk_mapping) ? vk->map_to : 0; + + if (modifiers & NSShiftKeyMask) pressed_key |= WKC_SHIFT; + if (modifiers & NSControlKeyMask) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); + if (modifiers & NSAlternateKeyMask) pressed_key |= WKC_ALT; + if (modifiers & NSCommandKeyMask) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); + + static bool console = false; + + /* The second backquote may have a character, which we don't want to interpret. */ + if (pressed_key == WKC_BACKQUOTE && (console || unicode == 0)) { + if (!console) { + /* Backquote is a dead key, require a double press for hotkey behaviour (i.e. console). */ + console = true; + return YES; + } else { + /* Second backquote, don't interpret as text input. */ + interpret_keys = NO; + } + } + console = false; + + /* Don't handle normal characters if an edit box has the focus. */ + if (!EditBoxInGlobalFocus() || IsInsideMM(pressed_key & ~WKC_SPECIAL_KEYS, WKC_F1, WKC_PAUSE + 1)) { + HandleKeypress(pressed_key, unicode); + } + DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key); + } else { + DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode); + } + + return interpret_keys; +} + +- (void)keyDown:(NSEvent *)event +{ + /* Quit, hide and minimize */ + switch (event.keyCode) { + case QZ_q: + case QZ_h: + case QZ_m: + if (event.modifierFlags & NSCommandKeyMask) { + [ self interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; + } + break; + } + + /* Convert UTF-16 characters to UCS-4 chars. */ + std::vector unicode_str = NSStringToUTF32([ event characters ]); + if (unicode_str.empty()) unicode_str.push_back(0); + + if (EditBoxInGlobalFocus()) { + if ([ self internalHandleKeycode:event.keyCode unicode:unicode_str[0] pressed:YES modifiers:event.modifierFlags ]) { + [ self interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; + } + } else { + [ self internalHandleKeycode:event.keyCode unicode:unicode_str[0] pressed:YES modifiers:event.modifierFlags ]; + for (size_t i = 1; i < unicode_str.size(); i++) { + [ self internalHandleKeycode:0 unicode:unicode_str[i] pressed:YES modifiers:event.modifierFlags ]; + } + } +} + +- (void)keyUp:(NSEvent *)event +{ + /* Quit, hide and minimize */ + switch (event.keyCode) { + case QZ_q: + case QZ_h: + case QZ_m: + if (event.modifierFlags & NSCommandKeyMask) { + [ self interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; + } + break; + } + + /* Convert UTF-16 characters to UCS-4 chars. */ + std::vector unicode_str = NSStringToUTF32([ event characters ]); + if (unicode_str.empty()) unicode_str.push_back(0); + + [ self internalHandleKeycode:event.keyCode unicode:unicode_str[0] pressed:NO modifiers:event.modifierFlags ]; +} + +- (void)flagsChanged:(NSEvent *)event +{ + const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA }; + + NSUInteger newMods = event.modifierFlags; + if (self->_current_mods == newMods) return; + + /* Iterate through the bits, testing each against the current modifiers */ + for (unsigned int i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + unsigned int currentMask, newMask; + + currentMask = self->_current_mods & bit; + newMask = newMods & bit; + + if (currentMask && currentMask != newMask) { // modifier up event + [ self internalHandleKeycode:mapping[i] unicode:0 pressed:NO modifiers:newMods ]; + } else if (newMask && currentMask != newMask) { // modifier down event + [ self internalHandleKeycode:mapping[i] unicode:0 pressed:YES modifiers:newMods ]; + } + } + + _current_mods = newMods; +} + + /** Insert the given text at the given range. */ - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index d6c4e5552c..17d4c437dc 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -28,7 +28,6 @@ #include "../../core/geometry_type.hpp" #include "cocoa_v.h" #include "cocoa_wnd.h" -#include "cocoa_keys.h" #include "../../blitter/factory.hpp" #include "../../gfx_func.h" #include "../../network/network.h" @@ -48,9 +47,8 @@ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information. */ +extern bool _tab_is_down; -static unsigned int _current_mods; -static bool _tab_is_down; #ifdef _DEBUG static uint32 _tEvent; #endif @@ -64,236 +62,6 @@ static uint32 GetTick() return tim.tv_usec / 1000 + tim.tv_sec * 1000; } -struct VkMapping { - unsigned short vk_from; - byte map_to; -}; - -#define AS(x, z) {x, z} - -static const VkMapping _vk_mapping[] = { - AS(QZ_BACKQUOTE, WKC_BACKQUOTE), // key left of '1' - AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode - - /* Pageup stuff + up/down */ - AS(QZ_PAGEUP, WKC_PAGEUP), - AS(QZ_PAGEDOWN, WKC_PAGEDOWN), - - AS(QZ_UP, WKC_UP), - AS(QZ_DOWN, WKC_DOWN), - AS(QZ_LEFT, WKC_LEFT), - AS(QZ_RIGHT, WKC_RIGHT), - - AS(QZ_HOME, WKC_HOME), - AS(QZ_END, WKC_END), - - AS(QZ_INSERT, WKC_INSERT), - AS(QZ_DELETE, WKC_DELETE), - - /* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */ - AS(QZ_a, 'A'), - AS(QZ_b, 'B'), - AS(QZ_c, 'C'), - AS(QZ_d, 'D'), - AS(QZ_e, 'E'), - AS(QZ_f, 'F'), - AS(QZ_g, 'G'), - AS(QZ_h, 'H'), - AS(QZ_i, 'I'), - AS(QZ_j, 'J'), - AS(QZ_k, 'K'), - AS(QZ_l, 'L'), - AS(QZ_m, 'M'), - AS(QZ_n, 'N'), - AS(QZ_o, 'O'), - AS(QZ_p, 'P'), - AS(QZ_q, 'Q'), - AS(QZ_r, 'R'), - AS(QZ_s, 'S'), - AS(QZ_t, 'T'), - AS(QZ_u, 'U'), - AS(QZ_v, 'V'), - AS(QZ_w, 'W'), - AS(QZ_x, 'X'), - AS(QZ_y, 'Y'), - AS(QZ_z, 'Z'), - /* Same thing for digits */ - AS(QZ_0, '0'), - AS(QZ_1, '1'), - AS(QZ_2, '2'), - AS(QZ_3, '3'), - AS(QZ_4, '4'), - AS(QZ_5, '5'), - AS(QZ_6, '6'), - AS(QZ_7, '7'), - AS(QZ_8, '8'), - AS(QZ_9, '9'), - - AS(QZ_ESCAPE, WKC_ESC), - AS(QZ_PAUSE, WKC_PAUSE), - AS(QZ_BACKSPACE, WKC_BACKSPACE), - - AS(QZ_SPACE, WKC_SPACE), - AS(QZ_RETURN, WKC_RETURN), - AS(QZ_TAB, WKC_TAB), - - /* Function keys */ - AS(QZ_F1, WKC_F1), - AS(QZ_F2, WKC_F2), - AS(QZ_F3, WKC_F3), - AS(QZ_F4, WKC_F4), - AS(QZ_F5, WKC_F5), - AS(QZ_F6, WKC_F6), - AS(QZ_F7, WKC_F7), - AS(QZ_F8, WKC_F8), - AS(QZ_F9, WKC_F9), - AS(QZ_F10, WKC_F10), - AS(QZ_F11, WKC_F11), - AS(QZ_F12, WKC_F12), - - /* Numeric part */ - AS(QZ_KP0, '0'), - AS(QZ_KP1, '1'), - AS(QZ_KP2, '2'), - AS(QZ_KP3, '3'), - AS(QZ_KP4, '4'), - AS(QZ_KP5, '5'), - AS(QZ_KP6, '6'), - AS(QZ_KP7, '7'), - AS(QZ_KP8, '8'), - AS(QZ_KP9, '9'), - AS(QZ_KP_DIVIDE, WKC_NUM_DIV), - AS(QZ_KP_MULTIPLY, WKC_NUM_MUL), - AS(QZ_KP_MINUS, WKC_NUM_MINUS), - AS(QZ_KP_PLUS, WKC_NUM_PLUS), - AS(QZ_KP_ENTER, WKC_NUM_ENTER), - AS(QZ_KP_PERIOD, WKC_NUM_DECIMAL), - - /* Other non-letter keys */ - AS(QZ_SLASH, WKC_SLASH), - AS(QZ_SEMICOLON, WKC_SEMICOLON), - AS(QZ_EQUALS, WKC_EQUALS), - AS(QZ_LEFTBRACKET, WKC_L_BRACKET), - AS(QZ_BACKSLASH, WKC_BACKSLASH), - AS(QZ_RIGHTBRACKET, WKC_R_BRACKET), - - AS(QZ_QUOTE, WKC_SINGLEQUOTE), - AS(QZ_COMMA, WKC_COMMA), - AS(QZ_MINUS, WKC_MINUS), - AS(QZ_PERIOD, WKC_PERIOD) -}; - - -static uint32 QZ_MapKey(unsigned short sym) -{ - uint32 key = 0; - - for (const VkMapping *map = _vk_mapping; map != endof(_vk_mapping); ++map) { - if (sym == map->vk_from) { - key = map->map_to; - break; - } - } - - if (_current_mods & NSShiftKeyMask) key |= WKC_SHIFT; - if (_current_mods & NSControlKeyMask) key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); - if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT; - if (_current_mods & NSCommandKeyMask) key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); - - return key; -} - -static bool QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down) -{ - bool interpret_keys = true; - - switch (keycode) { - case QZ_UP: SB(_dirkeys, 1, 1, down); break; - case QZ_DOWN: SB(_dirkeys, 3, 1, down); break; - case QZ_LEFT: SB(_dirkeys, 0, 1, down); break; - case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break; - - case QZ_TAB: _tab_is_down = down; break; - - case QZ_RETURN: - case QZ_f: - if (down && (_current_mods & NSCommandKeyMask)) { - VideoDriver::GetInstance()->ToggleFullscreen(!_fullscreen); - } - break; - - case QZ_v: - if (down && EditBoxInGlobalFocus() && (_current_mods & (NSCommandKeyMask | NSControlKeyMask))) { - HandleKeypress(WKC_CTRL | 'V', unicode); - } - break; - case QZ_u: - if (down && EditBoxInGlobalFocus() && (_current_mods & (NSCommandKeyMask | NSControlKeyMask))) { - HandleKeypress(WKC_CTRL | 'U', unicode); - } - break; - } - - if (down) { - uint32 pressed_key = QZ_MapKey(keycode); - - static bool console = false; - - /* The second backquote may have a character, which we don't want to interpret. */ - if (pressed_key == WKC_BACKQUOTE && (console || unicode == 0)) { - if (!console) { - /* Backquote is a dead key, require a double press for hotkey behaviour (i.e. console). */ - console = true; - return true; - } else { - /* Second backquote, don't interpret as text input. */ - interpret_keys = false; - } - } - console = false; - - /* Don't handle normal characters if an edit box has the focus. */ - if (!EditBoxInGlobalFocus() || IsInsideMM(pressed_key & ~WKC_SPECIAL_KEYS, WKC_F1, WKC_PAUSE + 1)) { - HandleKeypress(pressed_key, unicode); - } - DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key); - } else { - DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode); - } - - return interpret_keys; -} - -static void QZ_DoUnsidedModifiers(unsigned int newMods) -{ - const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA }; - - if (_current_mods == newMods) return; - - /* Iterate through the bits, testing each against the current modifiers */ - for (unsigned int i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { - unsigned int currentMask, newMask; - - currentMask = _current_mods & bit; - newMask = newMods & bit; - - if (currentMask && currentMask != newMask) { // modifier up event - /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */ - if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES); - QZ_KeyEvent(mapping[i], 0, NO); - } else if (newMask && currentMask != newMask) { // modifier down event - QZ_KeyEvent(mapping[i], 0, YES); - /* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */ - if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO); - } - } - - _current_mods = newMods; -} - - - - bool VideoDriver_Cocoa::PollEvent() { #ifdef _DEBUG @@ -307,61 +75,8 @@ bool VideoDriver_Cocoa::PollEvent() #endif if (event == nil) return false; - if (!this->active) { - [ NSApp sendEvent:event ]; - return true; - } - QZ_DoUnsidedModifiers( [ event modifierFlags ] ); - - NSString *chars; - switch ([ event type ]) { - case NSKeyDown: { - /* Quit, hide and minimize */ - switch ([ event keyCode ]) { - case QZ_q: - case QZ_h: - case QZ_m: - if ([ event modifierFlags ] & NSCommandKeyMask) { - [ NSApp sendEvent:event ]; - } - break; - } - - chars = [ event characters ]; - unsigned short unicode = [ chars length ] > 0 ? [ chars characterAtIndex:0 ] : 0; - if (EditBoxInGlobalFocus()) { - if (QZ_KeyEvent([ event keyCode ], unicode, YES)) { - [ this->cocoaview interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; - } - } else { - QZ_KeyEvent([ event keyCode ], unicode, YES); - for (uint i = 1; i < [ chars length ]; i++) { - QZ_KeyEvent(0, [ chars characterAtIndex:i ], YES); - } - } - break; - } - - case NSKeyUp: - /* Quit, hide and minimize */ - switch ([ event keyCode ]) { - case QZ_q: - case QZ_h: - case QZ_m: - if ([ event modifierFlags ] & NSCommandKeyMask) { - [ NSApp sendEvent:event ]; - } - break; - } - - chars = [ event characters ]; - QZ_KeyEvent([ event keyCode ], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO); - break; - - default: - [ NSApp sendEvent:event ]; - } + [ NSApp sendEvent:event ]; return true; } @@ -410,8 +125,10 @@ void VideoDriver_Cocoa::GameLoop() break; } + NSUInteger cur_mods = [ NSEvent modifierFlags ]; + #if defined(_DEBUG) - if (_current_mods & NSShiftKeyMask) + if (cur_mods & NSShiftKeyMask) #else if (_tab_is_down) #endif @@ -429,8 +146,8 @@ void VideoDriver_Cocoa::GameLoop() bool old_ctrl_pressed = _ctrl_pressed; - _ctrl_pressed = !!(_current_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); - _shift_pressed = !!(_current_mods & NSShiftKeyMask); + _ctrl_pressed = !!(cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); + _shift_pressed = !!(cur_mods & NSShiftKeyMask); if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); From 23389e949169ee65ca2b53cb09c11f6d4ce2bd67 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 20:09:12 +0100 Subject: [PATCH 079/275] Remove: [OSX] Startup splash screen. It wasn't displayed anyway as it was never copied to the bundle. --- src/os/macosx/CMakeLists.txt | 2 - src/os/macosx/splash.cpp | 185 ----------------------------------- src/os/macosx/splash.h | 17 ---- src/video/cocoa/event.mm | 19 ---- 4 files changed, 223 deletions(-) delete mode 100644 src/os/macosx/splash.cpp delete mode 100644 src/os/macosx/splash.h diff --git a/src/os/macosx/CMakeLists.txt b/src/os/macosx/CMakeLists.txt index 31f6af7d49..6b4f2f279d 100644 --- a/src/os/macosx/CMakeLists.txt +++ b/src/os/macosx/CMakeLists.txt @@ -4,8 +4,6 @@ add_files( macos.h macos.mm osx_stdafx.h - splash.cpp - splash.h string_osx.cpp string_osx.h CONDITION APPLE diff --git a/src/os/macosx/splash.cpp b/src/os/macosx/splash.cpp deleted file mode 100644 index ac2f86425b..0000000000 --- a/src/os/macosx/splash.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file splash.cpp Splash screen support for OSX. */ - -#include "../../stdafx.h" -#include "../../openttd.h" -#include "../../debug.h" -#include "../../gfx_func.h" -#include "../../fileio_func.h" -#include "../../blitter/factory.hpp" -#include "../../core/mem_func.hpp" - -#include "splash.h" - -#ifdef WITH_PNG - -#include - -#include "../../safeguards.h" - -/** - * Handle pnglib error. - * - * @param png_ptr Pointer to png struct. - * @param message Error message text. - */ -static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message) -{ - DEBUG(misc, 0, "[libpng] error: %s - %s", message, (char *)png_get_error_ptr(png_ptr)); - longjmp(png_jmpbuf(png_ptr), 1); -} - -/** - * Handle warning in pnglib. - * - * @param png_ptr Pointer to png struct. - * @param message Warning message text. - */ -static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message) -{ - DEBUG(misc, 1, "[libpng] warning: %s - %s", message, (char *)png_get_error_ptr(png_ptr)); -} - -/** - * Display a splash image shown on startup (WITH_PNG). - */ -void DisplaySplashImage() -{ - FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE, "r", BASESET_DIR); - if (f == nullptr) return; - - png_byte header[8]; - fread(header, sizeof(png_byte), 8, f); - if (png_sig_cmp(header, 0, 8) != 0) { - fclose(f); - return; - } - - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) nullptr, png_my_error, png_my_warning); - - if (png_ptr == nullptr) { - fclose(f); - return; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == nullptr) { - png_destroy_read_struct(&png_ptr, (png_infopp)nullptr, (png_infopp)nullptr); - fclose(f); - return; - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (end_info == nullptr) { - png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)nullptr); - fclose(f); - return; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(f); - return; - } - - png_init_io(png_ptr, f); - png_set_sig_bytes(png_ptr, 8); - - png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); - - uint width = png_get_image_width(png_ptr, info_ptr); - uint height = png_get_image_height(png_ptr, info_ptr); - uint bit_depth = png_get_bit_depth(png_ptr, info_ptr); - uint color_type = png_get_color_type(png_ptr, info_ptr); - - if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) { - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(f); - return; - } - - if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(f); - return; - } - - png_colorp palette; - int num_palette; - png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); - - png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr); - - if (width > (uint) _screen.width) width = _screen.width; - if (height > (uint) _screen.height) height = _screen.height; - - uint xoff = (_screen.width - width) / 2; - uint yoff = (_screen.height - height) / 2; - - switch (BlitterFactory::GetCurrentBlitter()->GetScreenDepth()) { - case 8: { - uint8 *dst_ptr = (uint8 *)_screen.dst_ptr; - /* Initialize buffer */ - MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height); - - for (uint y = 0; y < height; y++) { - uint8 *src = row_pointers[y]; - uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; - - memcpy(dst, src, width); - } - - for (int i = 0; i < num_palette; i++) { - _cur_palette.palette[i].a = i == 0 ? 0 : 0xff; - _cur_palette.palette[i].r = palette[i].red; - _cur_palette.palette[i].g = palette[i].green; - _cur_palette.palette[i].b = palette[i].blue; - } - - _cur_palette.palette[0xff].a = 0xff; - _cur_palette.palette[0xff].r = 0; - _cur_palette.palette[0xff].g = 0; - _cur_palette.palette[0xff].b = 0; - - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - break; - } - case 32: { - uint32 *dst_ptr = (uint32 *)_screen.dst_ptr; - /* Initialize buffer */ - MemSetT(dst_ptr, 0, _screen.pitch * _screen.height); - - for (uint y = 0; y < height; y++) { - uint8 *src = row_pointers[y]; - uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; - - for (uint x = 0; x < width; x++) { - dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000; - } - } - break; - } - } - - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - fclose(f); - return; -} - - - -#else /* WITH_PNG */ - -/** - * Empty 'Display a splash image' routine (WITHOUT_PNG). - */ -void DisplaySplashImage() {} - -#endif /* WITH_PNG */ diff --git a/src/os/macosx/splash.h b/src/os/macosx/splash.h deleted file mode 100644 index 8ddb638578..0000000000 --- a/src/os/macosx/splash.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file splash.h Functions to support splash screens for OSX. */ - -#ifndef SPLASH_H -#define SPLASH_H - -#define SPLASH_IMAGE_FILE "splash.png" - -void DisplaySplashImage(); - -#endif /* SPLASH_H */ diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index 17d4c437dc..c7ab70538d 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -23,7 +23,6 @@ #include "../../openttd.h" #include "../../debug.h" -#include "../../os/macosx/splash.h" #include "../../settings_type.h" #include "../../core/geometry_type.hpp" #include "cocoa_v.h" @@ -93,24 +92,6 @@ void VideoDriver_Cocoa::GameLoop() uint32 st = 0; #endif - DisplaySplashImage(); - this->CheckPaletteAnim(); - this->Draw(true); - CSleep(1); - - for (int i = 0; i < 2; i++) ::GameLoop(); - - UpdateWindows(); - this->CheckPaletteAnim(); - this->Draw(); - CSleep(1); - - /* Set the proper OpenTTD palette which got spoilt by the splash - * image when using 8bpp blitter */ - GfxInitPalettes(); - this->CheckPaletteAnim(); - this->Draw(true); - for (;;) { @autoreleasepool { From 94b76ce9a4ec8280f65ff289c637ea739514fb9d Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 20:22:37 +0100 Subject: [PATCH 080/275] Cleanup: [OSX] Move event loop into video driver file. --- src/video/cocoa/CMakeLists.txt | 1 - src/video/cocoa/cocoa_v.h | 2 +- src/video/cocoa/cocoa_v.mm | 123 +++++++++++++++++++++++- src/video/cocoa/event.mm | 165 --------------------------------- 4 files changed, 122 insertions(+), 169 deletions(-) delete mode 100644 src/video/cocoa/event.mm diff --git a/src/video/cocoa/CMakeLists.txt b/src/video/cocoa/CMakeLists.txt index 8bcc6b2e03..968a98a91d 100644 --- a/src/video/cocoa/CMakeLists.txt +++ b/src/video/cocoa/CMakeLists.txt @@ -4,6 +4,5 @@ add_files( cocoa_v.mm cocoa_wnd.h cocoa_wnd.mm - event.mm CONDITION APPLE ) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 0112f57515..8ebf5ba6e1 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -70,7 +70,7 @@ public: /* --- The following methods should be private, but can't be due to Obj-C limitations. --- */ /** Main game loop. */ - void GameLoop(); // In event.mm. + void GameLoop(); void AllocateBackingStore(); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 07640a0f83..c35ee9b7dd 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -27,16 +27,21 @@ #include "../../openttd.h" #include "../../debug.h" #include "../../core/geometry_type.hpp" +#include "../../core/math_func.hpp" #include "cocoa_v.h" #include "cocoa_wnd.h" #include "../../blitter/factory.hpp" +#include "../../framerate_type.h" +#include "../../network/network.h" #include "../../gfx_func.h" +#include "../../thread.h" +#include "../../core/random_func.hpp" +#include "../../settings_type.h" #include "../../window_func.h" #include "../../window_gui.h" -#include "../../core/math_func.hpp" -#include "../../framerate_type.h" #import /* for MAXPATHLEN */ +#import /* gettimeofday */ /** * Important notice regarding all modifications!!!!!!! @@ -55,6 +60,12 @@ bool _cocoa_video_started = false; +extern bool _tab_is_down; + +#ifdef _DEBUG +static uint32 _tEvent; +#endif + /** List of common display/window sizes. */ static const Dimension _default_resolutions[] = { @@ -75,6 +86,15 @@ static const Dimension _default_resolutions[] = { static FVideoDriver_Cocoa iFVideoDriver_Cocoa; +static uint32 GetTick() +{ + struct timeval tim; + + gettimeofday(&tim, NULL); + return tim.tv_usec / 1000 + tim.tv_sec * 1000; +} + + /* Subclass of OTTD_CocoaView to fix Quartz rendering */ @interface OTTD_QuartzView : NSView { VideoDriver_Cocoa *driver; @@ -578,6 +598,105 @@ void VideoDriver_Cocoa::CheckPaletteAnim() } +bool VideoDriver_Cocoa::PollEvent() +{ +#ifdef _DEBUG + uint32 et0 = GetTick(); +#endif + NSEvent *event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[ NSDate distantPast ] inMode:NSDefaultRunLoopMode dequeue:YES ]; +#ifdef _DEBUG + _tEvent += GetTick() - et0; +#endif + + if (event == nil) return false; + + [ NSApp sendEvent:event ]; + + return true; +} + + +void VideoDriver_Cocoa::GameLoop() +{ + uint32 cur_ticks = GetTick(); + uint32 last_cur_ticks = cur_ticks; + uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK; + +#ifdef _DEBUG + uint32 et0 = GetTick(); + uint32 st = 0; +#endif + + for (;;) { + @autoreleasepool { + + uint32 prev_cur_ticks = cur_ticks; // to check for wrapping + InteractiveRandom(); // randomness + + while (this->PollEvent()) {} + + if (_exit_game) { + /* Restore saved resolution if in fullscreen mode. */ + if (this->IsFullscreen()) _cur_resolution = this->orig_res; + break; + } + + NSUInteger cur_mods = [ NSEvent modifierFlags ]; + +#if defined(_DEBUG) + if (cur_mods & NSShiftKeyMask) { +#else + if (_tab_is_down) { +#endif + if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; + } else if (_fast_forward & 2) { + _fast_forward = 0; + } + + cur_ticks = GetTick(); + if (cur_ticks >= next_tick || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { + _realtime_tick += cur_ticks - last_cur_ticks; + last_cur_ticks = cur_ticks; + next_tick = cur_ticks + MILLISECONDS_PER_TICK; + + bool old_ctrl_pressed = _ctrl_pressed; + + _ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0; + _shift_pressed = (cur_mods & NSShiftKeyMask) != 0; + + if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); + + ::GameLoop(); + + UpdateWindows(); + this->CheckPaletteAnim(); + this->Draw(); + } else { +#ifdef _DEBUG + uint32 st0 = GetTick(); +#endif + CSleep(1); +#ifdef _DEBUG + st += GetTick() - st0; +#endif + NetworkDrawChatMessage(); + DrawMouseCursor(); + this->Draw(); + } + } + } + +#ifdef _DEBUG + uint32 et = GetTick(); + + DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _tEvent); + DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st); + DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_tEvent / (double)(et - et0) * 100); + DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_tEvent / (double)(et - et0 - st) * 100); +#endif +} + + @implementation OTTD_QuartzView - (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm deleted file mode 100644 index c7ab70538d..0000000000 --- a/src/video/cocoa/event.mm +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/****************************************************************************** - * Cocoa video driver * - * Known things left to do: * - * Nothing at the moment. * - ******************************************************************************/ - -#ifdef WITH_COCOA - -#include "../../stdafx.h" - -#define Rect OTTDRect -#define Point OTTDPoint -#import -#undef Rect -#undef Point - -#include "../../openttd.h" -#include "../../debug.h" -#include "../../settings_type.h" -#include "../../core/geometry_type.hpp" -#include "cocoa_v.h" -#include "cocoa_wnd.h" -#include "../../blitter/factory.hpp" -#include "../../gfx_func.h" -#include "../../network/network.h" -#include "../../core/random_func.hpp" -#include "../../core/math_func.hpp" -#include "../../texteff.hpp" -#include "../../window_func.h" -#include "../../thread.h" - -#import /* gettimeofday */ - -/** - * Important notice regarding all modifications!!!!!!! - * There are certain limitations because the file is objective C++. - * gdb has limitations. - * C++ and objective C code can't be joined in all cases (classes stuff). - * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information. - */ - -extern bool _tab_is_down; - -#ifdef _DEBUG -static uint32 _tEvent; -#endif - - -static uint32 GetTick() -{ - struct timeval tim; - - gettimeofday(&tim, NULL); - return tim.tv_usec / 1000 + tim.tv_sec * 1000; -} - -bool VideoDriver_Cocoa::PollEvent() -{ -#ifdef _DEBUG - uint32 et0 = GetTick(); -#endif - NSEvent *event = [ NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[ NSDate distantPast ] - inMode:NSDefaultRunLoopMode dequeue:YES ]; -#ifdef _DEBUG - _tEvent += GetTick() - et0; -#endif - - if (event == nil) return false; - - [ NSApp sendEvent:event ]; - - return true; -} - - -void VideoDriver_Cocoa::GameLoop() -{ - uint32 cur_ticks = GetTick(); - uint32 last_cur_ticks = cur_ticks; - uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK; - -#ifdef _DEBUG - uint32 et0 = GetTick(); - uint32 st = 0; -#endif - - for (;;) { - @autoreleasepool { - - uint32 prev_cur_ticks = cur_ticks; // to check for wrapping - InteractiveRandom(); // randomness - - while (this->PollEvent()) {} - - if (_exit_game) { - /* Restore saved resolution if in fullscreen mode. */ - if (this->IsFullscreen()) _cur_resolution = this->orig_res; - break; - } - - NSUInteger cur_mods = [ NSEvent modifierFlags ]; - -#if defined(_DEBUG) - if (cur_mods & NSShiftKeyMask) -#else - if (_tab_is_down) -#endif - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } - - cur_ticks = GetTick(); - if (cur_ticks >= next_tick || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { - _realtime_tick += cur_ticks - last_cur_ticks; - last_cur_ticks = cur_ticks; - next_tick = cur_ticks + MILLISECONDS_PER_TICK; - - bool old_ctrl_pressed = _ctrl_pressed; - - _ctrl_pressed = !!(cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); - _shift_pressed = !!(cur_mods & NSShiftKeyMask); - - if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); - - ::GameLoop(); - - UpdateWindows(); - this->CheckPaletteAnim(); - this->Draw(); - } else { -#ifdef _DEBUG - uint32 st0 = GetTick(); -#endif - CSleep(1); -#ifdef _DEBUG - st += GetTick() - st0; -#endif - NetworkDrawChatMessage(); - DrawMouseCursor(); - this->Draw(); - } - } - } - -#ifdef _DEBUG - uint32 et = GetTick(); - - DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _tEvent); - DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st); - DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_tEvent / (double)(et - et0) * 100); - DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_tEvent / (double)(et - et0 - st) * 100); -#endif -} - -#endif /* WITH_COCOA */ From 2a8c3a2cf6460f8abb6032a449bf4cd4be01e847 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 20:23:53 +0100 Subject: [PATCH 081/275] Codechange: [OSX] Align backing buffer pitch for a tiny bit performance. --- src/video/cocoa/cocoa_v.mm | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index c35ee9b7dd..f74c17c81e 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -109,6 +109,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa() { this->window_width = 0; this->window_height = 0; + this->window_pitch = 0; this->buffer_depth = 0; this->window_buffer = nullptr; this->pixel_buffer = nullptr; @@ -315,9 +316,9 @@ bool VideoDriver_Cocoa::IsFullscreen() void VideoDriver_Cocoa::GameSizeChanged() { /* Tell the game that the resolution has changed */ - _screen.width = this->window_width; - _screen.height = this->window_height; - _screen.pitch = this->window_width; + _screen.width = this->window_width; + _screen.height = this->window_height; + _screen.pitch = this->buffer_depth == 8 ? this->window_width : this->window_pitch; _screen.dst_ptr = this->buffer_depth == 8 ? this->pixel_buffer : this->window_buffer; /* Store old window size if we entered fullscreen mode. */ @@ -448,7 +449,7 @@ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bo const uint8 *src = (uint8*)this->pixel_buffer; uint32 *dst = (uint32*)this->window_buffer; uint width = this->window_width; - uint pitch = this->window_width; + uint pitch = this->window_pitch; for (int y = top; y < bottom; y++) { for (int x = left; x < right; x++) { @@ -538,13 +539,14 @@ void VideoDriver_Cocoa::AllocateBackingStore() this->window_width = (int)newframe.size.width; this->window_height = (int)newframe.size.height; + this->window_pitch = Align(this->window_width, 16 / sizeof(uint32)); // Quartz likes lines that are multiple of 16-byte. this->buffer_depth = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); /* Create Core Graphics Context */ free(this->window_buffer); - this->window_buffer = malloc(this->window_width * this->window_height * sizeof(uint32)); + this->window_buffer = malloc(this->window_pitch * this->window_height * sizeof(uint32)); /* Initialize with opaque black. */ - ClearWindowBuffer((uint32 *)this->window_buffer, this->window_width, this->window_height); + ClearWindowBuffer((uint32 *)this->window_buffer, this->window_pitch, this->window_height); CGContextRelease(this->cgcontext); this->cgcontext = CGBitmapContextCreate( @@ -552,7 +554,7 @@ void VideoDriver_Cocoa::AllocateBackingStore() this->window_width, // width this->window_height, // height 8, // bits per component - this->window_width * 4, // bytes per row + this->window_pitch * 4, // bytes per row this->color_space, // color space kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host ); @@ -566,6 +568,9 @@ void VideoDriver_Cocoa::AllocateBackingStore() free(this->pixel_buffer); this->pixel_buffer = malloc(this->window_width * this->window_height); if (this->pixel_buffer == nullptr) usererror("Out of memory allocating pixel buffer"); + } else { + free(this->pixel_buffer); + this->pixel_buffer = nullptr; } /* Redraw screen */ From 43326d11d8861721c9db45922bc7d42cf99dccba Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 6 Feb 2021 22:58:51 +0100 Subject: [PATCH 082/275] Change: [OSX] Use a layer-backed view to speed up drawing. --- CMakeLists.txt | 5 +++ src/video/cocoa/cocoa_v.mm | 86 +++++++------------------------------- 2 files changed, 19 insertions(+), 72 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5d7ac1137..2af3d30da3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,6 +131,7 @@ if(NOT WIN32) find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox) find_library(AUDIOUNIT_LIBRARY AudioUnit) find_library(COCOA_LIBRARY Cocoa) + find_library(QUARTZCORE_LIBRARY QuartzCore) endif() endif() @@ -163,6 +164,9 @@ if(APPLE) if(NOT COCOA_LIBRARY) message(FATAL_ERROR "Cocoa is required for this platform") endif() + if(NOT QUARTZCORE_LIBRARY) + message(FATAL_ERROR "QuartzCore is required for this platform") + endif() endif() if(OPTION_PACKAGE_DEPENDENCIES) @@ -250,6 +254,7 @@ if(APPLE) ${AUDIOTOOLBOX_LIBRARY} ${AUDIOUNIT_LIBRARY} ${COCOA_LIBRARY} + ${QUARTZCORE_LIBRARY} ) add_definitions( diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index f74c17c81e..dea64e60df 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -100,8 +100,6 @@ static uint32 GetTick() VideoDriver_Cocoa *driver; } - (instancetype)initWithFrame:(NSRect)frameRect andDriver:(VideoDriver_Cocoa *)drv; - -- (void)drawRect:(NSRect)invalidRect; @end @@ -708,6 +706,12 @@ void VideoDriver_Cocoa::GameLoop() { if (self = [ super initWithFrame:frameRect ]) { self->driver = drv; + + /* We manage our content updates ourselves. */ + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; + self.wantsLayer = YES; + + self.layer.magnificationFilter = kCAFilterNearest; } return self; } @@ -722,80 +726,18 @@ void VideoDriver_Cocoa::GameLoop() return YES; } -- (void)drawRect:(NSRect)invalidRect +- (BOOL)wantsUpdateLayer +{ + return YES; +} + +- (void)updateLayer { if (driver->cgcontext == nullptr) return; - NSGraphicsContext *ctx = [ NSGraphicsContext currentContext ]; - CGContextRef viewContext = [ ctx respondsToSelector:@selector(CGContext) ] ? [ ctx CGContext ] : (CGContextRef)[ ctx graphicsPort ]; - CGContextSetShouldAntialias(viewContext, FALSE); - CGContextSetInterpolationQuality(viewContext, kCGInterpolationNone); - - /* The obtained 'rect' is actually a union of all dirty rects, let's ask for an explicit list of rects instead */ - const NSRect *dirtyRects; - NSInteger dirtyRectCount; - [ self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount ]; - - /* We need an Image in order to do blitting, but as we don't touch the context between this call and drawing no copying will actually be done here */ + /* Set layer contents to our backing buffer, which avoids needless copying. */ CGImageRef fullImage = CGBitmapContextCreateImage(driver->cgcontext); - - /* Calculate total area we are blitting */ - uint32 blitArea = 0; - for (int n = 0; n < dirtyRectCount; n++) { - blitArea += (uint32)(dirtyRects[n].size.width * dirtyRects[n].size.height); - } - - /* - * This might be completely stupid, but in my extremely subjective opinion it feels faster - * The point is, if we're blitting less than 50% of the dirty rect union then it's still a good idea to blit each dirty - * rect separately but if we blit more than that, it's just cheaper to blit the entire union in one pass. - * Feel free to remove or find an even better value than 50% ... / blackis - */ - NSRect frameRect = [ self frame ]; - if (blitArea / (float)(invalidRect.size.width * invalidRect.size.height) > 0.5f) { - NSRect rect = invalidRect; - CGRect clipRect; - CGRect blitRect; - - blitRect.origin.x = rect.origin.x; - blitRect.origin.y = rect.origin.y; - blitRect.size.width = rect.size.width; - blitRect.size.height = rect.size.height; - - clipRect.origin.x = rect.origin.x; - clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; - - clipRect.size.width = rect.size.width; - clipRect.size.height = rect.size.height; - - /* Blit dirty part of image */ - CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); - CGContextDrawImage(viewContext, blitRect, clippedImage); - CGImageRelease(clippedImage); - } else { - for (int n = 0; n < dirtyRectCount; n++) { - NSRect rect = dirtyRects[n]; - CGRect clipRect; - CGRect blitRect; - - blitRect.origin.x = rect.origin.x; - blitRect.origin.y = rect.origin.y; - blitRect.size.width = rect.size.width; - blitRect.size.height = rect.size.height; - - clipRect.origin.x = rect.origin.x; - clipRect.origin.y = frameRect.size.height - rect.origin.y - rect.size.height; - - clipRect.size.width = rect.size.width; - clipRect.size.height = rect.size.height; - - /* Blit dirty part of image */ - CGImageRef clippedImage = CGImageCreateWithImageInRect(fullImage, clipRect); - CGContextDrawImage(viewContext, blitRect, clippedImage); - CGImageRelease(clippedImage); - } - } - + self.layer.contents = (__bridge id)fullImage; CGImageRelease(fullImage); } From 649ff5f9f9777e0c8b66e868d24af37af6c942be Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 7 Feb 2021 14:00:59 +0100 Subject: [PATCH 083/275] Codechange: [OSX] Use relative mouse handling during scrolling. --- src/video/cocoa/cocoa_wnd.mm | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 2755b26ff4..8c947fe046 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -524,22 +524,25 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (void)internalMouseMoveEvent:(NSEvent *)event { - NSPoint pt = [ self mousePositionFromEvent:event ]; - - if (_cursor.UpdateCursorPosition(pt.x, pt.y, false) && [ NSApp isActive ]) { - /* Warping cursor when in foreground */ - NSPoint warp = [ self convertPoint:NSMakePoint(_cursor.pos.x, self.bounds.size.height - _cursor.pos.y) toView:nil ]; - warp = [ self.window convertRectToScreen:NSMakeRect(warp.x, warp.y, 0, 0) ].origin; - warp.y = NSScreen.screens[0].frame.size.height - warp.y; - - /* Do the actual warp */ - CGWarpMouseCursorPosition(NSPointToCGPoint(warp)); - /* this is the magic call that fixes cursor "freezing" after warp */ - CGAssociateMouseAndMouseCursorPosition(true); + if (_cursor.fix_at) { + _cursor.UpdateCursorPositionRelative(event.deltaX, event.deltaY); + } else { + NSPoint pt = [ self mousePositionFromEvent:event ]; + _cursor.UpdateCursorPosition(pt.x, pt.y, false); } + HandleMouseEvents(); } +- (void)internalMouseButtonEvent +{ + bool cur_fix = _cursor.fix_at; + HandleMouseEvents(); + + /* Cursor fix mode was changed, synchronize with OS. */ + if (cur_fix != _cursor.fix_at) CGAssociateMouseAndMouseCursorPosition(!_cursor.fix_at); +} + - (BOOL)emulateRightButton:(NSEvent *)event { uint32 keymask = 0; @@ -564,7 +567,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel [ self rightMouseDown:event ]; } else { _left_button_down = true; - [ self internalMouseMoveEvent:event ]; + [ self internalMouseButtonEvent ]; } } - (void)mouseUp:(NSEvent *)event @@ -574,7 +577,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } else { _left_button_down = false; _left_button_clicked = false; - [ self internalMouseMoveEvent:event ]; + [ self internalMouseButtonEvent ]; } } @@ -586,12 +589,12 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel { _right_button_down = true; _right_button_clicked = true; - [ self internalMouseMoveEvent:event ]; + [ self internalMouseButtonEvent ]; } - (void)rightMouseUp:(NSEvent *)event { _right_button_down = false; - [ self internalMouseMoveEvent:event ]; + [ self internalMouseButtonEvent ]; } - (void)scrollWheel:(NSEvent *)event From 9c8721922b13a6789c9fed971f8550bda3099f7a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 7 Feb 2021 16:04:07 +0100 Subject: [PATCH 084/275] Fix: [OSX] An emulated right mouse down event has to be followed by right mouse up. --- src/video/cocoa/cocoa_wnd.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 8c947fe046..5a3de7e553 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -451,6 +451,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @implementation OTTD_CocoaView { float _current_magnification; NSUInteger _current_mods; + bool _emulated_down; } /** @@ -564,6 +565,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (void)mouseDown:(NSEvent *)event { if ([ self emulateRightButton:event ]) { + self->_emulated_down = true; [ self rightMouseDown:event ]; } else { _left_button_down = true; @@ -572,7 +574,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel } - (void)mouseUp:(NSEvent *)event { - if ([ self emulateRightButton:event ]) { + if (self->_emulated_down) { [ self rightMouseUp:event ]; } else { _left_button_down = false; From c78e559e88a7864a0b55cb00c82b6deac27ff1da Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 12 Feb 2021 01:18:36 +0100 Subject: [PATCH 085/275] Codechange: [OSX] Remove unused 'app active' flag. --- src/video/cocoa/cocoa_v.h | 3 +- src/video/cocoa/cocoa_v.mm | 1 - src/video/cocoa/cocoa_wnd.h | 3 -- src/video/cocoa/cocoa_wnd.mm | 55 ------------------------------------ 4 files changed, 1 insertion(+), 61 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 8ebf5ba6e1..3f62102d14 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -39,8 +39,7 @@ private: uint32 palette[256]; ///< Colour Palette public: - bool active; ///< Whether the window is visible - bool setup; + bool setup; ///< Window is currently being created. OTTD_CocoaWindow *window; ///< Pointer to window object OTTD_CocoaView *cocoaview; ///< Pointer to view object diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index dea64e60df..40d041a5dd 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -111,7 +111,6 @@ VideoDriver_Cocoa::VideoDriver_Cocoa() this->buffer_depth = 0; this->window_buffer = nullptr; this->pixel_buffer = nullptr; - this->active = false; this->setup = false; this->window = nil; diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index 98ed7df7ec..fa7036396c 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -32,11 +32,8 @@ extern NSString *OTTDMainLaunchGameEngine; @interface OTTD_CocoaWindow : NSWindow - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv; -- (void)miniaturize:(id)sender; - (void)display; - (void)setFrame:(NSRect)frameRect display:(BOOL)flag; -- (void)appDidHide:(NSNotification*)note; -- (void)appDidUnhide:(NSNotification*)note; @end /** Subclass of NSView to support mouse awareness and text input. */ diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 5a3de7e553..a836646b56 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -370,13 +370,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv { if (self = [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]) { - /* Make our window subclass receive these application notifications */ - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; - - [ [ NSNotificationCenter defaultCenter ] addObserver:self - selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; - self->driver = drv; [ self setContentMinSize:NSMakeSize(64.0f, 64.0f) ]; @@ -391,17 +384,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel return self; } -/** - * Minimize the window - */ -- (void)miniaturize:(id)sender -{ - /* window is hidden now */ - driver->active = false; - - [ super miniaturize:sender ]; -} - /** * This method fires just before the window deminaturizes from the Dock. * We'll save the current visible surface, let the window manager redraw any @@ -418,9 +400,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel /* restore visible surface */ [ self restoreCachedImage ]; - - /* window is visible again */ - driver->active = true; } /** * Define the rectangle we draw our window in @@ -431,20 +410,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel driver->AllocateBackingStore(); } -/** - * Handle hiding of the application - */ -- (void)appDidHide:(NSNotification*)note -{ - driver->active = false; -} -/** - * Unhide and restore display plane and re-activate driver - */ -- (void)appDidUnhide:(NSNotification*)note -{ - driver->active = true; -} @end @@ -1122,26 +1087,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel return NO; } -/** Handle key acceptance */ -- (void)windowDidBecomeKey:(NSNotification*)aNotification -{ - driver->active = true; -} -/** Resign key acceptance */ -- (void)windowDidResignKey:(NSNotification*)aNotification -{ - driver->active = false; -} -/** Handle becoming main window */ -- (void)windowDidBecomeMain:(NSNotification*)aNotification -{ - driver->active = true; -} -/** Resign being main window */ -- (void)windowDidResignMain:(NSNotification*)aNotification -{ - driver->active = false; -} /** Window entered fullscreen mode (10.7). */ - (void)windowDidEnterFullScreen:(NSNotification *)aNotification { From acca56b6a5791e965950682ede1c97e2301564de Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 12 Feb 2021 01:19:00 +0100 Subject: [PATCH 086/275] Cleanup: [OSX] Improve some comments. --- src/video/cocoa/cocoa_v.h | 4 +--- src/video/cocoa/cocoa_v.mm | 45 +++++++++++++++++++----------------- src/video/cocoa/cocoa_wnd.mm | 4 ++-- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 3f62102d14..596a9e27d4 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -63,12 +63,10 @@ public: void EditBoxLostFocus() override; - /** Return driver name */ const char *GetName() const override { return "cocoa"; } /* --- The following methods should be private, but can't be due to Obj-C limitations. --- */ - /** Main game loop. */ void GameLoop(); void AllocateBackingStore(); @@ -77,7 +75,7 @@ protected: Dimension GetScreenSize() const override; private: - bool PollEvent(); // In event.mm. + bool PollEvent(); bool IsFullscreen(); void GameSizeChanged(); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 40d041a5dd..5493c06525 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -86,6 +86,10 @@ static const Dimension _default_resolutions[] = { static FVideoDriver_Cocoa iFVideoDriver_Cocoa; +/** + * Get current realtime. + * @return Tick time in milliseconds. + */ static uint32 GetTick() { struct timeval tim; @@ -95,7 +99,7 @@ static uint32 GetTick() } -/* Subclass of OTTD_CocoaView to fix Quartz rendering */ +/** Subclass of NSView for drawing to screen. */ @interface OTTD_QuartzView : NSView { VideoDriver_Cocoa *driver; } @@ -123,9 +127,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa() this->num_dirty_rects = lengthof(this->dirty_rects); } -/** - * Stop the cocoa video subdriver. - */ +/** Stop Cocoa video driver. */ void VideoDriver_Cocoa::Stop() { if (!_cocoa_video_started) return; @@ -146,9 +148,7 @@ void VideoDriver_Cocoa::Stop() _cocoa_video_started = false; } -/** - * Initialize a cocoa video subdriver. - */ +/** Try to start Cocoa video driver. */ const char *VideoDriver_Cocoa::Start(const StringList &parm) { if (!MacOSVersionIsAtLeast(10, 7, 0)) return "The Cocoa video driver requires Mac OS X 10.7 or later."; @@ -184,7 +184,6 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) /** * Set dirty a rectangle managed by a cocoa video subdriver. - * * @param left Left x cooordinate of the dirty rectangle. * @param top Uppder y coordinate of the dirty rectangle. * @param width Width of the dirty rectangle. @@ -216,7 +215,6 @@ void VideoDriver_Cocoa::MainLoop() /** * Change the resolution when using a cocoa video driver. - * * @param w New window width. * @param h New window height. * @return Whether the video driver was successfully updated. @@ -250,7 +248,6 @@ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) /** * Toggle between windowed and full screen mode for cocoa display driver. - * * @param full_screen Whether to switch to full screen or not. * @return Whether the mode switch was successful. */ @@ -269,7 +266,6 @@ bool VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) /** * Callback invoked after the blitter was changed. - * * @return True if no error. */ bool VideoDriver_Cocoa::AfterBlitterChange() @@ -299,7 +295,7 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const } /** - * Are we in fullscreen mode + * Are we in fullscreen mode? * @return whether fullscreen mode is currently used */ bool VideoDriver_Cocoa::IsFullscreen() @@ -329,7 +325,7 @@ void VideoDriver_Cocoa::GameSizeChanged() } /** - * Update the video modus. + * Update the video mode. */ void VideoDriver_Cocoa::UpdateVideoModes() { @@ -359,6 +355,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) { this->setup = true; + /* Limit window size to screen frame. */ NSSize screen_size = [ [ NSScreen mainScreen ] frame ].size; if (width > screen_size.width) width = screen_size.width; if (height > screen_size.height) height = screen_size.height; @@ -376,8 +373,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) /* Add built in full-screen support when available (OS X 10.7 and higher) * This code actually compiles for 10.5 and later, but only makes sense in conjunction - * with the quartz fullscreen support as found only in 10.7 and later - */ + * with the quartz fullscreen support as found only in 10.7 and later. */ if ([ this->window respondsToSelector:@selector(toggleFullScreen:) ]) { NSWindowCollectionBehavior behavior = [ this->window collectionBehavior ]; behavior |= NSWindowCollectionBehaviorFullScreenPrimary; @@ -394,11 +390,11 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) [ this->window center ]; [ this->window makeKeyAndOrderFront:nil ]; - /* Create wrapper view for text input. */ + /* Create wrapper view for input and event handling. */ NSRect view_frame = [ this->window contentRectForFrameRect:[ this->window frame ] ]; this->cocoaview = [ [ OTTD_CocoaView alloc ] initWithFrame:view_frame ]; if (this->cocoaview == nil) { - DEBUG(driver, 0, "Could not create the text wrapper view."); + DEBUG(driver, 0, "Could not create the event wrapper view."); this->setup = false; return false; } @@ -413,6 +409,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) } [ draw_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable ]; + /* Create view chain: window -> input wrapper view -> content view. */ [ this->window setContentView:this->cocoaview ]; [ this->cocoaview addSubview:draw_view ]; [ this->window makeFirstResponder:this->cocoaview ]; @@ -433,7 +430,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) } /** - * This function copies 8bpp pixels from the screen buffer in 32bpp windowed mode. + * This function copies 8bpp pixels to the screen buffer in 32bpp windowed mode. * * @param left The x coord for the left edge of the box to blit. * @param top The y coord for the top edge of the box to blit. @@ -455,7 +452,8 @@ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bo } } -/** Draw window +/** + * Draw window. * @param force_update Whether to redraw unconditionally */ void VideoDriver_Cocoa::Draw(bool force_update) @@ -500,7 +498,7 @@ void VideoDriver_Cocoa::Draw(bool force_update) this->num_dirty_rects = 0; } -/** Update the palette */ +/** Update the palette. */ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors) { if (this->buffer_depth != 8) return; @@ -575,6 +573,7 @@ void VideoDriver_Cocoa::AllocateBackingStore() this->GameSizeChanged(); } +/** Check if palette updates need to be performed. */ void VideoDriver_Cocoa::CheckPaletteAnim() { if (_cur_palette.count_dirty != 0) { @@ -600,6 +599,10 @@ void VideoDriver_Cocoa::CheckPaletteAnim() } +/** + * Poll and handle a single event from the OS. + * @return True if there was an event to handle. + */ bool VideoDriver_Cocoa::PollEvent() { #ifdef _DEBUG @@ -617,7 +620,7 @@ bool VideoDriver_Cocoa::PollEvent() return true; } - +/** Main game loop. */ void VideoDriver_Cocoa::GameLoop() { uint32 cur_ticks = GetTick(); diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index a836646b56..089bfe8344 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -175,7 +175,7 @@ static std::vector NSStringToUTF32(NSString *s) { HandleExitGameRequest(); - return NSTerminateCancel; // NSTerminateLater ? + return NSTerminateCancel; } /** @@ -296,7 +296,7 @@ bool CocoaSetupApplication() } /** - * + * Deregister app delegate. */ void CocoaExitApplication() { From f1fc083f2b7f168931cd881cf040d7f3b084fb27 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sat, 13 Feb 2021 18:49:50 +0000 Subject: [PATCH 087/275] Change: Make order window hotkeys toggle for load & unload variants --- src/order_gui.cpp | 76 ++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index d3b4aa9527..bd11656220 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -576,27 +576,22 @@ private: /** * Handle the click on the full load button. - * @param load_type the way to load. + * @param load_type Load flag to apply. If matches existing load type, toggles to default of 'load if possible'. + * @param toggle If we toggle or not (used for hotkey behavior) */ - void OrderClick_FullLoad(int load_type) + void OrderClick_FullLoad(OrderLoadFlags load_type, bool toggle = false) { VehicleOrderID sel_ord = this->OrderGetSel(); const Order *order = this->vehicle->GetOrder(sel_ord); - if (order == nullptr || order->GetLoadType() == load_type) return; + if (order == nullptr) return; - if (load_type < 0) { - load_type = order->GetLoadType() == OLF_LOAD_IF_POSSIBLE ? OLF_FULL_LOAD_ANY : OLF_LOAD_IF_POSSIBLE; + if (toggle && order->GetLoadType() == load_type) { + load_type = OLF_LOAD_IF_POSSIBLE; // reset to 'default' } - DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_LOAD | (load_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); - } + if (order->GetLoadType() == load_type) return; // If we still match, do nothing - /** - * Handle the 'no loading' hotkey - */ - void OrderHotkey_NoLoad() - { - this->OrderClick_FullLoad(OLFB_NO_LOAD); + DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_LOAD | (load_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); } /** @@ -631,17 +626,20 @@ private: /** * Handle the click on the unload button. + * @param unload_type Unload flag to apply. If matches existing unload type, toggles to default of 'unload if possible'. + * @param toggle If we toggle or not (used for hotkey behavior) */ - void OrderClick_Unload(int unload_type) + void OrderClick_Unload(OrderUnloadFlags unload_type, bool toggle = false) { VehicleOrderID sel_ord = this->OrderGetSel(); const Order *order = this->vehicle->GetOrder(sel_ord); - if (order == nullptr || order->GetUnloadType() == unload_type) return; + if (order == nullptr) return; - if (unload_type < 0) { - unload_type = order->GetUnloadType() == OUF_UNLOAD_IF_POSSIBLE ? OUFB_UNLOAD : OUF_UNLOAD_IF_POSSIBLE; + if (toggle && order->GetUnloadType() == unload_type) { + unload_type = OUF_UNLOAD_IF_POSSIBLE; } + if (order->GetUnloadType() == unload_type) return; // If we still match, do nothing DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 20), MOF_UNLOAD | (unload_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER)); @@ -652,22 +650,6 @@ private: } } - /** - * Handle the transfer hotkey - */ - void OrderHotkey_Transfer() - { - this->OrderClick_Unload(OUFB_TRANSFER); - } - - /** - * Handle the 'no unload' hotkey - */ - void OrderHotkey_NoUnload() - { - this->OrderClick_Unload(OUFB_NO_UNLOAD); - } - /** * Handle the click on the nonstop button. * @param non_stop what non-stop type to use; -1 to use the 'next' one. @@ -1262,7 +1244,7 @@ public: case WID_O_FULL_LOAD: if (this->GetWidget(widget)->ButtonHit(pt)) { - this->OrderClick_FullLoad(-1); + this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true); } else { ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), WID_O_FULL_LOAD, 0, 2); } @@ -1270,7 +1252,7 @@ public: case WID_O_UNLOAD: if (this->GetWidget(widget)->ButtonHit(pt)) { - this->OrderClick_Unload(-1); + this->OrderClick_Unload(OUFB_UNLOAD, true); } else { ShowDropDownMenu(this, _order_unload_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType(), WID_O_UNLOAD, 0, 8); } @@ -1361,11 +1343,11 @@ public: break; case WID_O_FULL_LOAD: - this->OrderClick_FullLoad(index); + this->OrderClick_FullLoad((OrderLoadFlags)index); break; case WID_O_UNLOAD: - this->OrderClick_Unload(index); + this->OrderClick_Unload((OrderUnloadFlags)index); break; case WID_O_GOTO: @@ -1434,17 +1416,17 @@ public: if (this->vehicle->owner != _local_company) return ES_NOT_HANDLED; switch (hotkey) { - case OHK_SKIP: this->OrderClick_Skip(); break; - case OHK_DELETE: this->OrderClick_Delete(); break; + case OHK_SKIP: this->OrderClick_Skip(); break; + case OHK_DELETE: this->OrderClick_Delete(); break; case OHK_GOTO: this->OrderClick_Goto(OPOS_GOTO); break; - case OHK_NONSTOP: this->OrderClick_Nonstop(-1); break; - case OHK_FULLLOAD: this->OrderClick_FullLoad(-1); break; - case OHK_UNLOAD: this->OrderClick_Unload(-1); break; - case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break; - case OHK_ALWAYS_SERVICE: this->OrderClick_Service(-1); break; - case OHK_TRANSFER: this->OrderHotkey_Transfer(); break; - case OHK_NO_UNLOAD: this->OrderHotkey_NoUnload(); break; - case OHK_NO_LOAD: this->OrderHotkey_NoLoad(); break; + case OHK_NONSTOP: this->OrderClick_Nonstop(-1); break; + case OHK_FULLLOAD: this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true); break; + case OHK_UNLOAD: this->OrderClick_Unload(OUFB_UNLOAD, true); break; + case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break; + case OHK_ALWAYS_SERVICE: this->OrderClick_Service(-1); break; + case OHK_TRANSFER: this->OrderClick_Unload(OUFB_TRANSFER, true); break; + case OHK_NO_UNLOAD: this->OrderClick_Unload(OUFB_NO_UNLOAD, true); break; + case OHK_NO_LOAD: this->OrderClick_FullLoad(OLFB_NO_LOAD, true); break; default: return ES_NOT_HANDLED; } return ES_HANDLED; From 2b08f21625da0c0425bc8f5843b802f84b72a0b6 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sat, 13 Feb 2021 21:50:51 +0000 Subject: [PATCH 088/275] Fix #8625: Wrong ending year was displayed in highscore table --- known-bugs.txt | 9 +++++++++ src/highscore_gui.cpp | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/known-bugs.txt b/known-bugs.txt index a687dff4a5..ddfe7aa0c1 100644 --- a/known-bugs.txt +++ b/known-bugs.txt @@ -409,3 +409,12 @@ Involuntary cargo exchange with cargodist via neutral station [#6114]: shared station make the order "no unload" and if you're unloading make it "no load". Cargodist will then figure out that it should not create such a route. + +Incorrect ending year displayed in end of game newspaper [#8625] + The ending year of the game is configurable, but the date displayed in + the newspaper at the end of the game is part of the graphics, not text. + So to fix this would involve fixing the graphics in every baseset, + including the original. Additionally, basesets are free to put this + text in different positions (which they do), making a proper solution + to this infinitely more complex for a part of the game that fewer than + 1% of players ever see. diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index a473424f81..b1c428a768 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -183,7 +183,7 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow { this->SetupHighScoreEndWindow(); Point pt = this->GetTopLeft(ScaleGUITrad(640), ScaleGUITrad(480)); - SetDParam(0, ORIGINAL_END_YEAR); + SetDParam(0, _settings_game.game_creation.ending_year); DrawStringMultiLine(pt.x + ScaleGUITrad(70), pt.x + ScaleGUITrad(570), pt.y, pt.y + ScaleGUITrad(140), !_networking ? STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED : STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME, TC_FROMSTRING, SA_CENTER); /* Draw Highscore peepz */ From 8121706b89998769fc37c02e89205ca414358f82 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sat, 13 Feb 2021 21:18:03 +0000 Subject: [PATCH 089/275] Fix #8620: Scale spacing between date & news in history window according to font scaling --- src/news_gui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 639c075746..3412c351ce 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -34,6 +34,7 @@ #include "settings_internal.h" #include "guitimer_func.h" #include "group_gui.h" +#include "zoom_func.h" #include "widgets/news_widget.h" @@ -1174,8 +1175,8 @@ struct MessageHistoryWindow : Window { bool rtl = _current_text_dir == TD_RTL; uint date_left = rtl ? r.right - WD_FRAMERECT_RIGHT - this->date_width : r.left + WD_FRAMERECT_LEFT; uint date_right = rtl ? r.right - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT + this->date_width; - uint news_left = rtl ? r.left + WD_FRAMERECT_LEFT : r.left + WD_FRAMERECT_LEFT + this->date_width + WD_FRAMERECT_RIGHT; - uint news_right = rtl ? r.right - WD_FRAMERECT_RIGHT - this->date_width - WD_FRAMERECT_RIGHT : r.right - WD_FRAMERECT_RIGHT; + uint news_left = rtl ? r.left + WD_FRAMERECT_LEFT : r.left + WD_FRAMERECT_LEFT + this->date_width + WD_FRAMERECT_RIGHT + ScaleFontTrad(5); + uint news_right = rtl ? r.right - WD_FRAMERECT_RIGHT - this->date_width - WD_FRAMERECT_RIGHT - ScaleFontTrad(5) : r.right - WD_FRAMERECT_RIGHT; for (int n = this->vscroll->GetCapacity(); n > 0; n--) { SetDParam(0, ni->date); DrawString(date_left, date_right, y, STR_SHORT_DATE); From 21a2cd7bc386207c68735edc05a21bb987dddd6b Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 22:44:45 +0100 Subject: [PATCH 090/275] Codechange: Replace magic numbers by constants. --- src/fontcache.cpp | 4 ++-- src/fontcache_internal.h | 3 +++ src/os/windows/font_win32.cpp | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 6a0b500d86..50d2cf22e4 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -440,7 +440,7 @@ void FreeTypeFontCache::SetFontSize(FontSize fs, FT_Face face, int pixels) /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ int diff = scaled_height - ScaleFontTrad(_default_font_height[FS_SMALL]); - pixels = Clamp(std::min(head->Lowest_Rec_PPEM, 20u) + diff, scaled_height, MAX_FONT_SIZE); + pixels = Clamp(std::min(head->Lowest_Rec_PPEM, MAX_FONT_MIN_REC_SIZE) + diff, scaled_height, MAX_FONT_SIZE); } } else { pixels = ScaleFontTrad(pixels); @@ -608,7 +608,7 @@ const Sprite *FreeTypeFontCache::InternalGetGlyph(GlyphID key, bool aa) uint height = std::max(1U, (uint)slot->bitmap.rows + (this->fs == FS_NORMAL)); /* Limit glyph size to prevent overflows later on. */ - if (width > 256 || height > 256) usererror("Font glyph is too large"); + if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) usererror("Font glyph is too large"); /* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */ SpriteLoader::Sprite sprite; diff --git a/src/fontcache_internal.h b/src/fontcache_internal.h index 09e676234f..2f74547338 100644 --- a/src/fontcache_internal.h +++ b/src/fontcache_internal.h @@ -22,6 +22,9 @@ static const byte SHADOW_COLOUR = 2; /** Font cache for fonts that are based on a TrueType font. */ class TrueTypeFontCache : public FontCache { protected: + static constexpr int MAX_GLYPH_DIM = 256; ///< Maximum glyph dimensions. + static constexpr uint MAX_FONT_MIN_REC_SIZE = 20u; ///< Upper limit for the recommended font size in case a font file contains nonsensical values. + int req_size; ///< Requested font size. int used_size; ///< Used font size. diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 4bcbb145d9..7df24828b7 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -414,7 +414,7 @@ void Win32FontCache::SetFontSize(FontSize fs, int pixels) /* Font height is minimum height plus the difference between the default * height for this font size and the small size. */ int diff = scaled_height - ScaleFontTrad(this->GetDefaultFontHeight(FS_SMALL)); - pixels = Clamp(std::min(otm->otmusMinimumPPEM, 20u) + diff, scaled_height, MAX_FONT_SIZE); + pixels = Clamp(std::min(otm->otmusMinimumPPEM, MAX_FONT_MIN_REC_SIZE) + diff, scaled_height, MAX_FONT_SIZE); SelectObject(dc, old); DeleteObject(temp); @@ -489,7 +489,7 @@ void Win32FontCache::ClearFontCache() uint height = std::max(1U, (uint)gm.gmBlackBoxY + (this->fs == FS_NORMAL)); /* Limit glyph size to prevent overflows later on. */ - if (width > 256 || height > 256) usererror("Font glyph is too large"); + if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) usererror("Font glyph is too large"); /* GDI has rendered the glyph, now we allocate a sprite and copy the image into it. */ SpriteLoader::Sprite sprite; From 6755ff63e168dca62d16f3797a1a9dd5ceba307a Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 22:51:18 +0100 Subject: [PATCH 091/275] Add: [OSX] Native font rendering without using FreeType. --- .github/workflows/ci-build.yml | 2 +- .github/workflows/release.yml | 2 +- CMakeLists.txt | 2 +- src/bootstrap_gui.cpp | 4 +- src/fontcache.cpp | 7 +- src/os/macosx/CMakeLists.txt | 1 + src/os/macosx/font_osx.cpp | 279 +++++++++++++++++++++++++++++++++ src/os/macosx/font_osx.h | 40 +++++ src/os/macosx/string_osx.cpp | 16 +- src/settings.cpp | 4 +- src/strings.cpp | 4 +- src/textfile_gui.cpp | 2 +- 12 files changed, 345 insertions(+), 18 deletions(-) create mode 100644 src/os/macosx/font_osx.h diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 029c0416e9..0d93ce944b 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -161,7 +161,7 @@ jobs: vcpkgDirectory: '/usr/local/share/vcpkg' doNotUpdateVcpkg: false vcpkgGitCommitId: 2a42024b53ebb512fb5dd63c523338bf26c8489c - vcpkgArguments: 'freetype liblzma lzo' + vcpkgArguments: 'liblzma lzo' vcpkgTriplet: '${{ matrix.arch }}-osx' - name: Install OpenGFX diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 07feba9186..d31df95ca7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -482,7 +482,7 @@ jobs: vcpkgDirectory: '/usr/local/share/vcpkg' doNotUpdateVcpkg: false vcpkgGitCommitId: 2a42024b53ebb512fb5dd63c523338bf26c8489c - vcpkgArguments: 'freetype:x64-osx liblzma:x64-osx lzo:x64-osx freetype:arm64-osx liblzma:arm64-osx lzo:arm64-osx' + vcpkgArguments: 'liblzma:x64-osx lzo:x64-osx liblzma:arm64-osx lzo:arm64-osx' - name: Build tools run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 2af3d30da3..24496f459c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,8 +116,8 @@ find_package(PNG) if(NOT WIN32) find_package(Allegro) - find_package(Freetype) if(NOT APPLE) + find_package(Freetype) find_package(SDL2) if(NOT SDL2_FOUND) find_package(SDL) diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index a0f040d1aa..7ec391b47d 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -11,7 +11,7 @@ #include "base_media_base.h" #include "blitter/factory.hpp" -#if defined(WITH_FREETYPE) || defined(WITH_UNISCRIBE) +#if defined(WITH_FREETYPE) || defined(WITH_UNISCRIBE) || defined(WITH_COCOA) #include "core/geometry_func.hpp" #include "fontcache.h" @@ -218,7 +218,7 @@ bool HandleBootstrap() if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) goto failure; /* If there is no network or no freetype, then there is nothing we can do. Go straight to failure. */ -#if (defined(_WIN32) && defined(WITH_UNISCRIBE)) || (defined(WITH_FREETYPE) && (defined(WITH_FONTCONFIG) || defined(__APPLE__))) +#if (defined(_WIN32) && defined(WITH_UNISCRIBE)) || (defined(WITH_FREETYPE) && (defined(WITH_FONTCONFIG) || defined(__APPLE__))) || defined(WITH_COCOA) if (!_network_available) goto failure; /* First tell the game we're bootstrapping. */ diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 50d2cf22e4..be36ac1076 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -697,6 +697,9 @@ void InitFreeType(bool monospace) #elif defined(_WIN32) extern void LoadWin32Font(FontSize fs); LoadWin32Font(fs); +#elif defined(WITH_COCOA) + extern void LoadCoreTextFont(FontSize fs); + LoadCoreTextFont(fs); #endif } } @@ -717,11 +720,11 @@ void UninitFreeType() #endif /* WITH_FREETYPE */ } -#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA) #ifdef WITH_FREETYPE FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) { return FT_Err_Cannot_Open_Resource; } #endif /* WITH_FREETYPE */ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; } -#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) */ +#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA) */ diff --git a/src/os/macosx/CMakeLists.txt b/src/os/macosx/CMakeLists.txt index 6b4f2f279d..645a057c7d 100644 --- a/src/os/macosx/CMakeLists.txt +++ b/src/os/macosx/CMakeLists.txt @@ -1,6 +1,7 @@ add_files( crashlog_osx.cpp font_osx.cpp + font_osx.h macos.h macos.mm osx_stdafx.h diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index f9436312b5..4ce2b24e09 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -9,13 +9,21 @@ #include "../../stdafx.h" #include "../../debug.h" +#include "font_osx.h" +#include "../../blitter/factory.hpp" +#include "../../fileio_func.h" #include "../../fontdetection.h" #include "../../string_func.h" #include "../../strings_func.h" +#include "../../zoom_func.h" #include "macos.h" +#include + +#include "../../table/control_codes.h" #include "safeguards.h" + #ifdef WITH_FREETYPE #include @@ -136,3 +144,274 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i callback->FindMissingGlyphs(); return result; } + + +CoreTextFontCache::CoreTextFontCache(FontSize fs, CFAutoRelease &&font, int pixels) : TrueTypeFontCache(fs, pixels), font_desc(std::move(font)) +{ + this->SetFontSize(pixels); +} + +/** + * Reset cached glyphs. + */ +void CoreTextFontCache::ClearFontCache() +{ + /* GUI scaling might have changed, determine font size anew if it was automatically selected. */ + if (this->font) this->SetFontSize(this->req_size); + + this->TrueTypeFontCache::ClearFontCache(); +} + +void CoreTextFontCache::SetFontSize(int pixels) +{ + if (pixels == 0) { + /* Try to determine a good height based on the height recommended by the font. */ + int scaled_height = ScaleFontTrad(this->GetDefaultFontHeight(this->fs)); + pixels = scaled_height; + + CFAutoRelease font(CTFontCreateWithFontDescriptor(this->font_desc.get(), 0.0f, nullptr)); + if (font) { + float min_size = 0.0f; + + /* The 'head' TrueType table contains information about the + * 'smallest readable size in pixels'. Try to read it, if + * that doesn't work, we use the default OS font size instead. + * + * Reference: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6head.html */ + CFAutoRelease data(CTFontCopyTable(font.get(), kCTFontTableHead, kCTFontTableOptionNoOptions)); + if (data) { + uint16_t lowestRecPPEM; // At offset 46 of the 'head' TrueType table. + CFDataGetBytes(data.get(), CFRangeMake(46, sizeof(lowestRecPPEM)), (UInt8 *)&lowestRecPPEM); + min_size = CFSwapInt16BigToHost(lowestRecPPEM); // TrueType data is always big-endian. + } else { + CFAutoRelease size((CFNumberRef)CTFontCopyAttribute(font.get(), kCTFontSizeAttribute)); + CFNumberGetValue(size.get(), kCFNumberFloatType, &min_size); + } + + /* Font height is minimum height plus the difference between the default + * height for this font size and the small size. */ + int diff = scaled_height - ScaleFontTrad(this->GetDefaultFontHeight(FS_SMALL)); + pixels = Clamp(std::min(min_size, MAX_FONT_MIN_REC_SIZE) + diff, scaled_height, MAX_FONT_SIZE); + } + } else { + pixels = ScaleFontTrad(pixels); + } + this->used_size = pixels; + + this->font.reset(CTFontCreateWithFontDescriptor(this->font_desc.get(), pixels, nullptr)); + + /* Query the font metrics we needed. We generally round all values up to + * make sure we don't inadvertently cut off a row or column of pixels, + * except when determining glyph to glyph advances. */ + this->units_per_em = CTFontGetUnitsPerEm(this->font.get()); + this->ascender = (int)std::ceil(CTFontGetAscent(this->font.get())); + this->descender = -(int)std::ceil(CTFontGetDescent(this->font.get())); + this->height = this->ascender - this->descender; + + /* Get real font name. */ + char name[128]; + CFAutoRelease font_name((CFStringRef)CTFontCopyAttribute(this->font.get(), kCTFontDisplayNameAttribute)); + CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8); + this->font_name = name; + + DEBUG(freetype, 2, "Loaded font '%s' with size %d", this->font_name.c_str(), pixels); +} + +GlyphID CoreTextFontCache::MapCharToGlyph(WChar key) +{ + assert(IsPrintable(key)); + + if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) { + return this->parent->MapCharToGlyph(key); + } + + /* Convert characters outside of the Basic Multilingual Plane into surrogate pairs. */ + UniChar chars[2]; + if (key >= 0x010000U) { + chars[0] = (UniChar)(((key - 0x010000U) >> 10) + 0xD800); + chars[1] = (UniChar)(((key - 0x010000U) & 0x3FF) + 0xDC00); + } else { + chars[0] = (UniChar)(key & 0xFFFF); + } + + CGGlyph glyph[2] = {0, 0}; + if (CTFontGetGlyphsForCharacters(this->font.get(), chars, glyph, key >= 0x010000U ? 2 : 1)) { + return glyph[0]; + } + + return 0; +} + +const void *CoreTextFontCache::InternalGetFontTable(uint32 tag, size_t &length) +{ + CFAutoRelease data(CTFontCopyTable(this->font.get(), (CTFontTableTag)tag, kCTFontTableOptionNoOptions)); + if (!data) return nullptr; + + length = CFDataGetLength(data.get()); + auto buf = MallocT(length); + + CFDataGetBytes(data.get(), CFRangeMake(0, (CFIndex)length), buf); + return buf; +} + +const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa) +{ + /* Get glyph size. */ + CGGlyph glyph = (CGGlyph)key; + CGRect bounds = CGRectNull; + if (MacOSVersionIsAtLeast(10, 8, 0)) { + bounds = CTFontGetOpticalBoundsForGlyphs(this->font.get(), &glyph, nullptr, 1, 0); + } else { + bounds = CTFontGetBoundingRectsForGlyphs(this->font.get(), kCTFontOrientationDefault, &glyph, nullptr, 1); + } + if (CGRectIsNull(bounds)) usererror("Unable to render font glyph"); + + uint bb_width = (uint)std::ceil(bounds.size.width) + 1; // Sometimes the glyph bounds are too tight and cut of the last pixel after rounding. + uint bb_height = (uint)std::ceil(bounds.size.height); + + /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel. */ + uint width = std::max(1U, bb_width + (this->fs == FS_NORMAL ? 1 : 0)); + uint height = std::max(1U, bb_height + (this->fs == FS_NORMAL ? 1 : 0)); + + /* Limit glyph size to prevent overflows later on. */ + if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) usererror("Font glyph is too large"); + + SpriteLoader::Sprite sprite; + sprite.AllocateData(ZOOM_LVL_NORMAL, width * height); + sprite.type = ST_FONT; + sprite.width = width; + sprite.height = height; + sprite.x_offs = (int16)std::round(CGRectGetMinX(bounds)); + sprite.y_offs = this->ascender - (int16)std::ceil(CGRectGetMaxY(bounds)); + + if (bounds.size.width > 0) { + /* Glyph is not a white-space glyph. Render it to a bitmap context. */ + + /* We only need the alpha channel, as we apply our own colour constants to the sprite. */ + int pitch = Align(bb_width, 16); + byte *bmp = CallocT(bb_height * pitch); + CFAutoRelease context(CGBitmapContextCreate(bmp, bb_width, bb_height, 8, pitch, nullptr, kCGImageAlphaOnly)); + /* Set antialias according to requirements. */ + CGContextSetAllowsAntialiasing(context.get(), use_aa); + CGContextSetAllowsFontSubpixelPositioning(context.get(), use_aa); + CGContextSetAllowsFontSubpixelQuantization(context.get(), !use_aa); + CGContextSetShouldSmoothFonts(context.get(), false); + + float offset = 0.5f; // CoreText uses 0.5 as pixel centers. We want pixel alignment. + CGPoint pos{offset - bounds.origin.x, offset - bounds.origin.y}; + CTFontDrawGlyphs(this->font.get(), &glyph, &pos, 1, context.get()); + + /* Draw shadow for medium size. */ + if (this->fs == FS_NORMAL && !use_aa) { + for (uint y = 0; y < bb_height; y++) { + for (uint x = 0; x < bb_width; x++) { + if (bmp[y * pitch + x] > 0) { + sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR; + sprite.data[1 + x + (1 + y) * sprite.width].a = use_aa ? bmp[x + y * pitch] : 0xFF; + } + } + } + } + + /* Extract pixel data. */ + for (uint y = 0; y < bb_height; y++) { + for (uint x = 0; x < bb_width; x++) { + if (bmp[y * pitch + x] > 0) { + sprite.data[x + y * sprite.width].m = FACE_COLOUR; + sprite.data[x + y * sprite.width].a = use_aa ? bmp[x + y * pitch] : 0xFF; + } + } + } + } + + GlyphEntry new_glyph; + new_glyph.sprite = BlitterFactory::GetCurrentBlitter()->Encode(&sprite, AllocateFont); + new_glyph.width = (byte)std::round(CTFontGetAdvancesForGlyphs(this->font.get(), kCTFontOrientationDefault, &glyph, nullptr, 1)); + this->SetGlyphPtr(key, &new_glyph); + + return new_glyph.sprite; +} + +/** + * Loads the TrueType font. + * If a CoreText font description is present, e.g. from the automatic font + * fallback search, use it. Otherwise, try to resolve it by font name. + * @param fs The font size to load. + */ +void LoadCoreTextFont(FontSize fs) +{ + static const char *SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; + + FreeTypeSubSetting *settings = nullptr; + switch (fs) { + default: NOT_REACHED(); + case FS_SMALL: settings = &_freetype.small; break; + case FS_NORMAL: settings = &_freetype.medium; break; + case FS_LARGE: settings = &_freetype.large; break; + case FS_MONO: settings = &_freetype.mono; break; + } + + if (StrEmpty(settings->font)) return; + + CFAutoRelease font_ref; + + if (settings->os_handle != nullptr) { + font_ref.reset(static_cast(const_cast(settings->os_handle))); + CFRetain(font_ref.get()); // Increase ref count to match a later release. + } + + if (!font_ref && MacOSVersionIsAtLeast(10, 6, 0)) { + /* Might be a font file name, try load it. Direct font loading is + * only supported starting on OSX 10.6. */ + CFAutoRelease path; + + /* See if this is an absolute path. */ + if (FileExists(settings->font)) { + path.reset(CFStringCreateWithCString(kCFAllocatorDefault, settings->font, kCFStringEncodingUTF8)); + } else { + /* Scan the search-paths to see if it can be found. */ + std::string full_font = FioFindFullPath(BASE_DIR, settings->font); + if (!full_font.empty()) { + path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8)); + } + } + + if (path) { + /* Try getting a font descriptor to see if the system can use it. */ + CFAutoRelease url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(), kCFURLPOSIXPathStyle, false)); + CFAutoRelease descs(CTFontManagerCreateFontDescriptorsFromURL(url.get())); + + if (descs && CFArrayGetCount(descs.get()) > 0) { + font_ref.reset((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0)); + CFRetain(font_ref.get()); + } else { + ShowInfoF("Unable to load file '%s' for %s font, using default OS font selection instead", settings->font, SIZE_TO_NAME[fs]); + } + } + } + + if (!font_ref) { + CFAutoRelease name(CFStringCreateWithCString(kCFAllocatorDefault, settings->font, kCFStringEncodingUTF8)); + + /* Simply creating the font using CTFontCreateWithNameAndSize will *always* return + * something, no matter the name. As such, we can't use it to check for existence. + * We instead query the list of all font descriptors that match the given name which + * does not do this stupid name fallback. */ + CFAutoRelease name_desc(CTFontDescriptorCreateWithNameAndSize(name.get(), 0.0)); + CFAutoRelease mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&kCTFontNameAttribute)), 1, &kCFTypeSetCallBacks)); + CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(name_desc.get(), mandatory_attribs.get())); + + /* Assume the first result is the one we want. */ + if (descs && CFArrayGetCount(descs.get()) > 0) { + font_ref.reset((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0)); + CFRetain(font_ref.get()); + } + } + + if (!font_ref) { + ShowInfoF("Unable to use '%s' for %s font, using sprite font instead", settings->font, SIZE_TO_NAME[fs]); + return; + } + + new CoreTextFontCache(fs, std::move(font_ref), settings->size); +} diff --git a/src/os/macosx/font_osx.h b/src/os/macosx/font_osx.h new file mode 100644 index 0000000000..bdfd7316d0 --- /dev/null +++ b/src/os/macosx/font_osx.h @@ -0,0 +1,40 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file font_osx.h Functions related to font handling on MacOS. */ + +#ifndef FONT_OSX_H +#define FONT_OSX_H + +#include "../../fontcache_internal.h" +#include "os/macosx/macos.h" + +#include + +class CoreTextFontCache : public TrueTypeFontCache { + CFAutoRelease font_desc; ///< Font descriptor exlcuding font size. + CFAutoRelease font; ///< CoreText font handle. + + std::string font_name; ///< Cached font name. + + void SetFontSize(int pixels); + const Sprite *InternalGetGlyph(GlyphID key, bool use_aa) override; + const void *InternalGetFontTable(uint32 tag, size_t &length) override; +public: + CoreTextFontCache(FontSize fs, CFAutoRelease &&font, int pixels); + ~CoreTextFontCache() {} + + void ClearFontCache() override; + GlyphID MapCharToGlyph(WChar key) override; + const char *GetFontName() override { return font_name.c_str(); } + bool IsBuiltInFont() override { return false; } + const void *GetOSHandle() override { return font.get(); } +}; + +void LoadCoreTextFont(FontSize fs); + +#endif /* FONT_OSX_H */ diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 12440e1e1c..5cd14e8e1e 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -174,12 +174,16 @@ static CTRunDelegateCallbacks _sprite_font_callback = { for (const auto &i : fontMapping) { if (i.first - last == 0) continue; - if (!_font_cache[i.second->fc->GetSize()]) { - /* Cache font information. */ - CFAutoRelease font_name(CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8)); - _font_cache[i.second->fc->GetSize()].reset(CTFontCreateWithName(font_name.get(), i.second->fc->GetFontSize(), nullptr)); + CTFontRef font = (CTFontRef)i.second->fc->GetOSHandle(); + if (font == nullptr) { + if (!_font_cache[i.second->fc->GetSize()]) { + /* Cache font information. */ + CFAutoRelease font_name(CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8)); + _font_cache[i.second->fc->GetSize()].reset(CTFontCreateWithName(font_name.get(), i.second->fc->GetFontSize(), nullptr)); + } + font = _font_cache[i.second->fc->GetSize()].get(); } - CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTFontAttributeName, _font_cache[i.second->fc->GetSize()].get()); + CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTFontAttributeName, font); CGColorRef color = CGColorCreateGenericGray((uint8)i.second->colour / 255.0f, 1.0f); // We don't care about the real colours, just that they are different. CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color); @@ -300,7 +304,7 @@ void MacOSRegisterExternalFont(const char *file_path) CTFontManagerRegisterFontsForURL(url.get(), kCTFontManagerScopeProcess, nullptr); } -/** Store current language locale as a CoreFounation locale. */ +/** Store current language locale as a CoreFoundation locale. */ void MacOSSetCurrentLocaleName(const char *iso_code) { if (!MacOSVersionIsAtLeast(10, 5, 0)) return; diff --git a/src/settings.cpp b/src/settings.cpp index b5a07fbb25..d3be596929 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -38,7 +38,7 @@ #include "sound_func.h" #include "company_func.h" #include "rev.h" -#if defined(WITH_FREETYPE) || defined(_WIN32) +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) #include "fontcache.h" #endif #include "textbuf_gui.h" @@ -67,7 +67,7 @@ #include "void_map.h" #include "station_base.h" -#if defined(WITH_FREETYPE) || defined(_WIN32) +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) #define HAS_TRUETYPE_FONT #endif diff --git a/src/strings.cpp b/src/strings.cpp index 1d6fca8b6f..acebf88eed 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2073,7 +2073,7 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher { void SetFontNames(FreeTypeSettings *settings, const char *font_name, const void *os_data) override { -#if defined(WITH_FREETYPE) || defined(_WIN32) +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) strecpy(settings->small.font, font_name, lastof(settings->small.font)); strecpy(settings->medium.font, font_name, lastof(settings->medium.font)); strecpy(settings->large.font, font_name, lastof(settings->large.font)); @@ -2103,7 +2103,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) static LanguagePackGlyphSearcher pack_searcher; if (searcher == nullptr) searcher = &pack_searcher; bool bad_font = !base_font || searcher->FindMissingGlyphs(); -#if defined(WITH_FREETYPE) || defined(_WIN32) +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) if (bad_font) { /* We found an unprintable character... lets try whether we can find * a fallback font that can print the characters in the current language. */ diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index fd544f5fc4..075898fd71 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -194,7 +194,7 @@ void TextfileWindow::SetupScrollbars() /* virtual */ void TextfileWindow::SetFontNames(FreeTypeSettings *settings, const char *font_name, const void *os_data) { -#if defined(WITH_FREETYPE) || defined(_WIN32) +#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) strecpy(settings->mono.font, font_name, lastof(settings->mono.font)); settings->mono.os_handle = os_data; #endif From b66e977acd6790d2e7c26d39f17ac5158b499167 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 23:08:02 +0100 Subject: [PATCH 092/275] Change: [OSX] When auto-detecting a font, try for sans-serif first. On a display, especially with small fonts or low pixel sizes, sans-serif fonts are usually easier to read than serif fonts. --- src/os/macosx/font_osx.cpp | 57 +++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index 4ce2b24e09..0a1b9e99ab 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -101,36 +101,43 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i CFAutoRelease descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get())); bool result = false; - for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) { - CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i); + for (int tries = 0; tries < 2; tries++) { + for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) { + CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i); - /* Get font traits. */ - CFAutoRelease traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)); - CTFontSymbolicTraits symbolic_traits; - CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); + /* Get font traits. */ + CFAutoRelease traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)); + CTFontSymbolicTraits symbolic_traits; + CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits); - /* Skip symbol fonts and vertical fonts. */ - if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; - /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ - if (symbolic_traits & kCTFontBoldTrait) continue; - /* Select monospaced fonts if asked for. */ - if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; + /* Skip symbol fonts and vertical fonts. */ + if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue; + /* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */ + if (symbolic_traits & kCTFontBoldTrait) continue; + /* Select monospaced fonts if asked for. */ + if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue; - /* Get font name. */ - char name[128]; - CFAutoRelease font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute)); - CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8); + /* Get font name. */ + char name[128]; + CFAutoRelease font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute)); + CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8); - /* There are some special fonts starting with an '.' and the last - * resort font that aren't usable. Skip them. */ - if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; + /* Serif fonts usually look worse on-screen with only small + * font sizes. As such, we try for a sans-serif font first. + * If we can't find one in the first try, try all fonts. */ + if (tries == 0 && (symbolic_traits & kCTFontClassMaskTrait) != (CTFontStylisticClass)kCTFontSansSerifClass) continue; - /* Save result. */ - callback->SetFontNames(settings, name); - if (!callback->FindMissingGlyphs()) { - DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); - result = true; - break; + /* There are some special fonts starting with an '.' and the last + * resort font that aren't usable. Skip them. */ + if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue; + + /* Save result. */ + callback->SetFontNames(settings, name); + if (!callback->FindMissingGlyphs()) { + DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name); + result = true; + break; + } } } From 8906e9e0fd6dc7bd64f9ad2c633da6f110dbf921 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Wed, 6 Jan 2021 23:02:10 +0100 Subject: [PATCH 093/275] Codechange: Consistently use screen size and not driver resolution for determining window sizes. --- src/video/cocoa/cocoa_v.mm | 2 +- src/window.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 5493c06525..c1fb996dec 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -270,7 +270,7 @@ bool VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) */ bool VideoDriver_Cocoa::AfterBlitterChange() { - this->ChangeResolution(_screen.width, _screen.height); + this->ChangeResolution(_cur_resolution.width, _cur_resolution.height); this->UpdatePalette(0, 256); return true; } diff --git a/src/window.cpp b/src/window.cpp index aea7bf3418..5e49aacb0f 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2158,8 +2158,8 @@ void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen) * the resolution clamp it in such a manner that it stays within the bounds. */ int new_right = w->left + w->width + delta_x; int new_bottom = w->top + w->height + delta_y; - if (new_right >= (int)_cur_resolution.width) delta_x -= Ceil(new_right - _cur_resolution.width, std::max(1U, w->nested_root->resize_x)); - if (new_bottom >= (int)_cur_resolution.height) delta_y -= Ceil(new_bottom - _cur_resolution.height, std::max(1U, w->nested_root->resize_y)); + if (new_right >= (int)_screen.width) delta_x -= Ceil(new_right - _screen.width, std::max(1U, w->nested_root->resize_x)); + if (new_bottom >= (int)_screen.height) delta_y -= Ceil(new_bottom - _screen.height, std::max(1U, w->nested_root->resize_y)); } w->SetDirty(); @@ -3468,7 +3468,7 @@ void ReInitAllWindows() NetworkReInitChatBoxSize(); /* Make sure essential parts of all windows are visible */ - RelocateAllWindows(_cur_resolution.width, _cur_resolution.height); + RelocateAllWindows(_screen.width, _screen.height); MarkWholeScreenDirty(); } From 0fc763bc5597e04ee528a34ca2730f780d25fb5e Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 7 Jan 2021 21:18:25 +0100 Subject: [PATCH 094/275] Change: [OSX] Render screen in full native resolution on HiDPI displays. --- os/macosx/Info.plist.in | 2 ++ src/video/cocoa/cocoa_v.mm | 16 ++++++++++++++-- src/video/cocoa/cocoa_wnd.h | 3 +++ src/video/cocoa/cocoa_wnd.mm | 30 ++++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/os/macosx/Info.plist.in b/os/macosx/Info.plist.in index 04d6ea6d33..359d28de8d 100644 --- a/os/macosx/Info.plist.in +++ b/os/macosx/Info.plist.in @@ -29,5 +29,7 @@ Copyright 2004-${CURRENT_YEAR} The OpenTTD team NSPrincipalClass NSApplication + NSHighResolutionCapable + True diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index c1fb996dec..c21edc7acd 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -322,6 +322,11 @@ void VideoDriver_Cocoa::GameSizeChanged() BlitterFactory::GetCurrentBlitter()->PostResize(); ::GameSizeChanged(); + + /* We need to store the window size as non-Retina size in + * the config file to get same windows size on next start. */ + _cur_resolution.width = [ this->cocoaview frame ].size.width; + _cur_resolution.height = [ this->cocoaview frame ].size.height; } /** @@ -491,7 +496,7 @@ void VideoDriver_Cocoa::Draw(bool force_update) /* Normally drawRect will be automatically called by Mac OS X during next update cycle, * and then blitting will occur. If force_update is true, it will be done right now. */ - [ this->cocoaview setNeedsDisplayInRect:dirtyrect ]; + [ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ]; if (force_update) [ this->cocoaview displayIfNeeded ]; } @@ -530,7 +535,7 @@ void VideoDriver_Cocoa::AllocateBackingStore() { if (this->window == nil || this->cocoaview == nil || this->setup) return; - NSRect newframe = [ this->cocoaview frame ]; + NSRect newframe = [ this->cocoaview getRealRect:[ this->cocoaview frame ] ]; this->window_width = (int)newframe.size.width; this->window_height = (int)newframe.size.height; @@ -743,6 +748,13 @@ void VideoDriver_Cocoa::GameLoop() CGImageRelease(fullImage); } +- (void)viewDidChangeBackingProperties +{ + [ super viewDidChangeBackingProperties ]; + + self.layer.contentsScale = [ driver->cocoaview getContentsScale ]; +} + @end #endif /* WITH_COCOA */ diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index fa7036396c..55f0561b77 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -38,6 +38,9 @@ extern NSString *OTTDMainLaunchGameEngine; /** Subclass of NSView to support mouse awareness and text input. */ @interface OTTD_CocoaView : NSView +- (NSRect)getRealRect:(NSRect)rect; +- (NSRect)getVirtualRect:(NSRect)rect; +- (CGFloat)getContentsScale; - (NSPoint)mousePositionFromEvent:(NSEvent *)e; @end diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 089bfe8344..cd194f7128 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -417,6 +417,30 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel float _current_magnification; NSUInteger _current_mods; bool _emulated_down; + bool _use_hidpi; +} + +- (instancetype)initWithFrame:(NSRect)frameRect +{ + if (self = [ super initWithFrame:frameRect ]) { + self->_use_hidpi = [ self respondsToSelector:@selector(convertRectToBacking:) ] && [ self respondsToSelector:@selector(convertRectFromBacking:) ]; + } + return self; +} + +- (NSRect)getRealRect:(NSRect)rect +{ + return _use_hidpi ? [ self convertRectToBacking:rect ] : rect; +} + +- (NSRect)getVirtualRect:(NSRect)rect +{ + return _use_hidpi ? [ self convertRectFromBacking:rect ] : rect; +} + +- (CGFloat)getContentsScale +{ + return _use_hidpi && self.window != nil ? [ self.window backingScaleFactor ] : 1.0f; } /** @@ -483,15 +507,13 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel if ([ e window ] == nil) pt = [ self.window convertRectFromScreen:NSMakeRect(pt.x, pt.y, 0, 0) ].origin; pt = [ self convertPoint:pt fromView:nil ]; - pt.y = self.bounds.size.height - pt.y; - - return pt; + return [ self getRealRect:NSMakeRect(pt.x, self.bounds.size.height - pt.y, 0, 0) ].origin; } - (void)internalMouseMoveEvent:(NSEvent *)event { if (_cursor.fix_at) { - _cursor.UpdateCursorPositionRelative(event.deltaX, event.deltaY); + _cursor.UpdateCursorPositionRelative(event.deltaX * self.getContentsScale, event.deltaY * self.getContentsScale); } else { NSPoint pt = [ self mousePositionFromEvent:event ]; _cursor.UpdateCursorPosition(pt.x, pt.y, false); From e5c325364285b1e6e93afa2a0a79b1ec437f238e Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 7 Jan 2021 22:09:43 +0100 Subject: [PATCH 095/275] Add: [OSX] Setting to disable HiDPI graphics rendering. --- src/table/misc_settings.ini | 10 ++++++++++ src/video/cocoa/cocoa_wnd.mm | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index d46ebe9bb4..edc779cafd 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -9,6 +9,10 @@ extern std::string _config_language_file; static const char *_support8bppmodes = "no|system|hardware"; +#ifdef WITH_COCOA +extern bool _allow_hidpi_window; +#endif + static const SettingDescGlobVarList _misc_settings[] = { [post-amble] }; @@ -317,5 +321,11 @@ min = ZOOM_LVL_MIN max = ZOOM_LVL_OUT_4X cat = SC_BASIC +[SDTG_BOOL] +ifdef = WITH_COCOA +name = ""allow_hidpi"" +var = _allow_hidpi_window +def = true + [SDTG_END] diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index cd194f7128..afe2cece69 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -46,6 +46,8 @@ * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information. */ +bool _allow_hidpi_window = true; // Referenced from table/misc_settings.ini + @interface OTTDMain : NSObject @end @@ -417,13 +419,13 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel float _current_magnification; NSUInteger _current_mods; bool _emulated_down; - bool _use_hidpi; + bool _use_hidpi; ///< Render content in native resolution? } - (instancetype)initWithFrame:(NSRect)frameRect { if (self = [ super initWithFrame:frameRect ]) { - self->_use_hidpi = [ self respondsToSelector:@selector(convertRectToBacking:) ] && [ self respondsToSelector:@selector(convertRectFromBacking:) ]; + self->_use_hidpi = _allow_hidpi_window && [ self respondsToSelector:@selector(convertRectToBacking:) ] && [ self respondsToSelector:@selector(convertRectFromBacking:) ]; } return self; } From f5555a6d262a77f3754934447d7440df381f37d9 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 14 Feb 2021 12:36:11 +0100 Subject: [PATCH 096/275] Fix 9c872192: [OSX] Clear mouse button emulation flag. --- src/video/cocoa/cocoa_wnd.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index afe2cece69..30fa3969bc 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -564,6 +564,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (void)mouseUp:(NSEvent *)event { if (self->_emulated_down) { + self->_emulated_down = false; [ self rightMouseUp:event ]; } else { _left_button_down = false; From a2c3197f424daa6e02201d8304015b0eb67d0b04 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 8 Jan 2021 22:11:57 +0100 Subject: [PATCH 097/275] Codechange: Make the settings for min/max zoom early load settings. --- src/table/misc_settings.ini | 29 +++++++++++++++++++++++++++++ src/table/settings.ini | 27 --------------------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index edc779cafd..be5088ec9e 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -5,6 +5,8 @@ ; [pre-amble] +static bool ZoomMinMaxChanged(int32 p1); + extern std::string _config_language_file; static const char *_support8bppmodes = "no|system|hardware"; @@ -24,6 +26,7 @@ SDTG_STR = SDTG_STR($name, $type, $flags, $guiflags, $var, $def, SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), +SDTC_VAR = SDTC_VAR($var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra), SDTG_END = SDTG_END() [defaults] @@ -303,6 +306,32 @@ min = 0 max = UINT32_MAX cat = SC_EXPERT +[SDTC_VAR] +var = gui.zoom_min +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = ZOOM_LVL_MIN +min = ZOOM_LVL_MIN +max = ZOOM_LVL_OUT_4X +str = STR_CONFIG_SETTING_ZOOM_MIN +strhelp = STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT +strval = STR_CONFIG_SETTING_ZOOM_LVL_MIN +proc = ZoomMinMaxChanged + +[SDTC_VAR] +var = gui.zoom_max +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = ZOOM_LVL_MAX +min = ZOOM_LVL_OUT_8X +max = ZOOM_LVL_MAX +str = STR_CONFIG_SETTING_ZOOM_MAX +strhelp = STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT +strval = STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X +proc = ZoomMinMaxChanged + [SDTG_VAR] name = ""gui_zoom"" type = SLE_UINT8 diff --git a/src/table/settings.ini b/src/table/settings.ini index 2e085058f2..e08cadafe9 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -38,7 +38,6 @@ static bool InvalidateAISettingsWindow(int32 p1); static bool RedrawTownAuthority(int32 p1); static bool InvalidateCompanyInfrastructureWindow(int32 p1); static bool InvalidateCompanyWindow(int32 p1); -static bool ZoomMinMaxChanged(int32 p1); static bool MaxVehiclesChanged(int32 p1); static bool InvalidateShipPathCache(int32 p1); @@ -2791,32 +2790,6 @@ strhelp = STR_CONFIG_SETTING_SOFT_LIMIT_HELPTEXT strval = STR_CONFIG_SETTING_SOFT_LIMIT_VALUE cat = SC_EXPERT -[SDTC_VAR] -var = gui.zoom_min -type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING -def = ZOOM_LVL_MIN -min = ZOOM_LVL_MIN -max = ZOOM_LVL_OUT_4X -str = STR_CONFIG_SETTING_ZOOM_MIN -strhelp = STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT -strval = STR_CONFIG_SETTING_ZOOM_LVL_MIN -proc = ZoomMinMaxChanged - -[SDTC_VAR] -var = gui.zoom_max -type = SLE_UINT8 -flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -guiflags = SGF_MULTISTRING -def = ZOOM_LVL_MAX -min = ZOOM_LVL_OUT_8X -max = ZOOM_LVL_MAX -str = STR_CONFIG_SETTING_ZOOM_MAX -strhelp = STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT -strval = STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X -proc = ZoomMinMaxChanged - [SDTC_BOOL] var = gui.population_in_label flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC From 22f5aeab07cb1c67561b9e348e2c944740233607 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 8 Jan 2021 22:15:06 +0100 Subject: [PATCH 098/275] Feature: Automatic UI and font zoom levels when supported by the OS. --- src/gfx.cpp | 24 ++++++++++++++++++++++++ src/gfx_func.h | 1 + src/lang/english.txt | 2 ++ src/openttd.cpp | 1 + src/settings_gui.cpp | 18 +++++++++++------- src/table/misc_settings.ini | 16 ++++++++-------- src/video/video_driver.hpp | 21 ++++++++++++++++++++- src/zoom_type.h | 5 +++++ 8 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 54851d375f..786bbb25b5 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -59,6 +59,10 @@ static ReusableBuffer _cursor_backup; ZoomLevel _gui_zoom; ///< GUI Zoom level ZoomLevel _font_zoom; ///< Font Zoom level +int8 _gui_zoom_cfg; ///< GUI zoom level in config. +int8 _font_zoom_cfg; ///< Font zoom level in config. + + /** * The rect for repaint. * @@ -1876,3 +1880,23 @@ void SortResolutions() { std::sort(_resolutions.begin(), _resolutions.end()); } + +/** + * Resolve GUI zoom level, if auto-suggestion is requested. + */ +void UpdateGUIZoom() +{ + /* Determine real GUI zoom to use. */ + if (_gui_zoom_cfg == ZOOM_LVL_CFG_AUTO) { + _gui_zoom = static_cast(Clamp(VideoDriver::GetInstance()->GetSuggestedUIZoom(), _settings_client.gui.zoom_min, _settings_client.gui.zoom_max)); + } else { + _gui_zoom = static_cast(_gui_zoom_cfg); + } + + /* Determine real font zoom to use. */ + if (_font_zoom_cfg == ZOOM_LVL_CFG_AUTO) { + _font_zoom = static_cast(VideoDriver::GetInstance()->GetSuggestedUIZoom()); + } else { + _font_zoom = static_cast(_font_zoom_cfg); + } +} diff --git a/src/gfx_func.h b/src/gfx_func.h index 7ac26f29bb..8695fa0e28 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -77,6 +77,7 @@ void UpdateWindows(); void DrawMouseCursor(); void ScreenSizeChanged(); void GameSizeChanged(); +void UpdateGUIZoom(); void UndrawMouseCursor(); /** Size of the buffer used for drawing strings. */ diff --git a/src/lang/english.txt b/src/lang/english.txt index 567d238203..88ef187027 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1004,6 +1004,7 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :other STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Interface size STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Select the interface element size to use +STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO :(auto-detect) STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Double size STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Quad size @@ -1011,6 +1012,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Quad size STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Font size STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Select the interface font size to use +STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(auto-detect) STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Normal STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Double size STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Quad size diff --git a/src/openttd.cpp b/src/openttd.cpp index a631bd852b..b68f378cf6 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -771,6 +771,7 @@ int openttd_main(int argc, char *argv[]) /* Initialize the zoom level of the screen to normal */ _screen.zoom = ZOOM_LVL_NORMAL; + UpdateGUIZoom(); NetworkStartUp(); // initialize network-core diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index e04c50ac34..8bf118e76c 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -58,6 +58,7 @@ static const StringID _autosave_dropdown[] = { }; static const StringID _gui_zoom_dropdown[] = { + STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM, @@ -65,6 +66,7 @@ static const StringID _gui_zoom_dropdown[] = { }; static const StringID _font_zoom_dropdown[] = { + STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM, @@ -291,16 +293,16 @@ struct GameOptionsWindow : Window { break; case WID_GO_GUI_ZOOM_DROPDOWN: { - *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom; + *selected_index = _gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom + 1 : 0; const StringID *items = _gui_zoom_dropdown; for (int i = 0; *items != INVALID_STRING_ID; items++, i++) { - list.emplace_back(new DropDownListStringItem(*items, i, _settings_client.gui.zoom_min > ZOOM_LVL_OUT_4X - i)); + list.emplace_back(new DropDownListStringItem(*items, i, i != 0 && _settings_client.gui.zoom_min > ZOOM_LVL_OUT_4X - i + 1)); } break; } case WID_GO_FONT_ZOOM_DROPDOWN: { - *selected_index = ZOOM_LVL_OUT_4X - _font_zoom; + *selected_index = _font_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _font_zoom + 1 : 0; const StringID *items = _font_zoom_dropdown; for (int i = 0; *items != INVALID_STRING_ID; items++, i++) { list.emplace_back(new DropDownListStringItem(*items, i, false)); @@ -333,8 +335,8 @@ struct GameOptionsWindow : Window { case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break; case WID_GO_LANG_DROPDOWN: SetDParamStr(0, _current_language->own_name); break; case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _resolutions.size() ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break; - case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break; - case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break; + case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[_gui_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _gui_zoom_cfg + 1 : 0]); break; + case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[_font_zoom_cfg != ZOOM_LVL_CFG_AUTO ? ZOOM_LVL_OUT_4X - _font_zoom_cfg + 1 : 0]); break; case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name.c_str()); break; case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break; case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name.c_str()); break; @@ -538,7 +540,8 @@ struct GameOptionsWindow : Window { case WID_GO_GUI_ZOOM_DROPDOWN: GfxClearSpriteCache(); - _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index); + _gui_zoom_cfg = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; + UpdateGUIZoom(); UpdateCursorSize(); UpdateAllVirtCoords(); FixTitleGameZoom(); @@ -547,7 +550,8 @@ struct GameOptionsWindow : Window { case WID_GO_FONT_ZOOM_DROPDOWN: GfxClearSpriteCache(); - _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index); + _font_zoom_cfg = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; + UpdateGUIZoom(); ClearFontCache(); LoadStringWidthTable(); UpdateAllVirtCoords(); diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index be5088ec9e..8cb6d4211f 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -334,19 +334,19 @@ proc = ZoomMinMaxChanged [SDTG_VAR] name = ""gui_zoom"" -type = SLE_UINT8 -var = _gui_zoom -def = ZOOM_LVL_OUT_4X -min = ZOOM_LVL_MIN +type = SLE_INT8 +var = _gui_zoom_cfg +def = ZOOM_LVL_CFG_AUTO +min = ZOOM_LVL_CFG_AUTO max = ZOOM_LVL_OUT_4X cat = SC_BASIC [SDTG_VAR] name = ""font_zoom"" -type = SLE_UINT8 -var = _font_zoom -def = ZOOM_LVL_OUT_4X -min = ZOOM_LVL_MIN +type = SLE_INT8 +var = _font_zoom_cfg +def = ZOOM_LVL_CFG_AUTO +min = ZOOM_LVL_CFG_AUTO max = ZOOM_LVL_OUT_4X cat = SC_BASIC diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index d4e7501342..bc445d92d1 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -13,6 +13,7 @@ #include "../driver.h" #include "../core/geometry_type.hpp" #include "../core/math_func.hpp" +#include "../zoom_type.h" #include extern std::string _ini_videodriver; @@ -105,6 +106,18 @@ public: */ virtual void EditBoxGainedFocus() {} + /** + * Get a suggested default GUI zoom taking screen DPI into account. + */ + virtual ZoomLevel GetSuggestedUIZoom() + { + float dpi_scale = this->GetDPIScale(); + + if (dpi_scale >= 3.0f) return ZOOM_LVL_NORMAL; + if (dpi_scale >= 1.5f) return ZOOM_LVL_OUT_2X; + return ZOOM_LVL_OUT_4X; + } + /** * Get the currently active instance of the video driver. */ @@ -113,11 +126,17 @@ public: } protected: - /* + /** * Get the resolution of the main screen. */ virtual Dimension GetScreenSize() const { return { DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT }; } + /** + * Get DPI scaling factor of the screen OTTD is displayed on. + * @return 1.0 for default platform DPI, > 1.0 for higher DPI values, and < 1.0 for smaller DPI values. + */ + virtual float GetDPIScale() { return 1.0f; } + /** * Apply resolution auto-detection and clamp to sensible defaults. */ diff --git a/src/zoom_type.h b/src/zoom_type.h index 2606e07677..0945e1cc09 100644 --- a/src/zoom_type.h +++ b/src/zoom_type.h @@ -15,6 +15,8 @@ static uint const ZOOM_LVL_SHIFT = 2; static uint const ZOOM_LVL_BASE = 1 << ZOOM_LVL_SHIFT; +static const int8 ZOOM_LVL_CFG_AUTO = -1; + /** All zoom levels we know. */ enum ZoomLevel : byte { /* Our possible zoom-levels */ @@ -48,6 +50,9 @@ enum ZoomLevel : byte { }; DECLARE_POSTFIX_INCREMENT(ZoomLevel) +extern int8 _gui_zoom_cfg; +extern int8 _font_zoom_cfg; + extern ZoomLevel _gui_zoom; extern ZoomLevel _font_zoom; #define ZOOM_LVL_GUI (_gui_zoom) From 33099355b8f89e9a2e87f3f7797b7366fc68f330 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sat, 13 Feb 2021 19:24:11 +0100 Subject: [PATCH 099/275] Codechange: Re-init GUI zoom only when really changed. --- src/settings_gui.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 8bf118e76c..6abc4260f8 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -538,24 +538,32 @@ struct GameOptionsWindow : Window { } break; - case WID_GO_GUI_ZOOM_DROPDOWN: - GfxClearSpriteCache(); - _gui_zoom_cfg = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; - UpdateGUIZoom(); - UpdateCursorSize(); - UpdateAllVirtCoords(); - FixTitleGameZoom(); - ReInitAllWindows(); + case WID_GO_GUI_ZOOM_DROPDOWN: { + int8 new_zoom = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; + if (new_zoom != _gui_zoom_cfg) { + GfxClearSpriteCache(); + _gui_zoom_cfg = new_zoom; + UpdateGUIZoom(); + UpdateCursorSize(); + UpdateAllVirtCoords(); + FixTitleGameZoom(); + ReInitAllWindows(); + } break; + } - case WID_GO_FONT_ZOOM_DROPDOWN: - GfxClearSpriteCache(); - _font_zoom_cfg = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; - UpdateGUIZoom(); - ClearFontCache(); - LoadStringWidthTable(); - UpdateAllVirtCoords(); + case WID_GO_FONT_ZOOM_DROPDOWN: { + int8 new_zoom = index > 0 ? ZOOM_LVL_OUT_4X - index + 1 : ZOOM_LVL_CFG_AUTO; + if (new_zoom != _font_zoom_cfg) { + GfxClearSpriteCache(); + _font_zoom_cfg = new_zoom; + UpdateGUIZoom(); + ClearFontCache(); + LoadStringWidthTable(); + UpdateAllVirtCoords(); + } break; + } case WID_GO_BASE_GRF_DROPDOWN: this->SetMediaSet(index); From f137b3057a9f618fbdfd9dc2f7eee1ea576086ac Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 14 Jan 2021 23:11:21 +0100 Subject: [PATCH 100/275] Codechange: [Win32] Increase SDK version for 32-bit target. Use the same Windows XP target as for 64-bit. Current MSVC version will not produce a binary that works on anything earlier anyway. --- src/stdafx.h | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/stdafx.h b/src/stdafx.h index 7ee3ce2041..fe2dc8f612 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -157,22 +157,12 @@ /* Stuff for MSVC */ #if defined(_MSC_VER) # pragma once -# ifdef _WIN64 - /* No 64-bit Windows below XP, so we can safely assume it as the target platform. */ -# define NTDDI_VERSION NTDDI_WINXP // Windows XP -# define _WIN32_WINNT 0x501 // Windows XP -# define _WIN32_WINDOWS 0x501 // Windows XP -# define WINVER 0x0501 // Windows XP -# define _WIN32_IE_ 0x0600 // 6.0 (XP+) -# else - /* Define a win32 target platform, to override defaults of the SDK - * We need to define NTDDI version for Vista SDK, but win2k is minimum */ -# define NTDDI_VERSION NTDDI_WIN2K // Windows 2000 -# define _WIN32_WINNT 0x0500 // Windows 2000 -# define _WIN32_WINDOWS 0x400 // Windows 95 -# define WINVER 0x0400 // Windows NT 4.0 / Windows 95 -# define _WIN32_IE_ 0x0401 // 4.01 (win98 and NT4SP5+) -# endif +# define NTDDI_VERSION NTDDI_WINXP // Windows XP +# define _WIN32_WINNT 0x501 // Windows XP +# define _WIN32_WINDOWS 0x501 // Windows XP +# define WINVER 0x0501 // Windows XP +# define _WIN32_IE_ 0x0600 // 6.0 (XP+) + # define NOMINMAX // Disable min/max macros in windows.h. # pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data From f175e38666e2f21f5873e95ca52f5aa321e8d3bf Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Fri, 8 Jan 2021 22:17:04 +0100 Subject: [PATCH 101/275] Add: [Win32] Automatic zoom level suggestion for Win32 video driver. The zoom level suggestion is based on the DPI scaling set in Windows. We use 150% scaling as the threshold for 2X zoom and 300% scaling as the threshold for 4X zoom. --- src/video/win32_v.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/video/win32_v.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index c1b31d14ab..68e6572baa 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -1316,3 +1316,43 @@ Dimension VideoDriver_Win32::GetScreenSize() const { return { static_cast(GetSystemMetrics(SM_CXSCREEN)), static_cast(GetSystemMetrics(SM_CYSCREEN)) }; } + +float VideoDriver_Win32::GetDPIScale() +{ + typedef UINT (WINAPI *PFNGETDPIFORWINDOW)(HWND hwnd); + typedef UINT (WINAPI *PFNGETDPIFORSYSTEM)(VOID); + typedef HRESULT (WINAPI *PFNGETDPIFORMONITOR)(HMONITOR hMonitor, int dpiType, UINT *dpiX, UINT *dpiY); + + static PFNGETDPIFORWINDOW _GetDpiForWindow = nullptr; + static PFNGETDPIFORSYSTEM _GetDpiForSystem = nullptr; + static PFNGETDPIFORMONITOR _GetDpiForMonitor = nullptr; + + static bool init_done = false; + if (!init_done) { + init_done = true; + + _GetDpiForWindow = (PFNGETDPIFORWINDOW)GetProcAddress(GetModuleHandle(_T("User32")), "GetDpiForWindow"); + _GetDpiForSystem = (PFNGETDPIFORSYSTEM)GetProcAddress(GetModuleHandle(_T("User32")), "GetDpiForSystem"); + _GetDpiForMonitor = (PFNGETDPIFORMONITOR)GetProcAddress(LoadLibrary(_T("Shcore.dll")), "GetDpiForMonitor"); + } + + UINT cur_dpi = 0; + + if (cur_dpi == 0 && _GetDpiForWindow != nullptr && _wnd.main_wnd != nullptr) { + /* Per window DPI is supported since Windows 10 Ver 1607. */ + cur_dpi = _GetDpiForWindow(_wnd.main_wnd); + } + if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && _wnd.main_wnd != nullptr) { + /* Per monitor is supported since Windows 8.1. */ + UINT dpiX, dpiY; + if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(_wnd.main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) { + cur_dpi = dpiX; // X and Y are always identical. + } + } + if (cur_dpi == 0 && _GetDpiForSystem != nullptr) { + /* Fall back to system DPI. */ + cur_dpi = _GetDpiForSystem(); + } + + return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96. +} diff --git a/src/video/win32_v.h b/src/video/win32_v.h index ef02e132e6..1849a9ebc9 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -43,6 +43,8 @@ public: protected: Dimension GetScreenSize() const override; + + float GetDPIScale() override; }; /** The factory for Windows' video driver. */ From 8d780e0607b8f313251710639fb2642f6e733b97 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 14 Feb 2021 13:26:46 +0100 Subject: [PATCH 102/275] Add: [OSX] Automatic zoom level suggestion for Cocoa video driver. --- src/video/cocoa/cocoa_v.h | 1 + src/video/cocoa/cocoa_v.mm | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 596a9e27d4..5dd3d1d1f4 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -73,6 +73,7 @@ public: protected: Dimension GetScreenSize() const override; + float GetDPIScale() override; private: bool PollEvent(); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index c21edc7acd..4c6ce6cab2 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -294,6 +294,12 @@ Dimension VideoDriver_Cocoa::GetScreenSize() const return { static_cast(NSWidth(frame)), static_cast(NSHeight(frame)) }; } +/** Get DPI scale of our window. */ +float VideoDriver_Cocoa::GetDPIScale() +{ + return this->cocoaview != nil ? [ this->cocoaview getContentsScale ] : 1.0f; +} + /** * Are we in fullscreen mode? * @return whether fullscreen mode is currently used From 6b04b7cf187a17f8df027fe0134474b118c6a0d8 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 14 Feb 2021 19:01:09 +0000 Subject: [PATCH 103/275] Update: Translations from eints slovak: 13 changes by FuryPapaya catalan: 7 changes by J0anJosep french: 1 change by arikover --- src/lang/catalan.txt | 8 +++++++- src/lang/french.txt | 2 +- src/lang/slovak.txt | 20 +++++++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index 926ee9f55f..5a754ff4fe 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -2606,12 +2606,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Aleatori # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Finança una nova indústria STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Escolleix el tipus d'indústria adequada d'aquesta llista -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Moltes indústries aleatòries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Crea indústries aleatòries STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Omple el mapa amb indústries situades aleatòriament +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Crea indústries aleatòries +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Esteu segur que voleu crear moltes indústries aleatòries? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Cost: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospecciona STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Construeix STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Finança +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Treu totes les indústries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Treu totes les indústries que hi ha actualment al mapa. +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Treu totes les indústries +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Esteu segur que voleu treure totes les indústries? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Cadena industrial per la indústria {STRING} diff --git a/src/lang/french.txt b/src/lang/french.txt index 868063acb8..198e6bd4db 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -4696,7 +4696,7 @@ STR_TOWN_BUILDING_NAME_OFFICE_BLOCK_1 :Immeuble de bur STR_TOWN_BUILDING_NAME_SMALL_BLOCK_OF_FLATS_1 :Petit immeuble résidentiel STR_TOWN_BUILDING_NAME_CHURCH_1 :Église STR_TOWN_BUILDING_NAME_LARGE_OFFICE_BLOCK_1 :Gros immeuble de bureaux -STR_TOWN_BUILDING_NAME_TOWN_HOUSES_1 :Bâtiments municipaux +STR_TOWN_BUILDING_NAME_TOWN_HOUSES_1 :Maisons de ville STR_TOWN_BUILDING_NAME_HOTEL_1 :Hôtel STR_TOWN_BUILDING_NAME_STATUE_1 :Statue STR_TOWN_BUILDING_NAME_FOUNTAIN_1 :Fontaine diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index 565b811678..4562072e75 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -2645,7 +2645,7 @@ STR_FOUND_TOWN_NEW_TOWN_TOOLTIP :{BLACK}Založi STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Nahodné mesto STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Postaviť mesto na náhodnej pozícii STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Veľa náhodných miest -STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Pokryt mapu nahodne umiestnenymi mestami +STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Pokryť mapu náhodne umiestnenými mestami STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Meno mesta: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Vložte meno mesta @@ -2673,12 +2673,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Náhodn # Fund new industry window STR_FUND_INDUSTRY_CAPTION :{WHITE}Financovať nový priemysel STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Vyberte vhodný typ priemyslu zo zoznamu -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Veľa náhodného priemyslu -STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Pokryt mapu nahodne umiestnenym priemyslom +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Vytvoriť náhodný priemysel +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Pokryť mapu náhodne umiestneným priemyslom +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Vytvoriť náhodný priemysel +STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Ste si istý, že chcete vytvoriť veľké množstvo náhodného priemyslu? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Cena: {YELLOW}{CURRENCY_LONG} STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Vyhladat -STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Postavit -STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Založit +STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Postaviť +STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Založiť +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Odstrániť všetok priemysel +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Odstrániť všetok priemysel umiestnený na mape +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Odstrániť všetok priemysel +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Ste si istý, že chcete odstrániť všetok priemysel? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Reťazec pre priemysel: {STRING} @@ -4444,11 +4450,11 @@ STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... v ce # Industry related errors STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... príliš veľa priemyslu -STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemozno vygenerovat priemysel ... +STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nemožno vygenerovať priemysel... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING} sa tu nedá postaviť... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Nemôžeš tu postaviť tento typ priemyslu... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... príliš blízko iného priemyslu -STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... najskor treba postavit mesto... +STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... najskôr je potrebné založiť mesto STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... povolené len jedno pre 1mesto STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200 :{WHITE}... môže byť postavené v mestách z populáciou väčšou ako 1200 STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST :{WHITE}... môže byť postavené len v dažďovom pralese From a18188ae902b05aa355cd24e252e92d459e6e946 Mon Sep 17 00:00:00 2001 From: Joan Josep Date: Sun, 14 Feb 2021 23:09:01 +0100 Subject: [PATCH 104/275] Doc: Add labels to landscape grid description. (#8452) --- docs/landscape_grid.html | 425 +++++++++++++++++---------------------- 1 file changed, 184 insertions(+), 241 deletions(-) diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index d4a88d0bb5..7eac768591 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -5,10 +5,14 @@ OpenTTD Landscape Internals - #2