1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use ggez::{*, graphics::Color};
use mooeye::{ui, ui::UiContent, scene_manager};


// # UI, UI elements, UI element builder and basic messages
// In this example, our scene struct contains a gui consiting of a single UI element.


/// Another very basic scene. This time, it contains a UiElement called gui.
/// This is the root element of you GUI, and any interactions and acces to the GUI of this scene happen through this object.
pub struct CScene{
    /// The scenes GUI root element.
    gui: ui::UiElement<()>,
}

impl CScene {
    /// Creates a new CScene.
    /// Once again, we have no special parameters. Often, you ```new``` function will contain a lot of code
    /// basically describing the laoyut of you GUI, so this can get lengthy.
    /// Split in to helper functions as appropriate!    
    pub fn new(ctx: &Context) -> Self{
        // The scene constructor is usually the place where we create the state of our UI.
        // In this case, we will only create a single element.

        let text_element = 
        // First, we create anything implementing UiContent. ggez Image and Text do that, so we'll use a Text.
        // You can format that text as you can in ggez, so let's use our custom font and set a larger size.
        graphics::Text::new("Take me back!") 
        .set_font("Bahnschrift")
        .set_scale(32.)
        // Then we'll convert that content to an UiElementBuilder. We have to give it an ID.
        // ID 0 is reserved for elements not sending messages, but since we want to use the Text as a button, we'll use 1.
        .to_owned()
        .to_element_builder(1, ctx) 
        // We can now use the functions of UiElementBuilder to style and position our element.
        // First, we'll set the visuals using a Visuals struct.
        .with_visuals(ui::Visuals::new(
            Color::from_rgb(49, 53, 69),
            Color::from_rgb(250, 246, 230),
            4.,8. 
        ))
        // Additionally, you can add keycodes that make your element respond to key presses as it would respond to clicks
        .with_trigger_key(winit::event::VirtualKeyCode::A)
        // We can also set the alignment within the window...
        .with_alignment(ui::Alignment::Min, ui::Alignment::Center)
        // ... offset the element (note that we can pass None into most of these functions to leave the presets for one dimension untouched) ...
        .with_offset(25., None)
        // ... or set its padding ...
        .with_padding((5., 10., 5., 10.))
        // ... and size. Here, we use a special method 'shrink' that sets the size of both dimension to shrink without changing their boundaries.
        // Using the function .with_size would require us to also pass in boundaries.
        .as_shrink()
        // Finally, we build the element.
        .build();

        Self{gui: text_element}
    }

}

impl scene_manager::Scene for CScene{
    fn update(&mut self, ctx: &mut Context) -> Result<scene_manager::SceneSwitch, GameError> {

        // Usually, we would first perform our game logic here, but this scene has no logic.


        // You can get messages sent by your UI with the manage_messages function.
        // Usually, you also pass in extern messages created by your game state to bring the UI up to date. Since we don't have a game state, we can pass None (this is useful for menu scenes and similar).
        let messages = self.gui.manage_messages(ctx, None);

        // We then check if our button has been clicked by creating a Clicked event with the correct ID and checking if it is contained in the messages set.
        if messages.contains(&ui::UiMessage::Triggered(1)){
            // If it is, we end the current scene (and return to the previous one) by popping it off the stack.
            return Ok(scene_manager::SceneSwitch::pop(1));
        }

        // Otherwise, no scene switch is neccessary.
        Ok(scene_manager::SceneSwitch::None)
    }

    fn draw(&mut self, ctx: &mut Context, mouse_listen: bool) -> Result<(), GameError> {
        // Once again, we first create a canvas and set a pixel sampler. Note that this time, we dont clear the background.
        let mut canvas = ggez::graphics::Canvas::from_frame(ctx, None);        
        canvas.set_sampler(ggez::graphics::Sampler::nearest_clamp());
        
        // Here, you would draw your gamestate.

        // Drawing a gui is as easy as calling draw_to_screen on the root element.
        // If you are using a scene, you can simply pass on the mouse_listen parameter. It will be managed by the scene manager.
        self.gui.draw_to_screen(ctx, &mut canvas, mouse_listen);

        // Once again, we end drawing by finishing the canvas.
        canvas.finish(ctx)?;

        Ok(())
    }
}