use notan::egui::{self, *};
use notan::prelude::*;
#[derive(AppState)]
struct State {
triangle: Triangle,
angle: f32,
}
impl State {
pub fn new(gfx: &mut Graphics) -> Self {
Self {
triangle: Triangle::new(gfx),
angle: 0.0,
}
}
}
#[notan_main]
fn main() -> Result<(), String> {
let win = WindowConfig::default()
.set_lazy_loop(true)
.set_vsync(true)
.set_high_dpi(true);
notan::init_with(State::new)
.add_config(win)
.add_config(EguiConfig)
.draw(draw)
.build()
}
fn draw(gfx: &mut Graphics, plugins: &mut Plugins, state: &mut State) {
let mut output = plugins.egui(|ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
egui::Frame::canvas(ui.style()).show(ui, |ui| {
let (rect, response) =
ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag());
state.angle += response.drag_delta().x * 0.01;
let triangle = state.triangle.clone();
let angle = state.angle;
let cb = EguiCallbackFn::new(move |info, device| {
triangle.draw(device, info, angle);
});
let callback = egui::PaintCallback {
rect,
callback: std::sync::Arc::new(cb),
};
ui.painter().add(callback);
});
ui.label("Drag to rotate!");
});
});
output.clear_color(Color::BLACK);
gfx.render(&output);
}
const VERT: ShaderSource = notan::vertex_shader! {
r#"
#version 450
layout(location = 0) in vec2 a_pos;
layout(location = 1) in vec3 a_color;
layout(location = 0) out vec3 v_color;
layout(set = 0, binding = 0) uniform Locals {
float u_angle;
};
void main() {
v_color = a_color;
gl_Position = vec4(a_pos, 0.0, 1.0);
gl_Position.x *= cos(u_angle);
}
"#
};
const FRAG: ShaderSource = notan::fragment_shader! {
r#"
#version 450
precision mediump float;
layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 color;
void main() {
color = vec4(v_color, 1.0);
}
"#
};
#[derive(Clone)]
struct Triangle {
pipeline: Pipeline,
vbo: Buffer,
ubo: Buffer,
}
impl Triangle {
fn new(gfx: &mut Graphics) -> Self {
let vertex_info = VertexInfo::new()
.attr(0, VertexFormat::Float32x2)
.attr(1, VertexFormat::Float32x3);
let pipeline = gfx
.create_pipeline()
.from(&VERT, &FRAG)
.with_vertex_info(&vertex_info)
.build()
.unwrap();
#[rustfmt::skip]
let vertices = [
0.0, 1.0, 1.0, 0.2, 0.3,
-1.0, -1.0, 0.1, 1.0, 0.3,
1.0, -1.0, 0.1, 0.2, 1.0,
];
let vbo = gfx
.create_vertex_buffer()
.with_info(&vertex_info)
.with_data(&vertices)
.build()
.unwrap();
let ubo = gfx
.create_uniform_buffer(0, "Locals")
.with_data(&[0.0])
.build()
.unwrap();
Self { pipeline, vbo, ubo }
}
fn draw(&self, device: &mut Device, info: egui::PaintCallbackInfo, angle: f32) {
device.set_buffer_data(&self.ubo, &[angle]);
let mut renderer = device.create_renderer();
renderer.set_scissors(
info.clip_rect.min.x,
info.clip_rect.min.y,
info.clip_rect.width(),
info.clip_rect.height(),
);
renderer.begin(None);
renderer.set_viewport(
info.viewport.min.x,
info.viewport.min.y,
info.viewport.width(),
info.viewport.height(),
);
renderer.set_pipeline(&self.pipeline);
renderer.bind_buffer(&self.vbo);
renderer.draw(0, 3);
renderer.end();
device.render(renderer.commands());
}
}