egui/
egui.rs

1//
2// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30extern crate neocogi;
31
32use neocogi::glfw;
33use neocogi::glfw::{Action, Context, Key};
34
35use neocogi::rs_math3d::*;
36use neocogi::*;
37
38use neocogi::renderer::*;
39
40use neocogi::egui;
41use neocogi::egui::widgets::*;
42
43fn main() {
44    // initialize GLFW3 with OpenGL ES 3.0
45    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
46    glfw.window_hint(glfw::WindowHint::ContextCreationApi(
47        glfw::ContextCreationApi::Egl,
48    ));
49    glfw.window_hint(glfw::WindowHint::ClientApi(glfw::ClientApiHint::OpenGlEs));
50    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 0));
51    glfw.window_hint(glfw::WindowHint::OpenGlProfile(
52        glfw::OpenGlProfileHint::Core,
53    ));
54    glfw.window_hint(glfw::WindowHint::DoubleBuffer(true));
55    glfw.window_hint(glfw::WindowHint::Resizable(true));
56    glfw.window_hint(glfw::WindowHint::Floating(true));
57
58    let (mut window, events) = glfw
59        .create_window(1024, 900, "Egui Test", glfw::WindowMode::Windowed)
60        .expect("Failed to create GLFW window.");
61
62    window.set_char_polling(true);
63    window.set_cursor_pos_polling(true);
64    window.set_key_polling(true);
65    window.set_mouse_button_polling(true);
66    window.make_current();
67    glfw.set_swap_interval(glfw::SwapInterval::Sync(1));
68
69    let mut driver = renderer::get_driver();
70
71    // initialize EGUI
72    let mut egui_ctx = egui::Context::default();
73    let mut painter = ui::Painter::new(&mut driver, &mut window, 1024, 900);
74
75    let (width, height) = window.get_framebuffer_size();
76    let native_pixels_per_point = window.get_content_scale().0;
77
78    println!("pixels per point: {}", native_pixels_per_point);
79    let mut egui_input_state = ui::EguiInputState::new(egui::RawInput {
80        screen_rect: Some(egui::Rect::from_min_size(
81            egui::Pos2::new(0f32, 0f32),
82            egui::vec2(width as f32, height as f32) / native_pixels_per_point,
83        )),
84        pixels_per_point: Some(native_pixels_per_point),
85        ..Default::default()
86    });
87
88    let start_time = std::time::Instant::now();
89    let mut quit = false;
90    while !window.should_close() {
91        let (width, height) = window.get_framebuffer_size();
92        painter.set_canvas_size(width as u32, height as u32);
93        let native_pixels_per_point = window.get_content_scale().0;
94        egui_input_state.egui_input.screen_rect = Some(egui::Rect::from_min_size(
95            egui::Pos2::new(0f32, 0f32),
96            egui::vec2(width as f32, height as f32) / native_pixels_per_point,
97        ));
98        egui_input_state.egui_input.time = Some(start_time.elapsed().as_secs_f64());
99
100        let egui_output = egui_ctx.run(egui_input_state.egui_input.take(), |egui_ctx| {
101            egui::SidePanel::left("Test").show(&egui_ctx, |ui| {
102                if ui.button("click me!").clicked() {
103                    println!("Clicked")
104                }
105            });
106        });
107
108        //Handle cut, copy text from egui
109        if !egui_output.platform_output.copied_text.is_empty() {
110            ui::copy_to_clipboard(
111                &mut egui_input_state,
112                egui_output.platform_output.copied_text,
113            );
114        }
115
116        let paint_jobs = egui_ctx.tessellate(egui_output.shapes);
117        let mut pass = Pass::new(
118            width as usize,
119            height as usize,
120            None,
121            [
122                ColorPassAction::Clear(color4b(0x7F, 0x7F, 0x7F, 0xFF)),
123                ColorPassAction::Previous,
124                ColorPassAction::Previous,
125                ColorPassAction::Previous,
126            ],
127            DepthPassAction::Clear(1.0),
128        );
129
130        //Note: passing a bg_color to paint_jobs will clear any previously drawn stuff.
131        //Use this only if egui is being used for all drawing and you aren't mixing your own Open GL
132        //drawing calls with it.
133        //Since we are custom drawing an OpenGL Triangle we don't need egui to clear the background.
134        painter.paint_jobs(
135            &mut pass,
136            paint_jobs,
137            &egui_output.textures_delta,
138            native_pixels_per_point,
139        );
140
141        driver.render_pass(&mut pass);
142        window.swap_buffers();
143
144        glfw.poll_events();
145        for (_, event) in glfw::flush_messages(&events) {
146            match event {
147                glfw::WindowEvent::Key(glfw::Key::Escape, _, _, _) | glfw::WindowEvent::Close => {
148                    quit = true
149                }
150                _ => neocogi::ui::handle_event(event, &mut egui_input_state),
151            }
152        }
153
154        if quit {
155            window.set_should_close(true)
156        }
157    }
158}