Merge branch 'master' into jgrpp

# Conflicts:
#	src/lang/english_US.txt
pull/221/head
Jonathan G Rennison 3 years ago
commit d58989f552

@ -194,6 +194,7 @@ STR_COLOUR_DEFAULT :Default
STR_UNITS_VELOCITY_IMPERIAL :{COMMA}{NBSP}mph
STR_UNITS_VELOCITY_METRIC :{COMMA}{NBSP}km/h
STR_UNITS_VELOCITY_SI :{COMMA}{NBSP}m/s
STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}tiles/day
STR_UNITS_POWER_IMPERIAL :{COMMA}{NBSP}hp
STR_UNITS_POWER_METRIC :{COMMA}{NBSP}hp
@ -313,8 +314,15 @@ STR_SORT_BY_CARGO_CAPACITY :Cargo capacity
STR_SORT_BY_RANGE :Range
STR_SORT_BY_POPULATION :Population
STR_SORT_BY_RATING :Rating
STR_SORT_BY_NUM_VEHICLES :Number of vehicles
STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Total profit last year
STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Total profit this year
STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Average profit last year
STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Average profit this year
# Group by options for vehicle list
STR_GROUP_BY_NONE :None
STR_GROUP_BY_SHARED_ORDERS :Shared orders
# Tooltips for the main toolbar
STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Pause game
@ -605,7 +613,7 @@ STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :Transport Coord
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :Route Supervisor
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR :Director
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE :Chief Executive
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :Chairman
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :Chairperson
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT :President
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON :Tycoon
@ -688,7 +696,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Click on
STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Top companies who reached {NUM}
STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME :{BIG_FONT}{BLACK}Company League Table in {NUM}
STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}.
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Businessman
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Businessperson
STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Entrepreneur
STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Industrialist
STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Capitalist
@ -740,6 +748,7 @@ STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLA
STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Rough Land
STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Grass Land
STR_SMALLMAP_LEGENDA_BARE_LAND :{TINY_FONT}{BLACK}Bare Land
STR_SMALLMAP_LEGENDA_RAINFOREST :{TINY_FONT}{BLACK}Rainforest
STR_SMALLMAP_LEGENDA_FIELDS :{TINY_FONT}{BLACK}Fields
STR_SMALLMAP_LEGENDA_TREES :{TINY_FONT}{BLACK}Trees
STR_SMALLMAP_LEGENDA_ROCKS :{TINY_FONT}{BLACK}Rocks
@ -771,6 +780,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Display
STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Show last message or news report
STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - -
STR_STATUSBAR_PAUSED :{YELLOW}* * PAUSED * *
STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * PAUSED (waiting for link graph update) * *
STR_STATUSBAR_AUTOSAVE :{RED}AUTOSAVE
STR_STATUSBAR_SAVING_GAME :{RED}* * SAVING GAME * *
@ -936,6 +946,8 @@ STR_GAME_OPTIONS_CURRENCY_MXN :Mexican Peso (M
STR_GAME_OPTIONS_CURRENCY_NTD :New Taiwan Dollar (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :Chinese Renminbi (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kong Dollar (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Indian Rupee (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :Indonesian Rupiah (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Drive on left
@ -992,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
@ -999,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
@ -1437,6 +1451,7 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Keep building t
STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Keep the building tools for bridges, tunnels, etc. open after use
STR_CONFIG_SETTING_EXPENSES_LAYOUT :Group expenses in company finance window: {STRING}
STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Define the layout for the company expenses window
STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatically remove signals during track construction if the signals are in the way. Note that this can potentially lead to train crashes.
STR_CONFIG_SETTING_SOUND_TICKER :News ticker: {STRING}
STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Play sound for summarized news messages
@ -1550,6 +1565,10 @@ STR_CONFIG_SETTING_ENDING_YEAR :Scoring end yea
STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Year the game ends for scoring purposes. At the end of this year, the company's score is recorded and the high-score screen is displayed, but the players can continue playing after that.{}If this is before the starting year, the high-score screen is never displayed.
STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM}
STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Never
STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT :Smooth economy makes production changes more often, and in smaller steps. Frozen economy stops production changes and industry closures. This setting may have no effect if industry types are provided by a NewGRF.
STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL :Original
STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH :Smooth
STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN :Frozen
STR_CONFIG_SETTING_ALLOW_SHARES :Allow buying shares from other companies: {STRING}
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT :When enabled, allow buying and selling of company shares. Shares will only be available for companies reaching a certain age
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES :Minimum company age to trade shares: {STRING}
@ -1601,6 +1620,10 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Linear
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :In-game placement of trees: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Control random appearance of trees during the game. This might affect industries which rely on tree growth, for example lumber mills
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Grow but don't spread {RED}(breaks lumber mill)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Grow but only spread in rain forests
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :Grow and spread everywhere
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Don't grow, don't spread {RED}(breaks lumber mill)
STR_CONFIG_SETTING_TOOLBAR_POS :Position of main toolbar: {STRING}
STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Horizontal position of the main toolbar at the top of the screen
@ -1667,6 +1690,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Whenever a spee
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metric (km/h)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Game units (tiles/day)
STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Vehicle power units: {STRING}
STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_HELPTEXT :Whenever a vehicle's power is shown in the user interface, show it in the selected units
@ -1810,6 +1834,7 @@ STR_ABANDON_SCENARIO_QUERY :{YELLOW}Are you
# Cheat window
STR_CHEATS :{WHITE}Cheats
STR_CHEATS_TOOLTIP :{BLACK}Checkboxes indicate if you have used this cheat before
STR_CHEATS_NOTE :{BLACK}Note: any usage of these settings will be recorded by the savegame
STR_CHEAT_MONEY :{LTBLUE}Increase money by {CURRENCY_LONG}
STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Playing as company: {ORANGE}{COMMA}
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Magic bulldozer (remove industries, unmovable objects): {ORANGE}{STRING}
@ -1961,6 +1986,10 @@ STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Join gam
STR_NETWORK_SERVER_LIST_REFRESH :{BLACK}Refresh server
STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP :{BLACK}Refresh the server info
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET :{BLACK}Search internet
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_INTERNET_TOOLTIP :{BLACK}Search internet for public servers
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN :{BLACK}Search LAN
STR_NETWORK_SERVER_LIST_SEARCH_SERVER_LAN_TOOLTIP :{BLACK}Search local area network for servers
STR_NETWORK_SERVER_LIST_ADD_SERVER :{BLACK}Add server
STR_NETWORK_SERVER_LIST_ADD_SERVER_TOOLTIP :{BLACK}Adds a server to the list which will always be checked for running games
STR_NETWORK_SERVER_LIST_START_SERVER :{BLACK}Start server
@ -2185,11 +2214,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Game still paus
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Game still paused ({STRING}, {STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Game still paused ({STRING}, {STRING}, {STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Game still paused ({STRING}, {STRING}, {STRING}, {STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Game still paused ({STRING}, {STRING}, {STRING}, {STRING}, {STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Game unpaused ({STRING})
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :number of players
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :connecting clients
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manual
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :game script
STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :waiting for link graph update
############ End of leave-in-this-order
STR_NETWORK_MESSAGE_CLIENT_LEAVING :leaving
STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} has joined the game
@ -2317,6 +2348,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Join way
STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Build a separate waypoint
# Generic toolbar
STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Disabled as currently no vehicles are available for this infrastructure
# Rail construction toolbar
STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Railroad Construction
@ -2512,6 +2544,12 @@ STR_TREES_RANDOM_TYPE :{BLACK}Trees of
STR_TREES_RANDOM_TYPE_TOOLTIP :{BLACK}Place trees of random type. Shift toggles building/showing cost estimate
STR_TREES_RANDOM_TREES_BUTTON :{BLACK}Random Trees
STR_TREES_RANDOM_TREES_TOOLTIP :{BLACK}Plant trees randomly throughout the landscape
STR_TREES_MODE_NORMAL_BUTTON :{BLACK}Normal
STR_TREES_MODE_NORMAL_TOOLTIP :{BLACK}Plant single trees by dragging over the landscape.
STR_TREES_MODE_FOREST_SM_BUTTON :{BLACK}Grove
STR_TREES_MODE_FOREST_SM_TOOLTIP :{BLACK}Plant small forests by dragging over the landscape.
STR_TREES_MODE_FOREST_LG_BUTTON :{BLACK}Forest
STR_TREES_MODE_FOREST_LG_TOOLTIP :{BLACK}Plant large forests by dragging over the landscape.
# Land generation window (SE)
STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION :{WHITE}Land Generation
@ -2562,12 +2600,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
@ -2588,6 +2632,7 @@ STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP :{BLACK}Select t
# Land area window
STR_LAND_AREA_INFORMATION_CAPTION :{WHITE}Land Area Information
STR_LAND_AREA_INFORMATION_LOCATION_TOOLTIP :{BLACK}Center the main view on tile location. Ctrl+Click opens a new viewport on tile location
STR_LAND_AREA_INFORMATION_COST_TO_CLEAR_N_A :{BLACK}Cost to clear: {LTBLUE}N/A
STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Cost to clear: {RED}{CURRENCY_LONG}
STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Revenue when cleared: {LTBLUE}{CURRENCY_LONG}
@ -3057,6 +3102,7 @@ STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Toggle m
# Sign window
STR_EDIT_SIGN_CAPTION :{WHITE}Edit sign text
STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Center the main view on sign location. Ctrl+Click opens a new viewport on sign location
STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Go to next sign
STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Go to previous sign
@ -3140,10 +3186,10 @@ STR_GOALS_COMPANY_TITLE :{BLACK}Company
STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on goal to center main view on industry/town/tile. Ctrl+Click opens a new viewport on industry/town/tile location
# Goal question window
STR_GOAL_QUESTION_CAPTION_QUESTION :Question
STR_GOAL_QUESTION_CAPTION_INFORMATION :Information
STR_GOAL_QUESTION_CAPTION_WARNING :Warning
STR_GOAL_QUESTION_CAPTION_ERROR :Error
STR_GOAL_QUESTION_CAPTION_QUESTION :{BLACK}Question
STR_GOAL_QUESTION_CAPTION_INFORMATION :{BLACK}Information
STR_GOAL_QUESTION_CAPTION_WARNING :{BLACK}Warning
STR_GOAL_QUESTION_CAPTION_ERROR :{YELLOW}Error
############ Start of Goal Question button list
STR_GOAL_QUESTION_BUTTON_CANCEL :Cancel
@ -3334,6 +3380,7 @@ STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS :{BLACK}Rebuild
STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON :{BLACK}Details
STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP :{BLACK}View detailed infrastructure counts
STR_COMPANY_VIEW_GIVE_MONEY_BUTTON :{BLACK}Give money
STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP :{BLACK}Give money to this company
STR_COMPANY_VIEW_NEW_FACE_BUTTON :{BLACK}New Face
STR_COMPANY_VIEW_NEW_FACE_TOOLTIP :{BLACK}Select new face for president
@ -3373,6 +3420,10 @@ STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Industri
STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- None -
STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY}
STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Industry names - click on name to center main view on industry. Ctrl+Click opens a new viewport on industry location
STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Accepted cargo: {SILVER}{STRING}
STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Produced cargo: {SILVER}{STRING}
STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :All cargo types
STR_INDUSTRY_DIRECTORY_FILTER_NONE :None
# Industry view
STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY}
@ -3703,6 +3754,10 @@ STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make aut
# Vehicle view
STR_VEHICLE_VIEW_CAPTION :{WHITE}{VEHICLE}
STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP :{BLACK}Center main view on train's location. Double click will follow train in main view. Ctrl+Click opens a new viewport on train's location
STR_VEHICLE_VIEW_ROAD_VEHICLE_CENTER_TOOLTIP :{BLACK}Center main view on vehicle's location. Double click will follow vehicle in main view. Ctrl+Click opens a new viewport on vehicle's location
STR_VEHICLE_VIEW_SHIP_CENTER_TOOLTIP :{BLACK}Center main view on ship's location. Double click will follow ship in main view. Ctrl+Click opens a new viewport on ship's location
STR_VEHICLE_VIEW_AIRCRAFT_CENTER_TOOLTIP :{BLACK}Center main view on aircraft's location. Double click will follow aircraft in main view. Ctrl+Click opens a new viewport on aircraft's location
STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send train to depot. Ctrl+Click will only service
STR_VEHICLE_VIEW_ROAD_VEHICLE_SEND_TO_DEPOT_TOOLTIP :{BLACK}Send vehicle to depot. Ctrl+Click will only service
@ -3734,7 +3789,12 @@ STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Show roa
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Show ship details
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Show aircraft details
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Current train action - click to stop/start train
STR_VEHICLE_VIEW_ROAD_VEHICLE_STATUS_START_STOP_TOOLTIP :{BLACK}Current vehicle action - click to stop/start vehicle
STR_VEHICLE_VIEW_SHIP_STATE_STATUS_STOP_TOOLTIP :{BLACK}Current ship action - click to stop/start ship
STR_VEHICLE_VIEW_AIRCRAFT_STATUS_START_STOP_TOOLTIP :{BLACK}Current aircraft action - click to stop/start aircraft
STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP :{BLACK}Center main view on order destination. Ctrl+Click opens a new viewport on the order destination's location
# Messages in the start stop button in the vehicle view
STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Loading / Unloading
@ -4206,6 +4266,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Savegame is mad
STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :File not readable
STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :File not writable
STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :Data integrity check failed
STR_GAME_SAVELOAD_ERROR_PATCHPACK :Savegame is made with a modified version
STR_GAME_SAVELOAD_NOT_AVAILABLE :<not available>
STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}Game was saved in version without streetcar support. All streetcars have been removed
@ -4286,6 +4347,7 @@ STR_ERROR_LOAN_ALREADY_REPAYED :{WHITE}... no l
STR_ERROR_CURRENCY_REQUIRED :{WHITE}... {CURRENCY_LONG} required
STR_ERROR_CAN_T_REPAY_LOAN :{WHITE}Can't repay loan...
STR_ERROR_INSUFFICIENT_FUNDS :{WHITE}Can't give away money that is loaned from the bank...
STR_ERROR_CAN_T_GIVE_MONEY :{WHITE}Can't give away money to this company...
STR_ERROR_CAN_T_BUY_COMPANY :{WHITE}Can't buy company...
STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS :{WHITE}Can't build company headquarters...
STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS :{WHITE}Can't buy 25% share in this company...
@ -4412,6 +4474,8 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Wrong depot typ
STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}{VEHICLE} is too long after replacement
STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}No autoreplace/renew rules applied
STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(money limit)
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}New vehicle can't carry {STRING}
STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT :{WHITE}New vehicle can't do refit in order {NUM}
# Rail construction errors
STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Impossible track combination
@ -4698,10 +4762,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sugar Mine
##id 0x6000
STR_SV_EMPTY :
STR_SV_UNNAMED :Unnamed
STR_SV_TRAIN_NAME :Train {COMMA}
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle {COMMA}
STR_SV_SHIP_NAME :Ship {COMMA}
STR_SV_AIRCRAFT_NAME :Aircraft {COMMA}
STR_SV_TRAIN_NAME :Train #{COMMA}
STR_SV_ROAD_VEHICLE_NAME :Road Vehicle #{COMMA}
STR_SV_SHIP_NAME :Ship #{COMMA}
STR_SV_AIRCRAFT_NAME :Aircraft #{COMMA}
STR_SV_STNAME :{STRING}
STR_SV_STNAME_NORTH :{STRING} North
@ -5003,6 +5067,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Buoy
STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA}
STR_FORMAT_COMPANY_NUM :(Company {COMMA})
STR_FORMAT_GROUP_NAME :Group {COMMA}
STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA}
STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING}
STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint
STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA}

@ -1327,6 +1327,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Nowy dolar tajw
STR_GAME_OPTIONS_CURRENCY_CNY :Juan chiński (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Dolar hongkoński (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Rupia Indyjska (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :Rupia Indonezyjska (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Jazda po lewej

@ -46,15 +46,11 @@
#endif
static struct {
HWND main_wnd; ///< Handle to system window.
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
void *buffer_bits; ///< Internal rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
int width; ///< Width in pixels of our display surface.
int height; ///< Height in pixels of our display surface.
int width_org; ///< Original monitor resolution width, before we changed it.
int height_org; ///< Original monitor resolution height, before we changed it.
bool fullscreen; ///< Whether to use (true) fullscreen mode.
bool has_focus; ///< Does our window have system focus?
bool running; ///< Is the main loop running?
} _wnd;
@ -76,44 +72,7 @@ static Palette _local_palette;
/** Region of the screen that needs redrawing. */
static Rect _dirty_rect;
static void MakePalette()
{
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY));
pal->palVersion = 0x300;
pal->palNumEntries = 256;
for (uint i = 0; i != 256; i++) {
pal->palPalEntry[i].peRed = _local_palette.palette[i].r;
pal->palPalEntry[i].peGreen = _local_palette.palette[i].g;
pal->palPalEntry[i].peBlue = _local_palette.palette[i].b;
pal->palPalEntry[i].peFlags = 0;
}
_wnd.gdi_palette = CreatePalette(pal);
if (_wnd.gdi_palette == nullptr) usererror("CreatePalette failed!\n");
}
static void UpdatePalette(HDC dc, uint start, uint count)
{
RGBQUAD rgb[256];
uint i;
for (i = 0; i != count; i++) {
rgb[i].rgbRed = _local_palette.palette[start + i].r;
rgb[i].rgbGreen = _local_palette.palette[start + i].g;
rgb[i].rgbBlue = _local_palette.palette[start + i].b;
rgb[i].rgbReserved = 0;
}
SetDIBColorTable(dc, start, count, rgb);
}
bool VideoDriver_Win32::ClaimMousePointer()
bool VideoDriver_Win32Base::ClaimMousePointer()
{
MyShowCursor(false, true);
return true;
@ -187,65 +146,28 @@ static uint MapWindowsKey(uint sym)
return key;
}
static bool AllocateDibSection(int w, int h, bool force = false);
static void ClientSizeChanged(int w, int h)
/** Colour depth to use for fullscreen display modes. */
uint8 VideoDriver_Win32Base::GetFullscreenBpp()
{
/* allocate new dib section of the new size */
if (AllocateDibSection(w, h)) {
/* mark all palette colours dirty */
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
BlitterFactory::GetCurrentBlitter()->PostResize();
GameSizeChanged();
}
}
#ifdef _DEBUG
/* Keep this function here..
* It allows you to redraw the screen from within the MSVC debugger */
int RedrawScreenDebug()
{
HDC dc, dc2;
static int _fooctr;
HBITMAP old_bmp;
HPALETTE old_palette;
UpdateWindows();
dc = GetDC(_wnd.main_wnd);
dc2 = CreateCompatibleDC(dc);
old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
SelectPalette(dc, old_palette, TRUE);
SelectObject(dc2, old_bmp);
DeleteDC(dc2);
ReleaseDC(_wnd.main_wnd, dc);
return _fooctr++;
/* Check modes for the relevant fullscreen bpp */
return _support8bpp != S8BPP_HARDWARE ? 32 : BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
}
#endif
/**
* Instantiate a new window.
* @param full_screen Whether to make a full screen window or not.
* @return True if the window could be created.
*/
bool VideoDriver_Win32::MakeWindow(bool full_screen)
bool VideoDriver_Win32Base::MakeWindow(bool full_screen)
{
/* full_screen is whether the new window should be fullscreen,
* _wnd.fullscreen is whether the current window is. */
_fullscreen = full_screen;
/* recreate window? */
if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
DestroyWindow(_wnd.main_wnd);
_wnd.main_wnd = 0;
if ((full_screen || this->fullscreen) && this->main_wnd) {
DestroyWindow(this->main_wnd);
this->main_wnd = 0;
}
if (full_screen) {
@ -257,13 +179,12 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT;
settings.dmBitsPerPel = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
settings.dmBitsPerPel = this->GetFullscreenBpp();
settings.dmPelsWidth = _wnd.width_org;
settings.dmPelsHeight = _wnd.height_org;
/* Check for 8 bpp support. */
if (settings.dmBitsPerPel == 8 &&
(_support8bpp != S8BPP_HARDWARE || ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL)) {
if (settings.dmBitsPerPel == 8 && ChangeDisplaySettings(&settings, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) {
settings.dmBitsPerPel = 32;
}
@ -282,7 +203,7 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
this->MakeWindow(false); // don't care about the result
return false; // the request failed
}
} else if (_wnd.fullscreen) {
} else if (this->fullscreen) {
/* restore display? */
ChangeDisplaySettings(nullptr, 0);
/* restore the resolution */
@ -296,8 +217,8 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
int w, h;
showstyle = SW_SHOWNORMAL;
_wnd.fullscreen = full_screen;
if (_wnd.fullscreen) {
this->fullscreen = full_screen;
if (this->fullscreen) {
style = WS_POPUP;
SetRect(&r, 0, 0, _wnd.width_org, _wnd.height_org);
} else {
@ -311,8 +232,8 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
w = r.right - r.left;
h = r.bottom - r.top;
if (_wnd.main_wnd != nullptr) {
if (!_window_maximize) SetWindowPos(_wnd.main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
if (this->main_wnd != nullptr) {
if (!_window_maximize) SetWindowPos(this->main_wnd, 0, 0, 0, w, h, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
} else {
int x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
int y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
@ -320,92 +241,19 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
char window_title[64];
seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision);
_wnd.main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), 0);
if (_wnd.main_wnd == nullptr) usererror("CreateWindow failed");
ShowWindow(_wnd.main_wnd, showstyle);
this->main_wnd = CreateWindow(_T("OTTD"), MB_TO_WIDE(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this);
if (this->main_wnd == nullptr) usererror("CreateWindow failed");
ShowWindow(this->main_wnd, showstyle);
}
}
BlitterFactory::GetCurrentBlitter()->PostResize();
GameSizeChanged(); // invalidate all windows, force redraw
return true; // the request succeeded
}
/** Do palette animation and blit to the window. */
void VideoDriver_Win32::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
if (IsEmptyRect(_dirty_rect)) return;
/* Convert update region from logical to device coordinates. */
POINT pt = {0, 0};
ClientToScreen(_wnd.main_wnd, &pt);
RECT r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right, _dirty_rect.bottom };
OffsetRect(&r, pt.x, pt.y);
/* Create a device context that is clipped to the region we need to draw.
* GetDCEx 'consumes' the update region, so we may not destroy it ourself. */
HRGN rgn = CreateRectRgnIndirect(&r);
HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN);
HDC dc2 = CreateCompatibleDC(dc);
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
if (_cur_palette.count_dirty != 0) {
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
switch (blitter->UsePaletteAnimation()) {
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty);
break;
case Blitter::PALETTE_ANIMATION_BLITTER:
blitter->PaletteAnimate(_local_palette);
break;
case Blitter::PALETTE_ANIMATION_NONE:
break;
default:
NOT_REACHED();
}
_cur_palette.count_dirty = 0;
}
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
SelectPalette(dc, old_palette, TRUE);
SelectObject(dc2, old_bmp);
DeleteDC(dc2);
ReleaseDC(_wnd.main_wnd, dc);
_dirty_rect = {};
}
void VideoDriver_Win32::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
_draw_signal->notify_one();
/* Now wait for the first thing to draw! */
_draw_signal->wait(*_draw_mutex);
while (_draw_continue) {
this->Paint();
/* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */
GdiFlush();
_draw_signal->wait(*_draw_mutex);
}
GameSizeChanged();
return true;
}
/* static */ void VideoDriver_Win32::PaintThreadThunk(VideoDriver_Win32 *drv)
/* static */ void VideoDriver_Win32Base::PaintThreadThunk(VideoDriver_Win32Base *drv)
{
drv->PaintThread();
}
@ -609,13 +457,16 @@ static void CancelIMEComposition(HWND hwnd)
HandleTextInput(nullptr, true);
}
static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static uint32 keycode = 0;
static bool console = false;
VideoDriver_Win32Base *video_driver = (VideoDriver_Win32Base *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch (msg) {
case WM_CREATE:
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);
_cursor.in_window = false; // Win32 has mouse tracking.
SetCompositionPos(hwnd);
_imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
@ -624,7 +475,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
case WM_PAINT: {
RECT r;
GetUpdateRect(hwnd, &r, FALSE);
static_cast<VideoDriver_Win32 *>(VideoDriver::GetInstance())->MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
video_driver->MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
ValidateRect(hwnd, nullptr);
return 0;
@ -634,18 +485,9 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
if ((HWND)wParam == hwnd) return 0;
FALLTHROUGH;
case WM_QUERYNEWPALETTE: {
HDC hDC = GetWindowDC(hwnd);
HPALETTE hOldPalette = SelectPalette(hDC, _wnd.gdi_palette, FALSE);
UINT nChanged = RealizePalette(hDC);
SelectPalette(hDC, hOldPalette, TRUE);
ReleaseDC(hwnd, hDC);
if (nChanged != 0) {
static_cast<VideoDriver_Win32 *>(VideoDriver::GetInstance())->MakeDirty(0, 0, _screen.width, _screen.height);
}
case WM_QUERYNEWPALETTE:
video_driver->PaletteChanged(hwnd);
return 0;
}
case WM_CLOSE:
HandleExitGameRequest();
@ -829,7 +671,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
switch (wParam) {
case VK_RETURN:
case 'F': // Full Screen on ALT + ENTER/F
ToggleFullScreen(!_wnd.fullscreen);
ToggleFullScreen(!video_driver->fullscreen);
return 0;
case VK_MENU: // Just ALT
@ -851,7 +693,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
* switched to fullscreen from a maximized state */
_window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen));
if (_window_maximize || _fullscreen) _bck_resolution = _cur_resolution;
ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
video_driver->ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
}
return 0;
@ -948,11 +790,11 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
bool active = (LOWORD(wParam) != WA_INACTIVE);
bool minimized = (HIWORD(wParam) != 0);
if (_wnd.fullscreen) {
if (video_driver->fullscreen) {
if (active && minimized) {
/* Restore the game window */
ShowWindow(hwnd, SW_RESTORE);
static_cast<VideoDriver_Win32 *>(VideoDriver::GetInstance())->MakeWindow(true);
video_driver->MakeWindow(true);
} else if (!active && !minimized) {
/* Minimise the window and restore desktop */
ShowWindow(hwnd, SW_MINIMIZE);
@ -990,43 +832,6 @@ static void RegisterWndClass()
if (!RegisterClass(&wnd)) usererror("RegisterClass failed");
}
static bool AllocateDibSection(int w, int h, bool force)
{
BITMAPINFO *bi;
HDC dc;
uint bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
w = std::max(w, 64);
h = std::max(h, 64);
if (!force && w == _screen.width && h == _screen.height) return false;
bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = _wnd.width = w;
bi->bmiHeader.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = BI_RGB;
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
dc = GetDC(0);
_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, nullptr, 0);
if (_wnd.dib_sect == nullptr) usererror("CreateDIBSection failed");
ReleaseDC(0, dc);
_screen.width = w;
_screen.pitch = (bpp == 8) ? Align(w, 4) : w;
_screen.height = h;
_screen.dst_ptr = _wnd.buffer_bits;
return true;
}
static const Dimension default_resolutions[] = {
{ 640, 480 },
{ 800, 600 },
@ -1041,20 +846,12 @@ static const Dimension default_resolutions[] = {
{ 1920, 1200 }
};
static void FindResolutions()
static void FindResolutions(uint8 bpp)
{
uint i;
DEVMODEA dm;
/* Check modes for the relevant fullscreen bpp */
uint bpp = _support8bpp != S8BPP_HARDWARE ? 32 : BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
_resolutions.clear();
/* XXX - EnumDisplaySettingsW crashes with unicows.dll on Windows95
* Doesn't really matter since we don't pass a string anyways, but still
* a letdown */
for (i = 0; EnumDisplaySettingsA(nullptr, i, &dm) != 0; i++) {
DEVMODE dm;
for (uint i = 0; EnumDisplaySettings(nullptr, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel != bpp || dm.dmPelsWidth < 640 || dm.dmPelsHeight < 480) continue;
if (std::find(_resolutions.begin(), _resolutions.end(), Dimension(dm.dmPelsWidth, dm.dmPelsHeight)) != _resolutions.end()) continue;
_resolutions.emplace_back(dm.dmPelsWidth, dm.dmPelsHeight);
@ -1068,55 +865,36 @@ static void FindResolutions()
SortResolutions();
}
static FVideoDriver_Win32 iFVideoDriver_Win32;
const char *VideoDriver_Win32::Start(const StringList &parm)
void VideoDriver_Win32Base::Initialize()
{
if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
this->UpdateAutoResolution();
memset(&_wnd, 0, sizeof(_wnd));
RegisterWndClass();
MakePalette();
FindResolutions();
DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height);
FindResolutions(this->GetFullscreenBpp());
/* fullscreen uses those */
_wnd.width_org = _cur_resolution.width;
_wnd.height_org = _cur_resolution.height;
_wnd.width = _wnd.width_org = _cur_resolution.width;
_wnd.height = _wnd.height_org = _cur_resolution.height;
AllocateDibSection(_cur_resolution.width, _cur_resolution.height);
this->MakeWindow(_fullscreen);
MarkWholeScreenDirty();
_draw_threaded = !GetDriverParamBool(parm, "no_threads") && !GetDriverParamBool(parm, "no_thread") && std::thread::hardware_concurrency() > 1;
return nullptr;
DEBUG(driver, 2, "Resolution for display: %ux%u", _cur_resolution.width, _cur_resolution.height);
}
void VideoDriver_Win32::Stop()
void VideoDriver_Win32Base::Stop()
{
DeleteObject(_wnd.gdi_palette);
DeleteObject(_wnd.dib_sect);
DestroyWindow(_wnd.main_wnd);
DestroyWindow(this->main_wnd);
if (_wnd.fullscreen) ChangeDisplaySettings(nullptr, 0);
if (this->fullscreen) ChangeDisplaySettings(nullptr, 0);
MyShowCursor(true);
}
void VideoDriver_Win32::MakeDirty(int left, int top, int width, int height)
void VideoDriver_Win32Base::MakeDirty(int left, int top, int width, int height)
{
Rect r = {left, top, left + width, top + height};
_dirty_rect = BoundingRect(_dirty_rect, r);
}
void VideoDriver_Win32::CheckPaletteAnim()
void VideoDriver_Win32Base::CheckPaletteAnim()
{
if (_cur_palette.count_dirty == 0) return;
@ -1124,7 +902,7 @@ void VideoDriver_Win32::CheckPaletteAnim()
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
void VideoDriver_Win32::InputLoop()
void VideoDriver_Win32Base::InputLoop()
{
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
@ -1160,7 +938,7 @@ void VideoDriver_Win32::InputLoop()
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
void VideoDriver_Win32::MainLoop()
void VideoDriver_Win32Base::MainLoop()
{
MSG mesg;
@ -1180,7 +958,7 @@ void VideoDriver_Win32::MainLoop()
this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32::PaintThreadThunk, this);
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32Base::PaintThreadThunk, this);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
@ -1239,12 +1017,27 @@ void VideoDriver_Win32::MainLoop()
}
}
bool VideoDriver_Win32::ChangeResolution(int w, int h)
void VideoDriver_Win32Base::ClientSizeChanged(int w, int h)
{
/* Allocate backing store of the new size. */
if (this->AllocateBackingStore(w, h)) {
/* Mark all palette colours dirty. */
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
BlitterFactory::GetCurrentBlitter()->PostResize();
GameSizeChanged();
}
}
bool VideoDriver_Win32Base::ChangeResolution(int w, int h)
{
std::unique_lock<std::recursive_mutex> lock;
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
if (_window_maximize) ShowWindow(_wnd.main_wnd, SW_SHOWNORMAL);
if (_window_maximize) ShowWindow(this->main_wnd, SW_SHOWNORMAL);
_wnd.width = _wnd.width_org = w;
_wnd.height = _wnd.height_org = h;
@ -1252,7 +1045,7 @@ bool VideoDriver_Win32::ChangeResolution(int w, int h)
return this->MakeWindow(_fullscreen); // _wnd.fullscreen screws up ingame resolution switching
}
bool VideoDriver_Win32::ToggleFullscreen(bool full_screen)
bool VideoDriver_Win32Base::ToggleFullscreen(bool full_screen)
{
std::unique_lock<std::recursive_mutex> lock;
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
@ -1260,38 +1053,32 @@ bool VideoDriver_Win32::ToggleFullscreen(bool full_screen)
return this->MakeWindow(full_screen);
}
bool VideoDriver_Win32::AfterBlitterChange()
{
assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0);
return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
}
void VideoDriver_Win32::AcquireBlitterLock()
void VideoDriver_Win32Base::AcquireBlitterLock()
{
if (_draw_mutex != nullptr) _draw_mutex->lock();
}
void VideoDriver_Win32::ReleaseBlitterLock()
void VideoDriver_Win32Base::ReleaseBlitterLock()
{
if (_draw_mutex != nullptr) _draw_mutex->unlock();
}
void VideoDriver_Win32::EditBoxLostFocus()
void VideoDriver_Win32Base::EditBoxLostFocus()
{
std::unique_lock<std::recursive_mutex> lock;
if (_draw_mutex != nullptr) lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
CancelIMEComposition(_wnd.main_wnd);
SetCompositionPos(_wnd.main_wnd);
SetCandidatePos(_wnd.main_wnd);
CancelIMEComposition(this->main_wnd);
SetCompositionPos(this->main_wnd);
SetCandidatePos(this->main_wnd);
}
Dimension VideoDriver_Win32::GetScreenSize() const
Dimension VideoDriver_Win32Base::GetScreenSize() const
{
return { static_cast<uint>(GetSystemMetrics(SM_CXSCREEN)), static_cast<uint>(GetSystemMetrics(SM_CYSCREEN)) };
}
float VideoDriver_Win32::GetDPIScale()
float VideoDriver_Win32Base::GetDPIScale()
{
typedef UINT (WINAPI *PFNGETDPIFORWINDOW)(HWND hwnd);
typedef UINT (WINAPI *PFNGETDPIFORSYSTEM)(VOID);
@ -1312,14 +1099,14 @@ float VideoDriver_Win32::GetDPIScale()
UINT cur_dpi = 0;
if (cur_dpi == 0 && _GetDpiForWindow != nullptr && _wnd.main_wnd != nullptr) {
if (cur_dpi == 0 && _GetDpiForWindow != nullptr && this->main_wnd != nullptr) {
/* Per window DPI is supported since Windows 10 Ver 1607. */
cur_dpi = _GetDpiForWindow(_wnd.main_wnd);
cur_dpi = _GetDpiForWindow(this->main_wnd);
}
if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && _wnd.main_wnd != nullptr) {
if (cur_dpi == 0 && _GetDpiForMonitor != nullptr && this->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))) {
if (SUCCEEDED(_GetDpiForMonitor(MonitorFromWindow(this->main_wnd, MONITOR_DEFAULTTOPRIMARY), 0 /* MDT_EFFECTIVE_DPI */, &dpiX, &dpiY))) {
cur_dpi = dpiX; // X and Y are always identical.
}
}
@ -1331,13 +1118,211 @@ float VideoDriver_Win32::GetDPIScale()
return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96.
}
bool VideoDriver_Win32::LockVideoBuffer()
bool VideoDriver_Win32Base::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
return true;
}
void VideoDriver_Win32::UnlockVideoBuffer()
void VideoDriver_Win32Base::UnlockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.unlock();
}
static FVideoDriver_Win32GDI iFVideoDriver_Win32GDI;
const char *VideoDriver_Win32GDI::Start(const StringList &param)
{
if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported";
this->Initialize();
this->MakePalette();
this->AllocateBackingStore(_cur_resolution.width, _cur_resolution.height);
this->MakeWindow(_fullscreen);
MarkWholeScreenDirty();
_draw_threaded = !GetDriverParam(param, "no_threads") && !GetDriverParam(param, "no_thread") && std::thread::hardware_concurrency() > 1;
return nullptr;
}
void VideoDriver_Win32GDI::Stop()
{
DeleteObject(this->gdi_palette);
DeleteObject(this->dib_sect);
this->VideoDriver_Win32Base::Stop();
}
bool VideoDriver_Win32GDI::AllocateBackingStore(int w, int h, bool force)
{
uint bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
w = std::max(w, 64);
h = std::max(h, 64);
if (!force && w == _screen.width && h == _screen.height) return false;
BITMAPINFO *bi = (BITMAPINFO *)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = _wnd.width = w;
bi->bmiHeader.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = BI_RGB;
if (this->dib_sect) DeleteObject(this->dib_sect);
HDC dc = GetDC(0);
this->dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID **)&_wnd.buffer_bits, nullptr, 0);
if (this->dib_sect == nullptr) usererror("CreateDIBSection failed");
ReleaseDC(0, dc);
_screen.width = w;
_screen.pitch = (bpp == 8) ? Align(w, 4) : w;
_screen.height = h;
_screen.dst_ptr = _wnd.buffer_bits;
return true;
}
bool VideoDriver_Win32GDI::AfterBlitterChange()
{
assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0);
return this->AllocateBackingStore(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
}
void VideoDriver_Win32GDI::MakePalette()
{
_cur_palette.first_dirty = 0;
_cur_palette.count_dirty = 256;
_local_palette = _cur_palette;
LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY));
pal->palVersion = 0x300;
pal->palNumEntries = 256;
for (uint i = 0; i != 256; i++) {
pal->palPalEntry[i].peRed = _local_palette.palette[i].r;
pal->palPalEntry[i].peGreen = _local_palette.palette[i].g;
pal->palPalEntry[i].peBlue = _local_palette.palette[i].b;
pal->palPalEntry[i].peFlags = 0;
}
this->gdi_palette = CreatePalette(pal);
if (this->gdi_palette == nullptr) usererror("CreatePalette failed!\n");
}
void VideoDriver_Win32GDI::UpdatePalette(HDC dc, uint start, uint count)
{
RGBQUAD rgb[256];
for (uint i = 0; i != count; i++) {
rgb[i].rgbRed = _local_palette.palette[start + i].r;
rgb[i].rgbGreen = _local_palette.palette[start + i].g;
rgb[i].rgbBlue = _local_palette.palette[start + i].b;
rgb[i].rgbReserved = 0;
}
SetDIBColorTable(dc, start, count, rgb);
}
void VideoDriver_Win32GDI::PaletteChanged(HWND hWnd)
{
HDC hDC = GetWindowDC(hWnd);
HPALETTE hOldPalette = SelectPalette(hDC, this->gdi_palette, FALSE);
UINT nChanged = RealizePalette(hDC);
SelectPalette(hDC, hOldPalette, TRUE);
ReleaseDC(hWnd, hDC);
if (nChanged != 0) this->MakeDirty(0, 0, _screen.width, _screen.height);
}
void VideoDriver_Win32GDI::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
if (IsEmptyRect(_dirty_rect)) return;
HDC dc = GetDC(this->main_wnd);
HDC dc2 = CreateCompatibleDC(dc);
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->dib_sect);
HPALETTE old_palette = SelectPalette(dc, this->gdi_palette, FALSE);
if (_cur_palette.count_dirty != 0) {
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
switch (blitter->UsePaletteAnimation()) {
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
this->UpdatePalette(dc2, _local_palette.first_dirty, _local_palette.count_dirty);
break;
case Blitter::PALETTE_ANIMATION_BLITTER:
blitter->PaletteAnimate(_local_palette);
break;
case Blitter::PALETTE_ANIMATION_NONE:
break;
default:
NOT_REACHED();
}
_cur_palette.count_dirty = 0;
}
BitBlt(dc, 0, 0, _wnd.width, _wnd.height, dc2, 0, 0, SRCCOPY);
SelectPalette(dc, old_palette, TRUE);
SelectObject(dc2, old_bmp);
DeleteDC(dc2);
ReleaseDC(this->main_wnd, dc);
_dirty_rect = {};
}
void VideoDriver_Win32GDI::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
_draw_signal->notify_one();
/* Now wait for the first thing to draw! */
_draw_signal->wait(*_draw_mutex);
while (_draw_continue) {
this->Paint();
/* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */
GdiFlush();
_draw_signal->wait(*_draw_mutex);
}
}
#ifdef _DEBUG
/* Keep this function here..
* It allows you to redraw the screen from within the MSVC debugger */
/* static */ int VideoDriver_Win32GDI::RedrawScreenDebug()
{
static int _fooctr;
_screen.dst_ptr = _wnd.buffer_bits;
UpdateWindows();
VideoDriver_Win32GDI *drv = static_cast<VideoDriver_Win32GDI *>(VideoDriver::GetInstance());
drv->Paint();
GdiFlush();
return _fooctr++;
}
#endif

