105 lines
2.8 KiB
Rust
105 lines
2.8 KiB
Rust
use std::collections::HashMap;
|
|
use std::io::Cursor;
|
|
use std::path::Path;
|
|
|
|
use base64_url as base64;
|
|
use image::ImageFormat;
|
|
use log::{debug, trace};
|
|
use ray_format::Ray;
|
|
use serde::{Deserialize, Serialize};
|
|
use tauri::api::dialog::blocking::FileDialogBuilder;
|
|
use tauri::api::path::home_dir;
|
|
|
|
const OBJ_URL: &'static str = "data:image/png;base64,";
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
pub(crate) struct WebRay {
|
|
frames: [String; 4],
|
|
meta: HashMap<String, String>,
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub(crate) async fn open_image() -> Option<String> {
|
|
let path = FileDialogBuilder::new()
|
|
.add_filter("Images", &["png", "jpg"])
|
|
.set_directory(home_dir()?)
|
|
.set_title("Select an image")
|
|
.pick_file()?;
|
|
if let Ok(b) = image::open(path) {
|
|
let mut buf = Cursor::new(vec![]);
|
|
b.write_to(&mut buf, ImageFormat::Png).unwrap();
|
|
let encoded = base64::encode(buf.get_ref());
|
|
trace!("Encoded: {:?}", encoded);
|
|
|
|
Some(format!("{}{}", OBJ_URL, encoded))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub(crate) async fn open_ray() -> Option<WebRay> {
|
|
let path = FileDialogBuilder::new()
|
|
.add_filter("Rays", &["ray"])
|
|
.set_directory(home_dir()?)
|
|
.pick_file()?;
|
|
|
|
load_ray(path).await
|
|
}
|
|
|
|
pub(crate) async fn load_ray(path: impl AsRef<Path>) -> Option<WebRay> {
|
|
let ray = Ray::load(path).ok()?;
|
|
let mut frames = [String::new(), String::new(), String::new(), String::new()];
|
|
let mut meta = HashMap::new();
|
|
|
|
for i in 0..4 {
|
|
debug!("Trying frame {}", i);
|
|
if let Some(f) = ray.get_frame(i as usize) {
|
|
debug!("Got frame {}", i);
|
|
if f.is_empty() {
|
|
debug!("Frame {} was empty", i);
|
|
continue;
|
|
}
|
|
let encoded = base64::encode(&f);
|
|
|
|
frames[i as usize] = format!("{}{}", OBJ_URL, encoded);
|
|
}
|
|
}
|
|
|
|
for k in ray.get_meta_keys() {
|
|
if let Some(v) = ray.get_meta_value(&k) {
|
|
meta.insert(k.clone(), v.clone());
|
|
}
|
|
}
|
|
|
|
Some(WebRay { frames, meta })
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub(crate) async fn save_ray(ray: WebRay) -> Result<(), String> {
|
|
if let Some(path) = FileDialogBuilder::new()
|
|
.add_filter("Rays", &["ray"])
|
|
.set_directory(home_dir().unwrap())
|
|
.set_title("Save Ray")
|
|
.set_file_name("new.ray")
|
|
.save_file()
|
|
{
|
|
let mut res = Ray::default();
|
|
|
|
for (i, f) in ray.frames.iter().enumerate() {
|
|
let stripped = f.strip_prefix(OBJ_URL).unwrap_or(f);
|
|
let decoded = base64::decode(stripped).unwrap();
|
|
res.set_frame(i as usize, decoded);
|
|
}
|
|
|
|
for (k, v) in ray.meta {
|
|
res.add_meta(k, v);
|
|
}
|
|
|
|
res.save(&path)
|
|
.map_err(|e| format!("Failed to save ray file: {}", e))
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|