diff --git a/CMakeSettings.json b/CMakeSettings.json index 54599ff993e..a744135a5b9 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,34 +1,40 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "variables": [] - }, - { - "name": "x64-Release", - "generator": "Ninja", - "configurationType": "RelWithDebInfo", - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ], - "variables": [ +{ + "configurations": [ { - "name": "CMAKE_BUILD_TYPE", - "value": "RelWithDebInfo", - "type": "STRING" + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "variables": [] + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] + }, + { + "name": "x64-Profiling", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "-DPROFILER_ENABLED=1", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] } - ] - } - ] -} \ No newline at end of file + ] +} diff --git a/COMPILING.txt b/COMPILING.txt index b6ab546bd8b..9341e03520c 100644 --- a/COMPILING.txt +++ b/COMPILING.txt @@ -120,15 +120,14 @@ questions are welcome anytime. 3. Go to File->Open->CMake and select pioneer/CMakeLists.txt -4. If a Release build is desired, select 'Manage Configurations' under the build type, - which will default to x64-Debug and add x64-Release. +4. Select the appropriate build type (x64-Debug or x64-Release) under the configuration + drop down on the main toolbar, located next to the run button. -5. Select the appropriate build type. +5. Build the project (Build->Build All). -6. Buid the project (Build->Build All). - -7. Pioneer can be run and debugged by selecting 'pioneer.exe' on the - 'Select Startup Item' toolbar button, and then clicking run. +6. Pioneer can be run and debugged by selecting 'pioneer.exe' on the + 'Select Startup Item' menu (click the small down arrow on the run button), and then clicking run. + Be sure to select 'pioneer.exe' and not 'pioneer.exe (install)'. 1.5 OS X - Homebrew diff --git a/Changelog.txt b/Changelog.txt index 8e5f6f71d63..c6a2e55b48f 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,19 @@ +October 2020 + * New Features + * Ship-specific atmospheric pressure limits (#4958) + * Make thruster upgrades availabile based on tech level (#4956) + + * Internal Changes + * Optimize body list container in Space.cpp (#4957) + * Use an offscreen buffer as the primary rendering target (#4974) + * Use Reverse-Z depth buffer, drop logZ hack (#4975) + * Add PlanetsGravity processor for GalaxyStats tool (#4971) + * Add theme color display/editor to debug menu (#4979) + + * Fixes + * Fix Flight Log crashes (#4973) + * Update MSVC CMake configuration and instructions (#4980) + September 2020 * New Features * Add external camera interpolation and spring (#4955) @@ -6,6 +22,8 @@ September 2020 * Internal Changes * Cleanup Renderer API to Remove Fixed-Function State (#4947) * Add pigui handlers for PiGuiViews (#4952) + * Collapse PiGui namespaces, load pigui theme from Lua (#4963) + * Clean up Lua PiGui code, split into multiple modules (#4964) * Fixes * Show the ship's translated name in savegame stats (#4953) diff --git a/data/lang/core/bg.json b/data/lang/core/bg.json index 5c1ea56a76e..83ecd07252d 100644 --- a/data/lang/core/bg.json +++ b/data/lang/core/bg.json @@ -5,7 +5,7 @@ }, "ALERT_CANCELLED": { "description": "", - "message": "Alert cancelled." + "message": "Сигналът за тревога е отменен." }, "ALLEGIANCE": { "description": "", @@ -17,15 +17,15 @@ }, "AND_HIGHLY_COMPLEX_ECOSYSTEM": { "description": "", - "message": "\" and a highly complex ecosystem.\"" + "message": "\" и изключително сложна екосистема\"" }, "AND_INDIGENOUS_MICROBIAL_LIFE": { "description": "", - "message": "\" and indigenous microbial life.\"" + "message": "\" и локален микробен живот\"" }, "AND_INDIGENOUS_PLANT_LIFE": { "description": "", - "message": "\" and indigenous plant life.\"" + "message": "\" и локален растителен живот\"" }, "ANIMAL_MEAT": { "description": "", @@ -33,11 +33,11 @@ }, "APOAPSIS_DISTANCE": { "description": "", - "message": "Apoapsis distance" + "message": "Разстояние при апоапсидата" }, "AR_ATMOSPHERE": { "description": "", - "message": "\" Argon atmosphere\"" + "message": "\" атмосфера от аргон\"" }, "ASTEROID": { "description": "", @@ -53,35 +53,35 @@ }, "AUTOPILOT_DOCK_WITH_STATION": { "description": "", - "message": "Autopilot: Dock with {target}" + "message": "Автопилот: Скачване с {target}" }, "AUTOPILOT_ENTER_HIGH_ORBIT_AROUND": { "description": "", - "message": "Autopilot: Enter high orbit around {target}" + "message": "Автопилот: Висока орбита около {target}" }, "AUTOPILOT_ENTER_LOW_ORBIT_AROUND": { "description": "", - "message": "Autopilot: Enter low orbit around {target}" + "message": "Автопилот: Ниска орбита около {target}" }, "AUTOPILOT_ENTER_MEDIUM_ORBIT_AROUND": { "description": "", - "message": "Autopilot: Enter medium orbit around {target}" + "message": "Автопилот: Средна орбита около {target}" }, "AUTOPILOT_FLY_TO_VICINITY_OF": { "description": "", - "message": "Autopilot: Fly to vicinity of {target}" + "message": "Автопилот: Полет към {target}" }, "AUTOPILOT_ON": { "description": "", - "message": "Автопилот включен" + "message": "Автопилотът е включен" }, "AXIAL_TILT": { "description": "", - "message": "Axial tilt" + "message": "Наклон на оста" }, "A_FEW_THOUSAND": { "description": "regarding population", - "message": "Only a few thousand" + "message": "Само няколко хиляди" }, "BATTLE_WEAPONS": { "description": "", @@ -89,7 +89,7 @@ }, "BINARY_SYSTEM": { "description": "", - "message": "Binary system" + "message": "Двойна система" }, "BODIES": { "description": "space bodies", @@ -101,7 +101,7 @@ }, "BROWN_DWARF": { "description": "", - "message": "Brown dwarf sub-stellar object" + "message": "Кафяво джудже" }, "BUTTON": { "description": "", @@ -133,15 +133,15 @@ }, "CANT_SAVE_DEAD_PLAYER": { "description": "", - "message": "Can't save game after the player has died" + "message": "Играта не може да бъде запазена след като играчът е гушнал букета" }, "CANT_SAVE_IN_HYPERSPACE": { "description": "", - "message": "Can't save game while in hyperspace" + "message": "Играта не може да бъде запазена в хиперпространството" }, "CAPITALIST": { "description": "", - "message": "Capitalist" + "message": "Капиталистическа" }, "CARBON_ORE": { "description": "", @@ -153,7 +153,7 @@ }, "CARGO_BAY_LIFE_SUPPORT_LOST": { "description": "", - "message": "Sensors report critical cargo bay life-support conditions." + "message": "Сензорите отчитат критични нива на животоподдържащите системи в товарния отсек." }, "CARGO_N": { "description": "", @@ -161,11 +161,11 @@ }, "CARGO_SCOOP_ACTIVE_1_TONNE_X_COLLECTED": { "description": "", - "message": "Cargo scoop active. Collected 1 tonne of %item." + "message": "Товаросъбирачът е активен. Събран е 1 тон %item." }, "CARGO_SCOOP_ATTEMPTED": { "description": "", - "message": "Cargo scoop attempted. Not enough room in cargo hold." + "message": "Товаросъбирачът не е активен. Корабът е пълен." }, "CENTER": { "description": "", @@ -173,15 +173,15 @@ }, "CH4_ATMOSPHERE": { "description": "", - "message": "\" Methane atmosphere\"" + "message": "\" атмосфера от метан\"" }, "CLEARANCE_ALREADY_GRANTED_BAY_N": { "description": "", - "message": "Clearance already granted. Proceed to docking bay %bay." + "message": "Заявката е вече приета. Започнете скачване с %bay." }, "CLEARANCE_DENIED_NO_BAYS": { "description": "", - "message": "Clearance denied. There are no free docking bays." + "message": "Заявката е отхвърлена. Няма безплатен обяд." }, "CLEARANCE_DENIED_TOO_FAR": { "description": "Shown if player requests docking too far away from station", @@ -189,15 +189,15 @@ }, "CLEARANCE_GRANTED_BAY_N": { "description": "", - "message": "Clearance granted. Proceed to docking bay %bay." + "message": "Заявката е приета. Започнете скачване с %bay." }, "CO2_ATMOSPHERE": { "description": "", - "message": "\" Carbon Dioxide atmosphere\"" + "message": "\" атмосфера от въглероден двуоксид\"" }, "COMMA_HIGHLY_VOLCANIC": { "description": "", - "message": ", highly volcanic" + "message": ", силно вулканична" }, "COMMODITY_NONE": { "description": "When no commodities exist", @@ -205,19 +205,19 @@ }, "COMMODITY_TRADE_ANALYSIS_COMPARE": { "description": "", - "message": "Commodity trade analysis of #ff0%selected_system#fff (selected) against #ff0%current_system#fff (current):" + "message": "Анализ на стоковата търговия на #ff0%selected_system#fff (избрана) и #ff0%current_system#fff (сегашна):" }, "COMMODITY_TRADE_ANALYSIS_SELF": { "description": "", - "message": "Commodity trade analysis of #fff%system#fff" + "message": "Анализ на стоковата търговия на #fff%system#fff" }, "COMMS": { "description": "", - "message": "Comms" + "message": "Съобщения" }, "COMMUNIST": { "description": "", - "message": "Communist" + "message": "Комунизъм" }, "COMPASS_E": { "description": "Abbreviation for compass direction: East", @@ -257,11 +257,11 @@ }, "COMPUTER_HEADING_CONTROL": { "description": "", - "message": "Computer heading control" + "message": "Компютърно управление на посоката" }, "COMPUTER_SPEED_CONTROL": { "description": "", - "message": "Computer speed control" + "message": "Компютърно управление на скоростта" }, "CONSUMER_GOODS": { "description": "", @@ -289,7 +289,7 @@ }, "CO_ATMOSPHERE": { "description": "", - "message": "\" Carbon Monoxide atmosphere\"" + "message": "\" атмосфера от въглероден оксид\"" }, "CTRL": { "description": "Ctrl key on keyboard", @@ -301,7 +301,7 @@ }, "DATE_DUE_N": { "description": "", - "message": "Date due: %date" + "message": "Краен срок: %date" }, "DAY_LENGTH": { "description": "", @@ -313,7 +313,7 @@ }, "DECREASE_SET_SPEED": { "description": "", - "message": "Decrease set speed" + "message": "Намали зададената скорост" }, "DECREASE_TIME_ACCELERATION": { "description": "", @@ -321,7 +321,7 @@ }, "DEMOGRAPHICS": { "description": "", - "message": "Demographics" + "message": "Демография" }, "DESTINATION": { "description": "", @@ -337,23 +337,23 @@ }, "DOCKED": { "description": "", - "message": "Docked" + "message": "Скачен" }, "DOCKING": { "description": "", - "message": "Docking" + "message": "Скачване" }, "DOCKING_CLEARANCE_EXPIRED": { "description": "", - "message": "Docking clearance expired. If you wish to dock you must repeat your request." + "message": "Заявката за скачване е просрочена. Ако искате да извършите скачване, трябва да повторите Вашата заявка." }, "DOWNGRADING_ALERT_STATUS": { "description": "", - "message": "No fire detected for 60 seconds, downgrading alert status." + "message": "В последните 60 секунди не е открит огън, степента на тревога е понижена." }, "DRAW_OUT_RANGE_LABELS": { "description": "", - "message": "Label out-of-range systems" + "message": "Маркирай далечните системи" }, "DRAW_UNINHABITED_LABELS": { "description": "", @@ -361,35 +361,35 @@ }, "DRAW_VERTICAL_LINES": { "description": "", - "message": "Draw vertical lines" + "message": "Начертай вертикални линии" }, "EARTH": { "description": "", - "message": "Земя" + "message": "земни" }, "EARTH_FEDERATION_COLONIAL_RULE": { "description": "", - "message": "Earth Federation Colonial Rule" + "message": "Колониално Управление на Земната Федерация" }, "EARTH_FEDERATION_DEMOCRACY": { "description": "", - "message": "Earth Federation Democracy" + "message": "Земна Федерална Демокрация" }, "ECCENTRICITY": { "description": "", - "message": "Eccentricity" + "message": "Ексцентрицитет" }, "ECONOMIC_INFO": { "description": "", - "message": "Economic info" + "message": "Икономика" }, "ECONOMY_TYPE": { "description": "", - "message": "Economy type:" + "message": "Вид на икономиката:" }, "EQUATORIAL_RADIUS_TO_POLAR_RADIUS_RATIO": { "description": "", - "message": "Equatorial to polar radius ratio" + "message": "Съотношение на екваториалния към полярния радиус" }, "EXACT_MATCH_X": { "description": "", @@ -401,7 +401,7 @@ }, "EXTERNAL_ATMOSPHERIC_PRESSURE": { "description": "", - "message": "External atmospheric pressure" + "message": "Външно атмосферно налягане" }, "EXTERNAL_VIEW": { "description": "", @@ -417,7 +417,7 @@ }, "FIRE_LASER": { "description": "", - "message": "Fire weapon" + "message": "Открий огън" }, "FIRE_MISSILE": { "description": "", @@ -425,11 +425,11 @@ }, "FLYBY_VIEW": { "description": "camera view setting", - "message": "Flyby view" + "message": "Прелитащ изглед" }, "FOLLOWING_SELECTION": { "description": "", - "message": "following selection" + "message": "Следвай селекцията" }, "FRUIT_AND_VEG": { "description": "", @@ -441,7 +441,7 @@ }, "FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED": { "description": "", - "message": "Fuel scoop active. You now have %quantity tonnes of hydrogen." + "message": "Горивосъбирачът е активен. Събрани са %quantity тона водород." }, "GALACTIC_VIEW": { "description": "view galactic map", @@ -453,7 +453,7 @@ }, "GAME_LOAD_CANNOT_OPEN": { "description": "", - "message": "Save file '%filename' could not be found (or the game does not have access to open it)." + "message": "Запазената игра '%filename' не може да бъде намерена (или програмата няма достъп до нея)." }, "GAME_LOAD_CORRUPT": { "description": "", @@ -469,7 +469,7 @@ }, "GAME_SAVE_CANNOT_WRITE": { "description": "", - "message": "This saved game file could not be written because of a system error." + "message": "Запазената игра не може да бъде записана, поради системна грешка." }, "GENERAL_VIEW_CONTROLS": { "description": "", @@ -477,7 +477,7 @@ }, "GOVERNMENT_TYPE": { "description": "", - "message": "Government type:" + "message": "Вид на правителството:" }, "GRAIN": { "description": "like wheat or barley", @@ -485,7 +485,7 @@ }, "GRID_DISPLAY_MODE_TOGGLE": { "description": "Switch show no grid", - "message": "Switch between grid display modes." + "message": "Координатна мрежа" }, "HAND_WEAPONS": { "description": "", @@ -493,7 +493,7 @@ }, "HARD_CAPITALIST": { "description": "", - "message": "Entirely Capitalist - no government welfare provision" + "message": "Изцяло капиталистическа - без намеса от правителството" }, "HAT": { "description": "Hat switch: Is the top button on a joystick", @@ -501,15 +501,15 @@ }, "HEADING_LOCK_ANTINORMAL": { "description": "Autopilot direction (perpendicular, down), relative to plane of orbit", - "message": "Hold {target} anti-normal" + "message": "Задръж {target} анти-нормално" }, "HEADING_LOCK_BACKWARD": { "description": "Autopilot points/holds/faces you retrograde (backwards rel. orbital direction)", - "message": "Hold {target} retrograde" + "message": "Задръж {target} ретроградно" }, "HEADING_LOCK_FORWARD": { "description": "Autopilot points/holds/faces you prograde (tangent to the orbit, i.e. forward), http://wiki.kerbalspaceprogram.com/wiki/Maneuver_node", - "message": "Hold {target} prograde" + "message": "Задръж {target} проградно" }, "HEADING_LOCK_KILLROT": { "description": "", @@ -517,15 +517,15 @@ }, "HEADING_LOCK_NORMAL": { "description": "Autopilot direction (perpendicular, up), relative to plane of orbit. ", - "message": "Hold {target} normal" + "message": "Задръж {target} нормално" }, "HEADING_LOCK_RADIALLY_INWARD": { "description": "Autopilot direction, relative to orbit (face towards planet)", - "message": "Hold {target} radially in" + "message": "Задръж {target} в радиала" }, "HEADING_LOCK_RADIALLY_OUTWARD": { "description": "Autopilot direction, relative to orbit (face away from palent)", - "message": "Hold {target} radially out" + "message": "Задръж {target} извън радиала" }, "HEAVY_INDUSTRY": { "description": "", @@ -533,11 +533,11 @@ }, "HE_ATMOSPHERE": { "description": "", - "message": "\" Helium atmosphere\"" + "message": "\" атмосфера от хелий\"" }, "HIGHLY_VOLCANIC": { "description": "", - "message": "Highly volcanic" + "message": "силно вулканична" }, "HIGH_POPULATION_OUTDOOR_WORLD": { "description": "", @@ -545,11 +545,11 @@ }, "HULL_INTEGRITY": { "description": "", - "message": "Hull integrity" + "message": "Здравина на корпуса" }, "HULL_TEMP": { "description": "", - "message": "Hull temp" + "message": "Температура на корпуса" }, "HYDROGEN": { "description": "", @@ -557,7 +557,7 @@ }, "HYPERSPACE": { "description": "", - "message": "Hyperspace" + "message": "Хиперпространство" }, "HYPERSPACE_ARRIVAL_CLOUD": { "description": "", @@ -573,39 +573,39 @@ }, "HYPERSPACE_JUMP_ABORT": { "description": "Mouse over text for hyperdrive button on ship control panel", - "message": "Disengage Hyperdrive" + "message": "Изключва Хипердвигателя" }, "HYPERSPACE_JUMP_ABORTED": { "description": "", - "message": "Hyperspace jump aborted." + "message": "Хиперпространственият скок е прекъснат." }, "HYPERSPACE_JUMP_DISABLED": { "description": "Mouse over text for hyperdrive button on ship control panel", - "message": "Hyperdrive disabled" + "message": "Хиперсветлинния двигател е изключен" }, "HYPERSPACE_JUMP_ENGAGE": { "description": "Mouse over text for hyperdrive button on ship control panel", - "message": "Engage Hyperdrive" + "message": "Включва Хипердвигателя" }, "HYPERSPACE_JUMP_FORBIDDEN": { "description": "Mouse over text for hyperdrive button on ship control panel", - "message": "Hyperdrive forbidden zone" + "message": "Забранена зона за хипердвигатели" }, "HYPERSPACE_TARGET": { "description": "", - "message": "Hyperspace target" + "message": "Хиперпространствена цел" }, "H_ATMOSPHERE": { "description": "", - "message": "\" Hydrogen atmosphere\"" + "message": "\" атмосфера от водород\"" }, "ICE_WORLD": { "description": "", - "message": "\" ice world\"" + "message": "\" ледена планета\"" }, "ILLEGAL_CURRENT_SYSTEM": { "description": "Short (tooltip) description of commodity (singular) status in the system the player is currently in", - "message": "Illegal (current system):" + "message": "Нелегални (сегашна система):" }, "ILLEGAL_GOODS": { "description": "", @@ -613,7 +613,7 @@ }, "IMPERIAL_RULE": { "description": "", - "message": "Imperial Rule" + "message": "Имперска Власт" }, "INCREASE_RADAR_RANGE": { "description": "", @@ -621,7 +621,7 @@ }, "INCREASE_SET_SPEED": { "description": "", - "message": "Increase set speed" + "message": "Увеличи зададената скорост" }, "INCREASE_TIME_ACCELERATION": { "description": "", @@ -657,11 +657,11 @@ }, "L4L5_DISPLAY_MODE_TOGGLE": { "description": "Either show L4/L5 points or don't", - "message": "Switch between Lagrange L4/L5 point display modes." + "message": "Точки на Лагранж - L4/L5" }, "LANDED": { "description": "", - "message": "Landed" + "message": "Приземен" }, "LANG_NAME": { "description": "The name that native speakers use for this language. This will be used in the language selection screen.", @@ -669,15 +669,15 @@ }, "LARGE": { "description": "regarding terrestrial planet size (mass actually)", - "message": "Large" + "message": "голяма" }, "LARGE_GAS_GIANT": { "description": "", - "message": "Large gas giant" + "message": "голям газов гигант" }, "LASER_FIRE_DETECTED": { "description": "", - "message": "Weapons fire detected." + "message": "Открит е огън." }, "LATITUDE": { "description": "Short for latitude", @@ -693,7 +693,7 @@ }, "LEGAL_CURRENT_SYSTEM": { "description": "Short (tooltip) description of commodity (singular) status in the system the player is currently in", - "message": "Legal (current system):" + "message": "Легални (сегашна система):" }, "LIBERAL_DEMOCRACY": { "description": "", @@ -701,7 +701,7 @@ }, "LIQUID_OXYGEN": { "description": "", - "message": "Liquid Oxygen" + "message": "Течен Кислород" }, "LIQUOR": { "description": "", @@ -729,11 +729,11 @@ }, "MAJOR_EXPORTS": { "description": "", - "message": "Major Exports:" + "message": "Основен Износ:" }, "MAJOR_EXPORT_CURRENT_SYSTEM": { "description": "Short (tooltip) description of how much one commodity trades in the system the player is currently in", - "message": "Major export (current system)" + "message": "Основен износ (сегашна система)" }, "MAJOR_IMPORTS": { "description": "", @@ -741,7 +741,7 @@ }, "MAJOR_IMPORT_CURRENT_SYSTEM": { "description": "Short (tooltip) description of how much one commodity trades in the system the player is currently in", - "message": "Major import (current system)" + "message": "Основен внос (сегашна система)" }, "MANUAL_CONTROL": { "description": "", @@ -749,11 +749,11 @@ }, "MANUAL_CONTROL_MODE": { "description": "", - "message": "Manual control mode" + "message": "Ръчен контролен режим" }, "MAP_LOCK_HYPERSPACE_TARGET": { "description": "", - "message": "Lock Hyperspace Target" + "message": "Заключи Хиперпространствената Цел" }, "MAP_TOGGLE_INFO_PANEL": { "description": "", @@ -765,55 +765,55 @@ }, "MAP_VIEW_ROTATE_DOWN": { "description": "", - "message": "Rotate View Down" + "message": "Завърти Изгледа Надолу" }, "MAP_VIEW_ROTATE_LEFT": { "description": "", - "message": "Rotate View Left" + "message": "Завърти Изгледа Наляво" }, "MAP_VIEW_ROTATE_RIGHT": { "description": "", - "message": "Rotate View Right" + "message": "Завърти Изгледа Надясно" }, "MAP_VIEW_ROTATE_UP": { "description": "", - "message": "Rotate View Up" + "message": "Завърти Изгледа Нагоре" }, "MAP_VIEW_SHIFT_BACKWARD": { "description": "", - "message": "Shift View Backwards" + "message": "Премести Изгледа Назад" }, "MAP_VIEW_SHIFT_DOWN": { "description": "", - "message": "Shift View Down" + "message": "Премести Изгледа Надолу" }, "MAP_VIEW_SHIFT_FORWARD": { "description": "", - "message": "Shift View Forwards" + "message": "Премести Изгледа Напред" }, "MAP_VIEW_SHIFT_LEFT": { "description": "", - "message": "Shift View Left" + "message": "Премести Изгледа Наляво" }, "MAP_VIEW_SHIFT_RIGHT": { "description": "", - "message": "Shift View Right" + "message": "Премести Изгледа Надясно" }, "MAP_VIEW_SHIFT_UP": { "description": "", - "message": "Shift View Up" + "message": "Премести Изгледа Нагоре" }, "MAP_WARP_TO_CURRENT_SYSTEM": { "description": "", - "message": "Warp to Current System" + "message": "Хипервръзка със Сегашната Система" }, "MAP_WARP_TO_HYPERSPACE_TARGET": { "description": "", - "message": "Warp to Hyperspace Target" + "message": "Хипервръзка с Целта" }, "MAP_WARP_TO_SELECTED_SYSTEM": { "description": "", - "message": "Warp to Selected System" + "message": "Хипервръзка с Избраната Система" }, "MASS": { "description": "", @@ -821,11 +821,11 @@ }, "MASSIVE": { "description": "", - "message": "Massive" + "message": "масивна" }, "MASS_N_TONNES": { "description": "", - "message": "Маса: %{mass}т" + "message": "Маса: %{mass} т." }, "MEDICINES": { "description": "", @@ -833,7 +833,7 @@ }, "MEDIUM_GAS_GIANT": { "description": "", - "message": "Medium gas giant" + "message": "среден газов гигант" }, "MESSAGE_FROM_X": { "description": "", @@ -869,19 +869,19 @@ }, "MINOR_EXPORTS": { "description": "", - "message": "Minor Exports:" + "message": "Незначителен Износ:" }, "MINOR_EXPORT_CURRENT_SYSTEM": { "description": "Short (tooltip) description of how much one commodity trades in the system the player is currently in", - "message": "Minor export (current system)" + "message": "Незначителен износ (сегашна система)" }, "MINOR_IMPORTS": { "description": "", - "message": "Minor Imports:" + "message": "Незначителен Внос:" }, "MINOR_IMPORT_CURRENT_SYSTEM": { "description": "Short (tooltip) description of how much one commodity trades in the system the player is currently in", - "message": "Minor import (current system)" + "message": "Незначителен внос (сегашна система)" }, "MISCELLANEOUS": { "description": "", @@ -961,11 +961,11 @@ }, "NAVIGATION_STAR_MAPS": { "description": "", - "message": "Navigation and star maps" + "message": "Навигация и звездни карти" }, "NAVIGATION_TARGETS_IN_THIS_SYSTEM": { "description": "", - "message": "Navigation targets in this system" + "message": "Навигационни цели в тази система" }, "NERVE_GAS": { "description": "", @@ -977,7 +977,7 @@ }, "NOT_FOUND_BEST_MATCH_X": { "description": "", - "message": "Not found, best match: %system" + "message": "Няма резултати. Най-добро съвпадение: %system" }, "NOW": { "description": "In System Orbit View", @@ -985,35 +985,35 @@ }, "NO_ALERT": { "description": "", - "message": "No alert" + "message": "Няма сигнал за тревога" }, "NO_AUTOPILOT_INSTALLED": { "description": "", - "message": "Autopilot not installed on ship, cannot enable autopilot" + "message": "Автопилотът не може да се включи, защото кораба няма автопилот" }, "NO_CENTRAL_GOVERNANCE": { "description": "", - "message": "No central governance" + "message": "Няма централно управление" }, "NO_ESTABLISHED_ORDER": { "description": "", - "message": "No established order" + "message": "Няма установен ред" }, "NO_HYPERDRIVE": { "description": "", - "message": "No hyperdrive" + "message": "Няма хипердвигател" }, "NO_REGISTERED_INHABITANTS": { "description": "", - "message": "No registered inhabitants" + "message": "Няма обитатели" }, "NO_TARGET_SELECTED": { "description": "", - "message": "Ship Computer: No target selected" + "message": "Корабен компютър: Не е избрана цел" }, "NUMBER_DAYS": { "description": "", - "message": "%days{f.0} дн." + "message": "%days{f.0} дни" }, "NUMBER_DECIMAL_POINT": { "description": "Decimal delimiter used in numbers.", @@ -1033,7 +1033,7 @@ }, "NUMBER_GROUP_SEP": { "description": "For large number, separator used when grouping digits. E.g. 1,000 or 1 000 or 1'000.", - "message": "'" + "message": "." }, "NUMBER_HOURS": { "description": "", @@ -1045,23 +1045,23 @@ }, "NUMBER_TONNES": { "description": "", - "message": "%{mass}т" + "message": "%{mass} т." }, "N_ATMOSPHERE": { "description": "", - "message": "\" Nitrogen atmosphere\"" + "message": "\" атмосфера от азот\"" }, "N_CELSIUS": { "description": "", - "message": "%temperature C" + "message": "%temperature Ц" }, "N_DAYS": { "description": "", - "message": "%days{f.1} дн." + "message": "%days{f.1} дни" }, "N_DEGREES": { "description": "", - "message": "%angle{f.1} град." + "message": "%angle{f.1} градуса" }, "N_EARTH_DAYS": { "description": "", @@ -1077,23 +1077,23 @@ }, "N_YEARS": { "description": "", - "message": "%years{f.1} год." + "message": "%years{f.1} години" }, "O2_ATMOSPHERE": { "description": "", - "message": "\" Oxygen atmosphere\"" + "message": "\" атмосфера от кислород\"" }, "OBJECT_INFO": { "description": "Originally for use as a window title and a button tooltip in the system map", - "message": "Object info" + "message": "Информация за обекта" }, "OCEANICWORLD": { "description": "", - "message": "\" oceanic world\"" + "message": "\" водна планета\"" }, "ORBITAL_PERIOD": { "description": "", - "message": "Orbital period" + "message": "Орбитален период" }, "ORBITAL_STARPORT": { "description": "", @@ -1109,15 +1109,15 @@ }, "OVER_N_BILLION": { "description": "", - "message": "Over %population billion" + "message": "Над %population млрд." }, "OVER_N_MILLION": { "description": "", - "message": "Over %population million" + "message": "Над %population мил." }, "PASSENGER_CABIN": { "description": "", - "message": "Occupied Passenger Cabin" + "message": "Заета Пасажерска Кабина" }, "PAUSED": { "description": "", @@ -1125,11 +1125,11 @@ }, "PAY_FINE_REMOTELY": { "description": "", - "message": "Pay fine by remote transfer (%amount)" + "message": "Плати глобата с паричен превод (%amount)" }, "PERIAPSIS_DISTANCE": { "description": "", - "message": "Periapsis distance" + "message": "Разстояние при периапсидата" }, "PIONEER": { "description": "", @@ -1141,27 +1141,27 @@ }, "PITCH_DOWN": { "description": "", - "message": "Pitch down" + "message": "Наклони надолу" }, "PITCH_UP": { "description": "", - "message": "Pitch up" + "message": "Наклони нагоре" }, "PLANETARY_INFO": { "description": "", - "message": "Информация за планетата" + "message": "Система" }, "PLANET_CONTAINING_LIQUID_WATER": { "description": "", - "message": "\" planet containing liquid water\"" + "message": "\" планета, съдържаща течна вода\"" }, "PLANET_WITH_SOME_ICE": { "description": "", - "message": "\" planet with some ice\"" + "message": "\" планета с наличие на лед\"" }, "PLANNED_ECONOMY": { "description": "", - "message": "Centrally planned economy" + "message": "Централно планирана икономика" }, "PLANNER_RESET_FACTOR": { "description": "For system orbit view", @@ -1189,7 +1189,7 @@ }, "PLUTOCRATIC_DICTATORSHIP": { "description": "", - "message": "Plutocratic dictatorship" + "message": "Плутократична диктатура" }, "POPULATION": { "description": "", @@ -1201,11 +1201,11 @@ }, "PRESSURE_N_ATMOSPHERES": { "description": "", - "message": "P: %pressure{f.2} атм." + "message": "Н: %pressure{f.2} атм." }, "QUADRUPLE_SYSTEM": { "description": "", - "message": "Quadruple system" + "message": "Четворна система" }, "RADAR_CONTROL": { "description": "", @@ -1221,11 +1221,11 @@ }, "RECENTLY_EXPLORED_SYSTEM": { "description": "", - "message": "This system was explored on %date." + "message": "Тази система е проучена на %date." }, "REQUEST_DOCKING_CLEARANCE": { "description": "", - "message": "Request docking clearance from {target}" + "message": "Заяви скачване с {target}" }, "RESET": { "description": "", @@ -1233,7 +1233,7 @@ }, "RESET_ORIENTATION_AND_ZOOM": { "description": "", - "message": "Reset Orientation and Zoom" + "message": "Нулирай Ориентацията и Мащабирането" }, "ROBOTS": { "description": "", @@ -1241,11 +1241,11 @@ }, "ROCKY_PLANET": { "description": "", - "message": "\" rocky planet\"" + "message": "\" скалиста планета\"" }, "ROCKY_PLANET_CONTAINING_COME_LIQUIDS": { "description": "", - "message": "\" rocky planet containing some liquids,\"" + "message": "\" скалиста планета, съдържаща някои течности,\"" }, "ROLL": { "description": "", @@ -1253,39 +1253,39 @@ }, "ROLL_LEFT": { "description": "", - "message": "Roll left" + "message": "Завърти наляво" }, "ROLL_RIGHT": { "description": "", - "message": "Roll right" + "message": "Завърти надясно" }, "ROTATE_DOWN": { "description": "", - "message": "Rotate Down" + "message": "Завърти Надолу" }, "ROTATE_LEFT": { "description": "", - "message": "Rotate Left" + "message": "Завърти Наляво" }, "ROTATE_RIGHT": { "description": "", - "message": "Rotate Right" + "message": "Завърти Надясно" }, "ROTATE_UP": { "description": "", - "message": "Rotate Up" + "message": "Завърти Нагоре" }, "ROTATIONAL_PERIOD": { "description": "", - "message": "\" (rotational period)\"" + "message": "\" (период на въртене)\"" }, "ROTATION_DAMPING_OFF": { "description": "", - "message": "Rotation damping off" + "message": "Изключи плавната ротация" }, "ROTATION_DAMPING_ON": { "description": "", - "message": "Rotation damping on" + "message": "Включи плавната ротация" }, "RUBBISH": { "description": "", @@ -1293,11 +1293,11 @@ }, "SCOOP": { "description": "Is followed by a number, repersenting scoop mounts/slots available to fit cargo scoop and/or fuel scoop", - "message": "Scoop" + "message": "Събирачи" }, "SCREENSHOT_FILENAME_TEMPLATE": { "description": "", - "message": "screenshot%index{d08}.png" + "message": "изображение%index{d08}.png" }, "SEARCH": { "description": "", @@ -1309,7 +1309,7 @@ }, "SECTOR_COORDINATES": { "description": "", - "message": "Sector coordinates:" + "message": "Секторни координати:" }, "SECTOR_MAP_VIEW": { "description": "", @@ -1333,19 +1333,19 @@ }, "SEMI_MAJOR_AXIS": { "description": "", - "message": "Semi-major axis" + "message": "Голяма полуос" }, "SET_AS_COMBAT_TARGET": { "description": "", - "message": "Set as combat target" + "message": "Задай за бойна цел" }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "SET_HYPERSPACE_DESTINATION_TO": { "description": "", - "message": "Set hyperspace destination to %system" + "message": "Задай %system за хиперпространствена дестинация" }, "SET_HYPERSPACE_TARGET_TO_FOLLOW_THIS_DEPARTURE": { "description": "", @@ -1357,19 +1357,19 @@ }, "SET_NAVTARGET_TO": { "description": "", - "message": "Set navigation target to: " + "message": "Задай навигационната цел на: " }, "SET_SPEED_KM_S": { "description": "", - "message": "Set speed: %speed{f.2} km/s" + "message": "Задай скорост: %speed{f.2} км/с" }, "SET_SPEED_M_S": { "description": "", - "message": "Set speed: %speed{f.0} m/s" + "message": "Задай скорост: %speed{f.0} м/с" }, "SHIELD_INTEGRITY": { "description": "", - "message": "Shield integrity" + "message": "Здравина на щитовете" }, "SHIELD_STRENGTH_N": { "description": "", @@ -1385,11 +1385,11 @@ }, "SHIPS_DISPLAY_MODE_TOGGLE": { "description": "Either show no ships, show ships, or show ships + their orbits", - "message": "Switch between ship display modes." + "message": "Космически кораби" }, "SHIP_DETECTED_NEARBY": { "description": "", - "message": "Ship detected nearby." + "message": "Наблизо е открит кораб." }, "SHIP_INFORMATION": { "description": "", @@ -1401,7 +1401,7 @@ }, "SHIP_NEARBY": { "description": "", - "message": "Ship nearby" + "message": "Наблизо има кораб" }, "SHIP_ORIENTATION": { "description": "", @@ -1413,7 +1413,7 @@ }, "SIDEREAL_VIEW": { "description": "camera view setting", - "message": "Sidereal view" + "message": "Звезден изглед" }, "SLAVES": { "description": "", @@ -1421,15 +1421,15 @@ }, "SMALL": { "description": "", - "message": "Small" + "message": "малка" }, "SMALL_GAS_GIANT": { "description": "", - "message": "Small gas giant" + "message": "малък газов гигант" }, "SMALL_INDUSTRIAL_OUTPOST": { "description": "", - "message": "Small industrial outpost." + "message": "Малък индустриален аванпост." }, "SMALL_SCALE_PROSPECTING_NO_SETTLEMENTS": { "description": "", @@ -1441,7 +1441,7 @@ }, "SOLAR": { "description": "", - "message": "Solar" + "message": "Слънчеви" }, "SOME_ESTABLISHED_MINING": { "description": "", @@ -1457,7 +1457,7 @@ }, "STABLE_SYSTEM_WITH_N_MAJOR_BODIES_STARPORTS": { "description": "", - "message": "Stable system with %bodycount major %{body(s)} and %portcount %{starport(s)}" + "message": "Стабилна система с %bodycount големи %{body(s)} и %portcount %{starport(s)}" }, "STARPORT": { "description": "", @@ -1469,131 +1469,131 @@ }, "STAR_A": { "description": "", - "message": "Type 'A' hot white star" + "message": "Клас 'А' гореща бяла звезда" }, "STAR_AF_GIANT": { "description": "", - "message": "White giant star" + "message": "Бял гигант" }, "STAR_AF_HYPER_GIANT": { "description": "", - "message": "White hyper giant star" + "message": "Бял хипергигант" }, "STAR_AF_SUPER_GIANT": { "description": "", - "message": "White super giant star" + "message": "Бял супергигант" }, "STAR_B": { "description": "", - "message": "Bright type 'B' blue star" + "message": "Клас 'Б' ярка синя звезда" }, "STAR_B_GIANT": { "description": "", - "message": "Blue giant star" + "message": "Син гигант" }, "STAR_B_HYPER_GIANT": { "description": "", - "message": "Blue hyper giant star" + "message": "Син хипергигант" }, "STAR_B_SUPER_GIANT": { "description": "", - "message": "Blue super giant star" + "message": "Син супергигант" }, "STAR_B_WF": { "description": "", - "message": "Wolf-Rayet star - Risk of collapse" + "message": "Звезда на Волф-Райе - Риск от разпадане" }, "STAR_F": { "description": "", - "message": "Type 'F' white star" + "message": "Клас 'Ф' бяла звезда" }, "STAR_G": { "description": "", - "message": "Type 'G' yellow star" + "message": "Клас 'Г' жълта звезда" }, "STAR_G_GIANT": { "description": "", - "message": "Yellow giant star - Unstable" + "message": "Жълт гигант - Нестабилен" }, "STAR_G_HYPER_GIANT": { "description": "", - "message": "Yellow hyper giant star - Unstable" + "message": "Жълт хипергигант - Нестабилен" }, "STAR_G_SUPER_GIANT": { "description": "", - "message": "Yellow super giant star" + "message": "Жълт супергигант" }, "STAR_IM_BH": { "description": "", - "message": "An intermediate-mass black hole" + "message": "Черна дупка с междинна маса" }, "STAR_K": { "description": "", - "message": "Type 'K' orange star" + "message": "Клас 'К' оранжева звезда" }, "STAR_K_GIANT": { "description": "", - "message": "Orange giant star - Unstable" + "message": "Оранжев гигант - Нестабилен" }, "STAR_K_HYPER_GIANT": { "description": "", - "message": "Orange hyper giant star - Unstable" + "message": "Оранжев хипергигант - Нестабилен" }, "STAR_K_SUPER_GIANT": { "description": "", - "message": "Orange super giant star" + "message": "Оранжев супергигант" }, "STAR_M": { "description": "", - "message": "Type 'M' red star" + "message": "Клас 'М' червена звезда" }, "STAR_M_GIANT": { "description": "", - "message": "Red giant star" + "message": "Червен гигант" }, "STAR_M_HYPER_GIANT": { "description": "", - "message": "Red hyper giant star" + "message": "Червен хипергигант" }, "STAR_M_SUPER_GIANT": { "description": "", - "message": "Red super giant star" + "message": "Червен супергигант" }, "STAR_M_WF": { "description": "", - "message": "Wolf-Rayet star - Unstable" + "message": "Звезда на Волф-Райе - Нестабилна" }, "STAR_O": { "description": "", - "message": "Hot, massive type 'O' star" + "message": "Клас 'О' масивна, гореща звезда" }, "STAR_O_GIANT": { "description": "", - "message": "Hot Blue giant star" + "message": "Горещ син гигант" }, "STAR_O_HYPER_GIANT": { "description": "", - "message": "Hot Blue hyper giant star" + "message": "Горещ син хипергигант" }, "STAR_O_SUPER_GIANT": { "description": "", - "message": "Hot Blue super giant star" + "message": "Горещ син супергигант" }, "STAR_O_WF": { "description": "", - "message": "Wolf-Rayet star - Imminent collapse" + "message": "Звезда на Волф-Райе - Предстоящо разпадане" }, "STAR_SM_BH": { "description": "", - "message": "Our galactic anchor" + "message": "Галактичен център" }, "STAR_SYSTEM_INFORMATION": { "description": "", - "message": "Star system information" + "message": "Информация за звездната система" }, "STAR_S_BH": { "description": "", - "message": "A stellar black hole" + "message": "Звездна черна дупка" }, "SUGGESTED_RESPONSES": { "description": "", @@ -1605,19 +1605,19 @@ }, "SURFACE_TEMPERATURE": { "description": "", - "message": "Surface temperature" + "message": "Повърхностна температура" }, "SWAP_SELECTED_HYPERSPACE_TARGET": { "description": "", - "message": "Swap selected and hyperjump target" + "message": "Размени целта за хисперскок и избраната цел" }, "SWITCHED_TO_PARENT": { "description": "Show ship's heading, coordinates are on the celestial sphere (defined by the ecliptic).", - "message": "Switched heading display to system-wide coordinates." + "message": "Използване на системните координати" }, "SWITCHED_TO_ROTATIONAL": { "description": "Show ship's heading in planetary coordinates. heading 0 = north, 90 = east, 180 = south, 270 = west.", - "message": "Switched heading display to planetary coordinates." + "message": "Използване на планетарните координати" }, "SYSTEM": { "description": "star system", @@ -1625,7 +1625,7 @@ }, "SYSTEM_NUMBER": { "description": "", - "message": "System number:" + "message": "Системен номер:" }, "SYSTEM_ORBIT_VIEW": { "description": "", @@ -1637,7 +1637,7 @@ }, "S_ATMOSPHERE": { "description": "", - "message": "\" Sulfuric atmosphere\"" + "message": "\" атмосфера от сяра\"" }, "TAKEOFF": { "description": "", @@ -1645,11 +1645,11 @@ }, "TARGET_OBJECT_IN_SIGHTS": { "description": "", - "message": "Target object in cross-hairs" + "message": "Целта е в прицела" }, "TENUOUS": { "description": "atmosphere thickness", - "message": "tenuous" + "message": "тънка" }, "TEXTILES": { "description": "", @@ -1657,11 +1657,11 @@ }, "THICK": { "description": "", - "message": "thick" + "message": "плътна" }, "THIN": { "description": "", - "message": "thin" + "message": "тънка" }, "THRIVING_OUTDOOR_WORLD": { "description": "", @@ -1669,35 +1669,35 @@ }, "THRUSTER_DORSAL": { "description": "", - "message": "Thrust down" + "message": "Тяга надолу" }, "THRUSTER_MAIN": { "description": "", - "message": "Thrust forward" + "message": "Тяга напред" }, "THRUSTER_PORT": { "description": "", - "message": "Thrust left" + "message": "Тяга наляво" }, "THRUSTER_RETRO": { "description": "", - "message": "Thrust backwards" + "message": "Тяга назад" }, "THRUSTER_STARBOARD": { "description": "", - "message": "Thrust right" + "message": "Тяга надясно" }, "THRUSTER_VENTRAL": { "description": "", - "message": "Thrust up" + "message": "Тяга нагоре" }, "TIME_POINT": { "description": "", - "message": "Time point:" + "message": "Час и дата: " }, "TINY": { "description": "", - "message": "Tiny" + "message": "дребна" }, "TOGGLE_EQUIPMENT_VIEW": { "description": "Tooltip for the Equipment View button", @@ -1709,7 +1709,7 @@ }, "TOGGLE_LUA_CONSOLE": { "description": "", - "message": "Включи Lua конзола" + "message": "Превключи конзолата на Lua" }, "TOGGLE_RADAR_MODE": { "description": "", @@ -1717,11 +1717,11 @@ }, "TOGGLE_RADAR_VIEW": { "description": "Tooltip for the Radar View button", - "message": "Radar View" + "message": "Радарен Изглед" }, "TOGGLE_ROTATION_DAMPING": { "description": "", - "message": "Toggle rotation damping" + "message": "Превключи плавната ротация" }, "TOMBSTONE_EPITAPH": { "description": "shown on tombstone when player dies", @@ -1733,23 +1733,23 @@ }, "TRIPLE_SYSTEM": { "description": "", - "message": "Triple system" + "message": "Тройна система" }, "UNDOCKING": { "description": "Flight state of ship when leaving station", - "message": "Undocking" + "message": "Откачване" }, "UNEXPLORED_SYSTEM_NO_DATA": { "description": "", - "message": "Unexplored system. No more data available." + "message": "Неизследвана система. Няма повече налични данни." }, "UNEXPLORED_SYSTEM_NO_SYSTEM_VIEW": { "description": "", - "message": "Unexplored system. System view unavailable." + "message": "Неизследвана система. Системният изглед не е наличен." }, "UNEXPLORED_SYSTEM_STAR_INFO_ONLY": { "description": "", - "message": "Unexplored System. Star information has been gathered by remote telescope, but no planetary information is available." + "message": "Неизследвана система. Информацията за звездите е взета от отдалечен телескоп, но информацията за планетите не е налична." }, "UNIT_AU": { "description": "Distance unit: an astronomical unit, radius of Earth's orbit", @@ -1813,7 +1813,7 @@ }, "UNSET_NAVTARGET": { "description": "", - "message": "Unset navigation target." + "message": "Премахни навигационна цел." }, "USE_LOW_THRUST": { "description": "", @@ -1825,11 +1825,11 @@ }, "VERY_DENSE": { "description": "", - "message": "very dense" + "message": "много плътна" }, "VERY_LARGE_GAS_GIANT": { "description": "", - "message": "Very large gas giant" + "message": "много голям газов гигант" }, "VIEW": { "description": "", @@ -1837,7 +1837,7 @@ }, "VIOLENT_ANARCHY": { "description": "", - "message": "Disorder - Overall governance contested by armed factions" + "message": "Анархия - контролът се оспорва от въоръжени групировки" }, "WATER": { "description": "", @@ -1849,7 +1849,7 @@ }, "WEAPON_TEMP": { "description": "", - "message": "Weapon temp" + "message": "Температура на оръжията" }, "WHEELS_ARE_DOWN": { "description": "", @@ -1861,7 +1861,7 @@ }, "WHITE_DWARF": { "description": "", - "message": "White dwarf stellar remnant" + "message": "Бяло джудже" }, "WITH_A": { "description": "", @@ -1869,7 +1869,7 @@ }, "WITH_NO_SIGNIFICANT_ATMOSPHERE": { "description": "", - "message": "\" with no significant atmosphere\"" + "message": "\" незначителна атмосфера\"" }, "X": { "description": "keybinding: x axis", @@ -1901,7 +1901,7 @@ }, "ZOOM_IN": { "description": "", - "message": "Увеличи" + "message": "Приближи" }, "ZOOM_OUT": { "description": "", diff --git a/data/lang/equipment-core/bg.json b/data/lang/equipment-core/bg.json index a969f37a0c0..ee3f22fbf67 100644 --- a/data/lang/equipment-core/bg.json +++ b/data/lang/equipment-core/bg.json @@ -21,7 +21,7 @@ }, "ATMOSPHERIC_SHIELDING_HEAVY_DESCRIPTION": { "description": "", - "message": "По-добра версия на Атмосферните Щитове" + "message": "Подобрена версия на Атмосферните Щитове." }, "AUTOPILOT": { "description": "", @@ -29,19 +29,19 @@ }, "AUTOPILOT_DESCRIPTION": { "description": "", - "message": "Летателен бордови компютър" + "message": "Летателен бордови компютър." }, "BEAMLASER_1MW": { "description": "", - "message": "1MW лъчеви лазер" + "message": "1 MW лъчеви лазер" }, "BEAMLASER_DUAL_1MW": { "description": "", - "message": "1MW двоен лъчеви лазер" + "message": "1 MW двоен лъчеви лазер" }, "BEAMLASER_RAPID_2MW": { "description": "", - "message": "2MW скорострелен лъчеви лазер" + "message": "2 MW скорострелен лъчеви лазер" }, "CARGO_LIFE_SUPPORT": { "description": "", @@ -57,43 +57,43 @@ }, "CARGO_SCOOP_DESCRIPTION": { "description": "", - "message": "Разрешава товаренето на стока от космоса." + "message": "Позволява товаренето на стока от космоса." }, "DRIVE_CLASS1": { "description": "", - "message": "Клас 1 Хиперсветлинен Двигател" + "message": "Клас 1 Хипердвигател" }, "DRIVE_CLASS2": { "description": "", - "message": "Клас 2 Хиперсветлинен Двигател" + "message": "Клас 2 Хипердвигател" }, "DRIVE_CLASS3": { "description": "", - "message": "Клас 3 Хиперсветлинен Двигател" + "message": "Клас 3 Хипердвигател" }, "DRIVE_CLASS4": { "description": "", - "message": "Клас 4 Хиперсветлинен Двигател" + "message": "Клас 4 Хипердвигател" }, "DRIVE_CLASS5": { "description": "", - "message": "Клас 5 Хиперсветлинен Двигател" + "message": "Клас 5 Хипердвигател" }, "DRIVE_CLASS6": { "description": "", - "message": "Клас 6 Хиперсветлинен Двигател" + "message": "Клас 6 Хипердвигател" }, "DRIVE_CLASS7": { "description": "", - "message": "Клас 7 Хиперсветлинен Двигател" + "message": "Клас 7 Хипердвигател" }, "DRIVE_CLASS8": { "description": "", - "message": "Клас 8 Хиперсветлинен Двигател" + "message": "Клас 8 Хипердвигател" }, "DRIVE_CLASS9": { "description": "", - "message": "Клас 9 Хиперсветлинен Двигател" + "message": "Клас 9 Хипердвигател" }, "DRIVE_MIL1": { "description": "", @@ -153,7 +153,7 @@ }, "FUEL_SCOOP_DESCRIPTION": { "description": "", - "message": "Разрешава събирането на водородно гориво от планетите газови гиганти." + "message": "Позволява събирането на водородно гориво от планетите газови гиганти." }, "HULL_AUTOREPAIR": { "description": "", @@ -185,7 +185,7 @@ }, "MININGCANNON_17MW": { "description": "", - "message": "17MW оръдие за взривно миниране" + "message": "17 MW оръдие за взривно миниране" }, "MININGCANNON_17MW_DESCRIPTION": { "description": "", @@ -208,12 +208,12 @@ "message": "R40 Самостоятелна Ракета" }, "MULTI_SCOOP": { - "description": "A ship equipment: a cargo scoop and fuel scoop combined to one", + "description": "A ship equipment: a cargo scoop and fuel scoop combined into one", "message": "Комбиниран Товарач" }, "MULTI_SCOOP_DESCRIPTION": { "description": "", - "message": "Разрешава товаренето на стока и събирането на гориво, но е по-малко ефективен от товарача за гориво" + "message": "Позволява товаренето на стока и събирането на гориво, но е по-малко ефективен от товарача за гориво." }, "OUT_OF_SCANRANGE": { "description": "", @@ -225,39 +225,39 @@ }, "PLANETSCANNER": { "description": "Scans the nearest body for resources", - "message": "Сканиране на тяло" + "message": "Скенер" }, "PLANETSCANNER_DESCRIPTION": { "description": "", - "message": "Сканиране на най-близкото тяло за ресурси." + "message": "Сканира най-близкото тяло за ресурси." }, "PULSECANNON_10MW": { "description": "", - "message": "10MW пулсиращо оръдие" + "message": "10 MW пулсиращо оръдие" }, "PULSECANNON_1MW": { "description": "", - "message": "1MW пулсиращо оръдие" + "message": "1 MW пулсиращо оръдие" }, "PULSECANNON_20MW": { "description": "", - "message": "20MW пулсиращо оръдие" + "message": "20 MW пулсиращо оръдие" }, "PULSECANNON_2MW": { "description": "", - "message": "2MW пулсиращо оръдие" + "message": "2 MW пулсиращо оръдие" }, "PULSECANNON_4MW": { "description": "", - "message": "4MW пулсиращо оръдие" + "message": "4 MW пулсиращо оръдие" }, "PULSECANNON_DUAL_1MW": { "description": "", - "message": "1MW двойно пулсиращо оръдие" + "message": "1 MW двойно пулсиращо оръдие" }, "PULSECANNON_RAPID_2MW": { "description": "", - "message": "2MW скорострелно пулсиращо оръдие" + "message": "2 MW скорострелно пулсиращо оръдие" }, "RADAR": { "description": "", @@ -265,7 +265,7 @@ }, "RADAR_DESCRIPTION": { "description": "", - "message": "Осигурява 3Д карта на близките кораби." + "message": "Осигурява 3D карта на близките кораби." }, "SCAN_COMPLETED": { "description": "", @@ -317,7 +317,7 @@ }, "THRUSTERS_BEST": { "description": "", - "message": "Направени по Поръчка Ускорители" + "message": "Поръчкови Ускорители" }, "THRUSTERS_BEST_DESCRIPTION": { "description": "", @@ -337,7 +337,7 @@ }, "TRADE_COMPUTER_DESCRIPTION": { "description": "", - "message": "Показва печелившите стоки за търговия между избраната и сегашната система" + "message": "Показва печелившите стоки за търговия между избраната и сегашната система." }, "UNOCCUPIED_CABIN": { "description": "", @@ -345,6 +345,6 @@ }, "UNOCCUPIED_CABIN_DESCRIPTION": { "description": "", - "message": "Използва се за превоз на един пасажер" + "message": "Използва се за превоз на един пасажер." } } diff --git a/data/lang/module-advice/es.json b/data/lang/module-advice/es.json index a58fe4c1d74..bcba4cca065 100644 --- a/data/lang/module-advice/es.json +++ b/data/lang/module-advice/es.json @@ -9,7 +9,7 @@ }, "ADVICE_1_BODYTEXT": { "description": "Point made is: the real illegal goods traders are fixed to each station, but police's fake illegal goods traders will be random every time.", - "message": "As you return to a station, be wary of those alternative market places you do not recognize, and you will stay out of trouble with the law." + "message": "Cuando regrese a una estación, tenga cuidado con los mercados alternativos que no reconozca y no se meterá en problemas con la ley." }, "ADVICE_1_HEADLINE": { "description": "", diff --git a/data/lang/module-aiwarning/ar.json b/data/lang/module-aiwarning/ar.json index 945e66a8b09..1ced33f6af9 100644 --- a/data/lang/module-aiwarning/ar.json +++ b/data/lang/module-aiwarning/ar.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "الطيار الالي" diff --git a/data/lang/module-aiwarning/bg.json b/data/lang/module-aiwarning/bg.json index 32d41ed8bbc..41c896028d1 100644 --- a/data/lang/module-aiwarning/bg.json +++ b/data/lang/module-aiwarning/bg.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Атмосферното налягане е над допустимото за кораба" + }, "AUTOPILOT": { "description": "", "message": "Автопилот" @@ -13,6 +17,6 @@ }, "STARPORT_REFUSED_DOCKING_PERMISSION": { "description": "", - "message": "Междузвездната станция отказа разрешение за скачване" + "message": "Космодрумът отказа разрешение за скачване" } } diff --git a/data/lang/module-aiwarning/ca.json b/data/lang/module-aiwarning/ca.json index 72c5a21e6a8..01221ba1d6a 100644 --- a/data/lang/module-aiwarning/ca.json +++ b/data/lang/module-aiwarning/ca.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Pilot automàtic" diff --git a/data/lang/module-aiwarning/cs.json b/data/lang/module-aiwarning/cs.json index c48ad6a90ac..96eba6f2880 100644 --- a/data/lang/module-aiwarning/cs.json +++ b/data/lang/module-aiwarning/cs.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/da.json b/data/lang/module-aiwarning/da.json index dad1af2c56a..314d755f6a3 100644 --- a/data/lang/module-aiwarning/da.json +++ b/data/lang/module-aiwarning/da.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/de.json b/data/lang/module-aiwarning/de.json index c31ae0d39cd..a3f4611d3fc 100644 --- a/data/lang/module-aiwarning/de.json +++ b/data/lang/module-aiwarning/de.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/el.json b/data/lang/module-aiwarning/el.json index 807b11c8a65..4457e3cceb1 100644 --- a/data/lang/module-aiwarning/el.json +++ b/data/lang/module-aiwarning/el.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Αυτόματος Πιλότος" diff --git a/data/lang/module-aiwarning/en.json b/data/lang/module-aiwarning/en.json index 46f079eeca7..1043906a3ea 100644 --- a/data/lang/module-aiwarning/en.json +++ b/data/lang/module-aiwarning/en.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/eo.json b/data/lang/module-aiwarning/eo.json index 46f079eeca7..1043906a3ea 100644 --- a/data/lang/module-aiwarning/eo.json +++ b/data/lang/module-aiwarning/eo.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/es.json b/data/lang/module-aiwarning/es.json index f6789e2ccef..5d83c35f631 100644 --- a/data/lang/module-aiwarning/es.json +++ b/data/lang/module-aiwarning/es.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Presión atmosférica sobre los límites de la nave" + }, "AUTOPILOT": { "description": "", "message": "Piloto automático" diff --git a/data/lang/module-aiwarning/fr.json b/data/lang/module-aiwarning/fr.json index 2388e83f26a..4e1d552b9df 100644 --- a/data/lang/module-aiwarning/fr.json +++ b/data/lang/module-aiwarning/fr.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Pilote automatique" diff --git a/data/lang/module-aiwarning/ga.json b/data/lang/module-aiwarning/ga.json index a6a1b6de034..befa9d7a8fa 100644 --- a/data/lang/module-aiwarning/ga.json +++ b/data/lang/module-aiwarning/ga.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Uathphíolóta" diff --git a/data/lang/module-aiwarning/gd.json b/data/lang/module-aiwarning/gd.json index a140475e785..bd668b49551 100644 --- a/data/lang/module-aiwarning/gd.json +++ b/data/lang/module-aiwarning/gd.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Fèin-stiùireadh" diff --git a/data/lang/module-aiwarning/hr.json b/data/lang/module-aiwarning/hr.json index 1e92eec9ece..c2a159268cf 100644 --- a/data/lang/module-aiwarning/hr.json +++ b/data/lang/module-aiwarning/hr.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Automatski pilot" diff --git a/data/lang/module-aiwarning/hu.json b/data/lang/module-aiwarning/hu.json index 6f88bc09e77..cb43a7ba2ce 100644 --- a/data/lang/module-aiwarning/hu.json +++ b/data/lang/module-aiwarning/hu.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Robotpilóta" diff --git a/data/lang/module-aiwarning/id.json b/data/lang/module-aiwarning/id.json index 33cc0ebb6fc..262b8603b24 100644 --- a/data/lang/module-aiwarning/id.json +++ b/data/lang/module-aiwarning/id.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Pilot otomatis" diff --git a/data/lang/module-aiwarning/it.json b/data/lang/module-aiwarning/it.json index 2667228b4e3..806473df9e1 100644 --- a/data/lang/module-aiwarning/it.json +++ b/data/lang/module-aiwarning/it.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Pressione atmosferica superiore ai limiti del vascello" + }, "AUTOPILOT": { "description": "", "message": "Pilota Automatico" diff --git a/data/lang/module-aiwarning/lt.json b/data/lang/module-aiwarning/lt.json index a4bfac4dc3f..498c7372def 100644 --- a/data/lang/module-aiwarning/lt.json +++ b/data/lang/module-aiwarning/lt.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilotas" diff --git a/data/lang/module-aiwarning/nb.json b/data/lang/module-aiwarning/nb.json index ba0b6f9aaa1..793172b208e 100644 --- a/data/lang/module-aiwarning/nb.json +++ b/data/lang/module-aiwarning/nb.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/nl.json b/data/lang/module-aiwarning/nl.json index 8f5d9f1fc69..2a3a98705ea 100644 --- a/data/lang/module-aiwarning/nl.json +++ b/data/lang/module-aiwarning/nl.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Automatische piloot" diff --git a/data/lang/module-aiwarning/pl.json b/data/lang/module-aiwarning/pl.json index 049b440b649..d08250bd463 100644 --- a/data/lang/module-aiwarning/pl.json +++ b/data/lang/module-aiwarning/pl.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/pt.json b/data/lang/module-aiwarning/pt.json index 83c699c1b06..e9957b78f33 100644 --- a/data/lang/module-aiwarning/pt.json +++ b/data/lang/module-aiwarning/pt.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Piloto automático" diff --git a/data/lang/module-aiwarning/pt_BR.json b/data/lang/module-aiwarning/pt_BR.json index 453eebbfa74..95cafc48ac0 100644 --- a/data/lang/module-aiwarning/pt_BR.json +++ b/data/lang/module-aiwarning/pt_BR.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Piloto Automático" diff --git a/data/lang/module-aiwarning/ro.json b/data/lang/module-aiwarning/ro.json index a6070ffd08f..9d2c408f053 100644 --- a/data/lang/module-aiwarning/ro.json +++ b/data/lang/module-aiwarning/ro.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/ru.json b/data/lang/module-aiwarning/ru.json index 5742ed03b73..b6d7cfb16d9 100644 --- a/data/lang/module-aiwarning/ru.json +++ b/data/lang/module-aiwarning/ru.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Автопилот" diff --git a/data/lang/module-aiwarning/sv.json b/data/lang/module-aiwarning/sv.json index 8f91b6eb455..92a5f0a62ec 100644 --- a/data/lang/module-aiwarning/sv.json +++ b/data/lang/module-aiwarning/sv.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmospheric pressure above ship limits" + }, "AUTOPILOT": { "description": "", "message": "Autopilot" diff --git a/data/lang/module-aiwarning/tr.json b/data/lang/module-aiwarning/tr.json index 42426674469..ac01a50a92c 100644 --- a/data/lang/module-aiwarning/tr.json +++ b/data/lang/module-aiwarning/tr.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "Atmosfer basıncı gemi sınırlarının üstünde" + }, "AUTOPILOT": { "description": "", "message": "Otomatik pilot" diff --git a/data/lang/module-aiwarning/zh.json b/data/lang/module-aiwarning/zh.json index c379a64330b..f6894f44946 100644 --- a/data/lang/module-aiwarning/zh.json +++ b/data/lang/module-aiwarning/zh.json @@ -1,4 +1,8 @@ { + "ATMO_PRESSURE_OVER_LIMIT": { + "description": "", + "message": "大气压力高于飞船极限" + }, "AUTOPILOT": { "description": "", "message": "自动驾驶" diff --git a/data/lang/module-assassination/bg.json b/data/lang/module-assassination/bg.json index f1dc1785a9b..aaf66da29a1 100644 --- a/data/lang/module-assassination/bg.json +++ b/data/lang/module-assassination/bg.json @@ -193,11 +193,11 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Задайте като навигационна цел" + "message": "Задай като навигационна цел" }, "SET_RETURN_ROUTE": { "description": "", - "message": "Задайте маршрут за връщане" + "message": "Задай маршрут за връщане" }, "SHIP": { "description": "", diff --git a/data/lang/module-assassination/es.json b/data/lang/module-assassination/es.json index 5f4a6bacba6..e23711ec372 100644 --- a/data/lang/module-assassination/es.json +++ b/data/lang/module-assassination/es.json @@ -93,7 +93,7 @@ }, "FLAVOUR_2_FAILUREMSG": { "description": "", - "message": "It is most regrettable that {target} is still alive and well. You will receive no payment as you did not complete your contract." + "message": "Es muy lamentable que {target} siga vivo y coleando. No recibirá ningún pago ya que no ha completado su contrato." }, "FLAVOUR_2_FAILUREMSG2": { "description": "", @@ -117,7 +117,7 @@ }, "FLAVOUR_3_FAILUREMSG2": { "description": "", - "message": "Are you asking money for a job done by someone else? Get lost." + "message": "¿Está pidiendo dinero por un trabajo cumplido por otro? Piérdase." }, "FLAVOUR_3_INTROTEXT": { "description": "", diff --git a/data/lang/module-breakdownservicing/bg.json b/data/lang/module-breakdownservicing/bg.json index 5b3581e4db0..41c9fd8232c 100644 --- a/data/lang/module-breakdownservicing/bg.json +++ b/data/lang/module-breakdownservicing/bg.json @@ -1,7 +1,7 @@ { "FLAVOUR_0_INTRO": { "description": "", - "message": "Избегнете неудобството от повреден хиперсветлинен двигател. Обслужете своя днес при лицензираната {name} Двигателна Обслужваща Компания.\n" + "message": "Избегнете неудобството от повреден хиперпространствен двигател. Обслужете своя днес при лицензираната {name} Двигателна Обслужваща Компания.\n" }, "FLAVOUR_0_PRICE": { "description": "", @@ -17,11 +17,11 @@ }, "FLAVOUR_0_YESPLEASE": { "description": "", - "message": "Обслужи хиперсветлинен двигател" + "message": "Обслужи хиперпространствен двигател" }, "FLAVOUR_1_INTRO": { "description": "", - "message": "Аз съм {proprietor}. Мога да обслужа Вашия хиперсветлинен двигател и Ви гарантирам поне година безпроблемна работа." + "message": "Аз съм {proprietor}. Мога да обслужа Вашия хипердвигател и Ви гарантирам поне година безпроблемна работа." }, "FLAVOUR_1_PRICE": { "description": "", @@ -29,19 +29,19 @@ }, "FLAVOUR_1_RESPONSE": { "description": "", - "message": "Обслужих Вашия хиперсветлинен двигател." + "message": "Обслужих Вашия хипердвигател." }, "FLAVOUR_1_TITLE": { "description": "", - "message": "{proprietor}: Специалист по поддръжката на хиперсветлинни двигатели" + "message": "{proprietor}: Специалист по поддръжката на хипердвигатели" }, "FLAVOUR_1_YESPLEASE": { "description": "", - "message": "Обслужи моя хиперсветлинен двигател" + "message": "Обслужи моя двигател" }, "FLAVOUR_2_INTRO": { "description": "", - "message": "Ехо. Ние от {proprietor} & Ко залагаме репутацията си на труда си.\nМожем да регулираме Вашия хиперсветлинен двигател, като гарантираме 12 месеца безпроблемна работа." + "message": "Ехо. Ние от {proprietor} & Ко залагаме репутацията си на труда си.\nМожем да регулираме Вашия хипердвигател, като гарантираме 12 месеца безпроблемна работа." }, "FLAVOUR_2_PRICE": { "description": "", @@ -57,11 +57,11 @@ }, "FLAVOUR_2_YESPLEASE": { "description": "", - "message": "Моля, регулирайте моя хиперсветлинен двигател на посочената цена" + "message": "Моля, регулирайте моя хипердвигател на посочената цена" }, "FLAVOUR_3_INTRO": { "description": "", - "message": "Добре дошли при Поддръжка СуперФикс. Време е за поддръжка? Ние ще СуперФиксираме вашия хиперсветлинен двигател!" + "message": "Добре дошли при Поддръжка СуперФикс. Време е за поддръжка? Ние ще СуперФиксираме вашия хиперпространствен двигател!" }, "FLAVOUR_3_PRICE": { "description": "", @@ -89,7 +89,7 @@ }, "FLAVOUR_4_RESPONSE": { "description": "", - "message": "Завършихме работата по Вашия хиперсветлинен двигател." + "message": "Завършихме работата по Вашия хиперпространствен двигател." }, "FLAVOUR_4_TITLE": { "description": "", @@ -101,7 +101,7 @@ }, "FLAVOUR_5_INTRO": { "description": "", - "message": "Избегнете неудобството от повреден хиперсветлинен двигател. Обслужете своя днес.\n" + "message": "Избегнете неудобството от повреден хиперпространствен двигател. Обслужете своя днес.\n" }, "FLAVOUR_5_PRICE": { "description": "", @@ -117,7 +117,7 @@ }, "FLAVOUR_5_YESPLEASE": { "description": "", - "message": "Обслужи хипер двигател" + "message": "Обслужи хиперпространствен двигател" }, "I_DONT_HAVE_ENOUGH_MONEY": { "description": "", @@ -125,11 +125,11 @@ }, "I_FIXED_THE_HYPERDRIVE_BEFORE_IT_BROKE_DOWN": { "description": "", - "message": "Поправих хиперсветлинния двигател преди да се повреди." + "message": "Поправих хипердвигателя преди да се повреди." }, "THE_SHIPS_HYPERDRIVE_HAS_BEEN_DESTROYED_BY_A_MALFUNCTION": { "description": "", - "message": "Хиперсветлинния двигател на кораба се разруши, поради неизправност." + "message": "Хипердвигателя на кораба се разруши, поради неизправност." }, "YOUR_DRIVE_HAS_NOT_BEEN_SERVICED": { "description": "", @@ -145,6 +145,6 @@ }, "YOU_FIXED_THE_HYPERDRIVE_BEFORE_IT_BROKE_DOWN": { "description": "", - "message": "Вие поправихте хиперсветлинния двигател преди да се повреди." + "message": "Вие поправихте хипердвигателя преди да се повреди." } } diff --git a/data/lang/module-breakdownservicing/es.json b/data/lang/module-breakdownservicing/es.json index d2f867dba3e..1781923116f 100644 --- a/data/lang/module-breakdownservicing/es.json +++ b/data/lang/module-breakdownservicing/es.json @@ -1,7 +1,7 @@ { "FLAVOUR_0_INTRO": { "description": "", - "message": "Avoid the inconvenience of a broken-down hyperspace engine. Get yours serviced today, by the officially endorsed {name} Engine Servicing Company.\n" + "message": "Evite las molestias de un hiperimpulsor averiado. Tenga el suyo reparado hoy, por la oficialmente aprobada Compañía de Servicio de Motores {name} .\n" }, "FLAVOUR_0_PRICE": { "description": "", @@ -41,7 +41,7 @@ }, "FLAVOUR_2_INTRO": { "description": "", - "message": "Hi there. We at {proprietor} & Co stake our reputation on our work.\nWe can tune your ship's hyperdrive, ensuring 12 months of trouble-free operation. " + "message": "Saludos. En {propietor} & Co arriesgamos nuestra reputación por nuestro trabajo. Podemos ajustar el hiperimpulsor de su nave, lo que garantiza 12 meses de funcionamiento sin problemas." }, "FLAVOUR_2_PRICE": { "description": "", @@ -49,7 +49,7 @@ }, "FLAVOUR_2_RESPONSE": { "description": "", - "message": "Service complete. Thanks for your custom." + "message": "Servicio completado. Gracias por su visita." }, "FLAVOUR_2_TITLE": { "description": "", @@ -61,11 +61,11 @@ }, "FLAVOUR_3_INTRO": { "description": "", - "message": "Welcome SuperFix Maintenance. Time for your biannual maintenance? Let us SuperFix your hyperdrive!" + "message": "Bienvenido a Mantenimientos SuperFix. ¿Es el momento de su revisión bianual? ¡Déjelo en manos de SuperFix!" }, "FLAVOUR_3_PRICE": { "description": "", - "message": "\n\n{lasttime}\nWe can tune your {drive} for just {price}. There's nobody cheaper!" + "message": "\n\n{lasttime}\nPodemos ajustar su {drive} por solo {price}. ¡No encontrará nada más económico!" }, "FLAVOUR_3_RESPONSE": { "description": "", @@ -85,7 +85,7 @@ }, "FLAVOUR_4_PRICE": { "description": "", - "message": "\n{lasttime}\nServicing your {drive} will cost {price}. Would you like to proceed?" + "message": "\n{lasttime}\nEl mantenimiento de su {drive} le costará {price}. ¿Desea proceder?" }, "FLAVOUR_4_RESPONSE": { "description": "", @@ -101,7 +101,7 @@ }, "FLAVOUR_5_INTRO": { "description": "", - "message": "Avoid the inconvenience of a broken-down hyperspace engine. Get yours serviced today.\n" + "message": "Evite el inconveniente de un motor hiperespacial averiado. Mantenga el suyo en servicio hoy mismo.\n" }, "FLAVOUR_5_PRICE": { "description": "", diff --git a/data/lang/module-cargorun/bg.json b/data/lang/module-cargorun/bg.json index 8a4df4c42a9..ee2d552bb76 100644 --- a/data/lang/module-cargorun/bg.json +++ b/data/lang/module-cargorun/bg.json @@ -25,39 +25,39 @@ }, "ADTEXT_1": { "description": "", - "message": "РАЗНОС. Доставка на товар до системата {system}." + "message": "РАЗНОС: Доставка на товар до системата {system}." }, "ADTEXT_2": { "description": "", - "message": "ТРЯБВА МИ ТРАНСПОРТ. Нуждая се от транспорт на стоки до системата {system}. Плащам {cash}." + "message": "НЕОБХОДИМ Е ТРАНСПОРТ: Транспорт на стоки до системата {system}. Плащам {cash}." }, "ADTEXT_EXPENSIVE_1": { "description": "", - "message": "ДОСТАВКА. Ценен товар до системата {system}. {cash} за опитен пилот." + "message": "ДОСТАВКА: Ценен товар до системата {system}. {cash} за опитен пилот." }, "ADTEXT_LOCAL_1": { "description": "", - "message": "МЕСТНА ДОСТАВКА. Преместване на стоки до {starport}." + "message": "МЕСТНА ДОСТАВКА: Преместване на стоки до {starport}." }, "ADTEXT_LOCAL_2": { "description": "", - "message": "ТЪРСИ СЕ ТРАНСПОРТ. Доставка на местен товар до {starport}." + "message": "ТЪРСИ СЕ ТРАНСПОРТ: Доставка на местен товар до {starport}." }, "ADTEXT_LOCAL_3": { "description": "", - "message": "МЕСТЕН РАЗНОС. Доставка на стоки до {starport}." + "message": "МЕСТЕН РАЗНОС: Доставка на стоки до {starport}." }, "ADTEXT_PICKUP_1": { "description": "", - "message": "CARGO PICKUP. Pickup of cargo from the {system} system required." + "message": "ТОВАРЕН ПРЕНОС: Товар от системата {system}." }, "ADTEXT_PICKUP_LOCAL_1": { "description": "", - "message": "RELOCATION. Move of cargo from {starport} required." + "message": "РЕЛОКАЦИЯ: Товар от {starport}." }, "ADTEXT_WHOLESALER_1": { "description": "", - "message": "ТОВАРНА УСЛУГА. Нуждаем се от доставчик до системата {system}." + "message": "ТОВАРНА УСЛУГА: Доставчик до системата {system}." }, "ALUMINIUM_TUBES": { "description": "custom cargo", @@ -89,7 +89,7 @@ }, "CEASE_FIRE": { "description": "", - "message": "Прекрати огъня, прекрати огъня! На твоя страна съм!" + "message": "Не стреляй, не стреляй! На твоя страна съм!" }, "CLUS": { "description": "custom cargo", @@ -133,7 +133,7 @@ }, "DENY_6": { "description": "", - "message": "Върнете се, когато натрупате повече опит." + "message": "Върни се, когато натрупаш повече опит." }, "DIAMONDS": { "description": "custom cargo", @@ -153,23 +153,23 @@ }, "ESCORT_CHATTER_1": { "description": "", - "message": "Hostile craft detected. Let us attack it together." + "message": "Открит е вражески кораб. Нека да го нападнем заедно." }, "ESCORT_CHATTER_2": { "description": "", - "message": "Great. This pirate will be my first kill." + "message": "Страхотно. Този пират ще бъде първото ми попадение." }, "ESCORT_CHATTER_3": { "description": "", - "message": "Enemy spotted. Commencing attack." + "message": "Забелязан е враг. Всички да атакуват." }, "ESCORT_CHATTER_4": { "description": "", - "message": "Proceed to your destination. I'll cover you." + "message": "Продължете към Вашата дестинация. Ще Ви прикривам." }, "ESCORT_CHATTER_5": { "description": "", - "message": "Tally ho. This will be my first catch today." + "message": "Еха. Това ще бъде първият ми улов за днес." }, "EXPLOSIVES": { "description": "custom cargo", @@ -177,23 +177,23 @@ }, "FAILUREMSG_1": { "description": "", - "message": "I'm very disappointed by the late delivery. You will not be paid." + "message": "Много съм разочарован от бавната доставка. Няма да получиш заплащане." }, "FAILUREMSG_2": { "description": "", - "message": "You are too late! What should I do with this now, it's worthless!" + "message": "Твърде късно е! Какво да правя с това, вече е безполезно!" }, "FAILUREMSG_3": { "description": "", - "message": "Listen, we were clear about the deadline. You can forget about getting paid." + "message": "Слушай, бяхме ясни за крайния срок. Мечтай си да получиш заплащане от нас." }, "FAILUREMSG_4": { "description": "", - "message": "From now on, I will reject all job requests from you." + "message": "Отсега нататък ти ще бъдеш в моя черен списък." }, "FAILUREMSG_FLUFFY_1": { "description": "", - "message": "You monster! You've waited too long for this delivery. All my fluffy pets are starved!" + "message": "Чудовище такова! Цяла вечност мина. Моите пухкави домашни любимци умират от глад!" }, "FURNITURE": { "description": "custom cargo", @@ -217,27 +217,27 @@ }, "HOWMUCH_2": { "description": "regarding mass, always more than 1t", - "message": "{amount}т" + "message": "{amount} т." }, "HOWMUCH_3": { "description": "regarding mass, always more than 1t", - "message": "Тежи {amount}т." + "message": "Тежи {amount} т." }, "HOWMUCH_4": { "description": "regarding mass, always more than 1t", - "message": "Има {amount}т." + "message": "Има {amount} т." }, "HOWMUCH_SINGULAR_1": { "description": "This string is only used for 1 metric tons (singular)", - "message": "Само {amount}т." + "message": "Само {amount} т." }, "HOWMUCH_WHOLESALER_1": { "description": "", - "message": "Има {amount}т от {cargoname}." + "message": "Има {amount} т. от {cargoname}." }, "HOWMUCH_WHOLESALER_2": { "description": "", - "message": "{amount}т {cargoname}" + "message": "{amount} т. {cargoname}" }, "HOW_MUCH_MASS": { "description": "", @@ -249,71 +249,71 @@ }, "INTROTEXT_1": { "description": "", - "message": "Hi, I'm {name}. I'll pay you {cash} if you will deliver {cargoname} to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, a distance of {dist} ly." + "message": "Здрасти, аз съм {name}. Ще ти платя {cash}, ако доставиш {cargoname} в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." }, "INTROTEXT_2": { "description": "{name} is the full name of a person", - "message": "Greetings! {name} Transport Services needs you to deliver {cargoname} to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, {dist} ly away. We pay {cash} for a safe and complete delivery." + "message": "Поздрави! Транспортни Услуги {name} искат да доставиш {cargoname} в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. Ще платим {cash} за безопасна и безаварийна доставка." }, "INTROTEXT_3": { "description": "", - "message": "Good day. I'm {name}, founder of the {name} Ltd. I need someone trustworthy to deliver {cargoname} to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system. I will pay {cash} for the {dist} ly long flight." + "message": "Добър ден. Аз съм {name}, създател на {name} ООД. Нуждая се от надежден пилот да достави {cargoname} в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}). Ще платя {cash} за разстоянието от {dist} сг." }, "INTROTEXT_EXPENSIVE_1": { "description": "", - "message": "Hello. We need someone experienced for a potentially dangerous run to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system. We'll pay {cash}. The distance is {dist} ly." + "message": "Здравейте. Нуждаем се от опитен пилот за потенциално опасна мисия до {starport} в системата {system} ({sectorx}, {sectory}, {sectorz}). Ще платим {cash}. Разстоянието е {dist} сг." }, "INTROTEXT_FLUFFY_1": { "description": "this is used for the delivery of Quibbles, which is a nod to Tribble (star trek ref. see wikipedia)", - "message": "Hi, my name is {name}. I have a fluffy shipment of {cargoname} for delivery to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system. The distance is {dist} ly. For this delivery I will pay you {cash}." + "message": "Здрасти, името ми е {name}. Имам пухкава пратка от {cargoname} за доставка в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}). Разстоянието е {dist} сг. За доставката ще ти платя {cash}." }, "INTROTEXT_INFRASTRUCTURE_1": { "description": "", - "message": "Greetings. I'm {name}. The {system} government wants to deliver {cargoname} to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system. The pay is {cash}. {system} is located {dist} ly from here." + "message": "Поздрави! Аз съм {name}. Правителството на {system} трябва да достави {cargoname} в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}). Заплащането е {cash}. {system} се на намира на разстояние от {dist} сг." }, "INTROTEXT_LOCAL_1": { "description": "", - "message": "Nice to meet you. I'm {name} and I work for the {starport} administration. We pay {cash} to someone who is able to move {cargoname} to {starport}." + "message": "Радвам се да се запознаем. Аз съм {name} и работя в администрацията на {starport}. Ще платим {cash} на всеки, който може да премести {cargoname} в {starport}." }, "INTROTEXT_LOCAL_2": { "description": "", - "message": "Hi. I'm {name} and I will pay {cash} for a short delivery of {cargoname} to {starport}." + "message": "Здрасти. Аз съм {name} и ще платя {cash} за кратка доставка на {cargoname} в {starport}." }, "INTROTEXT_LOCAL_3": { "description": "", - "message": "My name is {name} and I need {cargoname} delivered to a client at {starport}. I'll pay you {cash} for this run." + "message": "Името ми е {name} и искам {cargoname} да се достави на клиент в {starport}. Ще ти платя {cash} за този разнос." }, "INTROTEXT_MINING_1": { "description": "{name} is the full name of a person", - "message": "Hello. The {name} Mining Company wants to deliver {cargoname} to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, {dist} ly away, to build a new mine. The pay is {cash}." + "message": "Здравейте. Минната Компания {name} трябва да достави {cargoname} в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг, за да построи нова мина. Ще платят {cash}." }, "INTROTEXT_PICKUP_1": { "description": "", - "message": "How do you do? My name is {name}, and I need a ship that is able to fly to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, to pickup {cargoname} and return to {dom_starport} in the {dom_system} ({dom_sectorx}, {dom_sectory}, {dom_sectorz}) system for {cash}. The distance to {system} is {dist} ly." + "message": "Как е? Името ми е {name}, трябва ми кораб, който да отиде до {starport} в системата {system} ({sectorx}, {sectory}, {sectorz}), да натовари {cargoname} и да се върне в {dom_starport}, в системата {dom_system} ({dom_sectorx}, {dom_sectory}, {dom_sectorz}) за {cash}. Разстоянието до {system} е {dist} сг." }, "INTROTEXT_PICKUP_2": { "description": "", - "message": "How are you? I'm {name}. One of my clients wants to import {cargoname} from {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, {dist} ly distant. He pays {cash} for this cargo run. Return here to {dom_starport} in the {dom_system} ({dom_sectorx}, {dom_sectory}, {dom_sectorz}) system to unload the cargo." + "message": "Как си? Аз съм {name}. Един от моите клиенти иска да внесе {cargoname} от {starport} в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. Той ще плати {cash} за този разнос. Върни се в {dom_starport}, в системата {dom_system} ({dom_sectorx}, {dom_sectory}, {dom_sectorz}) за да разтовариш товара." }, "INTROTEXT_PICKUP_LOCAL_1": { "description": "", - "message": "Greetings. I'm {name}. I will pay {cash} to someone who will transport {cargoname} from {starport} to {dom_starport}." + "message": "Поздрави. Аз съм {name}.Ще платя {cash} на някой, който може да транспортира {cargoname} от {starport} до {dom_starport}." }, "INTROTEXT_PICKUP_LOCAL_2": { "description": "", - "message": "Hello. My name is {name}. My employer is willing to hire you for {cash} to help us relocate our warehouse by moving {cargoname} from {starport} to our new domicile {dom_starport}." + "message": "Здравейте. Казвам се {name}. Моят работодател е готов да те наеме за {cash}, във връзка с релокацията на нашият склад, като преместиш {cargoname} от {starport} в нашето ново седалище в {dom_starport}." }, "INTROTEXT_WEDDING_1": { "description": "", - "message": "Greetings. Have you heard of the wedding season of {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system? We want to transport {cargoname} there. It's {dist} ly away. The pay is {cash}. How about it?" + "message": "Поздрави. Чувал ли си за брачния сезон в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz})? Искаме да транспортираме {cargoname} дотам. Разстоянието е {dist} сг. Ще платим {cash}. Какво ще кажеш?" }, "INTROTEXT_WHOLESALER_1": { "description": "", - "message": "Hello, my name is {name} and I'm a wholesale dealer in the {system} system. I pay {cash} for the run to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, {dist} ly." + "message": "Здравейте, името ми е {name}, аз съм търговец на едро в системата {system}. Ще Ви платя {cash} за разноса до {starport} в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." }, "INTROTEXT_WHOLESALER_2": { "description": "", - "message": "Greetings, my name is {name} and I work for Haber Corp. We pay {cash} for the run to {starport} in the {system} ({sectorx}, {sectory}, {sectorz}) system, a distance of {dist} ly." + "message": "Поздрави, името ми е {name} и работя за Хаберската Корпорация. Ще платим {cash} за разноса до {starport} в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." }, "I_AM_ON_MY_WAY": { "description": "", @@ -321,11 +321,11 @@ }, "I_HAVE_DEBITED_YOUR_ACCOUNT": { "description": "", - "message": "I've debited your account with the missing goods." + "message": "Липсващите стоки са за твоя сметка." }, "I_NEED_HELP": { "description": "", - "message": "Понасям щети. Нуждая се от помощ." + "message": "Напълниха ме с олово. Нуждая се от помощ." }, "LY": { "description": "", @@ -349,15 +349,15 @@ }, "PIRATE_GRIPES_1": { "description": "", - "message": "Damn! You will pay for this!" + "message": "По дяволите! Ще си платиш за това!" }, "PIRATE_GRIPES_2": { "description": "", - "message": "Oh no. My poor ship!" + "message": "Не. Горкият ми кораб!" }, "PIRATE_GRIPES_3": { "description": "said with vengeance", - "message": "Wait, I'll show you." + "message": "Сега ще видиш ти." }, "PIRATE_TAUNTS_1": { "description": "", @@ -381,11 +381,11 @@ }, "PIRATE_TAUNTS_6": { "description": "", - "message": "Looks like you're carrying more than you can handle. Let me help you with that." + "message": "Изглеждаш доста натоварен. Ей сега ще ти помогна да се разтовариш." }, "PIRATE_TAUNTS_7": { "description": "", - "message": "Your luck has run out!" + "message": "Късмета ти беше дотук!" }, "PLUTONIUM": { "description": "custom cargo", @@ -405,47 +405,47 @@ }, "RISK_3": { "description": "", - "message": "Това е ценен товар, отваряйте си очите на четири." + "message": "Това е ценен товар, отваряй си очите на четири." }, "RISK_4": { "description": "", - "message": "Може да е опасно, трябва да сте сигурни, че сте подготвени адекватно." + "message": "Може да е опасно, трябва да си сигурен, че си подготвен адекватно." }, "RISK_5": { "description": "", - "message": "Това може да е много рисковано, най-вероятно ще срещнете силна съпротива." + "message": "Това може да е много рисковано, най-вероятно ще срещнеш силна съпротива." }, "RISK_6": { "description": "", - "message": "Не се надявайте да стигнете невредими." + "message": "Не се надявай да стигнеш невредим." }, "RISK_ART_1": { "description": "", - "message": "The goods are very sought after by art lovers." + "message": "Тези стоки са мишена на любителите на изкуството." }, "RISK_EXPENSIVE_1": { "description": "", - "message": "We have done everything to keep the delivery secret. But we can never be certain." + "message": "Направихме всичко възможно доставката да остане в тайна. Но дори и стените имат уши." }, "RISK_EXPENSIVE_2": { "description": "", - "message": "The police informed us that an unknown group of pirates is operating in this system." + "message": "Полицията ни информира, че е забелязана неизвестна група от пирати в тази система." }, "RISK_GEMS_1": { "description": "", - "message": "It is possible that an unscrupulous jewel trader wants to intercept the cargo." + "message": "Възможно е да си имаш работа с някой безскрупулен търговец на бижута." }, "RISK_WHOLESALER_1": { "description": "", - "message": "Don't worry. A police patrol is ready in case of trouble." + "message": "Не се притеснявай. Полицията е готова да се намеси при необходимост." }, "RISK_WHOLESALER_2": { "description": "", - "message": "Maybe there's a risk. But the police have promised us to patrol the area." + "message": "Вероятно има риск. Но полицията си върши работата." }, "RISK_WHOLESALER_3": { "description": "", - "message": "The risk is high. But an escort is ready to guard you." + "message": "Рискът е голям. Но ескортът е готов за действие." }, "SEMI_FINISHED_PRODUCTS": { "description": "custom cargo", @@ -453,11 +453,11 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "SET_RETURN_ROUTE": { "description": "", - "message": "Задайте маршрут за връщане" + "message": "Задай маршрут за връщане" }, "SPACEPORT": { "description": "", @@ -473,23 +473,23 @@ }, "SUCCESSMSG_1": { "description": "", - "message": "Thank you for the delivery. You have been paid." + "message": "Благодаря Ви за доставката. Получихте възнаграждението си." }, "SUCCESSMSG_2": { "description": "", - "message": "Thanks for the timely delivery. The money was transferred." + "message": "Благодаря за бързата доставка. Парите са преведени по Вашата сметка." }, "SUCCESSMSG_3": { "description": "", - "message": "Excellent, it was a pleasure to work with you. I have paid the bill." + "message": "Отлично, за мен беше удоволствие да работя с Вас. Разходите са за моя сметка." }, "SUCCESSMSG_4": { "description": "", - "message": "Thanks! I will definitely recommend you. Money has been transferred." + "message": "Благодаря! Ще Ви препоръчам. Преведох парите по Вашата сметка." }, "SUCCESSMSG_FLUFFY_1": { "description": "Said when receiving a shipment of Quibbles (see wikipedia Tribble)", - "message": "Oh dear, what to do with so many fluffy beings. Either way, money has been sent." + "message": "О, Боже, какво да правя с толкова много пухкави същества. Така или иначе, парите са Ви изплатени." }, "SYSTEM": { "description": "", @@ -545,71 +545,71 @@ }, "WE_HAVE_LOADED_UP_THE_CARGO_ON_YOUR_SHIP": { "description": "", - "message": "Заредихме товара на Вашия кораб." + "message": "Заредихме товара." }, "WHAT_IS_THIS": { "description": "", - "message": "What's this? Have you jettisoned my cargo? Are you crazy?" + "message": "Какво? Изхвърлил си моя товар? Луд ли си?" }, "WHYSOMUCH_1": { "description": "", - "message": "This is the standard fee." + "message": "Това е стандартното заплащане." }, "WHYSOMUCH_2": { "description": "", - "message": "Accept it, or leave it be." + "message": "Няма значение дали ти харесва или не." }, "WHYSOMUCH_3": { "description": "", - "message": "What is considered \"much\" is relative." + "message": "Това, което се счита за \"много\", е относително." }, "WHYSOMUCH_4": { "description": "", - "message": "The pay reflects our wish for the goods to be delivered on time and in one piece." + "message": "Плащането отразява нашето желание стоките да бъдат доставени навреме и без драскотини." }, "WHYSOMUCH_5": { "description": "", - "message": "See it as a bonus for you to be discreet about this delivery." + "message": "Това е бонус, за да си държите езика зад зъбите." }, "WHYSOMUCH_6": { "description": "", - "message": "Е, ще се радваме да Ви платим по-малко пари." + "message": "Е, ще се радваме да ти платим по-малко пари." }, "WHYSOMUCH_CENTRIFUGES_1": { "description": "", - "message": "Some {cargoname} were destroyed due to a software error and have to be replaced urgently." + "message": "Някои {cargoname} са унищожени, поради софтуерна грешка и спешно трябва да бъдат заменени." }, "WHYSOMUCH_CHEMICAL_1": { "description": "", - "message": "The production in the chemical plant depends on these goods and must not be interrupted. Nothing must stop the machine." + "message": "Производството в химическия завод зависи от тези стоки и не трябва да се прекъсва. Нищо не трябва да спира машината." }, "WHYSOMUCH_EXPENSIVE_1": { "description": "", - "message": "Valuable goods are in great demand." + "message": "Ценните стоки са търсени." }, "WHYSOMUCH_EXPENSIVE_2": { "description": "", - "message": "Because these goods are quite expensive." + "message": "Защото тези стоки са доста скъпи." }, "WHYSOMUCH_FLUFFY_1": { "description": "", - "message": "{cargoname} is a fast seller this season. You should invest in {cargoname} shares if you want to make a lot of money." + "message": "{cargoname} са доста печеливши. Трябва да инвестираш в {cargoname}, ако искаш да изкараш много пари." }, "WHYSOMUCH_INFRASTRUCTURE_1": { "description": "", - "message": "These goods are crucial for a construction project." + "message": "Тези стоки са жизненоважни за строителния проект." }, "WHYSOMUCH_MINING_1": { "description": "", - "message": "These goods are essential for the construction of a new mine." + "message": "Тези стоки са от съществено значение за строежа на новата мина." }, "WHYSOMUCH_URGENT_1": { "description": "", - "message": "My favourite pilot is sick and time is short." + "message": "Любимият ми пилот е болен, а времето е малко." }, "WHYSOMUCH_URGENT_2": { "description": "", - "message": "If we do not meet the delivery date, the project will come to a standstill." + "message": "Ако не извършим доставката навреме, проектът ще бъде спрян." }, "WHYSOMUCH_URGENT_3": { "description": "", @@ -617,7 +617,7 @@ }, "WHYSOMUCH_WEDDING_1": { "description": "", - "message": "So far I could not find anyone to perform this transport. When the season is over, my merchandise is worthless." + "message": "Досега не можах да намеря някой, който да извърши този транспорт. Когато сезонът свърши, стоката ми ще е безполезна." }, "WHY_SO_MUCH_MONEY": { "description": "", @@ -629,10 +629,10 @@ }, "YOU_DO_NOT_HAVE_ENOUGH_CARGO_SPACE_ON_YOUR_SHIP": { "description": "", - "message": "Нямате достатъчно товарно пространство на Вашия кораб." + "message": "Нямаш достатъчно товарно пространство." }, "YOU_DO_NOT_HAVE_ENOUGH_EMPTY_CARGO_SPACE": { "description": "", - "message": "Моля, върнете се, когато имате достатъчно товарно пространство." + "message": "Моля, върни се, когато имаш достатъчно товарно пространство." } } diff --git a/data/lang/module-combat/bg.json b/data/lang/module-combat/bg.json index ab100417562..14121cf17a1 100644 --- a/data/lang/module-combat/bg.json +++ b/data/lang/module-combat/bg.json @@ -61,27 +61,27 @@ }, "CORPORATION_1": { "description": "Name of a corporation", - "message": "Precious Goods Foundation" + "message": "Фондация за Скъпоценни Стоки" }, "CORPORATION_2": { "description": "Name of a corporation", - "message": "Omega Mining Company" + "message": "Минна Компания Омега" }, "CORPORATION_3": { "description": "Name of a corporation", - "message": "United Ore Mines Syndicate" + "message": "Обединени Рудни Синдикати" }, "CORPORATION_4": { "description": "Name of a corporation", - "message": "Galactic Explorer Corporation" + "message": "Корпорация на Галактическите Изследователи" }, "CORPORATION_5": { "description": "Name of a corporation", - "message": "Haber Corporation" + "message": "Хаберска Корпорация" }, "CORPORATION_6": { "description": "Name of a corporation", - "message": "Precious Metal Prospectors АД" + "message": "Търсачи на Благородни Метали АД" }, "CORPORATION_7": { "description": "Name of a corporation", @@ -165,7 +165,7 @@ }, "HARVESTING_LAND_THERE": { "description": "", - "message": "Имаме продавач във всяка слънчева система наоколо. Този човек ще се свърже с Вас, когато се приземите." + "message": "Имаме продавач във всяка звездна система наоколо. Този човек ще се свърже с теб, когато се приземиш." }, "HOW_WILL_I_BE_PAID": { "description": "", @@ -221,11 +221,11 @@ }, "MINING_IT_MUST_BE_COMPLETED_BY": { "description": "", - "message": "Има конвой на път към {area}. Мисията трябва да се изпълни преди {date}." + "message": "Има конвой на път за {area}. Мисията трябва да се изпълни преди {date}." }, "MINING_LAND_THERE": { "description": "", - "message": "Имаме служители във всяка слънчева система наоколо. Просто посетете най-близката станция и се свържете с местния им офис." + "message": "Имаме служители във всяка звездна система наоколо. Просто посетете най-близката станция и се свържете с местния им офис." }, "MISSION": { "description": "", @@ -277,7 +277,7 @@ }, "POLICE_2": { "description": "{area} is an asteroid or planet", - "message": "Ние от {org} ще платим {cash} за бойна мисия в системата {system} ({sectorx}, {sectory}, {sectorz}). Нямаме достатъчно пилоти и кораби. Поради тази причина, това може да е Вашият шанс да изкарате някой кредит в повече. Целта е малка пиратска база на {area}. Нуждаете се от хиперсветлинен двигател с гориво за {dist} сг и допълнително гориво за връщане." + "message": "Ние от {org} ще платим {cash} за бойна мисия в системата {system} ({sectorx}, {sectory}, {sectorz}). Нямаме достатъчно пилоти и кораби. Поради тази причина, това може да е твоят шанс да изкараш някой кредит в повече. Целта е малка пиратска база на {area}. Ще ти е нужен хипердвигател с гориво за {dist} сг и допълнително гориво за връщане." }, "POLICE_3": { "description": "{area} is an asteroid or planet", @@ -293,7 +293,7 @@ }, "RADAR_NOT_INSTALLED": { "description": "", - "message": "Съжалявам, едва ли ще се справите без радар." + "message": "Съжалявам, едва ли ще се справиш без радар." }, "RISK_1": { "description": "", @@ -309,15 +309,15 @@ }, "RISK_4": { "description": "", - "message": "Врагът е много добре оборудван и има достъп до последните технологии. Внимавайте!" + "message": "Врагът е много добре оборудван и има достъп до последните технологии. Бъди внимателен!" }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "SUCCESSMSG_1": { "description": "", - "message": "Знаех си, че си точния човек за тази мисия. Това е за теб." + "message": "Знаех си, че уцелих точния човек за тази мисия. Това е за Вас." }, "SUCCESSMSG_2": { "description": "", diff --git a/data/lang/module-combat/es.json b/data/lang/module-combat/es.json index 1bd118771be..940ca96d456 100644 --- a/data/lang/module-combat/es.json +++ b/data/lang/module-combat/es.json @@ -293,7 +293,7 @@ }, "RADAR_NOT_INSTALLED": { "description": "", - "message": "Sorry, I don't think you can handle this without a radar." + "message": "Lo siento, no creo que pueda hacer eso sin un radar." }, "RISK_1": { "description": "", diff --git a/data/lang/module-deliverpackage/bg.json b/data/lang/module-deliverpackage/bg.json index cf55b420051..86dc4e5c74f 100644 --- a/data/lang/module-deliverpackage/bg.json +++ b/data/lang/module-deliverpackage/bg.json @@ -17,11 +17,11 @@ }, "DENY_0": { "description": "", - "message": "Съжалявам, не мога да Ви имам доверие за тази доставка." + "message": "Съжалявам, не мога да ти имам доверие за тази доставка." }, "DENY_1": { "description": "", - "message": "Върнете се, когато натрупате нужния опит." + "message": "Върни се, когато натрупаш нужния опит." }, "DENY_2": { "description": "", @@ -65,7 +65,7 @@ }, "FLAVOUR_0_INTROTEXT": { "description": "", - "message": "Здрасти, аз съм {name}. Ще ти платя {cash}, ако доставиш малък пакет в {starport}, намираща се в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." + "message": "Здрасти, аз съм {name}. Ще ти платя {cash}, ако доставиш малък пакет в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." }, "FLAVOUR_0_SUCCESSMSG": { "description": "", @@ -77,7 +77,7 @@ }, "FLAVOUR_1_ADTEXT": { "description": "", - "message": "ТЪРСИ СЕ. Доставка на пакет до системата {system}." + "message": "ТЪРСИ СЕ: Доставка на пакет до системата {system}." }, "FLAVOUR_1_FAILUREMSG": { "description": "", @@ -85,7 +85,7 @@ }, "FLAVOUR_1_INTROTEXT": { "description": "", - "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, намираща се в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " + "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " }, "FLAVOUR_1_SUCCESSMSG": { "description": "", @@ -105,7 +105,7 @@ }, "FLAVOUR_2_INTROTEXT": { "description": "", - "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, намираща се в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " + "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " }, "FLAVOUR_2_SUCCESSMSG": { "description": "", @@ -117,7 +117,7 @@ }, "FLAVOUR_3_ADTEXT": { "description": "", - "message": "ДОСТАВКА. Документи до системата {system}. {cash} за пилот с опит." + "message": "ДОСТАВКА: Документи до системата {system}. {cash} за пилот с опит." }, "FLAVOUR_3_FAILUREMSG": { "description": "", @@ -125,7 +125,7 @@ }, "FLAVOUR_3_INTROTEXT": { "description": "", - "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, намираща се в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " + "message": "Здрасти, аз съм {name}. Склонен съм да платя {cash} за кораб, който да достави пакет в {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг. " }, "FLAVOUR_3_SUCCESSMSG": { "description": "", @@ -137,7 +137,7 @@ }, "FLAVOUR_4_ADTEXT": { "description": "", - "message": "ПОЩЕНСКА УСЛУГА. Нуждаем се от доставчик до системата {system}." + "message": "ПОЩЕНСКА УСЛУГА: Нуждаем се от доставчик до системата {system}." }, "FLAVOUR_4_FAILUREMSG": { "description": "", @@ -145,7 +145,7 @@ }, "FLAVOUR_4_INTROTEXT": { "description": "", - "message": "Поздрави. Това е автоматично съобщение от Куриерски Услуги Бедфорд и {name}. Плащаме {cash} за доставка до {starport}, намираща се в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." + "message": "Поздрави. Това е автоматично съобщение от Куриерски Услуги Бедфорд и {name}. Плащаме {cash} за доставка до {starport}, в системата {system} ({sectorx}, {sectory}, {sectorz}), на разстояние от {dist} сг." }, "FLAVOUR_4_SUCCESSMSG": { "description": "", @@ -153,11 +153,11 @@ }, "FLAVOUR_4_WHYSOMUCHTEXT": { "description": "", - "message": "Ще се радваме да Ви платим по-малко пари." + "message": "Ще се радваме да ти платим по-малко пари." }, "FLAVOUR_5_ADTEXT": { "description": "", - "message": "ПРЕМЕСТВАНЕ. Преместване на железария до {starport} от склада." + "message": "ПРЕМЕСТВАНЕ: Преместване на железария до {starport} от склада." }, "FLAVOUR_5_FAILUREMSG": { "description": "", @@ -177,7 +177,7 @@ }, "FLAVOUR_6_ADTEXT": { "description": "", - "message": "КУРИЕР ЗА ЕДИН МИГ. Доставка на малък пакет до {starport}." + "message": "КУРИЕР ЗА ЕДИН МИГ: Доставка на малък пакет до {starport}." }, "FLAVOUR_6_FAILUREMSG": { "description": "", @@ -197,7 +197,7 @@ }, "FLAVOUR_7_ADTEXT": { "description": "", - "message": "МЕЖДУПЛАНЕТЕН НОСАЧ. Превоз на локален товар до {starport}." + "message": "МЕЖДУПЛАНЕТЕН НОСАЧ: Превоз на локален товар до {starport}." }, "FLAVOUR_7_FAILUREMSG": { "description": "", @@ -217,11 +217,11 @@ }, "FLAVOUR_8_ADTEXT": { "description": "", - "message": "БЛИЗКА ДОСТАВКА. Нуждая се от бърза доставка на артикул до {starport}." + "message": "БЛИЗКА ДОСТАВКА: Нуждая се от бърза доставка на артикул до {starport}." }, "FLAVOUR_8_FAILUREMSG": { "description": "", - "message": "Имаш премия за бързата доставка! Отказвам да ти платя." + "message": "Трябваше да получиш премия за бърза доставка! Отказвам да ти платя." }, "FLAVOUR_8_INTROTEXT": { "description": "", @@ -237,7 +237,7 @@ }, "FLAVOUR_9_ADTEXT": { "description": "", - "message": "ОСТАВЯНЕ НА ПАКЕТ. Спешно изпращане на нетрайни стоки до {starport}." + "message": "ОСТАВЯНЕ НА ПАКЕТ: Спешно изпращане на нетрайни стоки до {starport}." }, "FLAVOUR_9_FAILUREMSG": { "description": "", @@ -325,11 +325,11 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "SPACEPORT": { "description": "", - "message": "Космическа станция:" + "message": "Космодрум:" }, "SYSTEM": { "description": "", @@ -341,7 +341,7 @@ }, "THIS_IS_VERY_RISKY_YOU_WILL_ALMOST_CERTAINLY_RUN_INTO_RESISTANCE": { "description": "", - "message": "Това е много рисковано, най-вероятно ще срещнете съпротива." + "message": "Това е много рисковано, най-вероятно ще срещнеш съпротива." }, "WHY_SO_MUCH_MONEY": { "description": "", diff --git a/data/lang/module-donatetocranks/bg.json b/data/lang/module-donatetocranks/bg.json index 39230e50a7a..e5442a8d274 100644 --- a/data/lang/module-donatetocranks/bg.json +++ b/data/lang/module-donatetocranks/bg.json @@ -9,11 +9,11 @@ }, "FLAVOUR_1_MESSAGE": { "description": "", - "message": "Мир Вам, братко. Моля, изберете сума за дарение към Пазителите на Безплатния Дух." + "message": "Мир на теб, братко. Моля, избери сума за дарение към Пазителите на Безплатния Дух." }, "FLAVOUR_1_TITLE": { "description": "", - "message": "ДАРЯВАЙ. Пазителите на Безплатния Дух смирено молят за Вашата милостиня за да поддържат нашите манастири." + "message": "ДАРЯВАЙТЕ. Пазителите на Безплатния Дух смирено молят за Вашата милостиня за да поддържат нашите манастири." }, "FLAVOUR_2_MESSAGE": { "description": "", @@ -21,7 +21,7 @@ }, "FLAVOUR_2_TITLE": { "description": "", - "message": "ЧУВСТВАТЕ СЕ ЩЕДЪР? Подкрепа за Военните Сираци се нуждае от Вашата помощ за да продължи да функционира." + "message": "ЧУВСТВАТЕ СЕ ЩЕДЪР? Подкрепа за Военните Сираци се нуждае от твоята помощ за да продължи да функционира." }, "FLAVOUR_3_MESSAGE": { "description": "", diff --git a/data/lang/module-easteregg-message/bg.json b/data/lang/module-easteregg-message/bg.json index f790ab33feb..7e6d8be4d22 100644 --- a/data/lang/module-easteregg-message/bg.json +++ b/data/lang/module-easteregg-message/bg.json @@ -1,7 +1,7 @@ { "FLAVOUR_0_BODY": { "description": "This is a very rare string, that's part of an 'Easter egg'. This specific one is a reference to the song by AC/DC", - "message": "Обадете се на 36 24 36, аз съм къщно пиле. Занимавам се с:\n- Бетонни обувки,\n- Цианид,\n- TNT,\n- Вратовръзки,\n- Договори,\n- Високо напрежение,\n\n ...или просто ми се обадете да си приказваме." + "message": "Обадете се на 36 24 36, винаги съм вкъщи. Занимавам се с:\n- Бетонни обувки,\n- Цианид,\n- TNT,\n- Вратовръзки,\n- Договори,\n- Високо напрежение,\n\n ...или просто ми се обадете да си приказваме." }, "FLAVOUR_0_TITLE": { "description": "The 'all caps' title should probably not be translated, as it's an AC/DC song title reference. Either way, it's a very rare 'Easter egg'", diff --git a/data/lang/module-fuelclub/es.json b/data/lang/module-fuelclub/es.json index c83fd6b7dea..2e8c0b7688c 100644 --- a/data/lang/module-fuelclub/es.json +++ b/data/lang/module-fuelclub/es.json @@ -33,7 +33,7 @@ }, "FLAVOUR_2_CLUBNAME": { "description": "Fuel club for the CIW (Commonwealth of Independent Worlds) faction", - "message": "The Commonwealth Fuel Union" + "message": "La Mancomunidad Unida de Fuel" }, "FLAVOUR_2_NONMEMBER_INTRO": { "description": "Commonwealth of Independent Worlds is the name of the CIW faction", diff --git a/data/lang/module-goodstrader/bg.json b/data/lang/module-goodstrader/bg.json index cd13a90f349..43787508242 100644 --- a/data/lang/module-goodstrader/bg.json +++ b/data/lang/module-goodstrader/bg.json @@ -1,7 +1,7 @@ { "GOODS_TRADER_0": { "description": "", - "message": "Универмаг на {name}" + "message": "Универсален Магазин на {name}" }, "GOODS_TRADER_1": { "description": "", @@ -21,7 +21,7 @@ }, "GOODS_TRADER_5": { "description": "", - "message": "{name} & Синове" + "message": "{name} и Синове" }, "SLOGAN_0": { "description": "", diff --git a/data/lang/module-newseventcommodity/bg.json b/data/lang/module-newseventcommodity/bg.json index b899755bcd6..db75098f9eb 100644 --- a/data/lang/module-newseventcommodity/bg.json +++ b/data/lang/module-newseventcommodity/bg.json @@ -13,7 +13,7 @@ }, "FLAVOUR_10_NEWSBODY": { "description": "Imply high demand of AIR_PROCESSORS commodity. (Prekall as in Rekall, the fictional company from the Schwarzenegger-movie Total Recall (1990)).", - "message": "Prekall Inc. искат да монополизират въздуха в {system} ({sectorx}, {sectory}, {sectorz}). Поемете дълбоко въздух, защото може да е последния безплатен." + "message": "Фирмата Прикал иска да монополизира въздуха в {system} ({sectorx}, {sectory}, {sectorz}). Поемете дълбоко въздух, защото може да е последния безплатен." }, "FLAVOUR_11_HEADLINE": { "description": "", @@ -125,7 +125,7 @@ }, "FLAVOUR_23_NEWSBODY": { "description": "Imply high demand of METAL_ALLOYS. Amissionox is a play on words for Victorinox.", - "message": "Новата фабрика Amissionox в системата {system} ({sectorx}, {sectory}, {sectorz}) вече работи. Тя ще произвежда висококачествени ножове, способни да отрежат космически ботуш, но поради липса на достатъчно материали за направата на остриетата, все още не е достигнала пълния си производствен потенциал." + "message": "Новата фабрика Амисионокс в системата {system} ({sectorx}, {sectory}, {sectorz}) вече работи. Тя ще произвежда висококачествени ножове, способни да отрежат космически ботуш, но поради липса на достатъчно материали за направата на остриетата, все още не е достигнала пълния си производствен потенциал." }, "FLAVOUR_2_HEADLINE": { "description": "", @@ -217,59 +217,59 @@ }, "NEWSPAPER_CIW": { "description": "", - "message": "The Commonwealth Chronicle" + "message": "Обществената Хроника" }, "NEWSPAPER_FED": { "description": "", - "message": "The Federal Times" + "message": "Федералните Времена" }, "NEWSPAPER_IMP": { "description": "", - "message": "The Imperial Herald" + "message": "Имперският Вестител" }, "NEWSPAPER_IND_0": { "description": "", - "message": "The Pioneer Courier" + "message": "Пионерският Куриер" }, "NEWSPAPER_IND_1": { "description": "", - "message": "The Independent Tribune" + "message": "Независимата Трибуна" }, "NEWSPAPER_IND_10": { "description": "", - "message": "The Orbital Observer" + "message": "Орбиталният Наблюдател" }, "NEWSPAPER_IND_2": { "description": "", - "message": "The Galactic Post" + "message": "Галактическата Служба" }, "NEWSPAPER_IND_3": { "description": "", - "message": "The Universal Sun" + "message": "Универсалното Слънце" }, "NEWSPAPER_IND_4": { "description": "", - "message": "The Planetary Press" + "message": "Планетарната Преса" }, "NEWSPAPER_IND_5": { "description": "", - "message": "The Royal Gazette" + "message": "Кралският Вестник" }, "NEWSPAPER_IND_6": { "description": "", - "message": "The Universal Mail" + "message": "Универсалната Поща" }, "NEWSPAPER_IND_7": { "description": "", - "message": "The Daily Express" + "message": "Ежедневникът" }, "NEWSPAPER_IND_8": { "description": "", - "message": "The Tellurian Telegraph" + "message": "Телурският Телеграф" }, "NEWSPAPER_IND_9": { "description": "", - "message": "The Satellite Journal" + "message": "Сателитният Дневник" }, "TITLE_0": { "description": "", diff --git a/data/lang/module-newseventcommodity/es.json b/data/lang/module-newseventcommodity/es.json index 594c5f1c09a..beee547c974 100644 --- a/data/lang/module-newseventcommodity/es.json +++ b/data/lang/module-newseventcommodity/es.json @@ -37,15 +37,15 @@ }, "FLAVOUR_13_NEWSBODY": { "description": "Imply that nobody wants to buy ROBOTS anymore.", - "message": "It is now man against machine in the {system} system ({sectorx}, {sectory}, {sectorz}), as \"behavioural malfunction\" causes home consumers to lose faith in robot servants." + "message": "Ahora es el hombre contra la máquina en el sistema {system} ({sectorx}, {sectory}, {sectorz}), ya que el \"mal funcionamiento del comportamiento\" hace que los consumidores domésticos pierdan confianza en los servidores robóticos." }, "FLAVOUR_14_HEADLINE": { "description": "", - "message": "NEWS {date}: Solar flare causes biggest blackout in a millennium in the {system} system." + "message": "NOTICIAS {date}: Una erupción solar causa el mayor apagón del milenio en el sistema {system}." }, "FLAVOUR_14_NEWSBODY": { "description": "Avoid using word Tupperware, say tuppenware, blooperware, tooperwar or plastic containers etc. If translation doesn't work, feel free to be creative, as long as it is implying a high demand of PLASTICS.", - "message": "The system wide power outage wrecks havoc to the {system} system ({sectorx}, {sectory}, {sectorz}). Consumers line up to buy the last Trapperware to replace their fridges, as the producer has run out of raw material." + "message": "Un corte de energía total causa estragos en el sistema {system} ({sectorx}, {sectory}, {sectorz}). Los consumidores hacen fila para comprar el último \"Trapperware\" para reemplazar sus refrigeradores, ya que el fabricante se ha quedado sin materia prima." }, "FLAVOUR_15_HEADLINE": { "description": "", @@ -61,7 +61,7 @@ }, "FLAVOUR_16_NEWSBODY": { "description": "Imply high demand of FARM_MACHINERY.", - "message": "During the Great Steam Fair in the {system} system ({sectorx}, {sectory}, {sectorz}) an attempt for the galactic record in the biggest tractor pulling contest ended in mayhem as one of the contestants lost control of his contraption, destroying all other participants' machines. Administration says it could spell doom for the local farmers." + "message": "Durante la Gran Feria del Vapor en el sistema {system} ({sectorx}, {sectory}, {sectorz}), un intento por lograr el récord galáctico en el mayor concurso de de tractores terminó en un caos cuando uno de los participantes perdió el control de su artilugio, destruyendo las máquinas de todos los demás participantes. La administración declara que esto podría significar la ruina para los agricultores locales." }, "FLAVOUR_17_HEADLINE": { "description": "", @@ -157,7 +157,7 @@ }, "FLAVOUR_5_NEWSBODY": { "description": "Imply high demand of SLAVES.", - "message": "Workers in the {system} system ({sectorx}, {sectory}, {sectorz}) have cast off their chains in rebellion as they refuse to work the Lotus fields. Economy comes to a standstill as no cheap workers can be found." + "message": "Trabajadores del sistema {system} ({sectorx}, {sectory}, {sectorz}) se han liberado de sus cadenas en plena rebelión al negarse a trabajar en los campos de Loto. La economía se paraliza porque no se puede encontrar mano de obra barata." }, "FLAVOUR_6_HEADLINE": { "description": "(Quibble as a derivative of Tribble from Star Trek TOS)", @@ -217,7 +217,7 @@ }, "NEWSPAPER_CIW": { "description": "", - "message": "The Commonwealth Chronicle" + "message": "La Crónica de la Mancomunidad" }, "NEWSPAPER_FED": { "description": "", diff --git a/data/lang/module-searchrescue/bg.json b/data/lang/module-searchrescue/bg.json index 604de8701f6..bc17cdbe1b9 100644 --- a/data/lang/module-searchrescue/bg.json +++ b/data/lang/module-searchrescue/bg.json @@ -1,7 +1,7 @@ { "ACCIDENT_DESTROYED_TARGET": { "description": "", - "message": "До нас достигна тъжната новина, че {shiplabel} е унищожен. Ще платим половината от уговорената цена за твоите усилия." + "message": "До нас достигна тъжната новина, че {shiplabel} е унищожен. Ще платим половината от уговорената цена за Вашите усилия." }, "AU": { "description": "", @@ -69,7 +69,7 @@ }, "ENTITY_FAMILY_BUSINESS_7": { "description": "", - "message": "{name} & {name}" + "message": "{name} и {name}" }, "ENTITY_FAMILY_BUSINESS_8": { "description": "", @@ -113,11 +113,11 @@ }, "ENTITY_GENERAL_8": { "description": "", - "message": "{locality} iSatellite ООД" + "message": "{locality} АзСателитът ООД" }, "ENTITY_GENERAL_9": { "description": "", - "message": "Корпорация за Покребални Услуги {locality}" + "message": "Корпорация за Погребални Услуги {locality}" }, "ENTITY_RESEARCH_1": { "description": "", @@ -161,123 +161,123 @@ }, "EQUIPMENT": { "description": "", - "message": "You are not equipped to handle this mission. {unit} {equipment} required." + "message": "Не си подготвен за тази мисия. Нуждаеш се от {unit} {equipment}." }, "FLAVOUR_1_ADTEXT": { "description": "", - "message": "SHIP CRASH LANDED on {planet}." + "message": "КОРАБ СЕ Е РАЗБИЛ на {planet}." }, "FLAVOUR_1_FAILUREMSG": { "description": "", - "message": "I can't believe you are just returning now! How much time has been wasted!" + "message": "Не мога да повярвам, че се връщаш чак сега! Изгубихме толкова време!" }, "FLAVOUR_1_HOWMUCHTIMETEXT": { "description": "", - "message": "For full reimbursement of expenses you have to be back by {due}." + "message": "За пълно възстановяване на сумата, трябва да се върнеш до {due}." }, "FLAVOUR_1_INTROTEXT": { "description": "", - "message": "{starport} air traffic control needs your IMMEDIATE help responding to a crash landing of a {ship} type starship on {planet}. Status of life support systems is unknown. The ship has been insured by {starport} starport insurance and is covered for {cash} in emergency response reimbursement." + "message": "Диспечерите от {starport} се нуждаят от СПЕШНА помощ, във връзка с {ship} кораб, който се е разбил на {planet}. Не е ясно дали има оцелели от катастрофата. Корабът е застрахован от космодрума {starport} за сумата от {cash} за спешни ситуации." }, "FLAVOUR_1_LOCATIONTEXT": { "description": "", - "message": "Last known location for this ship was {planet} at latitude/longitude coordinates: {lat} / {long}. Ship ID is {shiplabel}." + "message": "Последното известно местоположение на този кораб е на {planet}, на следната географска ширина/дължина: {lat} / {long}. Номерът на кораба е {shiplabel}." }, "FLAVOUR_1_SUCCESSMSG": { "description": "", - "message": "Thank you, this is a great relief! We will transmit the money momentarily." + "message": "Благодаря, това е голямо облекчение! Ще преведем парите моментално." }, "FLAVOUR_1_TRANSFERMSG": { "description": "", - "message": "{unit} has boarded the ship." + "message": "{unit} се качи на кораба." }, "FLAVOUR_1_TYPEOFHELPTEXT": { "description": "", - "message": "A crew of {crew} and {pass} passengers are reported to be on board the ship. We need someone to locate the ship, pick up any survivors from the site and bring them here immediately." + "message": "Корабът има {crew} членен екипаж и {pass} пасажера. Някой трябва да го намери и да върне обратно оцелелите хора, ако има такива." }, "FLAVOUR_2_ADTEXT": { "description": "", - "message": "SHIP OUT OF FUEL en route to {starport}." + "message": "КОРАБ ОСТАНА БЕЗ ГОРИВО на път за {starport}." }, "FLAVOUR_2_FAILUREMSG": { "description": "", - "message": "I can't believe you kept me waiting out here this long! Forget about your payment!" + "message": "Не мога да повярвам, че ме накара да чакам толкова време! Няма да получиш нищо." }, "FLAVOUR_2_HOWMUCHTIMETEXT": { "description": "", - "message": "To receive full payment you are asked to deliver the fuel by {due}." + "message": "За получиш пълното си възнаграждение, трябва да доставиш горивото до {due}." }, "FLAVOUR_2_INTROTEXT": { "description": "", - "message": "{starport} air traffic control just received notice that incoming flight {shiplabel} has run out of fuel and had to emergency land. The pilot is willing to pay {cash} for refueling services." + "message": "Диспечерите от {starport} току-що получиха известие, че пристигащият {shiplabel} е останал без гориво и е извършил аварийно приземяване. Пилотът е готов да плати {cash} за презареждането." }, "FLAVOUR_2_LOCATIONTEXT": { "description": "", - "message": "The ship is presently waiting at latitude {lat} / longitude {long} on planet {planet}." + "message": "Корабът се намира на географска ширина {lat} / географска дължина {long} на планетата {planet}." }, "FLAVOUR_2_SUCCESSMSG": { "description": "", - "message": "Thank you so much! I have transferred the full reward." + "message": "Много Ви благодаря! Преведох пълното възнаграждение по сметката Ви." }, "FLAVOUR_2_TRANSFERMSG": { "description": "", - "message": "{unit} ton of fuel has been transferred." + "message": "{unit} тон гориво е прехвърлен." }, "FLAVOUR_2_TYPEOFHELPTEXT": { "description": "", - "message": "The pilot is requesting {unit} tons of {cargo}." + "message": "Пилотът желае {unit} тона {cargo}." }, "FLAVOUR_3_ADTEXT": { "description": "", - "message": "MEDICAL EMERGENCY on ship close to {starport}." + "message": "СПЕШНА НУЖДА ОТ ЛЕКАР, на кораб, близо до {starport}." }, "FLAVOUR_3_FAILUREMSG": { "description": "", - "message": "Unacceptable performance! We will update our records accordingly." + "message": "Неприемливо представяне! Ще имаме едно наум за в бъдеще." }, "FLAVOUR_3_HOWMUCHTIMETEXT": { "description": "", - "message": "The substitute pilot will need to reach the ship by {due}." + "message": "Заместник-пилотът трябва да е в кораба до {due}." }, "FLAVOUR_3_INTROTEXT": { "description": "", - "message": "My name is {name} from {starport} air traffic control. I am requesting help in response to a medical emergency involving the pilot of flight {shiplabel} headed for {starport}." + "message": "Аз съм {name} от диспечерите в {starport}. Моля за помощ, във връзка със спешната нужда от лекар на полет {shiplabel} към {starport}." }, "FLAVOUR_3_LOCATIONTEXT": { "description": "", - "message": "The ship had to emergency land at the coordinates: {lat} / {long}. " + "message": "Корабът е извършил аварийно приземяване на следните координати: {lat} / {long}. " }, "FLAVOUR_3_SUCCESSMSG": { "description": "", - "message": "Thank you, commander! Your help has been duly noted." + "message": "Благодаря Ви, командире! Вашата помощ няма да бъде забравена." }, "FLAVOUR_3_TRANSFERMSG": { "description": "", - "message": "{unit} has left the ship." + "message": "{unit} напусна кораба." }, "FLAVOUR_3_TYPEOFHELPTEXT": { "description": "", - "message": "Please transport a substitute pilot from {starport} to the ship so they can fly the ship back to {starport}." + "message": "Моля, транспортирайте заместник-пилота от {starport} към бедстващия кораб, за да бъде завършен полета до {starport}." }, "FLAVOUR_4_ADTEXT": { "description": "", - "message": "SHIP OUT OF FUEL on {planet}." + "message": "КОРАБ ОСТАНА БЕЗ ГОРИВО на {planet}." }, "FLAVOUR_4_FAILUREMSG": { "description": "", - "message": "I will send someone else. Don't bother anymore." + "message": "Ще изпратя някой друг. Не се занимавай повече." }, "FLAVOUR_4_HOWMUCHTIMETEXT": { "description": "", - "message": "For full pay the pilot expects you to deliver the fuel by {due}." + "message": "За получите пълното си възнаграждение, пилотът очаква да доставиш горивото му до {due}." }, "FLAVOUR_4_INTROTEXT": { "description": "", - "message": "{starport} air traffic control has been contacted by the pilot of flight {shiplabel}. They are stranded with an empty fuel tank and have promised to pay {cash} to anyone that will refuel the ship." + "message": "Диспечерите от {starport} получиха съобщение от полет {shiplabel}, според което техният кораб е останал без гориво и пилотът е готов да плати {cash} на всеки, който може да презареди кораба." }, "FLAVOUR_4_LOCATIONTEXT": { "description": "", - "message": "The ship is stranded on {planet} at coordinates {lat} / {long}." + "message": "Корабът е заседнал на следните координати {lat} / {long} на {planet}." }, "FLAVOUR_4_SUCCESSMSG": { "description": "", @@ -285,119 +285,119 @@ }, "FLAVOUR_4_TRANSFERMSG": { "description": "", - "message": "{unit} ton of fuel has been transferred." + "message": "{unit} тон гориво е прехвърлен." }, "FLAVOUR_4_TYPEOFHELPTEXT": { "description": "", - "message": "The pilot is asking for {unit} tons of {cargo}." + "message": "Пилотът иска {unit} тона {cargo}." }, "FLAVOUR_5_ADTEXT": { "description": "", - "message": "SHIP OUT OF FUEL close to {starport}." + "message": "КОРАБ ОСТАНА БЕЗ ГОРИВО близо до {starport}." }, "FLAVOUR_5_FAILUREMSG": { "description": "", - "message": "People are just not dependable anymore." + "message": "В днешно време не можеш да имаш доверие на никого." }, "FLAVOUR_5_HOWMUCHTIMETEXT": { "description": "", - "message": "Please complete refueling by {due}." + "message": "Моля, завърши презареждането до {due}." }, "FLAVOUR_5_INTROTEXT": { "description": "", - "message": "{starport} air traffic control has identified a starship with ID {shiplabel} drifting without fuel close-by. We will pay {cash} to anyone who will refuel the ship so they can vacate {starport} vicinity." + "message": "Диспечерите от {starport} идентифицираха кораб с номер {shiplabel}, носещ се без гориво в близост до {starport}. Ще бъдат изплатени {cash} на всеки, който може да презареди кораба." }, "FLAVOUR_5_LOCATIONTEXT": { "description": "", - "message": "The target ship is currently drifting within {dist} km from here. You will have to track down the exact location yourself." + "message": "В момента, целевият кораб, е на {dist} км. от тук. Трябва сами да откриеш точното му местоположение." }, "FLAVOUR_5_SUCCESSMSG": { "description": "", - "message": "We will make record of your timely completion of the task." + "message": "Няма да забравим за Вашите бързи и точни действия." }, "FLAVOUR_5_TRANSFERMSG": { "description": "", - "message": "{unit} ton of fuel has been transferred." + "message": "{unit} тон гориво е прехвърлен." }, "FLAVOUR_5_TYPEOFHELPTEXT": { "description": "", - "message": "We request the delivery of {unit} tons of {cargo} to the ship." + "message": "Желаем доставката на {unit} тона {cargo} на кораба." }, "FLAVOUR_6_ADTEXT": { "description": "", - "message": "VESSEL UNRESPONSIVE in the {system} system." + "message": "ИЗГУБЕН Е КОНТАКТ С КОРАБ в системата {system}." }, "FLAVOUR_6_FAILUREMSG": { "description": "", - "message": "What a disaster! This is the death sentence to our poor colleagues!" + "message": "Какво бедствие! Това е смъртна присъда за нашите бедни колеги!" }, "FLAVOUR_6_HOWMUCHTIMETEXT": { "description": "", - "message": "You have to be back by {due}." + "message": "Трябва да се върнеш до {due}." }, "FLAVOUR_6_INTROTEXT": { "description": "", - "message": "My name is {name} of {entity}. We lost contact with our {ship} {shiplabel} following {problem}. We are willing to pay {cash} for immediate help." + "message": "Аз съм {name} от {entity}. Изгубихме връзка с нашия {ship} {shiplabel}, поради {problem}. Имаме неотложна нужда от помощ и сме готови да платим {cash}." }, "FLAVOUR_6_LOCATIONTEXT": { "description": "", - "message": "Last known position was the vicinity of {planet} in the {system} [{sectorx},{sectory},{sectorz}] system, {dist} ly away from here." + "message": "Последните получени данни са от {planet} в системата {system} [{sectorx},{sectory},{sectorz}], на разстояние от {dist} сг." }, "FLAVOUR_6_SUCCESSMSG": { "description": "", - "message": "Thank you! You can't imagine how relieved we are." + "message": "Благодарим Ви! Не можете да си представите какво облекчение изпитваме." }, "FLAVOUR_6_TRANSFERMSG": { "description": "", - "message": "{unit} has boarded the ship." + "message": "{unit} се качи на кораба." }, "FLAVOUR_6_TYPEOFHELPTEXT": { "description": "", - "message": "I need someone willing to leave immediately and bring our colleagues back to {starport}, should they be alive. The ship had {crew} crew and {pass} passengers on board." + "message": "Нуждая се от някой, който да върне веднага нашите колеги в {starport}, ако са все още живи. Корабът има {crew} членен екипаж и {pass} пасажера." }, "FLAVOUR_7_ADTEXT": { "description": "", - "message": "IMMEDIATE CREW TRANSPORT to the {system} system requested." + "message": "НЕОТЛОЖЕН ТРАНСПОРТ НА ЕКИПАЖ до системата {system}." }, "FLAVOUR_7_FAILUREMSG": { "description": "", - "message": "Thank you very much, but you are too late!" + "message": "Благодаря Ви много, но вече е прекалено късно!" }, "FLAVOUR_7_HOWMUCHTIMETEXT": { "description": "", - "message": "The replacement crew has to reach the ship by {due}." + "message": "Новият екипаж трябва да е в кораба до {due}." }, "FLAVOUR_7_INTROTEXT": { "description": "", - "message": "My name is {name} of {entity}. Our only ship, {ship} {shiplabel}, is drifting with a crew of {crew} after {problem}. I am willing to pay {cash} for immediate help." + "message": "Аз съм {name} от {entity}. Единственият ни кораб, {ship} {shiplabel}, се носи безконтролно с {crew} членен екипаж, след {problem}. Имаме неотложна нужда от помощ и сме готови да платим {cash}." }, "FLAVOUR_7_LOCATIONTEXT": { "description": "", - "message": "You will find the ship in the {system} [{sectorx},{sectory},{sectorz}] system, {dist} ly from here. It is being kept in orbit around {planet}." + "message": "Ще намериш кораба в системата {system} [{sectorx},{sectory},{sectorz}], на разстояние от {dist} сг. Той е в орбита около {planet}." }, "FLAVOUR_7_SUCCESSMSG": { "description": "", - "message": "Thank you! I have been authorized to transmit the full payment." + "message": "Благодаря Ви! Упълномощен съм да Ви предам пълното възнаграждение." }, "FLAVOUR_7_TRANSFERMSG": { "description": "", - "message": "{unit} has transferred to the target ship." + "message": "{unit} се прехвърли на целевия кораб." }, "FLAVOUR_7_TYPEOFHELPTEXT": { "description": "", - "message": "We can't return the ship without minimal crew present. I am searching for someone willing to transport a replacement crew of {deliver_crew} to our starship immediately." + "message": "Не можем да върнем кораба с толкова малък екипаж. Търся някой, който да транспортира {deliver_crew} заместници, които да запълнят празните места веднага." }, "FULL_CARGO": { "description": "", - "message": "Ship full. No more room for additional cargo." + "message": "Корабът е пълен. Няма повече товарно място." }, "FULL_CREW": { "description": "", - "message": "Crew roster full. No more space for more crew." + "message": "Корабът е пълен. Няма повече места за екипажа." }, "FULL_PASSENGERS": { "description": "", - "message": "All cabins full. No more space for more passengers." + "message": "Корабът е пълен. Няма повече места за пасажерите." }, "HOW_FAR": { "description": "", @@ -409,11 +409,11 @@ }, "INTERACTION_ABORTED": { "description": "", - "message": "Interaction aborted. Please come closer and try again." + "message": "Взаимодействието е прекъснато. Моля, приближете се и опитайте отново." }, "INTERACTION_DISTANCE_REACHED": { "description": "", - "message": "Interaction distance reached." + "message": "Достигнато е разстоянието за взаимодействие." }, "IT_MUST_BE_COMPLETED_BY": { "description": "", @@ -441,19 +441,19 @@ }, "MISSING_COMM": { "description": "", - "message": "Cannot complete transfer. {cargotype} missing." + "message": "Прехвърлянето не може да бъде завършено. Липсва {cargotype}." }, "MISSING_CREW": { "description": "", - "message": "Cannot complete transfer. Crew missing." + "message": "Прехвърлянето не може да бъде завършено. Екипажът липсва." }, "MISSING_PASS": { "description": "", - "message": "Cannot complete transfer. Passengers missing." + "message": "Прехвърлянето не може да бъде завършено. Пасажерите липсват." }, "MISSING_PASSENGER": { "description": "", - "message": "Cannot complete transfer. Passenger missing." + "message": "Прехвърлянето не може да бъде завършено. Пасажерът липсва." }, "OK_AGREED": { "description": "", @@ -465,7 +465,7 @@ }, "PARTIAL": { "description": "", - "message": "Thank you for your efforts. I hope you will return to complete the task!" + "message": "Благодарим Ви за усилията. Надявам се, че ще се върнете за да довършите започнатото." }, "PASSENGERS": { "description": "", @@ -477,163 +477,163 @@ }, "PICKUP": { "description": "", - "message": "PICKUP" + "message": "ВЗЕМАНЕ" }, "PLACE_OF_ASSISTANCE": { "description": "", - "message": "At the place of assistance" + "message": "На оказаното място" }, "PLAYER_DESTROYED_TARGET": { "description": "", - "message": "We have heard of your deeds, captain! Rest assured that we will report you to the local authorities for destroying the very ship you were sent out to help. A criminal lawsuit will follow." + "message": "Чували сме за теб, капитане! Ще те докладваме на властите за това, че унищожи кораба, на който трябваше да помогнеш. Очаква те наказателно дело." }, "PLEASE_LAND": { "description": "", - "message": "Please land ship to allow transfer." + "message": "Моля, приземете кораба за да се осъществи прехвърлянето." }, "PROBLEM_CREW_1": { "description": "", - "message": "a deadly fight among the crew members" + "message": "е имало битка до смърт между членовете на екипажа" }, "PROBLEM_CREW_10": { "description": "", - "message": "a mutiny" + "message": "е имало бунт" }, "PROBLEM_CREW_2": { "description": "", - "message": "the crew had to chase a deadly {locality} snake found loose on the ship" + "message": "членовете на екипажа е трябвало да изгонят смъртоносна {locality} змия от кораба си" }, "PROBLEM_CREW_3": { "description": "", - "message": "a {locality} spider killed all the others" + "message": "{locality} паяк е убил всички останали" }, "PROBLEM_CREW_4": { "description": "", - "message": "what it seems like a {locality} scorpion got into the crew quarters at night" + "message": "нещо като {locality} скорпион е влязъл в жилищната част на екипажа през нощта" }, "PROBLEM_CREW_5": { "description": "", - "message": "a severe form of {locality} fever killed the others" + "message": "тежка форма на {locality} треска е убила останалите" }, "PROBLEM_CREW_6": { "description": "", - "message": "the other crew members did not return from a space walk" + "message": "останалите членове на екипажа не са се върнали от космическата разходка" }, "PROBLEM_CREW_7": { "description": "", - "message": "a severe form of food poisoning on the ship" + "message": "е имало тежка форма на хранително отравяне в кораба" }, "PROBLEM_CREW_8": { "description": "", - "message": "a terrible accident that lead to the ejection of the others into space" + "message": "тежък инцидент е довел до изстрелването на останалите в космоса" }, "PROBLEM_CREW_9": { "description": "", - "message": "a circumstance that I can't comment on publicly" + "message": "има нещо, за което не мога да коментирам публично" }, "PROBLEM_GENERAL_1": { "description": "", - "message": "a fire in the cargo hold" + "message": "е имало пожар в товарното отделение" }, "PROBLEM_GENERAL_10": { "description": "", - "message": "the receipt of a distress call from within {locality}" + "message": "е получен сигнал за бедствие от {locality}" }, "PROBLEM_GENERAL_2": { "description": "", - "message": "a power failure in the engine core" + "message": "е имало късо съединение в ядрото на двигателя" }, "PROBLEM_GENERAL_3": { "description": "", - "message": "an air leak" + "message": "е имало изтичане на въздух" }, "PROBLEM_GENERAL_4": { "description": "", - "message": "a severe form of food poisoning involving all personnel on board the ship" + "message": "всеки в кораба е имал тежка форма на хранително отравяне" }, "PROBLEM_GENERAL_5": { "description": "", - "message": "a small meteor impact" + "message": "е имало малък метеоритен сблъсък" }, "PROBLEM_GENERAL_6": { "description": "", - "message": "a fight among crew members" + "message": "е имало битка между членовете на екипажа" }, "PROBLEM_GENERAL_7": { "description": "", - "message": "contact with an unidentified flight object" + "message": "е имало контакт с НЛО" }, "PROBLEM_GENERAL_8": { "description": "", - "message": "a dispute with a competitor's vessel" + "message": "е имало спор с конкурентен кораб" }, "PROBLEM_GENERAL_9": { "description": "", - "message": "a reboot of the main computer" + "message": "е имало рестартиране на главния компютър" }, "PROBLEM_RESEARCH_1": { "description": "", - "message": "an unexpected chemical reaction in one of the reaction chambers" + "message": "е имало неочаквана химична реакция в една от реакционните камери" }, "PROBLEM_RESEARCH_10": { "description": "", - "message": "a major discovery at {locality} that I am not at liberty to disclose at this time" + "message": "е имало важно откритие в {locality}, за което не мога да коментирам в момента" }, "PROBLEM_RESEARCH_2": { "description": "", - "message": "an infection of a crew member with a pathogen local to {locality}" + "message": "е имало инфекция на член от екипажа с патоген от {locality}" }, "PROBLEM_RESEARCH_3": { "description": "", - "message": "a leak of experimental pathogens into the main air supply" + "message": "е имало теч на експериментални патогени в главното въздушно захранване" }, "PROBLEM_RESEARCH_4": { "description": "", - "message": "crew exposure to a specimen collected at {locality}" + "message": "екипажът е бил подложен на екземпляр от {locality}" }, "PROBLEM_RESEARCH_5": { "description": "", - "message": "a chemical explosion in one of the on-board fume hoods" + "message": "е имало химична експлозия в един от аспираторите на кораба" }, "PROBLEM_RESEARCH_6": { "description": "", - "message": "an experimental recreation of {locality} atmospheric gases" + "message": "е имало експериментално пресъздаване на атмосферни газове от {locality}" }, "PROBLEM_RESEARCH_7": { "description": "", - "message": "a heated dispute between scientists on board the ship" + "message": "е имало разгорещен спор между учените в кораба" }, "PROBLEM_RESEARCH_8": { "description": "", - "message": "the sudden disappearance of a lead investigator on board the ship" + "message": "внезапно изчезва главен следовател от кораба" }, "PROBLEM_RESEARCH_9": { "description": "", - "message": "the accidental combination of incompatible specimens from {locality}" + "message": "е имало случайна комбинация между несъвместими екземпляри от {locality}" }, "RESULT_DELIVERY_COMM": { "description": "", - "message": "Transferred {done} of {todo} tons of {cargotype} to target ship." + "message": "Към целевия кораб са прехвърлени {done} тона {cargotype} от {todo}." }, "RESULT_DELIVERY_CREW": { "description": "", - "message": "Transferred {done} of {todo} crew members to target ship." + "message": "Към целевия кораб са прехвърлени {done} членове на екипажа от {todo}." }, "RESULT_DELIVERY_PASS": { "description": "", - "message": "Transferred {done} of {todo} passengers to target ship." + "message": "Към целевия кораб са прехвърлени {done} пасажера от {todo}." }, "RESULT_PICKUP_COMM": { "description": "", - "message": "Picked up {done} of {todo} tons of {cargotype} from target ship." + "message": "От целевия кораб са качени {done} тона {cargotype} от {todo}." }, "RESULT_PICKUP_CREW": { "description": "", - "message": "Picked up {done} of {todo} crew members from target ship." + "message": "От целевия кораб са качени {done} членове на екипажа от {todo}." }, "RESULT_PICKUP_PASS": { "description": "", - "message": "Picked up {done} of {todo} passengers from target ship." + "message": "От целевия кораб са качени {done} пасажера от {todo}." }, "RETURN_TO": { "description": "", @@ -649,15 +649,15 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "SET_RETURN_ROUTE": { "description": "", - "message": "Задайте маршрут за връщане" + "message": "Задай маршрут за връщане" }, "SHIP_UNRESPONSIVE": { "description": "", - "message": "Target ship unresponsive." + "message": "Целевият кораб не отговаря." }, "SYSTEM": { "description": "", @@ -665,42 +665,42 @@ }, "TARGET_SHIP_ID": { "description": "", - "message": "Target ship ID:" + "message": "Номер на целевия кораб:" }, "THANK_YOU_ACCEPTANCE_TXT": { "description": "", - "message": "Thank you so much. Your help is greatly appreciated." + "message": "Много Ви благодаря. Вашата помощ е високо оценена." }, "TONS_OF_FREE_CARGO_SPACE": { "description": "", - "message": "tons of free cargo space" + "message": "тона свободно товарно пространство" }, "TRANSFER_ABORTED": { "description": "", - "message": "Transfer has been aborted!" + "message": "Прехвърлянето е прекратено!" }, "TRANSFER_COMPLETE": { "description": "", - "message": "Transfer has been completed!" + "message": "Прехвърлянето е завършено!" }, "TRANSFER_PARTIAL": { "description": "", - "message": "Transfer has been partially completed. Please return to finish transfer." + "message": "Прехвърлянето е частично завършено. Моля, свършете си работата докрай." }, "TRANSFER_TIME": { "description": "", - "message": "Please allow {minutes} minutes for transfer." + "message": "Моля, отделете {minutes} минути за прехвърлянето." }, "TYPE_OF_HELP": { "description": "", - "message": "What type of help is needed?" + "message": "Какъв вид помощ е необходима?" }, "UNOCCUPIED_PASSENGER_CABINS": { "description": "", - "message": "unoccupied passenger cabins" + "message": "незаети пасажерски кабини" }, "WHERE_IS_THE_TARGET": { "description": "", - "message": "Къде да търся целта?" + "message": "Къде да намеря целта?" } } diff --git a/data/lang/module-secondhand/bg.json b/data/lang/module-secondhand/bg.json index bb1e50bf9e8..078279e4073 100644 --- a/data/lang/module-secondhand/bg.json +++ b/data/lang/module-secondhand/bg.json @@ -17,15 +17,15 @@ }, "FLAVOUR_1_BODY": { "description": "", - "message": "Здрасти! Казвам се {name}. Имам {equipment} без драскотина, продавам за {price}." + "message": "Здрасти! Казвам се {name}. Имам {equipment}, без драскотина, продавам само за {price}." }, "FLAVOUR_1_TITLE": { "description": "Selling second hand ship equipment", - "message": "ПРОДАВАМ: {equipment} без драскотина на достъпна цена!" + "message": "ПРОДАВАМ: {equipment}, без драскотина, на достъпна цена!" }, "FLAVOUR_2_BODY": { "description": "", - "message": "Здравейте! Казвам се {name} и имам {equipment} без драскотина, за Вас е само {price}." + "message": "Здравейте! Казвам се {name} и имам {equipment}, без драскотина, за Вас е само {price}." }, "FLAVOUR_2_TITLE": { "description": "Selling second hand ship equipment", @@ -45,7 +45,7 @@ }, "FLAVOUR_4_TITLE": { "description": "Selling second hand ship equipment", - "message": "ПРОДАВА СЕ: {equipment}, в добро състояние." + "message": "ПРОДАВА СЕ: {equipment} в добро състояние." }, "FLAVOUR_5_BODY": { "description": "", @@ -65,7 +65,7 @@ }, "REPEAT_OFFER": { "description": "", - "message": "Повтори офертата" + "message": "Повторете офертата" }, "YOU_DONT_HAVE_ENOUGH_MONEY": { "description": "", diff --git a/data/lang/module-statstracking/bg.json b/data/lang/module-statstracking/bg.json index 971c6d04c75..875d1873619 100644 --- a/data/lang/module-statstracking/bg.json +++ b/data/lang/module-statstracking/bg.json @@ -5,6 +5,6 @@ }, "WELL_DONE_COMMANDER_YOUR_COMBAT_RATING_HAS_IMPROVED": { "description": "", - "message": "Командир, добра работа! Бойната Ви репутация се подобри!" + "message": "Добра работа, командире! Бойната Ви репутация се подобри!" } } diff --git a/data/lang/module-system/bg.json b/data/lang/module-system/bg.json index 8af3f8fa79a..854be1e44f7 100644 --- a/data/lang/module-system/bg.json +++ b/data/lang/module-system/bg.json @@ -25,14 +25,14 @@ }, "GETTING_SENSOR_DATA": { "description": "Shown when entering an unexplored system", - "message": "Събиране и анализиране на системни данни..." + "message": "Събиране и анализиране на системните данни..." }, "YOUR_FUEL_TANK_IS_ALMOST_EMPTY": { "description": "", - "message": "Вашия резервоар за гориво е почти празен." + "message": "Вашият резервоар за гориво е почти празен." }, "YOUR_FUEL_TANK_IS_EMPTY": { "description": "", - "message": "Вашия резервоар за гориво е празен." + "message": "Вашият резервоар за гориво е празен." } } diff --git a/data/lang/module-taxi/bg.json b/data/lang/module-taxi/bg.json index 0cf06c0eccf..f8eddb87347 100644 --- a/data/lang/module-taxi/bg.json +++ b/data/lang/module-taxi/bg.json @@ -5,7 +5,7 @@ }, "CORPORATIONS_1": { "description": "", - "message": "ТОП" + "message": "Апогей" }, "CORPORATIONS_10": { "description": "", @@ -61,11 +61,11 @@ }, "DENY_0": { "description": "", - "message": "Съжалявам, но не мога да Ви се доверя." + "message": "Съжалявам, но не мога да ти се доверя." }, "DENY_1": { "description": "", - "message": "Върнете се, когато натрупате нужния опит." + "message": "Върни се, когато натрупаш нужния опит." }, "DENY_2": { "description": "", @@ -173,7 +173,7 @@ }, "FLAVOUR_11_FAILUREMSG": { "description": "", - "message": "Ще загубя работата си, заради твоята некомпетентност. Затова от мен пари няма да видиш." + "message": "Ще загубя работата си, заради твоята некомпетентност. Затова, от мен пари няма да видиш." }, "FLAVOUR_11_HOWMANY": { "description": "", @@ -549,7 +549,7 @@ }, "PIRATE_TAUNTS_0": { "description": "", - "message": "Ще съжалваш, че се занимаваш с {client}" + "message": "Ще съжаляваш, че се занимаваш с {client}" }, "PIRATE_TAUNTS_1": { "description": "", @@ -565,7 +565,7 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Задайте за навигационна цел" + "message": "Задай за навигационна цел" }, "TAXI": { "description": "", diff --git a/data/lang/quitconfirmation-core/bg.json b/data/lang/quitconfirmation-core/bg.json index b0909ecc210..8d67ad7b1fe 100644 --- a/data/lang/quitconfirmation-core/bg.json +++ b/data/lang/quitconfirmation-core/bg.json @@ -37,11 +37,11 @@ }, "MSG_18": { "description": "Catch phrase of 2016?", - "message": "Направи Pioneer велика! Само загубеняците си тръгват, нали не си загубеняк?" + "message": "Направи Pioneer велика! Само загубеняците си тръгват, нали не си един от тях?" }, "MSG_19": { "description": "Alluding to / inviting the player to contribute content to the game", - "message": "Стига тестване, време е за принос към играта?" + "message": "Стига си играл, време е да допринесеш с нещо към играта, нали?" }, "MSG_2": { "description": "", @@ -57,7 +57,7 @@ }, "MSG_22": { "description": "alluding to suicide", - "message": "Не го прави! По-добре ще става от тук нататък! Ти наистина ли се предаваш?" + "message": "Не го прави! По-добре ще става от тук нататък! Ама наистина ли се предаваш?" }, "MSG_3": { "description": "", @@ -73,7 +73,7 @@ }, "MSG_6": { "description": "", - "message": "{no} е само за смелите хора, {yes} е за всички останали." + "message": "Избери {no} и покажи истински кураж, избери {yes} и се скрий в твоя гараж." }, "MSG_7": { "description": "Doom 1 anyone? Although it said DOS instead of Command line", diff --git a/data/lang/ui-core/ar.json b/data/lang/ui-core/ar.json index afcfea9efa9..dac2c521174 100644 --- a/data/lang/ui-core/ar.json +++ b/data/lang/ui-core/ar.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "التدريع الجوي" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "محاولة إصلاح درع السفينة" diff --git a/data/lang/ui-core/bg.json b/data/lang/ui-core/bg.json index 802e81ee34f..a1c470f907b 100644 --- a/data/lang/ui-core/bg.json +++ b/data/lang/ui-core/bg.json @@ -9,7 +9,7 @@ }, "ADD_JUMP": { "description": "UI-button: Add hyper jump to list of planned jumps", - "message": "Add Jump" + "message": "Добави Хиперскок" }, "AFTER_TRADE_IN": { "description": "", @@ -17,11 +17,11 @@ }, "ALLEGIANCE": { "description": "", - "message": "Вярност:" + "message": "Преданост:" }, "ALL_UP_WEIGHT": { "description": "", - "message": "All-up weight" + "message": "Цялостно тегло" }, "AMOUNT": { "description": "", @@ -37,19 +37,23 @@ }, "ARRIVAL_DATE": { "description": "Time of arrival, used in flight log", - "message": "Arrival date" + "message": "Дата на пристигане" }, "ATMOSPHERIC_SHIELDING": { "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Атмосферен щит" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", - "message": "Attempt to repair hull" + "message": "Опитайте да поправите корпуса" }, "AUTO_ROUTE": { "description": "Automatically find shortest jump route (measured in time) in star map", - "message": "Auto Route" + "message": "Автоматичен Mаршрут" }, "AVAILABLE_FOR_PURCHASE": { "description": "", @@ -61,7 +65,7 @@ }, "BACKWARD_ACCEL": { "description": "", - "message": "Backward acceleration" + "message": "Ускорение назад" }, "BULLETIN_BOARD": { "description": "", @@ -73,7 +77,7 @@ }, "BUY_SHIP": { "description": "", - "message": "Купи Кораба" + "message": "Купуване" }, "CABINS": { "description": "For passengers", @@ -93,7 +97,7 @@ }, "CANNOT_SELL_ITEM": { "description": "", - "message": "This item cannot be sold" + "message": "Този артикул не може да бъде продаден" }, "CAPACITY": { "description": "Capacity of ship to fit more equipment", @@ -117,11 +121,11 @@ }, "CARGO_T_FREE": { "description": "t for tonne", - "message": "{amount}т свободни" + "message": "{amount} т. свободни" }, "CARGO_T_USED": { "description": "t for tonne", - "message": "{amount}т заети" + "message": "{amount} т. заети" }, "CASH": { "description": "", @@ -133,15 +137,15 @@ }, "CENTER_ON_SYSTEM": { "description": "Center on selected star system", - "message": "Center on System" + "message": "Центрирай върху Системата" }, "CHANGE": { "description": "Face feature option", - "message": "Change:" + "message": "Промени:" }, "CHANGE_BINDING": { "description": "Key binding option", - "message": "Change Binding" + "message": "Промени Контролите" }, "CHIEF_MECHANIC": { "description": "", @@ -149,7 +153,7 @@ }, "CIRCULAR_ORBIT_SPEED": { "description": "", - "message": "Circular orbit speed" + "message": "Скорост при кръгова орбита" }, "CITY_DETAIL_LEVEL": { "description": "Game graphics option", @@ -185,7 +189,7 @@ }, "COMMODITY_MARKET": { "description": "", - "message": "Стоков Пазар" + "message": "Пазар за Стоки" }, "COMPACT_RADAR": { "description": "Game settings option", @@ -201,7 +205,7 @@ }, "COMPRESS_TEXTURES": { "description": "graphics option in game settings menu ", - "message": "Compress Textures" + "message": "Компресирай Текстурите" }, "CONFIRM_PURCHASE": { "description": "", @@ -213,11 +217,11 @@ }, "CONSTABLE": { "description": "", - "message": "Constable" + "message": "Полицай" }, "CONTINUE_GAME": { "description": "", - "message": "Continue game" + "message": "Продължи играта" }, "CONTROLS": { "description": "", @@ -225,7 +229,7 @@ }, "CONTROL_OPTIONS": { "description": "", - "message": "Control Options" + "message": "Опции за Управление" }, "COULD_NOT_LOAD_GAME": { "description": "", @@ -241,15 +245,15 @@ }, "CREW_CABINS": { "description": "", - "message": "Crew cabins" + "message": "Екипажни кабини" }, "CREW_ROSTER": { "description": "", - "message": "Crew Roster" + "message": "Състав на Екипажа" }, "CRIMINAL_RECORD": { "description": "Past crimes / crime history of character", - "message": "Criminal record" + "message": "Криминално досие" }, "CURRENT_FUEL": { "description": "For hyperjump planner", @@ -265,7 +269,7 @@ }, "DATE": { "description": "Date of an event, used in flight log", - "message": "Date" + "message": "Дата" }, "DEADLY": { "description": "Player combat rating", @@ -293,15 +297,15 @@ }, "DEPARTURE_DATE": { "description": "Time of departure, used in flight log", - "message": "Departure date" + "message": "Дата на отпътуване" }, "DESCENT_TO_GROUND_SPEED": { "description": "", - "message": "Descent-to-ground speed:" + "message": "Скорост на спускане към повърхността:" }, "DESTROY_ENEMY_SHIP": { "description": "", - "message": "Destroy enemy ship" + "message": "Унищожете вражеския кораб" }, "DETAIL_DESC": { "description": "tooltip description in settings menu", @@ -329,7 +333,7 @@ }, "DISPLAY_NAV_TUNNELS": { "description": "Settings option: hyperspace tunnel effect", - "message": "Display nav tunnels" + "message": "Покажи навигационните тунели" }, "DISPLAY_NAV_TUNNELS_DESC": { "description": "tooltip description in settings menu", @@ -337,7 +341,7 @@ }, "DISPLAY_SPEED_LINES": { "description": "Settings option: effect when travelling in space", - "message": "Display speed lines" + "message": "Покажи скоростните линии" }, "DISPLAY_SPEED_LINES_DESC": { "description": "tooltip description in settings menu", @@ -345,11 +349,11 @@ }, "DOCKED_AT": { "description": "", - "message": "Docked at" + "message": "Скачен с" }, "DOCK_AT_CURRENT_TARGET": { "description": "", - "message": "Dock at current target" + "message": "Скачи се със сегашната цел" }, "DRIVE_ACTIVE": { "description": "Ship jump status", @@ -361,7 +365,7 @@ }, "DUMPING": { "description": "The illegal act of dumping waste", - "message": "Dumping" + "message": "Изхвърляне" }, "D_DAYS_LEFT": { "description": "", @@ -373,7 +377,7 @@ }, "EDIT": { "description": "Tooltip, to edit a flight log entry", - "message": "Edit" + "message": "Редактирай" }, "EFFECTS": { "description": "", @@ -385,7 +389,7 @@ }, "EMPLOYMENT": { "description": "", - "message": "Employment" + "message": "Заетост" }, "ENABLE_ANISOTROPIC_FILTERING": { "description": "Use Anisotropic Filtering", @@ -393,7 +397,7 @@ }, "ENABLE_AUTOSAVE": { "description": "Allow the game to autosave when docking", - "message": "Enable Autosave" + "message": "Включи Автоматично запазване" }, "ENABLE_AUTOSAVE_DESC": { "description": "tooltip description in settings menu", @@ -409,11 +413,11 @@ }, "ENABLE_JOYSTICK": { "description": "", - "message": "Enable joystick" + "message": "Активирай джойстик" }, "END_GAME": { "description": "", - "message": "End Game" + "message": "Край на Играта" }, "ENGINEERING": { "description": "Engineering skills of crew", @@ -421,7 +425,7 @@ }, "ENTRY": { "description": "A note/entry/record into the flight log", - "message": "Entry" + "message": "Записка" }, "EQUIPMENT": { "description": "", @@ -429,11 +433,11 @@ }, "EQUIPMENT_MARKET": { "description": "", - "message": "Equipment Market" + "message": "Пазар за Оборудване" }, "EQUIPPED": { "description": "", - "message": "Equipped" + "message": "Оборудван" }, "ERROR": { "description": "", @@ -441,15 +445,15 @@ }, "ERROR_LANDING_GEAR_DOWN": { "description": "", - "message": "Can not initiate hyperjump; landing gear is not retracted!" + "message": "Хиперскокът не може да започне, колесниците не са вдигнати!" }, "ESCAPE_SPEED": { "description": "", - "message": "Escape speed:" + "message": "Втора космическа скорост:" }, "EXIT_THIS_GAME": { "description": "", - "message": "Exit this game" + "message": "Излез от тази игра" }, "EXPERIENCED": { "description": "For player reputation", @@ -517,7 +521,7 @@ }, "FLIGHTLOG_DOCKING": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is a station name", - "message": "Docking at {primary_info}" + "message": "Скачване с {primary_info}" }, "FLIGHTLOG_FLYING": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is the name of a space body", @@ -525,31 +529,31 @@ }, "FLIGHTLOG_HYPERSPACE": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is the star system targeted for hyperspace jump.", - "message": "In Hyperspace, enroute to {primary_info}" + "message": "В хиперпространството, на път за {primary_info}" }, "FLIGHTLOG_JUMPING": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is the star system targeted for hyperspace jump.", - "message": "Hyper jumping towards {primary_info}" + "message": "Хиперотскок към {primary_info}" }, "FLIGHTLOG_LANDED": { "description": "Used in Flight Log, to indicate player's position, 'primary_info' is the name of a space body, typically a planet, the other two variables are latitude and longitude as floating point number, e.g. 'Landed on Trantor, position (-43.23, 67.89)'", - "message": "Landed on {primary_info}, position ({secondary_info}, {tertiary_info})" + "message": "Приземен на {primary_info}, координати ({secondary_info}, {tertiary_info})" }, "FLIGHTLOG_STARPORT_ORBITAL": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is a station name, 'secondary_info' is a space body (planet, moon/satelite, star) name", - "message": "Docked at {primary_info}, in orbit around {secondary_info}" + "message": "Скачен с {primary_info} в орбита, около {secondary_info}" }, "FLIGHTLOG_STARPORT_SURFACE": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is a station name, 'secondary_info' is a space body (planet, moon/satelite, star) name", - "message": "Docked at {primary_info}, on {secondary_info}" + "message": "Скачен с {primary_info} на {secondary_info}" }, "FLIGHTLOG_UNDOCKING": { "description": "Used in Flight Log, to indicate player's position. 'primary_info' is a station name", - "message": "Undocking at {primary_info}" + "message": "Откачване от {primary_info}" }, "FLIGHT_LOG": { "description": "Title for flight log screen, in info view", - "message": "Flight Log" + "message": "Летателен Дневник" }, "FLIGHT_STATE": { "description": "", @@ -561,23 +565,23 @@ }, "FORWARD_ACCEL": { "description": "", - "message": "Forward acceleration" + "message": "Ускорение напред" }, "FORWARD_ACCEL_EMPTY": { "description": "", - "message": "Forward accel (empty)" + "message": "Ускорение >| (празен)" }, "FORWARD_ACCEL_FULL": { "description": "", - "message": "Forward accel (full)" + "message": "Ускорение >| (пълен)" }, "FRACTAL_DETAIL": { "description": "", - "message": "Fractal detail" + "message": "Фрактален детайл" }, "FREE": { "description": "Used in Ship Information view as in Capacity: 10t (5t free)", - "message": "свободни" + "message": "Свободни" }, "FRONT_WEAPON": { "description": "", @@ -593,7 +597,7 @@ }, "FUEL_WEIGHT": { "description": "", - "message": "Fuel weight" + "message": "Тежест на горивото" }, "FULL_SCREEN": { "description": "", @@ -605,11 +609,11 @@ }, "GENERAL_CREW": { "description": "", - "message": "General crew" + "message": "Основен екипаж" }, "GIVE_ORDERS_TO_CREW": { "description": "", - "message": "Give orders to crew" + "message": "Дай заповеди на екипажа" }, "GOOD_RIDDANCE_TO_YOU_TOO": { "description": "", @@ -625,7 +629,7 @@ }, "HANG_UP": { "description": "", - "message": "Hang up." + "message": "Затвори" }, "HARMLESS": { "description": "Player combat rating", @@ -633,39 +637,39 @@ }, "HEAVY_CARGO_SHUTTLE": { "description": "", - "message": "Heavy cargo shuttle" + "message": "Тежкотоварна совалка" }, "HEAVY_COURIER": { "description": "", - "message": "Heavy courier" + "message": "Тежък куриер" }, "HEAVY_FIGHTER": { "description": "", - "message": "Heavy fighter" + "message": "Тежък изтребител" }, "HEAVY_FREIGHTER": { "description": "", - "message": "Heavy freighter" + "message": "Тежкотоварен кораб" }, "HEAVY_PASSENGER_SHUTTLE": { "description": "", - "message": "Heavy passenger shuttle" + "message": "Тежка пасажерска совалка" }, "HEAVY_PASSENGER_TRANSPORT": { "description": "", - "message": "Heavy passenger transport" + "message": "Тежък пасажерски транспортен кораб" }, "HIGH": { "description": "Game settings option: for graphics resolution", - "message": "High" + "message": "Високо" }, "HUD_2D_RADAR": { "description": "Popup text: the name of the azimuthal equidistant projection radar", - "message": "2D azimuthal equidistant projection" + "message": "2D азимутална равномеждинна проекция" }, "HUD_3D_RADAR": { "description": "Popup text: the name of the planar projection radar (traditional frontier-style)", - "message": "3D planar projection" + "message": "3D планарна проекция" }, "HUD_ATMOSPHERIC_PRESSURE": { "description": "Tooltip: Atmospheric Pressure.", @@ -673,7 +677,7 @@ }, "HUD_BACKWARD_GUN_TEMPERATURE": { "description": "Tooltip: Backward Gun Temperature.", - "message": "Backward Gun Temperature" + "message": "Температура на Задното Оръжие" }, "HUD_BRAKE_DISTANCE_MAIN_THRUSTERS": { "description": "Tooltip: The braking distance using the main thrusters.", @@ -681,19 +685,19 @@ }, "HUD_BUTTON_AUTOPILOT_DOCKING": { "description": "Tooltip: Autopilot docking", - "message": "Autopilot docking" + "message": "Автопилотът извършва скачване" }, "HUD_BUTTON_AUTOPILOT_ENTERING_ORBIT": { "description": "Tooltip: Autopilot entering orbit", - "message": "Autopilot entering orbit" + "message": "Автопилотът влиза в орбита" }, "HUD_BUTTON_AUTOPILOT_FLYING_TO_TARGET": { "description": "Tooltip: Autopilot flying to target", - "message": "Autopilot flying to target" + "message": "Автопилотът лети към целта" }, "HUD_BUTTON_BLASTOFF": { "description": "Tooltip: Blastoff", - "message": "Blastoff" + "message": "Изстрелване" }, "HUD_BUTTON_EQUIPMENT": { "description": "Tooltip: Equipment", @@ -729,19 +733,19 @@ }, "HUD_BUTTON_FLYBY_VIEW": { "description": "Tooltip: Flyby camera view", - "message": "Flyby view" + "message": "Прелитащ изглед" }, "HUD_BUTTON_HYPERDRIVE_DISABLED": { "description": "Tooltip: Hyperdrive disabled (docked or landed)", - "message": "Hyperdrive disabled" + "message": "Хиперсветлинния двигател е изключен" }, "HUD_BUTTON_INITIATE_HYPERJUMP": { "description": "Tooltip: Initiate legal hyperjump", - "message": "Initiate hyperjump" + "message": "Започни хиперскок" }, "HUD_BUTTON_INITIATE_ILLEGAL_HYPERJUMP": { "description": "Tooltip: Initiate illegal hyperjump", - "message": "Initiate illegal hyperjump" + "message": "Започни нелегален хиперскок" }, "HUD_BUTTON_INTERNAL_VIEW": { "description": "Tooltip: Internal camera view", @@ -769,11 +773,11 @@ }, "HUD_BUTTON_ROTATION_DAMPING_IS_OFF": { "description": "Tooltip: Rotation damping is off", - "message": "Rotation damping is off" + "message": "Плавната ротация е изключена" }, "HUD_BUTTON_ROTATION_DAMPING_IS_ON": { "description": "Tooltip: Rotation damping is on", - "message": "Rotation damping is on" + "message": "Плавната ротация е включена" }, "HUD_BUTTON_SCANNER": { "description": "Tooltip: Scanner", @@ -785,39 +789,39 @@ }, "HUD_BUTTON_SHOW_COMMS": { "description": "Tooltip: Show comms", - "message": "Show comms" + "message": "Покажи съобщенията" }, "HUD_BUTTON_SHOW_PERSONAL_INFO": { "description": "Tooltip: Show personal info", - "message": "Show personal info" + "message": "Покажи личната информация" }, "HUD_BUTTON_SIDEREAL_VIEW": { "description": "Tooltip: Sidereal camera view", - "message": "Sidereal view" + "message": "Звезден изглед" }, "HUD_BUTTON_SWITCH_TO_GALAXY_MAP": { "description": "Tooltip: Switch to galaxy map", - "message": "Switch to galaxy map" + "message": "Галактическа карта" }, "HUD_BUTTON_SWITCH_TO_SECTOR_MAP": { "description": "Tooltip: Switch to sector map", - "message": "Switch to sector map" + "message": "Секторна карта" }, "HUD_BUTTON_SWITCH_TO_SYSTEM_MAP": { "description": "Tooltip: Switch to system map", - "message": "Switch to system map" + "message": "Системна карта" }, "HUD_BUTTON_SWITCH_TO_SYSTEM_OVERVIEW": { "description": "Tooltip: Switch to system overview", - "message": "Switch to system overview" + "message": "Общ преглед на системата" }, "HUD_BUTTON_SWITCH_TO_WORLD_VIEW": { "description": "Tooltip: Switch to world view", - "message": "Switch to world view" + "message": "Мироглед" }, "HUD_BUTTON_UNDOCK": { "description": "Tooltip: Undock", - "message": "Undock" + "message": "Откачи" }, "HUD_CARGO_MASS": { "description": "Cargo Mass", @@ -841,11 +845,11 @@ }, "HUD_CURRENT_PITCH": { "description": "Tooltip: the current pitch.", - "message": "The current pitch" + "message": "Сегашното накланяне" }, "HUD_CURRENT_ROLL": { "description": "Tooltip: the current roll.", - "message": "The current roll" + "message": "Сегашното завъртане" }, "HUD_DELTA_V": { "description": "Tooltip: The remaining Δv.", @@ -857,7 +861,7 @@ }, "HUD_DELTA_V_PERCENT": { "description": "Tooltip: The remaining Δv in percent.", - "message": "% от максимална Δv" + "message": "% от максималнo Δv" }, "HUD_DISTANCE_TO_SURFACE_OF_FRAME": { "description": "Tooltip: Distance to the surface of the frame of reference.", @@ -877,15 +881,15 @@ }, "HUD_FORWARD_GUN_TEMPERATURE": { "description": "Tooltip: Forward Gun Temperature.", - "message": "Forward Gun Temperature" + "message": "Температура на Предното Оръжие" }, "HUD_HULL_STRENGTH": { "description": "Tooltip: Hull Strength.", - "message": "Hull Strength" + "message": "Издръжливост на Корпуса" }, "HUD_HULL_TEMPERATURE": { "description": "Tooltip: Hull Temperature.", - "message": "Hull Temperature" + "message": "Температура на Корпуса" }, "HUD_HYPERSPACING_TO_N_IN_N_SECONDS": { "description": "", @@ -925,11 +929,11 @@ }, "HUD_IN_TRANSIT_TO_N_X_X_X": { "description": "", - "message": "In transit to {system} [{x},{y},{z}]" + "message": "На път за {system} [{x},{y},{z}]" }, "HUD_JUMP_COMPLETE": { "description": "", - "message": "Jump complete: {percent}%" + "message": "Изпълнение на хиперскок: {percent}%" }, "HUD_MASS": { "description": "Mass", @@ -937,15 +941,15 @@ }, "HUD_RADAR_DISTANCE": { "description": "Tooltip: Current distance of the radar.", - "message": "Active radar distance" + "message": "Активно радарно разстояние" }, "HUD_REQUEST_TIME_ACCEL": { "description": "Tooltip: Request time acceleration {time}", - "message": "Request time acceleration: {time}" + "message": "Заяви ускорение на времето: {time}" }, "HUD_SHIELD_STRENGTH": { "description": "Tooltip: Shield Strength.", - "message": "Shield Strength" + "message": "Издръжливост на Щитовете" }, "HUD_SHOW_COMBAT_TARGET": { "description": "Tooltip: Show the current combat target.", @@ -965,11 +969,11 @@ }, "HUD_SPEED_OF_APPROACH_TO_TARGET": { "description": "Tooltip: The speed of approach relative to target.", - "message": "The speed of approach relative to target" + "message": "Скоростта на приближаване, спрямо целта" }, "HUD_SPEED_RELATIVE_TO_TARGET": { "description": "Tooltip: The speed relative to the target.", - "message": "The speed relative to the target" + "message": "Скоростта, спрямо целта" }, "HUD_THRUST_INDICATOR": { "description": "Tooltip: describe what the thrust/velocity indicator shows", @@ -981,51 +985,51 @@ }, "HUD_WARNING_IMPACT": { "description": "Alert tooltip", - "message": "Impact warning" + "message": "Опасност от сблъсък" }, "HUD_WARNING_IMPACT_IMMINENT": { "description": "Alert tooltip", - "message": "Impact imminent" + "message": "Предстои сблъсък" }, "HULL_DOES_NOT_REQUIRE_REPAIR": { "description": "", - "message": "Hull does not require repair." + "message": "Корпусът не се нуждае от поправка." }, "HULL_INTEGRITY": { "description": "", - "message": "Hull integrity" + "message": "Здравина на корпуса" }, "HULL_REPAIRED_BY_NAME_NOW_AT_N_PERCENT": { "description": "", - "message": "Hull repaired by {name}, now at {repairPercent}%" + "message": "Корпусът е поправен от {name}, на {repairPercent}%" }, "HULL_REPAIR_ATTEMPT_FAILED_HULL_SUFFERED_MINOR_DAMAGE": { "description": "", - "message": "Hull repair attempt failed. Hull suffered minor damage." + "message": "Поправката е неуспешна. Корпусът претърпя незначителни поражения." }, "HYPERDRIVE": { "description": "", - "message": "Hyperdrive" + "message": "Хиперсветлинен двигател" }, "HYPERDRIVE_FITTED": { "description": "", - "message": "Hyperdrive fitted:" + "message": "Монтирани хиперсветлинни двигатели:" }, "HYPERJUMP_ROUTE": { "description": "", - "message": "HyperJump Route" + "message": "Маршрут на Хиперскока" }, "HYPERSPACE_RANGE": { "description": "", - "message": "Hyperspace range" + "message": "Хиперпространствен обхват" }, "ILLEGAL_JUMP": { "description": "A finable crime", - "message": "Reckless hyperjump registered" + "message": "Засечен е безразсъден хиперскок" }, "IM_TIRED_OF_WORKING_FOR_NOTHING_DONT_YOU_KNOW_WHAT_A_CONTRACT_IS": { "description": "", - "message": "I'm tired of working for nothing. Don't you know what a contract is?" + "message": "Омръзна ми да работя за нищо. Не знаеш ли значението на думата договор?" }, "INACTIVE": { "description": "", @@ -1045,7 +1049,7 @@ }, "INITIATED": { "description": "Ship jump status", - "message": "Initiated" + "message": "Започнат" }, "INSUFFICIENT_FUEL": { "description": "Ship jump status", @@ -1057,35 +1061,35 @@ }, "INVERT_MOUSE_Y": { "description": "", - "message": "Invert Mouse Y" + "message": "Обърни вертикалната посока на мишката" }, "IN_CARGO_HOLD": { "description": "", - "message": "In cargo hold" + "message": "Натоварени" }, "IN_STOCK": { "description": "", - "message": "In stock" + "message": "Наличност" }, "IN_SYSTEM": { "description": "Used in flight log, show which star system we are/were in", - "message": "In system" + "message": "В системата" }, "ITEM_IS_OUT_OF_STOCK": { "description": "", - "message": "This item is out of stock." + "message": "Този артикул е изчерпан." }, "ITS_BEEN_GREAT_WORKING_FOR_YOU_IF_YOU_NEED_ME_AGAIN_ILL_BE_HERE_A_WHILE": { "description": "", - "message": "It's been great working for you. If you need me again, I'll be here a while." + "message": "Беше удоволствие да работя за Вас. Ако имате нужда от мен отново, ще може да ме намерите тук." }, "JETTISON": { "description": "", - "message": "Jettison" + "message": "Изхвърли" }, "JUMPING": { "description": "Flight State", - "message": "Jumping" + "message": "Хиперотскок" }, "KILLS": { "description": "", @@ -1101,43 +1105,43 @@ }, "LAUNCH_PERMISSION_DENIED_BUSY": { "description": "", - "message": "Permission to launch denied: docking bay busy." + "message": "Разрешението за излитане е отказано: има трафик." }, "LAUNCH_PERMISSION_DENIED_CREW": { "description": "", - "message": "Permission to launch denied: not enough crew to handle this ship." + "message": "Разрешението за излитане е отказано: екипажът на кораба не е достатъчен." }, "LAUNCH_PERMISSION_DENIED_FINED": { "description": "", - "message": "Permission to launch denied: you have outstanding fines." + "message": "Разрешението за излитане е отказано: имате неплатени глоби." }, "LEGAL_STATUS": { "description": "", - "message": "Legal status" + "message": "Правен статут" }, "LIGHT_CARGO_SHUTTLE": { "description": "", - "message": "Light cargo shuttle" + "message": "Лекотоварна совалка" }, "LIGHT_COURIER": { "description": "", - "message": "Light courier" + "message": "Лек куриер" }, "LIGHT_FIGHTER": { "description": "", - "message": "Light fighter" + "message": "Лек изтребител" }, "LIGHT_FREIGHTER": { "description": "", - "message": "Light freighter" + "message": "Лекотоварен кораб" }, "LIGHT_PASSENGER_SHUTTLE": { "description": "", - "message": "Light passenger shuttle" + "message": "Лека пасажерска совалка" }, "LIGHT_PASSENGER_TRANSPORT": { "description": "", - "message": "Light passenger transport" + "message": "Лек пасажерски транспортен кораб" }, "LOAD": { "description": "", @@ -1157,7 +1161,7 @@ }, "LOCATED_N_KM_FROM_THE_CENTRE_OF_NAME": { "description": "", - "message": "Намира се на {distance}км от центъра на {name}:" + "message": "Намира се на {distance} км. от центъра на {name}:" }, "LOCATION": { "description": "", @@ -1165,23 +1169,23 @@ }, "LOG_CUSTOM": { "description": "Label tab for showing custom logged events", - "message": "Custom Log" + "message": "Персонализиран Дневник" }, "LOG_NEW": { "description": "Indicate to make an entry into flight log system", - "message": "New Entry" + "message": "Нова Записка" }, "LOG_STATION": { "description": "Label tab for showing logged station events", - "message": "Station Log" + "message": "Дневник на Станцията" }, "LOG_SYSTEM": { "description": "Label tab for showing logged system events", - "message": "System Log" + "message": "Дневник на Системата" }, "LOW": { "description": "", - "message": "Low" + "message": "Ниско" }, "LY": { "description": "Light year", @@ -1205,11 +1209,11 @@ }, "MARKET_BUYLINE": { "description": "", - "message": "Buy {amount} units for {price}" + "message": "Купи {amount} за {price}" }, "MARKET_SELLINE": { "description": "", - "message": "Sell {amount} units for {price}" + "message": "Продай {amount} за {price}" }, "MASS": { "description": "", @@ -1237,27 +1241,27 @@ }, "MEDIUM_CARGO_SHUTTLE": { "description": "", - "message": "Medium cargo shuttle" + "message": "Среднотоварна совалка" }, "MEDIUM_COURIER": { "description": "", - "message": "Medium courier" + "message": "Среден куриер" }, "MEDIUM_FIGHTER": { "description": "", - "message": "Medium fighter" + "message": "Среден изтребител" }, "MEDIUM_FREIGHTER": { "description": "", - "message": "Medium freighter" + "message": "Среднотоварен кораб" }, "MEDIUM_PASSENGER_SHUTTLE": { "description": "", - "message": "Medium passenger shuttle" + "message": "Средна пасажерска совалка" }, "MEDIUM_PASSENGER_TRANSPORT": { "description": "", - "message": "Medium passenger transport" + "message": "Среден пасажерски транспортен кораб" }, "METAL_ALLOYS": { "description": "", @@ -1273,15 +1277,15 @@ }, "MINOR_EXPORTS_ITEM": { "description": "", - "message": "Minor exports" + "message": "Незначителен износ" }, "MINOR_IMPORTS_ITEM": { "description": "", - "message": "Minor imports" + "message": "Незначителен внос" }, "MISSILE_MOUNTS": { "description": "", - "message": "Missile mounts" + "message": "Ракетни монтировки" }, "MISSIONS": { "description": "", @@ -1293,7 +1297,7 @@ }, "MORE_INFO": { "description": "", - "message": "Повече информация..." + "message": "Подробности..." }, "MOSTLY_HARMLESS": { "description": "", @@ -1301,15 +1305,15 @@ }, "MOVE_DOWN": { "description": "move selection down in list", - "message": "Move Down" + "message": "Премести Надолу" }, "MOVE_UP": { "description": "move selection up in list", - "message": "Move Up" + "message": "Премести Нагоре" }, "MULTISAMPLING": { "description": "", - "message": "Multisampling" + "message": "Мултисемплиране" }, "MULTISAMPLING_DESC": { "description": "", @@ -1353,7 +1357,7 @@ }, "NEXT_PAID": { "description": "", - "message": "Next paid" + "message": "Следващо плащане" }, "NO": { "description": "Negative answer to a question", @@ -1369,7 +1373,7 @@ }, "NONE_FOR_SALE_IN_THIS_STATION": { "description": "", - "message": "None for sale in this station." + "message": "Няма за продажба в тази станция." }, "NORMA_ARM": { "description": "Arm of the Milky Way galaxy", @@ -1381,11 +1385,11 @@ }, "NOT_ENOUGH_ALLOY_TO_ATTEMPT_A_REPAIR": { "description": "", - "message": "Not enough {alloy} to attempt a repair" + "message": "Няма достатъчно {alloy} за поправката на корпуса" }, "NOT_SUPPORTED_ON_THIS_SHIP": { "description": "", - "message": "{equipment} is not supported on this ship model" + "message": "{equipment} не се поддържа на този корабен модел" }, "NO_DRIVE": { "description": "Ship jump status", @@ -1393,7 +1397,7 @@ }, "NO_FILTER_MATCHES": { "description": "No matches to this filter.", - "message": "Nothing matches that filter" + "message": "Нищо не съвпада с този филтър" }, "NO_MISSIONS": { "description": "", @@ -1401,7 +1405,7 @@ }, "NO_VALID_ROUTE": { "description": "Message in the sector map, issued by the autoroute function.", - "message": "No valid route to the selected system." + "message": "Няма валиден маршрут до избраната система." }, "N_LIGHT_YEARS_N_MAX": { "description": "", @@ -1409,15 +1413,15 @@ }, "N_OCCUPIED_PASSENGER_CABINS": { "description": "", - "message": "{quantity} Occupied Passenger Cabins" + "message": "{quantity} Заети Пасажерски Кабини" }, "N_SHIELD_GENERATORS": { "description": "", - "message": "{quantity} Shield Generators" + "message": "{quantity} Генератора на Щитовете" }, "N_UNOCCUPIED_PASSENGER_CABINS": { "description": "", - "message": "{quantity} Unoccupied Passenger Cabins" + "message": "{quantity} Незаети Пасажерски Кабини" }, "OFF": { "description": "", @@ -1441,7 +1445,7 @@ }, "ORBITAL_ANALYSIS": { "description": "", - "message": "Orbital Analysis" + "message": "Орбитален Анализ" }, "ORBITAL_ANALYSIS_NOTES": { "description": "", @@ -1453,7 +1457,7 @@ }, "OUTSTANDING_FINES": { "description": "Unpaid fines for crimes committed", - "message": "Outstanding fines" + "message": "Неплатени глоби" }, "OUT_OF_RANGE": { "description": "Ship jump status", @@ -1493,7 +1497,7 @@ }, "PILOT_SEAT_IS_NOW_OCCUPIED_BY_NAME": { "description": "", - "message": "Pilot seat is now occupied by {name}" + "message": "Новият пилот е {name}" }, "PIRACY": { "description": "", @@ -1501,11 +1505,11 @@ }, "PLANET_DETAIL_DISTANCE": { "description": "", - "message": "Planet detail distance" + "message": "Ниво на планетните детайли" }, "PLANET_TEXTURES": { "description": "", - "message": "Planet textures" + "message": "Планетни текстури" }, "POLICE": { "description": "", @@ -1521,7 +1525,7 @@ }, "PRESS_A_KEY_OR_CONTROLLER_BUTTON": { "description": "", - "message": "Press a key or controller button or escape to clear" + "message": "Натиснете бутон или Esc за изчистване" }, "PREVIOUS_FACE_FEATURE": { "description": "Face feature switch button for FaceGenerator in the PersonalInfo view", @@ -1537,11 +1541,11 @@ }, "PUMP_DOWN": { "description": "Drain the fuel tank", - "message": "Pump down" + "message": "Източи" }, "QUALIFICATION_SCORES": { "description": "", - "message": "Qualification scores" + "message": "Квалификационни резултати" }, "QUIT": { "description": "", @@ -1549,7 +1553,7 @@ }, "QUIT_CONFIRMATION": { "description": "For the checkbox in settings window", - "message": "Quit confirmation" + "message": "Потвърждение за изход" }, "RANDOM_FACE": { "description": "Generate random face", @@ -1569,11 +1573,11 @@ }, "REFUEL": { "description": "", - "message": "Refuel" + "message": "Презареди" }, "REFUEL_FULL": { "description": "", - "message": "Refuel full" + "message": "Догоре" }, "REGISTRATION_NUMBER": { "description": "", @@ -1585,19 +1589,19 @@ }, "REMOVE": { "description": "Remove, e.g. deleting a log entry", - "message": "Remove" + "message": "Премахни" }, "REMOVE_JUMP": { "description": "UI-button: remove hyper jump from list of planned jumps", - "message": "Remove Jump" + "message": "Премахни Хиперскок" }, "REMOVE_WHEN_COMPLETED": { "description": "For UI hyperjump planner, referring to jump target system", - "message": "Remove jump when completed" + "message": "Премахни хиперскока, след завършването му" }, "REPAIR_X_HULL_DAMAGE_FOR_X": { "description": "", - "message": "Repair {damage}% hull damage for {price}" + "message": "Поправи {damage}% щети на корпуса за {price}" }, "REPUTATION": { "description": "", @@ -1605,7 +1609,7 @@ }, "REQUEST_LAUNCH": { "description": "", - "message": "Request Launch" + "message": "Заяви Излитане" }, "REQUIRED_FUEL": { "description": "Fuel usage for traveling to star system", @@ -1617,19 +1621,19 @@ }, "RETURN_TO_GAME": { "description": "", - "message": "Return to game" + "message": "Върни се в играта" }, "RETURN_TO_MENU": { "description": "", - "message": "Return to menu" + "message": "Върни се в менюто" }, "REVERSE_ACCEL_EMPTY": { "description": "", - "message": "Reverse accel (empty)" + "message": "Ускорение |< (празен)" }, "REVERSE_ACCEL_FULL": { "description": "", - "message": "Reverse accel (full)" + "message": "Ускорение |< (пълен)" }, "REWARD": { "description": "", @@ -1637,15 +1641,15 @@ }, "ROTATE_VIEW": { "description": "", - "message": "Rotate view" + "message": "Завърти изгледа" }, "ROUTE_INFO": { "description": "For hyperjump planner", - "message": "Route Info" + "message": "Информация за Маршрута" }, "ROUTE_JUMPS": { "description": "For hyperjump planner", - "message": "Route Jumps" + "message": "Скокове в Маршрута" }, "SAFETY_LOCKOUT": { "description": "Ship jump status", @@ -1661,7 +1665,7 @@ }, "SCOOP_MOUNTS": { "description": "How many slots or mounts exist on the ship for fitting SCOOPS (e.g. cargo scoop, fuel scoop, multi-scoop) ", - "message": "Scoop mounts" + "message": "Събирачни монтировки" }, "SCUTUM_CENTAURUS_ARM": { "description": "Arm of the Milky Way galaxy", @@ -1693,7 +1697,7 @@ }, "SENSORS_AND_DEFENCE": { "description": "", - "message": "Sensors and defence" + "message": "Сензори и защита" }, "SETTINGS": { "description": "UI option", @@ -1701,7 +1705,7 @@ }, "SET_AS_TARGET": { "description": "", - "message": "Set destination as navigation target." + "message": "Задай дестинацията като навигационна цел." }, "SHIP": { "description": "", @@ -1709,7 +1713,7 @@ }, "SHIPS_ENGINEER": { "description": "", - "message": "Ship's Engineer" + "message": "Корабен Инженер" }, "SHIP_INFORMATION": { "description": "", @@ -1717,23 +1721,23 @@ }, "SHIP_IS_ALREADY_FULLY_REPAIRED": { "description": "", - "message": "Your ship is in perfect working condition." + "message": "Вашият кораб е в перфектно техническо състояние." }, "SHIP_IS_FULLY_EQUIPPED": { "description": "", - "message": "Your ship is fully equipped." + "message": "Вашият кораб е напълно оборудван." }, "SHIP_IS_FULLY_LADEN": { "description": "", - "message": "Your ship is fully laden." + "message": "Вашият кораб е напълно натоварен." }, "SHIP_MARKET": { "description": "", - "message": "Ship Market" + "message": "Пазар за Кораби" }, "SHIP_REPAIRS": { "description": "", - "message": "Ship Repairs" + "message": "Ремонт на Кораби" }, "SHIP_TYPE": { "description": "", @@ -1741,7 +1745,7 @@ }, "SHIP_VIEWING_WAS_SOLD": { "description": "", - "message": "The ship you were viewing has been sold" + "message": "Корабът, който разглеждахте, беше продаден" }, "SIMULATING_UNIVERSE_EVOLUTION_N_BYEARS": { "description": "", @@ -1757,7 +1761,7 @@ }, "START_AT_BARNARDS_STAR_DESC": { "description": "", - "message": "This is a difficult start from the System Administration Resting prison station." + "message": "Това е труден старт от космическия затвор Почивната База на Системната Администрация" }, "START_AT_EARTH": { "description": "", @@ -1765,7 +1769,7 @@ }, "START_AT_EARTH_DESC": { "description": "", - "message": "This is an easy start from London on Earth in the Sol system." + "message": "Това е лесен старт от Лондон на Земята в Слънчевата система." }, "START_AT_MARS": { "description": "", @@ -1773,7 +1777,7 @@ }, "START_AT_MARS_DESC": { "description": "", - "message": "This is an easy start from Cydonia on Mars in the Sol system." + "message": "Това е лесен старт от Сидония на Марс в Слънчевата система." }, "START_AT_NEW_HOPE": { "description": "New Hope is an in game location", @@ -1781,7 +1785,7 @@ }, "START_AT_NEW_HOPE_DESC": { "description": "", - "message": "This is a moderate start from Itzalean on New Hope in the Epsilon Eridani system." + "message": "Това е умерен старт от Ицалиян на Нова Надежда в системата Епсилон Еридани." }, "START_LOG_ENTRY_1": { "description": "First custom log message when starting a new game, giving backstory to the character. Importantly we here hint at what actions the player is best to take: buy fuel, get reputation, ask for take off clearance.", @@ -1797,27 +1801,27 @@ }, "STAR_FIELD_DENSITY": { "description": "", - "message": "Density of Star field" + "message": "Гъстота на звездите" }, "STATION": { "description": "Flight log info, will refer to a station by name", - "message": "Station" + "message": "Станция" }, "STATION_DOCKS": { "description": "Information shown in the station lobby, for total number of docking pads", - "message": "Our total capacity is {total_docking_pads} docking pads." + "message": "Нашият максимален капацитет е {total_docking_pads} площадки за скачване." }, "STATION_MANAGER": { "description": "", - "message": "Station manager" + "message": "Управител на станцията" }, "STATION_ORBIT": { "description": "Information shown in the station loby", - "message": "We are in a {orbit_period} day period orbit around {parent_body}." + "message": "Ние сме в {orbit_period} дневен орбитален период около {parent_body}." }, "STATION_TECH_TOO_LOW": { "description": "", - "message": "Station tech level too low to sell this item" + "message": "Технологичното ниво на станцията е твърде ниско за продажбата на този артикул" }, "STATUS": { "description": "", @@ -1825,7 +1829,7 @@ }, "TECH_CERTIFIED": { "description": "Lobby screen shows the tech level (an integer number) of the station", - "message": "This station holds a level {tech_level} technology certificate." + "message": "Тази станция има технологичен сертификат от ниво {tech_level}." }, "TECH_CERTIFIED_MILITARY": { "description": "Lobby screen shows the tech level of the station", @@ -1837,55 +1841,55 @@ }, "THANKS_AND_REMEMBER_TO_BUY_FUEL": { "description": "", - "message": "Thank you for your purchase. Remember to fit equipment and buy fuel before you depart." + "message": "Благодарим Ви за покупката. Не забравяйте да монтирате оборудването си и да си купите гориво, преди тръгване." }, "THERE_IS_NOBODY_ELSE_ON_BOARD_ABLE_TO_FLY_THIS_SHIP": { "description": "", - "message": "There is nobody else on board able to fly this ship." + "message": "На борда няма друг, който е способен да управлява кораба." }, "THE_SHIP_IS_UNDER_STATION_CONTROL_COMMANDER": { "description": "", - "message": "The ship is under station control, Commander." + "message": "Командире, корабът е под управлението на станцията." }, "THIS_IS_FACTION_POLICE": { "description": "Greeting message in police station. 'faction' is one of (English, non-translatable) strings: 'Solar Federation', 'Commonwealth of Independent Worlds', or 'Haber Corporation', and 'faction_police' is one of: 'SolFed Police Force', 'Confederal Police' or, 'Haber Enforcement Division'", - "message": "This is the {faction_police} of the {faction}" + "message": "Това е {faction_police} от {faction}" }, "THREE_KPC_ARM": { "description": "Arm of the Milky Way galaxy", - "message": "Ръкав 3kpc" + "message": "Ръкав 3-кпс" }, "TOGGLE_MALE_FEMALE": { "description": "player gender", - "message": "Toggle male/female" + "message": "Превключи мъж/жена" }, "TOGGLE_OVERVIEW_SHOW_MOONS": { "description": "toggle whether the overview window shows moons or not", - "message": "Toggle showing moons in the overview" + "message": "Превключи показването на луните в общия преглед" }, "TOGGLE_OVERVIEW_SHOW_STATIONS": { "description": "toggle whether the overview window shows stations or not", - "message": "Toggle showing stations in the overview" + "message": "Превключи показването на станциите в общия преглед" }, "TOGGLE_OVERVIEW_SORT_BY_PLAYER_DISTANCE": { "description": "toggle whether the overview window sorts by distance from the player or from the system center", - "message": "Switch between sorting by distance from player and distance from system center" + "message": "Разстояние от играча или от центъра на системата" }, "TOGGLE_OVERVIEW_WINDOW": { "description": "show/hide the overview window / navigation window", - "message": "Toggle the overview window" + "message": "Превключи прозореца за общия преглед" }, "TOO_SMALL_FOR_CURRENT_CREW": { "description": "", - "message": "Ship is too small for the current crew." + "message": "Корабът е твърде малък за сегашния екипаж." }, "TOO_SMALL_TO_TRANSSHIP": { "description": "Ship market error message", - "message": "New ship lacks capacity for current cargo and hyperdrive." + "message": "Новият кораб няма капацитет за сегашния товар и хипердвигател." }, "TOTAL": { "description": "", - "message": "Общо:" + "message": "Общо: " }, "TOTAL_DISTANCE": { "description": "Total distance of a (possibly series) of hyper jump(s)", @@ -1921,11 +1925,11 @@ }, "UP_ACCEL": { "description": "", - "message": "Up acceleration" + "message": "Ускорение нагоре" }, "USED": { "description": "", - "message": "Used" + "message": "Използвани" }, "VERY_HIGH": { "description": "Game settings option: graphic resolution", @@ -1933,11 +1937,11 @@ }, "VERY_LOW": { "description": "Game settings option: graphic resolution", - "message": "Very low" + "message": "Много ниско" }, "VICINITY_OF": { "description": "", - "message": "In vicinity of" + "message": "В близост до" }, "VIDEO": { "description": "", @@ -1969,23 +1973,23 @@ }, "WEIGHT_EMPTY": { "description": "", - "message": "Weight empty" + "message": "Нетна тежест" }, "WEIGHT_FULLY_LOADED": { "description": "", - "message": "Weight fully loaded" + "message": "Брутно тегло" }, "WE_ARE_IN_HYPERSPACE_COMMANDER": { "description": "", - "message": "We are in hyperspace, Commander." + "message": "Командире, ние сме в хиперпространството." }, "WE_HAVE_NO_BUSINESS_WITH_YOU": { "description": "Said by the police to law abiding player", - "message": "We have no business with you at the moment." + "message": "В момента нямаме работа с теб." }, "X_CANNOT_BE_TOLERATED_HERE": { "description": "Message to be sent over comms by police when crime is committed by player", - "message": "{crime} cannot be tolerated here!" + "message": "Тук не се толерира {crime}!" }, "YES": { "description": "Positive answer to a question", @@ -1997,11 +2001,11 @@ }, "YOUR_HULL_IS_AT_X_INTEGRITY": { "description": "", - "message": "Your hull is at {value}% integrity." + "message": "Вашият корпус е с здравина от {value}%." }, "YOU_DONT_HAVE_ENOUGH_MONEY_FOR_THAT_OPTION": { "description": "", - "message": "You don't have enough money for that option." + "message": "Нямате достатъчно пари за тази опция." }, "YOU_HAVE_X_UNITS_IN_YOUR_CARGOHOLD": { "description": "", @@ -2009,23 +2013,23 @@ }, "YOU_MUST_FIRST_SELECT_A_COMBAT_TARGET_COMMANDER": { "description": "", - "message": "You must first select a combat target, Commander." + "message": "Командире, първо трябва да изберете бойна цел." }, "YOU_MUST_FIRST_SELECT_A_SUITABLE_NAVIGATION_TARGET_COMMANDER": { "description": "", - "message": "You must first select a suitable navigation target, Commander." + "message": "Командире, първо трябва да изберете подходяща навигационна цел." }, "YOU_MUST_LAUNCH_FIRST_COMMANDER": { "description": "", - "message": "You must launch first, Commander." + "message": "Командире, първо трябва да излетите." }, "YOU_MUST_REQUEST_LAUNCH_CLEARANCE_FIRST_COMMANDER": { "description": "", - "message": "You must request launch clearance first, Commander." + "message": "Командире, първо трябва да заявите излитане." }, "YOU_NOT_ENOUGH_MONEY": { "description": "", - "message": "You do not have enough money" + "message": "Нямате достатъчно пари" }, "ZOOM": { "description": "Label for a zoom (magnification) control bar.", diff --git a/data/lang/ui-core/ca.json b/data/lang/ui-core/ca.json index 70f66d0d069..fa95aa3757b 100644 --- a/data/lang/ui-core/ca.json +++ b/data/lang/ui-core/ca.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/cs.json b/data/lang/ui-core/cs.json index 4d0fa49e145..a5610fea207 100644 --- a/data/lang/ui-core/cs.json +++ b/data/lang/ui-core/cs.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmosférický štít" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Zkus opravit trup" diff --git a/data/lang/ui-core/da.json b/data/lang/ui-core/da.json index 7c5af8aac8a..5fcc607ca1f 100644 --- a/data/lang/ui-core/da.json +++ b/data/lang/ui-core/da.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Forsøg at reparere skrog" diff --git a/data/lang/ui-core/de.json b/data/lang/ui-core/de.json index d2cc4637fab..c37cb263988 100644 --- a/data/lang/ui-core/de.json +++ b/data/lang/ui-core/de.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmosphärische Abschirmung" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Versuchen, den Rumpf zu reparieren" diff --git a/data/lang/ui-core/el.json b/data/lang/ui-core/el.json index 4085eb3bdcc..1eb4d252547 100644 --- a/data/lang/ui-core/el.json +++ b/data/lang/ui-core/el.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/en.json b/data/lang/ui-core/en.json index f18d1e13640..b65ff2f31c9 100644 --- a/data/lang/ui-core/en.json +++ b/data/lang/ui-core/en.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/eo.json b/data/lang/ui-core/eo.json index f18d1e13640..b65ff2f31c9 100644 --- a/data/lang/ui-core/eo.json +++ b/data/lang/ui-core/eo.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/es.json b/data/lang/ui-core/es.json index 520bb725f8d..a8541fcc809 100644 --- a/data/lang/ui-core/es.json +++ b/data/lang/ui-core/es.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Escudo atmosférico" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Límite de presión atmo." + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Reparar casco" @@ -977,15 +981,15 @@ }, "HUD_WARNING_DESCENT_RATE": { "description": "Shown on HUD as a warning flasher", - "message": "DESCENT RATE" + "message": "TASA DE DESCENSO" }, "HUD_WARNING_IMPACT": { "description": "Alert tooltip", - "message": "Impact warning" + "message": "Alerta de impacto" }, "HUD_WARNING_IMPACT_IMMINENT": { "description": "Alert tooltip", - "message": "Impact imminent" + "message": "Impacto inminente" }, "HULL_DOES_NOT_REQUIRE_REPAIR": { "description": "", diff --git a/data/lang/ui-core/fr.json b/data/lang/ui-core/fr.json index c4434c29d42..803b4be4d24 100644 --- a/data/lang/ui-core/fr.json +++ b/data/lang/ui-core/fr.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Boucliers Thermiques" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Tentative de réparation de la coque." diff --git a/data/lang/ui-core/ga.json b/data/lang/ui-core/ga.json index cfd1b707f60..ede8f6620eb 100644 --- a/data/lang/ui-core/ga.json +++ b/data/lang/ui-core/ga.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Sciathadh atmaisféarach" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Iarracht an chabhail a dheisiú" diff --git a/data/lang/ui-core/gd.json b/data/lang/ui-core/gd.json index 79e3c0299db..f0fceaa485d 100644 --- a/data/lang/ui-core/gd.json +++ b/data/lang/ui-core/gd.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Dìonadh àile" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "A' feuchainn ris an t-slige a chàradh" diff --git a/data/lang/ui-core/hr.json b/data/lang/ui-core/hr.json index 5459ddf5306..75b4b08995e 100644 --- a/data/lang/ui-core/hr.json +++ b/data/lang/ui-core/hr.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/hu.json b/data/lang/ui-core/hu.json index 6306eb40154..e857a5b85da 100644 --- a/data/lang/ui-core/hu.json +++ b/data/lang/ui-core/hu.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmoszférapajzs" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Kíséreld meg a hajótest javítását" diff --git a/data/lang/ui-core/id.json b/data/lang/ui-core/id.json index 4593a0a2e7c..c1f81489bd0 100644 --- a/data/lang/ui-core/id.json +++ b/data/lang/ui-core/id.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/it.json b/data/lang/ui-core/it.json index e6a43b75b5b..d7691262ce6 100644 --- a/data/lang/ui-core/it.json +++ b/data/lang/ui-core/it.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Scudi atmosferici" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Limite pressione atm." + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Tenta di riparare lo scavo" diff --git a/data/lang/ui-core/lt.json b/data/lang/ui-core/lt.json index ba6b75e8ec5..4fa6c7654a0 100644 --- a/data/lang/ui-core/lt.json +++ b/data/lang/ui-core/lt.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/nb.json b/data/lang/ui-core/nb.json index f016f64d717..6c12d5f9281 100644 --- a/data/lang/ui-core/nb.json +++ b/data/lang/ui-core/nb.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/nl.json b/data/lang/ui-core/nl.json index daf7326c8cd..449442c3020 100644 --- a/data/lang/ui-core/nl.json +++ b/data/lang/ui-core/nl.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmosfeerschilden" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Romp repareren" diff --git a/data/lang/ui-core/pl.json b/data/lang/ui-core/pl.json index ecfba05dde4..f46bab0a107 100644 --- a/data/lang/ui-core/pl.json +++ b/data/lang/ui-core/pl.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Tarcze atmosferyczne" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Przystąpić do naprawy kadłuba" diff --git a/data/lang/ui-core/pt.json b/data/lang/ui-core/pt.json index df86a71244f..8517f099da5 100644 --- a/data/lang/ui-core/pt.json +++ b/data/lang/ui-core/pt.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmospheric shielding" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Attempt to repair hull" diff --git a/data/lang/ui-core/pt_BR.json b/data/lang/ui-core/pt_BR.json index a435df6e105..592d2c8a00c 100644 --- a/data/lang/ui-core/pt_BR.json +++ b/data/lang/ui-core/pt_BR.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Blindagem atmosférica" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Tentativa de reparar fuselagem" diff --git a/data/lang/ui-core/ro.json b/data/lang/ui-core/ro.json index 21584d3b31f..e42211d2314 100644 --- a/data/lang/ui-core/ro.json +++ b/data/lang/ui-core/ro.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Scut atmosferic" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Încearcă repararea fuzelajului" diff --git a/data/lang/ui-core/ru.json b/data/lang/ui-core/ru.json index 777f7b4bdf8..25a6ef8fe4e 100644 --- a/data/lang/ui-core/ru.json +++ b/data/lang/ui-core/ru.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Атмосферный щит" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Попытаться отремонтировать корпус" diff --git a/data/lang/ui-core/sv.json b/data/lang/ui-core/sv.json index 5a2d07e1745..f36ee77f257 100644 --- a/data/lang/ui-core/sv.json +++ b/data/lang/ui-core/sv.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmosfärkapabel" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. pressure limit" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Försök att reparera skrov" diff --git a/data/lang/ui-core/tr.json b/data/lang/ui-core/tr.json index b4384fee76b..92d09946083 100644 --- a/data/lang/ui-core/tr.json +++ b/data/lang/ui-core/tr.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "Atmosfer kalkanı" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "Atmo. basınç limiti" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "Gövdeyi tamir etmeyi dene" diff --git a/data/lang/ui-core/zh.json b/data/lang/ui-core/zh.json index 4a991919f69..0844d646797 100644 --- a/data/lang/ui-core/zh.json +++ b/data/lang/ui-core/zh.json @@ -43,6 +43,10 @@ "description": "Used in ShipInfo view, followed by a yes/no depending on if the ship can carry atmospheric shields", "message": "可安装大气护盾" }, + "ATMO_PRESS_LIMIT": { + "description": "Base external pressure limit of a ship (without atmo shield)", + "message": "气压极限" + }, "ATTEMPT_TO_REPAIR_HULL": { "description": "", "message": "尝试修理船体" diff --git a/data/libs/Equipment.lua b/data/libs/Equipment.lua index 9b415f26987..0130b771e36 100644 --- a/data/libs/Equipment.lua +++ b/data/libs/Equipment.lua @@ -785,19 +785,19 @@ misc.hull_autorepair = EquipType.New({ }) misc.thrusters_basic = EquipType.New({ l10n_key="THRUSTERS_BASIC", slots="thruster", price=3000, - tech_level=1, + tech_level=5, capabilities={mass=0, thruster_power=1}, purchasable=true, icon_name="thrusters_basic" }) misc.thrusters_medium = EquipType.New({ l10n_key="THRUSTERS_MEDIUM", slots="thruster", price=6500, - tech_level=1, + tech_level=8, capabilities={mass=0, thruster_power=2}, purchasable=true, icon_name="thrusters_medium" }) misc.thrusters_best = EquipType.New({ l10n_key="THRUSTERS_BEST", slots="thruster", price=14000, - tech_level=1, + tech_level="MILITARY", capabilities={mass=0, thruster_power=3}, purchasable=true, icon_name="thrusters_best" }) diff --git a/data/libs/FlightLog.lua b/data/libs/FlightLog.lua index 4e10f14ecbe..364ab5b3c3f 100644 --- a/data/libs/FlightLog.lua +++ b/data/libs/FlightLog.lua @@ -344,30 +344,39 @@ FlightLog = { text = text or "" local location = "" local state = Game.player:GetFlightState() + local path = "" if state == "DOCKED" then local station = Game.player:GetDockedWith() local parent_body = station.path:GetSystemBody().parent.name location = {station.type, station.label, parent_body} + path = Game.system.path elseif state == "DOCKING" or state == "UNDOCKING" then location = {state, Game.player:FindNearestTo("SPACESTATION").label} + path = Game.system.path elseif state == "FLYING" then - location = {state, Game.player.frameBody.label} + if Game.player.frameBody then + location = {state, Game.player.frameBody.label} + else + location = {state, Game.system.name} -- if orbiting a system barycenter, there will be no frame object + end + path = Game.system.path elseif state == "LANDED" then + path = Game.system.path local alt, vspd, lat, long = Game.player:GetGPS() if not (lat and long) then lat, long = "nil", "nil" end location = {state, Game.player:FindNearestTo("PLANET").label, lat, long} elseif state == "JUMPING" or state == "HYPERSPACE" then - -- bug: if in hyperspace, there's no Game.system (!) - -- local spath, sysname = Game.player:GetHyperspaceDestination() - sysname = "" + --if in hyperspace, there's no Game.system + local spath, sysname = Game.player:GetHyperspaceDestination() + path = spath location = {state, sysname} end table.insert(FlightLogCustom,1, - {Game.system.path, Game.time, Game.player:GetMoney(), location, text}) + {path, Game.time, Game.player:GetMoney(), location, text}) end, -- diff --git a/data/libs/ui/PiguiFace.lua b/data/libs/ui/PiguiFace.lua index 6518e39caf3..b3fd702d3e2 100644 --- a/data/libs/ui/PiguiFace.lua +++ b/data/libs/ui/PiguiFace.lua @@ -66,7 +66,7 @@ function PiGuiFace:render () if(self.style.showCharInfo) then local lastPos = ui.getCursorPos() ui.setCursorPos(lastPos - Vector2(0.0, self.style.charInfoHeight + self.style.itemSpacing.y)) - ui.withStyleColorsAndVars({ChildWindowBg = self.style.charInfoBgColor}, {WindowPadding = self.style.charInfoPadding, ItemSpacing = self.style.itemSpacing}, function () + ui.withStyleColorsAndVars({ChildBg = self.style.charInfoBgColor}, {WindowPadding = self.style.charInfoPadding, ItemSpacing = self.style.itemSpacing}, function () ui.child("PlayerInfoDetails", Vector2(self.style.size.x, self.style.charInfoHeight), charInfoFlags, function () ui.withFont(self.style.nameFont.name, self.style.nameFont.size, function() ui.text(self.character.name) diff --git a/data/modules/AIWarning/AIWarning.lua b/data/modules/AIWarning/AIWarning.lua index ff4ede13ef8..12267252517 100644 --- a/data/modules/AIWarning/AIWarning.lua +++ b/data/modules/AIWarning/AIWarning.lua @@ -9,6 +9,7 @@ local l = Lang.GetResource("module-aiwarning") local messages = { GRAV_TOO_HIGH = l.CANNOT_COMPENSATE_FOR_LOCAL_GRAVITY, + PRESS_TOO_HIGH = l.ATMO_PRESSURE_OVER_LIMIT, REFUSED_PERM = l.STARPORT_REFUSED_DOCKING_PERMISSION, ORBIT_IMPOSSIBLE = l.CANNOT_COMPUTE_ORBIT_PARAMETERS, } diff --git a/data/pigui/baseui.lua b/data/pigui/baseui.lua new file mode 100644 index 00000000000..ddd5545bc59 --- /dev/null +++ b/data/pigui/baseui.lua @@ -0,0 +1,73 @@ +local Engine = require 'Engine' +local pigui = Engine.pigui +local ui = require 'pigui.libs.forwarded' +require 'pigui.libs.wrappers' + + +local defaultTheme = require 'pigui.themes.default' + +local pi = 3.14159264 +local pi_2 = pi / 2 +local pi_4 = pi / 4 +local two_pi = pi * 2 +local standard_gravity = 9.80665 +local one_over_sqrt_two = 1 / math.sqrt(2) + +ui.oneOverSqrtTwo = one_over_sqrt_two +ui.standardGravity = standard_gravity +ui.theme = defaultTheme +ui.twoPi = two_pi +ui.pi_2 = pi_2 +ui.pi_4 = pi_4 +ui.pi = pi + +ui.anchor = { left = 1, right = 2, center = 3, top = 4, bottom = 5, baseline = 6 } + + +function ui.get_icon_tex_coords(icon) + assert(icon, "no icon given") + local count = 16.0 -- icons per row/column + local rem = math.floor(icon % count) + local quot = math.floor(icon / count) + return Vector2(rem / count, quot/count), Vector2((rem+1) / count, (quot+1)/count) +end + +function ui.circleSegments(radius) + if radius < 5 then + return 8 + elseif radius < 20 then + return 16 + elseif radius < 50 then + return 32 + elseif radius < 100 then + return 64 + else + return 128 + end +end + +local modules = {} + +function ui.registerModule(mode, fun) + if not modules[mode] then + modules[mode] = {} + end + table.insert(modules[mode], { fun = fun, enabled = true }) +end + +function ui.getModules(mode) + return modules[mode] or {} +end + +function ui.registerHandler(name, fun) + pigui.handlers[name] = fun +end + +function ui.registerTheme(name, theme) + assert(type(theme) == "table", "UI Themes must be table values!") + pigui.handlers[name] = theme +end + +ui.registerTheme('default', defaultTheme) + +return ui diff --git a/data/pigui/init.lua b/data/pigui/init.lua index bb817a4605a..0c323e0440e 100644 --- a/data/pigui/init.lua +++ b/data/pigui/init.lua @@ -1,4 +1,18 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -return require 'pigui.pigui' + +-- for some reason, this is required or the functions on Game.Player +-- aren't available later... +local Player = require 'Player' + +local ui = require 'pigui.baseui' + +require 'pigui.libs.text' +require 'pigui.libs.icons' +require 'pigui.libs.buttons' +require 'pigui.libs.radial-menu' +require 'pigui.libs.gauge' + + +return ui diff --git a/data/pigui/libs/buttons.lua b/data/pigui/libs/buttons.lua new file mode 100644 index 00000000000..e4e4e7ddb32 --- /dev/null +++ b/data/pigui/libs/buttons.lua @@ -0,0 +1,141 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +local Engine = require 'Engine' +local ui = require 'pigui.baseui' +local pigui = Engine.pigui + +-- +-- Function: ui.imageButton +-- +-- ui.imageButton(icon, size, frame_padding, bg_color, fg_color, tint_color, tooltip) +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- icon - image to place on button, e.g. from ui.theme.icons +-- size - size of button, Vector2 +-- frame_padding - number +-- bg_color - Color, for background +-- fg_color - Color, for forground +-- tint_color - Color, +-- tooltip - string, mouseover text, will be used as ID, must be unique, append "##uniqueID" if needed +-- +-- Returns: +-- +-- boolean - true if button was clicked +-- +function ui.imageButton(icon, size, frame_padding, bg_color, tint_color, tooltip) + local uv0, uv1 = get_icon_tex_coords(icon) + ui.withID(tooltip, function() + local res = pigui.ImageButton(ui.icons_texture, size, uv0, uv1, frame_padding, bg_color, tint_color) + end) + return res +end + + +-- +-- Function: ui.coloredSelectedButton +-- +-- ui.coloredSelectedButton(label, thesize, is_selected, bg_color, tooltip, enabled) +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- label - string, +-- thesize - Vector2, +-- is_selected - boolean, +-- bg_color - Color, for background +-- fg_color - Color, for forground +-- tint_color - Color, +-- tooltip - string, mouseover text, will be used as ID, must be unique, append "##uniqueID" if needed +-- +-- Returns: +-- +-- boolean - true if button was clicked +-- +function ui.coloredSelectedButton(label, thesize, is_selected, bg_color, tooltip, enabled) + if is_selected then + pigui.PushStyleColor("Button", bg_color) + if enabled then + pigui.PushStyleColor("ButtonHovered", bg_color:tint(0.1)) + pigui.PushStyleColor("ButtonActive", bg_color:tint(0.2)) + else + pigui.PushStyleColor("ButtonHovered", bg_color) + pigui.PushStyleColor("ButtonActive", bg_color) + end + else + pigui.PushStyleColor("Button", bg_color:shade(0.6)) + if enabled then + pigui.PushStyleColor("ButtonHovered", bg_color:shade(0.4)) + pigui.PushStyleColor("ButtonActive", bg_color:shade(0.2)) + else + pigui.PushStyleColor("ButtonHovered", bg_color) + pigui.PushStyleColor("ButtonActive", bg_color) + end + end + --pigui.PushID(label) + local res = pigui.Button(label,thesize) + --pigui.PopID() + pigui.PopStyleColor(3) + if pigui.IsItemHovered() and enabled and tooltip then + pigui.SetTooltip(tooltip) + end + return res +end + +-- +-- Function: ui.coloredSelectedIconButton +-- +-- > clicked = ui.coloredSelectedIconButton(icon, button_size, is_selected, +-- > frame_padding, bg_color, fg_color, tooltip, img_size) +-- +-- +-- Example: +-- +-- > clicked = ui.coloredSelectedIconButton(ui.theme.icons.bullseye, Vector2(10,10), false, +-- > 0, ui.theme.colors.buttonBlue, Color(255,0,0), "Click for action##42", Vector2(8,8)) +-- +-- Parameters: +-- +-- icon - image to place on button, e.g. from ui.theme.icons +-- button_size - size of button, Vector2 +-- is_selected - bool +-- frame_padding - number +-- bg_color - Color(R,G,B), for background +-- fg_color - Color(R,G,B), for forground +-- tooltip - string, mouseover text, will be used as ID, must be unique, append "##uniqueID" if needed +-- img_size - size of icon on the button, Vector2 +-- +-- Returns: +-- +-- clicked - true if button was clicked +-- +ui.coloredSelectedIconButton = function(icon, thesize, is_selected, frame_padding, bg_color, fg_color, tooltipID, img_size) + if is_selected then + pigui.PushStyleColor("Button", bg_color) + pigui.PushStyleColor("ButtonHovered", bg_color:tint(0.1)) + pigui.PushStyleColor("ButtonActive", bg_color:tint(0.2)) + else + pigui.PushStyleColor("Button", bg_color:shade(0.6)) + pigui.PushStyleColor("ButtonHovered", bg_color:shade(0.4)) + pigui.PushStyleColor("ButtonActive", bg_color:shade(0.2)) + end + local uv0,uv1 = ui.get_icon_tex_coords(icon) + pigui.PushID(tooltipID) + local res = pigui.ButtonImageSized(ui.icons_texture, thesize, img_size or Vector2(0,0), uv0, uv1, frame_padding, ui.theme.colors.lightBlueBackground, fg_color) + pigui.PopID() + pigui.PopStyleColor(3) + local pos = tooltipID:find("##") -- get position for id tag start + local pos = pos and pos - 1 -- if found, move back beyond first "#" + local tooltip = pos and string.sub(tooltipID, 1, pos) or tooltipID + if pigui.IsItemHovered() then + pigui.SetTooltip(tooltip) + end + return res +end diff --git a/data/pigui/libs/commodity-market.lua b/data/pigui/libs/commodity-market.lua index 826d3d59cac..623e2f769aa 100644 --- a/data/pigui/libs/commodity-market.lua +++ b/data/pigui/libs/commodity-market.lua @@ -1,27 +1,27 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Game = import 'Game' -local Lang = import 'Lang' -local Format = import 'Format' -local PiImage = import 'ui/PiImage' -local Equipment = import 'Equipment' +local Game = require 'Game' +local Lang = require 'Lang' +local Format = require 'Format' +local PiImage = require 'ui.PiImage' +local Equipment = require 'Equipment' -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local pionillium = ui.fonts.pionillium local orbiteer = ui.fonts.orbiteer -local MarketWidget = import 'pigui/libs/equipment-market.lua' +local MarketWidget = require 'pigui.libs.equipment-market' local l = Lang.GetResource("ui-core") local colors = ui.theme.colors local baseCommodityMarketSize = ui.rescaleUI(Vector2(1592, 654), Vector2(1600, 900)) local baseWidgetSizes = { - rescaleVector = Vector2(1, 1), + rescaleVector = Vector2(1, 1), buySellSize = Vector2(128, 48), buttonSizeBase = Vector2(64, 48), fontSizeLarge = 22.5, -- pionillium.large.size, - fontSizeXLarge = 27, -- pionillium.xlarge.size, + fontSizeXLarge = 27, -- pionillium.xlarge.size, iconSize = Vector2(0, 22.5 * 1.5), smallButton = Vector2(92, 48), bigButton = Vector2(128, 48), @@ -38,345 +38,345 @@ local containerFlags = ui.WindowFlags {"NoScrollbar"} local CommodityMarketWidget = {} function CommodityMarketWidget.New(id, title, config) - local self - - config = config or {} - config.style = config.style or {} - config.style.size = config.style.size or Vector2(0,0) - config.itemTypes = config.itemTypes or { Equipment.cargo } - config.columnCount = config.columnCount or 5 - config.initTable = config.initTable or function(self) - ui.setColumnWidth(0, self.style.widgetSizes.buttonSizeBase.x) - ui.setColumnWidth(1, self.style.size.x / 2 - 50 * self.style.widgetSizes.rescaleVector.x) - end - config.renderHeaderRow = config.renderHeaderRow or function(s) - ui.text('') - ui.nextColumn() - ui.text(l.NAME_OBJECT) - ui.nextColumn() - ui.text(l.PRICE) - ui.nextColumn() - ui.text(l.IN_STOCK) - ui.nextColumn() - ui.text(l.CARGO) - ui.nextColumn() - end - config.renderItem = config.renderItem or function(self, item) - if(self.icons[item.icon_name] == nil) then - self.icons[item.icon_name] = PiImage.New("icons/goods/".. item.icon_name ..".png") - end - self.icons[item.icon_name]:Draw(self.style.widgetSizes.iconSize) - ui.nextColumn() - ui.withStyleVars({ItemSpacing = (self.style.itemSpacing / 2)}, function() - ui.dummy(vZero) - ui.text(item:GetName()) - ui.nextColumn() - ui.dummy(vZero) - ui.text(Format.Money(self.funcs.getBuyPrice(self, item))) - ui.nextColumn() - ui.dummy(vZero) - ui.text(self.funcs.getStock(self, item)) - ui.nextColumn() - ui.dummy(vZero) - local n = Game.player:CountEquip(item) - ui.text(n > 0 and n or '') - end) - ui.nextColumn() - end - config.canDisplayItem = config.canDisplayItem or function (s, e) return e.purchasable and e:IsValidSlot("cargo") and Game.system:IsCommodityLegal(e) end - config.onClickItem = config.onClickItem or function(s,e,k) - s.selectedItem = e - s.tradeModeBuy = true - s:ChangeTradeAmount(-s.tradeAmount) - s:Refresh() - end - - self = MarketWidget.New(id, title, config) - self.icons = {} - self.tradeModeBuy = true; - self.selectedItem = nil - self.tradeAmount = 0 - self.tradeText = '' - self.textColorDefault = Color(255, 255, 255) - self.textColorWarning = Color(255, 255, 0) - self.textColorError = Color(255, 0, 0) - self.tradeTextColor = textColorDefault - self.style.defaults = { - windowPadding = self.windowPadding, - itemSpacing = self.itemSpacing - } - - setmetatable(self, { - __index = CommodityMarketWidget, - class = "UI.CommodityMarketWidget", - }) - - self:SetSize(self.style.size) - return self + local self + + config = config or {} + config.style = config.style or {} + config.style.size = config.style.size or Vector2(0,0) + config.itemTypes = config.itemTypes or { Equipment.cargo } + config.columnCount = config.columnCount or 5 + config.initTable = config.initTable or function(self) + ui.setColumnWidth(0, self.style.widgetSizes.buttonSizeBase.x) + ui.setColumnWidth(1, self.style.size.x / 2 - 50 * self.style.widgetSizes.rescaleVector.x) + end + config.renderHeaderRow = config.renderHeaderRow or function(s) + ui.text('') + ui.nextColumn() + ui.text(l.NAME_OBJECT) + ui.nextColumn() + ui.text(l.PRICE) + ui.nextColumn() + ui.text(l.IN_STOCK) + ui.nextColumn() + ui.text(l.CARGO) + ui.nextColumn() + end + config.renderItem = config.renderItem or function(self, item) + if(self.icons[item.icon_name] == nil) then + self.icons[item.icon_name] = PiImage.New("icons/goods/".. item.icon_name ..".png") + end + self.icons[item.icon_name]:Draw(self.style.widgetSizes.iconSize) + ui.nextColumn() + ui.withStyleVars({ItemSpacing = (self.style.itemSpacing / 2)}, function() + ui.dummy(vZero) + ui.text(item:GetName()) + ui.nextColumn() + ui.dummy(vZero) + ui.text(Format.Money(self.funcs.getBuyPrice(self, item))) + ui.nextColumn() + ui.dummy(vZero) + ui.text(self.funcs.getStock(self, item)) + ui.nextColumn() + ui.dummy(vZero) + local n = Game.player:CountEquip(item) + ui.text(n > 0 and n or '') + end) + ui.nextColumn() + end + config.canDisplayItem = config.canDisplayItem or function (s, e) return e.purchasable and e:IsValidSlot("cargo") and Game.system:IsCommodityLegal(e) end + config.onClickItem = config.onClickItem or function(s,e,k) + s.selectedItem = e + s.tradeModeBuy = true + s:ChangeTradeAmount(-s.tradeAmount) + s:Refresh() + end + + self = MarketWidget.New(id, title, config) + self.icons = {} + self.tradeModeBuy = true + self.selectedItem = nil + self.tradeAmount = 0 + self.tradeText = '' + self.textColorDefault = Color(255, 255, 255) + self.textColorWarning = Color(255, 255, 0) + self.textColorError = Color(255, 0, 0) + self.tradeTextColor = textColorDefault + self.style.defaults = { + windowPadding = self.windowPadding, + itemSpacing = self.itemSpacing + } + + setmetatable(self, { + __index = CommodityMarketWidget, + class = "UI.CommodityMarketWidget", + }) + + self:SetSize(self.style.size) + return self end function CommodityMarketWidget:ChangeTradeAmount(delta) - if self.selectedItem == nil then - return - end + if self.selectedItem == nil then + return + end - --get price of commodity after applying local effects of import/export modifiers - local price = Game.player:GetDockedWith():GetEquipmentPrice(self.selectedItem) + --get price of commodity after applying local effects of import/export modifiers + local price = Game.player:GetDockedWith():GetEquipmentPrice(self.selectedItem) - --do you have any money? - local playerCash = Game.player:GetMoney() + --do you have any money? + local playerCash = Game.player:GetMoney() - --blank value, needs to be initialized or later on lua will complain - local stock + --blank value, needs to be initialized or later on lua will complain + local stock - if self.tradeModeBuy then + if self.tradeModeBuy then price = self.funcs.getBuyPrice(self, self.selectedItem) - stock = self.funcs.getStock(self, self.selectedItem) - if stock == 0 then - self.tradeText = l.NONE_FOR_SALE_IN_THIS_STATION - self.tradeTextColor = textColorError - return - end - if price > playerCash then - self.tradeText = l.INSUFFICIENT_FUNDS - self.tradeTextColor = textColorWarning - return - end - else + stock = self.funcs.getStock(self, self.selectedItem) + if stock == 0 then + self.tradeText = l.NONE_FOR_SALE_IN_THIS_STATION + self.tradeTextColor = textColorError + return + end + if price > playerCash then + self.tradeText = l.INSUFFICIENT_FUNDS + self.tradeTextColor = textColorWarning + return + end + else price = self.funcs.getSellPrice(self, self.selectedItem) - stock = Game.player:CountEquip(self.selectedItem) - end - - --dont alter tradeamount before checks have been made - local wantamount = self.tradeAmount + delta - - --how much would the desired amount of merchandise cost? - local tradecost = wantamount * price - - --we cant trade more units than we have in stock - if delta > 0 and wantamount > stock then --this line is why stock needs to be initialized up there. its possible to get here without stock being set (?) - wantamount = stock - end - - --we dont trade in negative quantities - if wantamount < 0 then - wantamount = 0 - end - - --another empty initialized - self.tradeText = '' - if self.tradeModeBuy then - local playerfreecargo = Game.player.totalCargo - Game.player.usedCargo - if tradecost > playerCash then - wantamount = math.floor(playerCash / price) - end - local tradecargo = self.selectedItem.capabilities.mass * wantamount - if playerfreecargo < tradecargo then - wantamount = math.floor(playerfreecargo / self.selectedItem.capabilities.mass) - end - self.tradeText = l.MARKET_BUYLINE - else --mode = sell - --if market price is negative make sure player wont go below zero credits after the deal - if (playerCash + tradecost) < 0 then - wantamount = self.tradeAmount --kludge, ignore the delta unless player has finances to cover the deal - --if player starts at 0 quantity, presses +100 to "sell" radioactives but only has - --enough credits to sell 5, this kludge will ignore the +100 completely - --todo: change amount to 5 instead - end - self.tradeText = l.MARKET_SELLINE - end - --wantamount is now checked and modified to a safe bounded amount - self.tradeAmount = wantamount - - --current cost of market order if user confirms the deal - tradecost = self.tradeAmount * price - - --its possible to get to this line without tradetext being initialized unless done 30 rows up - self.tradeText = string.interp(self.tradeText,{ amount = string.format("%d", self.tradeAmount), price = Format.Money(tradecost)}) - self.tradeTextColor = self.textColorDefault + stock = Game.player:CountEquip(self.selectedItem) + end + + --dont alter tradeamount before checks have been made + local wantamount = self.tradeAmount + delta + + --how much would the desired amount of merchandise cost? + local tradecost = wantamount * price + + --we cant trade more units than we have in stock + if delta > 0 and wantamount > stock then --this line is why stock needs to be initialized up there. its possible to get here without stock being set (?) + wantamount = stock + end + + --we dont trade in negative quantities + if wantamount < 0 then + wantamount = 0 + end + + --another empty initialized + self.tradeText = '' + if self.tradeModeBuy then + local playerfreecargo = Game.player.totalCargo - Game.player.usedCargo + if tradecost > playerCash then + wantamount = math.floor(playerCash / price) + end + local tradecargo = self.selectedItem.capabilities.mass * wantamount + if playerfreecargo < tradecargo then + wantamount = math.floor(playerfreecargo / self.selectedItem.capabilities.mass) + end + self.tradeText = l.MARKET_BUYLINE + else --mode = sell + --if market price is negative make sure player wont go below zero credits after the deal + if (playerCash + tradecost) < 0 then + wantamount = self.tradeAmount --kludge, ignore the delta unless player has finances to cover the deal + --if player starts at 0 quantity, presses +100 to "sell" radioactives but only has + --enough credits to sell 5, this kludge will ignore the +100 completely + --todo: change amount to 5 instead + end + self.tradeText = l.MARKET_SELLINE + end + --wantamount is now checked and modified to a safe bounded amount + self.tradeAmount = wantamount + + --current cost of market order if user confirms the deal + tradecost = self.tradeAmount * price + + --its possible to get to this line without tradetext being initialized unless done 30 rows up + self.tradeText = string.interp(self.tradeText,{ amount = string.format("%d", self.tradeAmount), price = Format.Money(tradecost)}) + self.tradeTextColor = self.textColorDefault end --player clicked confirm purchase button function CommodityMarketWidget:DoBuy() - if not self.funcs.onClickBuy(self, self.selectedItem) then return end - - local price = self.funcs.getBuyPrice(self, self.selectedItem) - local stock = self.funcs.getStock(self, self.selectedItem) - local playerfreecargo = Game.player.totalCargo - Game.player.usedCargo - local orderAmount = price * self.tradeAmount - - --check cash (should never happen since trade amount buttons wont let it happen) - if orderAmount > Game.player:GetMoney() then - self.popup.msg = l.YOU_NOT_ENOUGH_MONEY - self.popup:open() - return - end - - --check stock - if self.tradeAmount > stock then - self.popup.msg = l.ITEM_IS_OUT_OF_STOCK - self.popup:open() - return - end - - --check cargo limit - local tradecargo = self.selectedItem.capabilities.mass * self.tradeAmount - if playerfreecargo < tradecargo then - self.popup.msg = l.SHIP_IS_FULLY_LADEN - self.popup:open() - return - end - - --all checks passed - assert(Game.player:AddEquip(self.selectedItem, self.tradeAmount, "cargo") == self.tradeAmount) - Game.player:AddMoney(-orderAmount) --grab the money - self.funcs.bought(self, self.selectedItem, self.tradeAmount) - self:ChangeTradeAmount(-self.tradeAmount) --reset the trade amount - - --update market rows - self.tradeAmount = 0; - self:ChangeTradeAmount(0) --update trade amount text - self:Refresh() --rows needs to be recalculated since now the amounts in stock have changed + if not self.funcs.onClickBuy(self, self.selectedItem) then return end + + local price = self.funcs.getBuyPrice(self, self.selectedItem) + local stock = self.funcs.getStock(self, self.selectedItem) + local playerfreecargo = Game.player.totalCargo - Game.player.usedCargo + local orderAmount = price * self.tradeAmount + + --check cash (should never happen since trade amount buttons wont let it happen) + if orderAmount > Game.player:GetMoney() then + self.popup.msg = l.YOU_NOT_ENOUGH_MONEY + self.popup:open() + return + end + + --check stock + if self.tradeAmount > stock then + self.popup.msg = l.ITEM_IS_OUT_OF_STOCK + self.popup:open() + return + end + + --check cargo limit + local tradecargo = self.selectedItem.capabilities.mass * self.tradeAmount + if playerfreecargo < tradecargo then + self.popup.msg = l.SHIP_IS_FULLY_LADEN + self.popup:open() + return + end + + --all checks passed + assert(Game.player:AddEquip(self.selectedItem, self.tradeAmount, "cargo") == self.tradeAmount) + Game.player:AddMoney(-orderAmount) --grab the money + self.funcs.bought(self, self.selectedItem, self.tradeAmount) + self:ChangeTradeAmount(-self.tradeAmount) --reset the trade amount + + --update market rows + self.tradeAmount = 0; + self:ChangeTradeAmount(0) --update trade amount text + self:Refresh() --rows needs to be recalculated since now the amounts in stock have changed end --player clicked the confirm sale button function CommodityMarketWidget:DoSell() - if not self.funcs.onClickSell(self, self.selectedItem) then return end + if not self.funcs.onClickSell(self, self.selectedItem) then return end - local price = self.funcs.getSellPrice(self, self.selectedItem) - local orderamount = price * self.tradeAmount + local price = self.funcs.getSellPrice(self, self.selectedItem) + local orderamount = price * self.tradeAmount - --if commodity price is negative (radioactives, garbage), player needs to have enough cash - Game.player:RemoveEquip(self.selectedItem, self.tradeAmount, "cargo") - Game.player:AddMoney(orderamount) --grab the money + --if commodity price is negative (radioactives, garbage), player needs to have enough cash + Game.player:RemoveEquip(self.selectedItem, self.tradeAmount, "cargo") + Game.player:AddMoney(orderamount) --grab the money self.funcs.sold(self, self.selectedItem, self.tradeAmount) - self:ChangeTradeAmount(-self.tradeAmount) --reset the trade amount + self:ChangeTradeAmount(-self.tradeAmount) --reset the trade amount - --if player sold all his cargo, switch to buy panel - if Game.player:CountEquip(self.selectedItem) == 0 then self.tradeModeBuy = true end + --if player sold all his cargo, switch to buy panel + if Game.player:CountEquip(self.selectedItem) == 0 then self.tradeModeBuy = true end - --update market rows - self.tradeAmount = 0; - self:ChangeTradeAmount(0) --update trade amount text - self:Refresh() --rows needs to be recalculated since now the amounts in stock have changed + --update market rows + self.tradeAmount = 0; + self:ChangeTradeAmount(0) --update trade amount text + self:Refresh() --rows needs to be recalculated since now the amounts in stock have changed end function CommodityMarketWidget:TradeMenu() - if(self.selectedItem) then - ui.withStyleVars({WindowPadding = self.style.windowPadding}, function() - ui.child(self.id .. "TradeMenu", vZero, tradeMenuFlags, function() - if(ui.coloredSelectedButton(l.BUY, self.style.widgetSizes.buySellSize, self.tradeModeBuy, colors.buttonBlue, nil, true)) then - self.tradeModeBuy = true - self:ChangeTradeAmount(-self.tradeAmount) - end - ui.sameLine() - if(ui.coloredSelectedButton(l.SELL, self.style.widgetSizes.buySellSize, not self.tradeModeBuy, colors.buttonBlue, nil, true)) then - self.tradeModeBuy = false - self:ChangeTradeAmount(-self.tradeAmount) - end - - ui.text('') - local bottomHalf = ui.getCursorPos() - bottomHalf.y = bottomHalf.y + ui.getContentRegion().y/1.65 - if(self.icons[self.selectedItem.icon_name] == nil) then - self.icons[self.selectedItem.icon_name] = PiImage.New("icons/goods/".. self.selectedItem.icon_name ..".png") - end - - ui.columns(2, "tradeMenuItemTitle", false) - ui.setColumnWidth(0, self.style.widgetSizes.buttonSizeBase.x) - self.icons[self.selectedItem.icon_name]:Draw(self.style.widgetSizes.iconSize) - ui.nextColumn() - ui.withStyleVars({ItemSpacing = self.style.itemSpacing/2}, function() - ui.withFont(orbiteer.xlarge.name, self.style.widgetSizes.fontSizeLarge, function() - ui.dummy(vZero) - ui.text(self.selectedItem:GetName()) - end) - end) - ui.columns(1, "", false) - ui.text('') - - ui.textWrapped(self.selectedItem:GetDescription()) - - ui.setCursorPos(bottomHalf) - if ui.coloredSelectedButton("-100", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-100) end - ui.sameLine() - if ui.coloredSelectedButton("-10", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-10) end - ui.sameLine() - if ui.coloredSelectedButton("-1", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-1) end - ui.sameLine() - if ui.coloredSelectedButton(l.RESET, self.style.widgetSizes.bigButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-self.tradeAmount) end - ui.sameLine() - if ui.coloredSelectedButton("+1", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(1) end - ui.sameLine() - if ui.coloredSelectedButton("+10", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(10) end - ui.sameLine() - if ui.coloredSelectedButton("+100", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(100) end - - ui.dummy(self.style.itemSpacing/2) - ui.withStyleColors({["Text"] = self.tradeTextColor }, function() - ui.withFont(pionillium.xlarge.name, self.style.widgetSizes.fontSizeLarge, function() - ui.text(self.tradeText) - end) - end) - - ui.setCursorPos(ui.getCursorPos() + Vector2(0, ui.getContentRegion().y - self.style.widgetSizes.confirmButtonSize.y)) - ui.withFont(orbiteer.xlarge.name, self.style.widgetSizes.fontSizeXLarge, function() - if ui.coloredSelectedButton(self.tradeModeBuy and l.CONFIRM_PURCHASE or l.CONFIRM_SALE, self.style.widgetSizes.confirmButtonSize, false, colors.buttonBlue, nil, true) then - if self.tradeModeBuy then self:DoBuy() - else self:DoSell() end - end - end) - end) - end) - end + if(self.selectedItem) then + ui.withStyleVars({WindowPadding = self.style.windowPadding}, function() + ui.child(self.id .. "TradeMenu", vZero, tradeMenuFlags, function() + if(ui.coloredSelectedButton(l.BUY, self.style.widgetSizes.buySellSize, self.tradeModeBuy, colors.buttonBlue, nil, true)) then + self.tradeModeBuy = true + self:ChangeTradeAmount(-self.tradeAmount) + end + ui.sameLine() + if(ui.coloredSelectedButton(l.SELL, self.style.widgetSizes.buySellSize, not self.tradeModeBuy, colors.buttonBlue, nil, true)) then + self.tradeModeBuy = false + self:ChangeTradeAmount(-self.tradeAmount) + end + + ui.text('') + local bottomHalf = ui.getCursorPos() + bottomHalf.y = bottomHalf.y + ui.getContentRegion().y/1.65 + if(self.icons[self.selectedItem.icon_name] == nil) then + self.icons[self.selectedItem.icon_name] = PiImage.New("icons/goods/".. self.selectedItem.icon_name ..".png") + end + + ui.columns(2, "tradeMenuItemTitle", false) + ui.setColumnWidth(0, self.style.widgetSizes.buttonSizeBase.x) + self.icons[self.selectedItem.icon_name]:Draw(self.style.widgetSizes.iconSize) + ui.nextColumn() + ui.withStyleVars({ItemSpacing = self.style.itemSpacing/2}, function() + ui.withFont(orbiteer.xlarge.name, self.style.widgetSizes.fontSizeLarge, function() + ui.dummy(vZero) + ui.text(self.selectedItem:GetName()) + end) + end) + ui.columns(1, "", false) + ui.text('') + + ui.textWrapped(self.selectedItem:GetDescription()) + + ui.setCursorPos(bottomHalf) + if ui.coloredSelectedButton("-100", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-100) end + ui.sameLine() + if ui.coloredSelectedButton("-10", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-10) end + ui.sameLine() + if ui.coloredSelectedButton("-1", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-1) end + ui.sameLine() + if ui.coloredSelectedButton(l.RESET, self.style.widgetSizes.bigButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(-self.tradeAmount) end + ui.sameLine() + if ui.coloredSelectedButton("+1", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(1) end + ui.sameLine() + if ui.coloredSelectedButton("+10", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(10) end + ui.sameLine() + if ui.coloredSelectedButton("+100", self.style.widgetSizes.smallButton, false, colors.buttonBlue, nil, true) then self:ChangeTradeAmount(100) end + + ui.dummy(self.style.itemSpacing/2) + ui.withStyleColors({["Text"] = self.tradeTextColor }, function() + ui.withFont(pionillium.xlarge.name, self.style.widgetSizes.fontSizeLarge, function() + ui.text(self.tradeText) + end) + end) + + ui.setCursorPos(ui.getCursorPos() + Vector2(0, ui.getContentRegion().y - self.style.widgetSizes.confirmButtonSize.y)) + ui.withFont(orbiteer.xlarge.name, self.style.widgetSizes.fontSizeXLarge, function() + if ui.coloredSelectedButton(self.tradeModeBuy and l.CONFIRM_PURCHASE or l.CONFIRM_SALE, self.style.widgetSizes.confirmButtonSize, false, colors.buttonBlue, nil, true) then + if self.tradeModeBuy then self:DoBuy() + else self:DoSell() end + end + end) + end) + end) + end end function CommodityMarketWidget:SetSize(size) - size.x = math.max(size.x, 100) - size.y = math.max(size.y, 100) - if self.style.widgetSize ~= size then - self.style.widgetSize = size - self.style.size = Vector2(size.x / 2, size.y) - - self.style.widgetSizes = ui.rescaleUI( - baseWidgetSizes, - Vector2(1592, 654), --Size the Commodity Market was scaled to during design - true, - size - ) - - self.windowPadding = ui.rescaleUI( - self.style.defaults.windowPadding, - Vector2(1592, 654), --Size the Commodity Market was scaled to during design - true, - size - ) - - self.itemSpacing = ui.rescaleUI( - self.style.defaults.itemSpacing, - Vector2(1592, 654), --Size the Commodity Market was scaled to during design - true, - size - ) - end + size.x = math.max(size.x, 100) + size.y = math.max(size.y, 100) + if self.style.widgetSize ~= size then + self.style.widgetSize = size + self.style.size = Vector2(size.x / 2, size.y) + + self.style.widgetSizes = ui.rescaleUI( + baseWidgetSizes, + Vector2(1592, 654), --Size the Commodity Market was scaled to during design + true, + size + ) + + self.windowPadding = ui.rescaleUI( + self.style.defaults.windowPadding, + Vector2(1592, 654), --Size the Commodity Market was scaled to during design + true, + size + ) + + self.itemSpacing = ui.rescaleUI( + self.style.defaults.itemSpacing, + Vector2(1592, 654), --Size the Commodity Market was scaled to during design + true, + size + ) + end end function CommodityMarketWidget:Refresh() - MarketWidget.refresh(self) + MarketWidget.refresh(self) end function CommodityMarketWidget:Render(size) - self:SetSize(size or ui.getContentRegion()) - - ui.withFont(pionillium.large.name, self.style.widgetSizes.fontSizeLarge, function() - ui.withStyleVars({WindowPadding = vZero, ItemSpacing = self.style.itemSpacing}, function() - ui.child(self.id .. "Container", self.style.widgetSize, containerFlags, function() - MarketWidget.render(self) - ui.sameLine() - self:TradeMenu() - end) - end) - end) + self:SetSize(size or ui.getContentRegion()) + + ui.withFont(pionillium.large.name, self.style.widgetSizes.fontSizeLarge, function() + ui.withStyleVars({WindowPadding = vZero, ItemSpacing = self.style.itemSpacing}, function() + ui.child(self.id .. "Container", self.style.widgetSize, containerFlags, function() + MarketWidget.render(self) + ui.sameLine() + self:TradeMenu() + end) + end) + end) end return CommodityMarketWidget diff --git a/data/pigui/libs/forwarded.lua b/data/pigui/libs/forwarded.lua new file mode 100644 index 00000000000..1c8790dd69a --- /dev/null +++ b/data/pigui/libs/forwarded.lua @@ -0,0 +1,117 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +-- Stuff from the C++ side that we want available directly in Lua +-- without any wrappers +local Engine = require 'Engine' +local pigui = Engine.pigui + +local ui = {} + +ui.calcTextAlignment = pigui.CalcTextAlignment +ui.lineOnClock = pigui.lineOnClock +ui.pointOnClock = pigui.pointOnClock +ui.screenWidth = pigui.screen_width +ui.screenHeight = pigui.screen_height +ui.setNextWindowPos = pigui.SetNextWindowPos +ui.setNextWindowSize = pigui.SetNextWindowSize +ui.setNextWindowSizeConstraints = pigui.SetNextWindowSizeConstraints +ui.dummy = pigui.Dummy +ui.newLine = pigui.NewLine +ui.spacing = pigui.Spacing +ui.text = pigui.Text +ui.combo = pigui.Combo +ui.listBox = pigui.ListBox +ui.textWrapped = pigui.TextWrapped +ui.textColored = pigui.TextColored +ui.inputText = pigui.InputText +ui.checkbox = pigui.Checkbox +ui.separator = pigui.Separator +ui.pushTextWrapPos = pigui.PushTextWrapPos +ui.popTextWrapPos = pigui.PopTextWrapPos +ui.setScrollHere = pigui.SetScrollHere +ui.selectable = pigui.Selectable +ui.progressBar = pigui.ProgressBar +ui.plotHistogram = pigui.PlotHistogram +ui.calcTextSize = pigui.CalcTextSize +ui.addCircle = pigui.AddCircle +ui.addCircleFilled = pigui.AddCircleFilled +ui.addRect = pigui.AddRect +ui.addRectFilled = pigui.AddRectFilled +ui.addLine = pigui.AddLine +ui.addText = pigui.AddText +ui.pathArcTo = pigui.PathArcTo +ui.pathStroke = pigui.PathStroke +ui.setCursorPos = pigui.SetCursorPos +ui.getCursorPos = pigui.GetCursorPos +ui.setCursorScreenPos = pigui.SetCursorScreenPos +ui.getCursorScreenPos = pigui.GetCursorScreenPos +ui.getTextLineHeight = pigui.GetTextLineHeight +ui.getTextLineHeightWithSpacing = pigui.GetTextLineHeightWithSpacing +ui.lowThrustButton = pigui.LowThrustButton +ui.thrustIndicator = pigui.ThrustIndicator +ui.isMouseClicked = pigui.IsMouseClicked +ui.isMouseDown = pigui.IsMouseDown +ui.getMousePos = pigui.GetMousePos +ui.getMouseWheel = pigui.GetMouseWheel +--ui.setTooltip = maybeSetTooltip +ui.shouldDrawUI = pigui.ShouldDrawUI +ui.getWindowPos = pigui.GetWindowPos +ui.getWindowSize = pigui.GetWindowSize +-- available content region +ui.getContentRegion = pigui.GetContentRegion +ui.getTextLineHeight = pigui.GetTextLineHeight +ui.getTextLineHeightWithSpacing = pigui.GetTextLineHeightWithSpacing +ui.getFrameHeight = pigui.GetFrameHeight +ui.getFrameHeightWithSpacing = pigui.GetFrameHeightWithSpacing +ui.getTargetsNearby = pigui.GetTargetsNearby +ui.getProjectedBodies = pigui.GetProjectedBodies +ui.getProjectedBodiesGrouped = pigui.GetProjectedBodiesGrouped +ui.isMouseReleased = pigui.IsMouseReleased +ui.isMouseHoveringRect = pigui.IsMouseHoveringRect +ui.collapsingHeader = pigui.CollapsingHeader +ui.beginPopupModal = pigui.BeginPopupModal +ui.endPopup = pigui.EndPopup +ui.openPopup = pigui.OpenPopup +ui.closeCurrentPopup = pigui.CloseCurrentPopup +ui.shouldShowLabels = pigui.ShouldShowLabels +ui.columns = pigui.Columns +ui.nextColumn = pigui.NextColumn +ui.setColumnOffset = pigui.SetColumnOffset +ui.getColumnWidth = pigui.GetColumnWidth +ui.setColumnWidth = pigui.SetColumnWidth +ui.getScrollY = pigui.GetScrollY +ui.keys = pigui.keys +ui.systemInfoViewNextPage = pigui.SystemInfoViewNextPage -- deprecated +ui.isKeyReleased = pigui.IsKeyReleased +ui.playSfx = pigui.PlaySfx +ui.isItemHovered = pigui.IsItemHovered +ui.isItemActive = pigui.IsItemActive +ui.isItemClicked = pigui.IsItemClicked +ui.isWindowHovered = pigui.IsWindowHovered +ui.vSliderInt = pigui.VSliderInt +ui.sliderInt = pigui.SliderInt +ui.colorEdit = pigui.ColorEdit +ui.nextItemWidth = pigui.NextItemWidth +ui.pushItemWidth = pigui.PushItemWidth +ui.popItemWidth = pigui.PopItemWidth +ui.sliderFloat = pigui.SliderFloat +ui.beginTabBar = pigui.BeginTabBar +ui.beginTabItem = pigui.BeginTabItem +ui.endTabItem = pigui.EndTabItem +ui.endTabBar = pigui.EndTabBar + +-- Flag validation functions. Call with a table of string flags as the only argument. +ui.SelectableFlags = pigui.SelectableFlags +ui.TreeNodeFlags = pigui.TreeNodeFlags +ui.InputTextFlags = pigui.InputTextFlags +ui.WindowFlags = pigui.WindowFlags +ui.HoveredFlags = pigui.HoveredFlags + +ui.button = pigui.Button + +ui.dataDirPath = pigui.DataDirPath +ui.addImage = pigui.AddImage +ui.image = pigui.Image + +return ui diff --git a/data/pigui/libs/gauge.lua b/data/pigui/libs/gauge.lua new file mode 100644 index 00000000000..388621b634f --- /dev/null +++ b/data/pigui/libs/gauge.lua @@ -0,0 +1,71 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +local ui = require 'pigui.baseui' + +local gauge_show_percent = true +ui.gauge_height = 25 +ui.gauge_width = 275 + +-- +-- Function: ui.gauge +-- +-- ui.gauge(position, value, unit, format, minimum, maximum, icon, +-- color, tooltip, width, height, formatFont, percentFont) +-- +-- Display a gauge at the given screen position. +-- +-- +-----+------+-----------------------------+ +-- | XX% | Icon |[Format unit *bar*] | +-- +-----+------+-----------------------------+ +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- position - Vector2, screen position +-- value - number, value to display (clamped between minimum and maximum) +-- unit - string, a unit value to display after the value text. Only shown if format is not nil +-- format - string, a format string used to display the value text. A value of nil will hide the value text +-- minimum - number, the minimum value (0%) +-- maximum - number, the maximum value (100%) +-- icon - number, id of an icon to display next to the guage bar +-- color - Color, color of the gauge bar +-- tooltip - string, tooltip shown on mouseover +-- width - number, width of the gauge +-- height - number, height of the gauge +-- formatFont - +-- percentFont - +-- +-- Returns: +-- +-- nil +-- +ui.gauge = function(position, value, unit, format, minimum, maximum, icon, color, tooltip, width, height, formatFont, percentFont) + local percent = math.clamp((value - minimum) / (maximum - minimum), 0, 1) + local offset = 60 + local uiPos = Vector2(position.x, position.y) + local gauge_width = width or ui.gauge_width + local gauge_height = height or ui.gauge_height + ui.withFont(ui.fonts.pionillium.medium.name, ui.fonts.pionillium.medium.size, function() + ui.addLine(uiPos, Vector2(uiPos.x + gauge_width, uiPos.y), ui.theme.colors.gaugeBackground, gauge_height, false) + if gauge_show_percent then + local one_hundred = ui.calcTextSize("100%") + uiPos.x = uiPos.x + one_hundred.x * 1.2 -- 1.2 for a bit of slack + ui.addStyledText(Vector2(uiPos.x, uiPos.y + gauge_height / 12), ui.anchor.right, ui.anchor.center, string.format("%i%%", percent * 100), ui.theme.colors.reticuleCircle, percentFont or ui.fonts.pionillium.medium, tooltip) + end + uiPos.x = uiPos.x + gauge_height * 1.2 + ui.addIcon(Vector2(uiPos.x - gauge_height / 2, uiPos.y), icon, ui.theme.colors.reticuleCircle, Vector2(gauge_height * 0.9, gauge_height * 0.9), ui.anchor.center, ui.anchor.center, tooltip) + local w = (position.x + gauge_width) - uiPos.x + ui.addLine(uiPos, Vector2(uiPos.x + w * percent, uiPos.y), color, gauge_height, false) + if value and format then + ui.addFancyText(Vector2(uiPos.x + gauge_height/2, uiPos.y + gauge_height/4), ui.anchor.left, ui.anchor.center, { + { text=string.format(format, value), color=ui.theme.colors.reticuleCircle, font=(formatFont or ui.fonts.pionillium.small), tooltip=tooltip }, + { text=unit, color=ui.theme.colors.reticuleCircleDark, font=(formatFont or ui.fonts.pionillium.small), tooltip=tooltip }}, + ui.theme.colors.gaugeBackground) + end + end) +end diff --git a/data/pigui/libs/icons.lua b/data/pigui/libs/icons.lua new file mode 100644 index 00000000000..9bd9f000bbc --- /dev/null +++ b/data/pigui/libs/icons.lua @@ -0,0 +1,157 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +local Engine = require 'Engine' +local ui = require 'pigui.baseui' +local pigui = Engine.pigui + +ui.icons_texture = pigui:LoadTextureFromSVG(pigui.DataDirPath({"icons", "icons.svg"}), 16 * 64, 16 * 64) + +local function get_wide_icon_tex_coords(icon) + assert(icon, "no icon given") + local count = 16.0 -- icons per row/column + local rem = math.floor(icon % count) + local quot = math.floor(icon / count) + return Vector2(rem / count, quot/count), Vector2((rem+2) / count, (quot+1)/count) +end + +-- +-- Function: ui.addIcon +-- +-- ui.addIcon(position, icon, color, size, anchor_horizontal, +-- anchor_vertical, tooltip, angle_rad) +-- +-- Display an icon at the given screen position +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- position - Vector2, screen position +-- icon - number, icon id ie ui.theme.icons.prograde +-- color - Color, icon color +-- size - Vector2, size to display the icon +-- anchor_horizontal - number, one of the following values: +-- - ui.anchor.left (1) +-- - ui.anchor.right (2) +-- - ui.anchor.center (3) +-- anchor_vertical - number, one of the following values: +-- - ui.anchor.top (4) +-- - ui.anchor.center (3) +-- - ui.anchor.bottom (5) +-- tooltip - string, tooltip to be displayed on mouseover +-- angle_rad - number, radians to rotate the icon +-- +-- Returns: +-- +-- number - the size of the icon displayed +-- +function ui.addIcon(position, icon, color, size, anchor_horizontal, anchor_vertical, tooltip, angle_rad) + local pos = ui.calcTextAlignment(position, size, anchor_horizontal, anchor_vertical) + local uv0, uv1 = ui.get_icon_tex_coords(icon) + if angle_rad then + local center = Vector2(pos.x + pos.x + size.x, pos.y + pos.y + size.y) / 2 + local up_left = Vector2(-size.x/2, size.y/2):rotate(angle_rad) + local up_right = up_left:right() + local down_left = up_left:left() + local down_right = -up_left + pigui.AddImageQuad(ui.icons_texture, center + up_left, center + up_right, center + down_right, center + down_left, uv0, Vector2(uv1.x, uv0.y), uv1, Vector2(uv0.x, uv1.y), color) + else + pigui.AddImage(ui.icons_texture, pos, pos + size, uv0, uv1, color) + end + if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then + if pigui.IsMouseHoveringRect(pos, pos + size, true) then + ui.maybeSetTooltip(tooltip) + end + end + return size +end + +-- +-- Function: ui.addWideIcon +-- +-- ui.addWideIcon(position, icon, color, size, anchor_horizontal, +-- anchor_vertical, tooltip, angle_rad) +-- +-- Display a wide, double width, icon at the given screen position +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- position - Vector2, screen position +-- icon - number, icon id ie ui.theme.icons.prograde +-- color - Color, icon color +-- size - Vector2, size to display the icon +-- anchor_horizontal - number, one of the following values: +-- - ui.anchor.left (1) +-- - ui.anchor.right (2) +-- - ui.anchor.center (3) +-- anchor_vertical - number, one of the following values: +-- - ui.anchor.top (4) +-- - ui.anchor.center (3) +-- - ui.anchor.bottom (5) +-- tooltip - string, tooltip to be displayed on mouseover +-- angle_rad - number, radians to rotate the icon +-- +-- Returns: +-- +-- number - the size of the icon displayed +-- +function ui.addWideIcon(position, icon, color, size, anchor_horizontal, anchor_vertical, tooltip, angle_rad) + local pos = ui.calcTextAlignment(position, size, anchor_horizontal, anchor_vertical) + local uv0, uv1 = get_wide_icon_tex_coords(icon) + if angle_rad then + local center = (pos + pos + size) / 2 + local up_left = Vector2(-size.x/2, size.y/2):rotate2d(angle_rad) + local up_right = up_left:right() + local down_left = up_left:left() + local down_right = -up_left + pigui.AddImageQuad(ui.icons_texture, center + up_left, center + up_right, center + down_right, center + down_left, uv0, Vector2(uv1.x, uv0.y), uv1, Vector2(uv0.x, uv1.y), color) + else + pigui.AddImage(ui.icons_texture, pos, pos + size, uv0, uv1, color) + end + if tooltip and (ui.isMouseHoveringWindow() or not is.isAnyWindowHovered()) and tooltip ~= "" then + if pigui.IsMouseHoveringRect(pos, pos + size, true) then + ui.maybeSetTooltip(tooltip) + end + end + + return size +end + +-- +-- Function: ui.addWideIcon +-- +-- ui.addWideIcon(icon, size, color, tooltip) +-- +-- Display an icon +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- icon - number, icon id ie ui.theme.icons.prograde +-- size - Vector2, size to display the icon +-- color - Color, icon color +-- tooltip - string, tooltip to be displayed on mouseover +-- +-- Returns: +-- +-- nil +-- +function ui.icon(icon, size, color, tooltip) + local uv0, uv1 = ui.get_icon_tex_coords(icon) + pigui.Image(ui.icons_texture, size, uv0, uv1, color) + if tooltip and ui.isItemHovered() then + ui.setTooltip(tooltip) + end +end diff --git a/data/pigui/libs/modal-win.lua b/data/pigui/libs/modal-win.lua index 4b18dca033b..bada64de345 100644 --- a/data/pigui/libs/modal-win.lua +++ b/data/pigui/libs/modal-win.lua @@ -1,7 +1,7 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local modals = {} local modalStack = {} diff --git a/data/pigui/libs/radial-menu.lua b/data/pigui/libs/radial-menu.lua new file mode 100644 index 00000000000..787e9d86142 --- /dev/null +++ b/data/pigui/libs/radial-menu.lua @@ -0,0 +1,186 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +local Lang = require 'Lang' +local Engine = require 'Engine' +local pigui = Engine.pigui +local Game = require 'Game' +local ui = require 'pigui.baseui' + +local lc = Lang.GetResource("core") + + +local shouldShowRadialMenu = false +local radialMenuPos = Vector2(0,0) +local radialMenuSize = 10 +local radialMenuTarget = nil +local radialMenuMouseButton = 1 +local radialMenuActions = {} +local radialMenuMousePos = nil + +-- +-- Function: ui.openRadialMenu +-- +-- ui.openRadialMenu(target, mouse_button, size, actions) +-- +-- Show a radial menu +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- target - +-- mouse_button - +-- size - +-- action - table +-- +-- Returns: +-- +-- nil +-- +function ui.openRadialMenu(target, mouse_button, size, actions) + ui.openPopup("##radialmenupopup") + shouldShowRadialMenu = true + radialMenuTarget = target + radialMenuPos = ui.getMousePos() + radialMenuSize = size + radialMenuMouseButton = mouse_button + radialMenuActions = actions + radialMenuMousePos = ui.getMousePos() + -- move away from screen edge + radialMenuPos.x = math.min(math.max(radialMenuPos.x, size*3), ui.screenWidth - size*3) + radialMenuPos.y = math.min(math.max(radialMenuPos.y, size*3), ui.screenHeight - size*3) +end + +-- TODO: add cloud Lang::SET_HYPERSPACE_TARGET_TO_FOLLOW_THIS_DEPARTURE +local radial_menu_actions_station = { + {icon=ui.theme.icons.comms, tooltip=lc.REQUEST_DOCKING_CLEARANCE, + action=function(target) + local msg = Game.player:RequestDockingClearance(target) + Game.AddCommsLogLine(msg, target.label) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + end}, + {icon=ui.theme.icons.autopilot_dock, tooltip=lc.AUTOPILOT_DOCK_WITH_STATION, + action=function(target) + if next(Game.player:GetEquip('autopilot')) ~= nil then + Game.player:SetFlightControlState("CONTROL_AUTOPILOT") + Game.player:AIDockWith(target) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + else + Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) + end + end}, +} + +local radial_menu_actions_all_bodies = { + {icon=ui.theme.icons.autopilot_fly_to, tooltip=lc.AUTOPILOT_FLY_TO_VICINITY_OF, + action=function(target) + if next(Game.player:GetEquip('autopilot')) ~= nil then + Game.player:SetFlightControlState("CONTROL_AUTOPILOT") + Game.player:AIFlyTo(target) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + else + Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) + end + end}, +} + +local radial_menu_actions_systembody = { + {icon=ui.theme.icons.autopilot_low_orbit, tooltip=lc.AUTOPILOT_ENTER_LOW_ORBIT_AROUND, + action=function(target) + if next(Game.player:GetEquip('autopilot')) ~= nil then + Game.player:SetFlightControlState("CONTROL_AUTOPILOT") + Game.player:AIEnterLowOrbit(target) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + else + Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) + end + end}, + {icon=ui.theme.icons.autopilot_medium_orbit, tooltip=lc.AUTOPILOT_ENTER_MEDIUM_ORBIT_AROUND, + action=function(target) + if next(Game.player:GetEquip('autopilot')) ~= nil then + Game.player:SetFlightControlState("CONTROL_AUTOPILOT") + Game.player:AIEnterMediumOrbit(target) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + else + Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) + end + end}, + {icon=ui.theme.icons.autopilot_high_orbit, tooltip=lc.AUTOPILOT_ENTER_HIGH_ORBIT_AROUND, + action=function(target) + if next(Game.player:GetEquip('autopilot')) ~= nil then + Game.player:SetFlightControlState("CONTROL_AUTOPILOT") + Game.player:AIEnterHighOrbit(target) + Game.player:SetNavTarget(target) + ui.playSfx("OK") + else + Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) + end + end}, +} + +function ui.openDefaultRadialMenu(body) + if body then + local actions = {} + for _,v in pairs(radial_menu_actions_all_bodies) do + table.insert(actions, v) + end + if body:IsStation() then + for _,v in pairs(radial_menu_actions_station) do + table.insert(actions, v) + end + elseif body:GetSystemBody() then + for _,v in pairs(radial_menu_actions_systembody) do + table.insert(actions, v) + end + end + ui.openRadialMenu(body, 1, 30, actions) + end +end + +local radialMenuWasOpen = {} +function ui.radialMenu(id) + if not radialMenuActions or #radialMenuActions == 0 then + return + end + local icons = {} + local tooltips = {} + for _,action in pairs(radialMenuActions) do + local uv0, uv1 = ui.get_icon_tex_coords(action.icon) + table.insert(icons, { id = ui.icons_texture, uv0 = uv0, uv1 = uv1 }) + -- TODO: don't just assume that radialMenuTarget is a Body + table.insert(tooltips, string.interp(action.tooltip, { target = radialMenuTarget and radialMenuTarget.label or "UNKNOWN" })) + end + local n = pigui.RadialMenu(radialMenuPos, "##radialmenupopup", radialMenuMouseButton, icons, radialMenuSize, tooltips) + if n == -1 then + pigui.DisableMouseFacing(true) + radialMenuWasOpen[id] = true + elseif n >= 0 or n == -2 then + radialMenuWasOpen[id] = false + shouldShowRadialMenu = false + local target = radialMenuTarget + radialMenuTarget = nil + pigui.DisableMouseFacing(false) + -- hack, imgui lets the press go through, but eats the release, so Pi still thinks rmb is held + pigui.SetMouseButtonState(3, false); + -- ui.setMousePos(radialMenuMousePos) + -- do this last, so it can theoretically open a new radial menu + -- though we can't as no button is pressed that could be released :-/ + if n >= 0 then + radialMenuActions[n+1].action(target) + end + end + if n == -3 and radialMenuWasOpen[id] then + pigui.SetMouseButtonState(3, false) + pigui.DisableMouseFacing(false) + radialMenuWasOpen[id] = false + end + return n +end diff --git a/data/pigui/libs/text-table.lua b/data/pigui/libs/text-table.lua index d8e70ee2ceb..91f5dfd39d2 100644 --- a/data/pigui/libs/text-table.lua +++ b/data/pigui/libs/text-table.lua @@ -1,7 +1,7 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local textTable = {} diff --git a/data/pigui/libs/text.lua b/data/pigui/libs/text.lua new file mode 100644 index 00000000000..bb5b941eb78 --- /dev/null +++ b/data/pigui/libs/text.lua @@ -0,0 +1,257 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +local Engine = require 'Engine' +local Lang = require 'Lang' +local Game = require 'Game' +local ui = require 'pigui.baseui' +local pigui = Engine.pigui + +local lc = Lang.GetResource("core"); + +local font_factor = ui.rescaleUI(1, Vector2(1920, 1200)) + +local textBackgroundMarginPixels = 2 + + + +ui.fonts = { + -- dummy font, actually renders icons + pionicons = { + small = { name = "icons", size = 16 * font_factor, offset = 14 * font_factor}, + medium = { name = "icons", size = 18 * font_factor, offset = 20 * font_factor}, + large = { name = "icons", size = 22 * font_factor, offset = 28 * font_factor} + }, + pionillium = { + xlarge = { name = "pionillium", size = 36 * font_factor, offset = 24 * font_factor }, + large = { name = "pionillium", size = 30 * font_factor, offset = 24 * font_factor}, + medlarge = { name = "pionillium", size = 24 * font_factor, offset = 18 * font_factor}, + medium = { name = "pionillium", size = 18 * font_factor, offset = 14 * font_factor}, + -- medsmall = { name = "pionillium", size = 15, offset = 12 }, + small = { name = "pionillium", size = 14 * font_factor, offset = 11 * font_factor}, + tiny = { name = "pionillium", size = 8 * font_factor, offset = 7 * font_factor}, + }, + orbiteer = { + xlarge = { name = "orbiteer", size = 36 * font_factor, offset = 24 * font_factor }, + large = { name = "orbiteer", size = 30 * font_factor, offset = 24 * font_factor }, + medlarge = { name = "orbiteer", size = 24 * font_factor, offset = 20 * font_factor}, + medium = { name = "orbiteer", size = 20 * font_factor, offset = 16 * font_factor}, + small = { name = "orbiteer", size = 14 * font_factor, offset = 11 * font_factor}, + tiny = { name = "orbiteer", size = 8 * font_factor, offset = 7 * font_factor}, + }, +} + +ui.Format = { + Latitude = function(decimal_degrees) + local prefix = lc.LATITUDE_NORTH_ABBREV + if decimal_degrees < 0 then + prefix = lc.LATITUDE_SOUTH_ABBREV + decimal_degrees = math.abs(decimal_degrees) + end + local deg = math.floor(decimal_degrees) + local min = (decimal_degrees - deg) * 60 + local sec = (min - math.floor(min)) * 60 + return string.format('%s %03i°%02i\'%02i"', prefix, deg, min, sec) + end, + Longitude = function(decimal_degrees) + local prefix = lc.LONGITUDE_EAST_ABBREV + if decimal_degrees < 0 then + prefix = lc.LONGITUDE_WEST_ABBREV + decimal_degrees = math.abs(decimal_degrees) + end + local deg = math.floor(decimal_degrees) + local min = (decimal_degrees - deg) * 60 + local sec = (min - math.floor(min)) * 60 + return string.format('%s %03i°%02i\'%02i"', prefix, deg, min, sec) + end, + Duration = function(duration, elements) + -- shown elements items (2 -> wd or dh, 3 -> dhm or hms) + local negative = false + if duration < 0 then + duration = math.abs(duration) + negative = true + end + local seconds = math.floor(duration % 60) + local minutes = math.floor(duration / 60 % 60) + local hours = math.floor(duration / 60 / 60 % 24) + local days = math.floor(duration / 60 / 60 / 24 % 7) + local weeks = math.floor(duration / 60 / 60 / 24 / 7) + local i = elements or 5 + local count = false + local result = "" + if i > 0 then + if weeks ~= 0 then + result = result .. weeks .. "w" + count = true + end + if count then + i = i - 1 + end + end + if i > 0 then + if days ~= 0 then + result = result .. days .. "d" + count = true + end + if count then + i = i - 1 + end + end + if i > 0 then + if hours ~= 0 then + result = result .. hours .. "h" + count = true + end + if count then + i = i - 1 + end + end + if i > 0 then + if minutes ~= 0 then + result = result .. minutes .. "m" + count = true + end + if count then + i = i - 1 + end + end + if i > 0 then + if seconds ~= 0 then + result = result .. seconds .. "s" + count = true + end + if result == "" then + result = "0s" + end + if count then + i = i - 1 + end + end + if negative then + result = "-" .. result + end + return result + end, + Distance = function(distance) + local d = math.abs(distance) + if d < 1000 then + return math.floor(distance), lc.UNIT_METERS + end + if d < 1000*1000 then + return string.format("%0.2f", distance / 1000), lc.UNIT_KILOMETERS + end + if d < 1000*1000*1000 then + return string.format("%0.2f", distance / 1000 / 1000), lc.UNIT_MILLION_METERS + end + return string.format("%0.2f", distance / 1.4960e11), lc.UNIT_AU + end, + Speed = function(distance) + local d = math.abs(distance) + if d < 1000 then + return math.floor(distance), lc.UNIT_METERS_PER_SECOND + end + if d < 1000*1000 then + return string.format("%0.2f", distance / 1000), lc.UNIT_KILOMETERS_PER_SECOND + end + return string.format("%0.2f", distance / 1000 / 1000), lc.UNIT_MILLION_METERS_PER_SECOND + -- no need for au/s + end, + Datetime = function(date) + local second, minute, hour, day, month, year = Game.GetPartsFromDateTime(date) + return string.format("%4i-%02i-%02i %02i:%02i:%02i", year, month, day, hour, minute, second) + end +} + +ui.addFancyText = function(position, anchor_horizontal, anchor_vertical, data, bg_color) + -- always align texts at baseline + local spacing = 2 + local size = Vector2(0, 0) + local max_offset = 0 + for i=1,#data do + local item = data[i] + assert(item.text, "missing text for item in addFancyText") + assert(item.font, "missing font for item in addFancyText") + assert(item.color, "missing font for item in addFancyText") + + local is_icon = item.font.name ~= "icons" + local s + local popfont + if is_icon then + popfont = pigui:PushFont(item.font.name, item.font.size) + s = pigui.CalcTextSize(item.text) + else + s = Vector2(item.font.size, item.font.size) + end + size.x = size.x + s.x + size.x = size.x + spacing -- spacing + size.y = math.max(size.y, s.y) + max_offset = math.max(max_offset, item.font.offset) + if is_icon then + if popfont then + pigui.PopFont() + end + end + end + size.x = size.x - spacing -- remove last spacing + position = ui.calcTextAlignment(position, size, anchor_horizontal, nil) + if anchor_vertical == ui.anchor.top then + position.y = position.y + size.y -- was max_offset, seems wrong + elseif anchor_vertical == ui.anchor.bottom then + position.y = position.y - size.y + max_offset + end + if bg_color then + pigui.AddRectFilled(position - Vector2(textBackgroundMarginPixels, size.y + textBackgroundMarginPixels), + position + Vector2(size.x + textBackgroundMarginPixels, textBackgroundMarginPixels), + bg_color, + 0, + 0) + end + for i=1,#data do + local item = data[i] + local is_icon = item.font.name ~= "icons" + if is_icon then + ui.withFont(item.font.name, item.font.size, function() + local s = ui.addStyledText(position, ui.anchor.left, ui.anchor.baseline, item.text, item.color, item.font, item.tooltip) + position.x = position.x + s.x + spacing + end) + else + local s = ui.addIcon(position, item.text, item.color, Vector2(item.font.size, item.font.size), ui.anchor.left, ui.anchor.bottom, item.tooltip) + position.x = position.x + s.x + spacing + end + end + return size +end + +ui.addStyledText = function(position, anchor_horizontal, anchor_vertical, text, color, font, tooltip, bg_color) + -- addStyledText aligns to upper left + local size = Vector2(0, 0) + ui.withFont(font.name, font.size, function() + size = pigui.CalcTextSize(text) + local vert + if anchor_vertical == ui.anchor.baseline then + vert = nil + else + vert = anchor_vertical + end + position = ui.calcTextAlignment(position, size, anchor_horizontal, vert) -- ignore vertical if baseline + if anchor_vertical == ui.anchor.baseline then + position.y = position.y - font.offset + end + if bg_color then + pigui.AddRectFilled(Vector2(position.x - textBackgroundMarginPixels, position.y - textBackgroundMarginPixels), + Vector2(position.x + size.x + textBackgroundMarginPixels, position.y + size.y + textBackgroundMarginPixels), + bg_color, + 0, + 0) + end + pigui.AddText(position, color, text) + -- pigui.AddQuad(position, position + Vector2(size.x, 0), position + Vector2(size.x, size.y), position + vector.new(0, size.y), colors.red, 1.0) + end) + if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then + if pigui.IsMouseHoveringRect(position, position + size, true) then + ui.maybeSetTooltip(tooltip) + end + end + return size +end + + diff --git a/data/pigui/libs/wrappers.lua b/data/pigui/libs/wrappers.lua new file mode 100644 index 00000000000..428642e31c8 --- /dev/null +++ b/data/pigui/libs/wrappers.lua @@ -0,0 +1,750 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +-- Convenience wrappers for the C++ UI functions and general functions +local Engine = require 'Engine' +local Game = require 'Game' +local utils = require 'utils' +local pigui = Engine.pigui +local ui = require 'pigui.libs.forwarded' + +-- +-- Function: ui.rescaleUI +-- +-- ui.rescaleUI(val, baseResolution, rescaleToScreenAspect, targetResolution) +-- +-- Scales a set of values (normally a size or a position) based on a base +-- resolution and the current or target resultion. +-- +-- +-- Example: +-- +-- > size = ui.rescaleUI(Vector2(96, 96), Vector2(1600, 900)) +-- +-- Parameters: +-- +-- val - number|Vector2|Table, the values to scale +-- baseResolution - Vector2, the resolution at which val is valid +-- rescaleToScreenAspect - (Optional) number, when scaling a Vector2, scale x and y +-- appropriately to match the given aspect ratio +-- targetResolution - (Optional) Vector2, the target resolution to scale +-- the value to. Default: current screen resolution. +-- +-- Returns: +-- +-- number|Vector2|Table - the scaled value +-- +function ui.rescaleUI(val, baseResolution, rescaleToScreenAspect, targetResolution) + if not targetResolution then + targetResolution = Vector2(pigui.screen_width, pigui.screen_height) + end + + local rescaleVector = Vector2(targetResolution.x / baseResolution.x, targetResolution.y / baseResolution.y) + local rescaleFactor = math.min(rescaleVector.x, rescaleVector.y) + local type = type(val) + + if type == 'table' then + local result = {} + for k, v in pairs(val) do + result[k] = ui.rescaleUI(v, baseResolution, rescaleToScreenAspect, targetResolution) + end + + return result + elseif type == 'userdata' and val.x and val.y then + return Vector2(val.x * ((rescaleToScreenAspect and rescaleVector.x) or rescaleFactor), val.y * ((rescaleToScreenAspect and rescaleVector.y) or rescaleFactor)) + elseif type == 'number' then + return val * rescaleFactor + end +end + +-- +-- Function: ui.pcall +-- +-- ui.pcall(fun, ...) +-- +-- Clean up the ImGui stack in case of an error +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- fun - +-- ... - +-- +-- Returns: +-- +-- nil +-- +function ui.pcall(fun, ...) + local stack = pigui.GetImguiStack() + return xpcall(fun, function(msg) + return msg .. pigui.CleanupImguiStack(stack) + end, ...) +end + +-- +-- Function: ui.window +-- +-- ui.window(name, params, fun) +-- +-- Display a window +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- name - String, a unique name for the window, +-- used to group its children +-- params - Table, window options: +-- - NoTitleBar : Disable title-bar +-- - NoResize : Disable user resizing with the lower-right grip +-- - NoMove : Disable user moving the window +-- - NoScrollbar : Disable scrollbars (window can still scroll with +-- mouse or programmatically) +-- - NoScrollWithMouse : Disable user vertically scrolling with mouse wheel. +-- On child window, mouse wheel will be forwarded to +-- the parent unless NoScrollbar is also set. +-- - NoCollapse : Disable user collapsing window by double-clicking +-- on it +-- - AlwaysAutoResize : Resize every window to its content every frame +-- - NoSavedSettings : Never load/save settings in .ini file +-- - NoInputs : +-- - MenuBar : Has a menu-bar +-- - HorizontalScrollbar : Allow horizontal scrollbar to appear (off by default). +-- - NoFocusOnAppearing : Disable taking focus when transitioning from hidden to +-- visible state +-- - NoBringToFrontOnFocus : Disable bringing window to front when taking focus +-- (e.g. clicking on it or programmatically giving it +-- focus) +-- - AlwaysVerticalScrollbar : Always show vertical scrollbar +-- - AlwaysHorizontalScrollbar : Always show horizontal scrollbar +-- - AlwaysUseWindowPadding : Ensure child windows without border uses +-- style.WindowPadding (ignored by default for +-- non-bordered child windows, because more convenient) +-- fun - Function, a function that is called to define the window contents +-- +-- Returns: +-- +-- nil +-- +function ui.window(name, params, fun) + local ok = pigui.Begin(name, params) + if ok then fun() end + pigui.End() +end + +-- +-- Function: ui.group +-- +-- ui.group(fun) +-- +-- Display items in a group +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- fun - Function, a function that is called to define the group contents +-- +-- Returns: +-- +-- nil +-- +function ui.group(fun) + pigui.BeginGroup() + fun() + pigui.EndGroup() +end + +-- +-- Function: ui.popup +-- +-- ui.popup(name, params, fun) +-- +-- Display a popup window +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- name - String, a unique name for the window, +-- used to group its children +-- fun - Function, a function that is called to define the popup contents +-- +-- Returns: +-- +-- nil +-- +function ui.popup(name, fun) + if pigui.BeginPopup(name) then + fun() + pigui.EndPopup() + end +end + +-- +-- Function: ui.child +-- +-- ui.child(id, size, flags, fun) +-- +-- Define a child window +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- id - String, a unique name for the window, +-- used to group its children +-- size - (Optional)Vector2 +-- flags - (Optional)Table, options: +-- - NoTitleBar : Disable title-bar +-- - NoResize : Disable user resizing with the lower-right grip +-- - NoMove : Disable user moving the window +-- - NoScrollbar : Disable scrollbars (window can still scroll with +-- mouse or programmatically) +-- - NoScrollWithMouse : Disable user vertically scrolling with mouse wheel. +-- On child window, mouse wheel will be forwarded to +-- the parent unless NoScrollbar is also set. +-- - NoCollapse : Disable user collapsing window by double-clicking +-- on it +-- - AlwaysAutoResize : Resize every window to its content every frame +-- - NoSavedSettings : Never load/save settings in .ini file +-- - NoInputs : +-- - MenuBar : Has a menu-bar +-- - HorizontalScrollbar : Allow horizontal scrollbar to appear (off by default). +-- - NoFocusOnAppearing : Disable taking focus when transitioning from hidden to +-- visible state +-- - NoBringToFrontOnFocus : Disable bringing window to front when taking focus +-- (e.g. clicking on it or programmatically giving it +-- focus) +-- - AlwaysVerticalScrollbar : Always show vertical scrollbar +-- - AlwaysHorizontalScrollbar : Always show horizontal scrollbar +-- - AlwaysUseWindowPadding : Ensure child windows without border uses +-- style.WindowPadding (ignored by default for +-- non-bordered child windows, because more convenient) +-- fun - Function, a function that is called to define the popup contents +-- +-- Returns: +-- +-- nil +-- +function ui.child(id, size, flags, fun) + if flags == nil and fun == nil then -- size is optional + fun = size + size = Vector2(-1,-1) + flags = {} + elseif fun == nil then + fun = flags + flags = {} + end + + pigui.BeginChild(id, size, flags) + fun() + pigui.EndChild() +end + +-- +-- Function: ui.withTooltip +-- +-- ui.withTooltip(tooltip, fun) +-- +-- Display something, but with a tooltip shown on mouseover +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- tooltip - String, the tooltip to display +-- fun - Function, a function that is called to display the contents +-- that will have the tooltip +-- +-- Returns: +-- +-- nil +-- +function ui.withTooltip(tooltip, fun) + local startPos = pigui.GetCursorPos() + fun() + if string.len(tooltip) > 0 then + local endPos = pigui.GetCursorPos() + local offset = pigui.GetWindowPos() + offset.y = offset.y - pigui.GetScrollY() + if pigui.IsMouseHoveringRect(offset + startPos, offset + endPos, false) then + pigui.SetTooltip(tooltip) + end + end +end + +-- +-- Function: ui.playBoinkNoise +-- +-- ui.playBoinkNoise() +-- +-- Boink! +-- +-- Example: +-- +-- > ui.playBoinkNoise() +-- +-- Parameters: +-- +-- Returns: +-- +-- nil +-- +function ui.playBoinkNoise() + ui.playSfx("Click", 0.3) +end + +-- +-- Function: ui.isMouseHoveringWindow +-- +-- ui.isMouseHoveringWindow() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if the mouse is currently within the current +-- window, false otherwise +-- +function ui.isMouseHoveringWindow() + return ui.isWindowHovered({"AllowWhenBlockedByPopup", "AllowWhenBlockedByActiveItem"}) +end + +-- +-- Function: ui.isAnyWindowHovered +-- +-- ui.isAnyWindowHovered() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if the mouse is currently within any window, +-- false otherwise +-- +function ui.isAnyWindowHovered() + return ui.isWindowHovered({"AnyWindow"}) +end + +-- +-- Function: ui.ctrlHeld +-- +-- ui.ctrlHeld() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if a ctrl key is being held +-- +function ui.ctrlHeld() return pigui.key_ctrl end + +-- +-- Function: ui.altHeld +-- +-- ui.altHeld() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if an alt key is being held +-- +function ui.altHeld() return pigui.key_alt end + +-- +-- Function: ui.shiftHeld +-- +-- ui.shiftHeld() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if a shift key is being held +-- +function ui.shiftHeld() return pigui.key_shift end + +-- +-- Function: ui.noModifierHeld +-- +-- ui.noModifierHeld() +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- boolean - true if no modifier (alt, shift, ctrl) keys are being held +-- +function ui.noModifierHeld() return pigui.key_none end + +-- +-- Function: ui.tabBar +-- +-- ui.tabBar(id, items) +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- id - String, unique id to identify the group of tabs by +-- items - Table, a list of contents. Each item should be a +-- table containing a table of tab options and a function +-- to call that displays the tabs contents +-- +-- Returns: +-- +-- boolean - true if the tab bar is open, false otherwise +-- +function ui.tabBar(id, items) + local open = pigui.BeginTabBar(id) + if not open then return false end + + for i, v in ipairs(items) do + if type(v) == "table" and v[1] and type(v[2]) == "function" then + if pigui.BeginTabItem(tostring(v[1]) .. "##" .. tostring(i)) then + v[2](v) + end + end + end + + pigui.EndTabBar() + return true +end + +-- +-- Function: ui.withFont +-- +-- ui.withFont(name, size, fun) +-- +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- name - Table|String, a table defining the font name and size or +-- a string containing the name of the font +-- size - (Optional) number, font size. Optional if name is a table and defines size +-- fun - function, a function to call that shows the contents with the defined font +-- +-- Returns: +-- +-- any - the value returned from fun +-- +function ui.withFont(name, size, fun) + -- allow `withFont(fontObj, fun)` + if type(name) == "table" and type(size) == "function" then + name, size, fun = table.unpack{name.name, name.size, size} + end + + local font = pigui:PushFont(name, size) + local res = fun() + if font then + pigui.PopFont() + end + return res +end + +-- +-- Function: ui.withStyleColors +-- +-- ui.withStyleColors(styles, fun) +-- +-- Display UI content with defined colors +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- styles - table, table of style elements with the desired colors: +-- Text, TextDisabled, WindowBg, ChildWindowBg, PopupBg, Border, +-- BorderShadow, FrameBg, FrameBgHovered, FrameBgActive,TitleBg, +-- TitleBgCollapsed, TitleBgActive, MenuBarBg, ScrollbarBg, +-- ScrollbarGrab, ScrollbarGrabHovered, ScrollbarGrabActive, +-- CheckMark, SliderGrab, SliderGrabActive, Button, +-- ButtonHovered, ButtonActive, Header, HeaderHovered, +-- HeaderActive, Separator, SeparatorHovered, SeparatorActive, +-- ResizeGrip, ResizeGripHovered, ResizeGripActive, PlotLines, +-- PlotLinesHovered, PlotHistogram, PlotHistogramHovered, +-- TextSelectedBg, ModalWindowDarkening +-- fun - function, a function to call that shows the contents with the defined font +-- +-- Returns: +-- +-- any - the value returned from fun +-- +function ui.withStyleColors(styles, fun) + for k,v in pairs(styles) do + pigui.PushStyleColor(k, v) + end + local res = fun() + pigui.PopStyleColor(utils.count(styles)) + return res +end + +-- +-- Function: ui.withStyleVars +-- +-- ui.withStyleVars(styles, fun) +-- +-- Display UI content with defined styles +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- vars - table, table of style elements with the desired values: +-- Alpha, WindowPadding, WindowRounding, WindowBorderSize, +-- WindowMinSize, ChildRounding, ChildBorderSize, FramePadding, +-- FrameRounding, FrameBorderSize, ItemSpacing, +-- ItemInnerSpacing, IndentSpacing, GrabMinSize, +-- ButtonTextAlign +-- fun - function, a function to call that shows the contents with the defined font +-- +-- Returns: +-- +-- any - the value returned from fun +-- +function ui.withStyleVars(vars, fun) + for k,v in pairs(vars) do + pigui.PushStyleVar(k, v) + end + local res = fun() + pigui.PopStyleVar(utils.count(vars)) + return res +end + +-- +-- Function: ui.withStyleColorsAndVars +-- +-- ui.withStyleColorsAndVars(styles, vars, fun) +-- +-- Display UI content with defined styles and colors +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- styles - table, table of style elements with the desired colors (see ui.withStyleColors) +-- vars - table, table of style elements with the desired values (see ui.withStyleVars) +-- fun - function, a function to call that shows the contents with the defined font +-- +-- Returns: +-- +-- any - the value returned from fun +-- +function ui.withStyleColorsAndVars(styles, vars, fun) + for k,v in pairs(styles) do + pigui.PushStyleColor(k, v) + end + for k,v in pairs(vars) do + pigui.PushStyleVar(k, v) + end + local res = fun() + pigui.PopStyleVar(utils.count(vars)) + pigui.PopStyleColor(utils.count(styles)) + return res +end + +-- +-- Function: ui.screenSize +-- +-- ui.screenSize() +-- +-- Return the current screen resolution as a Vector2 +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- +-- Returns: +-- +-- Vector2 - screen width and height +-- +function ui.screenSize() + return Vector2(ui.screenWidth, ui.screenHeight) +end + +-- +-- Function: ui.setNextWindowPosCenter +-- +-- ui.setNextWindowPosCenter(cond) +-- +-- Set the next window position to be centered on screen +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- cond - table, condition flags: Always, Once, FirstUseEver, Appearing +-- +-- Returns: +-- +-- nil +-- +function ui.setNextWindowPosCenter(cond) + ui.setNextWindowPos(ui.screenSize() / 2, cond, Vector2(0.5, 0.5)) +end + +-- +-- Function: ui.sameLine +-- +-- ui.sameLine(pos_x, spacing_w) +-- +-- Draw the next command on the same line as the previous +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- pos_x - (Optional) number, X position for next draw command, default 0 +-- spacing_w - (Optional) number, draw with spacing relative to previous, default -1 +-- +-- Returns: +-- +-- nil +-- +function ui.sameLine(pos_x, spacing_w) + local px = pos_x or 0.0 + local sw = spacing_w or -1.0 + pigui.SameLine(px, sw) +end + +-- +-- Function: ui.withID +-- +-- ui.withID(id, fun) +-- +-- Display content with a specified ID +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- id - string, the desired ID +-- fun - function, function called to display content +-- +-- Returns: +-- +-- nil +-- +function ui.withID(id, fun) + pigui.PushID(id) + fun() + pigui.PopID() +end + +-- +-- Function: ui.loadTextureFromSVG +-- +-- ui.loadTextureFromSVG(filename, width, height) +-- +-- Create a texture from an SVG +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- filename - string, svg path +-- width - number, width of texture to create +-- height - number, height of texture to create +-- +-- Returns: +-- +-- userdata - the texture +-- +function ui.loadTextureFromSVG(filename, width, height) + return pigui:LoadTextureFromSVG(filename, width, height) +end + +-- +-- Function: ui.loadTexture +-- +-- ui.loadTexture(filename) +-- +-- Load a texture from file +-- +-- Example: +-- +-- > +-- +-- Parameters: +-- filename - string, texture file path +-- +-- Returns: +-- +-- userdata - the texture +-- +function ui.loadTexture(filename) + return pigui:LoadTexture(filename) +end + +function ui.maybeSetTooltip(tooltip) + if not Game.player:IsMouseActive() then + pigui.SetTooltip(tooltip) + end +end + +ui.setTooltip = ui.maybeSetTooltip diff --git a/data/pigui/modules/flight-ui/indicators.lua b/data/pigui/modules/flight-ui/indicators.lua index 1ae4a4093cc..dd3f347b7e3 100644 --- a/data/pigui/modules/flight-ui/indicators.lua +++ b/data/pigui/modules/flight-ui/indicators.lua @@ -32,7 +32,7 @@ local function displayDirectionalMarkers() local function displayDirectionalMarker(ship_space, icon, showDirection, angle) local screen = Engine.ShipSpaceToScreenSpace(ship_space) local coord = Vector2(screen.x, screen.y) - if screen.z <= 1 then + if screen.z <= 0 then ui.addIcon(coord, icon, colors.reticuleCircle, Vector2(32, 32), ui.anchor.center, ui.anchor.center, nil, angle) end return showDirection and (coord - center):length() > reticuleCircleRadius diff --git a/data/pigui/modules/info-view/01-ship-info.lua b/data/pigui/modules/info-view/01-ship-info.lua index 9cb32bd1401..a1e6da14471 100644 --- a/data/pigui/modules/info-view/01-ship-info.lua +++ b/data/pigui/modules/info-view/01-ship-info.lua @@ -82,6 +82,12 @@ local function shipStats() local bwd_acc = player:GetAcceleration("reverse") local up_acc = player:GetAcceleration("up") + local atmo_shield = table.unpack(player:GetEquip("atmo_shield")) or nil + local atmo_shield_cap = 1 + if atmo_shield then + atmo_shield_cap = atmo_shield.capabilities.atmo_shield + end + textTable.draw { { l.REGISTRATION_NUMBER..":", shipLabel}, { l.HYPERDRIVE..":", hyperdrive and hyperdrive:GetName() or l.NONE }, @@ -113,8 +119,10 @@ local function shipStats() { l.CREW_CABINS..":", shipDef.maxCrew }, false, { l.MISSILE_MOUNTS..":", shipDef.equipSlotCapacity.missile}, - { l.ATMOSPHERIC_SHIELDING..":", shipDef.equipSlotCapacity.atmo_shield > 0 and l.YES or l.NO }, { l.SCOOP_MOUNTS..":", shipDef.equipSlotCapacity.scoop}, + false, + { l.ATMOSPHERIC_SHIELDING..":", shipDef.equipSlotCapacity.atmo_shield > 0 and l.YES or l.NO }, + { l.ATMO_PRESS_LIMIT..":", string.format("%d atm", shipDef.atmosphericPressureLimit * atmo_shield_cap) }, } end diff --git a/data/pigui/modules/master-alarm.lua b/data/pigui/modules/master-alarm.lua index 71a1979c176..22e169f109d 100644 --- a/data/pigui/modules/master-alarm.lua +++ b/data/pigui/modules/master-alarm.lua @@ -1,4 +1,4 @@ --- Copyright � 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt local Engine = require 'Engine' @@ -118,7 +118,7 @@ local function alarm () ui.playSfx("impact_chime", 1.0, 1.0) alreadyAlertedImpact = true end - + --with the following formula, alert triggers if --player ship's acceleration rate would not allow them to avoid a collision by simply accelerating sideways --exact calculations require complex integrals, this alert is accurate enough but just a tiny bit on the pessimistic side for extra safety measures @@ -135,4 +135,3 @@ end ui.registerModule("game", alarm) return {} - diff --git a/data/pigui/modules/station-view/01-lobby.lua b/data/pigui/modules/station-view/01-lobby.lua index 1fe1d9430a7..46acaf60d8c 100644 --- a/data/pigui/modules/station-view/01-lobby.lua +++ b/data/pigui/modules/station-view/01-lobby.lua @@ -1,28 +1,28 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local ui = import 'pigui/pigui.lua' -local StationView = import 'pigui/views/station-view' - -local Game = import 'Game' -local Rand = import 'Rand' -local Format = import 'Format' -local Equipment = import 'Equipment' -local ShipDef = import 'ShipDef' -local Character = import 'Character' -local Comms = import 'Comms' - -local InfoFace = import 'ui/PiguiFace' -local PiImage = import 'ui/PiImage' -local textTable = import 'pigui/libs/text-table.lua' -local ModalWindow = import 'pigui/libs/modal-win.lua' +local ui = require 'pigui' +local StationView = require 'pigui.views.station-view' + +local Game = require 'Game' +local Rand = require 'Rand' +local Format = require 'Format' +local Equipment = require 'Equipment' +local ShipDef = require 'ShipDef' +local Character = require 'Character' +local Comms = require 'Comms' + +local InfoFace = require 'ui.PiguiFace' +local PiImage = require 'ui.PiImage' +local textTable = require 'pigui.libs.text-table' +local ModalWindow = require 'pigui.libs.modal-win' local pionillium = ui.fonts.pionillium local orbiteer = ui.fonts.orbiteer local colors = ui.theme.colors local icons = ui.theme.icons -local Lang = import 'Lang' +local Lang = require 'Lang' local l = Lang.GetResource("ui-core") local rescaleVector = ui.rescaleUI(Vector2(1, 1), Vector2(1600, 900), true) diff --git a/data/pigui/modules/station-view/03-commodityMarket.lua b/data/pigui/modules/station-view/03-commodityMarket.lua index 7d6d8a0a608..90a3f8967d4 100644 --- a/data/pigui/modules/station-view/03-commodityMarket.lua +++ b/data/pigui/modules/station-view/03-commodityMarket.lua @@ -1,11 +1,11 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Lang = import 'Lang' -local StationView = import 'pigui/views/station-view' -local CommodityWidget = import 'pigui/libs/commodity-market.lua' +local Lang = require 'Lang' +local StationView = require 'pigui.views.station-view' +local CommodityWidget = require 'pigui.libs.commodity-market' -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local pionillium = ui.fonts.pionillium local orbiteer = ui.fonts.orbiteer local l = Lang.GetResource("ui-core") diff --git a/data/pigui/modules/station-view/04-shipMarket.lua b/data/pigui/modules/station-view/04-shipMarket.lua index c3b3daab5aa..c5fb4691f1a 100644 --- a/data/pigui/modules/station-view/04-shipMarket.lua +++ b/data/pigui/modules/station-view/04-shipMarket.lua @@ -1,17 +1,17 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Lang = import 'Lang' -local Game = import 'Game' -local Format = import 'Format' -local ShipDef = import 'ShipDef' -local Equipment = import 'Equipment' -local StationView = import 'pigui/views/station-view' -local Table = import 'pigui/libs/table.lua' -local PiImage = import 'ui/PiImage' -local ModelSpinner = import 'PiGui.Modules.ModelSpinner' - -local ui = import 'pigui/pigui.lua' +local Lang = require 'Lang' +local Game = require 'Game' +local Format = require 'Format' +local ShipDef = require 'ShipDef' +local Equipment = require 'Equipment' +local StationView = require 'pigui.views.station-view' +local Table = require 'pigui.libs.table' +local PiImage = require 'ui/PiImage' +local ModelSpinner = require 'PiGui.Modules.ModelSpinner' + +local ui = require 'pigui' local pionillium = ui.fonts.pionillium local orbiteer = ui.fonts.orbiteer local l = Lang.GetResource("ui-core") @@ -307,6 +307,15 @@ local tradeMenu = function() ui.nextColumn() ui.text(string.format("%d km/s", deltav_m / 1000)) ui.nextColumn() + ui.text(l.ATMO_PRESS_LIMIT) + ui.nextColumn() + if def.equipSlotCapacity["atmo_shield"] > 0 then + ui.text(string.format("%d(+%d/+%d) atm", def.atmosphericPressureLimit, def.atmosphericPressureLimit * (Equipment.misc.atmospheric_shielding.capabilities.atmo_shield - 1), def.atmosphericPressureLimit * (Equipment.misc.heavy_atmospheric_shielding.capabilities.atmo_shield - 1) )) + else + ui.text(string.format("%d atm", def.atmosphericPressureLimit)) + end + ui.nextColumn() + ui.text(l.SCOOP_MOUNTS) ui.nextColumn() ui.text(def.equipSlotCapacity["scoop"]) diff --git a/data/pigui/modules/station-view/05-equipmentMarket.lua b/data/pigui/modules/station-view/05-equipmentMarket.lua index bd415985bb2..ba18e079fd5 100644 --- a/data/pigui/modules/station-view/05-equipmentMarket.lua +++ b/data/pigui/modules/station-view/05-equipmentMarket.lua @@ -1,14 +1,14 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Lang = import 'Lang' -local Game = import 'Game' -local Format = import 'Format' -local Equipment = import 'Equipment' -local StationView = import 'pigui/views/station-view' -local EquipMarket = import 'pigui/libs/equipment-market.lua' +local Lang = require 'Lang' +local Game = require 'Game' +local Format = require 'Format' +local Equipment = require 'Equipment' +local StationView = require 'pigui.views.station-view' +local EquipMarket = require 'pigui.libs.equipment-market' -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local pionillium = ui.fonts.pionillium local l = Lang.GetResource("ui-core") diff --git a/data/pigui/modules/station-view/06-shipRepairs.lua b/data/pigui/modules/station-view/06-shipRepairs.lua index d9110176d95..41f0261bb30 100644 --- a/data/pigui/modules/station-view/06-shipRepairs.lua +++ b/data/pigui/modules/station-view/06-shipRepairs.lua @@ -1,16 +1,16 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local ui = import 'pigui/pigui.lua' -local StationView = import 'pigui/views/station-view' -local ShipDef = import("ShipDef") -local Game = import "Game" -local Rand = import "Rand" -local InfoFace = import 'ui/PiguiFace' -local Format = import "Format" -local Character = import "Character" -local ModalWindow = import 'pigui/libs/modal-win.lua' -local Lang = import 'Lang' +local ui = require 'pigui' +local StationView = require 'pigui.views.station-view' +local ShipDef = require "ShipDef" +local Game = require "Game" +local Rand = require "Rand" +local InfoFace = require 'ui/PiguiFace' +local Format = require "Format" +local Character = require "Character" +local ModalWindow = require 'pigui.libs.modal-win' +local Lang = require 'Lang' local l = Lang.GetResource("ui-core") local rescaleVector = ui.rescaleUI(Vector2(1, 1), Vector2(1600, 900), true) diff --git a/data/pigui/modules/station-view/07-police.lua b/data/pigui/modules/station-view/07-police.lua index 73f3466729c..ad2b4722dad 100644 --- a/data/pigui/modules/station-view/07-police.lua +++ b/data/pigui/modules/station-view/07-police.lua @@ -1,19 +1,19 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Game = import "Game" -local Rand = import "Rand" -local ui = import 'pigui/pigui.lua' -local StationView = import 'pigui/views/station-view' -local Lang = import 'Lang' -local Legal = import "Legal" -local utils = import "utils" -local InfoFace = import 'ui/PiguiFace' -local Format = import "Format" -local Character = import "Character" +local Game = require "Game" +local Rand = require "Rand" +local ui = require 'pigui' +local StationView = require 'pigui.views.station-view' +local Lang = require 'Lang' +local Legal = require "Legal" +local utils = require "utils" +local InfoFace = require 'ui/PiguiFace' +local Format = require "Format" +local Character = require "Character" local l = Lang.GetResource("ui-core") -local ModalWindow = import 'pigui/libs/modal-win.lua' +local ModalWindow = require 'pigui.libs.modal-win' local rescaleVector = ui.rescaleUI(Vector2(1, 1), Vector2(1600, 900), true) diff --git a/data/pigui/modules/theme-debug.lua b/data/pigui/modules/theme-debug.lua new file mode 100644 index 00000000000..0cdc1dd86d9 --- /dev/null +++ b/data/pigui/modules/theme-debug.lua @@ -0,0 +1,21 @@ +-- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +local ui = require 'pigui' +local debugView = require 'pigui.views.debug' + +local colors = ui.theme.colors + +local sortedColors = {} +for name in pairs(colors) do table.insert(sortedColors, name) end +table.sort(sortedColors) + +debugView.registerTab('debug-theme-colors', function() + if not ui.beginTabItem("Theme Colors") then return end + for _, name in ipairs(sortedColors) do + local changed, color = nil, colors[name] + changed, color = ui.colorEdit(name, color, true) + if changed then colors[name] = color end + end + ui.endTabItem() +end) diff --git a/data/pigui/pigui.lua b/data/pigui/pigui.lua deleted file mode 100644 index a9297735c15..00000000000 --- a/data/pigui/pigui.lua +++ /dev/null @@ -1,946 +0,0 @@ --- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details --- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt - --- TODO: don't move pointer in radial menu - -local Format = require 'Format' -local Game = require 'Game' -local Player = require 'Player' -local Space = require 'Space' -local Engine = require 'Engine' -local Event = require 'Event' -local ShipDef = require 'ShipDef' -local Lang = require 'Lang' -local Vector2 = _G.Vector2 - -local lui = Lang.GetResource("ui-core"); -local lc = Lang.GetResource("core"); -local lec = Lang.GetResource("equipment-core"); - -local utils = require 'utils' -local pigui = Engine.pigui - -local pi = 3.14159264 -local pi_2 = pi / 2 -local pi_4 = pi / 4 -local two_pi = pi * 2 -local standard_gravity = 9.80665 -local one_over_sqrt_two = 1 / math.sqrt(2) - -local ui = { } - -local defaultTheme = require '.themes.default' -ui.theme = defaultTheme - -ui.rescaleUI = function(val, baseResolution, rescaleToScreenAspect, targetResolution) - if not targetResolution then - targetResolution = Vector2(pigui.screen_width, pigui.screen_height) - end - - local rescaleVector = Vector2(targetResolution.x / baseResolution.x, targetResolution.y / baseResolution.y) - local rescaleFactor = math.min(rescaleVector.x, rescaleVector.y) - local type = type(val) - - if type == 'table' then - local result = {} - for k, v in pairs(val) do - result[k] = ui.rescaleUI(v, baseResolution, rescaleToScreenAspect, targetResolution) - end - - return result - elseif type == 'userdata' and val.x and val.y then - return Vector2(val.x * ((rescaleToScreenAspect and rescaleVector.x) or rescaleFactor), val.y * ((rescaleToScreenAspect and rescaleVector.y) or rescaleFactor)) - elseif type == 'number' then - return val * rescaleFactor - end -end - --- font sizes are correct for 1920x1200 -local font_factor = ui.rescaleUI(1, Vector2(1920, 1200)) - -ui.fonts = { - -- dummy font, actually renders icons - pionicons = { - small = { name = "icons", size = 16 * font_factor, offset = 14 * font_factor}, - medium = { name = "icons", size = 18 * font_factor, offset = 20 * font_factor}, - large = { name = "icons", size = 22 * font_factor, offset = 28 * font_factor} - }, - pionillium = { - xlarge = { name = "pionillium", size = 36 * font_factor, offset = 24 * font_factor }, - large = { name = "pionillium", size = 30 * font_factor, offset = 24 * font_factor}, - medlarge = { name = "pionillium", size = 24 * font_factor, offset = 18 * font_factor}, - medium = { name = "pionillium", size = 18 * font_factor, offset = 14 * font_factor}, - -- medsmall = { name = "pionillium", size = 15, offset = 12 }, - small = { name = "pionillium", size = 14 * font_factor, offset = 11 * font_factor}, - tiny = { name = "pionillium", size = 8 * font_factor, offset = 7 * font_factor}, - }, - orbiteer = { - xlarge = { name = "orbiteer", size = 36 * font_factor, offset = 24 * font_factor }, - large = { name = "orbiteer", size = 30 * font_factor, offset = 24 * font_factor }, - medlarge = { name = "orbiteer", size = 24 * font_factor, offset = 20 * font_factor}, - medium = { name = "orbiteer", size = 20 * font_factor, offset = 16 * font_factor}, - small = { name = "orbiteer", size = 14 * font_factor, offset = 11 * font_factor}, - tiny = { name = "orbiteer", size = 8 * font_factor, offset = 7 * font_factor}, - }, -} - -ui.anchor = { left = 1, right = 2, center = 3, top = 4, bottom = 5, baseline = 6 } - -local function maybeSetTooltip(tooltip) - if not Game.player:IsMouseActive() then - pigui.SetTooltip(tooltip) - end -end - -local textBackgroundMarginPixels = 2 - -ui.icons_texture = pigui:LoadTextureFromSVG(pigui.DataDirPath({"icons", "icons.svg"}), 16 * 64, 16 * 64) - --- Clean up the ImGui stack in case of an error -function ui.pcall(fun, ...) - local stack = pigui.GetImguiStack() - return xpcall(fun, function(msg) - return msg .. pigui.CleanupImguiStack(stack) - end, ...) -end - -function ui.window(name, params, fun) - local ok = pigui.Begin(name, params) - if ok then fun() end - pigui.End() -end - -function ui.group(fun) - pigui.BeginGroup() - fun() - pigui.EndGroup() -end - -function ui.popup(name, fun) - if pigui.BeginPopup(name) then - fun() - pigui.EndPopup() - end -end - -function ui.child(id, size, flags, fun) - if flags == nil and fun == nil then -- size is optional - fun = size - size = Vector2(-1,-1) - flags = {} - elseif fun == nil then - fun = flags - flags = {} - end - - pigui.BeginChild(id, size, flags) - fun() - pigui.EndChild() -end -function ui.withFont(name, size, fun) - -- allow `withFont(fontObj, fun)` - if type(name) == "table" and type(size) == "function" then - name, size, fun = table.unpack{name.name, name.size, size} - end - - local font = pigui:PushFont(name, size) - local res = fun() - if font then - pigui.PopFont() - end - return res -end - -function ui.withStyleColors(styles, fun) - for k,v in pairs(styles) do - pigui.PushStyleColor(k, v) - end - local res = fun() - pigui.PopStyleColor(utils.count(styles)) - return res -end - -function ui.withStyleVars(vars, fun) - for k,v in pairs(vars) do - pigui.PushStyleVar(k, v) - end - local res = fun() - pigui.PopStyleVar(utils.count(vars)) - return res -end - -function ui.withStyleColorsAndVars(styles, vars, fun) - for k,v in pairs(styles) do - pigui.PushStyleColor(k, v) - end - for k,v in pairs(vars) do - pigui.PushStyleVar(k, v) - end - local res = fun() - pigui.PopStyleVar(utils.count(vars)) - pigui.PopStyleColor(utils.count(styles)) - return res -end - -local function get_icon_tex_coords(icon) - assert(icon, "no icon given") - local count = 16.0 -- icons per row/column - local rem = math.floor(icon % count) - local quot = math.floor(icon / count) - return Vector2(rem / count, quot/count), Vector2((rem+1) / count, (quot+1)/count) -end - -local function get_wide_icon_tex_coords(icon) - assert(icon, "no icon given") - local count = 16.0 -- icons per row/column - local rem = math.floor(icon % count) - local quot = math.floor(icon / count) - return Vector2(rem / count, quot/count), Vector2((rem+2) / count, (quot+1)/count) -end - -ui.registerHandler = function(name, fun) - pigui.handlers[name] = fun -end - -ui.circleSegments = function(radius) - if radius < 5 then - return 8 - elseif radius < 20 then - return 16 - elseif radius < 50 then - return 32 - elseif radius < 100 then - return 64 - else - return 128 - end -end - -ui.Format = { - Latitude = function(decimal_degrees) - local prefix = lc.LATITUDE_NORTH_ABBREV - if decimal_degrees < 0 then - prefix = lc.LATITUDE_SOUTH_ABBREV - decimal_degrees = math.abs(decimal_degrees) - end - local deg = math.floor(decimal_degrees) - local min = (decimal_degrees - deg) * 60 - local sec = (min - math.floor(min)) * 60 - return string.format('%s %03i°%02i\'%02i"', prefix, deg, min, sec) - end, - Longitude = function(decimal_degrees) - local prefix = lc.LONGITUDE_EAST_ABBREV - if decimal_degrees < 0 then - prefix = lc.LONGITUDE_WEST_ABBREV - decimal_degrees = math.abs(decimal_degrees) - end - local deg = math.floor(decimal_degrees) - local min = (decimal_degrees - deg) * 60 - local sec = (min - math.floor(min)) * 60 - return string.format('%s %03i°%02i\'%02i"', prefix, deg, min, sec) - end, - Duration = function(duration, elements) - -- shown elements items (2 -> wd or dh, 3 -> dhm or hms) - local negative = false - if duration < 0 then - duration = math.abs(duration) - negative = true - end - local seconds = math.floor(duration % 60) - local minutes = math.floor(duration / 60 % 60) - local hours = math.floor(duration / 60 / 60 % 24) - local days = math.floor(duration / 60 / 60 / 24 % 7) - local weeks = math.floor(duration / 60 / 60 / 24 / 7) - local i = elements or 5 - local count = false - local result = "" - if i > 0 then - if weeks ~= 0 then - result = result .. weeks .. "w" - count = true - end - if count then - i = i - 1 - end - end - if i > 0 then - if days ~= 0 then - result = result .. days .. "d" - count = true - end - if count then - i = i - 1 - end - end - if i > 0 then - if hours ~= 0 then - result = result .. hours .. "h" - count = true - end - if count then - i = i - 1 - end - end - if i > 0 then - if minutes ~= 0 then - result = result .. minutes .. "m" - count = true - end - if count then - i = i - 1 - end - end - if i > 0 then - if seconds ~= 0 then - result = result .. seconds .. "s" - count = true - end - if result == "" then - result = "0s" - end - if count then - i = i - 1 - end - end - if negative then - result = "-" .. result - end - return result - end, - Distance = function(distance) - local d = math.abs(distance) - if d < 1000 then - return math.floor(distance), lc.UNIT_METERS - end - if d < 1000*1000 then - return string.format("%0.2f", distance / 1000), lc.UNIT_KILOMETERS - end - if d < 1000*1000*1000 then - return string.format("%0.2f", distance / 1000 / 1000), lc.UNIT_MILLION_METERS - end - return string.format("%0.2f", distance / 1.4960e11), lc.UNIT_AU - end, - Speed = function(distance) - local d = math.abs(distance) - if d < 1000 then - return math.floor(distance), lc.UNIT_METERS_PER_SECOND - end - if d < 1000*1000 then - return string.format("%0.2f", distance / 1000), lc.UNIT_KILOMETERS_PER_SECOND - end - return string.format("%0.2f", distance / 1000 / 1000), lc.UNIT_MILLION_METERS_PER_SECOND - -- no need for au/s - end, - Datetime = function(date) - local second, minute, hour, day, month, year = Game.GetPartsFromDateTime(date) - return string.format("%4i-%02i-%02i %02i:%02i:%02i", year, month, day, hour, minute, second) - end -} - -ui.addIcon = function(position, icon, color, size, anchor_horizontal, anchor_vertical, tooltip, angle_rad) - local pos = ui.calcTextAlignment(position, size, anchor_horizontal, anchor_vertical) - local uv0, uv1 = get_icon_tex_coords(icon) - if angle_rad then - local center = Vector2(pos.x + pos.x + size.x, pos.y + pos.y + size.y) / 2 - local up_left = Vector2(-size.x/2, size.y/2):rotate(angle_rad) - local up_right = up_left:right() - local down_left = up_left:left() - local down_right = -up_left - pigui.AddImageQuad(ui.icons_texture, center + up_left, center + up_right, center + down_right, center + down_left, uv0, Vector2(uv1.x, uv0.y), uv1, Vector2(uv0.x, uv1.y), color) - else - pigui.AddImage(ui.icons_texture, pos, pos + size, uv0, uv1, color) - end - if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then - if pigui.IsMouseHoveringRect(pos, pos + size, true) then - maybeSetTooltip(tooltip) - end - end - - return size -end - -ui.addWideIcon = function(position, icon, color, size, anchor_horizontal, anchor_vertical, tooltip, angle_rad) - local pos = ui.calcTextAlignment(position, size, anchor_horizontal, anchor_vertical) - local uv0, uv1 = get_wide_icon_tex_coords(icon) - if angle_rad then - local center = (pos + pos + size) / 2 - local up_left = Vector2(-size.x/2, size.y/2):rotate2d(angle_rad) - local up_right = up_left:right() - local down_left = up_left:left() - local down_right = -up_left - pigui.AddImageQuad(ui.icons_texture, center + up_left, center + up_right, center + down_right, center + down_left, uv0, Vector2(uv1.x, uv0.y), uv1, Vector2(uv0.x, uv1.y), color) - else - pigui.AddImage(ui.icons_texture, pos, pos + size, uv0, uv1, color) - end - if tooltip and (ui.isMouseHoveringWindow() or not is.isAnyWindowHovered()) and tooltip ~= "" then - if pigui.IsMouseHoveringRect(pos, pos + size, true) then - maybeSetTooltip(tooltip) - end - end - - return size -end - -ui.addFancyText = function(position, anchor_horizontal, anchor_vertical, data, bg_color) - -- always align texts at baseline - local spacing = 2 - local size = Vector2(0, 0) - local max_offset = 0 - for i=1,#data do - local item = data[i] - assert(item.text, "missing text for item in addFancyText") - assert(item.font, "missing font for item in addFancyText") - assert(item.color, "missing font for item in addFancyText") - - local is_icon = item.font.name ~= "icons" - local s - local popfont - if is_icon then - popfont = pigui:PushFont(item.font.name, item.font.size) - s = pigui.CalcTextSize(item.text) - else - s = Vector2(item.font.size, item.font.size) - end - size.x = size.x + s.x - size.x = size.x + spacing -- spacing - size.y = math.max(size.y, s.y) - max_offset = math.max(max_offset, item.font.offset) - if is_icon then - if popfont then - pigui.PopFont() - end - end - end - size.x = size.x - spacing -- remove last spacing - position = ui.calcTextAlignment(position, size, anchor_horizontal, nil) - if anchor_vertical == ui.anchor.top then - position.y = position.y + size.y -- was max_offset, seems wrong - elseif anchor_vertical == ui.anchor.bottom then - position.y = position.y - size.y + max_offset - end - if bg_color then - pigui.AddRectFilled(position - Vector2(textBackgroundMarginPixels, size.y + textBackgroundMarginPixels), - position + Vector2(size.x + textBackgroundMarginPixels, textBackgroundMarginPixels), - bg_color, - 0, - 0) - end - for i=1,#data do - local item = data[i] - local is_icon = item.font.name ~= "icons" - if is_icon then - ui.withFont(item.font.name, item.font.size, function() - local s = ui.addStyledText(position, ui.anchor.left, ui.anchor.baseline, item.text, item.color, item.font, item.tooltip) - position.x = position.x + s.x + spacing - end) - else - local s = ui.addIcon(position, item.text, item.color, Vector2(item.font.size, item.font.size), ui.anchor.left, ui.anchor.bottom, item.tooltip) - position.x = position.x + s.x + spacing - end - end - return size -end - -ui.addStyledText = function(position, anchor_horizontal, anchor_vertical, text, color, font, tooltip, bg_color) - -- addStyledText aligns to upper left - local size = Vector2(0, 0) - ui.withFont(font.name, font.size, function() - size = pigui.CalcTextSize(text) - local vert - if anchor_vertical == ui.anchor.baseline then - vert = nil - else - vert = anchor_vertical - end - position = ui.calcTextAlignment(position, size, anchor_horizontal, vert) -- ignore vertical if baseline - if anchor_vertical == ui.anchor.baseline then - position.y = position.y - font.offset - end - if bg_color then - pigui.AddRectFilled(Vector2(position.x - textBackgroundMarginPixels, position.y - textBackgroundMarginPixels), - Vector2(position.x + size.x + textBackgroundMarginPixels, position.y + size.y + textBackgroundMarginPixels), - bg_color, - 0, - 0) - end - pigui.AddText(position, color, text) - -- pigui.AddQuad(position, position + Vector2(size.x, 0), position + Vector2(size.x, size.y), position + vector.new(0, size.y), colors.red, 1.0) - end) - if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then - if pigui.IsMouseHoveringRect(position, position + size, true) then - maybeSetTooltip(tooltip) - end - end - return size -end - -ui.icon = function(icon, size, color, tooltip) - local uv0, uv1 = get_icon_tex_coords(icon) - pigui.Image(ui.icons_texture, size, uv0, uv1, color) - if tooltip and ui.isItemHovered() then - ui.setTooltip(tooltip) - end -end - --- Forward selected functions -ui.calcTextAlignment = pigui.CalcTextAlignment -ui.lineOnClock = pigui.lineOnClock -ui.pointOnClock = pigui.pointOnClock -ui.screenWidth = pigui.screen_width -ui.screenHeight = pigui.screen_height -ui.screenSize = function() - return Vector2(ui.screenWidth, ui.screenHeight) -end -ui.setNextWindowPos = pigui.SetNextWindowPos -ui.setNextWindowPosCenter = function(cond) - ui.setNextWindowPos(ui.screenSize() / 2, cond, Vector2(0.5, 0.5)) -end -ui.setNextWindowSize = pigui.SetNextWindowSize -ui.setNextWindowSizeConstraints = pigui.SetNextWindowSizeConstraints -ui.dummy = pigui.Dummy -ui.newLine = pigui.NewLine -ui.sameLine = function(pos_x, spacing_w) - local px = pos_x or 0.0 - local sw = spacing_w or -1.0 - pigui.SameLine(px, sw) -end -ui.spacing = pigui.Spacing -ui.text = pigui.Text -ui.combo = pigui.Combo -ui.listBox = pigui.ListBox -ui.textWrapped = pigui.TextWrapped -ui.textColored = pigui.TextColored -ui.inputText = pigui.InputText -ui.checkbox = pigui.Checkbox -ui.separator = pigui.Separator -ui.pushTextWrapPos = pigui.PushTextWrapPos -ui.popTextWrapPos = pigui.PopTextWrapPos -ui.setScrollHere = pigui.SetScrollHere -ui.selectable = pigui.Selectable -ui.progressBar = pigui.ProgressBar -ui.plotHistogram = pigui.PlotHistogram -ui.calcTextSize = pigui.CalcTextSize -ui.addCircle = pigui.AddCircle -ui.addCircleFilled = pigui.AddCircleFilled -ui.addRect = pigui.AddRect -ui.addRectFilled = pigui.AddRectFilled -ui.addLine = pigui.AddLine -ui.addText = pigui.AddText -ui.pathArcTo = pigui.PathArcTo -ui.pathStroke = pigui.PathStroke -ui.twoPi = two_pi -ui.pi_2 = pi_2 -ui.pi_4 = pi_4 -ui.pi = pi -ui.withID = function(id, fun) - pigui.PushID(id) - fun() - pigui.PopID() -end -ui.imageButton = function(icon, size, frame_padding, bg_color, tint_color, tooltip) - local uv0, uv1 = get_icon_tex_coords(icon) - ui.withID(tooltip, function() - local res = pigui.ImageButton(ui.icons_texture, size, uv0, uv1, frame_padding, bg_color, tint_color) - end) - return res -end -ui.setCursorPos = pigui.SetCursorPos -ui.getCursorPos = pigui.GetCursorPos -ui.setCursorScreenPos = pigui.SetCursorScreenPos -ui.getCursorScreenPos = pigui.GetCursorScreenPos -ui.getTextLineHeight = pigui.GetTextLineHeight -ui.getTextLineHeightWithSpacing = pigui.GetTextLineHeightWithSpacing -ui.lowThrustButton = pigui.LowThrustButton -ui.thrustIndicator = pigui.ThrustIndicator -ui.oneOverSqrtTwo = one_over_sqrt_two -ui.isMouseClicked = pigui.IsMouseClicked -ui.isMouseDown = pigui.IsMouseDown -ui.getMousePos = pigui.GetMousePos -ui.getMouseWheel = pigui.GetMouseWheel -ui.setTooltip = maybeSetTooltip -ui.shouldDrawUI = pigui.ShouldDrawUI -ui.getWindowPos = pigui.GetWindowPos -ui.getWindowSize = pigui.GetWindowSize --- available content region -ui.getContentRegion = pigui.GetContentRegion -ui.getTextLineHeight = pigui.GetTextLineHeight -ui.getTextLineHeightWithSpacing = pigui.GetTextLineHeightWithSpacing -ui.getFrameHeight = pigui.GetFrameHeight -ui.getFrameHeightWithSpacing = pigui.GetFrameHeightWithSpacing -ui.getTargetsNearby = pigui.GetTargetsNearby -ui.getProjectedBodies = pigui.GetProjectedBodies -ui.getProjectedBodiesGrouped = pigui.GetProjectedBodiesGrouped -ui.isMouseReleased = pigui.IsMouseReleased -ui.isMouseHoveringRect = pigui.IsMouseHoveringRect -ui.isMouseHoveringWindow = function() - return ui.isWindowHovered({"AllowWhenBlockedByPopup", "AllowWhenBlockedByActiveItem"}) -end -ui.isWindowHovered = pigui.IsWindowHovered -ui.isAnyWindowHovered = function() - return ui.isWindowHovered({"AnyWindow"}) -end -ui.collapsingHeader = pigui.CollapsingHeader -ui.beginPopupModal = pigui.BeginPopupModal -ui.endPopup = pigui.EndPopup -ui.openPopup = pigui.OpenPopup -ui.closeCurrentPopup = pigui.CloseCurrentPopup -ui.shouldShowLabels = pigui.ShouldShowLabels -ui.columns = pigui.Columns -ui.nextColumn = pigui.NextColumn -ui.setColumnOffset = pigui.SetColumnOffset -ui.getColumnWidth = pigui.GetColumnWidth -ui.setColumnWidth = pigui.SetColumnWidth -ui.getScrollY = pigui.GetScrollY -ui.keys = pigui.keys -ui.systemInfoViewNextPage = pigui.SystemInfoViewNextPage -- deprecated -ui.isKeyReleased = pigui.IsKeyReleased -ui.playSfx = pigui.PlaySfx -ui.isItemHovered = pigui.IsItemHovered -ui.isItemActive = pigui.IsItemActive -ui.isItemClicked = pigui.IsItemClicked -ui.ctrlHeld = function() return pigui.key_ctrl end -ui.altHeld = function() return pigui.key_alt end -ui.shiftHeld = function() return pigui.key_shift end -ui.noModifierHeld = function() return pigui.key_none end -ui.vSliderInt = pigui.VSliderInt -ui.sliderInt = pigui.SliderInt -ui.nextItemWidth = pigui.NextItemWidth -ui.pushItemWidth = pigui.PushItemWidth -ui.popItemWidth = pigui.PopItemWidth -ui.sliderFloat = pigui.SliderFloat - -ui.tabBar = function (id, items) - local open = pigui.BeginTabBar(id) - if not open then return false end - - for i, v in ipairs(items) do - if type(v) == "table" and v[1] and type(v[2]) == "function" then - if pigui.BeginTabItem(tostring(v[1]) .. "##" .. tostring(i)) then - v[2](v) - end - end - end - - pigui.EndTabBar() - return true -end -ui.beginTabBar = pigui.BeginTabBar -ui.beginTabItem = pigui.BeginTabItem -ui.endTabItem = pigui.EndTabItem -ui.endTabBar = pigui.EndTabBar - --- Flag validation functions. Call with a table of string flags as the only argument. -ui.SelectableFlags = pigui.SelectableFlags -ui.TreeNodeFlags = pigui.TreeNodeFlags -ui.InputTextFlags = pigui.InputTextFlags -ui.WindowFlags = pigui.WindowFlags -ui.HoveredFlags = pigui.HoveredFlags - --- FINALLY OUT OF Pi.cpp! BEGONE! -ui.playBoinkNoise = function () - ui.playSfx("Click", 0.3) -end - -local shouldShowRadialMenu = false -local radialMenuPos = Vector2(0,0) -local radialMenuSize = 10 -local radialMenuTarget = nil -local radialMenuMouseButton = 1 -local radialMenuActions = {} -local radialMenuMousePos = nil -ui.openRadialMenu = function(target, mouse_button, size, actions) - ui.openPopup("##radialmenupopup") - shouldShowRadialMenu = true - radialMenuTarget = target - radialMenuPos = ui.getMousePos() - radialMenuSize = size - radialMenuMouseButton = mouse_button - radialMenuActions = actions - radialMenuMousePos = ui.getMousePos() - -- move away from screen edge - radialMenuPos.x = math.min(math.max(radialMenuPos.x, size*3), ui.screenWidth - size*3) - radialMenuPos.y = math.min(math.max(radialMenuPos.y, size*3), ui.screenHeight - size*3) -end - --- TODO: add cloud Lang::SET_HYPERSPACE_TARGET_TO_FOLLOW_THIS_DEPARTURE -local radial_menu_actions_station = { - {icon=ui.theme.icons.comms, tooltip=lc.REQUEST_DOCKING_CLEARANCE, - action=function(target) - local msg = Game.player:RequestDockingClearance(target) - Game.AddCommsLogLine(msg, target.label) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - end}, - {icon=ui.theme.icons.autopilot_dock, tooltip=lc.AUTOPILOT_DOCK_WITH_STATION, - action=function(target) - if next(Game.player:GetEquip('autopilot')) ~= nil then - Game.player:SetFlightControlState("CONTROL_AUTOPILOT") - Game.player:AIDockWith(target) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - else - Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) - end - end}, -} - -local radial_menu_actions_all_bodies = { - {icon=ui.theme.icons.autopilot_fly_to, tooltip=lc.AUTOPILOT_FLY_TO_VICINITY_OF, - action=function(target) - if next(Game.player:GetEquip('autopilot')) ~= nil then - Game.player:SetFlightControlState("CONTROL_AUTOPILOT") - Game.player:AIFlyTo(target) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - else - Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) - end - - end}, -} - -local radial_menu_actions_systembody = { - {icon=ui.theme.icons.autopilot_low_orbit, tooltip=lc.AUTOPILOT_ENTER_LOW_ORBIT_AROUND, - action=function(target) - if next(Game.player:GetEquip('autopilot')) ~= nil then - Game.player:SetFlightControlState("CONTROL_AUTOPILOT") - Game.player:AIEnterLowOrbit(target) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - else - Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) - end - end}, - {icon=ui.theme.icons.autopilot_medium_orbit, tooltip=lc.AUTOPILOT_ENTER_MEDIUM_ORBIT_AROUND, - action=function(target) - if next(Game.player:GetEquip('autopilot')) ~= nil then - Game.player:SetFlightControlState("CONTROL_AUTOPILOT") - Game.player:AIEnterMediumOrbit(target) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - else - Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) - end - end}, - {icon=ui.theme.icons.autopilot_high_orbit, tooltip=lc.AUTOPILOT_ENTER_HIGH_ORBIT_AROUND, - action=function(target) - if next(Game.player:GetEquip('autopilot')) ~= nil then - Game.player:SetFlightControlState("CONTROL_AUTOPILOT") - Game.player:AIEnterHighOrbit(target) - Game.player:SetNavTarget(target) - ui.playSfx("OK") - else - Game.AddCommsLogLine(lc.NO_AUTOPILOT_INSTALLED) - end - end}, -} - -ui.openDefaultRadialMenu = function(body) - if body then - local actions = {} - for _,v in pairs(radial_menu_actions_all_bodies) do - table.insert(actions, v) - end - if body:IsStation() then - for _,v in pairs(radial_menu_actions_station) do - table.insert(actions, v) - end - elseif body:GetSystemBody() then - for _,v in pairs(radial_menu_actions_systembody) do - table.insert(actions, v) - end - end - ui.openRadialMenu(body, 1, 30, actions) - end -end - -local radialMenuWasOpen = {} -ui.radialMenu = function(id) - if not radialMenuActions or #radialMenuActions == 0 then - return - end - local icons = {} - local tooltips = {} - for _,action in pairs(radialMenuActions) do - local uv0, uv1 = get_icon_tex_coords(action.icon) - table.insert(icons, { id = ui.icons_texture, uv0 = uv0, uv1 = uv1 }) - -- TODO: don't just assume that radialMenuTarget is a Body - table.insert(tooltips, string.interp(action.tooltip, { target = radialMenuTarget and radialMenuTarget.label or "UNKNOWN" })) - end - local n = pigui.RadialMenu(radialMenuPos, "##radialmenupopup", radialMenuMouseButton, icons, radialMenuSize, tooltips) - if n == -1 then - pigui.DisableMouseFacing(true) - radialMenuWasOpen[id] = true - elseif n >= 0 or n == -2 then - radialMenuWasOpen[id] = false - shouldShowRadialMenu = false - local target = radialMenuTarget - radialMenuTarget = nil - pigui.DisableMouseFacing(false) - -- hack, imgui lets the press go through, but eats the release, so Pi still thinks rmb is held - pigui.SetMouseButtonState(3, false); - -- ui.setMousePos(radialMenuMousePos) - -- do this last, so it can theoretically open a new radial menu - -- though we can't as no button is pressed that could be released :-/ - if n >= 0 then - radialMenuActions[n+1].action(target) - end - end - if n == -3 and radialMenuWasOpen[id] then - pigui.SetMouseButtonState(3, false) - pigui.DisableMouseFacing(false) - radialMenuWasOpen[id] = false - end - return n -end -ui.button = pigui.Button -ui.coloredSelectedButton = function(label, thesize, is_selected, bg_color, tooltip, enabled) - if is_selected then - pigui.PushStyleColor("Button", bg_color) - if enabled then - pigui.PushStyleColor("ButtonHovered", bg_color:tint(0.1)) - pigui.PushStyleColor("ButtonActive", bg_color:tint(0.2)) - else - pigui.PushStyleColor("ButtonHovered", bg_color) - pigui.PushStyleColor("ButtonActive", bg_color) - end - else - pigui.PushStyleColor("Button", bg_color:shade(0.6)) - if enabled then - pigui.PushStyleColor("ButtonHovered", bg_color:shade(0.4)) - pigui.PushStyleColor("ButtonActive", bg_color:shade(0.2)) - else - pigui.PushStyleColor("ButtonHovered", bg_color) - pigui.PushStyleColor("ButtonActive", bg_color) - end - end - --pigui.PushID(label) - local res = pigui.Button(label,thesize) - --pigui.PopID() - pigui.PopStyleColor(3) - if pigui.IsItemHovered() and enabled and tooltip then - pigui.SetTooltip(tooltip) - end - return res -end - --- --- Function: ui.coloredSelectedIconButton --- --- > clicked = ui.coloredSelectedIconButton(icon, button_size, is_selected, --- > frame_padding, bg_color, fg_color, tooltip, img_size) --- --- --- Example: --- --- > clicked = ui.coloredSelectedIconButton(ui.theme.icons.bullseye, Vector2(10,10), false, --- > 0, ui.theme.colors.buttonBlue, Color(255,0,0), "Click for action##42", Vector2(8,8)) --- --- Parameters: --- --- icon - image to place on button, e.g. from ui.theme.icons --- button_size - size of button, Vector2 --- is_selected - bool --- frame_padding - number --- bg_color - Color(R,G,B), for background --- fg_color - Color(R,G,B), for forground --- tooltip - string, mouseover text, will be used as ID, must be unique, append "##uniqueID" if needed --- img_size - size of icon on the button, Vector2 --- --- Returns: --- --- clicked - true if button was clicked --- -ui.coloredSelectedIconButton = function(icon, thesize, is_selected, frame_padding, bg_color, fg_color, tooltipID, img_size) - if is_selected then - pigui.PushStyleColor("Button", bg_color) - pigui.PushStyleColor("ButtonHovered", bg_color:tint(0.1)) - pigui.PushStyleColor("ButtonActive", bg_color:tint(0.2)) - else - pigui.PushStyleColor("Button", bg_color:shade(0.6)) - pigui.PushStyleColor("ButtonHovered", bg_color:shade(0.4)) - pigui.PushStyleColor("ButtonActive", bg_color:shade(0.2)) - end - local uv0,uv1 = get_icon_tex_coords(icon) - pigui.PushID(tooltipID) - local res = pigui.ButtonImageSized(ui.icons_texture, thesize, img_size or Vector2(0,0), uv0, uv1, frame_padding, ui.theme.colors.lightBlueBackground, fg_color) - pigui.PopID() - pigui.PopStyleColor(3) - local pos = tooltipID:find("##") -- get position for id tag start - local pos = pos and pos - 1 -- if found, move back beyond first "#" - local tooltip = pos and string.sub(tooltipID, 1, pos) or tooltipID - if pigui.IsItemHovered() then - pigui.SetTooltip(tooltip) - end - return res -end - -local gauge_show_percent = true -ui.gauge_height = 25 -ui.gauge_width = 275 - -ui.gauge = function(position, value, unit, format, minimum, maximum, icon, color, tooltip, width, height, formatFont, percentFont) - local percent = math.clamp((value - minimum) / (maximum - minimum), 0, 1) - local offset = 60 - local uiPos = Vector2(position.x, position.y) - local gauge_width = width or ui.gauge_width - local gauge_height = height or ui.gauge_height - ui.withFont(ui.fonts.pionillium.medium.name, ui.fonts.pionillium.medium.size, function() - ui.addLine(uiPos, Vector2(uiPos.x + gauge_width, uiPos.y), ui.theme.colors.gaugeBackground, gauge_height, false) - if gauge_show_percent then - local one_hundred = ui.calcTextSize("100%") - uiPos.x = uiPos.x + one_hundred.x * 1.2 -- 1.2 for a bit of slack - ui.addStyledText(Vector2(uiPos.x, uiPos.y + gauge_height / 12), ui.anchor.right, ui.anchor.center, string.format("%i%%", percent * 100), ui.theme.colors.reticuleCircle, percentFont or ui.fonts.pionillium.medium, tooltip) - end - uiPos.x = uiPos.x + gauge_height * 1.2 - ui.addIcon(Vector2(uiPos.x - gauge_height / 2, uiPos.y), icon, ui.theme.colors.reticuleCircle, Vector2(gauge_height * 0.9, gauge_height * 0.9), ui.anchor.center, ui.anchor.center, tooltip) - local w = (position.x + gauge_width) - uiPos.x - ui.addLine(uiPos, Vector2(uiPos.x + w * percent, uiPos.y), color, gauge_height, false) - if value and format then - ui.addFancyText(Vector2(uiPos.x + gauge_height/2, uiPos.y + gauge_height/4), ui.anchor.left, ui.anchor.center, { - { text=string.format(format, value), color=ui.theme.colors.reticuleCircle, font=(formatFont or ui.fonts.pionillium.small), tooltip=tooltip }, - { text=unit, color=ui.theme.colors.reticuleCircleDark, font=(formatFont or ui.fonts.pionillium.small), tooltip=tooltip }}, - ui.theme.colors.gaugeBackground) - end - end) -end - -ui.loadTextureFromSVG = function(a, b, c) - return pigui:LoadTextureFromSVG(a, b, c) -end - -ui.loadTexture = function(filename) - return pigui:LoadTexture(filename) -end - -ui.dataDirPath = pigui.DataDirPath -ui.addImage = pigui.AddImage -ui.image = pigui.Image - -local modules = {} - -ui.registerModule = function(mode, fun) - if not modules[mode] then - modules[mode] = {} - end - table.insert(modules[mode], { fun = fun, enabled = true }) -end - -ui.getModules = function(mode) - return modules[mode] or {} -end - -ui.withTooltip = function(tooltip, fun) - local startPos = pigui.GetCursorPos() - fun() - if string.len(tooltip) > 0 then - local endPos = pigui.GetCursorPos() - local offset = pigui.GetWindowPos() - offset.y = offset.y - pigui.GetScrollY() - if pigui.IsMouseHoveringRect(offset + startPos, offset + endPos, false) then - pigui.SetTooltip(tooltip) - end - end -end - -return ui diff --git a/data/pigui/themes/default.lua b/data/pigui/themes/default.lua index 4050ad1ecbc..b1696a53e92 100644 --- a/data/pigui/themes/default.lua +++ b/data/pigui/themes/default.lua @@ -79,6 +79,11 @@ theme.colors = { unknown = Color(255,0,255) } +-- ImGui global theming styles +theme.styles = { + WindowBorderSize = 0.0, +} + theme.icons = { -- first row prograde = 0, @@ -311,10 +316,4 @@ theme.icons = { mouse_move_direction = 14 } --- TODO: apply these styles at startup. -theme.styles = { - WindowBorderSize = 0.0, - FrameBorderSize = 0.0 -} - return theme diff --git a/data/pigui/views/game.lua b/data/pigui/views/game.lua index f6b1288cb21..05c6a38be57 100644 --- a/data/pigui/views/game.lua +++ b/data/pigui/views/game.lua @@ -14,6 +14,8 @@ local lui = Lang.GetResource("ui-core"); local ui = require 'pigui' +local vutil = require 'pigui.libs.view-util' + -- cache ui local pionillium = ui.fonts.pionillium local pionicons = ui.fonts.pionicons @@ -42,7 +44,9 @@ local gameView = { player = nil } -import("pigui.libs.view-util").mixin_modules(gameView) +--import("pigui.libs.view-util").mixin_modules(gameView) +vutil.mixin_modules(gameView) + local function getBodyIcon(body) local st = body.superType diff --git a/data/pigui/views/info-view.lua b/data/pigui/views/info-view.lua index da1a0573d61..b58583f4cfe 100644 --- a/data/pigui/views/info-view.lua +++ b/data/pigui/views/info-view.lua @@ -1,8 +1,8 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local ui = import 'pigui/pigui.lua' -local TabView = import 'pigui/views/tab-view.lua' +local ui = require 'pigui' +local TabView = require 'pigui.views.tab-view' local infoView diff --git a/data/pigui/views/station-view.lua b/data/pigui/views/station-view.lua index 1d961c6023e..eec22aed6a1 100644 --- a/data/pigui/views/station-view.lua +++ b/data/pigui/views/station-view.lua @@ -1,15 +1,15 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Lang = import 'Lang' -local Game = import 'Game' -local Format = import 'Format' +local Lang = require 'Lang' +local Game = require 'Game' +local Format = require 'Format' local l = Lang.GetResource("ui-core") -local ui = import 'pigui/pigui.lua' +local ui = require 'pigui' local colors = ui.theme.colors local icons = ui.theme.icons local pionillium = ui.fonts.pionillium -local TabView = import 'pigui/views/tab-view.lua' +local TabView = require 'pigui.views.tab-view' local stationView diff --git a/data/pigui/views/tab-view.lua b/data/pigui/views/tab-view.lua index f3dbacd4699..348511ba67b 100644 --- a/data/pigui/views/tab-view.lua +++ b/data/pigui/views/tab-view.lua @@ -1,8 +1,9 @@ -- Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -local Game = import 'Game' -local ui = import 'pigui/pigui.lua' +local Game = require 'Game' +local ui = require 'pigui' + local orbiteer = ui.fonts.orbiteer local colors = ui.theme.colors diff --git a/data/shaders/opengl/FresnelColour.frag b/data/shaders/opengl/FresnelColour.frag index 7c7ca414168..de19e1ef6ed 100644 --- a/data/shaders/opengl/FresnelColour.frag +++ b/data/shaders/opengl/FresnelColour.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" in vec3 varyingEyepos; @@ -16,7 +15,7 @@ out vec4 frag_color; void main(void) { vec4 color = material.diffuse; - + vec3 eyenorm = normalize(-varyingEyepos); float fresnel = 1.0 - abs(dot(eyenorm, varyingNormal)); // Calculate fresnel. @@ -24,6 +23,4 @@ void main(void) fresnel += 0.05 * (1.0 - fresnel); color.a = color.a * clamp(fresnel * 0.5, 0.0, 1.0); frag_color = color; - - SetFragDepth(); } diff --git a/data/shaders/opengl/FresnelColour.vert b/data/shaders/opengl/FresnelColour.vert index 480f49c1e0b..affbac8427f 100644 --- a/data/shaders/opengl/FresnelColour.vert +++ b/data/shaders/opengl/FresnelColour.vert @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec3 varyingEyepos; @@ -10,7 +9,7 @@ out vec3 varyingNormal; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); varyingEyepos = vec3(uViewMatrix * a_vertex); varyingNormal = normalize(uNormalMatrix * a_normal); diff --git a/data/shaders/opengl/attributes.glsl b/data/shaders/opengl/attributes.glsl index 1cad8ab8351..5bcff2c262c 100644 --- a/data/shaders/opengl/attributes.glsl +++ b/data/shaders/opengl/attributes.glsl @@ -35,6 +35,16 @@ layout (location = 4) in vec4 a_uv1; layout (location = 5) in vec3 a_tangent; layout (location = 6) in mat4 a_transform; // a_transform @ 6 shadows (uses) 7, 8, and 9 -// next available is layout (location = 10) +// next available is layout (location = 10) -#endif // VERTEX_SHADER \ No newline at end of file +// shorthand to abstract away instancing +vec4 matrixTransform() +{ +#ifdef USE_INSTANCING + return uViewProjectionMatrix * a_transform * a_vertex; +#else + return uViewProjectionMatrix * a_vertex; +#endif +} + +#endif // VERTEX_SHADER diff --git a/data/shaders/opengl/billboard_sphereimpostor.frag b/data/shaders/opengl/billboard_sphereimpostor.frag index c0ae2a448a1..efae537d895 100644 --- a/data/shaders/opengl/billboard_sphereimpostor.frag +++ b/data/shaders/opengl/billboard_sphereimpostor.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" in vec4 color; @@ -21,5 +20,4 @@ void main(void) vec3 normal = vec3(uv.x, uv.y, sqrt(1.0 - len)); float diff = dot(normal, lightDir); frag_color = color * diff + scene.ambient; - SetFragDepth(); } diff --git a/data/shaders/opengl/billboard_sphereimpostor.vert b/data/shaders/opengl/billboard_sphereimpostor.vert index 90a7e6ffa78..d5bb653cd66 100644 --- a/data/shaders/opengl/billboard_sphereimpostor.vert +++ b/data/shaders/opengl/billboard_sphereimpostor.vert @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec4 color; @@ -11,7 +10,7 @@ out vec3 lightDir; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); color = a_color; uv = a_uv0.xy * 2.0 - 1.0; //recenter to -1,1 range lightDir = normalize(-a_vertex.xyz); diff --git a/data/shaders/opengl/billboards.frag b/data/shaders/opengl/billboards.frag index 38f70edbd2d..5e18c55e1b9 100644 --- a/data/shaders/opengl/billboards.frag +++ b/data/shaders/opengl/billboards.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" uniform sampler2D texture0; @@ -18,5 +17,4 @@ void main(void) #else frag_color = texture(texture0, gl_PointCoord); #endif - SetFragDepth(); } diff --git a/data/shaders/opengl/billboards.vert b/data/shaders/opengl/billboards.vert index 94550e05055..5b1309529fe 100644 --- a/data/shaders/opengl/billboards.vert +++ b/data/shaders/opengl/billboards.vert @@ -2,14 +2,13 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec2 uv; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); gl_PointSize = a_normal.z; uv = a_normal.xy; } diff --git a/data/shaders/opengl/gassphere_base.frag b/data/shaders/opengl/gassphere_base.frag index 2405dd5bae1..a4b3aa27815 100644 --- a/data/shaders/opengl/gassphere_base.frag +++ b/data/shaders/opengl/gassphere_base.frag @@ -1,8 +1,7 @@ -// Copyright 2008-2020 Pioneer Developers. See AUTHORS.txt for details +// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" #include "eclipse.glsl" @@ -51,18 +50,18 @@ void main(void) float fogFactor=0.0; { float atmosDist = (length(eyepos) - atmosStart); - + // a&b scaled so length of 1.0 means planet surface. vec3 a = (atmosStart * eyenorm - geosphereCenter) * geosphereInvRadius; vec3 b = (eyepos - geosphereCenter) * geosphereInvRadius; ldprod = AtmosLengthDensityProduct(a, b, atmosColor.w*geosphereAtmosFogDensity, atmosDist, geosphereAtmosInvScaleHeight); - fogFactor = clamp( 1.5 / exp(ldprod),0.0,1.0); + fogFactor = clamp( 1.5 / exp(ldprod),0.0,1.0); } //calculate sunset tone red when passing through more atmosphere, clamp everything. float atmpower = (diff.r+diff.g+diff.b)/3.0; vec4 sunset = vec4(0.8,clamp(pow(atmpower,0.8),0.0,1.0),clamp(pow(atmpower,1.2),0.0,1.0),1.0); - + vec4 texColor = texture(texture0, varyingTexCoord0); frag_color = @@ -71,8 +70,6 @@ void main(void) ((scene.ambient * texColor) + (diff * texColor)) + (1.0-fogFactor)*(diff*atmosColor) + - (0.02-clamp(fogFactor,0.0,0.01))*diff*ldprod*sunset + //increase fog scatter + (0.02-clamp(fogFactor,0.0,0.01))*diff*ldprod*sunset + //increase fog scatter (pow((1.0-pow(fogFactor,0.75)),256.0)*0.4*diff*atmosColor)*sunset; //distant fog. - - SetFragDepth(); } diff --git a/data/shaders/opengl/gassphere_base.vert b/data/shaders/opengl/gassphere_base.vert index 5d85e0fd730..389738a01a0 100644 --- a/data/shaders/opengl/gassphere_base.vert +++ b/data/shaders/opengl/gassphere_base.vert @@ -1,8 +1,7 @@ -// Copyright 2008-2020 Pioneer Developers. See AUTHORS.txt for details +// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec3 varyingEyepos; @@ -14,7 +13,7 @@ uniform float geosphereRadius; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); varyingEyepos = vec3(uViewMatrix * a_vertex); varyingNormal = normalize(uNormalMatrix * a_normal); varyingTexCoord0 = a_normal.xyz; diff --git a/data/shaders/opengl/gen-gas-giant-colour.frag b/data/shaders/opengl/gen-gas-giant-colour.frag index 5ef40811327..b6d3068351d 100644 --- a/data/shaders/opengl/gen-gas-giant-colour.frag +++ b/data/shaders/opengl/gen-gas-giant-colour.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "noise.glsl" uniform sampler2D texture2; // ??? @@ -79,10 +78,8 @@ void main(void) { float xfrac = (uv.x-0.5) * fracStep; float yfrac = (uv.y-0.5) * fracStep; - + // call the GetColour function implemented for this shader type // Hue Shift the colour and store the final result frag_color = HueShift(GetColour(GetSpherePoint(xfrac, yfrac))); - - SetFragDepth(); } diff --git a/data/shaders/opengl/gen-gas-giant-colour.vert b/data/shaders/opengl/gen-gas-giant-colour.vert index a8a1044b486..2892afb8c41 100644 --- a/data/shaders/opengl/gen-gas-giant-colour.vert +++ b/data/shaders/opengl/gen-gas-giant-colour.vert @@ -2,14 +2,13 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" out vec3 vertex; out vec2 uv; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); vertex = (uViewMatrix * a_vertex).xyz; uv = a_uv0.xy; } diff --git a/data/shaders/opengl/geosphere_sky.frag b/data/shaders/opengl/geosphere_sky.frag index b11f95720a5..7f09cd33bda 100644 --- a/data/shaders/opengl/geosphere_sky.frag +++ b/data/shaders/opengl/geosphere_sky.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" #include "eclipse.glsl" @@ -49,16 +48,16 @@ void main(void) sphereEntryExitDist(skyNear, skyFar, geosphereCenter, varyingEyepos.xyz, geosphereRadius * geosphereAtmosTopRad); float atmosDist = (skyFar - skyNear); float ldprod=0.0; - + // a&b scaled so length of 1.0 means planet surface. vec3 a = (skyNear * eyenorm - geosphereCenter) * geosphereInvRadius; vec3 b = (skyFar * eyenorm - geosphereCenter) * geosphereInvRadius; ldprod = AtmosLengthDensityProduct(a, b, atmosColor.a * geosphereAtmosFogDensity, atmosDist, geosphereAtmosInvScaleHeight); - + float fogFactor = 1.0 / exp(ldprod); vec4 atmosDiffuse = vec4(0.0); -#if (NUM_LIGHTS > 0) +#if (NUM_LIGHTS > 0) vec3 surfaceNorm = normalize(skyNear * eyenorm - geosphereCenter); for (int i=0; i 0 -- unlit rendering - stars //emission is used to boost colour of stars, which is a bit odd frag_color = material.emission + vertexColor; - - SetFragDepth(); } diff --git a/data/shaders/opengl/geosphere_star.vert b/data/shaders/opengl/geosphere_star.vert index e952acfc908..baac69f798a 100644 --- a/data/shaders/opengl/geosphere_star.vert +++ b/data/shaders/opengl/geosphere_star.vert @@ -1,14 +1,13 @@ -// Copyright 2008-2020 Pioneer Developers. See AUTHORS.txt for details +// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec4 vertexColor; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); vertexColor = a_color; } diff --git a/data/shaders/opengl/geosphere_terrain.frag b/data/shaders/opengl/geosphere_terrain.frag index 81771523a86..070529d7b39 100644 --- a/data/shaders/opengl/geosphere_terrain.frag +++ b/data/shaders/opengl/geosphere_terrain.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" #include "eclipse.glsl" @@ -217,6 +216,4 @@ void main(void) varyingEmission + #endif final_color; - - SetFragDepth(); } diff --git a/data/shaders/opengl/geosphere_terrain.vert b/data/shaders/opengl/geosphere_terrain.vert index a526e5efc90..867051038ce 100644 --- a/data/shaders/opengl/geosphere_terrain.vert +++ b/data/shaders/opengl/geosphere_terrain.vert @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec3 varyingFragPos; @@ -23,7 +22,7 @@ uniform Material material; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); vertexColor = a_color; varyingFragPos = vec3(uViewMatrix * a_vertex); varyingNormal = normalize(uNormalMatrix * a_normal); diff --git a/data/shaders/opengl/logz.glsl b/data/shaders/opengl/logz.glsl deleted file mode 100644 index 01860cb7d05..00000000000 --- a/data/shaders/opengl/logz.glsl +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt - -// See http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=263350&reply_id=3513134 -#ifdef FRAGMENT_SHADER -uniform float invLogZfarPlus1; -in float varLogDepth; -#else -out float varLogDepth; -#endif - -#ifdef VERTEX_SHADER -vec4 logarithmicTransform() -{ -#ifdef USE_INSTANCING - //vec4 vertexPosClip = uProjectionMatrix * uViewMatrix * a_transform * a_vertex; - vec4 vertexPosClip = uViewProjectionMatrix * a_transform * a_vertex; -#else - vec4 vertexPosClip = uViewProjectionMatrix * a_vertex; -#endif - varLogDepth = vertexPosClip.z; - return vertexPosClip; -} -#elif defined(FRAGMENT_SHADER) -void SetFragDepth() -{ - gl_FragDepth = gl_DepthRange.near + (gl_DepthRange.far * log(varLogDepth + 1.0) * invLogZfarPlus1); -} -#endif diff --git a/data/shaders/opengl/multi.frag b/data/shaders/opengl/multi.frag index 2c884d9905b..03a0a7f1227 100644 --- a/data/shaders/opengl/multi.frag +++ b/data/shaders/opengl/multi.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" #ifdef TEXTURE0 @@ -130,5 +129,4 @@ void main(void) #else frag_color = color; #endif - SetFragDepth(); } diff --git a/data/shaders/opengl/multi.vert b/data/shaders/opengl/multi.vert index 9cb2edda9e9..6e5d57e8e5b 100644 --- a/data/shaders/opengl/multi.vert +++ b/data/shaders/opengl/multi.vert @@ -4,7 +4,6 @@ // #extension GL_ARB_gpu_shader5 : enable #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" #ifdef TEXTURE0 @@ -29,7 +28,7 @@ out vec3 normal; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); #ifdef VERTEXCOLOR vertexColor = a_color; #endif diff --git a/data/shaders/opengl/planetrings.frag b/data/shaders/opengl/planetrings.frag index 1433413d665..de722ad9779 100644 --- a/data/shaders/opengl/planetrings.frag +++ b/data/shaders/opengl/planetrings.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" uniform sampler2D texture0; @@ -25,6 +24,4 @@ void main(void) } col.a = texCol.a; frag_color = col; - - SetFragDepth(); } diff --git a/data/shaders/opengl/planetrings.vert b/data/shaders/opengl/planetrings.vert index c550ff3a945..7365d8dbefb 100644 --- a/data/shaders/opengl/planetrings.vert +++ b/data/shaders/opengl/planetrings.vert @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" out vec2 texCoord0; @@ -10,7 +9,7 @@ out vec4 texCoord1; void main(void) { - gl_Position = logarithmicTransform(); + gl_Position = matrixTransform(); texCoord0 = a_uv0.xy; texCoord1 = a_vertex; diff --git a/data/shaders/opengl/shield.frag b/data/shaders/opengl/shield.frag index 6da527dddd8..1e39bed0d5f 100644 --- a/data/shaders/opengl/shield.frag +++ b/data/shaders/opengl/shield.frag @@ -2,7 +2,6 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "attributes.glsl" -#include "logz.glsl" #include "lib.glsl" in vec3 varyingEyepos; @@ -32,7 +31,7 @@ float calcIntensity(int shieldIndex) float life = radii[shieldIndex]; float radius = 50.0 * life; vec3 dif = varyingVertex - current_position; - + float sqrDist = dot(dif,dif); return clamp(1.0/sqrDist*radius, 0.0, 0.9) * (1.0 - life); @@ -43,26 +42,24 @@ void main(void) //vec4 color = material.diffuse; vec4 color = mix(red, blue, shieldStrength); vec4 fillColour = color * 0.15; - + vec3 eyenorm = normalize(-varyingEyepos); float fresnel = 1.0 - abs(dot(eyenorm, varyingNormal)); // Calculate fresnel. fresnel = pow(fresnel, 10.0); fresnel += 0.05 * (1.0 - fresnel); - + float sumIntensity = 0.0; for ( int hit=0; hit> 24) & 0xff), g((rgba >> 16) & 0xff), b((rgba >> 8) & 0xff), @@ -159,19 +159,19 @@ struct Color4ub { struct Color3ub { Uint8 r, g, b; - Color3ub() : + constexpr Color3ub() : r(0), g(0), b(0) {} - Color3ub(Uint8 v_) : + constexpr Color3ub(Uint8 v_) : r(v_), g(v_), b(v_) {} - Color3ub(Uint8 r_, Uint8 g_, Uint8 b_) : + constexpr Color3ub(Uint8 r_, Uint8 g_, Uint8 b_) : r(r_), g(g_), b(b_) {} - Color3ub(const Color4f &c) : + constexpr Color3ub(const Color4f &c) : r(Uint8(c.r * 255.f)), g(Uint8(c.g * 255.f)), b(Uint8(c.b * 255.f)) {} diff --git a/src/DynamicBody.h b/src/DynamicBody.h index 5f47727981f..59b09311b26 100644 --- a/src/DynamicBody.h +++ b/src/DynamicBody.h @@ -67,6 +67,7 @@ class DynamicBody : public ModelBody { AIERROR_NONE = 0, AIERROR_GRAV_TOO_HIGH, AIERROR_REFUSED_PERM, + AIERROR_PRESS_TOO_HIGH, AIERROR_ORBIT_IMPOSSIBLE }; AIError AIMessage(AIError msg = AIERROR_NONE) diff --git a/src/Game.cpp b/src/Game.cpp index d4667958f95..14ab1768d82 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -31,7 +31,7 @@ #include "UIView.h" #include "WorldView.h" #include "galaxy/GalaxyGenerator.h" -#include "pigui/View.h" +#include "pigui/PiGuiView.h" #include "ship/PlayerShipController.h" static const int s_saveVersion = 86; diff --git a/src/JobQueue.h b/src/JobQueue.h index c9435bb479c..143fe0c691f 100644 --- a/src/JobQueue.h +++ b/src/JobQueue.h @@ -263,6 +263,7 @@ class JobSet : public JobClient { virtual void Order(Job *job) { auto x = m_jobs.insert(m_queue->Queue(job, this)); + (void)x; // suppress unused variable warning assert(x.second); } virtual void RemoveJob(Job::Handle *handle) { m_jobs.erase(*handle); } diff --git a/src/ObjectViewerView.cpp b/src/ObjectViewerView.cpp index d19487be9f8..9c876b00093 100644 --- a/src/ObjectViewerView.cpp +++ b/src/ObjectViewerView.cpp @@ -17,7 +17,7 @@ #include "graphics/Light.h" #include "graphics/Renderer.h" #include "imgui/imgui.h" -#include "lua/LuaPiGui.h" +#include "pigui/LuaPiGui.h" #include "terrain/Terrain.h" #include "utils.h" @@ -242,7 +242,7 @@ void ObjectViewerView::DrawControlsWindow() OnChangeTerrain(); } - PiGUI::RunHandler(Pi::GetFrameTime(), GetViewName() + ".Controls"); + PiGui::RunHandler(Pi::GetFrameTime(), GetViewName() + ".Controls"); ImGui::End(); } diff --git a/src/ObjectViewerView.h b/src/ObjectViewerView.h index 38dbc01811d..461c2f99a81 100644 --- a/src/ObjectViewerView.h +++ b/src/ObjectViewerView.h @@ -7,7 +7,7 @@ #include "Camera.h" #include "gui/Gui.h" #include "libs.h" -#include "pigui/View.h" +#include "pigui/PiGuiView.h" class Body; class SystemBody; diff --git a/src/Pi.cpp b/src/Pi.cpp index 97ef2731ac7..6ff6c4378ad 100644 --- a/src/Pi.cpp +++ b/src/Pi.cpp @@ -27,10 +27,10 @@ #include "core/Log.h" #include "core/OS.h" #include "graphics/opengl/RendererGL.h" +#include "imgui/imgui.h" #include "lua/Lua.h" #include "lua/LuaConsole.h" #include "lua/LuaEvent.h" -#include "lua/LuaPiGui.h" #include "lua/LuaTimer.h" #include "profiler/Profiler.h" #include "sound/AmbientSounds.h" @@ -58,9 +58,9 @@ #include "galaxy/GalaxyGenerator.h" #include "gameui/Lua.h" #include "libs.h" +#include "pigui/LuaPiGui.h" #include "pigui/PerfInfo.h" #include "pigui/PiGui.h" -#include "pigui/PiGuiLua.h" #include "ship/PlayerShipController.h" #include "ship/ShipViewController.h" #include "sound/Sound.h" @@ -182,7 +182,7 @@ class LoadStep : public Application::Lifecycle { // FIXME: this is a hack, this class should have its lifecycle managed elsewhere // Ideally an application framework class handles this (as well as the rest of the main loop) // but for now this is the best we have. -std::unique_ptr perfInfoDisplay; +std::unique_ptr perfInfoDisplay; class MainMenu : public Application::Lifecycle { public: @@ -455,7 +455,7 @@ void Pi::App::Shutdown() FaceParts::Uninit(); Graphics::Uninit(); - PiGUI::Lua::Uninit(); + PiGui::Lua::Uninit(); ShutdownPiGui(); Pi::pigui = nullptr; Pi::ui.Reset(0); @@ -513,11 +513,14 @@ void LoadStep::Start() // Investigate using a pigui-only Lua state that we can initialize without depending on // normal init flow, or drawing the init screen in C++ instead? // Loads just the PiGui class and PiGui-related modules - PiGUI::Lua::Init(); + PiGui::Lua::Init(); + // FIXME: this just exists to load the theme out-of-order from Lua::InitModules. Needs a better solution + PiGui::LoadThemeFromDisk("default"); + PiGui::LoadTheme(ImGui::GetStyle(), "default"); // Don't render the first frame, just make sure all of our fonts are loaded Pi::pigui->NewFrame(); - PiGUI::RunHandler(0.01, "init"); + PiGui::RunHandler(0.01, "init"); Pi::pigui->EndFrame(); AddStep("UI::AddContext", []() { @@ -611,7 +614,7 @@ void LoadStep::Start() Pi::planner = new TransferPlanner(); - perfInfoDisplay.reset(new PiGUI::PerfInfo()); + perfInfoDisplay.reset(new PiGui::PerfInfo()); }); } @@ -634,7 +637,7 @@ void LoadStep::Update(float deltaTime) loader.name.c_str(), timer.milliseconds()); Pi::pigui->NewFrame(); - PiGUI::RunHandler(progress, "init"); + PiGui::RunHandler(progress, "init"); Pi::pigui->Render(); } else { @@ -675,7 +678,7 @@ void MainMenu::Update(float deltaTime) Pi::intro->Draw(deltaTime); Pi::pigui->NewFrame(); - PiGUI::RunHandler(deltaTime, "mainMenu"); + PiGui::RunHandler(deltaTime, "mainMenu"); perfInfoDisplay->Update(deltaTime * 1e3, 0.0); if (Pi::showDebugInfo) { @@ -1122,7 +1125,7 @@ void GameLoop::Update(float deltaTime) if (Pi::game && !Pi::player->IsDead()) { // FIXME: major hack to work around the fact that the console is in newUI and not pigui if (!Pi::IsConsoleActive()) - PiGUI::RunHandler(deltaTime, "game"); + PiGui::RunHandler(deltaTime, "game"); Pi::GetView()->DrawPiGui(); } diff --git a/src/SectorView.cpp b/src/SectorView.cpp index 907f31a746d..2414ad84b17 100644 --- a/src/SectorView.cpp +++ b/src/SectorView.cpp @@ -446,11 +446,9 @@ void SectorView::PutSystemLabels(RefCountedPtr sec, const vector3f &orig // place the label vector3d systemPos = vector3d((*sys).GetFullPosition() - origin); vector3d screenPos; - if (Gui::Screen::Project(systemPos, screenPos)) { - // reject back-projected labels - if (screenPos.z > 1.0f) - continue; - + Gui::Screen::Project(systemPos, screenPos); + // reject back-projected labels (negative Z in clipspace is in front of the view plane) + if (screenPos.z < 0.0f) { // work out the colour Color labelColor = sys->GetFaction()->AdjustedColour(sys->GetPopulation(), inRange); @@ -487,7 +485,8 @@ void SectorView::PutFactionLabels(const vector3f &origin) if ((m_pos * Sector::SIZE - sys.GetFullPosition()).Length() > (m_zoomClamped / FAR_THRESHOLD) * OUTER_RADIUS) continue; vector3d pos; - if (Gui::Screen::Project(vector3d(sys.GetFullPosition() - origin), pos)) { + Gui::Screen::Project(vector3d(sys.GetFullPosition() - origin), pos); + if (pos.z < 0.0f) { // reject back-projected stars std::string labelText = sys.GetName() + "\n" + (*it)->name; Color labelColor = (*it)->colour; diff --git a/src/Ship.cpp b/src/Ship.cpp index 96bfcca5790..06a1f5e8384 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -358,6 +358,14 @@ float Ship::GetPercentShields() const return 100.0f * (m_stats.shield_mass_left / m_stats.shield_mass); } +float Ship::GetAtmosphericPressureLimit() const +{ + int atmo_shield_cap = 0; + const_cast(this)->Properties().Get("atmo_shield_cap", atmo_shield_cap); + atmo_shield_cap = std::max(atmo_shield_cap, 1); //default to base limit if no shield installed + return m_type->atmosphericPressureLimit * atmo_shield_cap; +} + void Ship::SetPercentHull(float p) { m_stats.hull_mass_left = 0.01f * Clamp(p, 0.0f, 100.0f) * float(m_type->hullMass); diff --git a/src/Ship.h b/src/Ship.h index 0de39332a49..06516314eed 100644 --- a/src/Ship.h +++ b/src/Ship.h @@ -39,7 +39,7 @@ struct shipstats_t { int used_capacity; int used_cargo; int free_capacity; - int static_mass; // cargo, equipment + hull + int static_mass; // cargo, equipment + hull float hull_mass_left; // effectively hitpoints float hyperspace_range; float hyperspace_range_max; @@ -112,13 +112,13 @@ class Ship : public DynamicBody { virtual bool OnDamage(Object *attacker, float kgDamage, const CollisionContact &contactData) override; enum FlightState { // - FLYING, // open flight (includes autopilot) - DOCKING, // in docking animation - UNDOCKING, // in docking animation - DOCKED, // docked with station - LANDED, // rough landed (not docked) - JUMPING, // between space and hyperspace ;) - HYPERSPACE, // in hyperspace + FLYING, // open flight (includes autopilot) + DOCKING, // in docking animation + UNDOCKING, // in docking animation + DOCKED, // docked with station + LANDED, // rough landed (not docked) + JUMPING, // between space and hyperspace ;) + HYPERSPACE, // in hyperspace }; // vector3d CalcAtmoPassiveControl() const; @@ -182,12 +182,12 @@ class Ship : public DynamicBody { void AIGetStatusText(char *str); // Note: defined in Ship-AI.cpp void AIKamikaze(Body *target); // Note: defined in Ship-AI.cpp - void AIKill(Ship *target); // Note: defined in Ship-AI.cpp + void AIKill(Ship *target); // Note: defined in Ship-AI.cpp //void AIJourney(SystemBodyPath &dest); - void AIDock(SpaceStation *target); // Note: defined in Ship-AI.cpp - void AIFlyTo(Body *target); // Note: defined in Ship-AI.cpp + void AIDock(SpaceStation *target); // Note: defined in Ship-AI.cpp + void AIFlyTo(Body *target); // Note: defined in Ship-AI.cpp void AIOrbit(Body *target, double alt); // Note: defined in Ship-AI.cpp - void AIHoldPosition(); // Note: defined in Ship-AI.cpp + void AIHoldPosition(); // Note: defined in Ship-AI.cpp void AIBodyDeleted(const Body *const body){}; // Note: defined in Ship-AI.cpp // todo: signals @@ -206,6 +206,7 @@ class Ship : public DynamicBody { void SetLabel(const std::string &label) override; void SetShipName(const std::string &shipName); + float GetAtmosphericPressureLimit() const; float GetPercentShields() const; float GetPercentHull() const; void SetPercentHull(float); @@ -233,7 +234,6 @@ class Ship : public DynamicBody { double GetLandingPosOffset() const { return m_landingMinOffset; } protected: - vector3d CalcAtmosphericForce() const override; virtual void SaveToJson(Json &jsonObj, Space *space) override; diff --git a/src/ShipAICmd.cpp b/src/ShipAICmd.cpp index d6ee03f1192..96fc350db10 100644 --- a/src/ShipAICmd.cpp +++ b/src/ShipAICmd.cpp @@ -6,6 +6,7 @@ #include "Frame.h" #include "Game.h" #include "Pi.h" +#include "Planet.h" #include "Ship.h" #include "Space.h" #include "SpaceStation.h" @@ -444,7 +445,7 @@ bool AICmdKill::TimeStepUpdate() vector3d targav = m_target->GetAngVelocity(); if (skillEvade < 1.6 && targhead.z < 0.0) { // smart chase - vector3d objvel = targvel * rot; // obj space targvel + vector3d objvel = targvel * rot; // obj space targvel if ((objvel.x * objvel.x + objvel.y * objvel.y) < 10000) { evadethrust.x = objvel.x > 0.0 ? 1.0 : -1.0; evadethrust.y = objvel.y > 0.0 ? 1.0 : -1.0; @@ -762,7 +763,7 @@ static int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pa vector3d perpdir = (tanlen * pathdir + spos).Normalized(); double perpspeed = dBody->GetVelocity().Dot(perpdir); double parspeed = dBody->GetVelocity().Dot(pathdir); - if (parspeed < 0) parspeed = 0; // shouldn't break any important case + if (parspeed < 0) parspeed = 0; // shouldn't break any important case if (perpspeed > 0) perpspeed = 0; // prevent attempts to speculatively fly through planets // find time that dBody will pass through that point @@ -787,7 +788,7 @@ static bool ParentSafetyAdjust(DynamicBody *dBody, FrameId targframeId, vector3d while (frame) { Frame *bFrame = Frame::GetFrame(dBody->GetFrame()); if (bFrame->GetNonRotFrame() == frameId) break; // ship in frame, stop - if (frame->GetBody()) body = frame->GetBody(); // ignore grav points? + if (frame->GetBody()) body = frame->GetBody(); // ignore grav points? double sdist = dBody->GetPositionRelTo(frameId).Length(); if (sdist < frame->GetRadius()) break; // ship inside frame, stop @@ -995,7 +996,7 @@ bool AICmdFlyTo::TimeStepUpdate() m_child.reset(); } if (m_tangent && m_frameId.valid()) return true; // regen tangent on frame switch - m_reldir = reldir; // for +vel termination condition + m_reldir = reldir; // for +vel termination condition m_frameId = m_dBody->GetFrame(); } @@ -1024,7 +1025,7 @@ bool AICmdFlyTo::TimeStepUpdate() } } if (m_state < 0 && m_state > -6 && m_tangent) return true; // bail out - if (m_state < 0) m_state = targdist > 10000000.0 ? 1 : 0; // still lame + if (m_state < 0) m_state = targdist > 10000000.0 ? 1 : 0; // still lame double maxdecel = m_state ? m_prop->GetAccelFwd() : m_prop->GetAccelRev(); double gravdir = -reldir.Dot(m_dBody->GetPosition().Normalized()); @@ -1172,6 +1173,21 @@ AICmdDock::AICmdDock(DynamicBody *dBody, SpaceStation *target) : m_prop.Reset(ship->GetPropulsion()); assert(m_prop != nullptr); + if (target->IsGroundStation()) { + Frame *frame = Frame::GetFrame(target->GetFrame()); + Body *stationPlanet = frame->GetBody(); + Planet *p = static_cast(stationPlanet); + + double pressure, density; + p->GetAtmosphericState(target->GetPositionRelTo(stationPlanet).Length(), &pressure, &density); + + if (pressure > static_cast(dBody)->GetAtmosphericPressureLimit()) { + m_dBody->AIMessage(Ship::AIERROR_PRESS_TOO_HIGH); + m_target = nullptr; // bail out on next timestep call + return; + } + } + double grav = GetGravityAtPos(m_target->GetFrame(), m_target->GetPosition()); if (m_prop->GetAccelUp() < grav) { m_dBody->AIMessage(Ship::AIERROR_GRAV_TOO_HIGH); diff --git a/src/Space.cpp b/src/Space.cpp index c2dd911fa77..4bd4579c4ed 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -157,8 +157,8 @@ Space::Space(Game *game, RefCountedPtr galaxy, const Json &jsonObj, doub Space::~Space() { UpdateBodies(); // make sure anything waiting to be removed gets removed before we go and kill everything else - for (std::list::iterator i = m_bodies.begin(); i != m_bodies.end(); ++i) - KillBody(*i); + for (Body *body : m_bodies) + KillBody(body); UpdateBodies(); Frame::DeleteFrames(); } @@ -278,7 +278,7 @@ void Space::RemoveBody(Body *b) #ifndef NDEBUG assert(!m_processingFinalizationQueue); #endif - m_removeBodies.push_back(b); + m_assignedBodies.emplace_back(b, BodyAssignation::REMOVE); } void Space::KillBody(Body *b) @@ -296,7 +296,7 @@ void Space::KillBody(Body *b) // it still collides, moves, etc. better to just snapshot its position // elsewhere if (b != Pi::player) - m_killBodies.push_back(b); + m_assignedBodies.emplace_back(b, BodyAssignation::KILL); } } @@ -367,13 +367,13 @@ Body *Space::FindNearestTo(const Body *b, Object::Type t) const { Body *nearest = 0; double dist = FLT_MAX; - for (std::list::const_iterator i = m_bodies.begin(); i != m_bodies.end(); ++i) { - if ((*i)->IsDead()) continue; - if ((*i)->IsType(t)) { - double d = (*i)->GetPositionRelTo(b).Length(); + for (Body *const body : m_bodies) { + if (body->IsDead()) continue; + if (body->IsType(t)) { + double d = body->GetPositionRelTo(b).Length(); if (d < dist) { dist = d; - nearest = *i; + nearest = body; } } } @@ -1002,23 +1002,26 @@ void Space::UpdateBodies() m_processingFinalizationQueue = true; #endif - for (Body *rmb : m_removeBodies) { - rmb->SetFrame(FrameId::Invalid); - for (Body *b : m_bodies) - b->NotifyRemoved(rmb); - if (Pi::GetView()) Pi::game->GetSystemView()->BodyInaccessible(rmb); - m_bodies.remove(rmb); - } - m_removeBodies.clear(); - - for (Body *killb : m_killBodies) { - for (Body *b : m_bodies) - b->NotifyRemoved(killb); - if (Pi::GetView()) Pi::game->GetSystemView()->BodyInaccessible(killb); - m_bodies.remove(killb); - delete killb; + // removing or deleting bodies from space + for (const auto &b : m_assignedBodies) { + auto remove_iterator = m_bodies.end(); + for (auto it = m_bodies.begin(); it != m_bodies.end(); ++it) { + if (*it != b.first) + (*it)->NotifyRemoved(b.first); + else + remove_iterator = it; + } + if (remove_iterator != m_bodies.end()) { + *remove_iterator = m_bodies.back(); + m_bodies.pop_back(); + if (b.second == BodyAssignation::KILL) + delete b.first; + else + b.first->SetFrame(FrameId::Invalid); + } } - m_killBodies.clear(); + + m_assignedBodies.clear(); #ifndef NDEBUG m_processingFinalizationQueue = false; diff --git a/src/Space.h b/src/Space.h index 5f7f1900873..8bc767960f9 100644 --- a/src/Space.h +++ b/src/Space.h @@ -11,7 +11,6 @@ #include "RefCounted.h" #include "galaxy/StarSystem.h" #include "vector3.h" -#include class Body; class Frame; @@ -67,8 +66,8 @@ class Space { Body *FindBodyForPath(const SystemPath *path) const; Uint32 GetNumBodies() const { return static_cast(m_bodies.size()); } - IterationProxy> GetBodies() { return MakeIterationProxy(m_bodies); } - const IterationProxy> GetBodies() const { return MakeIterationProxy(m_bodies); } + IterationProxy> GetBodies() { return MakeIterationProxy(m_bodies); } + const IterationProxy> GetBodies() const { return MakeIterationProxy(m_bodies); } Background::Container *GetBackground() { return m_background.get(); } void RefreshBackground(); @@ -85,6 +84,7 @@ class Space { } void DebugDumpFrames(bool details); + private: void GenSectorCache(RefCountedPtr galaxy, const SystemPath *here); void UpdateStarSystemCache(const SystemPath *here); @@ -106,11 +106,15 @@ class Space { Game *m_game; // all the bodies we know about - std::list m_bodies; + std::vector m_bodies; // bodies that were removed/killed this timestep and need pruning at the end - std::list m_removeBodies; - std::list m_killBodies; + enum class BodyAssignation { + KILL = 0, + REMOVE = 1 + }; + + std::vector> m_assignedBodies; void RebuildBodyIndex(); void RebuildSystemBodyIndex(); @@ -160,7 +164,6 @@ class Space { //the NotifyRemoved callback (#735) bool m_processingFinalizationQueue; #endif - }; #endif /* _SPACE_H */ diff --git a/src/SystemView.cpp b/src/SystemView.cpp index 6df67d37469..ffffdcaf46e 100644 --- a/src/SystemView.cpp +++ b/src/SystemView.cpp @@ -1,7 +1,8 @@ // Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -#include "lua/LuaPiGui.h" +#include "graphics/Graphics.h" +#include "pigui/LuaPiGui.h" #include "SystemView.h" @@ -17,6 +18,7 @@ #include "StringF.h" #include "galaxy/Galaxy.h" #include "galaxy/StarSystem.h" +#include "galaxy/SystemPath.h" #include "graphics/Material.h" #include "graphics/Renderer.h" #include "graphics/TextureBuilder.h" @@ -336,25 +338,16 @@ void SystemView::PutOrbit(Projectable::bases base, RefType *ref, const Orbit *or } } - Gui::Screen::EnterOrtho(); - vector3d pos; - if (Gui::Screen::Project(offset + orbit->Perigeum(), pos) && pos.z < 1) - AddProjected(Projectable::PERIAPSIS, base, ref, pos, offset + orbit->Perigeum()); - if (Gui::Screen::Project(offset + orbit->Apogeum(), pos) && pos.z < 1) - AddProjected(Projectable::APOAPSIS, base, ref, pos, offset + orbit->Apogeum()); + AddProjected(Projectable::PERIAPSIS, base, ref, offset + orbit->Perigeum()); + AddProjected(Projectable::APOAPSIS, base, ref, offset + orbit->Apogeum()); if (showLagrange && m_showL4L5 != LAG_OFF) { const vector3d posL4 = orbit->EvenSpacedPosTrajectory((1.0 / 360.0) * 60.0, tMinust0); - if (Gui::Screen::Project(offset + posL4, pos) && pos.z < 1) { - AddProjected(Projectable::L4, base, ref, pos, offset + posL4); - } + AddProjected(Projectable::L4, base, ref, offset + posL4); const vector3d posL5 = orbit->EvenSpacedPosTrajectory((1.0 / 360.0) * 300.0, tMinust0); - if (Gui::Screen::Project(offset + posL5, pos) && pos.z < 1) { - AddProjected(Projectable::L5, base, ref, pos, offset + posL5); - } + AddProjected(Projectable::L5, base, ref, offset + posL5); } - Gui::Screen::LeaveOrtho(); } void SystemView::PutBody(const SystemBody *b, const vector3d &offset, const matrix4x4f &trans) @@ -384,7 +377,7 @@ void SystemView::PutBody(const SystemBody *b, const vector3d &offset, const matr m_renderer->SetTransform(trans); - AddNotProjected(Projectable::OBJECT, Projectable::SYSTEMBODY, b, offset); + AddProjected(Projectable::OBJECT, Projectable::SYSTEMBODY, b, offset); } Frame *frame = Frame::GetFrame(Pi::player->GetFrame()); @@ -561,7 +554,7 @@ void SystemView::Draw3D() Frame *playerNonRotFrame = Frame::GetFrame(playerNonRotFrameId); SystemBody *playerAround = playerNonRotFrame->GetSystemBody(); CalculateShipPositionAtTime(static_cast(Pi::player), playerOrbit, m_time, ppos); - AddNotProjected(Projectable::OBJECT, Projectable::PLAYER, PlayerBody, ppos + pos); + AddProjected(Projectable::OBJECT, Projectable::PLAYER, PlayerBody, ppos + pos); vector3d offset(0.0); CalculateFramePositionAtTime(playerNonRotFrameId, m_time, offset); @@ -576,9 +569,9 @@ void SystemView::Draw3D() playerAround->GetMass()); PutOrbit(Projectable::PLANNER, PlayerBody, &plannedOrbit, offset, svColor[PLANNER_ORBIT], playerAround->GetRadius()); if (std::fabs(m_time - m_game->GetTime()) > 1. && (m_time - plannerStartTime) > 0.) - AddNotProjected(Projectable::OBJECT, Projectable::PLANNER, PlayerBody, offset + plannedOrbit.OrbitalPosAtTime(m_time - plannerStartTime)); + AddProjected(Projectable::OBJECT, Projectable::PLANNER, PlayerBody, offset + plannedOrbit.OrbitalPosAtTime(m_time - plannerStartTime)); else - AddNotProjected(Projectable::OBJECT, Projectable::PLANNER, PlayerBody, offset + m_planner->GetPosition()); + AddProjected(Projectable::OBJECT, Projectable::PLANNER, PlayerBody, offset + m_planner->GetPosition()); } } } @@ -667,7 +660,7 @@ void SystemView::DrawShips(const double t, const vector3d &offset) pos = pos + offset; //draw highlighted orbit for selected ship const bool isSelected = m_selectedObject.type == Projectable::OBJECT && m_selectedObject.base != Projectable::SYSTEMBODY && m_selectedObject.ref.body == (*s).first; - AddNotProjected(Projectable::OBJECT, Projectable::SHIP, static_cast((*s).first), pos); + AddProjected(Projectable::OBJECT, Projectable::SHIP, static_cast((*s).first), pos); if (m_shipDrawing == ORBITS && (*s).first->GetFlightState() == Ship::FlightState::FLYING) { vector3d framepos(0.0); CalculateFramePositionAtTime(Frame::GetFrame((*s).first->GetFrame())->GetNonRotFrame(), m_time, framepos); @@ -713,25 +706,14 @@ void SystemView::DrawGrid() } template -void SystemView::AddNotProjected(Projectable::types type, Projectable::bases base, T *ref, const vector3d &worldpos) +void SystemView::AddProjected(Projectable::types type, Projectable::bases base, T *ref, const vector3d &worldpos) { - //project and add - Gui::Screen::EnterOrtho(); - vector3d screenpos; - if (Gui::Screen::Project(worldpos, screenpos) && screenpos.z < 1) - AddProjected(type, base, ref, screenpos, worldpos); - Gui::Screen::LeaveOrtho(); -} + vector3d pos = Graphics::ProjectToScreen(m_renderer, worldpos); + if (pos.z > 0.0) return; // reject back-projected objects + pos.y = m_renderer->GetViewport().h - pos.y; -template -void SystemView::AddProjected(Projectable::types type, Projectable::bases base, T *ref, vector3d &pos, const vector3d &worldpos) -{ - float scale[2]; - Gui::Screen::GetCoords2Pixels(scale); Projectable p(type, base, ref); - p.screenpos.x = pos.x / scale[0]; - p.screenpos.y = pos.y / scale[1]; - p.screenpos.z = pos.z; + p.screenpos = pos; p.worldpos = worldpos; m_projected.push_back(p); } diff --git a/src/SystemView.h b/src/SystemView.h index f231e7e7c5b..58321bfdc5a 100644 --- a/src/SystemView.h +++ b/src/SystemView.h @@ -5,6 +5,7 @@ #define _SYSTEMVIEW_H #include "Color.h" +#include "DeleteEmitter.h" #include "UIView.h" #include "graphics/Drawables.h" #include "matrix4x4.h" @@ -168,10 +169,10 @@ class SystemView : public UIView, public DeleteEmitter { void RefreshShips(void); void DrawShips(const double t, const vector3d &offset); void DrawGrid(); + + // Project a position in the current renderer project to screenspace and add it to the list of projected objects template - void AddProjected(Projectable::types type, Projectable::bases base, T *ref, vector3d &pos, const vector3d &worldpos); - template - void AddNotProjected(Projectable::types type, Projectable::bases base, T *ref, const vector3d &worldpos); + void AddProjected(Projectable::types type, Projectable::bases base, T *ref, const vector3d &worldpos); void CalculateShipPositionAtTime(const Ship *s, Orbit o, double t, vector3d &pos); void CalculateFramePositionAtTime(FrameId frameId, double t, vector3d &pos); double GetOrbitTime(double t, const SystemBody* b); diff --git a/src/WorldView.h b/src/WorldView.h index af02d5664f9..f7a88601700 100644 --- a/src/WorldView.h +++ b/src/WorldView.h @@ -5,7 +5,7 @@ #define _WORLDVIEW_H #include "gui/GuiWidget.h" -#include "pigui/View.h" +#include "pigui/PiGuiView.h" #include "ship/ShipViewController.h" class Body; diff --git a/src/enum_table.cpp b/src/enum_table.cpp index c8036efa552..2c87998a4a8 100644 --- a/src/enum_table.cpp +++ b/src/enum_table.cpp @@ -34,6 +34,7 @@ const struct EnumItem ENUM_ShipAIError[] = { { "NONE", int(Ship::AIERROR_NONE) }, { "GRAV_TOO_HIGH", int(Ship::AIERROR_GRAV_TOO_HIGH) }, + { "PRESS_TOO_HIGH", int(Ship::AIERROR_PRESS_TOO_HIGH) }, { "REFUSED_PERM", int(Ship::AIERROR_REFUSED_PERM) }, { "ORBIT_IMPOSSIBLE", int(Ship::AIERROR_ORBIT_IMPOSSIBLE) }, { 0, 0 }, @@ -289,11 +290,11 @@ const struct EnumItem ENUM_FileSystemRoot[] = { { 0, 0 }, }; -const struct EnumItem ENUM_PiGUIFaceFlags[] = { - { "RAND", int(PiGUI::Face::RAND) }, - { "MALE", int(PiGUI::Face::MALE) }, - { "FEMALE", int(PiGUI::Face::FEMALE) }, - { "ARMOUR", int(PiGUI::Face::ARMOUR) }, +const struct EnumItem ENUM_PiGuiFaceFlags[] = { + { "RAND", int(PiGui::Face::RAND) }, + { "MALE", int(PiGui::Face::MALE) }, + { "FEMALE", int(PiGui::Face::FEMALE) }, + { "ARMOUR", int(PiGui::Face::ARMOUR) }, { 0, 0 }, }; @@ -540,7 +541,7 @@ const struct EnumTable ENUM_TABLES[] = { { "GameUIFaceFlags", ENUM_GameUIFaceFlags }, { "DetailLevel", ENUM_DetailLevel }, { "FileSystemRoot", ENUM_FileSystemRoot }, - { "PiGUIFaceFlags", ENUM_PiGUIFaceFlags }, + { "PiGuiFaceFlags", ENUM_PiGuiFaceFlags }, { "ModelDebugFlags", ENUM_ModelDebugFlags }, { "ShipTypeThruster", ENUM_ShipTypeThruster }, { "PropulsionFuelStatus", ENUM_PropulsionFuelStatus }, @@ -588,7 +589,7 @@ const struct EnumTable ENUM_TABLES_PUBLIC[] = { { "GameUIFaceFlags", ENUM_GameUIFaceFlags }, { "DetailLevel", ENUM_DetailLevel }, { "FileSystemRoot", ENUM_FileSystemRoot }, - { "PiGUIFaceFlags", ENUM_PiGUIFaceFlags }, + { "PiGuiFaceFlags", ENUM_PiGuiFaceFlags }, { "ModelDebugFlags", ENUM_ModelDebugFlags }, { "ShipTypeThruster", ENUM_ShipTypeThruster }, { "PropulsionFuelStatus", ENUM_PropulsionFuelStatus }, diff --git a/src/enum_table.h b/src/enum_table.h index 16200da2665..806a810769c 100644 --- a/src/enum_table.h +++ b/src/enum_table.h @@ -36,7 +36,7 @@ extern const struct EnumItem ENUM_BodySuperType[]; extern const struct EnumItem ENUM_GameUIFaceFlags[]; extern const struct EnumItem ENUM_DetailLevel[]; extern const struct EnumItem ENUM_FileSystemRoot[]; -extern const struct EnumItem ENUM_PiGUIFaceFlags[]; +extern const struct EnumItem ENUM_PiGuiFaceFlags[]; extern const struct EnumItem ENUM_ModelDebugFlags[]; extern const struct EnumItem ENUM_ShipTypeThruster[]; extern const struct EnumItem ENUM_PropulsionFuelStatus[]; diff --git a/src/graphics/Frustum.cpp b/src/graphics/Frustum.cpp index 0882458916a..a59c2f1e205 100644 --- a/src/graphics/Frustum.cpp +++ b/src/graphics/Frustum.cpp @@ -17,16 +17,7 @@ namespace Graphics { Frustum::Frustum(float width, float height, float fovAng, float znear, float zfar) { - //http://www.opengl.org/resources/faq/technical/transformations.htm - const float fov = tan(DEG2RAD(Clamp(fovAng, FOV_MIN, FOV_MAX) / 2.0f)); - - const float aspect = width / height; - const float top = znear * fov; - const float bottom = -top; - const float left = bottom * aspect; - const float right = top * aspect; - - m_projMatrix = matrix4x4d::FrustumMatrix(left, right, bottom, top, znear, zfar); + m_projMatrix = matrix4x4d::PerspectiveMatrix(DEG2RAD(Clamp(fovAng, FOV_MIN, FOV_MAX)), width / height, znear, zfar); m_modelMatrix = matrix4x4d::Identity(); InitFromMatrix(m_projMatrix); @@ -102,6 +93,7 @@ namespace Graphics { return true; } + // Returns a vector3d in the range { 0..1, 0..1, 0..-1 } bool Frustum::ProjectPoint(const vector3d &in, vector3d &out) const { // see the OpenGL documentation @@ -131,7 +123,7 @@ namespace Graphics { const double w = vclip[3]; out.x = (vclip[0] / w) * 0.5 + 0.5; out.y = (vclip[1] / w) * 0.5 + 0.5; - out.z = (vclip[2] / w) * 0.5 + 0.5; + out.z = -(vclip[2] / w); return true; } diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 0e66e1e5db0..b3902e6ec22 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -62,6 +62,37 @@ namespace Graphics { return g_fovFactor; } + vector3d ProjectToScreen(const Renderer *r, const vector3d &in) + { + // implements gluProject (see the OpenGL documentation or the Mesa implementation of gluProject) + // this implementation is tailored to understand Reverse-Z and our data structures. + const vector3d vcam = matrix4x4d(r->GetTransform()) * in; + const matrix4x4d proj = matrix4x4d(r->GetProjection()); + + // compute the effective W component for perspective divide. + // This code assumes that it's being passed a 'standard' perspective or ortho matrix. + const double w = vcam.z * proj[11] + proj[15]; + + // convert view coordinates -> homogeneous coordinates -> NDC + // perspective divide is applied last (left-to-right associativity) + const vector3d vNDC = proj * vcam / w; + + // convert -1..1 NDC to 0..1 viewport coordinates + const vector3d vVP = { + vNDC.x * 0.5 + 0.5, + vNDC.y * 0.5 + 0.5, + -vNDC.z // undo reverse-Z coordinate flip + }; + + // viewport coord * size + position + const Viewport &vp = r->GetViewport(); + return vector3d{ + vVP.x * vp.w + vp.x, + vVP.y * vp.h + vp.y, + vVP.z + }; + } + Renderer *Init(Settings vs) { assert(!initted); diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index 2f019c218a8..01ad4c27cbf 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -81,6 +81,11 @@ namespace Graphics { void SetFov(float); float GetFovFactor(); //cached 2*tan(fov/2) for LOD + // Project a point in the renderer's current coordinate system to screenspace + // as defined by Renderer::GetViewport. + // TODO: find a better place to hang this off of; this is too useful to be tied to a renderer object + vector3d ProjectToScreen(const Renderer *r, const vector3d &in); + // does SDL video init, constructs appropriate Renderer Renderer *Init(Settings); void Uninit(); diff --git a/src/graphics/RenderTarget.h b/src/graphics/RenderTarget.h index c7651099937..3bab595b31f 100644 --- a/src/graphics/RenderTarget.h +++ b/src/graphics/RenderTarget.h @@ -18,12 +18,13 @@ namespace Graphics { // Specifying a depth format with no allowDepthTexture will create a depth buffer // fixed to this rendertarget struct RenderTargetDesc { - RenderTargetDesc(Uint16 _width, Uint16 _height, TextureFormat _colorFormat, TextureFormat _depthFormat, bool _allowDepthTexture) : + RenderTargetDesc(Uint16 _width, Uint16 _height, TextureFormat _colorFormat, TextureFormat _depthFormat, bool _allowDepthTexture = false, Uint16 _samples = 0) : width(_width), height(_height), colorFormat(_colorFormat), depthFormat(_depthFormat), - allowDepthTexture(_allowDepthTexture) + allowDepthTexture(_allowDepthTexture), + numSamples(_samples) {} const Uint16 width; @@ -31,6 +32,7 @@ namespace Graphics { const TextureFormat colorFormat; const TextureFormat depthFormat; const bool allowDepthTexture; + const Uint16 numSamples; }; class RenderTarget { diff --git a/src/graphics/Types.h b/src/graphics/Types.h index 4513d4e02ae..db9a93fe26b 100644 --- a/src/graphics/Types.h +++ b/src/graphics/Types.h @@ -42,17 +42,19 @@ namespace Graphics { BUFFER_MAP_READ }; + // clang-format off enum PrimitiveType { - POINTS = 0, //GL_POINTS, - LINE_SINGLE, //GL_LINES, //draw one line per two vertices - LINE_LOOP, //GL_LINE_LOOP, //connect vertices, connect start & end - LINE_STRIP, //GL_LINE_STRIP, //connect vertices - TRIANGLES, //GL_TRIANGLES, - TRIANGLE_STRIP, //GL_TRIANGLE_STRIP, - TRIANGLE_FAN, //GL_TRIANGLE_FAN + POINTS = 0, //GL_POINTS, + LINE_SINGLE, //GL_LINES, //draw one line per two vertices + LINE_LOOP, //GL_LINE_LOOP, //connect vertices, connect start & end + LINE_STRIP, //GL_LINE_STRIP, //connect vertices + TRIANGLES, //GL_TRIANGLES, + TRIANGLE_STRIP, //GL_TRIANGLE_STRIP, + TRIANGLE_FAN, //GL_TRIANGLE_FAN }; + // clang-format on - enum BlendMode { + enum BlendMode : uint32_t { BLEND_SOLID, BLEND_ADDITIVE, BLEND_ALPHA, @@ -62,7 +64,7 @@ namespace Graphics { BLEND_DEST_ALPHA // XXX maybe crappy name }; - enum FaceCullMode { + enum FaceCullMode : uint32_t { CULL_BACK, CULL_FRONT, CULL_NONE diff --git a/src/graphics/VertexBuffer.cpp b/src/graphics/VertexBuffer.cpp index 50e2a106165..86e2bff1544 100644 --- a/src/graphics/VertexBuffer.cpp +++ b/src/graphics/VertexBuffer.cpp @@ -1,4 +1,4 @@ -// Copyright � 2008-2020 Pioneer Developers. See AUTHORS.txt for details +// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "graphics/VertexBuffer.h" diff --git a/src/graphics/opengl/GLDebug.h b/src/graphics/opengl/GLDebug.h index 81a2432be8f..b7a827288be 100644 --- a/src/graphics/opengl/GLDebug.h +++ b/src/graphics/opengl/GLDebug.h @@ -86,6 +86,9 @@ namespace Graphics { GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) { + // filter out Type=Other informational messages + if (type > GL_DEBUG_TYPE_PERFORMANCE) + return; Output("Type: %s, Source: %s, ID: %u, Severity: %s, Message: %s\n", type_to_string(type), source_to_string(source), id, severity_to_string(severity), message); diff --git a/src/graphics/opengl/Program.cpp b/src/graphics/opengl/Program.cpp index fa7d99bc4f3..083368461c4 100644 --- a/src/graphics/opengl/Program.cpp +++ b/src/graphics/opengl/Program.cpp @@ -112,7 +112,7 @@ namespace Graphics { strCode.replace(found, (endFilename + 1) - found, incCode->GetData(), incCode->GetSize()); found = strCode.find("#include"); } else { - Error("Could not load %s", incPathBuffer.c_str()); + Error("Could not load shader #include %s for shader %s\n", incPathBuffer.c_str(), filename.c_str()); } } // Store the modified text with the included files (if any) diff --git a/src/graphics/opengl/RenderTargetGL.cpp b/src/graphics/opengl/RenderTargetGL.cpp index adb3b3d09c5..e50b00dcd22 100644 --- a/src/graphics/opengl/RenderTargetGL.cpp +++ b/src/graphics/opengl/RenderTargetGL.cpp @@ -7,34 +7,10 @@ namespace Graphics { namespace OGL { - RenderBuffer::RenderBuffer() - { - glGenRenderbuffers(1, &buffer); - } - - RenderBuffer::~RenderBuffer() - { - glDeleteRenderbuffers(1, &buffer); - } - - void RenderBuffer::Bind() - { - glBindRenderbuffer(GL_RENDERBUFFER, buffer); - } - - void RenderBuffer::Unbind() - { - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - - void RenderBuffer::Attach(GLenum attachment) - { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, buffer); - } - RenderTarget::RenderTarget(const RenderTargetDesc &d) : Graphics::RenderTarget(d), - m_active(false) + m_active(false), + m_depthRenderBuffer(0) { glGenFramebuffers(1, &m_fbo); } @@ -42,6 +18,7 @@ namespace Graphics { RenderTarget::~RenderTarget() { glDeleteFramebuffers(1, &m_fbo); + glDeleteRenderbuffers(1, &m_depthRenderBuffer); } Texture *RenderTarget::GetColorTexture() const @@ -74,7 +51,9 @@ namespace Graphics { //texture format should match the intended fbo format (aka. the one attached first) GLuint texId = 0; if (t) texId = static_cast(t)->GetTextureID(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GetDesc().numSamples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, texId, 0); + m_colorTexture.Reset(t); if (!bound) Unbind(); } @@ -87,7 +66,8 @@ namespace Graphics { if (!GetDesc().allowDepthTexture) return; GLuint texId = 0; if (t) texId = static_cast(t)->GetTextureID(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GetDesc().numSamples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, texId, 0); m_depthTexture.Reset(t); if (!bound) Unbind(); } @@ -113,11 +93,14 @@ namespace Graphics { { assert(!GetDesc().allowDepthTexture); assert(m_active); - m_depthRenderBuffer.Reset(new RenderBuffer()); - m_depthRenderBuffer->Bind(); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, GetDesc().width, GetDesc().height); - m_depthRenderBuffer->Attach(GL_DEPTH_ATTACHMENT); - m_depthRenderBuffer->Unbind(); + assert(m_depthRenderBuffer == 0); + + glGenRenderbuffers(1, &m_depthRenderBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderBuffer); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, GetDesc().numSamples, GL_DEPTH_COMPONENT32F, GetDesc().width, GetDesc().height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer); } } // namespace OGL diff --git a/src/graphics/opengl/RenderTargetGL.h b/src/graphics/opengl/RenderTargetGL.h index 22a1bf89c91..17750c027fb 100644 --- a/src/graphics/opengl/RenderTargetGL.h +++ b/src/graphics/opengl/RenderTargetGL.h @@ -17,21 +17,6 @@ namespace Graphics { namespace OGL { - class RenderTarget; - - class RenderBuffer : public RefCounted { - public: - ~RenderBuffer(); - void Bind(); - void Unbind(); - void Attach(GLenum attachment); - - protected: - friend class RenderTarget; - RenderBuffer(); - GLuint buffer; - }; - class RenderTarget : public Graphics::RenderTarget { public: ~RenderTarget(); @@ -51,8 +36,8 @@ namespace Graphics { bool m_active; GLuint m_fbo; + GLuint m_depthRenderBuffer; - RefCountedPtr m_depthRenderBuffer; RefCountedPtr m_colorTexture; RefCountedPtr m_depthTexture; }; diff --git a/src/graphics/opengl/RendererGL.cpp b/src/graphics/opengl/RendererGL.cpp index 5daf94198f5..ad8aa9b14df 100644 --- a/src/graphics/opengl/RendererGL.cpp +++ b/src/graphics/opengl/RendererGL.cpp @@ -39,44 +39,54 @@ namespace Graphics { - static bool CreateWindowAndContext(const char *name, const Graphics::Settings &vs, int samples, int depth_bits, SDL_Window **window, SDL_GLContext *context) + static bool CreateWindowAndContext(const char *name, const Graphics::Settings &vs, SDL_Window *&window, SDL_GLContext &context) { Uint32 winFlags = 0; - assert(vs.rendererType == Graphics::RendererType::RENDERER_OPENGL_3x); - winFlags |= SDL_WINDOW_OPENGL; + // We'd like a context that implements OpenGL 3.2 to allow creation of multisampled textures SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - // cannot initialise 3.x content on OSX with anything but CORE profile + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + // Request core profile as we're uninterested in old fixed-function API + // also cannot initialise 3.x context on OSX with anything but CORE profile SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - // OSX also forces us to use this for 3.2 onwards + // OSX doesn't care about forward-compatible flag, but it's good practice. if (vs.gl3ForwardCompatible) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depth_bits); + // Don't request a depth/stencil/multisample buffer. + // We'll render to an offscreen buffer supporting these features and blit to the OS window from there. + // This is for multiple reasons: + // - we need a 32-bit float depth buffer + // - we'd like to be able to render at e.g. 1600x900 and display on a 3200x1800 screen for laptops + // - changing graphics settings like antialiasing or resolution doesn't require restarting the game (or recreating the window) + // - we need to MSAA resolve before running post-processing + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); + // TODO: verify and enable sRGB-correct rendering through the entire pipeline + // SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1); - // need full 32-bit color - // (need an alpha channel because of the way progress bars are drawn) + // need at least 24-bit color + // alpha channel will be present on main render target instead of window surface SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); winFlags |= (vs.hidden ? SDL_WINDOW_HIDDEN : SDL_WINDOW_SHOWN); - if (!vs.hidden && vs.fullscreen) + if (!vs.hidden && vs.fullscreen) // TODO: support for borderless fullscreen and changing window size winFlags |= SDL_WINDOW_FULLSCREEN; - (*window) = SDL_CreateWindow(name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, vs.width, vs.height, winFlags); - if (!(*window)) + window = SDL_CreateWindow(name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, vs.width, vs.height, winFlags); + if (!window) return false; - (*context) = SDL_GL_CreateContext((*window)); - if (!(*context)) { - SDL_DestroyWindow((*window)); - (*window) = nullptr; + context = SDL_GL_CreateContext(window); + if (!context) { + SDL_DestroyWindow(window); + window = nullptr; return false; } @@ -85,39 +95,15 @@ namespace Graphics { static Renderer *CreateRenderer(const Settings &vs) { - bool ok; + assert(vs.rendererType == Graphics::RendererType::RENDERER_OPENGL_3x); const std::string name("Pioneer"); SDL_Window *window = nullptr; SDL_GLContext glContext = nullptr; - // attempt sequence is: - // 1- requested mode - ok = CreateWindowAndContext(name.c_str(), vs, vs.requestedSamples, 24, &window, &glContext); - - // 2- requested mode with no anti-aliasing (skipped if no AA was requested anyway) - // (skipped if no AA was requested anyway) - if (!ok && vs.requestedSamples) { - Output("Failed to set video mode. (%s). Re-trying without multisampling.\n", SDL_GetError()); - ok = CreateWindowAndContext(name.c_str(), vs, 0, 24, &window, &glContext); - } - - // 3- requested mode with 16 bit depth buffer + bool ok = CreateWindowAndContext(name.c_str(), vs, window, glContext); if (!ok) { - Output("Failed to set video mode. (%s). Re-trying with 16-bit depth buffer\n", SDL_GetError()); - ok = CreateWindowAndContext(name.c_str(), vs, vs.requestedSamples, 16, &window, &glContext); - } - - // 4- requested mode with 16-bit depth buffer and no anti-aliasing - // (skipped if no AA was requested anyway) - if (!ok && vs.requestedSamples) { - Output("Failed to set video mode. (%s). Re-trying with 16-bit depth buffer and no multisampling\n", SDL_GetError()); - ok = CreateWindowAndContext(name.c_str(), vs, 0, 16, &window, &glContext); - } - - // 5- abort! - if (!ok) { - Warning("Failed to set video mode: %s", SDL_GetError()); + Error("Failed to set video mode: %s", SDL_GetError()); return nullptr; } @@ -191,6 +177,12 @@ namespace Graphics { } } + if (!glewIsSupported("GL_ARB_clip_control")) { + Error( + "OpenGL extension GL_ARB_clip_control is not supported by your graphics card or graphics driver version.\n" + "Please check to see if your GPU driver vendor has an updated driver - or that drivers are installed correctly."); + } + const char *ver = reinterpret_cast(glGetString(GL_VERSION)); if (vs.gl3ForwardCompatible && strstr(ver, "9.17.10.4229")) { Warning("Driver needs GL3ForwardCompatible=0 in config.ini to display billboards (stars, navlights etc.)"); @@ -209,8 +201,10 @@ namespace Graphics { glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); + // use floating-point reverse-Z depth buffer to remove the need for depth buffer hacks + glDepthFunc(GL_GREATER); glDepthRange(0.0, 1.0); + glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); @@ -220,6 +214,7 @@ namespace Graphics { glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_NICEST); + glClearDepth(0.0); // clear to 0.0 for use with reverse-Z SetClearColor(Color4f(0.f, 0.f, 0.f, 0.f)); SetViewport(Viewport(0, 0, m_width, m_height)); @@ -234,6 +229,20 @@ namespace Graphics { assert(TRIANGLES == GL_TRIANGLES); assert(TRIANGLE_STRIP == GL_TRIANGLE_STRIP); assert(TRIANGLE_FAN == GL_TRIANGLE_FAN); + + RenderTargetDesc windowTargetDesc( + m_width, m_height, + // TODO: sRGB format for render target? + TextureFormat::TEXTURE_RGBA_8888, + TextureFormat::TEXTURE_DEPTH, + false, vs.requestedSamples); + + m_windowRenderTarget = static_cast(CreateRenderTarget(windowTargetDesc)); + SetRenderTarget(nullptr); + + if (!m_windowRenderTarget->CheckStatus()) + Error("Pioneer window render target is invalid.\n" + "Does your graphics driver support multisample anti-aliasing?"); } RendererOGL::~RendererOGL() @@ -243,6 +252,10 @@ namespace Graphics { for (auto state : m_renderStates) delete state.second; + if (m_windowRenderTarget->m_active) + m_windowRenderTarget->Unbind(); + delete m_windowRenderTarget; + SDL_GL_DeleteContext(m_glContext); } @@ -508,6 +521,15 @@ namespace Graphics { PROFILE_SCOPED() CheckRenderErrors(__FUNCTION__, __LINE__); + // Make sure we set the active FBO to our "default" window target + SetRenderTarget(nullptr); + + // TODO(sturnclaw): handle upscaling to higher-resolution screens + // we'll need an intermediate target to resolve to, resolve and rescale are mutually exclusive + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_windowRenderTarget->m_fbo); + SDL_GL_SwapWindow(m_window); m_stats.NextFrame(); return true; @@ -526,10 +548,19 @@ namespace Graphics { bool RendererOGL::SetRenderTarget(RenderTarget *rt) { PROFILE_SCOPED() - if (rt) + if (rt) { + if (m_activeRenderTarget) + m_activeRenderTarget->Unbind(); + else + m_windowRenderTarget->Unbind(); + static_cast(rt)->Bind(); - else if (m_activeRenderTarget) - m_activeRenderTarget->Unbind(); + } else { + if (m_activeRenderTarget) + m_activeRenderTarget->Unbind(); + + m_windowRenderTarget->Bind(); + } m_activeRenderTarget = static_cast(rt); CheckRenderErrors(__FUNCTION__, __LINE__); @@ -539,7 +570,8 @@ namespace Graphics { bool RendererOGL::SetDepthRange(double znear, double zfar) { - glDepthRange(znear, zfar); + // XXX since we're using reverse-Z, flip the inputs to this function to avoid breaking old code. + glDepthRange(1.0 - zfar, 1.0 - znear); return true; } @@ -603,14 +635,7 @@ namespace Graphics { m_invLogZfarPlus1 = 1.0f / (log1p(far_) / log(2.0f)); Graphics::SetFov(fov); - - float ymax = near_ * tan(fov * M_PI / 360.0); - float ymin = -ymax; - float xmin = ymin * aspect; - float xmax = ymax * aspect; - - const matrix4x4f frustrumMat = matrix4x4f::FrustumMatrix(xmin, xmax, ymin, ymax, near_, far_); - SetProjection(frustrumMat); + SetProjection(matrix4x4f::PerspectiveMatrix(DEG2RAD(fov), aspect, near_, far_)); return true; } @@ -1112,7 +1137,7 @@ namespace Graphics { false, false, 0, Graphics::TEXTURE_2D); - OGL::TextureGL *colorTex = new OGL::TextureGL(cdesc, false, false); + OGL::TextureGL *colorTex = new OGL::TextureGL(cdesc, false, false, desc.numSamples); rt->SetColorTexture(colorTex); } if (desc.depthFormat != TEXTURE_NONE) { diff --git a/src/graphics/opengl/RendererGL.h b/src/graphics/opengl/RendererGL.h index 01950b53f59..806e8c97d21 100644 --- a/src/graphics/opengl/RendererGL.h +++ b/src/graphics/opengl/RendererGL.h @@ -149,6 +149,7 @@ namespace Graphics { std::unordered_map m_renderStates; float m_invLogZfarPlus1; OGL::RenderTarget *m_activeRenderTarget; + OGL::RenderTarget *m_windowRenderTarget; RenderState *m_activeRenderState; matrix4x4f m_modelViewMat; diff --git a/src/graphics/opengl/TextureGL.cpp b/src/graphics/opengl/TextureGL.cpp index be62ed84b5c..89aaf4a4d07 100644 --- a/src/graphics/opengl/TextureGL.cpp +++ b/src/graphics/opengl/TextureGL.cpp @@ -82,13 +82,14 @@ namespace Graphics { return (format == TEXTURE_DXT1 || format == TEXTURE_DXT5); } - TextureGL::TextureGL(const TextureDescriptor &descriptor, const bool useCompressed, const bool useAnisoFiltering) : + TextureGL::TextureGL(const TextureDescriptor &descriptor, const bool useCompressed, const bool useAnisoFiltering, const Uint16 numSamples) : Texture(descriptor), m_allocSize(0), m_useAnisoFiltering(useAnisoFiltering && descriptor.useAnisotropicFiltering) { PROFILE_SCOPED() - m_target = GLTextureType(descriptor.type); + // this is kind of a hack, but it limits the amount of things that need to care about multisample textures. + m_target = numSamples ? GL_TEXTURE_2D_MULTISAMPLE : GLTextureType(descriptor.type); glGenTextures(1, &m_texture); glBindTexture(m_target, m_texture); @@ -99,6 +100,14 @@ namespace Graphics { const bool compressTexture = useCompressed && descriptor.allowCompression; switch (m_target) { + // XXX(sturnclaw): multisample assumes an uncompressed, un-mipmapped 2d texture descriptor. + case GL_TEXTURE_2D_MULTISAMPLE: { + glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, 0); + glTexImage2DMultisample( + m_target, numSamples, GLInternalFormat(descriptor.format), + descriptor.dataSize.x, descriptor.dataSize.y, true); // must use fixedsamplelocations when mixed with renderbuffer + CHECKERRORS(); + } break; case GL_TEXTURE_2D: if (!IsCompressed(descriptor.format)) { if (!descriptor.generateMipmaps) @@ -269,10 +278,13 @@ namespace Graphics { break; } - glTexParameteri(m_target, GL_TEXTURE_WRAP_S, wrapS); - glTexParameteri(m_target, GL_TEXTURE_WRAP_T, wrapS); - glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, magFilter); - glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, minFilter); + // multisample textures don't support wrap or filter operations. + if (!numSamples) { + glTexParameteri(m_target, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(m_target, GL_TEXTURE_WRAP_T, wrapS); + glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, magFilter); + glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, minFilter); + } // Anisotropic texture filtering if (m_useAnisoFiltering) { diff --git a/src/graphics/opengl/TextureGL.h b/src/graphics/opengl/TextureGL.h index 8b966e0cac5..8ee3c2c71d3 100644 --- a/src/graphics/opengl/TextureGL.h +++ b/src/graphics/opengl/TextureGL.h @@ -15,7 +15,7 @@ namespace Graphics { virtual void Update(const TextureCubeData &data, const vector3f &dataSize, TextureFormat format, const unsigned int numMips) override final; virtual void Update(const vecDataPtr &data, const vector3f &dataSize, const TextureFormat format, const unsigned int numMips) override final; - TextureGL(const TextureDescriptor &descriptor, const bool useCompressed, const bool useAnisoFiltering); + TextureGL(const TextureDescriptor &descriptor, const bool useCompressed, const bool useAnisoFiltering, const Uint16 numSamples = 0); virtual ~TextureGL(); virtual void Bind() override final; diff --git a/src/gui/GuiScreen.cpp b/src/gui/GuiScreen.cpp index 3488be0045a..adcbd9dff86 100644 --- a/src/gui/GuiScreen.cpp +++ b/src/gui/GuiScreen.cpp @@ -96,37 +96,24 @@ namespace Gui { { PROFILE_SCOPED() // implements gluProject (see the OpenGL documentation or the Mesa implementation of gluProject) - const float *const M = modelMatrix.Data(); - const float *const P = projMatrix.Data(); - - const double vcam[4] = { // camera space - in.x * M[0] + in.y * M[4] + in.z * M[8] + M[12], - in.x * M[1] + in.y * M[5] + in.z * M[9] + M[13], - in.x * M[2] + in.y * M[6] + in.z * M[10] + M[14], - in.x * M[3] + in.y * M[7] + in.z * M[11] + M[15] - }; - const double vclip[4] = { // clip space - vcam[0] * P[0] + vcam[1] * P[4] + vcam[2] * P[8] + vcam[3] * P[12], - vcam[0] * P[1] + vcam[1] * P[5] + vcam[2] * P[9] + vcam[3] * P[13], - vcam[0] * P[2] + vcam[1] * P[6] + vcam[2] * P[10] + vcam[3] * P[14], - vcam[0] * P[3] + vcam[1] * P[7] + vcam[2] * P[11] + vcam[3] * P[15] - }; - - if (is_zero_exact(vclip[3])) { - return false; - } - - const double w = vclip[3]; - - const double v[3] = { - (vclip[0] / w) * 0.5 + 0.5, - (vclip[1] / w) * 0.5 + 0.5, - (vclip[2] / w) * 0.5 + 0.5 + const vector3d vcam = matrix4x4d(modelMatrix) * in; + const double w = vcam.z * projMatrix[11] + projMatrix[15]; + + // convert view coordinates -> homogeneous coordinates -> NDC + // perspective divide is applied last (left-to-right associativity) + const vector3d vNDC = matrix4x4d(projMatrix) * vcam / w; + + // convert -1..1 NDC to 0..1 viewport coordinates + const vector3d vVP = { + vNDC.x * 0.5 + 0.5, + vNDC.y * 0.5 + 0.5, + -vNDC.z // undo reverse-Z coordinate flip }; - out.x = v[0] * viewport.w + viewport.x; - out.y = v[1] * viewport.h + viewport.y; - out.z = v[2]; + // viewport coord * size + position + out.x = vVP.x * viewport.w + viewport.x; + out.y = vVP.y * viewport.h + viewport.y; + out.z = vVP.z; // map to pixels out.x = out.x * width * invRealWidth; @@ -144,7 +131,7 @@ namespace Gui { projMatrix = r->GetProjection(); viewport = r->GetViewport(); - r->SetOrthographicProjection(0, width, height, 0, -1, 1); + r->SetOrthographicProjection(0, width, height, 0, 0, 1); r->SetTransform(matrix4x4f::Identity()); } diff --git a/src/lua/Lua.cpp b/src/lua/Lua.cpp index 48b5eae87f2..ea446c96654 100644 --- a/src/lua/Lua.cpp +++ b/src/lua/Lua.cpp @@ -36,7 +36,7 @@ #include "galaxy/StarSystem.h" #include "gameui/Lua.h" -#include "pigui/PiGuiLua.h" +#include "pigui/LuaPiGui.h" #include "scenegraph/Lua.h" #include "ui/Lua.h" @@ -44,9 +44,12 @@ namespace Lua { LuaManager *manager = 0; + void InitMath(); + void Init() { manager = new LuaManager(); + InitMath(); } void Uninit() @@ -55,6 +58,14 @@ namespace Lua { manager = 0; } + // initialize standalone math types as the "extended standard library" for all lua instances + void InitMath() + { + LuaVector::Register(manager->GetLuaState()); + LuaVector2::Register(manager->GetLuaState()); + LuaColor::Register(manager->GetLuaState()); + } + void InitModules() { PROFILE_SCOPED() @@ -104,9 +115,6 @@ namespace Lua { LuaMusic::Register(); LuaDev::Register(); LuaConsole::Register(); - LuaVector::Register(Lua::manager->GetLuaState()); - LuaVector2::Register(Lua::manager->GetLuaState()); - LuaColor::Register(Lua::manager->GetLuaState()); // XXX sigh UI::Lua::Init(); diff --git a/src/lua/LuaBody.cpp b/src/lua/LuaBody.cpp index 398b3be9975..9ed7ebbd354 100644 --- a/src/lua/LuaBody.cpp +++ b/src/lua/LuaBody.cpp @@ -25,11 +25,11 @@ #include "SpaceStation.h" #include "Star.h" -namespace PiGUI { - // Defined in LuaPiGui.h +namespace PiGui { + // Declared in LuaPiGuiInternal.h extern bool first_body_is_more_important_than(Body *, Body *); extern int pushOnScreenPositionDirection(lua_State *l, vector3d position); -} // namespace PiGUI +} // namespace PiGui /* * Class: Body @@ -247,7 +247,7 @@ static int l_body_is_more_important_than(lua_State *l) LuaPush(l, false); return 1; } - LuaPush(l, PiGUI::first_body_is_more_important_than(body, other)); + LuaPush(l, PiGui::first_body_is_more_important_than(body, other)); return 1; } /* @@ -654,7 +654,7 @@ static int l_body_get_projected_screen_position(lua_State *l) Body *b = LuaObject::CheckFromLua(1); WorldView *wv = Pi::game->GetWorldView(); vector3d p = wv->WorldSpaceToScreenSpace(b); - return PiGUI::pushOnScreenPositionDirection(l, p); + return PiGui::pushOnScreenPositionDirection(l, p); } static int l_body_get_atmospheric_state(lua_State *l) @@ -686,7 +686,7 @@ static int l_body_get_target_indicator_screen_position(lua_State *l) Body *b = LuaObject::CheckFromLua(1); WorldView *wv = Pi::game->GetWorldView(); vector3d p = wv->GetTargetIndicatorScreenPosition(b); - return PiGUI::pushOnScreenPositionDirection(l, p); + return PiGui::pushOnScreenPositionDirection(l, p); } static bool push_body_to_lua(Body *body) diff --git a/src/lua/LuaColor.cpp b/src/lua/LuaColor.cpp index 52d435272d8..e3a3d20668b 100644 --- a/src/lua/LuaColor.cpp +++ b/src/lua/LuaColor.cpp @@ -2,6 +2,7 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "LuaColor.h" +#include "Color.h" #include "LuaUtils.h" #include "libs.h" @@ -14,14 +15,57 @@ inline Color4ub ColorClamp(float r, float g, float b, float a) return Color4ub(r, g, b, a); } +static uint8_t char_to_nibble(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return (c - 'A') + 10; + else if (c >= 'a' && c <= 'f') + return (c - 'a') + 10; + + return 0xF; +} + +static Color4ub parse_color_hex(const std::string &str) +{ + if (str.size() == 3) { + uint8_t r = char_to_nibble(str[0]), g = char_to_nibble(str[1]), b = char_to_nibble(str[2]); + return Color4ub(r | (r << 4), g | (g << 4), b | (b << 4), 255); + } else if (str.size() == 6) { + uint8_t r = char_to_nibble(str[0]) | (char_to_nibble(str[1]) << 4); + uint8_t g = char_to_nibble(str[2]) | (char_to_nibble(str[3]) << 4); + uint8_t b = char_to_nibble(str[4]) | (char_to_nibble(str[5]) << 4); + return Color4ub(r, g, b, 255); + } else if (str.size() == 8) { + uint8_t r = char_to_nibble(str[0]) | (char_to_nibble(str[1]) << 4); + uint8_t g = char_to_nibble(str[2]) | (char_to_nibble(str[3]) << 4); + uint8_t b = char_to_nibble(str[4]) | (char_to_nibble(str[5]) << 4); + uint8_t a = char_to_nibble(str[6]) | (char_to_nibble(str[7]) << 4); + return Color4ub(r, g, b, a); + } + + return {}; +} + static int l_color_new(lua_State *L) { LUA_DEBUG_START(L); - double r = luaL_checknumber(L, 1); - double g = luaL_checknumber(L, 2); - double b = luaL_checknumber(L, 3); - double a = luaL_optnumber(L, 4, 255.0); - LuaColor::PushToLua(L, ColorClamp(r, g, b, a)); + if (lua_type(L, 1) == LUA_TSTRING) { + std::string str = lua_tostring(L, 1); + if (str.find_first_not_of("0123456789ABCDEFabcdef") != std::string::npos) { + return luaL_error(L, "Color string '%s' cannot contain non-hexadecimal characters!"); + } + + LuaColor::PushToLua(L, parse_color_hex(str)); + } else { + double r = luaL_checknumber(L, 1); + double g = luaL_checknumber(L, 2); + double b = luaL_checknumber(L, 3); + double a = luaL_optnumber(L, 4, 255.0); + LuaColor::PushToLua(L, ColorClamp(r, g, b, a)); + } + LUA_DEBUG_END(L, 1); return 1; } @@ -29,11 +73,21 @@ static int l_color_new(lua_State *L) static int l_color_call(lua_State *L) { LUA_DEBUG_START(L); - double r = luaL_checknumber(L, 2); - double g = luaL_checknumber(L, 3); - double b = luaL_checknumber(L, 4); - double a = luaL_optnumber(L, 5, 255.0); - LuaColor::PushToLua(L, ColorClamp(r, g, b, a)); + if (lua_type(L, 2) == LUA_TSTRING) { + std::string str = lua_tostring(L, 2); + if (str.find_first_not_of("0123456789ABCDEFabcdef") != std::string::npos) { + return luaL_error(L, "Color string '%s' cannot contain non-hexadecimal characters!"); + } + + LuaColor::PushToLua(L, parse_color_hex(str)); + } else { + double r = luaL_checknumber(L, 2); + double g = luaL_checknumber(L, 3); + double b = luaL_checknumber(L, 4); + double a = luaL_optnumber(L, 5, 255.0); + LuaColor::PushToLua(L, ColorClamp(r, g, b, a)); + } + LUA_DEBUG_END(L, 1); return 1; } @@ -164,24 +218,35 @@ static int l_color_set(lua_State *L) { LUA_DEBUG_START(L); Color4ub *col = LuaColor::CheckFromLua(L, 1); - double r = luaL_checknumber(L, 2); - double g = luaL_checknumber(L, 3); - double b = luaL_checknumber(L, 4); - double a = luaL_optnumber(L, 5, 255.0); - *col = ColorClamp(r, g, b, a); + + if (lua_type(L, 2) == LUA_TSTRING) { + std::string str = lua_tostring(L, 2); + if (str.find_first_not_of("0123456789ABCDEFabcdef") != std::string::npos) { + return luaL_error(L, "Color string '%s' cannot contain non-hexadecimal characters!"); + } + + *col = parse_color_hex(str); + } else { + double r = luaL_checknumber(L, 2); + double g = luaL_checknumber(L, 3); + double b = luaL_checknumber(L, 4); + double a = luaL_optnumber(L, 5, 255.0); + *col = ColorClamp(r, g, b, a); + } + lua_pushvalue(L, 1); // return the same color value. LUA_DEBUG_END(L, 1); return 1; } -static luaL_Reg l_vector_lib[] = { +static luaL_Reg l_color_lib[] = { { "new", &l_color_new }, { "shade", &l_color_shade }, { "tint", &l_color_tint }, { 0, 0 } }; -static luaL_Reg l_vector_meta[] = { +static luaL_Reg l_color_meta[] = { { "__tostring", &l_color_tostring }, { "__add", &l_color_add }, { "__mul", &l_color_mul }, @@ -200,7 +265,7 @@ void LuaColor::Register(lua_State *L) { LUA_DEBUG_START(L); - luaL_newlib(L, l_vector_lib); + luaL_newlib(L, l_color_lib); lua_newtable(L); lua_pushcfunction(L, &l_color_call); @@ -210,7 +275,7 @@ void LuaColor::Register(lua_State *L) lua_setglobal(L, LuaColor::LibName); luaL_newmetatable(L, LuaColor::TypeName); - luaL_setfuncs(L, l_vector_meta, 0); + luaL_setfuncs(L, l_color_meta, 0); // hide the metatable to thwart crazy exploits lua_pushboolean(L, 0); lua_setfield(L, -2, "__metatable"); diff --git a/src/lua/LuaDev.cpp b/src/lua/LuaDev.cpp index 9524a792f5e..4d27ad55595 100644 --- a/src/lua/LuaDev.cpp +++ b/src/lua/LuaDev.cpp @@ -32,6 +32,7 @@ * CountSystems * CountSystemNames * CountPopulation + * PlanetsGravity * * Availability: * @@ -121,6 +122,73 @@ static int l_dev_galaxy_stats(lua_State *l) } } CountPopulation; + class : public Processor { + RefCountedPtr galaxy = Pi::game->GetGalaxy(); + struct planet { + std::string name; + std::string systemname; + double gravity; + SystemPath path; + planet(const std::string &n, const std::string &sn, double g, const SystemPath &p) : + name(n), systemname(sn), gravity(g), path(p) {} + }; + std::vector Planets; + + public: + void ProcessSystem(const Sector::System &system) override + { + RefCountedPtr starsystem = galaxy->GetStarSystem(system.GetPath()); + for (const auto b : starsystem->GetBodies()) { + auto children = b->GetChildren(); + if (std::find_if(children.cbegin(), children.cend(), [](const SystemBody *kid) { + return kid->GetType() == SystemBody::TYPE_STARPORT_SURFACE; + }) != children.cend()) + // the radius and the mass of the planet is returned in the radii and the mass of the earth + // therefore the result is obtained in g + Planets.emplace_back(b->GetName(), system.GetName(), b->GetMassAsFixed().ToDouble() / b->GetRadiusAsFixed().ToDouble() / b->GetRadiusAsFixed().ToDouble(), b->GetPath()); + } + } + std::string Report() override + { + std::sort(Planets.begin(), Planets.end(), [](const planet &p1, const planet &p2) { + return p1.gravity > p2.gravity; + }); + const double step = 0.1; + const double from = std::floor(Planets.back().gravity / step) * step; + const double to = std::floor(Planets.front().gravity / step) * step + step * 0.5; // this is the middle of the last range + uint32_t top_amount = 20; // number of planets for the best / worst chart + if (top_amount > Planets.size() / 2) top_amount = Planets.size() / 2; + std::stringstream result; + result.precision(3); + result << "Total number of planets with star ports: " << Planets.size(); + result << "\nNumber of planets by gravity on the surface:"; + for (double i = from; i < to; i += step) { + uint32_t amount = 0; + for (const auto &p : Planets) + if (p.gravity > i && p.gravity <= i + step) amount++; + result << "\n" + << std::fixed << i << "g .. " << std::fixed << i + step << "g: " << amount / static_cast(Planets.size()) * 100 << "% (" << amount << " planets)"; + } + result << "\n------------------------------"; + result << "\nTop " << top_amount << " planets with max gravity:"; + for (uint32_t i = 0; i < top_amount; ++i) { + result << "\n" + << i + 1 << ". " << Planets[i].name << " : " << Planets[i].gravity << "g "; + result << "(" << Planets[i].systemname; + result << " " << Planets[i].path.sectorX << ", " << Planets[i].path.sectorY << ", " << Planets[i].path.sectorZ << ")"; + } + result << "\n------------------------------"; + result << "\nBottom " << top_amount << " planets with min gravity:"; + for (uint32_t i = Planets.size() - top_amount; i < Planets.size(); ++i) { + result << "\n" + << i + 1 << ". " << Planets[i].name << " : " << Planets[i].gravity << "g "; + result << "(" << Planets[i].systemname; + result << " " << Planets[i].path.sectorX << ", " << Planets[i].path.sectorY << ", " << Planets[i].path.sectorZ << ")"; + } + return result.str() + "\n"; + } + } PlanetsGravity; + // lua args int centerX = LuaPull(l, 1); int centerY = LuaPull(l, 2); @@ -136,7 +204,8 @@ static int l_dev_galaxy_stats(lua_State *l) // map strings into processors std::map processors = { { "CountSystemNames", &CountSystemNames }, { "CountPopulation", &CountPopulation }, - { "CountSystems", &CountSystems } }; + { "CountSystems", &CountSystems }, + { "PlanetsGravity", &PlanetsGravity } }; std::vector P; for (auto &option : options) if (processors.find(option) != processors.end()) diff --git a/src/lua/LuaEngine.cpp b/src/lua/LuaEngine.cpp index 470a905777f..9a3a92a5bf4 100644 --- a/src/lua/LuaEngine.cpp +++ b/src/lua/LuaEngine.cpp @@ -14,7 +14,7 @@ #include "LuaColor.h" #include "LuaConstants.h" #include "LuaObject.h" -#include "LuaPiGui.h" +#include "LuaPiGuiInternal.h" #include "LuaUtils.h" #include "LuaVector.h" #include "LuaVector2.h" @@ -821,7 +821,7 @@ static int l_engine_world_space_to_screen_space(lua_State *l) { vector3d pos = LuaPull(l, 1); - PiGUI::TScreenSpace res = PiGUI::lua_world_space_to_screen_space(pos); // defined in LuaPiGui.cpp + PiGui::TScreenSpace res = PiGui::lua_world_space_to_screen_space(pos); // defined in LuaPiGui.cpp LuaPush(l, res._onScreen); LuaPush(l, res._screenPosition); @@ -833,7 +833,7 @@ static int l_engine_rel_space_to_screen_space(lua_State *l) { vector3d pos = LuaPull(l, 1); - PiGUI::TScreenSpace res = PiGUI::lua_rel_space_to_screen_space(pos); // defined in LuaPiGui.cpp + PiGui::TScreenSpace res = PiGui::lua_rel_space_to_screen_space(pos); // defined in LuaPiGui.cpp LuaPush(l, res._onScreen); LuaPush(l, res._screenPosition); diff --git a/src/lua/LuaGame.cpp b/src/lua/LuaGame.cpp index 5edf5adff7e..bcd61f4771a 100644 --- a/src/lua/LuaGame.cpp +++ b/src/lua/LuaGame.cpp @@ -9,7 +9,6 @@ #include "GameSaveError.h" #include "Lang.h" #include "LuaObject.h" -#include "LuaPiGui.h" #include "LuaUtils.h" #include "Pi.h" #include "Player.h" @@ -22,6 +21,7 @@ #include "WorldView.h" #include "core/GZipFormat.h" #include "galaxy/Galaxy.h" +#include "pigui/LuaPiGui.h" /* * Interface: Game diff --git a/src/lua/LuaPiGui.cpp b/src/lua/LuaPiGui.cpp index 78836520a37..ea5e4d6b29f 100644 --- a/src/lua/LuaPiGui.cpp +++ b/src/lua/LuaPiGui.cpp @@ -1,7 +1,7 @@ // Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -#include "LuaPiGui.h" +#include "LuaPiGuiInternal.h" #include "EnumStrings.h" #include "Game.h" @@ -16,9 +16,10 @@ #include "SystemInfoView.h" #include "WorldView.h" #include "graphics/Graphics.h" +#include "imgui/imgui.h" #include "pigui/LuaFlags.h" +#include "pigui/LuaPiGui.h" #include "pigui/PiGui.h" -#include "pigui/PiGuiLua.h" #include "ship/PlayerShipController.h" #include "sound/Sound.h" #include "ui/Context.h" @@ -78,7 +79,7 @@ void pi_lua_generic_pull(lua_State *l, int index, ImVec2 &vec) vec = ImVec2(tr.x, tr.y); } -int PiGUI::pushOnScreenPositionDirection(lua_State *l, vector3d position) +int PiGui::pushOnScreenPositionDirection(lua_State *l, vector3d position) { PROFILE_SCOPED() const int width = Graphics::GetScreenWidth(); @@ -197,11 +198,12 @@ void pi_lua_generic_pull(lua_State *l, int index, ImGuiCond_ &value) value = parse_imgui_enum(l, index, imguiSetCondTable); } +/* clang-format off */ static LuaFlags imguiColTable = { { "Text", ImGuiCol_Text }, { "TextDisabled", ImGuiCol_TextDisabled }, { "WindowBg", ImGuiCol_WindowBg }, - { "ChildWindowBg", ImGuiCol_ChildWindowBg }, + { "ChildBg", ImGuiCol_ChildBg }, { "PopupBg", ImGuiCol_PopupBg }, { "Border", ImGuiCol_Border }, { "BorderShadow", ImGuiCol_BorderShadow }, @@ -209,8 +211,8 @@ static LuaFlags imguiColTable = { { "FrameBgHovered", ImGuiCol_FrameBgHovered }, { "FrameBgActive", ImGuiCol_FrameBgActive }, { "TitleBg", ImGuiCol_TitleBg }, - { "TitleBgCollapsed", ImGuiCol_TitleBgCollapsed }, { "TitleBgActive", ImGuiCol_TitleBgActive }, + { "TitleBgCollapsed", ImGuiCol_TitleBgCollapsed }, { "MenuBarBg", ImGuiCol_MenuBarBg }, { "ScrollbarBg", ImGuiCol_ScrollbarBg }, { "ScrollbarGrab", ImGuiCol_ScrollbarGrab }, @@ -231,13 +233,23 @@ static LuaFlags imguiColTable = { { "ResizeGrip", ImGuiCol_ResizeGrip }, { "ResizeGripHovered", ImGuiCol_ResizeGripHovered }, { "ResizeGripActive", ImGuiCol_ResizeGripActive }, + { "Tab", ImGuiCol_Tab, }, + { "TabHovered", ImGuiCol_TabHovered, }, + { "TabActive", ImGuiCol_TabActive, }, + { "TabUnfocused", ImGuiCol_TabUnfocused, }, + { "TabUnfocusedActive", ImGuiCol_TabUnfocusedActive, }, { "PlotLines", ImGuiCol_PlotLines }, { "PlotLinesHovered", ImGuiCol_PlotLinesHovered }, { "PlotHistogram", ImGuiCol_PlotHistogram }, { "PlotHistogramHovered", ImGuiCol_PlotHistogramHovered }, { "TextSelectedBg", ImGuiCol_TextSelectedBg }, - { "ModalWindowDarkening", ImGuiCol_ModalWindowDarkening } + { "DragDropTarget", ImGuiCol_DragDropTarget, }, + { "NavHighlight", ImGuiCol_NavHighlight, }, + { "NavWindowingHighlight", ImGuiCol_NavWindowingHighlight, }, + { "NavWindowingDimBg", ImGuiCol_NavWindowingDimBg, }, + { "ModalWindowDimBg", ImGuiCol_ModalWindowDimBg, }, }; +/* clang-format on */ void pi_lua_generic_pull(lua_State *l, int index, ImGuiCol_ &value) { @@ -251,14 +263,19 @@ static LuaFlags imguiStyleVarTable = { { "WindowRounding", ImGuiStyleVar_WindowRounding }, { "WindowBorderSize", ImGuiStyleVar_WindowBorderSize }, { "WindowMinSize", ImGuiStyleVar_WindowMinSize }, + { "WindowTitleAlign", ImGuiStyleVar_WindowTitleAlign }, { "ChildRounding", ImGuiStyleVar_ChildRounding }, { "ChildBorderSize", ImGuiStyleVar_ChildBorderSize }, + { "PopupRounding", ImGuiStyleVar_PopupRounding }, + { "PopupBorderSize", ImGuiStyleVar_PopupBorderSize }, { "FramePadding", ImGuiStyleVar_FramePadding }, { "FrameRounding", ImGuiStyleVar_FrameRounding }, { "FrameBorderSize", ImGuiStyleVar_FrameBorderSize }, { "ItemSpacing", ImGuiStyleVar_ItemSpacing }, { "ItemInnerSpacing", ImGuiStyleVar_ItemInnerSpacing }, { "IndentSpacing", ImGuiStyleVar_IndentSpacing }, + { "ScrollbarSize", ImGuiStyleVar_ScrollbarSize }, + { "ScrollbarRounding", ImGuiStyleVar_ScrollbarRounding }, { "GrabMinSize", ImGuiStyleVar_GrabMinSize }, { "ButtonTextAlign", ImGuiStyleVar_ButtonTextAlign } }; @@ -1629,7 +1646,7 @@ static int l_pigui_get_mouse_clicked_pos(lua_State *l) return 1; } -PiGUI::TScreenSpace PiGUI::lua_rel_space_to_screen_space(const vector3d &pos) +PiGui::TScreenSpace PiGui::lua_rel_space_to_screen_space(const vector3d &pos) { PROFILE_SCOPED() const WorldView *wv = Pi::game->GetWorldView(); @@ -1638,13 +1655,13 @@ PiGUI::TScreenSpace PiGUI::lua_rel_space_to_screen_space(const vector3d &pos) const int height = Graphics::GetScreenHeight(); const vector3d direction = (p - vector3d(width / 2, height / 2, 0)).Normalized(); if (vector3d(0, 0, 0) == p || p.x < 0 || p.y < 0 || p.x > width || p.y > height || p.z > 0) { - return PiGUI::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); + return PiGui::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); } else { - return PiGUI::TScreenSpace(true, vector2d(p.x, p.y), direction); + return PiGui::TScreenSpace(true, vector2d(p.x, p.y), direction); } } -PiGUI::TScreenSpace PiGUI::lua_world_space_to_screen_space(const vector3d &pos) +PiGui::TScreenSpace PiGui::lua_world_space_to_screen_space(const vector3d &pos) { PROFILE_SCOPED() const WorldView *wv = Pi::game->GetWorldView(); @@ -1653,13 +1670,13 @@ PiGUI::TScreenSpace PiGUI::lua_world_space_to_screen_space(const vector3d &pos) const int height = Graphics::GetScreenHeight(); const vector3d direction = (p - vector3d(width / 2, height / 2, 0)).Normalized(); if (vector3d(0, 0, 0) == p || p.x < 0 || p.y < 0 || p.x > width || p.y > height || p.z > 0) { - return PiGUI::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); + return PiGui::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); } else { - return PiGUI::TScreenSpace(true, vector2d(p.x, p.y), direction); + return PiGui::TScreenSpace(true, vector2d(p.x, p.y), direction); } } -PiGUI::TScreenSpace lua_world_space_to_screen_space(const Body *body) +PiGui::TScreenSpace lua_world_space_to_screen_space(const Body *body) { PROFILE_SCOPED() const WorldView *wv = Pi::game->GetWorldView(); @@ -1668,13 +1685,13 @@ PiGUI::TScreenSpace lua_world_space_to_screen_space(const Body *body) const int height = Graphics::GetScreenHeight(); const vector3d direction = (p - vector3d(width / 2, height / 2, 0)).Normalized(); if (vector3d(0, 0, 0) == p || p.x < 0 || p.y < 0 || p.x > width || p.y > height || p.z > 0) { - return PiGUI::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); + return PiGui::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1)); } else { - return PiGUI::TScreenSpace(true, vector2d(p.x, p.y), direction); + return PiGui::TScreenSpace(true, vector2d(p.x, p.y), direction); } } -bool PiGUI::first_body_is_more_important_than(Body *body, Body *other) +bool PiGui::first_body_is_more_important_than(Body *body, Body *other) { Object::Type a = body->GetType(); @@ -1804,7 +1821,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) const double cluster_size = LuaPull(l, 1); const double ship_max_distance = LuaPull(l, 2); - PiGUI::TSS_vector filtered; + PiGui::TSS_vector filtered; filtered.reserve(Pi::game->GetSpace()->GetNumBodies()); for (Body *body : Pi::game->GetSpace()->GetBodies()) { @@ -1812,7 +1829,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) if (body->GetType() == Object::PROJECTILE) continue; if (body->GetType() == Object::SHIP && body->GetPositionRelTo(Pi::player).Length() > ship_max_distance) continue; - const PiGUI::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp + const PiGui::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp if (!res._onScreen) continue; filtered.emplace_back(res); filtered.back()._body = body; @@ -1841,7 +1858,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) const Body *combat_target = Pi::game->GetPlayer()->GetCombatTarget(); const Body *setspeed_target = Pi::game->GetPlayer()->GetSetSpeedTarget(); - for (PiGUI::TScreenSpace &obj : filtered) { + for (PiGui::TScreenSpace &obj : filtered) { bool inserted = false; // never collapse combat target @@ -1857,7 +1874,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) group.m_hasNavTarget = true; group.m_mainBody = obj._body; group.m_screenCoords = obj._screenPosition; - } else if (!group.m_hasNavTarget && PiGUI::first_body_is_more_important_than(obj._body, group.m_mainBody)) { + } else if (!group.m_hasNavTarget && PiGui::first_body_is_more_important_than(obj._body, group.m_mainBody)) { group.m_mainBody = obj._body; group.m_screenCoords = obj._screenPosition; } @@ -1881,7 +1898,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) for (GroupInfo &group : groups) { std::sort(begin(group.m_bodies), end(group.m_bodies), [](Body *a, Body *b) { - return PiGUI::first_body_is_more_important_than(a, b); + return PiGui::first_body_is_more_important_than(a, b); }); } @@ -1910,19 +1927,19 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l) static int l_pigui_get_projected_bodies(lua_State *l) { PROFILE_SCOPED() - PiGUI::TSS_vector filtered; + PiGui::TSS_vector filtered; filtered.reserve(Pi::game->GetSpace()->GetNumBodies()); for (Body *body : Pi::game->GetSpace()->GetBodies()) { if (body == Pi::game->GetPlayer()) continue; if (body->GetType() == Object::PROJECTILE) continue; - const PiGUI::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp + const PiGui::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp if (!res._onScreen) continue; filtered.emplace_back(res); filtered.back()._body = body; } LuaTable result(l, 0, filtered.size()); - for (PiGUI::TScreenSpace &res : filtered) { + for (PiGui::TScreenSpace &res : filtered) { LuaTable object(l, 0, 3); object.Set("onscreen", res._onScreen); @@ -2025,7 +2042,7 @@ static int l_pigui_should_show_labels(lua_State *l) static int l_attr_handlers(lua_State *l) { PROFILE_SCOPED() - PiGUI::GetHandlers().PushCopyToStack(); + PiGui::GetHandlers().PushCopyToStack(); return 1; } @@ -2033,7 +2050,7 @@ static int l_attr_keys(lua_State *l) { PROFILE_SCOPED() // PiGui::Instance *pigui = LuaObject::CheckFromLua(1); - PiGUI::GetKeys().PushCopyToStack(); + PiGui::GetKeys().PushCopyToStack(); return 1; } @@ -2426,6 +2443,20 @@ static int l_pigui_vsliderfloat(lua_State *l) return 1; } +static int l_pigui_color_edit(lua_State *l) +{ + const char *lbl = LuaPull(l, 1); + Color4f color = LuaPull(l, 2).ToColor4f(); + bool hasAlpha = LuaPull(l, 3, true); + + const auto flags = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_NoDragDrop; + bool ok = ImGui::ColorEdit4(lbl, &color.r, flags | (hasAlpha ? ImGuiColorEditFlags_None : ImGuiColorEditFlags_NoAlpha)); + LuaPush(l, ok); + LuaPush(l, Color(color)); + + return 2; +} + static int l_pigui_is_key_released(lua_State *l) { PROFILE_SCOPED() @@ -2616,14 +2647,52 @@ static int l_pigui_push_text_wrap_pos(lua_State *l) return 0; } -void PiGUI::RunHandler(double delta, std::string handler) +static Color4ub to_Color4ub(ImVec4 c) { - PROFILE_SCOPED() - ScopedTable t(GetHandlers()); - if (t.Get(handler)) { - t.Call(handler, delta); - Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__); + return Color4ub(uint8_t(c.x * 255), uint8_t(c.y * 255), uint8_t(c.z * 255), uint8_t(c.w * 255)); +} + +static ImVec4 to_ImVec4(Color4ub c) +{ + Color4f _c = c.ToColor4f(); + return { _c.r, _c.g, _c.b, _c.a }; +} + +void PiGui::load_theme_from_table(LuaTable &table, ImGuiStyle &style) +{ + ScopedTable colors = table.Sub("colors"); + for (auto &pair : imguiColTable.LUT) { + Color4ub defaultColor = to_Color4ub(style.Colors[pair.second]); + style.Colors[pair.second] = to_ImVec4(colors.Get(pair.first, defaultColor)); } + + ScopedTable styles = table.Sub("styles"); +#define GET_STYLE(name) styles.Get(#name, style.name) +#define SET_STYLE(name) style.name = styles.Get(#name, style.name) + + // use template magic and decltype to efficiently load the correct data type + SET_STYLE(Alpha); + SET_STYLE(WindowPadding); + SET_STYLE(WindowRounding); + SET_STYLE(WindowBorderSize); + SET_STYLE(WindowMinSize); + SET_STYLE(WindowTitleAlign); + SET_STYLE(ChildRounding); + SET_STYLE(ChildBorderSize); + SET_STYLE(FramePadding); + SET_STYLE(FrameRounding); + SET_STYLE(FrameBorderSize); + SET_STYLE(PopupRounding); + SET_STYLE(PopupBorderSize); + SET_STYLE(ItemSpacing); + SET_STYLE(ItemInnerSpacing); + SET_STYLE(IndentSpacing); + SET_STYLE(ScrollbarSize); + SET_STYLE(ScrollbarRounding); + SET_STYLE(GrabMinSize); + SET_STYLE(ButtonTextAlign); + +#undef SET_STYLE } template <> @@ -2726,6 +2795,7 @@ void LuaObject::RegisterClass() { "SliderFloat", l_pigui_slider_float }, { "VSliderFloat", l_pigui_vsliderfloat }, { "VSliderInt", l_pigui_vsliderint }, + { "ColorEdit", l_pigui_color_edit }, { "GetMouseClickedPos", l_pigui_get_mouse_clicked_pos }, { "AddConvexPolyFilled", l_pigui_add_convex_poly_filled }, { "IsKeyReleased", l_pigui_is_key_released }, diff --git a/src/lua/LuaPiGui.h b/src/lua/LuaPiGuiInternal.h similarity index 87% rename from src/lua/LuaPiGui.h rename to src/lua/LuaPiGuiInternal.h index 3a66989ae18..5b2e9e62610 100644 --- a/src/lua/LuaPiGui.h +++ b/src/lua/LuaPiGuiInternal.h @@ -11,8 +11,9 @@ #include "vector3.h" class Body; +struct ImGuiStyle; -namespace PiGUI { +namespace PiGui { bool first_body_is_more_important_than(Body *body, Body *other); struct TScreenSpace { @@ -30,8 +31,7 @@ namespace PiGUI { TScreenSpace lua_rel_space_to_screen_space(const vector3d &pos); TScreenSpace lua_world_space_to_screen_space(const vector3d &pos); - // Run a lua PiGui handler. - void RunHandler(double delta, std::string handler = "GAME"); -} // namespace PiGUI + void load_theme_from_table(LuaTable &table, ImGuiStyle &style); +} // namespace PiGui #endif diff --git a/src/lua/LuaPlayer.cpp b/src/lua/LuaPlayer.cpp index 74ccc02a642..9f13095159e 100644 --- a/src/lua/LuaPlayer.cpp +++ b/src/lua/LuaPlayer.cpp @@ -6,7 +6,6 @@ #include "Game.h" #include "LuaConstants.h" #include "LuaObject.h" -#include "LuaPiGui.h" #include "LuaUtils.h" #include "LuaVector.h" #include "Pi.h" diff --git a/src/lua/LuaShipDef.cpp b/src/lua/LuaShipDef.cpp index 3a9a223ee76..88b3451a676 100644 --- a/src/lua/LuaShipDef.cpp +++ b/src/lua/LuaShipDef.cpp @@ -249,6 +249,7 @@ void LuaShipDef::Register() pi_lua_settable(l, "hyperdriveClass", st.hyperdriveClass); pi_lua_settable(l, "effectiveExhaustVelocity", st.effectiveExhaustVelocity); pi_lua_settable(l, "thrusterFuelUse", st.GetFuelUseRate()); + pi_lua_settable(l, "atmosphericPressureLimit", st.atmosphericPressureLimit); lua_newtable(l); for (int t = Thruster::THRUSTER_REVERSE; t < Thruster::THRUSTER_MAX; t++) diff --git a/src/matrix4x4.h b/src/matrix4x4.h index 23f6db5bce8..7c1fb2be72f 100644 --- a/src/matrix4x4.h +++ b/src/matrix4x4.h @@ -185,6 +185,25 @@ class matrix4x4 { m[15] = 1; return m; } + + /////////////////////////////////////////////////////////////////////////////// + // Matrix Construction Functions + // NOTE: all matrix functions here are optimized for reverse-Z depth buffers. + // Compared to "standard" DirectX or OpenGL matricies they invert the Z value + // so it ranges from 1.0 at the near plane to 0.0 at the far plane. + /////////////////////////////////////////////////////////////////////////////// + + // Construct a perspective projection matrix based on arbitrary left/right/top/bottom + // plane positions. + // This method is slower than the others, but supports view frustrums that are not + // aligned with the Z-axis. Unless you know what you're doing, you shouldn't use this. + // + // @param left - the minimum x-value of the view volume at the near plane + // @param right - the maxiumum x-value of the view volume at the near plane + // @param bottom - the maxiumum y-value of the view volume at the near plane + // @param top - the maxiumum y-value of the view volume at the near plane + // @param znear - the near clipping plane + // @param zfar - the far clipping plane static matrix4x4 FrustumMatrix(T left, T right, T bottom, T top, T znear, T zfar) { assert((znear > T(0)) && (zfar > T(0))); @@ -193,27 +212,86 @@ class matrix4x4 { const T sy = (T(2) * znear) / (top - bottom); const T A = (right + left) / (right - left); const T B = (top + bottom) / (top - bottom); - const T C = -(zfar + znear) / (zfar - znear); - const T D = -(T(2) * zfar * znear) / (zfar - znear); + const T C = (zfar) / (zfar - znear) - 1; + const T D = (zfar * znear) / (zfar - znear); matrix4x4 m; - m[0] = sx; - m[4] = 0; - m[8] = A; - m[12] = 0; - m[1] = 0; - m[5] = sy; - m[9] = B; - m[13] = 0; - m[2] = 0; - m[6] = 0; - m[10] = C; - m[14] = D; - m[3] = 0; - m[7] = 0; - m[11] = -1; - m[15] = 0; - return m; + + // http://glprogramming.com/red/appendixf.html + // OpenGL 'Red Book' on Perspective Projection + // Presented here in row-major notation (because that's what matrix4x4f uses internally) + T perspective[16] = { + sx, 0, 0, 0, + 0, sy, 0, 0, + A, B, C, -1, + 0, 0, D, 0 + }; + return matrix4x4(&perspective[0]); + } + + // Construct a perspective projection matrix based field of view and aspect ratio. + // This method is the optimized case when you know your screen aspect ratio and + // field of view and aren't interested in fancy math. Use this function or + // InfinitePerspectiveMatrix if at all possible. + // + // @param fovR - the camera FOV in radians + // @param aspect - the aspect ratio (width / height) of the viewport + // @param znear - the near clipping plane + // @param zfar - the far clipping plane + // @param fovX - whether the field of view is horizontal or vertical (default) + static matrix4x4 PerspectiveMatrix(T fovR, T aspect, T znear, T zfar, bool fovX = false) + { + assert((znear > T(0)) && (zfar > znear)); + + const T e = 1 / tan(fovR / T(2)); + const T x = fovX ? e : e / aspect; + const T y = fovX ? e / aspect : e; + const T z = (zfar) / (zfar - znear) - 1; + const T w = (zfar * znear) / (zfar - znear); + + // Based on: http://www.terathon.com/gdc07_lengyel.pdf + // Unlike gluProject / FrustumMatrix, this projection matrix can only be + // symmetric about the Z axis. + // This is what you want in 99% of cases, and simplifies the math a good deal. + T perspective[16] = { + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, -1, + 0, 0, w, 0 + }; + + return matrix4x4(&perspective[0]); } + + // Construct an infinite far-plane perspective projection matrix. + // Unless you specifically want to clip objects beyond a specific distance, + // this projection will work for any object at any distance. + // + // @param fovR - the camera FOV in radians + // @param aspect - the aspect ratio (width / height) of the viewport + // @param znear - the near clipping plane + // @param fovX - whether the field of view is horizontal or vertical (default) + static matrix4x4 InfinitePerspectiveMatrix(T fovR, T aspect, T znear, bool fovX = false) + { + assert(znear > T(0)); + + const T e = 1 / tan(fovR / T(2)); + const T x = fovX ? e : e / aspect; + const T y = fovX ? e / aspect : e; + const T w = znear; + + // Based on: http://dev.theomader.com/depth-precision/ + // An 'infinite far-plane' projection matrix. There is no concept of a zFar value, + // and it can handle everything up to and including homogeneous coordinates with w=0. + T perspective[16] = { + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, 0, -1, + 0, 0, w, 0 + }; + + return matrix4x4(&perspective[0]); + } + /////////////////////////////////////////////////////////////////////////////// // set a orthographic frustum with 6 params similar to glOrtho() // (left, right, bottom, top, near, far) @@ -223,17 +301,36 @@ class matrix4x4 { assert((znear >= T(-1)) && (zfar > T(0))); T a = T(2) / (right - left); T b = T(2) / (top - bottom); - T c = -T(2) / (zfar - znear); + T c = T(1) / (zfar - znear) - 1; + + T tx = (right + left) / (left - right); + T ty = (top + bottom) / (bottom - top); + T tz = (zfar + znear) / (zfar - znear); + + T ortho[16] = { + a, 0, 0, 0, + 0, b, 0, 0, + 0, 0, c, 0, + tx, ty, tz, 1 + }; + matrix4x4 m(&ortho[0]); + return m; + } + + static matrix4x4 OrthoMatrix(T width, T height, T znear, T zfar) + { + assert((znear >= T(-1)) && (zfar > T(0))); + T a = T(2) / width; + T b = T(2) / height; + T c = T(1) / (zfar - znear) - 1; - T tx = -(right + left) / (right - left); - T ty = -(top + bottom) / (top - bottom); - T tz = -(zfar + znear) / (zfar - znear); + T tz = (zfar + znear) / (zfar - znear); T ortho[16] = { a, 0, 0, 0, 0, b, 0, 0, 0, 0, c, 0, - tx, ty, tz, T(1) + 0, 0, tz, 1 }; matrix4x4 m(&ortho[0]); return m; diff --git a/src/pigui/Face.cpp b/src/pigui/Face.cpp index bb7041e5922..577242ee8f1 100644 --- a/src/pigui/Face.cpp +++ b/src/pigui/Face.cpp @@ -6,7 +6,7 @@ #include "SDLWrappers.h" #include "graphics/TextureBuilder.h" -namespace PiGUI { +namespace PiGui { RefCountedPtr Face::s_material; @@ -41,4 +41,4 @@ namespace PiGUI { return m_texture->GetDescriptor().texSize; } -} // namespace PiGUI +} // namespace PiGui diff --git a/src/pigui/Face.h b/src/pigui/Face.h index b471a0333f3..78fb609bdba 100644 --- a/src/pigui/Face.h +++ b/src/pigui/Face.h @@ -10,7 +10,7 @@ #include "graphics/Drawables.h" #include "graphics/Texture.h" -namespace PiGUI { +namespace PiGui { class Face : public RefCounted { public: @@ -19,7 +19,7 @@ namespace PiGUI { Uint32 GetTextureId(); vector2f GetTextureSize(); - enum Flags { // + enum Flags { // RAND = 0, MALE = (1 << 0), FEMALE = (1 << 1), @@ -37,6 +37,6 @@ namespace PiGUI { std::unique_ptr m_quad; }; -} // namespace PiGUI +} // namespace PiGui #endif diff --git a/src/pigui/Image.cpp b/src/pigui/Image.cpp index bce8e9eb9e6..c01cf2ba438 100644 --- a/src/pigui/Image.cpp +++ b/src/pigui/Image.cpp @@ -5,7 +5,7 @@ #include "FileSystem.h" #include "graphics/TextureBuilder.h" -namespace PiGUI { +namespace PiGui { Image::Image(const std::string &filename) { @@ -28,4 +28,4 @@ namespace PiGUI { return m_texture->GetDescriptor().texSize; } -} // namespace PiGUI +} // namespace PiGui diff --git a/src/pigui/Image.h b/src/pigui/Image.h index c06eb62c3fa..c36dd48973e 100644 --- a/src/pigui/Image.h +++ b/src/pigui/Image.h @@ -8,7 +8,7 @@ #include "SmartPtr.h" #include "graphics/TextureBuilder.h" -namespace PiGUI { +namespace PiGui { class Image : public RefCounted { public: @@ -22,6 +22,6 @@ namespace PiGUI { RefCountedPtr m_texture; }; -} // namespace PiGUI +} // namespace PiGui #endif diff --git a/src/pigui/LuaFace.cpp b/src/pigui/LuaFace.cpp index 30756713150..87c3908a530 100644 --- a/src/pigui/LuaFace.cpp +++ b/src/pigui/LuaFace.cpp @@ -2,13 +2,13 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "Face.h" +#include "LuaPiGui.h" #include "lua/LuaConstants.h" #include "lua/LuaObject.h" -#include "lua/LuaPiGui.h" #include "lua/LuaTable.h" #include "lua/LuaVector2.h" -namespace PiGUI { +namespace PiGui { class LuaPiguiFace { public: @@ -51,14 +51,14 @@ namespace PiGUI { if (lua_gettop(l) > 1 && !lua_isnil(l, 2)) seed = luaL_checkunsigned(l, 2); - LuaObject::PushToLua(new Face(face, seed)); + LuaObject::PushToLua(new Face(face, seed)); return 1; } static int l_face_attr_texture_id(lua_State *l) { PROFILE_SCOPED() - Face *f = LuaObject::CheckFromLua(1); + Face *f = LuaObject::CheckFromLua(1); Uint32 result = f->GetTextureId(); lua_pushlightuserdata(l, reinterpret_cast(result)); @@ -68,7 +68,7 @@ namespace PiGUI { static int l_face_attr_texture_size(lua_State *l) { PROFILE_SCOPED() - Face *f = LuaObject::CheckFromLua(1); + Face *f = LuaObject::CheckFromLua(1); vector2f result = f->GetTextureSize(); LuaVector2::PushToLuaF(l, result); @@ -76,22 +76,22 @@ namespace PiGUI { } }; -} // namespace PiGUI +} // namespace PiGui template <> -const char *LuaObject::s_type = "PiGui.Modules.Face"; +const char *LuaObject::s_type = "PiGui.Modules.Face"; template <> -void LuaObject::RegisterClass() +void LuaObject::RegisterClass() { static const luaL_Reg l_methods[] = { - { "New", PiGUI::LuaPiguiFace::l_new }, + { "New", PiGui::LuaPiguiFace::l_new }, { 0, 0 } }; static const luaL_Reg l_attrs[] = { - { "textureId", PiGUI::LuaPiguiFace::l_face_attr_texture_id }, - { "textureSize", PiGUI::LuaPiguiFace::l_face_attr_texture_size }, + { "textureId", PiGui::LuaPiguiFace::l_face_attr_texture_id }, + { "textureSize", PiGui::LuaPiguiFace::l_face_attr_texture_size }, { 0, 0 } }; diff --git a/src/pigui/LuaImage.cpp b/src/pigui/LuaImage.cpp index d3764629575..8af8085b953 100644 --- a/src/pigui/LuaImage.cpp +++ b/src/pigui/LuaImage.cpp @@ -2,13 +2,13 @@ // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt #include "Image.h" +#include "LuaPiGui.h" #include "lua/LuaConstants.h" #include "lua/LuaObject.h" -#include "lua/LuaPiGui.h" #include "lua/LuaTable.h" #include "lua/LuaVector2.h" -namespace PiGUI { +namespace PiGui { class LuaPiguiImage { public: @@ -16,13 +16,13 @@ namespace PiGUI { { std::string filename = LuaPull(l, 1); - LuaObject::PushToLua(new PiGUI::Image(filename)); + LuaObject::PushToLua(new PiGui::Image(filename)); return 1; } static int l_image_attr_texture_id(lua_State *l) { - Image *i = LuaObject::CheckFromLua(1); + Image *i = LuaObject::CheckFromLua(1); lua_pushlightuserdata(l, reinterpret_cast(i->GetId())); return 1; @@ -30,7 +30,7 @@ namespace PiGUI { static int l_image_attr_texture_size(lua_State *l) { - Image *i = LuaObject::CheckFromLua(1); + Image *i = LuaObject::CheckFromLua(1); LuaVector2::PushToLuaF(l, i->GetSize()); return 1; @@ -38,30 +38,30 @@ namespace PiGUI { static int l_image_attr_texture_uv(lua_State *l) { - Image *i = LuaObject::CheckFromLua(1); + Image *i = LuaObject::CheckFromLua(1); LuaVector2::PushToLuaF(l, i->GetUv()); return 1; } }; -} // namespace PiGUI +} // namespace PiGui template <> -const char *LuaObject::s_type = "PiGui.Modules.Image"; +const char *LuaObject::s_type = "PiGui.Modules.Image"; template <> -void LuaObject::RegisterClass() +void LuaObject::RegisterClass() { static const luaL_Reg l_methods[] = { - { "New", PiGUI::LuaPiguiImage::l_new }, + { "New", PiGui::LuaPiguiImage::l_new }, { 0, 0 } }; static const luaL_Reg l_attrs[] = { - { "id", PiGUI::LuaPiguiImage::l_image_attr_texture_id }, - { "size", PiGUI::LuaPiguiImage::l_image_attr_texture_size }, - { "uv", PiGUI::LuaPiguiImage::l_image_attr_texture_uv }, + { "id", PiGui::LuaPiguiImage::l_image_attr_texture_id }, + { "size", PiGui::LuaPiguiImage::l_image_attr_texture_size }, + { "uv", PiGui::LuaPiguiImage::l_image_attr_texture_uv }, { 0, 0 } }; diff --git a/src/pigui/LuaModelSpinner.cpp b/src/pigui/LuaModelSpinner.cpp index b54a87813ff..aae54902ccd 100644 --- a/src/pigui/LuaModelSpinner.cpp +++ b/src/pigui/LuaModelSpinner.cpp @@ -6,7 +6,7 @@ #include "lua/LuaVector2.h" #include "pigui/ModelSpinner.h" -namespace PiGUI { +namespace PiGui { namespace LuaPiguiModelSpinner { static int l_model_new(lua_State *l) { @@ -60,15 +60,15 @@ namespace PiGUI { return 0; } } // namespace LuaPiguiModelSpinner -} // namespace PiGUI +} // namespace PiGui -using namespace PiGUI::LuaPiguiModelSpinner; +using namespace PiGui::LuaPiguiModelSpinner; template <> -const char *LuaObject::s_type = "PiGui.Modules.ModelSpinner"; +const char *LuaObject::s_type = "PiGui.Modules.ModelSpinner"; template <> -void LuaObject::RegisterClass() +void LuaObject::RegisterClass() { const luaL_Reg l_meta[] = { diff --git a/src/pigui/PiGuiLua.cpp b/src/pigui/LuaPiGui.cpp similarity index 51% rename from src/pigui/PiGuiLua.cpp rename to src/pigui/LuaPiGui.cpp index e089746bcf2..6832220babc 100644 --- a/src/pigui/PiGuiLua.cpp +++ b/src/pigui/LuaPiGui.cpp @@ -1,10 +1,11 @@ // Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -#include "PiGuiLua.h" +#include "LuaPiGui.h" #include "Face.h" #include "Image.h" #include "ModelSpinner.h" +#include "lua/LuaPiGuiInternal.h" #include "lua/LuaTable.h" static std::vector> m_keycodes = { @@ -29,9 +30,10 @@ static std::vector> m_keycodes = { }; static LuaRef m_handlers; +static LuaRef m_themes; static LuaRef m_keys; -namespace PiGUI { +namespace PiGui { namespace Lua { @@ -43,6 +45,9 @@ namespace PiGUI { lua_newtable(l); m_handlers = LuaRef(l, -1); + lua_newtable(l); + m_themes = LuaRef(l, -1); + lua_newtable(l); m_keys = LuaRef(l, -1); LuaTable keys(l, -1); @@ -50,15 +55,16 @@ namespace PiGUI { keys.Set(p.first, p.second); } - LuaObject::RegisterClass(); - LuaObject::RegisterClass(); - LuaObject::RegisterClass(); + LuaObject::RegisterClass(); + LuaObject::RegisterClass(); + LuaObject::RegisterClass(); RegisterSandbox(); } void Uninit() { m_handlers.Unref(); + m_themes.Unref(); m_keys.Unref(); } @@ -66,4 +72,38 @@ namespace PiGUI { LuaRef GetHandlers() { return m_handlers; } LuaRef GetKeys() { return m_keys; } -} // namespace PiGUI + LuaRef GetThemes() { return m_themes; } + + void RunHandler(double delta, std::string handler) + { + PROFILE_SCOPED() + ScopedTable t(GetHandlers()); + if (t.Get(handler)) { + t.Call(handler, delta); + Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__); + } + } + + void LoadTheme(ImGuiStyle &style, std::string theme) + { + PROFILE_SCOPED(); + ScopedTable t(GetThemes()); + if (t.Get(theme)) { + ScopedTable theme_tab = t.Sub(theme); + load_theme_from_table(theme_tab, style); + } else { + Output("Unable to load theme %s from lua!\n", theme.c_str()); + } + } + + void LoadThemeFromDisk(std::string theme) + { + PROFILE_SCOPED(); + GetThemes().PushCopyToStack(); + + pi_lua_import(GetThemes().GetLua(), "pigui.themes." + theme); + lua_setfield(GetThemes().GetLua(), -2, theme.c_str()); + + lua_pop(GetThemes().GetLua(), 1); + } +} // namespace PiGui diff --git a/src/pigui/LuaPiGui.h b/src/pigui/LuaPiGui.h new file mode 100644 index 00000000000..33807ed8773 --- /dev/null +++ b/src/pigui/LuaPiGui.h @@ -0,0 +1,41 @@ +// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details +// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +#ifndef PIGUI_LUA_H +#define PIGUI_LUA_H + +#include "lua/LuaObject.h" + +struct ImGuiStyle; + +namespace PiGui { + + // Get registered PiGui handlers. + LuaRef GetHandlers(); + + // Get registered PiGui themes. + LuaRef GetThemes(); + + // Get a table of key name to SDL-keycode mappings + LuaRef GetKeys(); + + namespace Lua { + void RegisterSandbox(); + + void Init(); + void Uninit(); + } // namespace Lua + + // Run a lua PiGui handler. + void RunHandler(double delta, std::string handler = "GAME"); + + // Load a pigui theme into the specified ImGui style. + void LoadTheme(ImGuiStyle &style, std::string theme); + + // FIXME: TEMPORARY to resolve loading order fiasco + // we want themes up as soon as possible (because they're usually flat data objects) + // so this function exists to load a theme out-of-order from Lua::InitModules + void LoadThemeFromDisk(std::string theme); +} // namespace PiGui + +#endif diff --git a/src/pigui/ModelSpinner.cpp b/src/pigui/ModelSpinner.cpp index 86dd87cec5d..44c90737a42 100644 --- a/src/pigui/ModelSpinner.cpp +++ b/src/pigui/ModelSpinner.cpp @@ -9,7 +9,7 @@ #include -using namespace PiGUI; +using namespace PiGui; ModelSpinner::ModelSpinner() : m_pauseTime(.0f), diff --git a/src/pigui/ModelSpinner.h b/src/pigui/ModelSpinner.h index 706eb2ceab8..24920592608 100644 --- a/src/pigui/ModelSpinner.h +++ b/src/pigui/ModelSpinner.h @@ -24,7 +24,7 @@ using ImTextureID = void *; // In essence, we want to make the regular main-scene rendering code modular and able to render // arbitrary scenes to RTs that we can use in Pigui et. al. // For now we'll do a basic implementation here to move the model spinner functionality to Pigui. -namespace PiGUI { +namespace PiGui { class ModelSpinner : public RefCounted { public: ModelSpinner(); @@ -73,4 +73,4 @@ namespace PiGUI { // The rotation of the model. vector2f m_rot; }; -} // namespace PiGUI +} // namespace PiGui diff --git a/src/pigui/PerfInfo.cpp b/src/pigui/PerfInfo.cpp index 74d20ae8de5..31fef900d38 100644 --- a/src/pigui/PerfInfo.cpp +++ b/src/pigui/PerfInfo.cpp @@ -4,6 +4,7 @@ #include "PerfInfo.h" #include "Frame.h" #include "Game.h" +#include "LuaPiGui.h" #include "Pi.h" #include "Player.h" #include "Space.h" @@ -12,7 +13,6 @@ #include "graphics/Texture.h" #include "lua/Lua.h" #include "lua/LuaManager.h" -#include "lua/LuaPiGui.h" #include "scenegraph/Model.h" #include "text/TextureFont.h" @@ -28,7 +28,8 @@ #include #endif -using namespace PiGUI; +// using namespace PiGui; +using PerfInfo = PiGui::PerfInfo; struct PerfInfo::ImGuiState { bool perfWindowOpen = true; @@ -138,7 +139,7 @@ void PerfInfo::Update(float deltaTime, float physTime) if (lastUpdateTime > 1000.0) { lastUpdateTime = fmod(lastUpdateTime, 1000.0); - lua_mem = Lua::manager->GetMemoryUsage(); + lua_mem = ::Lua::manager->GetMemoryUsage(); process_mem = GetMemoryInfo(); } } @@ -220,22 +221,15 @@ void PerfInfo::DrawPerfWindow() DrawWorldViewStats(); ImGui::EndTabItem(); } - - if (Pi::game->GetGalaxy() && ImGui::BeginTabItem("Galaxy Stats")) { - auto &stats = Pi::game->GetGalaxy()->GetStats(); - stats.FlushFrame(); - DrawStatList(stats.GetFrameStats()); - ImGui::EndTabItem(); - } } - PiGUI::RunHandler(Pi::GetFrameTime(), "debug-tabs"); + PiGui::RunHandler(Pi::GetFrameTime(), "debug-tabs"); ImGui::EndTabBar(); } ImGui::End(); - PiGUI::RunHandler(Pi::GetFrameTime(), "debug"); + PiGui::RunHandler(Pi::GetFrameTime(), "debug"); } void PerfInfo::DrawRendererStats() diff --git a/src/pigui/PerfInfo.h b/src/pigui/PerfInfo.h index fe0db119c80..6c3668b7880 100644 --- a/src/pigui/PerfInfo.h +++ b/src/pigui/PerfInfo.h @@ -8,7 +8,7 @@ #include #include -namespace PiGUI { +namespace PiGui { class PerfInfo { public: @@ -61,4 +61,4 @@ namespace PiGUI { ImGuiState *m_state; }; -} // namespace PiGUI +} // namespace PiGui diff --git a/src/pigui/PiGui.cpp b/src/pigui/PiGui.cpp index 54927f8e34a..acdaddcfc8a 100644 --- a/src/pigui/PiGui.cpp +++ b/src/pigui/PiGui.cpp @@ -238,12 +238,6 @@ void Instance::RefreshFontsTexture() ImGui_ImplOpenGL3_CreateDeviceObjects(); } -void PiDefaultStyle(ImGuiStyle &style) -{ - PROFILE_SCOPED() - style.WindowBorderSize = 0.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. -} - // TODO: this isn't very RAII friendly, are we sure we need to call Init() seperately from creating the instance? void Instance::Init(Graphics::Renderer *renderer) { @@ -275,10 +269,6 @@ void Instance::Init(Graphics::Renderer *renderer) // Apply the base style ImGui::StyleColorsDark(); - // Apply Pioneer's style. - // TODO: load this from Lua. - PiDefaultStyle(ImGui::GetStyle()); - std::string imguiIni = FileSystem::JoinPath(FileSystem::GetUserDir(), "imgui.ini"); // this will be leaked, not sure how to deal with it properly in imgui... char *ioIniFilename = new char[imguiIni.size() + 1]; diff --git a/src/pigui/PiGuiLua.h b/src/pigui/PiGuiLua.h deleted file mode 100644 index a1ae5ecb554..00000000000 --- a/src/pigui/PiGuiLua.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details -// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt - -#ifndef PIGUI_LUA_H -#define PIGUI_LUA_H - -#include "lua/LuaObject.h" - -namespace PiGUI { - - // Get registered PiGui handlers. - LuaRef GetHandlers(); - // Get a table of key name to SDL-keycode mappings - LuaRef GetKeys(); - - namespace Lua { - void RegisterSandbox(); - - void Init(); - void Uninit(); - } // namespace Lua -} // namespace PiGUI - -#endif diff --git a/src/pigui/PiGuiSandbox.cpp b/src/pigui/PiGuiSandbox.cpp index 821825a84d0..24743aa870a 100644 --- a/src/pigui/PiGuiSandbox.cpp +++ b/src/pigui/PiGuiSandbox.cpp @@ -1,10 +1,9 @@ #include +#include "LuaPiGui.h" #include "PiGui.h" -#include "PiGuiLua.h" -#include "lua/LuaPiGui.h" #include "lua/LuaUtils.h" #include "imgui/imgui_internal.h" @@ -136,7 +135,7 @@ luaL_Reg l_stack_functions[] = { { NULL, NULL } }; -void PiGUI::Lua::RegisterSandbox() +void PiGui::Lua::RegisterSandbox() { lua_State *L = ::Lua::manager->GetLuaState(); LUA_DEBUG_START(L); diff --git a/src/pigui/View.cpp b/src/pigui/PiGuiView.cpp similarity index 64% rename from src/pigui/View.cpp rename to src/pigui/PiGuiView.cpp index 6eaa6aa1e03..0bb35e71041 100644 --- a/src/pigui/View.cpp +++ b/src/pigui/PiGuiView.cpp @@ -1,11 +1,11 @@ // Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt -#include "pigui/View.h" +#include "pigui/PiGuiView.h" +#include "LuaPiGui.h" #include "Pi.h" -#include "lua/LuaPiGui.h" void PiGuiView::DrawPiGui() { - PiGUI::RunHandler(Pi::GetFrameTime(), m_handlerName); + PiGui::RunHandler(Pi::GetFrameTime(), m_handlerName); } diff --git a/src/pigui/View.h b/src/pigui/PiGuiView.h similarity index 100% rename from src/pigui/View.h rename to src/pigui/PiGuiView.h diff --git a/src/ui/Context.cpp b/src/ui/Context.cpp index 91f0aa254cf..c7c270063dd 100644 --- a/src/ui/Context.cpp +++ b/src/ui/Context.cpp @@ -167,7 +167,7 @@ namespace UI { // reset renderer for each layer for (std::vector::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { - r->SetOrthographicProjection(0, m_width, m_height, 0, -1, 1); + r->SetOrthographicProjection(0, m_width, m_height, 0, 0, 1); r->SetTransform(matrix4x4f::Identity()); r->SetClearColor(Color::BLACK); @@ -177,7 +177,7 @@ namespace UI { } if (m_mousePointer && m_mousePointerEnabled) { - r->SetOrthographicProjection(0, m_width, m_height, 0, -1, 1); + r->SetOrthographicProjection(0, m_width, m_height, 0, 0, 1); r->SetTransform(matrix4x4f::Identity()); r->SetClearColor(Color::BLACK); DrawWidget(m_mousePointer); diff --git a/win32/vs2019/pioneer.vcxproj b/win32/vs2019/pioneer.vcxproj index 35493f87d1a..bb041a5618c 100644 --- a/win32/vs2019/pioneer.vcxproj +++ b/win32/vs2019/pioneer.vcxproj @@ -378,7 +378,6 @@ - @@ -487,12 +486,22 @@ + + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + $(IntDir)pigui\ + - + @@ -533,6 +542,7 @@ + @@ -588,7 +598,6 @@ - @@ -655,7 +664,7 @@ - + @@ -689,11 +698,11 @@ + - - + @@ -716,7 +725,7 @@ - + @@ -744,6 +753,7 @@ + diff --git a/win32/vs2019/pioneer.vcxproj.filters b/win32/vs2019/pioneer.vcxproj.filters index 403bd81b362..2f55c763e5b 100644 --- a/win32/vs2019/pioneer.vcxproj.filters +++ b/win32/vs2019/pioneer.vcxproj.filters @@ -228,9 +228,6 @@ src - - src - src @@ -363,9 +360,6 @@ src\pigui - - src\pigui - src\ship @@ -579,6 +573,15 @@ src\core + + src\ship + + + src\pigui + + + src\pigui + @@ -803,9 +806,6 @@ src - - src - src @@ -953,9 +953,6 @@ src\sound - - src\ship - src\ship @@ -968,9 +965,6 @@ src\pigui - - src\pigui - src\ship @@ -1058,9 +1052,6 @@ src\Lua - - src\Lua - src\Lua @@ -1118,9 +1109,6 @@ src\core - - src\pigui - src\pigui @@ -1139,6 +1127,21 @@ src\core + + src\ship + + + src + + + src\Lua + + + src\pigui + + + src\pigui +