@ -12,10 +12,10 @@
#include "video_driver.hpp"
/** The video driver for windows. */
class VideoDriver_Win32 : public VideoDriver {
/** Base class for Windows video drivers. */
class VideoDriver_Win32Base : public VideoDriver {
public:
const char *Start(const StringList &param) override;
VideoDriver_Win32Base() : main_wnd(nullptr), fullscreen(false) {}
void Stop() override;
@ -27,8 +27,6 @@ public:
bool ToggleFullscreen(bool fullscreen) override;
bool AfterBlitterChange() override;
void AcquireBlitterLock() override;
void ReleaseBlitterLock() override;
@ -37,31 +35,71 @@ public:
void EditBoxLostFocus() override;
const char *GetName() const override { return "win32"; }
bool MakeWindow(bool full_screen);
protected:
HWND main_wnd; ///< Handle to system window.
bool fullscreen; ///< Whether to use (true) fullscreen mode.
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
bool LockVideoBuffer() override;
void UnlockVideoBuffer() override;
void Paint() override;
void PaintThread() override;
void CheckPaletteAnim() override;
void Initialize();
bool MakeWindow(bool full_screen);
virtual uint8 GetFullscreenBpp();
/** (Re-)create the backing store. */
virtual bool AllocateBackingStore(int w, int h, bool force = false) = 0;
/** Palette of the window has changed. */
virtual void PaletteChanged(HWND hWnd) = 0;
private:
std::unique_lock<std::recursive_mutex> draw_lock;
static void PaintThreadThunk(VideoDriver_Win32 *drv);
void ClientSizeChanged(int w, int h);
static void PaintThreadThunk(VideoDriver_Win32Base *drv);
friend LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
/** The GDI video driver for windows. */
class VideoDriver_Win32GDI : public VideoDriver_Win32Base {
public:
VideoDriver_Win32GDI() : dib_sect(nullptr), gdi_palette(nullptr) {}
const char *Start(const StringList &param) override;
void Stop() override;
bool AfterBlitterChange() override;
const char *GetName() const override { return "win32"; }
protected:
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
void Paint() override;
void PaintThread() override;
bool AllocateBackingStore(int w, int h, bool force = false) override;
void PaletteChanged(HWND hWnd) override;
void MakePalette();
void UpdatePalette(HDC dc, uint start, uint count);
#ifdef _DEBUG
public:
static int RedrawScreenDebug();
#endif
};
/** The factory for Windows' video driver. */
class FVideoDriver_Win32 : public DriverFactoryBase {
class FVideoDriver_Win32GDI : public DriverFactoryBase {
public:
FVideoDriver_Win32() : DriverFactoryBase(Driver::DT_VIDEO, 10, "win32", "Win32 GDI Video Driver") {}
Driver *CreateInstance() const override { return new VideoDriver_Win32(); }
FVideoDriver_Win32GDI() : DriverFactoryBase(Driver::DT_VIDEO, 10, "win32", "Win32 GDI Video Driver") {}
Driver *CreateInstance() const override { return new VideoDriver_Win32GDI(); }
};
#endif /* VIDEO_WIN32_H */

Loading…
Cancel
Save