Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ rand = "0.9.1"
regex = "1.11.1"
ron = "0.8"
serde = "1.0.219"
rfd = "0.15.4"
2 changes: 1 addition & 1 deletion src/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fs::File;
use std::io;
use std::io::Read;

use crate::controller::ExportedProject;
use omagari::controller::ExportedProject;

struct PreparedEffect {
name: String,
Expand Down
74 changes: 6 additions & 68 deletions src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
use bevy::{platform::collections::HashMap, prelude::*};
use bevy_hanabi::prelude::*;
use ron::{de::from_str, ser::PrettyConfig};
use serde::{Deserialize, Serialize};
use ron::de::from_str;
use std::{
cell::RefCell,
fs::File,
io::{self, Read, Write},
io::{self, Read},
rc::Rc,
};

use crate::{effect::*, AppContext};

#[derive(Resource, Serialize, Deserialize, Default)]
pub struct OmagariProject {
pub effects: Vec<EffectEditor>,
}

#[derive(Resource, Serialize, Deserialize, Default)]
pub struct ExportedEffect {
pub name: String,
pub parent: Option<String>,
pub texture_index: Option<usize>,
pub effect_asset: EffectAsset,
}

#[derive(Resource, Serialize, Deserialize, Default)]
pub struct ExportedProject {
pub effects: Vec<ExportedEffect>,
}
use crate::OmagariProject;
use crate::editor_prelude::AppContext;

#[derive(Resource)]
pub struct EffectResource {
Expand Down Expand Up @@ -72,50 +54,6 @@ pub fn spawn_particle_effects(
}
}

pub fn export_effects_to_files(filename: &str, clone: Rc<RefCell<&mut OmagariProject>>) {
let base = filename.split('.').next().unwrap();
let other_filename = format!("{}.hanabi.ron", base);
let mut to_export = ExportedProject::default();
for effect in clone.borrow().effects.iter() {
to_export.effects.push(ExportedEffect {
name: effect.name().to_string(),
parent: effect.parent().clone(),
texture_index: effect.texture_index(),
effect_asset: effect.produce(),
});
}
let ron_string =
ron::ser::to_string_pretty(&to_export, PrettyConfig::new().new_line("\n".to_string()))
.unwrap();
let mut file = File::create(&other_filename).unwrap();
file.write_all(ron_string.as_bytes()).unwrap();
}

pub fn projects_list() -> Vec<String> {
let mut files = Vec::new();
let entries = std::fs::read_dir(".").unwrap();
for entry in entries {
let entry = entry.unwrap();
let filename = entry.file_name();
if filename.to_string_lossy().ends_with(".omagari.ron") {
files.push(filename.to_string_lossy().into_owned());
}
}
files
}

pub fn load_project(filename: &str) -> Result<OmagariProject, io::Error> {
let mut file = File::open(filename)?;
let mut ron_string = String::new();
file.read_to_string(&mut ron_string)?;
let graph: OmagariProject =
from_str(&ron_string).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(graph)
}

pub fn validate_project_filename(filename: &str) -> bool {
regex::Regex::new(r".*\.omagari\.ron")
.unwrap()
.captures(&filename)
.is_some()
pub fn validate_project_filename<P: AsRef<std::path::Path>>(p: P) -> bool {
p.as_ref().ends_with("omagari.ron")
}
2 changes: 1 addition & 1 deletion src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use bevy_hanabi::prelude::*;
use serde::Deserialize;
use serde::Serialize;

use crate::editor_prelude::AppContext;
use crate::helpers::*;
use crate::modifiers::ModifierProducer;
use crate::modifiers::RenderModifierProducer;
use crate::modifiers::*;
use crate::AppContext;

fn ui_for_modifiers_list<T, R>(
app: &mut AppContext,
Expand Down
2 changes: 1 addition & 1 deletion src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use bevy_hanabi::prelude::*;
use serde::Deserialize;
use serde::Serialize;

use crate::editor_prelude::AppContext;
use crate::helpers::*;
use crate::AppContext;

pub const ALL_ATTRS: [(Attribute, &str); 39] = [
(Attribute::ID, "ID"),
Expand Down
2 changes: 1 addition & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy::prelude::*;
use bevy_egui::*;

use crate::AppContext;
use crate::editor_prelude::AppContext;

pub trait UiProvider {
fn draw_ui(&mut self, app: &mut AppContext, ui: &mut egui::Ui, index: u64);
Expand Down
79 changes: 79 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use bevy::prelude::*;
use bevy_hanabi::prelude::*;
use serde::{Deserialize, Serialize};

pub mod controller;
pub mod effect;
pub mod expr;
pub mod helpers;
pub mod modifiers;

use effect::EffectEditor;
use std::io::{self, Read};

#[derive(Resource, Serialize, Deserialize, Default)]
pub struct OmagariProject {
pub effects: Vec<EffectEditor>,
}

impl OmagariProject {
pub fn load<P: AsRef<std::path::Path>>(p: P) -> Result<Self, std::io::Error> {
let mut file = std::fs::File::open(p)?;
let mut ron_string = String::new();
file.read_to_string(&mut ron_string)?;
let graph: OmagariProject = ron::de::from_str(&ron_string)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(graph)
}
}

impl From<OmagariProject> for OmagariBundle {
fn from(project: OmagariProject) -> Self {
Self {
effects: project
.effects
.iter()
.map(|e| OmagariEffect {
texture_asset: "effects/cloud2.png".to_string(),
effect: e.produce(),
})
.collect(),
}
}
}

pub struct OmagariEffect {
pub texture_asset: String,
pub effect: EffectAsset,
// For setting parenting for hanabi
// is_child: bool,
}

pub struct OmagariBundle {
pub effects: Vec<OmagariEffect>,
}

pub mod prelude {
pub use super::OmagariProject;
}

pub mod editor_prelude {
use std::path::PathBuf;

pub use super::controller::*;
pub use super::effect::*;
pub use super::expr::*;
pub use super::helpers::*;
pub use super::modifiers::*;

pub use super::OmagariProject;

use super::expr::ExprWriterEditor;

#[derive(Default)]
pub struct AppContext {
pub expr_clipboard: Option<ExprWriterEditor>,
pub visible_effects: Vec<String>,
pub filename: Option<PathBuf>,
}
}
51 changes: 17 additions & 34 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,16 @@ use bevy::{
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};

use bevy_egui::{
egui::{self, scroll_area::ScrollBarVisibility, Layout},
EguiContext, EguiContexts, EguiGlobalSettings, EguiPlugin, EguiPrimaryContextPass,
PrimaryEguiContext,
egui::{self, Layout, scroll_area::ScrollBarVisibility},
};
use bevy_hanabi::prelude::*;
use ron::ser::PrettyConfig;
use std::fs::File;
use std::io::Write;

mod controller;
mod effect;
mod expr;
mod helpers;
mod modifiers;

use crate::controller::*;
use crate::effect::*;
use crate::expr::*;
use crate::helpers::*;
use omagari::editor_prelude::*;

fn main() {
App::new()
Expand Down Expand Up @@ -78,13 +69,6 @@ fn setup(
});
}

#[derive(Default)]
struct AppContext {
expr_clipboard: Option<ExprWriterEditor>,
visible_effects: Vec<String>,
filename: Option<String>,
}

fn app_ui(
mut commands: Commands,
mut contexts: EguiContexts,
Expand All @@ -108,9 +92,9 @@ fn app_ui(
let mut filename = res
.context
.filename
.as_ref()
.unwrap_or(&"".to_string())
.clone();
.clone()
.map(|x| x.display().to_string())
.unwrap_or(String::new());

egui::TopBottomPanel::top("Toolbar")
.resizable(false)
Expand All @@ -128,10 +112,6 @@ fn app_ui(
);
}

if ui.button("🖭 EXPORT").clicked() {
export_effects_to_files(&filename, project.clone());
}

ui.add_space(10.0);
ui.separator();
ui.add_space(10.0);
Expand All @@ -148,21 +128,24 @@ fn app_ui(
}

filename_textedit.show(ui);
res.context.filename = Some(filename.clone());
res.context.filename = Some(std::path::PathBuf::from(&filename));

if ui.button("🌌 NEW").clicked() {
res.context.filename = None;
commands.insert_resource(OmagariProject::default());
}

ui.menu_button("⮉ LOAD", |ui| {
for f in projects_list() {
if ui.button(f.clone()).clicked() {
if let Ok(project) = load_project(&f) {
commands.insert_resource(project);
res.context.filename = Some(f.clone());
ui.close_menu();
}
let files = rfd::FileDialog::new()
.add_filter("omagari", &["omagari.ron"])
.set_directory(".")
.pick_file();

if let Some(path) = files {
if let Ok(project) = OmagariProject::load(&path) {
commands.insert_resource(project);
res.context.filename = Some(path.clone());
ui.close_menu();
}
}
});
Expand All @@ -176,7 +159,7 @@ fn app_ui(
)
.unwrap();

if let Ok(mut file) = File::create(filename) {
if let Ok(mut file) = File::create(&filename) {
file.write_all(ron_string.as_bytes()).unwrap();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/modifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use bevy_hanabi::prelude::*;
use serde::Deserialize;
use serde::Serialize;

use crate::editor_prelude::AppContext;
use crate::expr::*;
use crate::helpers::*;
use crate::AppContext;

pub trait ModifierProducer<T>
where
Expand Down