veloren_voxygen/menu/main/ui/
credits.rs1use super::Message;
2use crate::{
3 credits::Credits,
4 ui::{
5 fonts::IcedFonts as Fonts,
6 ice::{Element, component::neat_button, style},
7 },
8};
9use i18n::Localization;
10use iced::{Column, Container, HorizontalAlignment, Length, Scrollable, Space, button, scrollable};
11
12pub struct Screen {
14 back_button: button::State,
15 scroll: scrollable::State,
16}
17
18impl Screen {
19 pub fn new() -> Self {
20 Self {
21 back_button: Default::default(),
22 scroll: Default::default(),
23 }
24 }
25
26 pub(super) fn view(
27 &mut self,
28 fonts: &Fonts,
29 i18n: &Localization,
30 credits: &Credits,
31 button_style: style::button::Style,
32 ) -> Element<'_, Message> {
33 use core::fmt::Write;
34 let format_art_credit = |credit: &crate::credits::Art| -> Result<String, core::fmt::Error> {
35 let mut text = String::new();
36 write!(&mut text, "\"{}\"", &credit.name)?;
37
38 let mut authors = credit.authors.iter();
39 if let Some(author) = authors.next() {
40 write!(
41 &mut text,
42 " {} {}",
43 i18n.get_msg("main-credits-created_by"),
44 author
45 )?;
46 }
47 authors.try_for_each(|author| write!(&mut text, ", {}", author))?;
48
49 if !credit.license.is_empty() {
50 write!(&mut text, " ({})", &credit.license)?;
51 }
52
53 Ok::<_, core::fmt::Error>(text)
54 };
55 let format_sounds_credit =
56 |credit: &crate::credits::Sounds| -> Result<String, core::fmt::Error> {
57 let mut text = String::new();
58 let mut authors = credit.authors.iter();
59
60 if let Some(author) = authors.next() {
61 write!(&mut text, "{}", author)?;
62 }
63 authors.try_for_each(|author| write!(&mut text, ", {}", author))?;
64
65 if !credit.license.is_empty() {
66 write!(&mut text, " ({})", &credit.license)?;
67 }
68
69 Ok::<_, core::fmt::Error>(text)
70 };
71 let format_contributor_credit =
72 |credit: &crate::credits::Contributor| -> Result<String, core::fmt::Error> {
73 let mut text = String::new();
74 text.push_str(&credit.name);
75
76 if !credit.contributions.is_empty() {
77 write!(&mut text, "- {}", &credit.contributions)?;
78 }
79
80 Ok(text)
81 };
82
83 let music_header_color = iced::Color::from_rgb8(0xfc, 0x71, 0x76);
84 let fonts_header_color = iced::Color::from_rgb8(0xf7, 0xd1, 0x81);
85 let other_art_header_color = iced::Color::from_rgb8(0xc5, 0xe9, 0x80);
86 let contributors_header_color = iced::Color::from_rgb8(0x4a, 0xa6, 0x7b);
87
88 fn credit_section<'a, T>(
89 header_i18n_key: &str,
90 header_color: iced::Color,
91 credit_iter: impl Iterator<Item = T>,
92 format_credit: impl Fn(T) -> Result<String, core::fmt::Error>,
93 fonts: &Fonts,
94 i18n: &Localization,
95 ) -> Element<'a, Message> {
96 Column::with_children(
97 core::iter::once(
98 iced::Text::new(i18n.get_msg(header_i18n_key))
99 .font(fonts.cyri.id)
100 .size(fonts.cyri.scale(30))
101 .color(header_color)
102 .width(Length::Fill)
103 .horizontal_alignment(HorizontalAlignment::Center)
104 .into(),
105 )
106 .chain(credit_iter.map(|credit| {
107 let text = format_credit(credit).expect("Formatting failed!!!");
108 iced::Text::new(text)
109 .font(fonts.cyri.id)
110 .size(fonts.cyri.scale(23))
111 .width(Length::Fill)
112 .horizontal_alignment(HorizontalAlignment::Center)
113 .into()
114 }))
115 .chain(core::iter::once(
116 Space::new(Length::Fill, Length::Units(15)).into(),
117 ))
118 .collect(),
119 )
120 .width(Length::Fill)
121 .into()
122 }
123
124 let art_section = |header_i18n_key, header_color, art: &[_]| {
125 credit_section(
126 header_i18n_key,
127 header_color,
128 art.iter(),
129 format_art_credit,
130 fonts,
131 i18n,
132 )
133 };
134
135 let sounds_section = |header_i18n_key, header_color, art: &[_]| {
136 credit_section(
137 header_i18n_key,
138 header_color,
139 art.iter(),
140 format_sounds_credit,
141 fonts,
142 i18n,
143 )
144 };
145
146 Container::new(
147 Container::new(
148 Column::with_children(vec![
149 iced::Text::new(i18n.get_msg("main-credits"))
150 .font(fonts.cyri.id)
151 .size(fonts.cyri.scale(35))
152 .width(Length::Fill)
153 .horizontal_alignment(HorizontalAlignment::Center)
154 .into(),
155 Space::new(Length::Fill, Length::Units(25)).into(),
156 Scrollable::new(&mut self.scroll)
157 .push(art_section(
158 "main-credits-music",
159 music_header_color,
160 &credits.music,
161 ))
162 .push(sounds_section(
163 "main-credits-sound",
164 music_header_color,
165 &credits.sounds,
166 ))
167 .push(art_section(
168 "main-credits-fonts",
169 fonts_header_color,
170 &credits.fonts,
171 ))
172 .push(art_section(
173 "main-credits-other_art",
174 other_art_header_color,
175 &credits.other_art,
176 ))
177 .push(credit_section(
178 "main-credits-contributors",
179 contributors_header_color,
180 credits.contributors.iter(),
181 format_contributor_credit,
182 fonts,
183 i18n,
184 ))
185 .height(Length::FillPortion(1))
186 .width(Length::Fill)
187 .into(),
188 Container::new(
189 Container::new(neat_button(
190 &mut self.back_button,
191 i18n.get_msg("common-back"),
192 0.7,
193 button_style,
194 Some(Message::Back),
195 ))
196 .height(Length::Units(fonts.cyri.scale(50))),
197 )
198 .center_x()
199 .height(Length::Shrink)
200 .width(Length::Fill)
201 .into(),
202 ])
203 .spacing(5)
204 .padding(20)
205 .width(Length::Fill)
206 .height(Length::Fill),
207 )
208 .style(
209 style::container::Style::color_with_double_cornerless_border(
210 (22, 19, 17, 255).into(),
211 (11, 11, 11, 255).into(),
212 (54, 46, 38, 255).into(),
213 ),
214 ),
215 )
216 .center_x()
217 .center_y()
218 .padding(70)
219 .width(Length::Fill)
220 .height(Length::Fill)
221 .into()
222 }
223}