ui.cc (9737B)
1 #include "platform_ui.h" 2 #include "array.h" 3 #include "input.h" 4 #include "textbox.h" 5 #include "gitversion.h" 6 7 static TextBox main_text; 8 static TextBox chat_text; 9 10 static int window_width, window_height; 11 12 typedef struct { 13 char c; 14 15 Colour fg; 16 bool bold; 17 } StatusChar; 18 19 static DynamicArray< StatusChar > status; 20 static bool status_dirty = false; 21 22 void ui_init() { 23 ZoneScoped; 24 25 textbox_init( &main_text, SCROLLBACK_SIZE ); 26 textbox_init( &chat_text, CHAT_ROWS ); 27 28 ui_main_print( "> Mud Gangster ", 0, SYSTEM, BLACK, false ); 29 ui_main_print( APP_VERSION, 0, SYSTEM, BLACK, true ); 30 } 31 32 void ui_term() { 33 textbox_destroy( &main_text ); 34 textbox_destroy( &chat_text ); 35 } 36 37 void ui_fill_rect( int left, int top, int width, int height, Colour colour, bool bold ) { 38 platform_fill_rect( left, top, width, height, colour, bold ); 39 } 40 41 void ui_draw_char( int left, int top, char c, Colour colour, bool bold, bool force_bold_font ) { 42 int fw, fh; 43 ui_get_font_size( &fw, &fh ); 44 45 int left_spacing = fw / 2; 46 int right_spacing = fw - left_spacing; 47 int line_height = fh + SPACING; 48 int top_spacing = line_height / 2; 49 int bot_spacing = line_height - top_spacing; 50 51 // TODO: not the right char... 52 // if( u8( c ) == 155 ) { // fill 53 // ui_fill_rect( left, top, fw, fh, colour, bold ); 54 // return; 55 // } 56 57 // TODO: this has a vertical seam. using textbox-space coordinates would help 58 if( u8( c ) == 176 ) { // light shade 59 for( int y = 0; y < fh; y += 3 ) { 60 for( int x = y % 6 == 0 ? 0 : 1; x < fw; x += 2 ) { 61 ui_fill_rect( left + x, top + y, 1, 1, colour, bold ); 62 } 63 } 64 return; 65 } 66 67 // TODO: this has a horizontal seam but so does mm2k 68 if( u8( c ) == 177 ) { // medium shade 69 for( int y = 0; y < fh; y += 2 ) { 70 for( int x = y % 4 == 0 ? 1 : 0; x < fw; x += 2 ) { 71 ui_fill_rect( left + x, top + y, 1, 1, colour, bold ); 72 } 73 } 74 return; 75 } 76 77 // TODO: this probably has a horizontal seam 78 if( u8( c ) == 178 ) { // heavy shade 79 for( int y = 0; y < fh + SPACING; y++ ) { 80 for( int x = y % 2 == 0 ? 1 : 0; x < fw; x += 2 ) { 81 ui_fill_rect( left + x, top + y, 1, 1, colour, bold ); 82 } 83 } 84 return; 85 } 86 87 if( u8( c ) == 179 ) { // vertical 88 ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold ); 89 return; 90 // set_fg( colour, bold ); 91 // const char asdf[] = "│"; 92 // Xutf8DrawString( UI.display, UI.back_buffer, ( bold ? Style.fontBold : Style.font ).font, UI.gc, left, top + Style.font.ascent + SPACING, asdf, sizeof( asdf ) - 1 ); 93 } 94 95 if( u8( c ) == 180 ) { // right stopper 96 ui_fill_rect( left, top + top_spacing, left_spacing, 1, colour, bold ); 97 ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold ); 98 return; 99 } 100 101 if( u8( c ) == 186 ) { // double vertical 102 ui_fill_rect( left + left_spacing - 1, top, 1, line_height, colour, bold ); 103 ui_fill_rect( left + left_spacing + 1, top, 1, line_height, colour, bold ); 104 return; 105 } 106 107 if( u8( c ) == 187 ) { // double top right 108 ui_fill_rect( left, top + top_spacing - 1, right_spacing + 1, 1, colour, bold ); 109 ui_fill_rect( left + left_spacing + 1, top + top_spacing - 1, 1, bot_spacing + 1, colour, bold ); 110 ui_fill_rect( left, top + top_spacing + 1, right_spacing - 1, 1, colour, bold ); 111 ui_fill_rect( left + left_spacing - 1, top + top_spacing + 1, 1, bot_spacing - 1, colour, bold ); 112 return; 113 } 114 115 if( u8( c ) == 188 ) { // double bottom right 116 ui_fill_rect( left, top + top_spacing + 1, right_spacing + 1, 1, colour, bold ); 117 ui_fill_rect( left + left_spacing + 1, top, 1, top_spacing + 1, colour, bold ); 118 ui_fill_rect( left, top + top_spacing - 1, right_spacing - 1, 1, colour, bold ); 119 ui_fill_rect( left + left_spacing - 1, top, 1, top_spacing - 1, colour, bold ); 120 return; 121 } 122 123 if( u8( c ) == 191 ) { // top right 124 ui_fill_rect( left, top + top_spacing, left_spacing, 1, colour, bold ); 125 ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold ); 126 return; 127 } 128 129 if( u8( c ) == 192 ) { // bottom left 130 ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold ); 131 ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold ); 132 return; 133 } 134 135 if( u8( c ) == 193 ) { // bottom stopper 136 ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold ); 137 ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold ); 138 return; 139 } 140 141 if( u8( c ) == 194 ) { // top stopper 142 ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold ); 143 ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold ); 144 return; 145 } 146 147 if( u8( c ) == 195 ) { // left stopper 148 ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold ); 149 ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold ); 150 return; 151 } 152 153 if( u8( c ) == 196 ) { // horizontal 154 ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold ); 155 return; 156 } 157 158 if( u8( c ) == 197 ) { // cross 159 ui_fill_rect( left, top + top_spacing, fw, 1, colour, bold ); 160 ui_fill_rect( left + left_spacing, top, 1, line_height, colour, bold ); 161 return; 162 } 163 164 if( u8( c ) == 200 ) { // double bottom left 165 ui_fill_rect( left + left_spacing - 1, top + top_spacing + 1, right_spacing + 1, 1, colour, bold ); 166 ui_fill_rect( left + left_spacing - 1, top, 1, top_spacing + 1, colour, bold ); 167 ui_fill_rect( left + left_spacing + 1, top + top_spacing - 1, right_spacing - 1, 1, colour, bold ); 168 ui_fill_rect( left + left_spacing + 1, top, 1, top_spacing - 1, colour, bold ); 169 return; 170 } 171 172 if( u8( c ) == 201 ) { // double top left 173 ui_fill_rect( left + left_spacing - 1, top + top_spacing - 1, right_spacing + 1, 1, colour, bold ); 174 ui_fill_rect( left + left_spacing - 1, top + top_spacing - 1, 1, bot_spacing + 1, colour, bold ); 175 ui_fill_rect( left + left_spacing + 1, top + top_spacing + 1, right_spacing - 1, 1, colour, bold ); 176 ui_fill_rect( left + left_spacing + 1, top + top_spacing + 1, 1, bot_spacing - 1, colour, bold ); 177 return; 178 } 179 180 if( u8( c ) == 205 ) { // double horizontal 181 ui_fill_rect( left, top + top_spacing - 1, fw, 1, colour, bold ); 182 ui_fill_rect( left, top + top_spacing + 1, fw, 1, colour, bold ); 183 return; 184 } 185 186 if( u8( c ) == 217 ) { // bottom right 187 ui_fill_rect( left, top + top_spacing, right_spacing, 1, colour, bold ); 188 ui_fill_rect( left + left_spacing, top, 1, top_spacing, colour, bold ); 189 return; 190 } 191 192 if( u8( c ) == 218 ) { // top left 193 ui_fill_rect( left + left_spacing, top + top_spacing, right_spacing, 1, colour, bold ); 194 ui_fill_rect( left + left_spacing, top + top_spacing, 1, bot_spacing, colour, bold ); 195 return; 196 } 197 198 platform_draw_char( left, top, c, colour, bold, force_bold_font ); 199 } 200 201 void ui_clear_status() { 202 status.clear(); 203 status_dirty = true; 204 } 205 206 void ui_statusAdd( char c, Colour fg, bool bold ) { 207 status.add( { c, fg, bold } ); 208 status_dirty = true; 209 } 210 211 void ui_draw_status() { 212 int fw, fh; 213 ui_get_font_size( &fw, &fh ); 214 215 ui_fill_rect( 0, window_height - PADDING * 4 - fh * 2, window_width, fh + PADDING * 2, COLOUR_STATUSBG, false ); 216 217 for( size_t i = 0; i < status.size(); i++ ) { 218 StatusChar sc = status[ i ]; 219 220 int x = PADDING + i * fw; 221 int y = window_height - ( PADDING * 3 ) - fh * 2 - SPACING; 222 ui_draw_char( x, y, sc.c, sc.fg, sc.bold ); 223 } 224 225 platform_make_dirty( 0, window_height - PADDING * 4 - fh * 2, window_width, fh + PADDING * 2 ); 226 227 status_dirty = false; 228 } 229 230 void ui_redraw_dirty() { 231 if( main_text.dirty ) 232 textbox_draw( &main_text ); 233 if( chat_text.dirty ) 234 textbox_draw( &chat_text ); 235 if( input_is_dirty() ) 236 input_draw(); 237 if( status_dirty ) 238 ui_draw_status(); 239 } 240 241 void ui_redraw_everything() { 242 int fw, fh; 243 ui_get_font_size( &fw, &fh ); 244 245 ui_fill_rect( 0, 0, window_width, window_height, COLOUR_BG, false ); 246 247 input_draw(); 248 ui_draw_status(); 249 250 textbox_draw( &main_text ); 251 textbox_draw( &chat_text ); 252 253 int spacerY = ( 2 * PADDING ) + ( fh + SPACING ) * CHAT_ROWS; 254 ui_fill_rect( 0, spacerY, window_width, 1, COLOUR_STATUSBG, false ); 255 } 256 257 void ui_main_newline() { 258 textbox_newline( &main_text ); 259 } 260 261 void ui_main_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) { 262 textbox_add( &main_text, str, len, fg, bg, bold ); 263 } 264 265 void ui_chat_newline() { 266 textbox_newline( &chat_text ); 267 } 268 269 void ui_chat_print( const char * str, size_t len, Colour fg, Colour bg, bool bold ) { 270 textbox_add( &chat_text, str, len, fg, bg, bold ); 271 } 272 273 void ui_update_layout() { 274 int fw, fh; 275 ui_get_font_size( &fw, &fh ); 276 277 textbox_set_pos( &chat_text, PADDING, PADDING ); 278 textbox_set_size( &chat_text, window_width - ( 2 * PADDING ), ( fh + SPACING ) * CHAT_ROWS ); 279 280 textbox_set_pos( &main_text, PADDING, ( PADDING * 2 ) + CHAT_ROWS * ( fh + SPACING ) + 1 ); 281 textbox_set_size( &main_text, window_width - ( 2 * PADDING ), window_height 282 - ( ( ( fh + SPACING ) * CHAT_ROWS ) + ( PADDING * 2 ) ) 283 - ( ( fh * 2 ) + ( PADDING * 5 ) ) - 1 284 ); 285 286 input_set_pos( PADDING, window_height - PADDING - fh ); 287 input_set_size( window_width - PADDING * 2, fh ); 288 } 289 290 void ui_resize( int width, int height ) { 291 int old_width = window_width; 292 int old_height = window_height; 293 294 window_width = width; 295 window_height = height; 296 297 if( window_width == old_width && window_height == old_height ) 298 return; 299 300 ui_update_layout(); 301 } 302 303 void ui_scroll( int offset ) { 304 textbox_scroll( &main_text, offset ); 305 } 306 307 void ui_page_down() { 308 textbox_page_down( &main_text ); 309 } 310 311 void ui_page_up() { 312 textbox_page_up( &main_text ); 313 } 314 315 void ui_mouse_down( int x, int y ) { 316 textbox_mouse_down( &main_text, x, y ); 317 textbox_mouse_down( &chat_text, x, y ); 318 } 319 320 void ui_mouse_up( int x, int y ) { 321 textbox_mouse_up( &main_text, x, y ); 322 textbox_mouse_up( &chat_text, x, y ); 323 } 324 325 void ui_mouse_move( int x, int y ) { 326 textbox_mouse_move( &main_text, x, y ); 327 textbox_mouse_move( &chat_text, x, y ); 328 }