mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Localization system for Voxygen
- Added a localization system in voxygen - Support English and French languages - Added a configuration option in the interface settings to change the language
This commit is contained in:
parent
ec0692249a
commit
a6f9f533a5
@ -30,6 +30,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Added randomly selected Loading Screen background images
|
||||
- Added options to disable clouds and to use cheaper water rendering
|
||||
- Added client-side character saving
|
||||
- Added a localization system to provide multi-language support
|
||||
to voxygen
|
||||
- Added French language for Voxygen
|
||||
|
||||
### Changed
|
||||
|
||||
|
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -760,6 +760,11 @@ dependencies = [
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deunicode"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "2.0.2"
|
||||
@ -3251,6 +3256,7 @@ dependencies = [
|
||||
"cpal 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deunicode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dispatch 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3654,6 +3660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum daggy 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9293a0da7d1bc1f30090ece4d9f9de79a07be7302ddb00e5eb1fefb6ee6409e2"
|
||||
"checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4"
|
||||
"checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a"
|
||||
"checksum deunicode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a0f5bbdedde60605d0719b998e282af68e2b1c50203110211fe4abe857560"
|
||||
"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
|
||||
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
|
337
assets/voxygen/i18n/en.ron
Normal file
337
assets/voxygen/i18n/en.ron
Normal file
@ -0,0 +1,337 @@
|
||||
/// Translation document instructions
|
||||
///
|
||||
/// In order to keep localization documents readible please follow the following
|
||||
/// rules:
|
||||
/// - separate the string map sections using a commentary describing the purpose
|
||||
/// of the next section
|
||||
/// - prepend multi-line strings with a commentary
|
||||
/// - append one blank lines after a multi-line strings and two after sections
|
||||
///
|
||||
/// To add a new language in Veloren, just write an additional `.ron` file in
|
||||
/// `assets/voxygen/i18n` and that's it!
|
||||
|
||||
/// Localization for "global" English
|
||||
VoxygenLocalization(
|
||||
metadata: (
|
||||
language_name: "English",
|
||||
language_identifier: "en",
|
||||
),
|
||||
convert_utf8_to_ascii: false,
|
||||
string_map: {
|
||||
/// Start Common section
|
||||
// Texts used in multiple locations with the same formatting
|
||||
"common.username": "username",
|
||||
"common.singleplayer": "Singleplayer",
|
||||
"common.multiplayer": "Multiplayer",
|
||||
"common.servers": "Servers",
|
||||
"common.quit": "Quit",
|
||||
"common.settings": "Settings",
|
||||
"common.languages": "Languages",
|
||||
"common.interface": "Interface",
|
||||
"common.gameplay": "Gameplay",
|
||||
"common.controls": "Controls",
|
||||
"common.video": "Video",
|
||||
"common.sound": "Sound",
|
||||
"common.resume": "Resume",
|
||||
"common.characters": "Characters",
|
||||
"common.close": "Close",
|
||||
"common.yes": "Yes",
|
||||
"common.no": "No",
|
||||
"common.back": "Back",
|
||||
"common.create": "Create",
|
||||
"common.okay": "Okay",
|
||||
"common.disclaimer": "Disclaimer",
|
||||
"common.cancel": "Cancel",
|
||||
"common.none": "None",
|
||||
|
||||
// Message when connection to the server is lost
|
||||
"common.connection_lost": r#"Connection lost!
|
||||
Did the server restart?
|
||||
Is the client up to date?"#,
|
||||
|
||||
|
||||
"common.races.orc": "Orc",
|
||||
"common.races.human": "Human",
|
||||
"common.races.dwarf": "Dwarf",
|
||||
"common.races.elf": "Elf",
|
||||
"common.races.undead": "Undead",
|
||||
"common.races.danari": "Danari",
|
||||
|
||||
"common.weapons.axe": "Axe",
|
||||
"common.weapons.sword": "Sword",
|
||||
"common.weapons.staff": "Staff",
|
||||
"common.weapons.bow": "Bow",
|
||||
"common.weapons.hammer": "Hammer",
|
||||
/// End Common section
|
||||
|
||||
|
||||
/// Start Main screen section
|
||||
"main.connecting": "Connecting",
|
||||
"main.creating_world": "Creating world",
|
||||
|
||||
// Welcome notice that appears the first time Veloren is started
|
||||
"main.notice": r#"Welcome to the alpha version of Veloren!
|
||||
|
||||
Before you dive into the fun, please keep a few things in mind:
|
||||
|
||||
- This is a very early alpha. Expect bugs, extremely unfinished gameplay, unpolished mechanics, and missing features.
|
||||
- If you have constructive feedback or bug reports, you can contact us via Reddit, GitLab, or our community Discord server.
|
||||
- Veloren is licensed under the GPL 3 open-source licence. That means you're free to play, modify, and redistribute the game however you wish (provided derived work is also under GPL 3).
|
||||
- Veloren is a non-profit community project, and everybody working on it is a volunteer.
|
||||
If you like what you see, you're welcome to join the development or art teams!
|
||||
- 'Voxel RPG' is a genre in its own right. First-person shooters used to be called Doom clones.
|
||||
|
||||
Like them, we're trying to build a niche. This game is not a clone, and its development will diverge from existing games in the future.
|
||||
|
||||
Thanks for taking the time to read this notice, we hope you enjoy the game!
|
||||
|
||||
~ The Veloren Devs"#,
|
||||
|
||||
// Login process description
|
||||
"main.login_process": r#"Information on the Login Process:
|
||||
|
||||
The name you put in will be your character name ingame.
|
||||
|
||||
Character names and appearances will be saved on your computer.
|
||||
|
||||
Levels/Items are not saved yet."#,
|
||||
|
||||
|
||||
/// End Main screen section
|
||||
|
||||
|
||||
/// Start HUD Section
|
||||
"hud.do_not_show_on_startup": "Don't show this on Startup",
|
||||
"hud.show_tips": "Show Tips",
|
||||
"hud.quests": "Quests",
|
||||
"hud.you_died": "You Died",
|
||||
|
||||
"hud.press_key_to_show_keybindings_fmt": "Press {key} to show keybindings",
|
||||
"hud.press_key_to_show_debug_info_fmt": "Press {key} to show debug info",
|
||||
"hud.press_key_to_toggle_keybindings_fmt": "Press {key} to toogle keybindings",
|
||||
"hud.press_key_to_toggle_debug_info_fmt": "Press {key} to toogle debug info",
|
||||
|
||||
// Respawn message
|
||||
"hud.press_key_to_respawn": r#"Press {key} to respawn at your Waypoint.
|
||||
|
||||
Press Enter, type in /waypoint and confirm to set it here."#,
|
||||
|
||||
// Welcome message
|
||||
"hud.welcome": r#"Welcome to the Veloren Alpha!,
|
||||
|
||||
|
||||
Some tips before you start:
|
||||
|
||||
|
||||
MOST IMPORTANTLY: To set your respawn point type /waypoint into the chat.
|
||||
|
||||
This can also be done when you are already dead!
|
||||
|
||||
|
||||
Press F1 to see the available key commands.
|
||||
|
||||
Type /help into the chat to see chat commands
|
||||
|
||||
|
||||
There are chests and other objects randomly spawning in the World!
|
||||
|
||||
Right-Click to collect them.
|
||||
|
||||
To actually use whatever you loot from those chests open your inventory with 'B'.
|
||||
|
||||
Double click the items in your bag to use or equip them.
|
||||
|
||||
Throw them away by clicking them once and clicking outside of the bag
|
||||
|
||||
|
||||
Nights can get pretty dark in Veloren.
|
||||
|
||||
Light your lantern by typing /lantern into the chat
|
||||
|
||||
|
||||
Want to free your cursor to close this window? Press TAB!
|
||||
|
||||
|
||||
Enjoy your stay in the World of Veloren."#,
|
||||
|
||||
"hud.settings.general": "General",
|
||||
"hud.settings.help_window": "Help Window",
|
||||
"hud.settings.debug_info": "Debug Info",
|
||||
"hud.settings.tips_on_startup": "Tips-On-Startup",
|
||||
"hud.settings.ui_scale": "UI-Scale",
|
||||
"hud.settings.relative_scaling": "Relative Scaling",
|
||||
"hud.settings.custom_scaling": "Custom Scaling",
|
||||
"hud.settings.crosshair": "Crosshair",
|
||||
"hud.settings.transparency": "Transparency",
|
||||
"hud.settings.hotbar": "Hotbar",
|
||||
"hud.settings.toggle_bar_experience": "Toggle Experience Bar",
|
||||
"hud.settings.toggle_shortcuts": "Toggle Shortcuts",
|
||||
"hud.settings.toggle_bar_experience": "Toggle Shortcuts",
|
||||
"hud.settings.scrolling_combat_text": "Scrolling Combat Text",
|
||||
"hud.settings.single_damage_number": "Single Damage Numbers",
|
||||
"hud.settings.cumulated_damage": "Cumulated Damage",
|
||||
"hud.settings.incoming_damage": "Incoming Damage",
|
||||
"hud.settings.cumulated_incoming_damage": "Cumulated Incoming Damage",
|
||||
"hud.settings.energybar_numbers": "Energybar Numbers",
|
||||
"hud.settings.values": "Values",
|
||||
"hud.settings.percentages": "Percentages",
|
||||
"hud.settings.chat": "Chat",
|
||||
"hud.settings.background_transparency": "Background Transparency",
|
||||
|
||||
"hud.settings.pan_sensitivity": "Pan Sensitivity",
|
||||
"hud.settings.zoom_sensitivity": "Zoom Sensitivity",
|
||||
"hud.settings.invert_scroll_zoom": "Invert Scroll Zoom",
|
||||
"hud.settings.invert_mouse_y_axis": "Invert Mouse Y Axis",
|
||||
|
||||
"hud.settings.view_distance": "View Distance",
|
||||
"hud.settings.maximum_fps": "Maximum FPS",
|
||||
"hud.settings.fov": "Field of View (deg)",
|
||||
"hud.settings.antialiasing_mode": "AntiAliasing Mode",
|
||||
"hud.settings.cloud_rendering_mode": "Cloud Rendering Mode",
|
||||
"hud.settings.fluid_rendering_mode": "Fluid Rendering Mode",
|
||||
"hud.settings.fluid_rendering_mode.cheap": "Cheap",
|
||||
"hud.settings.fluid_rendering_mode.shiny": "Shiny",
|
||||
"hud.settings.cloud_rendering_mode.regular": "Regular",
|
||||
|
||||
"hud.settings.music_volume": "Music Volume",
|
||||
"hud.settings.sound_effect_volume": "Sound Effects Volume",
|
||||
"hud.settings.audio_device": "Audio Device",
|
||||
|
||||
// Control list
|
||||
"hud.settings.control_names": r#"Free Cursor
|
||||
Toggle Help Window
|
||||
Toggle Interface
|
||||
Toggle FPS and Debug Info
|
||||
Take Screenshot
|
||||
Toggle Nametags
|
||||
Toggle Fullscreen
|
||||
|
||||
|
||||
Move Forward
|
||||
Move Left
|
||||
Move Right
|
||||
Move Backwards
|
||||
|
||||
Jump
|
||||
|
||||
Glider
|
||||
|
||||
Dodge
|
||||
|
||||
Roll
|
||||
|
||||
Climb
|
||||
|
||||
Climb down
|
||||
|
||||
Auto Walk
|
||||
|
||||
Sheathe/Draw Weapons
|
||||
|
||||
Put on/Remove Helmet
|
||||
|
||||
Sit
|
||||
|
||||
Mount
|
||||
|
||||
Interact
|
||||
|
||||
|
||||
Basic Attack
|
||||
Secondary Attack/Block/Aim
|
||||
|
||||
|
||||
Skillbar Slot 1
|
||||
Skillbar Slot 2
|
||||
Skillbar Slot 3
|
||||
Skillbar Slot 4
|
||||
Skillbar Slot 5
|
||||
Skillbar Slot 6
|
||||
Skillbar Slot 7
|
||||
Skillbar Slot 8
|
||||
Skillbar Slot 9
|
||||
Skillbar Slot 10
|
||||
|
||||
|
||||
Pause Menu
|
||||
Settings
|
||||
Social
|
||||
Map
|
||||
Spellbook
|
||||
Character
|
||||
Questlog
|
||||
Bag
|
||||
|
||||
|
||||
|
||||
Send Chat Message
|
||||
Scroll Chat
|
||||
|
||||
|
||||
Chat commands:
|
||||
|
||||
/alias [Name] - Change your Chat Name
|
||||
/tp [Name] - Teleports you to another player
|
||||
/jump <dx> <dy> <dz> - Offset your position
|
||||
/goto <x> <y> <z> - Teleport to a position
|
||||
/kill - Kill yourself
|
||||
/pig - Spawn pig NPC
|
||||
/wolf - Spawn wolf NPC
|
||||
/help - Display chat commands"#,
|
||||
|
||||
"hud.social": "Social",
|
||||
"hud.social.online": "Online",
|
||||
"hud.social.friends": "Friends",
|
||||
"hud.social.not_yet_available": "Not yet available",
|
||||
"hud.social.Faction": "Faction",
|
||||
"hud.social.play_online_fmt": "{nb_player} player(s) online",
|
||||
|
||||
"hud.spell": "Spell",
|
||||
/// End HUD section
|
||||
|
||||
|
||||
/// Start chracter selection section
|
||||
"char_selection.delete_permanently": "Permanently delete this Character?",
|
||||
"char_selection.change_server": "Change Server",
|
||||
"char_selection.enter_world": "Enter World",
|
||||
"char_selection.logout": "Logout",
|
||||
"char_selection.create_new_charater": "Create New Character",
|
||||
"char_selection.character_creation": "Character Creation",
|
||||
|
||||
"char_selection.human_default": "Human Default",
|
||||
"char_selection.level_fmt": "Level {level_nb}",
|
||||
"char_selection.uncanny_valley": "Uncanny Valley",
|
||||
"char_selection.plains_of_uncertainty": "Plains of Uncertainty",
|
||||
"char_selection.beard": "Beard",
|
||||
"char_selection.hair_style": "Beard",
|
||||
"char_selection.hair_color": "Beard",
|
||||
"char_selection.chest_color": "Chest color",
|
||||
"char_selection.eye_color": "Eye color",
|
||||
"char_selection.skin": "Skin",
|
||||
"char_selection.eyebrows": "Eyebrows",
|
||||
"char_selection.accessories": "Accessories",
|
||||
|
||||
/// End chracter selection section
|
||||
|
||||
|
||||
/// Start character window section
|
||||
"character_window.character_name": "Character Name",
|
||||
// Charater stats
|
||||
"character_window.character_stats": r#"Stamina
|
||||
|
||||
Strength
|
||||
|
||||
Dexterity
|
||||
|
||||
Intelligence"#,
|
||||
|
||||
|
||||
/// Start character window section
|
||||
|
||||
|
||||
/// Start Escape Menu Section
|
||||
"esc_menu.logout": "Logout",
|
||||
"esc_menu.quit_game": "Quit Game",
|
||||
/// End Escape Menu Section
|
||||
}
|
||||
)
|
303
assets/voxygen/i18n/fr_FR.ron
Normal file
303
assets/voxygen/i18n/fr_FR.ron
Normal file
@ -0,0 +1,303 @@
|
||||
/// Localization for French (France locale)
|
||||
VoxygenLocalization(
|
||||
metadata: (
|
||||
language_name: "Français",
|
||||
language_identifier: "fr_FR",
|
||||
),
|
||||
convert_utf8_to_ascii: true,
|
||||
string_map: {
|
||||
// Common texts used in multiple locations
|
||||
"common.username": "pseudo",
|
||||
"common.singleplayer": "Solo",
|
||||
"common.multiplayer": "Multijoueur",
|
||||
"common.servers": "Serveurs",
|
||||
"common.quit": "Quitter",
|
||||
"common.settings": "Paramètres",
|
||||
"common.languages": "Langues",
|
||||
"common.interface": "Interface",
|
||||
"common.gameplay": "Gameplay",
|
||||
"common.controls": "Controles",
|
||||
"common.video": "Video",
|
||||
"common.sound": "Audio",
|
||||
"common.resume": "Reprendre",
|
||||
"common.characters": "Personages",
|
||||
"common.close": "Fermer",
|
||||
"common.create": "Créer",
|
||||
"common.back": "Retour",
|
||||
"common.yes": "Oui",
|
||||
"common.no": "Non",
|
||||
"common.okay": "Compris",
|
||||
"common.cancel": "Annuler",
|
||||
"common.none": "Aucun",
|
||||
|
||||
"common.races.orc": "Orc",
|
||||
"common.races.human": "Humain",
|
||||
"common.races.dwarf": "Nain",
|
||||
"common.races.elf": "Elfe",
|
||||
"common.races.undead": "Mort vivant",
|
||||
"common.races.danari": "Danari",
|
||||
|
||||
"common.weapons.axe": "Hâche",
|
||||
"common.weapons.sword": "Épée",
|
||||
"common.weapons.staff": "Bâton",
|
||||
"common.weapons.bow": "Arc",
|
||||
"common.weapons.hammer": "Marteau",
|
||||
|
||||
// Message when connection to the server is lost
|
||||
"common.connection_lost": r#"Connexion perdue!
|
||||
Le serveur a-il redémarré?
|
||||
Le client est-il à jour?"#,
|
||||
|
||||
|
||||
// Main screen texts
|
||||
"main.connecting": "Connexion",
|
||||
"main.creating_world": "Création du monde",
|
||||
"main.notice": r#"Bienvenue dans la version alpha de Veloren!
|
||||
|
||||
Avant de commencer à vous amuser, merci de garder les choses suivantes en tête:
|
||||
|
||||
- Il s'agit d'une version alpha très jeune. Attendez-vous à des bugs, un gameplay non terminé, des mécaniques non peaufinées et des fonctionalités manquantes.
|
||||
- Si vous avez des retours constructifs ou avez detecté un bug, vous pouvez nous contacter via Reddit, GitLab ou notre communauté Discord.
|
||||
- Veloren est un logiciel open-source sour licence GPL3. Cela signifit que vous êtes libre de jouer, modfier et redistribuer le jeu comme il vous semble (licence contaminante sous GPL 3 pour toute modification)
|
||||
- Veloren est un projet communautaire à but non-lucratif développé par des bénévolles.
|
||||
Si vous apprecier ce jeu, vous êtes les bienvenues pour rejoindre les équipes de développement ou d'artistes!
|
||||
- Le genre 'Voxel RPG' est un genre à part entiere. Les FPS étaient appelé Doom-like. De la même façon, nous essayons de construire un genre à part entière. Ce jeu n'est pas un clone et ses mechaniques changeront au cours du developpement.
|
||||
|
||||
Merci d'avoir pris le temps de lire cette notice, nous esperons que vous apprecierez le jeu!
|
||||
|
||||
~ L'équipe de Veloren"#,
|
||||
|
||||
|
||||
"main.login_process": r#"Information sur la procédure de connexion:
|
||||
|
||||
L'identifiant de connexion sera votre pseudo en jeu.
|
||||
|
||||
Le nom et l'apparence que vous choisirez seront
|
||||
sauvegardés sur votre ordinateur.
|
||||
|
||||
Les niveaux/objets ne sont pas sauvegardés."#,
|
||||
|
||||
|
||||
// HUD texts
|
||||
"hud.you_died": "Vous êtes mort",
|
||||
"hud.do_not_show_on_startup": "Ne pas afficher au démarage",
|
||||
"hud.press_key_to_show_keybindings_fmt": "Appuyer sur {key} pour afficher les contrôles",
|
||||
"hud.settings.toggle_shortcuts": "Activer les raccourcis",
|
||||
"hud.show_tips": "Voir les astuces",
|
||||
"hud.quests": "Quêtes",
|
||||
"hud.spell": "Sorts",
|
||||
"hud.press_key_to_toggle_debug_info_fmt": "Appuyer sur {key} pour activer les informations de debogage",
|
||||
"hud.press_key_to_show_debug_info_fmt": "Appuyer sur {key} pour afficher les informations de debogage",
|
||||
"hud.press_key_to_toggle_keybindings_fmt": "Appuyer sur {key} pour afficher les contrôles",
|
||||
|
||||
|
||||
/// Respawn message
|
||||
"hud.press_key_to_respawn": r#"Appuyer sur {key} pour revivre à votre point de repère.
|
||||
|
||||
Appuyez sur Entrée, taper /waypoint pour configurer le point de repère à l'endroit actuel"#,
|
||||
|
||||
|
||||
/// Welcome message
|
||||
"hud.welcome": r#"Bienvenue dans la version Alpha de Veloren!
|
||||
|
||||
|
||||
Quelques astuces avant de démarrer:
|
||||
|
||||
|
||||
POINT LE PLUS IMPORTANT: Pour configurer votre point de resurection tapez
|
||||
/waypoint dans le chat. (y-compris si vous être déjà mort!)
|
||||
|
||||
|
||||
Appuyer sur F1 pour voir les commandes disponibles.
|
||||
|
||||
Tapez /help dans le chat pour voir les commandes du chat.
|
||||
|
||||
|
||||
Des coffres et autres objets sont disposés aléatoirement dans le monde!
|
||||
|
||||
Utilisez le click droit pour le collecter.
|
||||
|
||||
Pour utilisez ce que vous ramassez des coffres, ouvrez votre inventaire avec 'B'.
|
||||
|
||||
Double cliquez sur les éléments de votre sac pour les utiliser ou les équiper.
|
||||
|
||||
Jettez-les en cliquant sur un element puis en cliquant en dehors du sac.
|
||||
|
||||
Les nuits peuvent être très sombre à Veloren.
|
||||
|
||||
Allumez votre lanterne en tapant /lantern dans le chat.
|
||||
|
||||
Vous souhaitez libérer votre souris pour fermer cette fenêtre? Tapez sur TAB!
|
||||
|
||||
Profitez de votre séjour dans le monde de Veloren."#,
|
||||
|
||||
"hud.settings.general": "Général",
|
||||
"hud.settings.help_window": "Fenêtre d'aide",
|
||||
"hud.settings.debug_info": "Information de débogage",
|
||||
"hud.settings.tips_on_startup": "Astuces au démarrage",
|
||||
|
||||
"hud.settings.ui_scale": "Echelle de l'interface",
|
||||
"hud.settings.relative_scaling": "Echelle relative",
|
||||
"hud.settings.custom_scaling": "Echelle personalisée",
|
||||
|
||||
"hud.settings.crosshair": "Réticule",
|
||||
"hud.settings.transparency": "Transparence",
|
||||
"hud.settings.hotbar": "Barre active",
|
||||
"hud.settings.toggle_bar_experience": "Activer la barre d'experience",
|
||||
|
||||
"hud.settings.scrolling_combat_text": "Texte de combat défillant",
|
||||
"hud.settings.single_damage_number": "Dégat adversaire (par dégat)",
|
||||
"hud.settings.cumulated_damage": "Dégat adversaire (cumulé)",
|
||||
"hud.settings.incoming_damage": "Dégat personnage (par dégat)",
|
||||
"hud.settings.cumulated_incoming_damage": "Dégat personnage (cumulé)",
|
||||
|
||||
"hud.settings.energybar_numbers": "Nombre des barres d'energie",
|
||||
"hud.settings.none": "Aucuns",
|
||||
"hud.settings.values": "Valeurs",
|
||||
"hud.settings.percentages": "Pourcentages",
|
||||
|
||||
"hud.settings.chat": "Tchat",
|
||||
"hud.settings.background_transparency": "Transparence du fond",
|
||||
|
||||
"hud.settings.pan_sensitivity": "Sensibilité de la souris",
|
||||
"hud.settings.zoom_sensitivity": "Sensibilité du zoom",
|
||||
"hud.settings.invert_scroll_zoom": "Inverser la molette",
|
||||
"hud.settings.invert_mouse_y_axis": "Inverser l'axe Y",
|
||||
|
||||
"hud.settings.view_distance": "Distance d'affichage",
|
||||
"hud.settings.maximum_fps": "Limite FPS",
|
||||
"hud.settings.fov": "Champs de vision (FOV)",
|
||||
"hud.settings.antialiasing_mode": "Mode anticrénelage",
|
||||
"hud.settings.cloud_rendering_mode": "Rendu des nuages",
|
||||
"hud.settings.fluid_rendering_mode": "Rendu des fluides",
|
||||
"hud.settings.fluid_rendering_mode.cheap": "Rapide",
|
||||
"hud.settings.fluid_rendering_mode.shiny": "Qualité",
|
||||
"hud.settings.cloud_rendering_mode.regular": "Normal",
|
||||
|
||||
"hud.settings.music_volume": "Volume de la musique",
|
||||
"hud.settings.sound_effect_volume": "Volume des effets",
|
||||
"hud.settings.audio_device": "Périphérique audio",
|
||||
|
||||
"hud.settings.control_names": r#"Libérer le curseur
|
||||
Activer la fenêtre d'aide
|
||||
Activer l'interface
|
||||
Activer la fenêtre de débogage
|
||||
Prendre une capture d'écran
|
||||
Activer les noms de personnage
|
||||
Activer le mode plein écran
|
||||
|
||||
|
||||
Avancer
|
||||
Aller à gauche
|
||||
Aller à droite
|
||||
Aller en arriere
|
||||
|
||||
Sauter
|
||||
|
||||
Planer
|
||||
|
||||
Esquiver
|
||||
|
||||
Roullade
|
||||
|
||||
Escalader
|
||||
|
||||
Desescalader
|
||||
|
||||
Marche automatique
|
||||
|
||||
Ranger/Sortir les armes
|
||||
|
||||
Mettre/Enlever le casque
|
||||
|
||||
S'assoir
|
||||
|
||||
Monter
|
||||
|
||||
Intéragir
|
||||
|
||||
|
||||
Attaque basique
|
||||
Attaque secondaire/Bloquer/Viser
|
||||
|
||||
|
||||
Barre de compétence 1
|
||||
Barre de compétence 2
|
||||
Barre de compétence 3
|
||||
Barre de compétence 4
|
||||
Barre de compétence 5
|
||||
Barre de compétence 6
|
||||
Barre de compétence 7
|
||||
Barre de compétence 8
|
||||
Barre de compétence 9
|
||||
Barre de compétence 10
|
||||
|
||||
|
||||
Pause
|
||||
Paramètres
|
||||
Social
|
||||
Carte
|
||||
Livre de sorts
|
||||
Personnages
|
||||
Livre de quêtes
|
||||
Sac à dos
|
||||
|
||||
|
||||
|
||||
Envoyer un message
|
||||
Défiler dans le tchat
|
||||
|
||||
|
||||
Commandes du tchat:
|
||||
|
||||
/alias [Nom] - Changer de nom
|
||||
/tp [Nom] - Se téléporter vers un autre joueur
|
||||
/jump <dx> <dy> <dz> - Sauter à partir de votre position
|
||||
/goto <x> <y> <z> - Se téléporter à une position
|
||||
/kill - Se suicider
|
||||
/pig - Faire aparaitre un cochon PNJ
|
||||
/wolf - Faire aparaitre un loup PNJ
|
||||
/help - Afficher les commandes de tchat"#,
|
||||
|
||||
|
||||
"hud.social": "Social",
|
||||
"hud.social.friends": "Amis",
|
||||
"hud.social.Faction": "Faction",
|
||||
"hud.social.online": "Jeu en ligne",
|
||||
"hud.social.not_yet_available": "Pas encore disponible",
|
||||
"hud.social.play_online_fmt": "{nb_player} joueurs en ligne",
|
||||
"char_selection.change_server": "Changer de serveur",
|
||||
"char_selection.delete_permanently": "Supprimer",
|
||||
|
||||
|
||||
"esc_menu.quit_game": "Quitter le jeu",
|
||||
"esc_menu.logout": "Deconnexion",
|
||||
|
||||
|
||||
"char_selection.beard": "Barbe",
|
||||
"char_selection.hair_style": "Coupe de cheveux",
|
||||
"char_selection.hair_color": "Couleur de cheveux",
|
||||
"char_selection.skin": "Couleur de peau",
|
||||
"char_selection.eyebrows": "Sourcils",
|
||||
"char_selection.eye_color": "Couleur des yeux",
|
||||
"char_selection.accessories": "Accessoires",
|
||||
"char_selection.level_fmt": "Niveau {level_nb}",
|
||||
"char_selection.create_new_charater": "Créer un nouveau personnage",
|
||||
"char_selection.human_default": "Humain par défault",
|
||||
"char_selection.uncanny_valley": "Vallée dérangeante",
|
||||
"char_selection.chest_color": "Couleur du buste",
|
||||
"char_selection.logout": "Se déconnecter",
|
||||
"char_selection.enter_world": "Entrer dans le monde",
|
||||
"char_selection.plains_of_uncertainty": "Plaines de l'incertitude",
|
||||
"char_selection.character_creation": "Création de personnages",
|
||||
|
||||
"character_window.character_name": "Personnage",
|
||||
"character_window.character_stats": r#"Endurance
|
||||
|
||||
Force
|
||||
|
||||
Dexterité
|
||||
|
||||
Intelligence"#,
|
||||
}
|
||||
)
|
@ -63,6 +63,7 @@ hashbrown = { version = "0.6.2", features = ["serde", "nightly"] }
|
||||
chrono = "0.4.9"
|
||||
rust-argon2 = "0.5"
|
||||
bincode = "1.2"
|
||||
deunicode = "1.0"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
dispatch = "0.1.4"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR, XP_COLOR};
|
||||
use crate::i18n::VoxygenLocalization;
|
||||
use common::comp::Stats;
|
||||
use conrod_core::{
|
||||
color,
|
||||
@ -72,18 +73,26 @@ pub struct CharacterWindow<'a> {
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
stats: &'a Stats,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
|
||||
impl<'a> CharacterWindow<'a> {
|
||||
pub fn new(_show: &'a Show, stats: &'a Stats, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
|
||||
pub fn new(
|
||||
_show: &'a Show,
|
||||
stats: &'a Stats,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_show,
|
||||
imgs,
|
||||
fonts,
|
||||
stats,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -144,12 +153,16 @@ impl<'a> Widget for CharacterWindow<'a> {
|
||||
|
||||
// Title
|
||||
// TODO: Use an actual character name.
|
||||
Text::new("Character Name")
|
||||
.mid_top_with_margin_on(state.charwindow_frame, 6.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.charwindow_title, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("character_window.character_name"),
|
||||
)
|
||||
.mid_top_with_margin_on(state.charwindow_frame, 6.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.charwindow_title, ui);
|
||||
|
||||
// Content Alignment
|
||||
Rectangle::fill_with([95.0 * 4.0, 108.0 * 4.0], color::TRANSPARENT)
|
||||
@ -381,13 +394,9 @@ impl<'a> Widget for CharacterWindow<'a> {
|
||||
|
||||
// Stats
|
||||
Text::new(
|
||||
"Stamina\n\
|
||||
\n\
|
||||
Strength\n\
|
||||
\n\
|
||||
Dexterity\n\
|
||||
\n\
|
||||
Intelligence",
|
||||
&self
|
||||
.localized_strings
|
||||
.get("character_window.character_stats"),
|
||||
)
|
||||
.top_left_with_margins_on(state.charwindow_rectangle, 140.0, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
|
@ -1,10 +1,10 @@
|
||||
use super::{img_ids::Imgs, settings_window::SettingsTab, Fonts, TEXT_COLOR};
|
||||
use crate::i18n::VoxygenLocalization;
|
||||
use conrod_core::{
|
||||
widget::{self, Button, Image},
|
||||
widget_ids, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
use super::{img_ids::Imgs, settings_window::SettingsTab, Fonts, TEXT_COLOR};
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
esc_bg,
|
||||
@ -22,15 +22,22 @@ widget_ids! {
|
||||
pub struct EscMenu<'a> {
|
||||
imgs: &'a Imgs,
|
||||
_fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
|
||||
impl<'a> EscMenu<'a> {
|
||||
pub fn new(imgs: &'a Imgs, _fonts: &'a Fonts) -> Self {
|
||||
pub fn new(
|
||||
imgs: &'a Imgs,
|
||||
_fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
imgs,
|
||||
_fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -82,7 +89,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Resume")
|
||||
.label(&self.localized_strings.get("common.resume"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -98,7 +105,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Settings")
|
||||
.label(&self.localized_strings.get("common.settings"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -113,7 +120,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Controls")
|
||||
.label(&self.localized_strings.get("common.controls"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -128,7 +135,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Characters")
|
||||
.label(&self.localized_strings.get("common.characters"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -143,7 +150,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Logout")
|
||||
.label(&self.localized_strings.get("esc_menu.logout"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -158,7 +165,7 @@ impl<'a> Widget for EscMenu<'a> {
|
||||
.w_h(210.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Quit Game")
|
||||
.label(&self.localized_strings.get("esc_menu.quit_game"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(3.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
|
@ -36,6 +36,7 @@ use spell::Spell;
|
||||
|
||||
use crate::{
|
||||
ecs::comp as vcomp,
|
||||
i18n::{i18n_asset_key, LanguageMetadata, VoxygenLocalization},
|
||||
render::{AaMode, CloudMode, Consts, FluidMode, Globals, Renderer},
|
||||
scene::camera::Camera,
|
||||
//settings::ControlSettings,
|
||||
@ -44,7 +45,7 @@ use crate::{
|
||||
GlobalState,
|
||||
};
|
||||
use client::{Client, Event as ClientEvent};
|
||||
use common::{comp, terrain::TerrainChunk, vol::RectRasterableVol};
|
||||
use common::{assets::load_expect, comp, terrain::TerrainChunk, vol::RectRasterableVol};
|
||||
use conrod_core::{
|
||||
image::Id,
|
||||
text::cursor::Index,
|
||||
@ -225,6 +226,7 @@ pub enum Event {
|
||||
DropInventorySlot(usize),
|
||||
Logout,
|
||||
Quit,
|
||||
ChangeLanguage(LanguageMetadata),
|
||||
}
|
||||
|
||||
// TODO: Are these the possible layouts we want?
|
||||
@ -529,6 +531,10 @@ impl Hud {
|
||||
common::util::GIT_VERSION.to_string()
|
||||
);
|
||||
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&global_state.settings.language.selected_language,
|
||||
));
|
||||
|
||||
if self.show.ingame {
|
||||
let ecs = client.state().ecs();
|
||||
let pos = ecs.read_storage::<comp::Pos>();
|
||||
@ -1208,42 +1214,7 @@ impl Hud {
|
||||
}
|
||||
|
||||
// Introduction Text
|
||||
let intro_text: &'static str = "Welcome to the Veloren Alpha!\n\
|
||||
\n\
|
||||
\n\
|
||||
Some tips before you start:\n\
|
||||
\n\
|
||||
\n\
|
||||
MOST IMPORTANTLY: To set your respawn point type /waypoint into the chat.\n\
|
||||
\n\
|
||||
This can also be done when you are already dead!\n\
|
||||
\n\
|
||||
\n\
|
||||
Press F1 to see the available key commands.\n\
|
||||
\n\
|
||||
Type /help into the chat to see chat commands\n\
|
||||
\n\
|
||||
\n\
|
||||
There are chests and other objects randomly spawning in the World!\n\
|
||||
\n\
|
||||
Right-Click to collect them.\n\
|
||||
\n\
|
||||
To actually use whatever you loot from those chests open your inventory with 'B'.\n\
|
||||
\n\
|
||||
Double click the items in your bag to use or equip them.\n\
|
||||
\n\
|
||||
Throw them away by clicking them once and clicking outside of the bag\n\
|
||||
\n\
|
||||
\n\
|
||||
Nights can get pretty dark in Veloren.\n\
|
||||
\n\
|
||||
Light your lantern by typing /lantern into the chat\n\
|
||||
\n\
|
||||
\n\
|
||||
Want to free your cursor to close this window? Press TAB!\n\
|
||||
\n\
|
||||
\n\
|
||||
Enjoy your stay in the World of Veloren.";
|
||||
let intro_text = &localized_strings.get("hud.welcome");
|
||||
if self.show.intro && !self.show.esc_menu && !self.intro_2 {
|
||||
match global_state.settings.gameplay.intro_show {
|
||||
Intro::Show => {
|
||||
@ -1260,7 +1231,7 @@ impl Hud {
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(100.0, 50.0)
|
||||
.mid_bottom_with_margin_on(self.ids.intro_bg, 10.0)
|
||||
.label("Close")
|
||||
.label(&localized_strings.get("common.close"))
|
||||
.label_font_size(20)
|
||||
.label_color(TEXT_COLOR)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
@ -1297,7 +1268,7 @@ impl Hud {
|
||||
{
|
||||
self.never_show = !self.never_show
|
||||
};
|
||||
Text::new("Don't show this on Startup")
|
||||
Text::new(&localized_strings.get("hud.do_not_show_on_startup"))
|
||||
.right_from(self.ids.intro_check, 10.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1343,7 +1314,7 @@ impl Hud {
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(100.0, 50.0)
|
||||
.mid_bottom_with_margin_on(self.ids.intro_bg, 10.0)
|
||||
.label("Close")
|
||||
.label(&localized_strings.get("common.close"))
|
||||
.label_font_size(20)
|
||||
.label_color(TEXT_COLOR)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
@ -1490,20 +1461,28 @@ impl Hud {
|
||||
.set(self.ids.num_figures, ui_widgets);
|
||||
|
||||
// Help Window
|
||||
Text::new(&format!(
|
||||
"Press {:?} to show keybindings",
|
||||
global_state.settings.controls.help
|
||||
))
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_toggle_keybindings_fmt")
|
||||
.replace(
|
||||
"{key}",
|
||||
&format!("{:?}", global_state.settings.controls.help),
|
||||
),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.num_figures, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
.set(self.ids.help_info, ui_widgets);
|
||||
// Info about Debug Shortcut
|
||||
Text::new(&format!(
|
||||
"Press {:?} to toggle debug info",
|
||||
global_state.settings.controls.toggle_debug
|
||||
))
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_toggle_debug_info_fmt")
|
||||
.replace(
|
||||
"{key}",
|
||||
&format!("{:?}", global_state.settings.controls.toggle_debug),
|
||||
),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.help_info, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1511,20 +1490,28 @@ impl Hud {
|
||||
.set(self.ids.debug_info, ui_widgets);
|
||||
} else {
|
||||
// Help Window
|
||||
Text::new(&format!(
|
||||
"Press {:?} to show keybindings",
|
||||
global_state.settings.controls.help
|
||||
))
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_show_keybindings_fmt")
|
||||
.replace(
|
||||
"{key}",
|
||||
&format!("{:?}", global_state.settings.controls.help),
|
||||
),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(16)
|
||||
.set(self.ids.help_info, ui_widgets);
|
||||
// Info about Debug Shortcut
|
||||
Text::new(&format!(
|
||||
"Press {:?} to toggle debug info",
|
||||
global_state.settings.controls.toggle_debug
|
||||
))
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_show_debug_info_fmt")
|
||||
.replace(
|
||||
"{key}",
|
||||
&format!("{:?}", global_state.settings.controls.toggle_debug),
|
||||
),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.help_info, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1563,7 +1550,7 @@ impl Hud {
|
||||
.w_h(120.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Show Tips")
|
||||
.label(&localized_strings.get("hud.show_tips"))
|
||||
.label_font_size(20)
|
||||
.label_color(TEXT_COLOR)
|
||||
.mid_bottom_with_margin_on(self.ids.help, 20.0)
|
||||
@ -1702,8 +1689,14 @@ impl Hud {
|
||||
|
||||
// Settings
|
||||
if let Windows::Settings = self.show.open_windows {
|
||||
for event in SettingsWindow::new(&global_state, &self.show, &self.imgs, &self.fonts)
|
||||
.set(self.ids.settings_window, ui_widgets)
|
||||
for event in SettingsWindow::new(
|
||||
&global_state,
|
||||
&self.show,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&localized_strings,
|
||||
)
|
||||
.set(self.ids.settings_window, ui_widgets)
|
||||
{
|
||||
match event {
|
||||
settings_window::Event::Sct(sct) => {
|
||||
@ -1782,6 +1775,9 @@ impl Hud {
|
||||
settings_window::Event::ChangeFluidMode(new_fluid_mode) => {
|
||||
events.push(Event::ChangeFluidMode(new_fluid_mode));
|
||||
}
|
||||
settings_window::Event::ChangeLanguage(language) => {
|
||||
events.push(Event::ChangeLanguage(language));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1789,10 +1785,11 @@ impl Hud {
|
||||
// Social Window
|
||||
if self.show.social {
|
||||
for event in Social::new(
|
||||
/*&global_state,*/ &self.show,
|
||||
&self.show,
|
||||
client,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&localized_strings,
|
||||
)
|
||||
.set(self.ids.social_window, ui_widgets)
|
||||
{
|
||||
@ -1810,8 +1807,14 @@ impl Hud {
|
||||
let ecs = client.state().ecs();
|
||||
let stats = ecs.read_storage::<comp::Stats>();
|
||||
let player_stats = stats.get(client.entity()).unwrap();
|
||||
match CharacterWindow::new(&self.show, &player_stats, &self.imgs, &self.fonts)
|
||||
.set(self.ids.character_window, ui_widgets)
|
||||
match CharacterWindow::new(
|
||||
&self.show,
|
||||
&player_stats,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&localized_strings,
|
||||
)
|
||||
.set(self.ids.character_window, ui_widgets)
|
||||
{
|
||||
Some(character_window::Event::Close) => {
|
||||
self.show.character_window(false);
|
||||
@ -1823,8 +1826,14 @@ impl Hud {
|
||||
|
||||
// Spellbook
|
||||
if self.show.spell {
|
||||
match Spell::new(&self.show, client, &self.imgs, &self.fonts)
|
||||
.set(self.ids.spell, ui_widgets)
|
||||
match Spell::new(
|
||||
&self.show,
|
||||
client,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&localized_strings,
|
||||
)
|
||||
.set(self.ids.spell, ui_widgets)
|
||||
{
|
||||
Some(spell::Event::Close) => {
|
||||
self.show.spell(false);
|
||||
@ -1836,8 +1845,14 @@ impl Hud {
|
||||
|
||||
// Quest Log
|
||||
if self.show.quest {
|
||||
match Quest::new(&self.show, client, &self.imgs, &self.fonts)
|
||||
.set(self.ids.quest, ui_widgets)
|
||||
match Quest::new(
|
||||
&self.show,
|
||||
client,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&localized_strings,
|
||||
)
|
||||
.set(self.ids.quest, ui_widgets)
|
||||
{
|
||||
Some(quest::Event::Close) => {
|
||||
self.show.quest(false);
|
||||
@ -1868,7 +1883,9 @@ impl Hud {
|
||||
}
|
||||
|
||||
if self.show.esc_menu {
|
||||
match EscMenu::new(&self.imgs, &self.fonts).set(self.ids.esc_menu, ui_widgets) {
|
||||
match EscMenu::new(&self.imgs, &self.fonts, &localized_strings)
|
||||
.set(self.ids.esc_menu, ui_widgets)
|
||||
{
|
||||
Some(esc_menu::Event::OpenSettings(tab)) => {
|
||||
self.show.open_setting_tab(tab);
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR};
|
||||
use crate::i18n::VoxygenLocalization;
|
||||
use client::{self, Client};
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, Button, Image, Rectangle, Text},
|
||||
@ -6,8 +8,6 @@ use conrod_core::{
|
||||
Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
use client::{self, Client};
|
||||
|
||||
widget_ids! {
|
||||
pub struct Ids {
|
||||
quest_frame,
|
||||
@ -25,17 +25,25 @@ pub struct Quest<'a> {
|
||||
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
|
||||
impl<'a> Quest<'a> {
|
||||
pub fn new(show: &'a Show, _client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
|
||||
pub fn new(
|
||||
show: &'a Show,
|
||||
_client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_show: show,
|
||||
imgs,
|
||||
_client,
|
||||
fonts: fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -93,7 +101,7 @@ impl<'a> Widget for Quest<'a> {
|
||||
|
||||
// Title
|
||||
// TODO: Use an actual character name.
|
||||
Text::new("Quest")
|
||||
Text::new(&self.localized_strings.get("hud.quests"))
|
||||
.mid_top_with_margin_on(state.quest_frame, 6.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
|
@ -3,6 +3,7 @@ use super::{
|
||||
TEXT_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
i18n::{list_localizations, LanguageMetadata, VoxygenLocalization},
|
||||
render::{AaMode, CloudMode, FluidMode},
|
||||
ui::{ImageSlider, ScaleMode, ToggleButton},
|
||||
GlobalState,
|
||||
@ -41,6 +42,8 @@ widget_ids! {
|
||||
absolute_scale_text,
|
||||
gameplay,
|
||||
controls,
|
||||
languages,
|
||||
languages_list,
|
||||
rectangle,
|
||||
general_txt,
|
||||
debug_button,
|
||||
@ -48,6 +51,7 @@ widget_ids! {
|
||||
tips_button,
|
||||
tips_button_label,
|
||||
interface,
|
||||
language_text,
|
||||
mouse_pan_slider,
|
||||
mouse_pan_label,
|
||||
mouse_pan_value,
|
||||
@ -146,11 +150,10 @@ pub enum SettingsTab {
|
||||
#[derive(WidgetCommon)]
|
||||
pub struct SettingsWindow<'a> {
|
||||
global_state: &'a GlobalState,
|
||||
|
||||
show: &'a Show,
|
||||
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
@ -161,12 +164,14 @@ impl<'a> SettingsWindow<'a> {
|
||||
show: &'a Show,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
global_state,
|
||||
show,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -205,6 +210,7 @@ pub enum Event {
|
||||
Sct(bool),
|
||||
SctPlayerBatch(bool),
|
||||
SctDamageBatch(bool),
|
||||
ChangeLanguage(LanguageMetadata),
|
||||
}
|
||||
|
||||
pub enum ScaleChange {
|
||||
@ -277,7 +283,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
|
||||
// Title
|
||||
Text::new("Settings")
|
||||
Text::new(&self.localized_strings.get("common.settings"))
|
||||
.mid_top_with_margin_on(state.ids.settings_bg, 5.0)
|
||||
.font_size(14)
|
||||
.color(TEXT_COLOR)
|
||||
@ -301,7 +307,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
self.imgs.settings_button_press
|
||||
})
|
||||
.top_left_with_margins_on(state.ids.settings_l, 8.0 * 4.0, 2.0 * 4.0)
|
||||
.label("Interface")
|
||||
.label(&self.localized_strings.get("common.interface"))
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.interface, ui)
|
||||
@ -317,7 +323,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
let ui_scale = self.global_state.settings.gameplay.ui_scale;
|
||||
let chat_transp = self.global_state.settings.gameplay.chat_transp;
|
||||
|
||||
Text::new("General")
|
||||
Text::new(&self.localized_strings.get("hud.settings.general"))
|
||||
.top_left_with_margins_on(state.ids.settings_content, 5.0, 5.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -340,7 +346,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
events.push(Event::ToggleHelp);
|
||||
}
|
||||
|
||||
Text::new("Help Window")
|
||||
Text::new(&self.localized_strings.get("hud.settings.help_window"))
|
||||
.right_from(state.ids.button_help, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -364,7 +370,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
events.push(Event::ToggleDebug);
|
||||
}
|
||||
|
||||
Text::new("Debug Info")
|
||||
Text::new(&self.localized_strings.get("hud.settings.debug_info"))
|
||||
.right_from(state.ids.debug_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -391,7 +397,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
Intro::Never => events.push(Event::Intro(Intro::Show)),
|
||||
}
|
||||
};
|
||||
Text::new("Tips on Startup")
|
||||
Text::new(&self.localized_strings.get("hud.settings.tips_on_startup"))
|
||||
.right_from(state.ids.tips_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -400,7 +406,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.tips_button_label, ui);
|
||||
|
||||
// Ui Scale
|
||||
Text::new("UI-Scale")
|
||||
Text::new(&self.localized_strings.get("hud.settings.ui_scale"))
|
||||
.down_from(state.ids.tips_button, 20.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -646,13 +652,13 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.graphics_for(state.ids.ch_3_bg)
|
||||
.set(state.ids.crosshair_inner_3, ui);
|
||||
// Crosshair Transparency Text and Slider
|
||||
Text::new("Crosshair")
|
||||
Text::new(&self.localized_strings.get("hud.settings.crosshair"))
|
||||
.down_from(state.ids.absolute_scale_button, 20.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.ch_title, ui);
|
||||
Text::new("Transparency")
|
||||
Text::new(&self.localized_strings.get("hud.settings.transparency"))
|
||||
.right_from(state.ids.ch_3_bg, 20.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -685,7 +691,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.ch_transp_value, ui);
|
||||
|
||||
// Hotbar text
|
||||
Text::new("Hotbar")
|
||||
Text::new(&self.localized_strings.get("hud.settings.hotbar"))
|
||||
.down_from(state.ids.ch_1_bg, 20.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -714,13 +720,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
XpBar::OnGain => events.push(Event::ToggleXpBar(XpBar::Always)),
|
||||
}
|
||||
}
|
||||
Text::new("Toggle Experience Bar")
|
||||
.right_from(state.ids.show_xpbar_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.show_xpbar_button)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.show_xpbar_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.toggle_bar_experience"),
|
||||
)
|
||||
.right_from(state.ids.show_xpbar_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.show_xpbar_button)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.show_xpbar_text, ui);
|
||||
// Show Shortcut Numbers
|
||||
if Button::image(match self.global_state.settings.gameplay.shortcut_numbers {
|
||||
ShortcutNumbers::On => self.imgs.checkbox_checked,
|
||||
@ -748,7 +758,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Text::new("Toggle Shortcuts")
|
||||
Text::new(&self.localized_strings.get("hud.settings.toggle_shortcuts"))
|
||||
.right_from(state.ids.show_shortcuts_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -773,12 +783,16 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
Number Display Duration: 1s ----I----5s
|
||||
*/
|
||||
// SCT/ Scrolling Combat Text
|
||||
Text::new("Scrolling Combat Text")
|
||||
.top_left_with_margins_on(state.ids.settings_content_r, 5.0, 5.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_title, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.scrolling_combat_text"),
|
||||
)
|
||||
.top_left_with_margins_on(state.ids.settings_content_r, 5.0, 5.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_title, ui);
|
||||
// Generally toggle the SCT
|
||||
let show_sct = ToggleButton::new(
|
||||
self.global_state.settings.gameplay.sct,
|
||||
@ -794,13 +808,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
if self.global_state.settings.gameplay.sct != show_sct {
|
||||
events.push(Event::Sct(!self.global_state.settings.gameplay.sct))
|
||||
}
|
||||
Text::new("Scrolling Combat Text")
|
||||
.right_from(state.ids.sct_show_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_show_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_show_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.scrolling_combat_text"),
|
||||
)
|
||||
.right_from(state.ids.sct_show_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_show_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_show_text, ui);
|
||||
if self.global_state.settings.gameplay.sct {
|
||||
// Toggle single damage numbers
|
||||
let show_sct_damage_batch = !ToggleButton::new(
|
||||
@ -814,13 +832,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.sct_single_dmg_radio, ui);
|
||||
|
||||
Text::new("Single Damage Numbers")
|
||||
.right_from(state.ids.sct_single_dmg_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_single_dmg_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_single_dmg_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.single_damage_number"),
|
||||
)
|
||||
.right_from(state.ids.sct_single_dmg_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_single_dmg_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_single_dmg_text, ui);
|
||||
// Toggle Batched Damage
|
||||
let show_sct_damage_batch = ToggleButton::new(
|
||||
show_sct_damage_batch,
|
||||
@ -838,7 +860,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
!self.global_state.settings.gameplay.sct_damage_batch,
|
||||
))
|
||||
}
|
||||
Text::new("Cumulated Damage")
|
||||
Text::new(&self.localized_strings.get("hud.settings.cumulated_damage"))
|
||||
.right_from(state.ids.sct_show_batch_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -857,7 +879,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.sct_inc_dmg_radio, ui);
|
||||
|
||||
Text::new("Incoming Damage")
|
||||
Text::new(&self.localized_strings.get("hud.settings.incoming_damage"))
|
||||
.right_from(state.ids.sct_inc_dmg_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -881,18 +903,22 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
!self.global_state.settings.gameplay.sct_player_batch,
|
||||
))
|
||||
}
|
||||
Text::new("Cumulated Incoming Damage")
|
||||
.right_from(state.ids.sct_batch_inc_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_batch_inc_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_batch_inc_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cumulated_incoming_damage"),
|
||||
)
|
||||
.right_from(state.ids.sct_batch_inc_radio, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.sct_batch_inc_radio)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sct_batch_inc_text, ui);
|
||||
}
|
||||
|
||||
// Energybars Numbers
|
||||
// Hotbar text
|
||||
Text::new("Energybar Numbers")
|
||||
Text::new(&self.localized_strings.get("hud.settings.energybar_numbers"))
|
||||
.down_from(
|
||||
if self.global_state.settings.gameplay.sct {
|
||||
state.ids.sct_batch_inc_radio
|
||||
@ -929,7 +955,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ToggleBarNumbers(BarNumbers::Off))
|
||||
}
|
||||
Text::new("None")
|
||||
Text::new(&self.localized_strings.get("hud.settings.none"))
|
||||
.right_from(state.ids.show_bar_numbers_none_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -960,7 +986,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ToggleBarNumbers(BarNumbers::Values))
|
||||
}
|
||||
Text::new("Values")
|
||||
Text::new(&self.localized_strings.get("hud.settings.values"))
|
||||
.right_from(state.ids.show_bar_numbers_values_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -991,7 +1017,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ToggleBarNumbers(BarNumbers::Percent))
|
||||
}
|
||||
Text::new("Percentages")
|
||||
Text::new(&self.localized_strings.get("hud.settings.percentages"))
|
||||
.right_from(state.ids.show_bar_numbers_percentage_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1000,18 +1026,22 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.show_bar_numbers_percentage_text, ui);
|
||||
|
||||
// Chat Transp
|
||||
Text::new("Chat")
|
||||
Text::new(&self.localized_strings.get("hud.settings.chat"))
|
||||
.down_from(state.ids.show_bar_numbers_percentage_button, 20.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_transp_title, ui);
|
||||
Text::new("Background Transparency")
|
||||
.right_from(state.ids.chat_transp_slider, 20.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_transp_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.background_transparency"),
|
||||
)
|
||||
.right_from(state.ids.chat_transp_slider, 20.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.chat_transp_text, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::continuous(
|
||||
chat_transp,
|
||||
@ -1029,6 +1059,34 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
{
|
||||
events.push(Event::ChatTransp(new_val));
|
||||
}
|
||||
|
||||
Text::new(&self.localized_strings.get("common.languages"))
|
||||
.down_from(state.ids.chat_transp_slider, 20.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.language_text, ui);
|
||||
|
||||
let selected_language = &self.global_state.settings.language.selected_language;
|
||||
let language_list = list_localizations();
|
||||
let language_list_str: Vec<String> = language_list
|
||||
.iter()
|
||||
.map(|e| e.language_name.clone())
|
||||
.collect();
|
||||
let selected = language_list
|
||||
.iter()
|
||||
.position(|x| x.language_identifier.contains(selected_language));
|
||||
|
||||
if let Some(clicked) = DropDownList::new(&language_list_str, selected)
|
||||
.down_from(state.ids.language_text, 8.0)
|
||||
.w_h(200.0, 22.0)
|
||||
.color(MENU_BG)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.set(state.ids.languages_list, ui)
|
||||
{
|
||||
events.push(Event::ChangeLanguage(language_list[clicked].to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Gameplay Tab --------------------------------
|
||||
@ -1049,7 +1107,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
self.imgs.settings_button_press
|
||||
})
|
||||
.right_from(state.ids.interface, 0.0)
|
||||
.label("Gameplay")
|
||||
.label(&self.localized_strings.get("common.gameplay"))
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.gameplay, ui)
|
||||
@ -1064,7 +1122,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
let display_zoom = self.global_state.settings.gameplay.zoom_sensitivity;
|
||||
|
||||
// Mouse Pan Sensitivity
|
||||
Text::new("Pan Sensitivity")
|
||||
Text::new(&self.localized_strings.get("hud.settings.pan_sensitivity"))
|
||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1096,7 +1154,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.mouse_pan_value, ui);
|
||||
|
||||
// Mouse Zoom Sensitivity
|
||||
Text::new("Zoom Sensitivity")
|
||||
Text::new(&self.localized_strings.get("hud.settings.zoom_sensitivity"))
|
||||
.down_from(state.ids.mouse_pan_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1145,13 +1203,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
Text::new("Invert Scroll Zoom")
|
||||
.right_from(state.ids.mouse_zoom_invert_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.button_help)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_zoom_invert_label, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.invert_scroll_zoom"),
|
||||
)
|
||||
.right_from(state.ids.mouse_zoom_invert_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.button_help)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_zoom_invert_label, ui);
|
||||
|
||||
// Mouse Y Inversion
|
||||
let mouse_y_inverted = ToggleButton::new(
|
||||
@ -1171,13 +1233,17 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
Text::new("Invert Mouse Y Axis")
|
||||
.right_from(state.ids.mouse_y_invert_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.button_help)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_y_invert_label, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.invert_mouse_y_axis"),
|
||||
)
|
||||
.right_from(state.ids.mouse_y_invert_button, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.graphics_for(state.ids.button_help)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.mouse_y_invert_label, ui);
|
||||
}
|
||||
|
||||
// 3) Controls Tab --------------------------------
|
||||
@ -1198,7 +1264,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
self.imgs.settings_button_press
|
||||
})
|
||||
.right_from(state.ids.gameplay, 0.0)
|
||||
.label("Controls")
|
||||
.label(&self.localized_strings.get("common.controls"))
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.controls, ui)
|
||||
@ -1210,94 +1276,12 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
// Contents
|
||||
if let SettingsTab::Controls = self.show.settings_tab {
|
||||
let controls = &self.global_state.settings.controls;
|
||||
Text::new(
|
||||
"Free Cursor\n\
|
||||
Toggle Help Window\n\
|
||||
Toggle Interface\n\
|
||||
Toggle FPS and Debug Info\n\
|
||||
Take Screenshot\n\
|
||||
Toggle Nametags\n\
|
||||
Toggle Fullscreen\n\
|
||||
\n\
|
||||
\n\
|
||||
Move Forward\n\
|
||||
Move Left\n\
|
||||
Move Right\n\
|
||||
Move Backwards\n\
|
||||
\n\
|
||||
Jump\n\
|
||||
\n\
|
||||
Glider
|
||||
\n\
|
||||
Dodge\n\
|
||||
\n\
|
||||
Roll\n\
|
||||
\n\
|
||||
Climb\n\
|
||||
\n\
|
||||
Climb down\n\
|
||||
\n\
|
||||
Auto Walk\n\
|
||||
\n\
|
||||
Sheathe/Draw Weapons\n\
|
||||
\n\
|
||||
Put on/Remove Helmet\n\
|
||||
\n\
|
||||
Sit\n\
|
||||
\n\
|
||||
Mount\n\
|
||||
\n\
|
||||
Interact\n\
|
||||
\n\
|
||||
\n\
|
||||
Basic Attack\n\
|
||||
Secondary Attack/Block/Aim\n\
|
||||
\n\
|
||||
\n\
|
||||
Skillbar Slot 1\n\
|
||||
Skillbar Slot 2\n\
|
||||
Skillbar Slot 3\n\
|
||||
Skillbar Slot 4\n\
|
||||
Skillbar Slot 5\n\
|
||||
Skillbar Slot 6\n\
|
||||
Skillbar Slot 7\n\
|
||||
Skillbar Slot 8\n\
|
||||
Skillbar Slot 9\n\
|
||||
Skillbar Slot 10\n\
|
||||
\n\
|
||||
\n\
|
||||
Pause Menu\n\
|
||||
Settings\n\
|
||||
Social\n\
|
||||
Map\n\
|
||||
Spellbook\n\
|
||||
Character\n\
|
||||
Questlog\n\
|
||||
Bag\n\
|
||||
\n\
|
||||
\n\
|
||||
\n\
|
||||
Send Chat Message\n\
|
||||
Scroll Chat\n\
|
||||
\n\
|
||||
\n\
|
||||
Chat commands: \n\
|
||||
\n\
|
||||
/alias [Name] - Change your Chat Name \n\
|
||||
/tp [Name] - Teleports you to another player \n\
|
||||
/jump <dx> <dy> <dz> - Offset your position \n\
|
||||
/goto <x> <y> <z> - Teleport to a position \n\
|
||||
/kill - Kill yourself \n\
|
||||
/pig - Spawn pig NPC \n\
|
||||
/wolf - Spawn wolf NPC \n\
|
||||
/help - Display chat commands
|
||||
",
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.top_left_with_margins_on(state.ids.settings_content, 5.0, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(18)
|
||||
.set(state.ids.controls_text, ui);
|
||||
Text::new(&self.localized_strings.get("hud.settings.control_names"))
|
||||
.color(TEXT_COLOR)
|
||||
.top_left_with_margins_on(state.ids.settings_content, 5.0, 5.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(18)
|
||||
.set(state.ids.controls_text, ui);
|
||||
// TODO: Replace with buttons that show actual keybinds and allow the user to change them.
|
||||
Text::new(&format!(
|
||||
"{}\n\
|
||||
@ -1446,7 +1430,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
self.imgs.settings_button_press
|
||||
})
|
||||
.right_from(state.ids.controls, 0.0)
|
||||
.label("Video")
|
||||
.label(&self.localized_strings.get("common.video"))
|
||||
.parent(state.ids.settings_r)
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR)
|
||||
@ -1459,7 +1443,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
// Contents
|
||||
if let SettingsTab::Video = self.show.settings_tab {
|
||||
// View Distance
|
||||
Text::new("View Distance")
|
||||
Text::new(&self.localized_strings.get("hud.settings.view_distance"))
|
||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1494,7 +1478,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.vd_value, ui);
|
||||
|
||||
// Max FPS
|
||||
Text::new("Maximum FPS")
|
||||
Text::new(&self.localized_strings.get("hud.settings.maximum_fps"))
|
||||
.down_from(state.ids.vd_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1561,7 +1545,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.set(state.ids.fov_value, ui);
|
||||
|
||||
// AaMode
|
||||
Text::new("AntiAliasing Mode")
|
||||
Text::new(&self.localized_strings.get("hud.settings.antialiasing_mode"))
|
||||
.down_from(state.ids.fov_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1602,15 +1586,24 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
|
||||
// CloudMode
|
||||
Text::new("Cloud Rendering Mode")
|
||||
.down_from(state.ids.aa_mode_list, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.cloud_mode_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode"),
|
||||
)
|
||||
.down_from(state.ids.aa_mode_list, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.cloud_mode_text, ui);
|
||||
|
||||
let mode_list = [CloudMode::None, CloudMode::Regular];
|
||||
let mode_label_list = ["None", "Regular"];
|
||||
let mode_label_list = [
|
||||
&self.localized_strings.get("common.none"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.cloud_rendering_mode.regular"),
|
||||
];
|
||||
|
||||
// Get which cloud rendering mode is currently active
|
||||
let selected = mode_list
|
||||
@ -1629,15 +1622,26 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
|
||||
// FluidMode
|
||||
Text::new("Fluid Rendering Mode")
|
||||
.down_from(state.ids.cloud_mode_list, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.fluid_mode_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.fluid_rendering_mode"),
|
||||
)
|
||||
.down_from(state.ids.cloud_mode_list, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.fluid_mode_text, ui);
|
||||
|
||||
let mode_list = [FluidMode::Cheap, FluidMode::Shiny];
|
||||
let mode_label_list = ["Cheap", "Shiny"];
|
||||
let mode_label_list = [
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.fluid_rendering_mode.cheap"),
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.fluid_rendering_mode.shiny"),
|
||||
];
|
||||
|
||||
// Get which fluid rendering mode is currently active
|
||||
let selected = mode_list
|
||||
@ -1675,7 +1679,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
})
|
||||
.right_from(state.ids.video, 0.0)
|
||||
.parent(state.ids.settings_r)
|
||||
.label("Sound")
|
||||
.label(&self.localized_strings.get("common.sound"))
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(state.ids.sound, ui)
|
||||
@ -1687,7 +1691,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
// Contents
|
||||
if let SettingsTab::Sound = self.show.settings_tab {
|
||||
// Music Volume -----------------------------------------------------
|
||||
Text::new("Music Volume")
|
||||
Text::new(&self.localized_strings.get("hud.settings.music_volume"))
|
||||
.top_left_with_margins_on(state.ids.settings_content, 10.0, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1712,12 +1716,16 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
|
||||
// SFX Volume -------------------------------------------------------
|
||||
Text::new("Sound Effects Volume")
|
||||
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sfx_volume_text, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.sound_effect_volume"),
|
||||
)
|
||||
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.sfx_volume_text, ui);
|
||||
|
||||
if let Some(new_val) = ImageSlider::continuous(
|
||||
self.global_state.settings.audio.sfx_volume,
|
||||
@ -1739,7 +1747,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
// Audio Device Selector --------------------------------------------
|
||||
let device = &self.global_state.audio.device;
|
||||
let device_list = &self.global_state.audio.device_list;
|
||||
Text::new("Audio Device")
|
||||
Text::new(&self.localized_strings.get("hud.settings.audio_device"))
|
||||
.down_from(state.ids.sfx_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
|
@ -2,7 +2,9 @@ use super::{
|
||||
img_ids::Imgs, BarNumbers, Fonts, ShortcutNumbers, XpBar, CRITICAL_HP_COLOR,
|
||||
/*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
|
||||
};
|
||||
use crate::i18n::{i18n_asset_key, VoxygenLocalization};
|
||||
use crate::GlobalState;
|
||||
use common::assets::load_expect;
|
||||
use common::comp::{
|
||||
item::Debug, item::Tool, ActionState, CharacterState, ControllerInputs, Energy, ItemKind, Stats,
|
||||
};
|
||||
@ -189,6 +191,10 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 0.8; //Animation timer
|
||||
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
|
||||
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&self.global_state.settings.language.selected_language,
|
||||
));
|
||||
|
||||
// Stamina Wheel
|
||||
/*
|
||||
let stamina_percentage =
|
||||
@ -277,34 +283,30 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.set(state.ids.level_down, ui);
|
||||
// Death message
|
||||
if self.stats.is_dead {
|
||||
Text::new("You Died")
|
||||
Text::new(&localized_strings.get("hud.you_died"))
|
||||
.middle_of(ui.window)
|
||||
.font_size(50)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
|
||||
.set(state.ids.death_message_1_bg, ui);
|
||||
Text::new(&format!(
|
||||
"Press {:?} to respawn at your Waypoint.\n\
|
||||
\n\
|
||||
Press Enter, type in /waypoint and confirm to set it here.",
|
||||
self.global_state.settings.controls.respawn
|
||||
Text::new(&localized_strings.get("hud.press_key_to_respawn").replace(
|
||||
"{key}",
|
||||
&format!("{:?}", self.global_state.settings.controls.respawn),
|
||||
))
|
||||
.mid_bottom_with_margin_on(state.ids.death_message_1_bg, -120.0)
|
||||
.font_size(30)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
|
||||
.set(state.ids.death_message_2_bg, ui);
|
||||
Text::new("You Died")
|
||||
Text::new(&localized_strings.get("hud.you_died"))
|
||||
.bottom_left_with_margins_on(state.ids.death_message_1_bg, 2.0, 2.0)
|
||||
.font_size(50)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(CRITICAL_HP_COLOR)
|
||||
.set(state.ids.death_message_1, ui);
|
||||
Text::new(&format!(
|
||||
"Press {:?} to respawn at your Waypoint.\n\
|
||||
\n\
|
||||
Press Enter, type in /waypoint and confirm to set it here.",
|
||||
self.global_state.settings.controls.respawn
|
||||
Text::new(&localized_strings.get("hud.press_key_to_respawn").replace(
|
||||
"{key}",
|
||||
&format!("{:?}", self.global_state.settings.controls.respawn),
|
||||
))
|
||||
.bottom_left_with_margins_on(state.ids.death_message_2_bg, 2.0, 2.0)
|
||||
.font_size(30)
|
||||
|
@ -1,5 +1,7 @@
|
||||
use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR, TEXT_COLOR_3};
|
||||
|
||||
use crate::i18n::VoxygenLocalization;
|
||||
use client::{self, Client};
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
||||
@ -7,8 +9,6 @@ use conrod_core::{
|
||||
Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
use client::{self, Client};
|
||||
|
||||
widget_ids! {
|
||||
pub struct Ids {
|
||||
social_frame,
|
||||
@ -41,26 +41,31 @@ pub struct Social<'a> {
|
||||
client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
|
||||
impl<'a> Social<'a> {
|
||||
pub fn new(show: &'a Show, client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
|
||||
pub fn new(
|
||||
show: &'a Show,
|
||||
client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
show: show,
|
||||
show,
|
||||
client,
|
||||
imgs,
|
||||
client: client,
|
||||
fonts: fonts,
|
||||
fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*pub struct State {
|
||||
ids: Ids,
|
||||
}*/
|
||||
|
||||
pub enum Event {
|
||||
Close,
|
||||
ChangeSocialTab(SocialTab),
|
||||
@ -113,7 +118,7 @@ impl<'a> Widget for Social<'a> {
|
||||
}
|
||||
|
||||
// Title
|
||||
Text::new("Social")
|
||||
Text::new(&self.localized_strings.get("hud.social"))
|
||||
.mid_top_with_margin_on(ids.social_frame, 6.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
@ -159,7 +164,7 @@ impl<'a> Widget for Social<'a> {
|
||||
self.imgs.social_button_press
|
||||
})
|
||||
.top_left_with_margins_on(ids.align, 4.0, 0.0)
|
||||
.label("Online")
|
||||
.label(&self.localized_strings.get("hud.social.online"))
|
||||
.label_font_size(14)
|
||||
.parent(ids.frame)
|
||||
.label_color(TEXT_COLOR)
|
||||
@ -183,12 +188,17 @@ impl<'a> Widget for Social<'a> {
|
||||
.resize(count, &mut ui.widget_id_generator())
|
||||
})
|
||||
}
|
||||
Text::new(&format!("{} player(s) online\n", count))
|
||||
.top_left_with_margins_on(ids.content_align, -2.0, 7.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(ids.online_title, ui);
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.social.play_online_fmt")
|
||||
.replace("{nb_player}", &format!("{:?}", count)),
|
||||
)
|
||||
.top_left_with_margins_on(ids.content_align, -2.0, 7.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(ids.online_title, ui);
|
||||
for (i, (_, player_alias)) in self.client.player_list.iter().enumerate() {
|
||||
Text::new(player_alias)
|
||||
.down(3.0)
|
||||
@ -218,7 +228,7 @@ impl<'a> Widget for Social<'a> {
|
||||
self.imgs.social_button
|
||||
})
|
||||
.right_from(ids.online_tab, 0.0)
|
||||
.label("Friends")
|
||||
.label(&self.localized_strings.get("hud.social.friends"))
|
||||
.label_font_size(14)
|
||||
.parent(ids.frame)
|
||||
.label_color(TEXT_COLOR_3)
|
||||
@ -231,7 +241,7 @@ impl<'a> Widget for Social<'a> {
|
||||
// Contents
|
||||
|
||||
if let SocialTab::Friends = self.show.social_tab {
|
||||
Text::new("Not yet available")
|
||||
Text::new(&self.localized_strings.get("hud.social.not_yet_available"))
|
||||
.middle_of(ids.content_align)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -248,7 +258,7 @@ impl<'a> Widget for Social<'a> {
|
||||
if Button::image(button_img)
|
||||
.w_h(30.0 * 4.0, 12.0 * 4.0)
|
||||
.right_from(ids.friends_tab, 0.0)
|
||||
.label("Faction")
|
||||
.label(&self.localized_strings.get("hud.social.faction"))
|
||||
.parent(ids.frame)
|
||||
.label_font_size(14)
|
||||
.label_color(TEXT_COLOR_3)
|
||||
@ -261,7 +271,7 @@ impl<'a> Widget for Social<'a> {
|
||||
// Contents
|
||||
|
||||
if let SocialTab::Faction = self.show.social_tab {
|
||||
Text::new("Not yet available")
|
||||
Text::new(&self.localized_strings.get("hud.social.not_yet_available"))
|
||||
.middle_of(ids.content_align)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
|
@ -8,6 +8,8 @@ use conrod_core::{
|
||||
|
||||
use client::{self, Client};
|
||||
|
||||
use crate::i18n::VoxygenLocalization;
|
||||
|
||||
widget_ids! {
|
||||
pub struct Ids {
|
||||
spell_frame,
|
||||
@ -25,17 +27,26 @@ pub struct Spell<'a> {
|
||||
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
}
|
||||
|
||||
impl<'a> Spell<'a> {
|
||||
pub fn new(show: &'a Show, _client: &'a Client, imgs: &'a Imgs, fonts: &'a Fonts) -> Self {
|
||||
pub fn new(
|
||||
show: &'a Show,
|
||||
_client: &'a Client,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_show: show,
|
||||
imgs,
|
||||
_client,
|
||||
fonts: fonts,
|
||||
imgs,
|
||||
fonts,
|
||||
localized_strings,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -93,7 +104,7 @@ impl<'a> Widget for Spell<'a> {
|
||||
|
||||
// Title
|
||||
// TODO: Use an actual character name.
|
||||
Text::new("Spell")
|
||||
Text::new(&self.localized_strings.get("hud.spell"))
|
||||
.mid_top_with_margin_on(state.spell_frame, 6.0)
|
||||
.font_id(self.fonts.cyri)
|
||||
.font_size(14)
|
||||
|
113
voxygen/src/i18n.rs
Normal file
113
voxygen/src/i18n.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use common::assets;
|
||||
use common::assets::{load_expect, load_glob, Asset};
|
||||
use deunicode::deunicode;
|
||||
use ron::de::from_reader;
|
||||
use serde_derive::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
||||
/// The reference language, aka the more up-to-date localization data.
|
||||
/// Also the default language at first startup.
|
||||
pub const REFERENCE_LANG: &str = "en";
|
||||
|
||||
/// How a language can be described
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct LanguageMetadata {
|
||||
/// A human friendly language name (e.g. "English (US)")
|
||||
pub language_name: String,
|
||||
|
||||
/// A short text identifier for this language (e.g. "en_US")
|
||||
///
|
||||
/// On the opposite of `language_name` that can change freely,
|
||||
/// `language_identifier` value shall be stable in time as it
|
||||
/// is used by setting components to store the language
|
||||
/// selected by the user.
|
||||
pub language_identifier: String,
|
||||
}
|
||||
|
||||
/// Store internationalization data
|
||||
///
|
||||
/// TODO: store the font locations here (Font asset path for instance)
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct VoxygenLocalization {
|
||||
/// A map storing the localized texts
|
||||
///
|
||||
/// Localized content can be access using a String key
|
||||
pub string_map: HashMap<String, String>,
|
||||
|
||||
/// Either to convert the input text encoded in UTF-8
|
||||
/// into a ASCII version by using the `deunicode` crate.
|
||||
pub convert_utf8_to_ascii: bool,
|
||||
|
||||
pub metadata: LanguageMetadata,
|
||||
}
|
||||
|
||||
impl VoxygenLocalization {
|
||||
/// Get a localized text from the given key
|
||||
///
|
||||
/// If the key is not present in the localization object
|
||||
/// then the key is returned.
|
||||
pub fn get(&self, key: &str) -> String {
|
||||
match self.string_map.get(key) {
|
||||
Some(localized_text) => localized_text.to_owned(),
|
||||
None => key.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the missing keys compared to the reference language and return
|
||||
/// them
|
||||
pub fn list_missing_entries(&self) -> HashSet<String> {
|
||||
let reference_localization =
|
||||
load_expect::<VoxygenLocalization>(i18n_asset_key(REFERENCE_LANG).as_ref());
|
||||
let reference_keys: HashSet<_> =
|
||||
reference_localization.string_map.keys().cloned().collect();
|
||||
let current_keys: HashSet<_> = self.string_map.keys().cloned().collect();
|
||||
|
||||
reference_keys.difference(¤t_keys).cloned().collect()
|
||||
}
|
||||
|
||||
/// Log missing entries (compared to the reference language) as warnings
|
||||
pub fn log_missing_entries(&self) {
|
||||
for missing_key in self.list_missing_entries() {
|
||||
log::warn!(
|
||||
"[{:?}] Missing key {:?}",
|
||||
self.metadata.language_identifier,
|
||||
missing_key
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for VoxygenLocalization {
|
||||
const ENDINGS: &'static [&'static str] = &["ron"];
|
||||
|
||||
/// Load the translations located in the input buffer and convert them
|
||||
/// into a `VoxygenLocalization` object.
|
||||
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
||||
let mut asked_localization: VoxygenLocalization = from_reader(buf_reader).unwrap();
|
||||
|
||||
// Update the text if UTF-8 to ASCII conversion is enabled
|
||||
if asked_localization.convert_utf8_to_ascii {
|
||||
for value in asked_localization.string_map.values_mut() {
|
||||
*value = deunicode(value);
|
||||
}
|
||||
}
|
||||
asked_localization.metadata.language_name =
|
||||
deunicode(&asked_localization.metadata.language_name);
|
||||
|
||||
Ok(asked_localization)
|
||||
}
|
||||
}
|
||||
|
||||
/// Load all the available languages located in the Voxygen asset directory
|
||||
pub fn list_localizations() -> Vec<LanguageMetadata> {
|
||||
let voxygen_locales_assets = "voxygen.i18n.*";
|
||||
let lang_list = load_glob::<VoxygenLocalization>(voxygen_locales_assets).unwrap();
|
||||
lang_list.iter().map(|e| (*e).metadata.clone()).collect()
|
||||
}
|
||||
|
||||
/// Return the asset associated with the language_id
|
||||
pub fn i18n_asset_key(language_id: &str) -> String {
|
||||
"voxygen.i18n.".to_string() + language_id
|
||||
}
|
@ -9,6 +9,7 @@ pub mod audio;
|
||||
mod ecs;
|
||||
pub mod error;
|
||||
pub mod hud;
|
||||
pub mod i18n;
|
||||
pub mod key_state;
|
||||
mod logging;
|
||||
pub mod menu;
|
||||
@ -26,8 +27,14 @@ pub mod window;
|
||||
pub use crate::error::Error;
|
||||
|
||||
use crate::{
|
||||
audio::AudioFrontend, menu::main::MainMenuState, meta::Meta, settings::Settings, window::Window,
|
||||
audio::AudioFrontend,
|
||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||
menu::main::MainMenuState,
|
||||
meta::Meta,
|
||||
settings::Settings,
|
||||
window::Window,
|
||||
};
|
||||
use common::assets::load_expect;
|
||||
use log::{debug, error};
|
||||
use std::{mem, panic, str::FromStr};
|
||||
|
||||
@ -131,6 +138,12 @@ fn main() {
|
||||
info_message: None,
|
||||
};
|
||||
|
||||
// Try to load the localization and log missing entries
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&global_state.settings.language.selected_language,
|
||||
));
|
||||
localized_strings.log_missing_entries();
|
||||
|
||||
// Set up panic handler to relay swish panic messages to the user
|
||||
let default_hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
|
@ -1,6 +1,7 @@
|
||||
mod scene;
|
||||
mod ui;
|
||||
|
||||
use crate::i18n::{i18n_asset_key, VoxygenLocalization};
|
||||
use crate::{
|
||||
session::SessionState, window::Event as WinEvent, Direction, GlobalState, PlayState,
|
||||
PlayStateResult,
|
||||
@ -108,15 +109,15 @@ impl PlayState for CharSelectionState {
|
||||
.render(global_state.window.renderer_mut(), self.scene.globals());
|
||||
|
||||
// Tick the client (currently only to keep the connection alive).
|
||||
let localized_strings = assets::load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&global_state.settings.language.selected_language,
|
||||
));
|
||||
if let Err(err) = self.client.borrow_mut().tick(
|
||||
comp::ControllerInputs::default(),
|
||||
clock.get_last_delta(),
|
||||
|_| {},
|
||||
) {
|
||||
global_state.info_message = Some(
|
||||
"Connection lost!\nDid the server restart?\nIs the client up to date?"
|
||||
.to_owned(),
|
||||
);
|
||||
global_state.info_message = Some(localized_strings.get("common.connection_lost"));
|
||||
error!("[session] Failed to tick the scene: {:?}", err);
|
||||
|
||||
return PlayStateResult::Pop;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::window::{Event as WinEvent, PressState};
|
||||
use crate::{
|
||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||
meta::CharacterData,
|
||||
render::{Consts, Globals, Renderer},
|
||||
ui::{
|
||||
@ -9,6 +10,7 @@ use crate::{
|
||||
GlobalState,
|
||||
};
|
||||
use client::Client;
|
||||
use common::assets::load_expect;
|
||||
use common::comp::{self, humanoid};
|
||||
use conrod_core::{
|
||||
color,
|
||||
@ -256,6 +258,7 @@ pub struct CharSelectionUi {
|
||||
fonts: Fonts,
|
||||
character_creation: bool,
|
||||
info_content: InfoContent,
|
||||
selected_language: String,
|
||||
//deletion_confirmation: bool,
|
||||
pub character_name: String,
|
||||
pub character_body: humanoid::Body,
|
||||
@ -287,6 +290,7 @@ impl CharSelectionUi {
|
||||
info_content: InfoContent::None,
|
||||
//deletion_confirmation: false,
|
||||
character_creation: false,
|
||||
selected_language: global_state.settings.language.selected_language.clone(),
|
||||
character_name: "Character Name".to_string(),
|
||||
character_body: humanoid::Body::random(),
|
||||
character_tool: Some(STARTER_SWORD),
|
||||
@ -302,6 +306,9 @@ impl CharSelectionUi {
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
common::util::GIT_VERSION.to_string()
|
||||
);
|
||||
let localized_strings =
|
||||
load_expect::<VoxygenLocalization>(&i18n_asset_key(&self.selected_language));
|
||||
|
||||
// Tooltip
|
||||
let tooltip_human = Tooltip::new({
|
||||
// Edge images [t, b, r, l]
|
||||
@ -337,7 +344,7 @@ impl CharSelectionUi {
|
||||
match self.info_content {
|
||||
InfoContent::None => unreachable!(),
|
||||
InfoContent::Deletion(character_index) => {
|
||||
Text::new("Permanently delete this Character?")
|
||||
Text::new(&localized_strings.get("char_selection.delete_permanently"))
|
||||
.mid_top_with_margin_on(self.ids.info_frame, 40.0)
|
||||
.font_size(24)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -349,7 +356,7 @@ impl CharSelectionUi {
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("No")
|
||||
.label(&localized_strings.get("common.no"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_font_size(18)
|
||||
.label_color(TEXT_COLOR)
|
||||
@ -364,8 +371,7 @@ impl CharSelectionUi {
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("Yes")
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label(&localized_strings.get("common.yes"))
|
||||
.label_font_size(18)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(self.ids.info_ok, ui_widgets)
|
||||
@ -435,7 +441,7 @@ impl CharSelectionUi {
|
||||
.parent(self.ids.charlist_bg)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Change Server")
|
||||
.label(&localized_strings.get("char_selection.change_server"))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_font_size(18)
|
||||
@ -452,7 +458,7 @@ impl CharSelectionUi {
|
||||
.w_h(250.0, 60.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Enter World")
|
||||
.label(&localized_strings.get("char_selection.enter_world"))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(26)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
@ -469,7 +475,7 @@ impl CharSelectionUi {
|
||||
.w_h(150.0, 40.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Logout")
|
||||
.label(&localized_strings.get("char_selection.logout"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -486,7 +492,7 @@ impl CharSelectionUi {
|
||||
.w_h(270.0, 50.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Create Character")
|
||||
.label(&localized_strings.get("char_selection.create_charater"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -599,7 +605,7 @@ impl CharSelectionUi {
|
||||
.w_h(386.0, 80.0)
|
||||
.hover_image(self.imgs.selection_hover)
|
||||
.press_image(self.imgs.selection_press)
|
||||
.label("Create New Character")
|
||||
.label(&localized_strings.get("char_selection.create_new_charater"))
|
||||
.label_color(Color::Rgba(0.38, 1.0, 0.07, 1.0))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.image_color(Color::Rgba(0.38, 1.0, 0.07, 1.0))
|
||||
@ -619,7 +625,7 @@ impl CharSelectionUi {
|
||||
.w_h(150.0, 40.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Back")
|
||||
.label(&localized_strings.get("common.back"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -635,7 +641,7 @@ impl CharSelectionUi {
|
||||
.w_h(150.0, 40.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Create")
|
||||
.label(&localized_strings.get("common.create"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -704,7 +710,7 @@ impl CharSelectionUi {
|
||||
.set(self.ids.selection_scrollbar, ui_widgets);
|
||||
|
||||
// Male/Female/Race Icons
|
||||
Text::new("Character Creation")
|
||||
Text::new(&localized_strings.get("char_selection.character_creation"))
|
||||
.mid_top_with_margin_on(self.ids.creation_alignment, 10.0)
|
||||
.font_size(24)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -794,7 +800,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.human)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Human", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.human"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
/*.tooltip_image(
|
||||
if let humanoid::BodyType::Male = self.character_body.body_type {
|
||||
self.imgs.human_m
|
||||
@ -822,7 +833,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.orc)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Orc", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.orc"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.race_2, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -842,7 +858,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.dwarf)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Dwarf", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.dwarf"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.race_3, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -862,7 +883,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.elf)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Elf", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.elf"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.race_4, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -882,7 +908,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.undead)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Undead", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.undead"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.race_5, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -902,7 +933,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.danari)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Danari", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.races.danari"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.race_6, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -924,7 +960,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.hammer)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Hammer", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.weapons.hammer"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.hammer_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -949,7 +990,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.bow)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Bow", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.weapons.bow"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.bow_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -972,7 +1018,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.staff)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Staff", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.weapons.staff"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.staff_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -995,7 +1046,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.sword)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Sword", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.weapons.sword"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.sword_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -1038,7 +1094,12 @@ impl CharSelectionUi {
|
||||
.middle_of(self.ids.axe)
|
||||
.hover_image(self.imgs.icon_border_mo)
|
||||
.press_image(self.imgs.icon_border_press)
|
||||
.with_tooltip(tooltip_manager, "Axe", "", &tooltip_human)
|
||||
.with_tooltip(
|
||||
tooltip_manager,
|
||||
&localized_strings.get("common.weapons.axe"),
|
||||
"",
|
||||
&tooltip_human,
|
||||
)
|
||||
.set(self.ids.axe_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
@ -1056,13 +1117,13 @@ impl CharSelectionUi {
|
||||
self.imgs.slider_range,
|
||||
);
|
||||
let char_slider = move |prev_id,
|
||||
text,
|
||||
text: String,
|
||||
text_id,
|
||||
max,
|
||||
selected_val,
|
||||
slider_id,
|
||||
ui_widgets: &mut UiCell| {
|
||||
Text::new(text)
|
||||
Text::new(&text.clone())
|
||||
.down_from(prev_id, 22.0)
|
||||
.align_middle_x_of(prev_id)
|
||||
.font_size(18)
|
||||
@ -1081,7 +1142,7 @@ impl CharSelectionUi {
|
||||
// Hair Style
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.creation_buttons_alignment_2,
|
||||
"Hair Style",
|
||||
localized_strings.get("char_selection.hair_style"),
|
||||
self.ids.hairstyle_text,
|
||||
self.character_body
|
||||
.race
|
||||
@ -1096,7 +1157,7 @@ impl CharSelectionUi {
|
||||
// Hair Color
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.hairstyle_slider,
|
||||
"Hair Color",
|
||||
localized_strings.get("char_selection.hair_color"),
|
||||
self.ids.haircolor_text,
|
||||
self.character_body.race.num_hair_colors() as usize - 1,
|
||||
self.character_body.hair_color as usize,
|
||||
@ -1108,7 +1169,7 @@ impl CharSelectionUi {
|
||||
// Skin
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.haircolor_slider,
|
||||
"Skin",
|
||||
localized_strings.get("char_selection.skin"),
|
||||
self.ids.skin_text,
|
||||
self.character_body.race.num_skin_colors() as usize - 1,
|
||||
self.character_body.skin as usize,
|
||||
@ -1121,7 +1182,7 @@ impl CharSelectionUi {
|
||||
let current_eyebrows = self.character_body.eyebrows;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.skin_slider,
|
||||
"Eyebrows",
|
||||
localized_strings.get("char_selection.eyebrows"),
|
||||
self.ids.eyebrows_text,
|
||||
humanoid::ALL_EYEBROWS.len() - 1,
|
||||
humanoid::ALL_EYEBROWS
|
||||
@ -1136,7 +1197,7 @@ impl CharSelectionUi {
|
||||
// EyeColor
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.eyebrows_slider,
|
||||
"Eye Color",
|
||||
localized_strings.get("char_selection.eye_color"),
|
||||
self.ids.eyecolor_text,
|
||||
self.character_body.race.num_eye_colors() as usize - 1,
|
||||
self.character_body.eye_color as usize,
|
||||
@ -1149,7 +1210,7 @@ impl CharSelectionUi {
|
||||
let _current_accessory = self.character_body.accessory;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.eyecolor_slider,
|
||||
"Accessories",
|
||||
localized_strings.get("char_selection.accessories"),
|
||||
self.ids.accessories_text,
|
||||
self.character_body
|
||||
.race
|
||||
@ -1170,7 +1231,7 @@ impl CharSelectionUi {
|
||||
{
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.accessories_slider,
|
||||
"Beard",
|
||||
localized_strings.get("char_selection.beard"),
|
||||
self.ids.beard_text,
|
||||
self.character_body
|
||||
.race
|
||||
@ -1183,7 +1244,7 @@ impl CharSelectionUi {
|
||||
self.character_body.beard = new_val as u8;
|
||||
}
|
||||
} else {
|
||||
Text::new("Beard")
|
||||
Text::new(&localized_strings.get("char_selection.beard"))
|
||||
.mid_bottom_with_margin_on(self.ids.accessories_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.cyri)
|
||||
@ -1203,7 +1264,7 @@ impl CharSelectionUi {
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.beard_slider,
|
||||
"Chest Color",
|
||||
localized_strings.get("char_selection.chest_color"),
|
||||
self.ids.chest_text,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
humanoid::ALL_CHESTS
|
||||
|
@ -4,11 +4,14 @@ mod ui;
|
||||
|
||||
use super::char_selection::CharSelectionState;
|
||||
use crate::{
|
||||
singleplayer::Singleplayer, window::Event, Direction, GlobalState, PlayState, PlayStateResult,
|
||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||
singleplayer::Singleplayer,
|
||||
window::Event,
|
||||
Direction, GlobalState, PlayState, PlayStateResult,
|
||||
};
|
||||
use argon2::{self, Config};
|
||||
use client_init::{ClientInit, Error as InitError};
|
||||
use common::{clock::Clock, comp};
|
||||
use common::{assets::load_expect, clock::Clock, comp};
|
||||
use log::warn;
|
||||
#[cfg(feature = "singleplayer")]
|
||||
use std::time::Duration;
|
||||
@ -147,9 +150,13 @@ impl PlayState for MainMenuState {
|
||||
}
|
||||
}
|
||||
}
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&global_state.settings.language.selected_language,
|
||||
));
|
||||
|
||||
if let Some(info) = global_state.info_message.take() {
|
||||
self.main_menu_ui.show_info(info);
|
||||
self.main_menu_ui
|
||||
.show_info(info, localized_strings.get("common.okay"));
|
||||
}
|
||||
|
||||
// Draw the UI to the screen.
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::i18n::{i18n_asset_key, VoxygenLocalization};
|
||||
use crate::ui::Graphic;
|
||||
use crate::{
|
||||
render::Renderer,
|
||||
@ -219,13 +220,11 @@ impl MainMenuUi {
|
||||
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||
const TEXT_COLOR_2: Color = Color::Rgba(1.0, 1.0, 1.0, 0.2);
|
||||
//const INACTIVE: Color = Color::Rgba(0.47, 0.47, 0.47, 0.47);
|
||||
let intro_text: &'static str = "Information on the Login Process:\n\
|
||||
\n\
|
||||
The name you put in will be your character name ingame.\n\
|
||||
\n\
|
||||
Character names and appearances will be saved on your computer.\n\
|
||||
\n\
|
||||
Levels/Items are not saved yet.";
|
||||
|
||||
let localized_strings = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
||||
&global_state.settings.language.selected_language,
|
||||
));
|
||||
let intro_text = &localized_strings.get("main.login_process");
|
||||
|
||||
// Tooltip
|
||||
let _tooltip = Tooltip::new({
|
||||
@ -349,39 +348,18 @@ impl MainMenuUi {
|
||||
.scroll_kids_vertically()
|
||||
.set(self.ids.disc_window, ui_widgets);
|
||||
|
||||
Text::new("Disclaimer")
|
||||
Text::new(&localized_strings.get("common.disclaimer"))
|
||||
.top_left_with_margins_on(self.ids.disc_window, 30.0, 40.0)
|
||||
.font_size(35)
|
||||
.font_id(self.fonts.alkhemi)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.disc_text_1, ui_widgets);
|
||||
Text::new(
|
||||
"Welcome to the alpha version of Veloren!\n\
|
||||
\n\
|
||||
\n\
|
||||
Before you dive into the fun, please keep a few things in mind:\n\
|
||||
\n\
|
||||
- This is a very early alpha. Expect bugs, extremely unfinished gameplay, unpolished mechanics, and missing features. \n\
|
||||
\n\
|
||||
-If you have constructive feedback or bug reports, you can contact us via Reddit, GitLab, or our community Discord server.\n\
|
||||
\n\
|
||||
- Veloren is licensed under the GPL 3 open-source licence. That means you're free to play, modify, and redistribute the game however you wish \n\
|
||||
(provided derived work is also under GPL 3).
|
||||
\n\
|
||||
- Veloren is a non-profit community project, and everybody working on it is a volunteer.\n\
|
||||
If you like what you see, you're welcome to join the development or art teams!
|
||||
\n\
|
||||
- 'Voxel RPG' is a genre in its own right. First-person shooters used to be called Doom clones.\n\
|
||||
Like them, we're trying to build a niche. This game is not a clone, and its development will diverge from existing games in the future.\n\
|
||||
\n\
|
||||
Thanks for taking the time to read this notice, we hope you enjoy the game!\n\
|
||||
\n\
|
||||
~ The Veloren Devs")
|
||||
.top_left_with_margins_on(self.ids.disc_window, 110.0, 40.0)
|
||||
.font_size(26)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.disc_text_2, ui_widgets);
|
||||
Text::new(&localized_strings.get("main.notice"))
|
||||
.top_left_with_margins_on(self.ids.disc_window, 110.0, 40.0)
|
||||
.font_size(26)
|
||||
.font_id(self.fonts.cyri)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.disc_text_2, ui_widgets);
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(300.0, 50.0)
|
||||
.mid_bottom_with_margin_on(self.ids.disc_window, 30.0)
|
||||
@ -407,8 +385,8 @@ impl MainMenuUi {
|
||||
self.connect = true;
|
||||
self.connecting = Some(std::time::Instant::now());
|
||||
self.popup = Some(PopupData {
|
||||
msg: "Connecting...".to_string(),
|
||||
button_text: "Cancel".to_string(),
|
||||
msg: localized_strings.get("main.connecting") + "...",
|
||||
button_text: localized_strings.get("common.cancel"),
|
||||
popup_type: PopupType::ConnectionInfo,
|
||||
});
|
||||
|
||||
@ -445,8 +423,8 @@ impl MainMenuUi {
|
||||
self.connect = true;
|
||||
self.connecting = Some(std::time::Instant::now());
|
||||
self.popup = Some(PopupData {
|
||||
msg: "Creating World...".to_string(),
|
||||
button_text: "Cancel".to_string(),
|
||||
msg: localized_strings.get("main.creating_world") + "...",
|
||||
button_text: localized_strings.get("common.cancel"),
|
||||
popup_type: PopupType::ConnectionInfo,
|
||||
});
|
||||
};
|
||||
@ -565,7 +543,7 @@ impl MainMenuUi {
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("Close")
|
||||
.label(&localized_strings.get("common.close"))
|
||||
.label_font_size(20)
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
@ -610,7 +588,7 @@ impl MainMenuUi {
|
||||
.w_h(258.0, 55.0)
|
||||
.down_from(self.ids.address_bg, 20.0)
|
||||
.align_middle_x_of(self.ids.address_bg)
|
||||
.label("Multiplayer")
|
||||
.label(&localized_strings.get("common.multiplayer"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(22)
|
||||
@ -637,7 +615,7 @@ impl MainMenuUi {
|
||||
.w_h(258.0, 55.0)
|
||||
.down_from(self.ids.login_button, 20.0)
|
||||
.align_middle_x_of(self.ids.address_bg)
|
||||
.label("Singleplayer")
|
||||
.label(&localized_strings.get("common.singleplayer"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(22)
|
||||
@ -655,7 +633,7 @@ impl MainMenuUi {
|
||||
.bottom_left_with_margins_on(ui_widgets.window, 60.0, 30.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Quit")
|
||||
.label(&localized_strings.get("common.quit"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -672,7 +650,7 @@ impl MainMenuUi {
|
||||
.up_from(self.ids.quit_button, 8.0)
|
||||
//.hover_image(self.imgs.button_hover)
|
||||
//.press_image(self.imgs.button_press)
|
||||
.label("Settings")
|
||||
.label(&localized_strings.get("common.settings"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR_2)
|
||||
.label_font_size(20)
|
||||
@ -689,7 +667,7 @@ impl MainMenuUi {
|
||||
.up_from(self.ids.settings_button, 8.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label("Servers")
|
||||
.label(&localized_strings.get("common.servers"))
|
||||
.label_font_id(self.fonts.cyri)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(20)
|
||||
@ -705,10 +683,10 @@ impl MainMenuUi {
|
||||
events
|
||||
}
|
||||
|
||||
pub fn show_info(&mut self, msg: String) {
|
||||
pub fn show_info(&mut self, msg: String, button_text: String) {
|
||||
self.popup = Some(PopupData {
|
||||
msg,
|
||||
button_text: "Okay".to_string(),
|
||||
button_text: button_text,
|
||||
popup_type: PopupType::Error,
|
||||
});
|
||||
self.connecting = None;
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::i18n::{i18n_asset_key, VoxygenLocalization};
|
||||
use crate::{
|
||||
ecs::MyEntity,
|
||||
hud::{DebugInfo, Event as HudEvent, Hud},
|
||||
@ -9,6 +10,8 @@ use crate::{
|
||||
};
|
||||
use client::{self, Client, Event::Chat};
|
||||
use common::{
|
||||
assets::load_watched,
|
||||
assets::watch,
|
||||
clock::Clock,
|
||||
comp,
|
||||
comp::{Pos, Vel},
|
||||
@ -132,6 +135,14 @@ impl PlayState for SessionState {
|
||||
}
|
||||
}
|
||||
|
||||
// Keep a watcher on the language
|
||||
let mut localization_watcher = watch::ReloadIndicator::new();
|
||||
let mut localized_strings = load_watched::<VoxygenLocalization>(
|
||||
&i18n_asset_key(&global_state.settings.language.selected_language),
|
||||
&mut localization_watcher,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Game loop
|
||||
let mut current_client_state = self.client.borrow().get_client_state();
|
||||
while let ClientState::Pending | ClientState::Character = current_client_state {
|
||||
@ -363,10 +374,7 @@ impl PlayState for SessionState {
|
||||
|
||||
// Perform an in-game tick.
|
||||
if let Err(err) = self.tick(clock.get_avg_delta()) {
|
||||
global_state.info_message = Some(
|
||||
"Connection lost!\nDid the server restart?\nIs the client up to date?"
|
||||
.to_owned(),
|
||||
);
|
||||
global_state.info_message = Some(localized_strings.get("common.connection_lost"));
|
||||
error!("[session] Failed to tick the scene: {:?}", err);
|
||||
|
||||
return PlayStateResult::Pop;
|
||||
@ -376,7 +384,7 @@ impl PlayState for SessionState {
|
||||
global_state.maintain(clock.get_last_delta().as_secs_f32());
|
||||
|
||||
// Extract HUD events ensuring the client borrow gets dropped.
|
||||
let hud_events = self.hud.maintain(
|
||||
let mut hud_events = self.hud.maintain(
|
||||
&self.client.borrow(),
|
||||
global_state,
|
||||
DebugInfo {
|
||||
@ -407,6 +415,11 @@ impl PlayState for SessionState {
|
||||
clock.get_last_delta(),
|
||||
);
|
||||
|
||||
// Look for changes in the localization files
|
||||
if localization_watcher.reloaded() {
|
||||
hud_events.push(HudEvent::ChangeLanguage(localized_strings.metadata.clone()));
|
||||
}
|
||||
|
||||
// Maintain the UI.
|
||||
for event in hud_events {
|
||||
match event {
|
||||
@ -560,6 +573,16 @@ impl PlayState for SessionState {
|
||||
global_state.settings.graphics.fluid_mode = new_fluid_mode;
|
||||
global_state.settings.save_to_file_warn();
|
||||
}
|
||||
HudEvent::ChangeLanguage(new_language) => {
|
||||
global_state.settings.language.selected_language =
|
||||
new_language.language_identifier;
|
||||
localized_strings = load_watched::<VoxygenLocalization>(
|
||||
&i18n_asset_key(&global_state.settings.language.selected_language),
|
||||
&mut localization_watcher,
|
||||
)
|
||||
.unwrap();
|
||||
localized_strings.log_missing_entries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::{
|
||||
hud::{BarNumbers, CrosshairType, Intro, ShortcutNumbers, XpBar},
|
||||
render::{AaMode, CloudMode, FluidMode},
|
||||
i18n,
|
||||
render::AaMode,
|
||||
render::{CloudMode, FluidMode},
|
||||
ui::ScaleMode,
|
||||
window::KeyMouse,
|
||||
};
|
||||
@ -234,6 +236,20 @@ impl Default for AudioSettings {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct LanguageSettings {
|
||||
pub selected_language: String,
|
||||
}
|
||||
|
||||
impl Default for LanguageSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
selected_language: i18n::REFERENCE_LANG.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Settings` contains everything that can be configured in the settings.ron file.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
@ -248,6 +264,7 @@ pub struct Settings {
|
||||
pub send_logon_commands: bool,
|
||||
// TODO: Remove at a later date, for dev testing
|
||||
pub logon_commands: Vec<String>,
|
||||
pub language: LanguageSettings,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@ -262,6 +279,7 @@ impl Default for Settings {
|
||||
show_disclaimer: true,
|
||||
send_logon_commands: false,
|
||||
logon_commands: Vec::new(),
|
||||
language: LanguageSettings::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user