summaryrefslogblamecommitdiffstats
path: root/examples/custom_shader/src/main.rs
blob: 3bfa3a433a2ed51c3586b6d2ff23451009d3b50c (plain) (tree)
1
2
3
4
5
6
7
8
9
          
 
                 


                        
                               
                                                                           
                 
           

                                                                      
  






                                             
                 

 















                                                                   






                                      







                                                                            

                                                   

                                               
                                       

                                    
                                                     

                                               
                                                    

                                                  
                                               










                                                                         

                                                  





                                              
                                                                             




                                    
                                             







                                        
                                                                      

                                                      
                                                






                           
                                                                      

                                                      
                                                






                           
                                                                      

                                                      
                                                









                                                              
                        

                                            
                    
                                                                         
 





                                                                           












                                                           
mod scene;

use scene::Scene;

use iced::executor;
use iced::time::Instant;
use iced::widget::shader::wgpu;
use iced::widget::{checkbox, column, container, row, shader, slider, text};
use iced::window;
use iced::{
    Alignment, Application, Color, Command, Element, Length, Renderer,
    Subscription, Theme,
};

fn main() -> iced::Result {
    IcedCubes::run(iced::Settings::default())
}

struct IcedCubes {
    start: Instant,
    scene: Scene,
}

#[derive(Debug, Clone)]
enum Message {
    CubeAmountChanged(u32),
    CubeSizeChanged(f32),
    Tick(Instant),
    ShowDepthBuffer(bool),
    LightColorChanged(Color),
}

impl Application for IcedCubes {
    type Executor = executor::Default;
    type Message = Message;
    type Theme = Theme;
    type Flags = ();

    fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
        (
            Self {
                start: Instant::now(),
                scene: Scene::new(),
            },
            Command::none(),
        )
    }

    fn title(&self) -> String {
        "Iced Cubes".to_string()
    }

    fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
        match message {
            Message::CubeAmountChanged(amount) => {
                self.scene.change_amount(amount);
            }
            Message::CubeSizeChanged(size) => {
                self.scene.size = size;
            }
            Message::Tick(time) => {
                self.scene.update(time - self.start);
            }
            Message::ShowDepthBuffer(show) => {
                self.scene.show_depth_buffer = show;
            }
            Message::LightColorChanged(color) => {
                self.scene.light_color = color;
            }
        }

        Command::none()
    }

    fn view(&self) -> Element<'_, Self::Message, Renderer<Self::Theme>> {
        let top_controls = row![
            control(
                "Amount",
                slider(
                    1..=scene::MAX,
                    self.scene.cubes.len() as u32,
                    Message::CubeAmountChanged
                )
                .width(100)
            ),
            control(
                "Size",
                slider(0.1..=0.25, self.scene.size, Message::CubeSizeChanged)
                    .step(0.01)
                    .width(100),
            ),
            checkbox(
                "Show Depth Buffer",
                self.scene.show_depth_buffer,
                Message::ShowDepthBuffer
            ),
        ]
        .spacing(40);

        let bottom_controls = row![
            control(
                "R",
                slider(0.0..=1.0, self.scene.light_color.r, move |r| {
                    Message::LightColorChanged(Color {
                        r,
                        ..self.scene.light_color
                    })
                })
                .step(0.01)
                .width(100)
            ),
            control(
                "G",
                slider(0.0..=1.0, self.scene.light_color.g, move |g| {
                    Message::LightColorChanged(Color {
                        g,
                        ..self.scene.light_color
                    })
                })
                .step(0.01)
                .width(100)
            ),
            control(
                "B",
                slider(0.0..=1.0, self.scene.light_color.b, move |b| {
                    Message::LightColorChanged(Color {
                        b,
                        ..self.scene.light_color
                    })
                })
                .step(0.01)
                .width(100)
            )
        ]
        .spacing(40);

        let controls = column![top_controls, bottom_controls,]
            .spacing(10)
            .padding(20)
            .align_items(Alignment::Center);

        let shader =
            shader(&self.scene).width(Length::Fill).height(Length::Fill);

        container(column![shader, controls].align_items(Alignment::Center))
            .width(Length::Fill)
            .height(Length::Fill)
            .center_x()
            .center_y()
            .into()
    }

    fn subscription(&self) -> Subscription<Self::Message> {
        window::frames().map(Message::Tick)
    }
}

fn control<'a>(
    label: &'static str,
    control: impl Into<Element<'a, Message>>,
) -> Element<'a, Message> {
    row![text(label), control.into()].spacing(10).into()
}