mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
[demo] Move Fractal Clock to WrapApp
This commit is contained in:
@@ -297,24 +297,6 @@ impl epi::App for DemoApp {
|
||||
self.frame_history
|
||||
.on_new_frame(ctx.input().time, frame.info().cpu_usage);
|
||||
|
||||
let web_location_hash = frame
|
||||
.info()
|
||||
.web_info
|
||||
.as_ref()
|
||||
.map(|info| info.web_location_hash.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
let link = if web_location_hash == "clock" {
|
||||
Some(super::DemoLink::Clock)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let demo_environment = super::DemoEnvironment {
|
||||
seconds_since_midnight: frame.info().seconds_since_midnight,
|
||||
link,
|
||||
};
|
||||
|
||||
let mean_frame_time = self.frame_history.mean_frame_time();
|
||||
|
||||
let Self {
|
||||
@@ -323,7 +305,7 @@ impl epi::App for DemoApp {
|
||||
..
|
||||
} = self;
|
||||
|
||||
demo_windows.ui(ctx, &demo_environment, frame.tex_allocator(), |ui| {
|
||||
demo_windows.ui(ctx, frame.tex_allocator(), |ui| {
|
||||
ui.separator();
|
||||
ui.checkbox(backend_window_open, "💻 Backend");
|
||||
|
||||
|
||||
@@ -2,24 +2,6 @@ use egui::{CtxRef, Resize, ScrollArea, Ui, Window};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Link to show a specific part of the demo app.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum DemoLink {
|
||||
Clock,
|
||||
}
|
||||
|
||||
/// Special input to the demo-app.
|
||||
#[derive(Default)]
|
||||
pub struct DemoEnvironment {
|
||||
/// Local time. Used for the clock in the demo app.
|
||||
pub seconds_since_midnight: Option<f64>,
|
||||
|
||||
/// Set to `Some` to open a specific part of the demo app.
|
||||
pub link: Option<DemoLink>,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
struct Demos {
|
||||
@@ -67,13 +49,8 @@ pub struct DemoWindows {
|
||||
#[serde(skip)]
|
||||
color_test: super::ColorTest,
|
||||
|
||||
fractal_clock: super::FractalClock,
|
||||
|
||||
/// open, title, view
|
||||
demos: Demos,
|
||||
|
||||
#[serde(skip)]
|
||||
previous_link: Option<DemoLink>,
|
||||
}
|
||||
|
||||
impl DemoWindows {
|
||||
@@ -82,26 +59,11 @@ impl DemoWindows {
|
||||
pub fn ui(
|
||||
&mut self,
|
||||
ctx: &CtxRef,
|
||||
env: &DemoEnvironment,
|
||||
tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>,
|
||||
sidebar_ui: impl FnOnce(&mut Ui),
|
||||
) {
|
||||
if self.previous_link != env.link {
|
||||
match env.link {
|
||||
None => {}
|
||||
Some(DemoLink::Clock) => {
|
||||
self.open_windows = OpenWindows {
|
||||
fractal_clock: true,
|
||||
..OpenWindows::none()
|
||||
};
|
||||
}
|
||||
}
|
||||
self.previous_link = env.link;
|
||||
}
|
||||
|
||||
egui::SidePanel::left("side_panel", 190.0).show(ctx, |ui| {
|
||||
ui.heading("✒ Egui Demo");
|
||||
egui::warn_if_debug_build(ui);
|
||||
|
||||
ui.separator();
|
||||
|
||||
@@ -132,24 +94,22 @@ impl DemoWindows {
|
||||
});
|
||||
|
||||
egui::TopPanel::top("menu_bar").show(ctx, |ui| {
|
||||
show_menu_bar(ui, &mut self.open_windows, env.seconds_since_midnight);
|
||||
show_menu_bar(ui);
|
||||
});
|
||||
|
||||
self.windows(ctx, env, tex_allocator);
|
||||
self.windows(ctx, tex_allocator);
|
||||
}
|
||||
|
||||
/// Show the open windows.
|
||||
fn windows(
|
||||
&mut self,
|
||||
ctx: &CtxRef,
|
||||
env: &DemoEnvironment,
|
||||
tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>,
|
||||
) {
|
||||
let Self {
|
||||
open_windows,
|
||||
demo_window,
|
||||
color_test,
|
||||
fractal_clock,
|
||||
demos,
|
||||
..
|
||||
} = self;
|
||||
@@ -191,12 +151,6 @@ impl DemoWindows {
|
||||
|
||||
demos.show(ctx);
|
||||
|
||||
fractal_clock.window(
|
||||
ctx,
|
||||
&mut open_windows.fractal_clock,
|
||||
env.seconds_since_midnight,
|
||||
);
|
||||
|
||||
self.resize_windows(ctx);
|
||||
}
|
||||
|
||||
@@ -259,7 +213,6 @@ impl DemoWindows {
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct OpenWindows {
|
||||
demo: bool,
|
||||
fractal_clock: bool,
|
||||
|
||||
// egui stuff:
|
||||
settings: bool,
|
||||
@@ -284,7 +237,6 @@ impl OpenWindows {
|
||||
fn none() -> Self {
|
||||
Self {
|
||||
demo: false,
|
||||
fractal_clock: false,
|
||||
|
||||
settings: false,
|
||||
inspection: false,
|
||||
@@ -298,7 +250,6 @@ impl OpenWindows {
|
||||
fn checkboxes(&mut self, ui: &mut Ui) {
|
||||
let Self {
|
||||
demo,
|
||||
fractal_clock,
|
||||
settings,
|
||||
inspection,
|
||||
memory,
|
||||
@@ -317,11 +268,10 @@ impl OpenWindows {
|
||||
.on_hover_text("For testing the integrations painter");
|
||||
ui.separator();
|
||||
ui.label("Misc:");
|
||||
ui.checkbox(fractal_clock, "🕑 Fractal Clock");
|
||||
}
|
||||
}
|
||||
|
||||
fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight: Option<f64>) {
|
||||
fn show_menu_bar(ui: &mut Ui) {
|
||||
use egui::*;
|
||||
|
||||
menu::bar(ui, |ui| {
|
||||
@@ -337,24 +287,5 @@ fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight:
|
||||
*ui.ctx().memory() = Default::default();
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(time) = seconds_since_midnight {
|
||||
let time = format!(
|
||||
"{:02}:{:02}:{:02}.{:02}",
|
||||
(time % (24.0 * 60.0 * 60.0) / 3600.0).floor(),
|
||||
(time % (60.0 * 60.0) / 60.0).floor(),
|
||||
(time % 60.0).floor(),
|
||||
(time % 1.0 * 100.0).floor()
|
||||
);
|
||||
|
||||
ui.with_layout(Layout::right_to_left(), |ui| {
|
||||
if ui
|
||||
.add(Button::new(time).text_style(TextStyle::Monospace))
|
||||
.clicked
|
||||
{
|
||||
windows.fractal_clock = !windows.fractal_clock;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
use egui::{containers::*, widgets::*, *};
|
||||
use std::f32::consts::TAU;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct FractalClock {
|
||||
paused: bool,
|
||||
time: f64,
|
||||
zoom: f32,
|
||||
start_line_width: f32,
|
||||
depth: usize,
|
||||
length_factor: f32,
|
||||
luminance_factor: f32,
|
||||
width_factor: f32,
|
||||
}
|
||||
|
||||
impl Default for FractalClock {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
paused: false,
|
||||
time: 0.0,
|
||||
zoom: 0.25,
|
||||
start_line_width: 2.5,
|
||||
depth: 9,
|
||||
length_factor: 0.8,
|
||||
luminance_factor: 0.8,
|
||||
width_factor: 0.9,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FractalClock {
|
||||
pub fn window(&mut self, ctx: &CtxRef, open: &mut bool, seconds_since_midnight: Option<f64>) {
|
||||
Window::new("🕑 Fractal Clock")
|
||||
.open(open)
|
||||
.default_size(vec2(512.0, 512.0))
|
||||
.scroll(false)
|
||||
// Dark background frame to make it pop:
|
||||
.frame(Frame::window(&ctx.style()).fill(Srgba::black_alpha(250)))
|
||||
.show(ctx, |ui| self.ui(ui, seconds_since_midnight));
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui, seconds_since_midnight: Option<f64>) {
|
||||
if !self.paused {
|
||||
self.time = seconds_since_midnight.unwrap_or_else(|| ui.input().time);
|
||||
ui.ctx().request_repaint();
|
||||
}
|
||||
|
||||
let painter = Painter::new(
|
||||
ui.ctx().clone(),
|
||||
ui.layer_id(),
|
||||
ui.available_rect_before_wrap_finite(),
|
||||
);
|
||||
self.paint(&painter);
|
||||
// Make sure we allocate what we used (everything)
|
||||
ui.expand_to_include_rect(painter.clip_rect());
|
||||
|
||||
Frame::popup(ui.style())
|
||||
.fill(Rgba::luminance_alpha(0.02, 0.5).into())
|
||||
.stroke(Stroke::none())
|
||||
.show(ui, |ui| {
|
||||
ui.set_max_width(270.0);
|
||||
CollapsingHeader::new("Settings")
|
||||
.show(ui, |ui| self.options_ui(ui, seconds_since_midnight));
|
||||
});
|
||||
}
|
||||
|
||||
fn options_ui(&mut self, ui: &mut Ui, seconds_since_midnight: Option<f64>) {
|
||||
if seconds_since_midnight.is_some() {
|
||||
ui.label(format!(
|
||||
"Local time: {:02}:{:02}:{:02}.{:03}",
|
||||
(self.time % (24.0 * 60.0 * 60.0) / 3600.0).floor(),
|
||||
(self.time % (60.0 * 60.0) / 60.0).floor(),
|
||||
(self.time % 60.0).floor(),
|
||||
(self.time % 1.0 * 100.0).floor()
|
||||
));
|
||||
} else {
|
||||
ui.label("The fractal_clock clock is not showing the correct time");
|
||||
};
|
||||
|
||||
ui.checkbox(&mut self.paused, "Paused");
|
||||
ui.add(Slider::f32(&mut self.zoom, 0.0..=1.0).text("zoom"));
|
||||
ui.add(Slider::f32(&mut self.start_line_width, 0.0..=5.0).text("Start line width"));
|
||||
ui.add(Slider::usize(&mut self.depth, 0..=14).text("depth"));
|
||||
ui.add(Slider::f32(&mut self.length_factor, 0.0..=1.0).text("length factor"));
|
||||
ui.add(Slider::f32(&mut self.luminance_factor, 0.0..=1.0).text("luminance factor"));
|
||||
ui.add(Slider::f32(&mut self.width_factor, 0.0..=1.0).text("width factor"));
|
||||
if ui.button("Reset").clicked {
|
||||
*self = Default::default();
|
||||
}
|
||||
|
||||
ui.add(
|
||||
Hyperlink::new("http://www.dqd.com/~mayoff/programs/FractalClock/")
|
||||
.text("Inspired by a screensaver by Rob Mayoff"),
|
||||
);
|
||||
}
|
||||
|
||||
fn paint(&mut self, painter: &Painter) {
|
||||
let rect = painter.clip_rect();
|
||||
|
||||
struct Hand {
|
||||
length: f32,
|
||||
angle: f32,
|
||||
vec: Vec2,
|
||||
}
|
||||
|
||||
impl Hand {
|
||||
fn from_length_angle(length: f32, angle: f32) -> Self {
|
||||
Self {
|
||||
length,
|
||||
angle,
|
||||
vec: length * Vec2::angled(angle),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let angle_from_period =
|
||||
|period| TAU * (self.time.rem_euclid(period) / period) as f32 - TAU / 4.0;
|
||||
|
||||
let hands = [
|
||||
// Second hand:
|
||||
Hand::from_length_angle(self.length_factor, angle_from_period(60.0)),
|
||||
// Minute hand:
|
||||
Hand::from_length_angle(self.length_factor, angle_from_period(60.0 * 60.0)),
|
||||
// Hour hand:
|
||||
Hand::from_length_angle(0.5, angle_from_period(12.0 * 60.0 * 60.0)),
|
||||
];
|
||||
|
||||
let scale = self.zoom * rect.width().min(rect.height());
|
||||
let paint_line = |points: [Pos2; 2], color: Srgba, width: f32| {
|
||||
let line = [
|
||||
rect.center() + scale * points[0].to_vec2(),
|
||||
rect.center() + scale * points[1].to_vec2(),
|
||||
];
|
||||
|
||||
painter.line_segment([line[0], line[1]], (width, color));
|
||||
};
|
||||
|
||||
let hand_rotations = [
|
||||
hands[0].angle - hands[2].angle + TAU / 2.0,
|
||||
hands[1].angle - hands[2].angle + TAU / 2.0,
|
||||
];
|
||||
|
||||
let hand_rotors = [
|
||||
hands[0].length * Rot2::from_angle(hand_rotations[0]),
|
||||
hands[1].length * Rot2::from_angle(hand_rotations[1]),
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Node {
|
||||
pos: Pos2,
|
||||
dir: Vec2,
|
||||
}
|
||||
|
||||
let mut nodes = Vec::new();
|
||||
|
||||
let mut width = self.start_line_width;
|
||||
|
||||
for (i, hand) in hands.iter().enumerate() {
|
||||
let center = pos2(0.0, 0.0);
|
||||
let end = center + hand.vec;
|
||||
paint_line([center, end], Srgba::additive_luminance(255), width);
|
||||
if i < 2 {
|
||||
nodes.push(Node {
|
||||
pos: end,
|
||||
dir: hand.vec,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut luminance = 0.7; // Start dimmer than main hands
|
||||
|
||||
let mut new_nodes = Vec::new();
|
||||
for _ in 0..self.depth {
|
||||
new_nodes.clear();
|
||||
new_nodes.reserve(nodes.len() * 2);
|
||||
|
||||
luminance *= self.luminance_factor;
|
||||
width *= self.width_factor;
|
||||
|
||||
let luminance_u8 = (255.0 * luminance).round() as u8;
|
||||
|
||||
for &rotor in &hand_rotors {
|
||||
for a in &nodes {
|
||||
let new_dir = rotor * a.dir;
|
||||
let b = Node {
|
||||
pos: a.pos + new_dir,
|
||||
dir: new_dir,
|
||||
};
|
||||
paint_line(
|
||||
[a.pos, b.pos],
|
||||
Srgba::additive_luminance(luminance_u8),
|
||||
width,
|
||||
);
|
||||
new_nodes.push(b);
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::swap(&mut nodes, &mut new_nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ mod drag_and_drop;
|
||||
mod font_book;
|
||||
pub mod font_contents_emoji;
|
||||
pub mod font_contents_ubuntu;
|
||||
mod fractal_clock;
|
||||
mod painting;
|
||||
mod scrolls;
|
||||
mod sliders;
|
||||
@@ -23,8 +22,8 @@ mod widgets;
|
||||
|
||||
pub use {
|
||||
app::*, color_test::ColorTest, dancing_strings::DancingStrings, demo_window::DemoWindow,
|
||||
demo_windows::*, drag_and_drop::*, font_book::FontBook, fractal_clock::FractalClock,
|
||||
painting::Painting, scrolls::Scrolls, sliders::Sliders, tests::Tests, widgets::Widgets,
|
||||
demo_windows::*, drag_and_drop::*, font_book::FontBook, painting::Painting, scrolls::Scrolls,
|
||||
sliders::Sliders, tests::Tests, widgets::Widgets,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user