aboutsummaryrefslogblamecommitdiffstats
path: root/src/render.rs
blob: 733f0c02b8325651847ac5a78d4e12e21cd3b3e1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                                                  
              






                                                    

















                                                                                  



                                       
                            
                                      
                            


                                                 
 




                                                  





                                                            
          
                     
    
 

                                                 


                                                
                              
                                                                          

                         
 
             
                                


















                                                                 
         









                                                                                                    
              
                                                            
        





                                                    



                                                               








                                                             
 








                                                           
      
                                
                                
     






                                                        
                        
                                  
                                                                        





















































                                                                                               
               


                                           

         
















































                                                                     





                                                               










                                                                 
                                                          
                                                              


                      
                                       


         





                                                                                                   
 

                         

                               














                                                                       
           
               
          























                                                                                             
       
 
                                                                                      
 













                                                                                                  



                                                               










                                                                

   
use crate::font::BakedFont;
use crate::generated::fonts::{FONT_CHERRY_BOMB_ONE, FONT_GALMURI};
use rand::Rng;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::Rect;
use sdl2::render::{Canvas, Texture, TextureCreator};
use sdl2::surface::Surface;
use sdl2::video::{Window, WindowContext};
use std::ops::DerefMut;

fn dvd_logo_offset(t: f64, screen_size_x: f64, screen_size_y: f64) -> (f64, f64) {
  let offset_x = t % (screen_size_x * 2.0);
  let offset_x = if offset_x > screen_size_x {
    screen_size_x * 2.0 - offset_x
  } else {
    offset_x
  };

  let offset_y = t % (screen_size_y * 2.0);
  let offset_y = if offset_y > screen_size_y {
    screen_size_y * 2.0 - offset_y
  } else {
    offset_y
  };

  (offset_x, offset_y)
}

pub const START_UWUSPACE: f64 = 0.0;
pub const START_BOUNCE: f64 = 0.5;
pub const START_SIN: f64 = 1.5;
pub const START_COMETOCOSIN: f64 = 2.5;
#[cfg(not(feature = "32k"))]
pub const SCENE_GREETINGS: f64 = 32.0;
#[cfg(not(feature = "32k"))]
pub const JUST_DVD: f64 = SCENE_GREETINGS + 28.0;

pub const PRINT_TIME: bool = true;

