languages support (WIP)
This commit is contained in:
parent
0837cf4f03
commit
7bf70bb26e
22
res/content/base/texts/en_US.txt
Normal file
22
res/content/base/texts/en_US.txt
Normal file
@ -0,0 +1,22 @@
|
||||
bazalt=Bazalt
|
||||
blue_lamp=Blue Lamp
|
||||
brick=Brick
|
||||
dirt=Dirt
|
||||
flower=Flower
|
||||
glass=Glass
|
||||
grass_block=Ground
|
||||
grass=Tall Grass
|
||||
green_lamp=Green Lamp
|
||||
lamp=Lamp
|
||||
leaves=Leaves
|
||||
lightbulb=Bulb
|
||||
metal=Metal
|
||||
pane=Pane
|
||||
pipe=Pipe
|
||||
planks=Planks
|
||||
red_lamp=Red Lamp
|
||||
rust=Rust
|
||||
sand=Sand
|
||||
stone=Stone
|
||||
water=Water
|
||||
wood=Wood
|
||||
22
res/content/base/texts/ru_RU.txt
Normal file
22
res/content/base/texts/ru_RU.txt
Normal file
@ -0,0 +1,22 @@
|
||||
bazalt=Базальт
|
||||
blue_lamp=Синяя Лампа
|
||||
brick=Кирпич
|
||||
dirt=Земля
|
||||
flower=Цветок
|
||||
glass=Стекло
|
||||
grass_block=Дёрн
|
||||
grass=Высокая Трава
|
||||
green_lamp=Зелёная Лампа
|
||||
lamp=Лампа
|
||||
leaves=Листва
|
||||
lightbulb=Лампочка
|
||||
metal=Металл
|
||||
pane=Панель
|
||||
pipe=Труба
|
||||
planks=Доски
|
||||
red_lamp=Красная Лампа
|
||||
rust=Ржавчина
|
||||
sand=Песок
|
||||
stone=Камень
|
||||
water=Вода
|
||||
wood=Бревно
|
||||
39
res/texts/en_US.txt
Normal file
39
res/texts/en_US.txt
Normal file
@ -0,0 +1,39 @@
|
||||
# Menu
|
||||
menu.new-world=New World
|
||||
menu.quit=Quit
|
||||
menu.create-world=Create World
|
||||
menu.save-and-quit=Save and Quit to Menu
|
||||
menu.missing-content=Missing Content!
|
||||
menu.controls=Controls
|
||||
menu.back-to-menu=Back to Main Menu
|
||||
menu.settings=Settings
|
||||
world.seed=Seed
|
||||
world.name=World Name
|
||||
world.create=Create World
|
||||
|
||||
# Settings
|
||||
chunks.load-distance=Load Distance
|
||||
chunks.load-speed=Load Speed
|
||||
graphics.fog-curve=Fog Curve
|
||||
graphics.backlight=Backlight
|
||||
display.vsync=V-Sync
|
||||
camera.fov=FOV
|
||||
mouse.sensitivity=Mouse Sensitivity
|
||||
|
||||
# Bindings
|
||||
movement.forward=Forward
|
||||
movement.back=Back
|
||||
movement.left=Left
|
||||
movement.right=Right
|
||||
movement.jump=Jump
|
||||
movement.sprint=Sprint
|
||||
movement.crouch=Crouch
|
||||
movement.cheat=Cheat
|
||||
hud.inventory=Inventory
|
||||
player.pick=Pick Block
|
||||
player.attack=Attack / Break
|
||||
player.build=Place Block
|
||||
player.flight=Flight
|
||||
player.noclip=No-clip
|
||||
camera.zoom=Zoom
|
||||
camera.mode=Switch Camera Mode
|
||||
11
res/texts/langs.json
Normal file
11
res/texts/langs.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"langs": {
|
||||
"en_US": {
|
||||
"name": "English"
|
||||
},
|
||||
"ru_RU": {
|
||||
"name": "Русский"
|
||||
}
|
||||
},
|
||||
"fallback": "en_US"
|
||||
}
|
||||
45
res/texts/ru_RU.txt
Normal file
45
res/texts/ru_RU.txt
Normal file
@ -0,0 +1,45 @@
|
||||
# Общее
|
||||
Yes=Да
|
||||
No=Нет
|
||||
Ok=Ок
|
||||
Back=Назад
|
||||
Continue=Продолжить
|
||||
|
||||
# Меню
|
||||
menu.new-world=Новый Мир
|
||||
menu.quit=Выход
|
||||
menu.continue=Продолжить
|
||||
menu.save-and-quit=Сохранить и Выйти в Меню
|
||||
menu.missing-content=Отсутствует Контент!
|
||||
menu.controls=Управление
|
||||
menu.back-to-menu=Вернуться в Меню
|
||||
menu.settings=Настройки
|
||||
world.seed=Зерно
|
||||
world.name=Название
|
||||
world.create=Создать Мир
|
||||
|
||||
# Настройки
|
||||
chunks.load-distance=Дистанция Загрузки
|
||||
chunks.load-speed=Скорость Загрузки
|
||||
graphics.fog-curve=Кривая Тумана
|
||||
graphics.backlight=Подсветка
|
||||
display.vsync=V-Sync
|
||||
camera.fov=Поле Зрения
|
||||
mouse.sensitivity=Чувствительность Мыши
|
||||
|
||||
# Управление
|
||||
movement.forward=Вперёд
|
||||
movement.back=Назад
|
||||
movement.left=Влево
|
||||
movement.right=Вправо
|
||||
movement.jump=Прыжок
|
||||
movement.sprint=Ускорение
|
||||
movement.crouch=Красться
|
||||
movement.cheat=Чит
|
||||
hud.inventory=Инвентарь
|
||||
player.pick=Подобрать Блок
|
||||
player.attack=Атаковать / Сломать
|
||||
player.build=Поставить Блок
|
||||
player.flight=Полёт
|
||||
camera.zoom=Приближение
|
||||
camera.mode=Сменить Режим Камеры
|
||||
@ -98,6 +98,18 @@ void BasicParser::skipWhitespace() {
|
||||
}
|
||||
}
|
||||
|
||||
void BasicParser::skipLine() {
|
||||
while (hasNext()) {
|
||||
if (source[pos] == '\n') {
|
||||
pos++;
|
||||
linestart = pos;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicParser::hasNext() {
|
||||
return pos < source.length();
|
||||
}
|
||||
@ -250,7 +262,7 @@ bool BasicParser::parseNumber(int sign, number_u& out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
string BasicParser::parseString(char quote) {
|
||||
string BasicParser::parseString(char quote, bool closeRequired) {
|
||||
std::stringstream ss;
|
||||
while (hasNext()) {
|
||||
char c = source[pos];
|
||||
@ -282,13 +294,16 @@ string BasicParser::parseString(char quote) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '\n') {
|
||||
if (c == '\n' && closeRequired) {
|
||||
throw error("non-closed string literal");
|
||||
}
|
||||
ss << c;
|
||||
pos++;
|
||||
}
|
||||
throw error("unexpected end");
|
||||
if (closeRequired) {
|
||||
throw error("unexpected end");
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
parsing_error BasicParser::error(std::string message) {
|
||||
|
||||
@ -70,6 +70,7 @@ protected:
|
||||
uint linestart = 0;
|
||||
|
||||
virtual void skipWhitespace();
|
||||
void skipLine();
|
||||
void expect(char expected);
|
||||
char peek();
|
||||
char nextChar();
|
||||
@ -79,7 +80,7 @@ protected:
|
||||
std::string parseName();
|
||||
int64_t parseSimpleInt(int base);
|
||||
bool parseNumber(int sign, number_u& out);
|
||||
std::string parseString(char chr);
|
||||
std::string parseString(char chr, bool closeRequired=true);
|
||||
|
||||
parsing_error error(std::string message);
|
||||
|
||||
|
||||
@ -115,16 +115,7 @@ Reader::Reader(Wrapper* wrapper, string file, string source) : BasicParser(file,
|
||||
void Reader::skipWhitespace() {
|
||||
BasicParser::skipWhitespace();
|
||||
if (hasNext() && source[pos] == '#') {
|
||||
pos++;
|
||||
while (hasNext()) {
|
||||
if (source[pos] == '\n') {
|
||||
pos++;
|
||||
linestart = pos;
|
||||
line++;
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
skipLine();
|
||||
if (hasNext() && is_whitespace(peek())) {
|
||||
skipWhitespace();
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "typedefs.h"
|
||||
|
||||
const int ENGINE_VERSION_MAJOR = 0;
|
||||
const int ENGINE_VERSION_MINOR = 15;
|
||||
const int ENGINE_VERSION_MINOR = 16;
|
||||
|
||||
const int CHUNK_W = 16;
|
||||
const int CHUNK_H = 256;
|
||||
@ -16,6 +16,7 @@ const int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D);
|
||||
|
||||
/* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */
|
||||
const blockid_t BLOCK_VOID = std::numeric_limits<blockid_t>::max();
|
||||
const blockid_t MAX_BLOCKS = BLOCK_VOID;
|
||||
|
||||
inline uint vox_index(int x, int y, int z, int w=CHUNK_W, int d=CHUNK_D) {
|
||||
return (y * d + z) * w + x;
|
||||
|
||||
17
src/content/ContentPack.cpp
Normal file
17
src/content/ContentPack.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "ContentPack.h"
|
||||
|
||||
using std::string;
|
||||
using std::filesystem::path;
|
||||
|
||||
ContentPack::ContentPack(const string id,
|
||||
const path folder)
|
||||
: id(id), folder(folder) {
|
||||
|
||||
}
|
||||
const string& ContentPack::getId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
const path& ContentPack::getFolder() const {
|
||||
return folder;
|
||||
}
|
||||
18
src/content/ContentPack.h
Normal file
18
src/content/ContentPack.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef CONTENT_CONTENT_PACK_H_
|
||||
#define CONTENT_CONTENT_PACK_H_
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
class ContentPack {
|
||||
const std::string id;
|
||||
const std::filesystem::path folder;
|
||||
public:
|
||||
ContentPack(const std::string id,
|
||||
const std::filesystem::path folder);
|
||||
|
||||
const std::string& getId() const;
|
||||
const std::filesystem::path& getFolder() const;
|
||||
};
|
||||
|
||||
#endif // CONTENT_CONTENT_PACK_H_
|
||||
@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include <filesystem>
|
||||
#define GLEW_STATIC
|
||||
@ -27,6 +28,9 @@
|
||||
#include "files/files.h"
|
||||
#include "files/engine_paths.h"
|
||||
|
||||
#include "content/ContentPack.h"
|
||||
#include "frontend/locale/langs.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::shared_ptr;
|
||||
using std::string;
|
||||
@ -55,6 +59,16 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths, Content* content)
|
||||
}
|
||||
Audio::initialize();
|
||||
gui = new GUI();
|
||||
|
||||
std::vector<const ContentPack*> packs;
|
||||
auto resdir = paths->getResources();
|
||||
auto base = std::make_unique<ContentPack>("base", resdir/path("content/base"));
|
||||
packs.push_back(base.get());
|
||||
|
||||
if (settings.ui.language == "auto") {
|
||||
settings.ui.language = platform::detect_locale();
|
||||
}
|
||||
langs::setup(resdir, settings.ui.language, packs);
|
||||
std::cout << "-- initializing finished" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,9 @@ toml::Wrapper create_wrapper(EngineSettings& settings) {
|
||||
debug.add("generator-test-mode", &settings.debug.generatorTestMode);
|
||||
debug.add("show-chunk-borders", &settings.debug.showChunkBorders);
|
||||
debug.add("do-write-lights", &settings.debug.doWriteLights);
|
||||
|
||||
toml::Section& ui = wrapper.add("ui");
|
||||
ui.add("language", &settings.ui.language);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "../locale/langs.h"
|
||||
|
||||
using namespace gui;
|
||||
using glm::vec2;
|
||||
using glm::vec4;
|
||||
@ -11,7 +13,7 @@ using std::string;
|
||||
using std::wstring;
|
||||
|
||||
Button* guiutil::backButton(PagesControl* menu) {
|
||||
return (new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) {
|
||||
return (new Button(langs::get(L"Back"), vec4(10.f)))->listenAction([=](GUI* gui) {
|
||||
menu->back();
|
||||
});
|
||||
}
|
||||
@ -27,7 +29,7 @@ void guiutil::alert(GUI* gui, wstring text, gui::runnable on_hidden) {
|
||||
Panel* panel = new Panel(vec2(500, 200), vec4(8.0f), 8.0f);
|
||||
panel->color(vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
panel->add(new Label(text));
|
||||
panel->add((new Button(L"Ok", vec4(10.f)))->listenAction([=](GUI* gui) {
|
||||
panel->add((new Button(langs::get(L"Ok"), vec4(10.f)))->listenAction([=](GUI* gui) {
|
||||
if (on_hidden)
|
||||
on_hidden();
|
||||
menu->back();
|
||||
@ -39,6 +41,9 @@ void guiutil::alert(GUI* gui, wstring text, gui::runnable on_hidden) {
|
||||
|
||||
void guiutil::confirm(GUI* gui, wstring text, gui::runnable on_confirm,
|
||||
wstring yestext, wstring notext) {
|
||||
if (yestext.empty()) yestext = langs::get(L"Yes");
|
||||
if (notext.empty()) notext = langs::get(L"No");
|
||||
|
||||
PagesControl* menu = gui->getMenu();
|
||||
Panel* panel = new Panel(vec2(600, 200), vec4(8.0f), 8.0f);
|
||||
panel->color(vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
|
||||
@ -13,7 +13,7 @@ namespace guiutil {
|
||||
gui::Button* gotoButton(std::wstring text, std::string page, gui::PagesControl* menu);
|
||||
void alert(gui::GUI* gui, std::wstring text, gui::runnable on_hidden=nullptr);
|
||||
void confirm(gui::GUI* gui, std::wstring text, gui::runnable on_confirm=nullptr,
|
||||
std::wstring yestext=L"Yes", std::wstring notext=L"No");
|
||||
std::wstring yestext=L"", std::wstring notext=L"");
|
||||
}
|
||||
|
||||
#endif // FRONTEND_GUI_GUI_UTIL_H_
|
||||
|
||||
133
src/frontend/locale/langs.cpp
Normal file
133
src/frontend/locale/langs.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "langs.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../../coders/json.h"
|
||||
#include "../../coders/commons.h"
|
||||
#include "../../content/ContentPack.h"
|
||||
#include "../../files/files.h"
|
||||
#include "../../util/stringutil.h"
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::vector;
|
||||
using std::unique_ptr;
|
||||
using std::unordered_map;
|
||||
using std::filesystem::path;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
unique_ptr<langs::Lang> langs::current;
|
||||
vector<langs::LocaleInfo> langs::locales_info;
|
||||
|
||||
langs::Lang::Lang(string locale) : locale(locale) {
|
||||
}
|
||||
|
||||
const wstring& langs::Lang::get(const wstring& key) const {
|
||||
auto found = map.find(key);
|
||||
if (found == map.end()) {
|
||||
return key;
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
void langs::Lang::put(const wstring& key, const wstring& text) {
|
||||
map[key] = text;
|
||||
}
|
||||
|
||||
/* Language key-value txt files parser */
|
||||
class Reader : public BasicParser {
|
||||
void skipWhitespace() override {
|
||||
BasicParser::skipWhitespace();
|
||||
if (hasNext() && source[pos] == '#') {
|
||||
skipLine();
|
||||
if (hasNext() && is_whitespace(peek())) {
|
||||
skipWhitespace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
Reader(string file, string source) : BasicParser(file, source) {
|
||||
}
|
||||
|
||||
void read(langs::Lang& lang, std::string prefix) {
|
||||
skipWhitespace();
|
||||
while (hasNext()) {
|
||||
string key = parseString('=', true);
|
||||
util::trim(key);
|
||||
key = prefix + key;
|
||||
string text = parseString('\n', false);
|
||||
util::trim(text);
|
||||
lang.put(util::str2wstr_utf8(key),
|
||||
util::str2wstr_utf8(text));
|
||||
skipWhitespace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void langs::loadLocalesInfo(const path& resdir, string& fallback) {
|
||||
path file = resdir/path(langs::TEXTS_FOLDER)/path("langs.json");
|
||||
unique_ptr<json::JObject> root (files::read_json(file));
|
||||
|
||||
langs::locales_info.clear();
|
||||
root->str("fallback", fallback);
|
||||
|
||||
auto langs = root->obj("langs");
|
||||
if (langs) {
|
||||
for (auto& entry : langs->map) {
|
||||
auto langInfo = entry.second;
|
||||
|
||||
string name;
|
||||
if (langInfo->type == json::valtype::object) {
|
||||
name = langInfo->value.obj->getStr("name", "none");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cout << "locale " << entry.first << " (" << name << ") added" << std::endl;
|
||||
langs::locales_info.push_back(LocaleInfo {entry.first, name});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void langs::load(const path& resdir,
|
||||
const string& locale,
|
||||
vector<const ContentPack*>& packs,
|
||||
Lang& lang) {
|
||||
path filename = path(TEXTS_FOLDER)/path(locale + LANG_FILE_EXT);
|
||||
path core_file = resdir/filename;
|
||||
if (fs::is_regular_file(core_file)) {
|
||||
string text = files::read_string(core_file);
|
||||
Reader reader(core_file.string(), text);
|
||||
reader.read(lang, "");
|
||||
}
|
||||
for (auto pack : packs) {
|
||||
path file = pack->getFolder()/filename;
|
||||
if (fs::is_regular_file(file)) {
|
||||
string text = files::read_string(file);
|
||||
Reader reader(file.string(), text);
|
||||
reader.read(lang, pack->getId()+":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void langs::load(const path& resdir,
|
||||
const string& locale,
|
||||
const string& fallback,
|
||||
vector<const ContentPack*>& packs) {
|
||||
unique_ptr<Lang> lang (new Lang(locale));
|
||||
load(resdir, fallback, packs, *lang.get());
|
||||
load(resdir, locale, packs, *lang.get());
|
||||
current.reset(lang.release());
|
||||
}
|
||||
|
||||
void langs::setup(const path& resdir,
|
||||
const string& locale,
|
||||
vector<const ContentPack*>& packs) {
|
||||
string fallback = langs::FALLBACK_DEFAULT;
|
||||
langs::loadLocalesInfo(resdir, fallback);
|
||||
langs::load(resdir, locale, fallback, packs);
|
||||
}
|
||||
|
||||
const wstring& langs::get(const wstring& key) {
|
||||
return current->get(key);
|
||||
}
|
||||
65
src/frontend/locale/langs.h
Normal file
65
src/frontend/locale/langs.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef FRONTEND_LOCALE_LANGS_H
|
||||
#define FRONTEND_LOCALE_LANGS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
|
||||
class ContentPack;
|
||||
|
||||
namespace langs {
|
||||
const char LANG_FILE_EXT[] = ".txt";
|
||||
const char TEXTS_FOLDER[] = "texts";
|
||||
const char FALLBACK_DEFAULT[] = "en_US";
|
||||
|
||||
/*
|
||||
Translation is mostly used for rendered text,
|
||||
so Font.draw and Lang both use wstring for strings.
|
||||
|
||||
Translation key is wstring too, allowing to use it as value
|
||||
if no any translation found, without conversion required
|
||||
|
||||
Key syntax: `modid:context.key` where modid is added at runtime for
|
||||
content pack texts
|
||||
*/
|
||||
class Lang {
|
||||
std::string locale;
|
||||
std::unordered_map<std::wstring, std::wstring> map;
|
||||
public:
|
||||
Lang(std::string locale);
|
||||
|
||||
const std::wstring& get(const std::wstring& key) const;
|
||||
void put(const std::wstring& key, const std::wstring& text);
|
||||
};
|
||||
|
||||
struct LocaleInfo {
|
||||
std::string locale;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
extern std::unique_ptr<Lang> current;
|
||||
extern std::vector<LocaleInfo> locales_info;
|
||||
|
||||
extern void loadLocalesInfo(
|
||||
const std::filesystem::path& resdir,
|
||||
std::string& fallback);
|
||||
|
||||
extern void load(const std::filesystem::path& resdir,
|
||||
const std::string& locale,
|
||||
std::vector<const ContentPack*>& packs,
|
||||
Lang& lang);
|
||||
extern void load(const std::filesystem::path& resdir,
|
||||
const std::string& locale,
|
||||
const std::string& fallback,
|
||||
std::vector<const ContentPack*>& packs);
|
||||
|
||||
extern const std::wstring& get(const std::wstring& key);
|
||||
|
||||
extern void setup(const std::filesystem::path& resdir,
|
||||
const std::string& locale,
|
||||
std::vector<const ContentPack*>& packs);
|
||||
}
|
||||
|
||||
#endif // FRONTEND_LOCALE_LANGS_H
|
||||
@ -23,6 +23,7 @@
|
||||
#include "../content/ContentLUT.h"
|
||||
|
||||
#include "gui/gui_util.h"
|
||||
#include "locale/langs.h"
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec4;
|
||||
@ -41,7 +42,7 @@ void show_content_missing(GUI* gui, const Content* content, ContentLUT* lut) {
|
||||
PagesControl* menu = gui->getMenu();
|
||||
Panel* panel = new Panel(vec2(500, 200), vec4(8.0f), 8.0f);
|
||||
panel->color(vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
panel->add(new Label(L"Content missing!"));
|
||||
panel->add(new Label(langs::get(L"menu.missing-content")));
|
||||
|
||||
Panel* subpanel = new Panel(vec2(500, 100));
|
||||
subpanel->color(vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
@ -67,7 +68,7 @@ void show_content_missing(GUI* gui, const Content* content, ContentLUT* lut) {
|
||||
subpanel->maxLength(400);
|
||||
panel->add(subpanel);
|
||||
|
||||
panel->add((new Button(L"Back to Main Menu", vec4(8.0f)))->listenAction([=](GUI*){
|
||||
panel->add((new Button(langs::get(L"menu.back-to-menu"), vec4(8.0f)))->listenAction([=](GUI*){
|
||||
menu->back();
|
||||
}));
|
||||
panel->refresh();
|
||||
@ -97,7 +98,7 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) {
|
||||
Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f);
|
||||
panel->color(vec4(0.0f));
|
||||
|
||||
panel->add(guiutil::gotoButton(L"New World", "new-world", menu));
|
||||
panel->add(guiutil::gotoButton(langs::get(L"menu.new-world"), "new-world", menu));
|
||||
|
||||
Panel* worldsPanel = new Panel(vec2(390, 200), vec4(5.0f));
|
||||
worldsPanel->color(vec4(1.0f, 1.0f, 1.0f, 0.07f));
|
||||
@ -135,8 +136,8 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) {
|
||||
}
|
||||
}
|
||||
panel->add(worldsPanel);
|
||||
panel->add(guiutil::gotoButton(L"Settings", "settings", menu));
|
||||
panel->add((new Button(L"Quit", vec4(10.f)))->listenAction([](GUI* gui) {
|
||||
panel->add(guiutil::gotoButton(langs::get(L"menu.settings"), "settings", menu));
|
||||
panel->add((new Button(langs::get(L"menu.quit"), vec4(10.f)))->listenAction([](GUI* gui) {
|
||||
Window::setShouldClose(true);
|
||||
}));
|
||||
panel->refresh();
|
||||
@ -149,7 +150,7 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) {
|
||||
|
||||
TextBox* worldNameInput;
|
||||
{
|
||||
Label* label = new Label(L"World Name");
|
||||
Label* label = new Label(langs::get(L"world.name"));
|
||||
panel->add(label);
|
||||
|
||||
TextBox* input = new TextBox(L"New World", vec4(6.0f));
|
||||
@ -159,7 +160,7 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) {
|
||||
|
||||
TextBox* seedInput;
|
||||
{
|
||||
Label* label = new Label(L"Seed");
|
||||
Label* label = new Label(langs::get(L"world.seed"));
|
||||
panel->add(shared_ptr<UINode>(label));
|
||||
|
||||
uint64_t randseed = rand() ^ (rand() << 8) ^
|
||||
@ -173,7 +174,7 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) {
|
||||
}
|
||||
|
||||
{
|
||||
Button* button = new Button(L"Create World", vec4(10.0f));
|
||||
Button* button = new Button(langs::get(L"world.create"), vec4(10.0f));
|
||||
button->margin(vec4(1, 20, 1, 1));
|
||||
vec4 basecolor = worldNameInput->color();
|
||||
button->listenAction([=](GUI*) {
|
||||
@ -239,7 +240,7 @@ Panel* create_controls_panel(Engine* engine, PagesControl* menu) {
|
||||
std::wstringstream ss;
|
||||
ss << std::fixed << std::setprecision(1);
|
||||
ss << engine->getSettings().camera.sensitivity;
|
||||
return L"Mouse Sensitivity: "+ss.str();
|
||||
return langs::get(L"mouse.sensitivity")+L": "+ss.str();
|
||||
}));
|
||||
|
||||
TrackBar* trackbar = new TrackBar(0.1, 10.0, 2.0, 0.1, 4);
|
||||
@ -264,7 +265,7 @@ Panel* create_controls_panel(Engine* engine, PagesControl* menu) {
|
||||
|
||||
InputBindBox* bindbox = new InputBindBox(entry.second);
|
||||
subpanel->add(bindbox);
|
||||
Label* label = new Label(util::str2wstr_utf8(bindname));
|
||||
Label* label = new Label(langs::get(util::str2wstr_utf8(bindname)));
|
||||
label->margin(vec4(6.0f));
|
||||
subpanel->add(label);
|
||||
scrollPanel->add(subpanel);
|
||||
@ -282,7 +283,7 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
|
||||
/* Load Distance setting track bar */{
|
||||
panel->add((new Label(L""))->textSupplier([=]() {
|
||||
return L"Load Distance: " +
|
||||
return langs::get(L"chunks.load-distance")+L": " +
|
||||
std::to_wstring(engine->getSettings().chunks.loadDistance);
|
||||
}));
|
||||
|
||||
@ -298,7 +299,7 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
|
||||
/* Load Speed setting track bar */{
|
||||
panel->add((new Label(L""))->textSupplier([=]() {
|
||||
return L"Load Speed: " +
|
||||
return langs::get(L"chunks.load-speed")+L": " +
|
||||
std::to_wstring(engine->getSettings().chunks.loadSpeed);
|
||||
}));
|
||||
|
||||
@ -317,7 +318,7 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
std::wstringstream ss;
|
||||
ss << std::fixed << std::setprecision(1);
|
||||
ss << engine->getSettings().graphics.fogCurve;
|
||||
return L"Fog Curve: " + ss.str();
|
||||
return langs::get(L"graphics.fog-curve")+L": " + ss.str();
|
||||
}));
|
||||
|
||||
TrackBar* trackbar = new TrackBar(1.0, 6.0, 1.0, 0.1, 2);
|
||||
@ -333,7 +334,7 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
/* Fov setting track bar */{
|
||||
panel->add((new Label(L""))->textSupplier([=]() {
|
||||
int fov = (int)engine->getSettings().camera.fov;
|
||||
return L"FOV: "+std::to_wstring(fov)+L"°";
|
||||
return langs::get(L"camera.fov")+L": "+std::to_wstring(fov)+L"°";
|
||||
}));
|
||||
|
||||
TrackBar* trackbar = new TrackBar(30.0, 120.0, 90, 1, 4);
|
||||
@ -360,7 +361,7 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
engine->getSettings().display.swapInterval = checked;
|
||||
});
|
||||
checkpanel->add(checkbox);
|
||||
checkpanel->add(new Label(L"V-Sync"));
|
||||
checkpanel->add(new Label(langs::get(L"display.vsync")));
|
||||
|
||||
panel->add(checkpanel);
|
||||
}
|
||||
@ -379,12 +380,12 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) {
|
||||
engine->getSettings().graphics.backlight = checked;
|
||||
});
|
||||
checkpanel->add(checkbox);
|
||||
checkpanel->add(new Label(L"Backlight"));
|
||||
checkpanel->add(new Label(langs::get(L"graphics.backlight")));
|
||||
|
||||
panel->add(checkpanel);
|
||||
}
|
||||
|
||||
panel->add(guiutil::gotoButton(L"Controls", "controls", menu));
|
||||
panel->add(guiutil::gotoButton(langs::get(L"menu.controls"), "controls", menu));
|
||||
panel->add(guiutil::backButton(menu));
|
||||
panel->refresh();
|
||||
return panel;
|
||||
@ -394,15 +395,15 @@ Panel* create_pause_panel(Engine* engine, PagesControl* menu) {
|
||||
Panel* panel = new Panel(vec2(400, 200));
|
||||
panel->color(vec4(0.0f));
|
||||
{
|
||||
Button* button = new Button(L"Continue", vec4(10.0f));
|
||||
Button* button = new Button(langs::get(L"Continue"), vec4(10.0f));
|
||||
button->listenAction([=](GUI*){
|
||||
menu->reset();
|
||||
});
|
||||
panel->add(shared_ptr<UINode>(button));
|
||||
}
|
||||
panel->add(guiutil::gotoButton(L"Settings", "settings", menu));
|
||||
panel->add(guiutil::gotoButton(langs::get(L"Settings"), "settings", menu));
|
||||
{
|
||||
Button* button = new Button(L"Save and Quit to Menu", vec4(10.f));
|
||||
Button* button = new Button(langs::get(L"menu.save-and-quit"), vec4(10.f));
|
||||
button->listenAction([engine](GUI*){
|
||||
engine->setScreen(shared_ptr<Screen>(new MenuScreen(engine)));
|
||||
});
|
||||
|
||||
@ -61,12 +61,17 @@ struct DebugSettings {
|
||||
bool doWriteLights = true;
|
||||
};
|
||||
|
||||
struct UiSettings {
|
||||
std::string language = "auto";
|
||||
};
|
||||
|
||||
struct EngineSettings {
|
||||
DisplaySettings display;
|
||||
ChunksSettings chunks;
|
||||
CameraSettings camera;
|
||||
GraphicsSettings graphics;
|
||||
DebugSettings debug;
|
||||
UiSettings ui;
|
||||
};
|
||||
|
||||
#endif // SRC_SETTINGS_H_
|
||||
@ -20,6 +20,15 @@ path platform::get_controls_file() {
|
||||
return path(CONTROLS_FILE);
|
||||
}
|
||||
|
||||
std::string platform::detect_locale() {
|
||||
// TODO: implement
|
||||
std::string name = setlocale(LC_ALL, nullptr);
|
||||
if (name.find("ru_RU") != std::string::npos) {
|
||||
return "ru_RU";
|
||||
}
|
||||
return "en_US";
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ namespace platform {
|
||||
extern void configure_encoding();
|
||||
extern std::filesystem::path get_settings_file();
|
||||
extern std::filesystem::path get_controls_file();
|
||||
extern std::string detect_locale();
|
||||
}
|
||||
|
||||
#endif // UTIL_PLATFORM_H_
|
||||
Loading…
x
Reference in New Issue
Block a user