gif plan, start eframe
This commit is contained in:
Generated
+5370
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "anime"
|
name = "anishio"
|
||||||
author = "inorishio"
|
author = "inorishio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eframe = "0.34.1"
|
eframe = "0.34.1"
|
||||||
egui = "0.34.1."
|
egui = "0.34.1"
|
||||||
reqwest = "0.13.2"
|
reqwest = "0.13.2"
|
||||||
open = "5.3.3"
|
open = "5.3.3"
|
||||||
tokio = "1.52.0"
|
tokio = "1.52.0"
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# Animated Icon Plan
|
||||||
|
|
||||||
|
Animate a Discord emote (GIF) as the app's window/taskbar icon using eframe/egui.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Add the `image` crate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo add image
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Place your GIF
|
||||||
|
|
||||||
|
Save your Discord emote as `assets/emote.gif` in the project root.
|
||||||
|
|
||||||
|
### 3. Load GIF frames
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use eframe::egui::{ViewportCommand, IconData};
|
||||||
|
use image::codecs::gif::GifDecoder;
|
||||||
|
use image::AnimationDecoder;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
fn load_gif_frames(gif_bytes: &[u8]) -> Vec<IconData> {
|
||||||
|
let decoder = GifDecoder::new(gif_bytes).unwrap();
|
||||||
|
decoder.into_frames()
|
||||||
|
.collect_frames()
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| {
|
||||||
|
let rgba = f.into_buffer();
|
||||||
|
let (w, h) = (rgba.width(), rgba.height());
|
||||||
|
IconData { rgba: rgba.into_raw(), width: w, height: h }
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Embed the GIF at compile time:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let gif_bytes = include_bytes!("../assets/emote.gif");
|
||||||
|
let icon_frames = load_gif_frames(gif_bytes);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Add fields to the app struct
|
||||||
|
|
||||||
|
```rust
|
||||||
|
icon_frames: Vec<IconData>,
|
||||||
|
current_frame: usize,
|
||||||
|
last_icon_swap: Instant,
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Cycle the icon in `update()`
|
||||||
|
|
||||||
|
```rust
|
||||||
|
if !self.icon_frames.is_empty() {
|
||||||
|
let elapsed = self.last_icon_swap.elapsed().as_millis();
|
||||||
|
if elapsed > 100 { // ~10 FPS
|
||||||
|
self.current_frame = (self.current_frame + 1) % self.icon_frames.len();
|
||||||
|
let icon = self.icon_frames[self.current_frame].clone();
|
||||||
|
ctx.send_viewport_cmd(ViewportCommand::Icon(Some(std::sync::Arc::new(icon))));
|
||||||
|
self.last_icon_swap = Instant::now();
|
||||||
|
ctx.request_repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The icon animates in both the taskbar and the window title bar on Windows.
|
||||||
|
- Adjust the `100`ms interval to control animation speed.
|
||||||
|
- Discord emotes are typically small (48x48 or 128x128) which works fine for icons.
|
||||||
@@ -1 +0,0 @@
|
|||||||
/target
|
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
use eframe::egui;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct AniShio {}
|
||||||
|
|
||||||
|
impl AniShio {
|
||||||
|
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||||
|
// Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_global_style.
|
||||||
|
// Restore app state using cc.storage (requires the "persistence" feature).
|
||||||
|
// Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
|
||||||
|
// for e.g. egui::PaintCallback.
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl eframe::App for AniShio {
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||||
|
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||||
|
ui.heading("Hello World!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-1
@@ -1,3 +1,12 @@
|
|||||||
|
mod app;
|
||||||
|
|
||||||
|
use app::AniShio;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let native_options = eframe::NativeOptions::default();
|
||||||
|
eframe::run_native(
|
||||||
|
"AniShio",
|
||||||
|
native_options,
|
||||||
|
Box::new(|cc| Ok(Box::new(AniShio::new(cc)))),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user