pub fn render(
  canvas: &mut Canvas<Window>,
  texture_creator: &TextureCreator<WindowContext>,
  time_seconds: f64,
) {
  if PRINT_TIME {
    println!("Time: {time_seconds}\x1b[F");
  }
  let colourthing = ((time_seconds * 60.0) % 510.0).round();
  let colourthing = if colourthing > 255.0 {
    (255.0 - (colourthing - 255.0)) as u8
  } else {
    colourthing as u8
  };

  let win_size = canvas.window().drawable_size();

  canvas.set_draw_color(Color::RGB(12, 12, 12));
  canvas.clear();

  #[cfg(not(feature = "32k"))]
  let is_dvd = time_seconds < SCENE_GREETINGS || time_seconds >= JUST_DVD;
  #[cfg(feature = "32k")]
  let is_dvd = true;

  if is_dvd {
    #[cfg(not(feature = "32k"))]
    let time_seconds = if time_seconds >= JUST_DVD {
      time_seconds - JUST_DVD + 15.0
    } else {
      time_seconds
    };
    if time_seconds >= START_UWUSPACE {
      let bounce_speed = 90.0;
      let padding_x = 16.0;
      let padding_y = 16.0;
      let (offset_x, offset_y) = if time_seconds > START_BOUNCE {
        let mut uwu_width = padding_x;
        let mut uwu_height: f32 = padding_y;
        for c in "UwU-Space".chars() {
          let char = FONT_CHERRY_BOMB_ONE.get_char(c);
          uwu_width += char.advance_width;
          let nh = f32::from(char.height) + padding_y;
          if nh > uwu_height {
            uwu_height = nh;
          }
        }
        let virtual_screen_size = (
          f64::from(win_size.0) - (uwu_width + padding_x),
          f64::from(win_size.1) - f64::from(uwu_height + padding_y),
        );
        let t = (time_seconds - START_BOUNCE) * bounce_speed;
        let (offset_x, offset_y) = dvd_logo_offset(t, virtual_screen_size.0, virtual_screen_size.1);
        (
          (padding_x + offset_x).round() as i32,
          (f64::from(padding_y) + offset_y).round() as i32,
        )
      } else {
        (padding_x.round() as i32, padding_y.round() as i32)
      };
      let mut offset: f64 = 0.0;
      for c in "UwU-Space".chars() {
        let char = FONT_CHERRY_BOMB_ONE.get_char(c);
        canvas
          .copy(
            &char
              .to_texture(
                texture_creator,
                Color::RGB(colourthing, 64, 255 - colourthing),
              )
              .unwrap(),
            None,
            char.to_rect(offset as i32 + offset_x, offset_y),
          )
          .unwrap();
        offset += char.advance_width;
      }
    }
  }

  #[cfg(not(feature = "32k"))]
  let no_other_rendering = time_seconds >= JUST_DVD;
  #[cfg(feature = "32k")]
  let no_other_rendering = false;
  #[cfg(not(feature = "32k"))]
  let is_greetings_scene = time_seconds >= SCENE_GREETINGS;
  #[cfg(feature = "32k")]
  let is_greetings_scene = false;
  if no_other_rendering {
    //
  } else if is_greetings_scene {
    #[cfg(not(feature = "32k"))]
    {
      let time_seconds = time_seconds - SCENE_GREETINGS;
      // Greetings
      let greeting_header_duration = 4.0;
      {
        let mut rng = rand::thread_rng();

        let mut i = 0.0;
        let strlen = 43;
        let mut uwuoffset_x = 0.0;
        for c in "Greetings by UwU-Space and /dev/urandom to:".chars() {
          let is_not_uwu = i <= 12.0 || i >= 22.0;
          let char = if is_not_uwu {
            FONT_GALMURI.get_char(c)
          } else {
            FONT_CHERRY_BOMB_ONE.get_char(c)
          };
          canvas
            .copy(
              &char
                .to_texture(
                  texture_creator,
                  Color::RGB(colourthing, 64, 255 - colourthing),
                )
                .unwrap(),
              None,
              char.to_rect(
                uwuoffset_x as i32 + 18 + rng.gen_range(-2..2),
                (if is_not_uwu { 24 } else { 16 }) + rng.gen_range(-3..3),
              ),
            )
            .unwrap();
          uwuoffset_x += char.advance_width;
          i += 1.0;
          if i > (time_seconds * (f64::from(strlen) / greeting_header_duration)).floor() {
            break;
          }
        }
        let mut offset_y = 36;
        let mut line_index = 0;
        for line in [
          vec!["Venty", "Erdit", "Kaede", "dui"],
          vec!["Deja", "vimja", "cy", "alu"],
          vec!["sashu", "expired bread", "gaben"],
        ] {
          offset_y += 24;
          let mut offset_x = (f64::from(line_index) * 90.0) + f64::from(win_size.0)
            - ((time_seconds - greeting_header_duration) * (f64::from(win_size.0) * 0.078125));
          line_index += 1;

          for c in line.join("   ").chars() {
            let char = FONT_GALMURI.get_char(c);
            canvas
              .copy(
                &char
                  .to_texture(
                    texture_creator,
                    Color::RGB(colourthing, 64, 255 - colourthing),
                  )
                  .unwrap(),
                None,
                char.to_rect(
                  offset_x as i32 + 18 + rng.gen_range(-2..2),
                  offset_y + rng.gen_range(-2..2),
                ),
              )
              .unwrap();
            offset_x += char.advance_width;
          }
        }
      }
      // We did most of this at mountainbytes
      {
        let mut offset = 0.0;
        let mut rng = rand::thread_rng();

        for c in "we did 90% onsite at mountainbytes 2025,".chars() {
          let char = FONT_GALMURI.get_char(c);
          canvas
            .copy(
              &char
                .to_texture(
                  texture_creator,
                  Color::RGB(colourthing, 64, 255 - colourthing),
                )
                .unwrap(),
              None,
              char.to_rect(
                offset as i32 + 18 + rng.gen_range(-2..2),
                win_size.1 as i32 - 64 + rng.gen_range(-2..2),
              ),
            )
            .unwrap();
          offset += char.advance_width;
        }
      }
      {
        let mut offset = 0.0;
        let mut rng = rand::thread_rng();

        for c in "the rest 2 months ago".chars() {
          let char = FONT_GALMURI.get_char(c);
          canvas
            .copy(
              &char
                .to_texture(
                  texture_creator,
                  Color::RGB(colourthing, 64, 255 - colourthing),
                )
                .unwrap(),
              None,
              char.to_rect(
                offset as i32 + 24 + rng.gen_range(-2..2),
                win_size.1 as i32 - 32 + rng.gen_range(-2..2),
              ),
            )
            .unwrap();
          offset += char.advance_width;
        }
      }
      // Sorry for shit invite
      {
        let mut offset = 0.0;
        let mut rng = rand::thread_rng();

        for c in "sorry for shit invite we have adhd".chars() {
          let char = FONT_GALMURI.get_char(c);
          canvas
            .copy(
              &char
                .to_texture(
                  texture_creator,
                  Color::RGB(colourthing, 64, 255 - colourthing),
                )
                .unwrap(),
              None,
              char.to_rect(
                offset as i32 + 18 + rng.gen_range(-2..2),
                win_size.1 as i32 - 96 + rng.gen_range(-2..2),
              ),
            )
            .unwrap();
          offset += char.advance_width;
        }
      }
    }
  } else {
    if time_seconds >= START_SIN {
      let time_seconds = time_seconds - START_SIN;
      let base_sin_offset = time_seconds * 0.1;
      let sin_offset = base_sin_offset - 0.75;
      let mut sin_surface = Surface::new(win_size.0, win_size.1, PixelFormatEnum::RGBA32).unwrap();

      let w = win_size.0;
      let h = win_size.1;
      let f64_w = f64::from(w);
      let f64_h = f64::from(h);
      let f = &mut sin_surface.deref_mut().without_lock_mut().unwrap();

      let min_x_pos = (if base_sin_offset > 1.0 {
        0.0
      } else {
        1.0 - base_sin_offset
      }) * f64_w;

      for x in 0..w {
        let f64_x = f64::from(x);
        let out_of_frame = f64_x < min_x_pos;
        let sin_x = {
          let mut sin_x = f64_x + (sin_offset * f64_w);
          if sin_x > f64_w {
            sin_x -= f64_w;
          }
          sin_x
        };
        let sin_y =
          ((f64::sin(sin_x * (3.141 * 2.0) / f64_w) + 1.0) * (f64_h / 2.0)).floor() as usize;
        // let sin_idx = (sin_y * w as usize + x as usize) * 4;

        for y in 0..h {
          let idx = (y * w + x) as usize * 4;
          let cx = x * 512 / w;
          f[idx] = (122 - (cx / 8)) as u8;
          f[idx + 1] = (255 - (cx / 2)) as u8;
          f[idx + 2] = (cx / 2) as u8;
          f[idx + 3] = if out_of_frame {
            0
          } else if sin_y < y as usize {
            let v: u16 = if idx % 5 == 0 { 255 } else { 122 };
            let v = if (sin_y + 3) < (y as usize) {
              v
            } else {
              v * 2 / 3
            };
            v as u8
          } else {
            0
          };
        }
      }

      let sin_texture = Texture::from_surface(&sin_surface, texture_creator).unwrap();

      canvas
        .copy(&sin_texture, None, Rect::new(0, 0, win_size.0, win_size.1))
        .unwrap();
    }
    if time_seconds >= START_COMETOCOSIN {
      let time_seconds = time_seconds - START_COMETOCOSIN;
      let wrap_width = f64::from(win_size.0);
      let mut offset = (18.0 + (time_seconds * 32.0)) % wrap_width;
      // WARNING: we wrap this! if the text is wider than the window, this whole thing falls apart
      for c in "Come to Cosin25 :3".chars() {
        let char = FONT_GALMURI.get_char(c);
        canvas
          .copy(
            &char
              .to_texture(
                texture_creator,
                Color::RGB(colourthing, 64, 255 - colourthing),
              )
              .unwrap(),
            None,
            char.to_rect(offset as i32, win_size.1 as i32 - 32),
          )
          .unwrap();
        offset += char.advance_width;
        if offset > wrap_width {
          offset -= wrap_width;
        }
      }
    }
  }
}