You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

710 lines
19 KiB

  1. #![allow(dead_code)]
  2. use std::cell::RefCell;
  3. use std::cmp::PartialEq;
  4. use std::collections::HashMap;
  5. use std::fmt::Display;
  6. use std::hash::{Hash, Hasher};
  7. use std::mem::size_of;
  8. use std::ops::Deref;
  9. use std::ptr::null;
  10. use std::rc::{Rc, Weak};
  11. use glc::{
  12. buffer::{Buffer, Usage},
  13. error::Error as GlcError,
  14. misc::BindGuard,
  15. shader::{Program, Type, Uniform},
  16. texture::{FilterMag, FilterMin, Target as TextureTarget, Texture, Wrap},
  17. vector::{Vector2f, Vector4f},
  18. vertex_array::{DataType, VertexArray},
  19. };
  20. use glyph_brush::{
  21. ab_glyph::{FontArc, FontVec},
  22. BrushAction, BrushError, FontId, GlyphBrush, GlyphBrushBuilder, GlyphVertex, Layout,
  23. OwnedSection, OwnedText, Rectangle,
  24. };
  25. use ordered_float::OrderedFloat;
  26. use space_crush_common::misc::{LogResult, Vfs, WorldHelper as _};
  27. use specs::World;
  28. use crate::{misc::WorldHelper, Error};
  29. pub use glyph_brush::{HorizontalAlign, VerticalAlign};
  30. /* TextManager */
  31. #[derive(Clone)]
  32. pub struct TextManager(Rc<RefCell<TextManagerInner>>);
  33. struct TextManagerInner {
  34. vfs: Vfs,
  35. program: Rc<Program>,
  36. fonts: HashMap<String, FontArc>,
  37. }
  38. impl TextManager {
  39. pub fn new(world: &World) -> Result<Self, Error> {
  40. let vfs = world.resource::<Vfs>()?.deref().clone();
  41. let program = world.load_program(vec![
  42. (Type::Vertex, "resources/shader/text/vert.glsl"),
  43. (Type::Geometry, "resources/shader/text/geom.glsl"),
  44. (Type::Fragment, "resources/shader/text/frag.glsl"),
  45. ])?;
  46. let program = Rc::new(program);
  47. Ok(Self(Rc::new(RefCell::new(TextManagerInner {
  48. vfs,
  49. program,
  50. fonts: HashMap::new(),
  51. }))))
  52. }
  53. pub fn create_cache(&self) -> Result<TextCache, Error> {
  54. TextCache::new(self)
  55. }
  56. pub fn font(&self, path: &str) -> Result<FontArc, Error> {
  57. if let Some(font) = self.0.borrow().fonts.get(path) {
  58. return Ok(font.clone());
  59. }
  60. let path = self.0.borrow().vfs.join(path)?;
  61. let mut data = Vec::new();
  62. path.open_file()?.read_to_end(&mut data)?;
  63. let font = FontVec::try_from_vec(data)?;
  64. let font = FontArc::new(font);
  65. {
  66. let mut this = self.0.borrow_mut();
  67. this.fonts.insert(path.filename(), font.clone());
  68. this.fonts.insert(path.as_str().to_owned(), font.clone());
  69. }
  70. Ok(font)
  71. }
  72. }
  73. /* TextCache */
  74. #[derive(Clone)]
  75. pub struct TextCache(Rc<RefCell<TextCacheInner>>);
  76. pub struct TextCacheInner {
  77. manager: TextManager,
  78. fonts: HashMap<String, FontId>,
  79. glyphs: Option<GlyphBrush<Vertex, Extra>>,
  80. texture: Rc<RefCell<Texture>>,
  81. texts: HashMap<usize, Weak<RefCell<TextInner>>>,
  82. text_ids: Vec<usize>,
  83. next_text_id: usize,
  84. update_counter: usize,
  85. update_requested: bool,
  86. }
  87. pub struct UpdateGuard(TextCache);
  88. impl TextCache {
  89. fn new(manager: &TextManager) -> Result<Self, Error> {
  90. let mut texture = Texture::new(TextureTarget::Texture2D)?;
  91. texture.set_filter(FilterMin::Linear, FilterMag::Linear)?;
  92. texture.set_wrap(Wrap::ClampToEdge, Wrap::ClampToEdge, Wrap::ClampToEdge)?;
  93. Ok(Self(Rc::new(RefCell::new(TextCacheInner {
  94. manager: manager.clone(),
  95. fonts: HashMap::new(),
  96. glyphs: None,
  97. texture: Rc::new(RefCell::new(texture)),
  98. texts: HashMap::new(),
  99. text_ids: Vec::new(),
  100. next_text_id: 0,
  101. update_counter: 0,
  102. update_requested: false,
  103. }))))
  104. }
  105. pub fn new_text(&self) -> TextBuilder {
  106. TextBuilder::new(self)
  107. }
  108. pub fn begin_update(&self) -> UpdateGuard {
  109. self.0.borrow_mut().update_counter += 1;
  110. UpdateGuard(self.clone())
  111. }
  112. fn end_update(&self) {
  113. let mut inner = self.0.borrow_mut();
  114. if inner.update_counter > 0 {
  115. inner.update_counter -= 1;
  116. }
  117. if inner.update_counter > 0 {
  118. return;
  119. }
  120. let update_requested = inner.update_requested;
  121. drop(inner);
  122. if update_requested {
  123. self.update().error("Unable to update text cache");
  124. }
  125. }
  126. fn font(&self, path: &str) -> Result<FontId, Error> {
  127. let mut inner = self.0.borrow_mut();
  128. if let Some(id) = inner.fonts.get(path) {
  129. return Ok(*id);
  130. }
  131. let font = inner.manager.font(path)?;
  132. inner.add_font(font)
  133. }
  134. fn next_text_id(&self) -> usize {
  135. let mut inner = self.0.borrow_mut();
  136. if let Some(id) = inner.text_ids.pop() {
  137. return id;
  138. }
  139. let ret = inner.next_text_id;
  140. inner.next_text_id += 1;
  141. ret
  142. }
  143. fn add_text(&self, text: Weak<RefCell<TextInner>>) -> Result<(), Error> {
  144. let text_id = self.next_text_id();
  145. for section in &mut text.upgrade().unwrap().borrow_mut().sections {
  146. for t in &mut section.text {
  147. t.extra.text_id = text_id;
  148. }
  149. }
  150. self.0.borrow_mut().texts.insert(text_id, text);
  151. self.update()
  152. }
  153. fn update(&self) -> Result<(), Error> {
  154. let mut inner = self.0.borrow_mut();
  155. let inner = &mut *inner;
  156. if inner.update_counter > 0 {
  157. inner.update_requested = true;
  158. return Ok(());
  159. }
  160. /* remove droped texts */
  161. let texts = &mut inner.texts;
  162. let text_ids = &mut inner.text_ids;
  163. texts.retain(|id, t| {
  164. if t.strong_count() > 0 {
  165. true
  166. } else {
  167. text_ids.push(*id);
  168. false
  169. }
  170. });
  171. /* add sections to glyph queue */
  172. let glyphs = inner.glyphs.as_mut().unwrap();
  173. for text in texts.values_mut() {
  174. for section in text.upgrade().unwrap().borrow_mut().sections.iter_mut() {
  175. glyphs.queue(section.to_borrowed());
  176. }
  177. }
  178. /* process glyph queue */
  179. let action = loop {
  180. let glyphs = inner.glyphs.as_mut().unwrap();
  181. let texture = inner.texture.borrow();
  182. let ret = glyphs.process_queued(
  183. move |rect, data| update_texture(&*texture, rect, data),
  184. create_vertex,
  185. );
  186. match ret {
  187. Ok(action) => break action,
  188. Err(BrushError::TextureTooSmall { suggested, .. }) => {
  189. let new_size = glyphs.texture_dimensions();
  190. let new_size = resize_texture(suggested, Some(new_size))?;
  191. glyphs.resize_texture(new_size.0, new_size.1);
  192. }
  193. }
  194. };
  195. // upate vertex data
  196. if let BrushAction::Draw(vertices) = action {
  197. let mut map = Vec::<Vec<VertexData>>::new();
  198. map.resize_with(inner.next_text_id, Default::default);
  199. for vertex in vertices {
  200. map[vertex.text_id].push(vertex.data);
  201. }
  202. for (text_id, data) in map.into_iter().enumerate() {
  203. if data.is_empty() {
  204. continue;
  205. }
  206. inner
  207. .texts
  208. .get(&text_id)
  209. .unwrap()
  210. .upgrade()
  211. .unwrap()
  212. .borrow_mut()
  213. .update(data)?;
  214. }
  215. }
  216. inner.update_requested = false;
  217. Ok(())
  218. }
  219. }
  220. impl TextCacheInner {
  221. fn add_font(&mut self, font: FontArc) -> Result<FontId, Error> {
  222. let (id, size) = match self.glyphs.as_mut() {
  223. Some(glyphs) => (glyphs.add_font(font), None),
  224. None => {
  225. let glyphs = GlyphBrushBuilder::using_font(font)
  226. .draw_cache_position_tolerance(2.0)
  227. .build();
  228. let size = glyphs.texture_dimensions();
  229. self.glyphs = Some(glyphs);
  230. (FontId(0), Some(size))
  231. }
  232. };
  233. if let Some(size) = size {
  234. let texture = self.texture.borrow();
  235. let _guard = BindGuard::new(&*texture);
  236. let new_size = resize_texture(size, None)?;
  237. self.glyphs
  238. .as_mut()
  239. .unwrap()
  240. .resize_texture(new_size.0, new_size.1);
  241. }
  242. Ok(id)
  243. }
  244. }
  245. impl Drop for UpdateGuard {
  246. fn drop(&mut self) {
  247. self.0.end_update()
  248. }
  249. }
  250. fn resize_texture(new_size: (u32, u32), cur_size: Option<(u32, u32)>) -> Result<(u32, u32), Error> {
  251. let mut max_size = 0;
  252. gl::get_integer_v(gl::MAX_TEXTURE_SIZE, &mut max_size);
  253. let max_size = max_size as u32;
  254. let (w, h) = if let Some(cur_size) = cur_size {
  255. if (new_size.0 > max_size || new_size.1 > max_size)
  256. && (cur_size.0 < max_size || cur_size.1 < max_size)
  257. {
  258. (max_size, max_size)
  259. } else {
  260. new_size
  261. }
  262. } else {
  263. new_size
  264. };
  265. GlcError::checked(|| {
  266. gl::tex_image_2d(
  267. gl::TEXTURE_2D,
  268. 0,
  269. gl::RED as _,
  270. w as _,
  271. h as _,
  272. 0,
  273. gl::RED,
  274. gl::UNSIGNED_BYTE,
  275. null(),
  276. )
  277. })?;
  278. Ok(new_size)
  279. }
  280. fn update_texture(texture: &Texture, rect: Rectangle<u32>, data: &[u8]) {
  281. GlcError::checked(|| {
  282. gl::texture_sub_image_2d(
  283. texture.id(),
  284. 0,
  285. rect.min[0] as _,
  286. rect.min[1] as _,
  287. rect.width() as _,
  288. rect.height() as _,
  289. gl::RED,
  290. gl::UNSIGNED_BYTE,
  291. data.as_ptr() as _,
  292. )
  293. })
  294. .error("Unable to update text texture");
  295. }
  296. fn create_vertex(data: GlyphVertex<Extra>) -> Vertex {
  297. let pos_min = Vector2f::new(data.pixel_coords.min.x, data.pixel_coords.min.y);
  298. let pos_max = Vector2f::new(data.pixel_coords.max.x, data.pixel_coords.max.y);
  299. let tex_min = Vector2f::new(data.tex_coords.min.x, data.tex_coords.min.y);
  300. let tex_max = Vector2f::new(data.tex_coords.max.x, data.tex_coords.max.y);
  301. Vertex {
  302. text_id: data.extra.text_id,
  303. data: VertexData {
  304. pos_min,
  305. pos_max,
  306. tex_min,
  307. tex_max,
  308. color: data.extra.color,
  309. },
  310. }
  311. }
  312. /* TextBuilder */
  313. pub struct TextBuilder {
  314. cache: TextCache,
  315. items: Vec<BuilderItem>,
  316. }
  317. enum BuilderItem {
  318. Position(f32, f32),
  319. Color(Vector4f),
  320. Font(String),
  321. Text(String),
  322. Scale(f32),
  323. VertAlign(VerticalAlign),
  324. HorzAlign(HorizontalAlign),
  325. Wrap,
  326. NoWrap,
  327. }
  328. impl TextBuilder {
  329. fn new(cache: &TextCache) -> Self {
  330. Self {
  331. cache: cache.clone(),
  332. items: Vec::new(),
  333. }
  334. }
  335. pub fn build(self) -> Result<Text, Error> {
  336. let mut sections = Vec::<OwnedSection<Extra>>::new();
  337. let mut scale = 20.0;
  338. let mut font_id = None;
  339. let mut color = Vector4f::new(0.0, 0.0, 0.0, 1.0);
  340. let mut position = None;
  341. let mut wrap = true;
  342. let mut vert_align = VerticalAlign::Top;
  343. let mut horz_align = HorizontalAlign::Left;
  344. for item in self.items {
  345. match item {
  346. BuilderItem::Text(text) => {
  347. let font_id = font_id.ok_or(Error::FontNotSet)?;
  348. let text = OwnedText::new(text)
  349. .with_extra(Extra { text_id: 0, color })
  350. .with_scale(scale)
  351. .with_font_id(font_id);
  352. let layout = if wrap {
  353. Layout::default_wrap()
  354. } else {
  355. Layout::default_single_line()
  356. };
  357. let layout = layout.v_align(vert_align).h_align(horz_align);
  358. match (sections.pop(), position.take()) {
  359. (Some(section), Some(pos)) => {
  360. sections.push(section);
  361. sections.push(
  362. OwnedSection::default()
  363. .with_screen_position(pos)
  364. .with_layout(layout)
  365. .add_text(text),
  366. );
  367. }
  368. (Some(section), None) => {
  369. sections.push(section.add_text(text));
  370. }
  371. (None, Some(pos)) => sections.push(
  372. OwnedSection::default()
  373. .with_screen_position(pos)
  374. .with_layout(layout)
  375. .add_text(text),
  376. ),
  377. (None, None) => sections
  378. .push(OwnedSection::default().with_layout(layout).add_text(text)),
  379. };
  380. }
  381. BuilderItem::Position(x, y) => position = Some((x, y)),
  382. BuilderItem::Color(c) => color = c,
  383. BuilderItem::Scale(s) => scale = s,
  384. BuilderItem::Font(path) => font_id = Some(self.cache.font(&path)?),
  385. BuilderItem::VertAlign(value) => vert_align = value,
  386. BuilderItem::HorzAlign(value) => horz_align = value,
  387. BuilderItem::Wrap => wrap = true,
  388. BuilderItem::NoWrap => wrap = false,
  389. }
  390. }
  391. let text = Text::new(&self.cache, sections)?;
  392. let weak = Rc::downgrade(&text.inner);
  393. self.cache.add_text(weak)?;
  394. Ok(text)
  395. }
  396. pub fn position(mut self, x: f32, y: f32) -> Self {
  397. self.items.push(BuilderItem::Position(x, y));
  398. self
  399. }
  400. pub fn font<S>(mut self, path: S) -> Self
  401. where
  402. S: Display,
  403. {
  404. self.items.push(BuilderItem::Font(path.to_string()));
  405. self
  406. }
  407. pub fn color(self, r: f32, g: f32, b: f32, a: f32) -> Self {
  408. self.color_vec(Vector4f::new(r, g, b, a))
  409. }
  410. pub fn color_vec(mut self, color: Vector4f) -> Self {
  411. self.items.push(BuilderItem::Color(color));
  412. self
  413. }
  414. pub fn text<S>(mut self, text: S) -> Self
  415. where
  416. S: Display,
  417. {
  418. self.items.push(BuilderItem::Text(text.to_string()));
  419. self
  420. }
  421. pub fn scale(mut self, scale: f32) -> Self {
  422. self.items.push(BuilderItem::Scale(scale));
  423. self
  424. }
  425. pub fn wrap(mut self) -> Self {
  426. self.items.push(BuilderItem::Wrap);
  427. self
  428. }
  429. pub fn nowrap(mut self) -> Self {
  430. self.items.push(BuilderItem::NoWrap);
  431. self
  432. }
  433. pub fn vert_align(mut self, value: VerticalAlign) -> Self {
  434. self.items.push(BuilderItem::VertAlign(value));
  435. self
  436. }
  437. pub fn horz_align(mut self, value: HorizontalAlign) -> Self {
  438. self.items.push(BuilderItem::HorzAlign(value));
  439. self
  440. }
  441. }
  442. /* Text */
  443. pub struct Text {
  444. cache: TextCache,
  445. inner: Rc<RefCell<TextInner>>,
  446. }
  447. struct TextInner {
  448. array: VertexArray,
  449. program: Rc<Program>,
  450. texture: Rc<RefCell<Texture>>,
  451. sections: Vec<OwnedSection<Extra>>,
  452. vertex_count: usize,
  453. color: Vector4f,
  454. }
  455. #[derive(Default, Debug, Clone)]
  456. struct Extra {
  457. text_id: usize,
  458. color: Vector4f,
  459. }
  460. #[derive(Default, Clone)]
  461. struct Vertex {
  462. text_id: usize,
  463. data: VertexData,
  464. }
  465. #[repr(C, packed)]
  466. #[derive(Default, Debug, Clone)]
  467. struct VertexData {
  468. pos_min: Vector2f,
  469. pos_max: Vector2f,
  470. tex_min: Vector2f,
  471. tex_max: Vector2f,
  472. color: Vector4f,
  473. }
  474. impl Text {
  475. fn new(cache: &TextCache, sections: Vec<OwnedSection<Extra>>) -> Result<Self, Error> {
  476. const STRIDE: gl::GLsizei = size_of::<VertexData>() as _;
  477. const SIZE_VEC2: gl::GLsizei = size_of::<Vector2f>() as _;
  478. const OFFSET_POS_MIN: gl::GLsizei = 0;
  479. const OFFSET_POS_MAX: gl::GLsizei = OFFSET_POS_MIN + SIZE_VEC2;
  480. const OFFSET_TEX_MIN: gl::GLsizei = OFFSET_POS_MAX + SIZE_VEC2;
  481. const OFFSET_TEX_MAX: gl::GLsizei = OFFSET_TEX_MIN + SIZE_VEC2;
  482. const OFFSET_COLOR: gl::GLsizei = OFFSET_TEX_MAX + SIZE_VEC2;
  483. let buffer = Buffer::new()?;
  484. let array = VertexArray::builder()
  485. .bind_buffer(buffer)
  486. .vertex_attrib_pointer(0, 2, DataType::Float, false, STRIDE, OFFSET_POS_MIN)?
  487. .vertex_attrib_pointer(1, 2, DataType::Float, false, STRIDE, OFFSET_POS_MAX)?
  488. .vertex_attrib_pointer(2, 2, DataType::Float, false, STRIDE, OFFSET_TEX_MIN)?
  489. .vertex_attrib_pointer(3, 2, DataType::Float, false, STRIDE, OFFSET_TEX_MAX)?
  490. .vertex_attrib_pointer(4, 4, DataType::Float, false, STRIDE, OFFSET_COLOR)?
  491. .build()?;
  492. let cache = cache.clone();
  493. let program = cache.0.borrow().manager.0.borrow().program.clone();
  494. let texture = cache.0.borrow().texture.clone();
  495. let inner = TextInner {
  496. array,
  497. program,
  498. texture,
  499. sections,
  500. vertex_count: 0,
  501. color: Vector4f::new(1.0, 1.0, 1.0, 1.0),
  502. };
  503. let text = Text {
  504. cache,
  505. inner: Rc::new(RefCell::new(inner)),
  506. };
  507. Ok(text)
  508. }
  509. pub fn render(&self) {
  510. self.render_offset(&Vector2f::new(0.0, 0.0));
  511. }
  512. pub fn render_offset(&self, pos: &Vector2f) {
  513. let inner = self.inner.borrow();
  514. let texture = inner.texture.borrow();
  515. let _guard = BindGuard::new(&*texture);
  516. let _guard = BindGuard::new(&inner.array);
  517. let _guard = BindGuard::new(&*inner.program);
  518. inner
  519. .program
  520. .uniform(1, Uniform::Vector4f(&inner.color))
  521. .warn("Unable to update color");
  522. inner
  523. .program
  524. .uniform(2, Uniform::Vector2f(pos))
  525. .warn("Unable to update text offset");
  526. gl::draw_arrays(gl::POINTS, 0, inner.vertex_count as _);
  527. }
  528. pub fn update<S>(&mut self, mut index: usize, text: S) -> Result<&Self, Error>
  529. where
  530. S: Display,
  531. {
  532. let mut inner = self.inner.borrow_mut();
  533. for section in &mut inner.sections {
  534. if index < section.text.len() {
  535. section.text[index].text = text.to_string();
  536. break;
  537. } else {
  538. index -= section.text.len();
  539. }
  540. }
  541. drop(inner);
  542. self.cache.update()?;
  543. Ok(self)
  544. }
  545. pub fn color(&self, color: Vector4f) -> &Self {
  546. let mut inner = self.inner.borrow_mut();
  547. inner.color = color;
  548. self
  549. }
  550. }
  551. impl TextInner {
  552. fn update(&mut self, data: Vec<VertexData>) -> Result<(), Error> {
  553. let buffers = self.array.buffers_mut();
  554. buffers[0].buffer_data(Usage::StaticDraw, &data)?;
  555. self.vertex_count = data.len();
  556. Ok(())
  557. }
  558. }
  559. impl Hash for Extra {
  560. fn hash<H>(&self, state: &mut H)
  561. where
  562. H: Hasher,
  563. {
  564. self.text_id.hash(state);
  565. OrderedFloat::from(self.color[0]).hash(state);
  566. OrderedFloat::from(self.color[1]).hash(state);
  567. OrderedFloat::from(self.color[2]).hash(state);
  568. OrderedFloat::from(self.color[3]).hash(state);
  569. }
  570. }
  571. impl PartialEq for Extra {
  572. fn eq(&self, other: &Self) -> bool {
  573. self.text_id.eq(&other.text_id) && self.color.eq(&other.color)
  574. }
  575. }