1 object FontColor = 2 val black : u8 = 0 3 val blue : u8 = 1 4 val green : u8 = 2 5 val red : u8 = 3 6 val gray : u8 = 4 7 val light_gray : u8 = 5 8 let count : u8 = 6 9 10 object TextMesh = 11 let palette = [Vector3.gray 0.1 12 Vector3 0.1 0.3 0.8 13 Vector3 0.1 0.5 0.1 14 Vector3 0.7 0.12 0 15 Vector3.gray 0.35 16 Vector3.gray 0.5] 17 18 val advance_char = 'A' 19 20 type TextMeshMemory = 21 val memory : MeshMemory 22 val char_height : u32 23 val line_height : u32 24 val advance : u32 25 val margin : Margin 26 val width : u32 27 val height : u32 28 29 def discard = 30 memory.discard 31 32 is Discard 33 34 type Font 35 def text_margin self = 36 let mut margin = self.margin divisor = 2.5 37 margin.down *= 20 38 margin 39 40 let is_in_selection (position : TextPos 41 maybe_selection : Option<(TextPos, TextPos)>) = 42 case maybe_selection of 43 None -> false 44 Some (from, to) -> position >= from && position < to 45 46 module text_mesh 47 48 def create (text : Slice<TextLine> 49 visible_up : u32 50 visible_down : u32 51 selection : Option<(TextPos, TextPos)> 52 font : Font) = 53 let space_width = font.space_width 54 let char_height = font.char_height 55 let rectangles = font.rectangles 56 let line_height = font.line_height 57 let font_width = font.memory.width 58 let font_height = font.memory.height 59 let font_height_rgba = font.memory_rgba.height 60 let margin = font.text_margin 61 62 let quads = List.new 63 let mut x = margin.left as i32 64 let mut y = margin.up as i32 65 let mut width : u32 = 0 66 let mut maybe_prev_c : Option<Char> = None 67 68 let skip_count = if visible_up < y as u32 69 then 0 70 else (visible_up - y as u32) / line_height 71 72 let after_last_line_index = 73 if visible_down < margin.up 74 then 0 75 else (visible_down - margin.up) / line_height + 1 76 |> min text.size as i32 77 78 let mut line_index = skip_count 79 y += line_index * line_height |> as<i32> 80 81 for l = line_index as i32 until after_last_line_index do 82 let line = text[l] 83 for i = 0 until line.length do 84 let char = line[i] 85 let c = 86 let c = char.char 87 if c == ' ' || c == '\n' || rectangles.contains c 88 then c 89 else Sys.unprintable_char 90 91 let position = TextPos line_index i 92 let is_eol = c == '\n' 93 let color_index = 94 if is_in_selection position selection 95 then char.color + FontColor.count 96 else char.color 97 98 let (offset, char_width) = 99 let prev_c = maybe_prev_c.unwrap_or ' ' 100 let offset = font.offset prev_c c 101 let w = if c == ' ' || is_eol 102 then space_width 103 else rectangles[c].width 104 105 (offset, w) 106 107 if not is_eol then 108 x += offset 109 110 if c <> ' ' && not is_eol then 111 let rectangle = rectangles[c] 112 let left = rectangle.left as f32 / font_width as f32 113 let right = rectangle.right as f32 / font_width as f32 114 let down = rectangle.down + color_index as u32 * font_height 115 |> as<f32> / font_height_rgba as f32 116 117 let up = rectangle.up + color_index as u32 * font_height 118 |> as<f32> / font_height_rgba as f32 119 120 let quad = Quad 121 up_left = Vector3 x.as<f32> y.as<f32> 0 122 up_right = Vector3 (x as f32 + rectangle.width as f32) y.as<f32> 0 123 down_left = Vector3 x.as<f32> (y as f32 + rectangle.height as f32) 0 124 down_right = Vector3 125 x = x as f32 + rectangle.width as f32 126 y = y as f32 + rectangle.height as f32 127 z = 0 128 129 uv_up_left = Vector2 left down 130 uv_up_right = Vector2 right down 131 uv_down_left = Vector2 left up 132 uv_down_right = Vector2 right up 133 color = TextMesh.palette[char.color as u32] 134 135 quads.add quad 136 137 if not is_eol then 138 x += char_width as i32 139 140 if x as u32 > width then 141 width = x as u32 142 143 maybe_prev_c = Some c 144 145 x = margin.left as i32 146 y += line_height as i32 147 maybe_prev_c = None 148 line_index += 1 149 150 width += margin.right 151 let memory = MeshMemory.from_quads quads.as_slice 152 let advance_char_offset = 153 font.offsets[(TextMesh.advance_char, TextMesh.advance_char)] 154 155 assert advance_char_offset == 0 156 let advance = rectangles[TextMesh.advance_char].width 157 let height = margin.up + margin.down + (text.size - 1) * line_height + char_height 158 159 TextMeshMemory =memory =char_height =line_height 160 =advance =margin =width =height 161