Skip to content

Commit

Permalink
Refactor intoplugins 56 (#58)
Browse files Browse the repository at this point in the history
* wip: refactoring out into more modular plugins

* refactor: create prelude, create ShadPlay Plugin

* refactor: moving things around, mostly into 'sensible?' dirs

* bug: log::error firing all the time when swapping from 2d to 3d -- but not the other way interestingly...

* fix: found the typo

* chore: matches! over a t,f =>
  • Loading branch information
alphastrata authored Nov 2, 2023
1 parent 97e96bb commit db23f6a
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 267 deletions.
191 changes: 22 additions & 169 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,175 +1,28 @@
pub mod drag_n_drop;
pub mod screenshot;
pub mod plugin;
pub mod shader_utils;
pub mod system_clipboard;
pub mod texture_tooling;
pub mod system;
pub mod ui;
pub mod utils;

pub mod system {
//! Logic and Helpers etc for dealing with the system Shadplay is running on, i.e
//! the app's default config, long-lived settings and the clipboard interactions.
use bevy::{
log,
prelude::{Query, ResMut, Resource},
window::{Window, WindowLevel},
pub mod prelude {
//! The Shadplay Prelude, you'll probably find yourself wanting things from/adding things to this, if you're working on Shadplay.
pub use crate::{
shader_utils::{
common::ShadplayShaderLibrary,
texture_tooling::{self, swap_2d_tex_from_idx, swap_3d_tex_from_idx, SetNewTexture},
DragNDropShader, MousePos, YourShader, YourShader2D,
},
system::drag_n_drop::{
add_and_set_dropped_file, file_drag_and_drop_listener, override_current_shader,
TexHandleQueue, UserAddedTexture,
},
system::screenshot::screenshot_and_version_shader_on_spacebar,
ui::colour_picker_plugin::ColourPickerPlugin,
utils::{
self, cam_switch_system, cleanup_2d, cleanup_3d, init_shapes, quit, rotate, setup_2d,
setup_3d, size_quad, switch_level, switch_shape, toggle_rotate, toggle_transparency,
toggle_window_passthrough, update_mouse_pos, AppState, MonitorsSpecs, Rotating,
ShadplayWindowDims, ShapeOptions, TransparencySet,
},
};
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::{
fs,
io::{self, Read},
path::{Path, PathBuf},
time::UNIX_EPOCH,
};

#[derive(Resource, Debug, Serialize, PartialEq, PartialOrd, Deserialize)]
pub struct UserConfig {
window_dims: (f32, f32),
decorations: bool,
always_on_top: bool,
last_updated: u64, //Toml doesn't supprot u128
}

impl UserConfig {
pub fn get_config_path() -> PathBuf {
match ProjectDirs::from("", "", "shadplay") {
Some(proj_dirs) => {
let config_path_full = proj_dirs.config_dir().join("config.toml");
log::info!("Config directory is: {}", config_path_full.display());

if !proj_dirs.config_dir().exists() {
log::error!("config_dir doesn't exist, creating it...",);
if let Err(e) = fs::create_dir_all(&proj_dirs.config_dir()) {
log::error!("Failed to create directory: {:?}", e);
}
log::info!("config_dir created.")
}

config_path_full
}
None => {
log::error!("Unable to find or create the config directory.");
unreachable!("If you see this error, shadpaly was unable to write the default user configuration to your system, please open an issue, on GH.")
}
}
}

pub fn save_to_toml<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
fs::write(
path,
toml::to_string(self).expect("Failed to serialize UserConfig to TOML"),
)?;

Ok(())
}

pub fn load_from_toml<P: AsRef<Path>>(path: P) -> io::Result<Self> {
let mut file_contents = String::new();
fs::File::open(path)?.read_to_string(&mut file_contents)?;
let config: UserConfig =
toml::from_str(&file_contents).expect("Failed to deserialize TOML into UserConfig");

Ok(config)
}

pub fn create_window_settings(&self) -> Window {
Window {
title: "shadplay".into(),
resolution: self.window_dims.into(),
transparent: true,
decorations: self.decorations,
// Mac only
#[cfg(target_os = "macos")]
composite_alpha_mode: CompositeAlphaMode::PostMultiplied,
window_level: self.window_level(),
..bevy::prelude::default()
}
}

fn window_level(&self) -> WindowLevel {
match self.always_on_top {
true => WindowLevel::AlwaysOnTop,
_ => WindowLevel::Normal,
}
}

/// System: When the screen dims change, we update the Self we have in the bevy [`Resource`]s.
pub fn runtime_updater(mut user_config: ResMut<UserConfig>, windows: Query<&Window>) {
let win = windows
.get_single()
.expect("Should be impossible to NOT get a window");

let (width, height) = (win.width(), win.height());

user_config.decorations = win.decorations;
user_config.always_on_top = match win.window_level {
WindowLevel::AlwaysOnTop => true,
_ => false,
};
user_config.window_dims = (width, height);
user_config.last_updated = std::time::SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();

match user_config.save_to_toml(Self::get_config_path()) {
Ok(_) => log::info!("User's config.toml's screen dims were updated."),
Err(e) => log::error!("Failed to update user's config {}", e),
}
}
}

impl Default for UserConfig {
fn default() -> Self {
Self {
window_dims: (720.0, 480.0),
decorations: true,
always_on_top: true,
last_updated: std::time::SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
}
}
}

#[cfg(test)]
mod tests {
use super::UserConfig;
use std::fs;

#[test]
fn save_and_load_user_config() {
let test_config = UserConfig {
window_dims: (1024.0, 768.0),
decorations: false,
always_on_top: false,
last_updated: 1635900000,
};

let temp_path = "./temp_config.toml";
test_config
.save_to_toml(temp_path)
.expect("Failed to save test config to TOML");

let loaded_config = UserConfig::load_from_toml(temp_path)
.expect("Failed to load test config from TOML");
assert_eq!(test_config, loaded_config);

fs::remove_file(temp_path).expect("Failed to remove temporary test config file");
}

#[test]
fn config_path_for_user_config() {
let p = UserConfig::get_config_path();
let test_config = UserConfig {
window_dims: (1024.0, 768.0),
decorations: false,
always_on_top: true,
last_updated: 1635900000,
};
test_config.save_to_toml(p).unwrap();
}
}
}
93 changes: 9 additions & 84 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
#[cfg(target_os = "macos")]
use bevy::window::CompositeAlphaMode;

///
/// ShadPlay
///
use bevy::{
asset::ChangeWatcher,
input::keyboard::KeyboardInput,
prelude::*,
sprite::Material2dPlugin,
utils::Duration,
window::{WindowLevel, WindowPlugin, WindowResized},
window::{WindowPlugin, WindowResized},
};
use bevy_panorbit_camera::PanOrbitCameraPlugin;

#[cfg(feature = "ui")]
use shadplay::ui::help_ui::HelpUIPlugin;

use shadplay::{
drag_n_drop::{self, TexHandleQueue, UserAddedTexture},
screenshot,
shader_utils::{self, DragNDropShader},
system::UserConfig,
texture_tooling,
ui::colour_picker_plugin,
utils::{self, AppState, MonitorsSpecs, Rotating, ShapeOptions, TransparencySet},
};
use shadplay::{plugin::ShadPlayPlugin, system::config::UserConfig, utils::AppState};

fn main() -> anyhow::Result<()> {
// Get UserConfig for the Shadplay window dimensions, decorations toggle etc.
Expand All @@ -33,6 +20,8 @@ fn main() -> anyhow::Result<()> {

let shadplay = app
.add_state::<AppState>()
.insert_resource(user_config)
.insert_resource(ClearColor(Color::NONE))
.add_plugins((
DefaultPlugins
.set(AssetPlugin {
Expand All @@ -43,81 +32,17 @@ fn main() -> anyhow::Result<()> {
primary_window: Some(user_cfg_window), // From UserConfig
..default()
}),
//
ShadPlayPlugin,
))
.add_plugins(shader_utils::common::ShadplayShaderLibrary) // Something of a library with common functions.
.add_plugins(colour_picker_plugin::ColourPickerPlugin)
.add_plugins(MaterialPlugin::<shader_utils::YourShader>::default())
.add_plugins(Material2dPlugin::<shader_utils::YourShader2D>::default())
// Resources
.insert_resource(MonitorsSpecs::default())
.insert_resource(user_config) //UserConfig
.insert_resource(TexHandleQueue::default())
.insert_resource(utils::ShadplayWindowDims::default())
.insert_resource(ShapeOptions::default())
.insert_resource(TransparencySet(true))
.insert_resource(Rotating(false))
.insert_resource(ClearColor(Color::NONE))
.add_plugins(PanOrbitCameraPlugin)
//events:
.add_event::<UserAddedTexture>()
.add_event::<DragNDropShader>()
// 3D
.add_systems(OnEnter(AppState::ThreeD), utils::setup_3d)
.add_systems(OnExit(AppState::ThreeD), utils::cleanup_3d)
// 2D
.add_systems(OnEnter(AppState::TwoD), utils::setup_2d)
.add_systems(OnExit(AppState::TwoD), utils::cleanup_2d)
// Setups.
.add_systems(PreStartup, utils::init_shapes)
// 3d Cam Systems
.add_systems(
Update,
(
utils::rotate.run_if(resource_equals::<Rotating>(shadplay::utils::Rotating(true))),
utils::switch_shape,
texture_tooling::swap_3d_tex_from_idx,
utils::toggle_rotate,
)
.run_if(in_state(AppState::ThreeD)),
)
// All the time systems
.add_systems(
Update,
(
// DEBUG:
// #[cfg(debug_assertions)]
// drag_n_drop::debug_tex_keys,
//
drag_n_drop::file_drag_and_drop_listener,
drag_n_drop::add_and_set_dropped_file.run_if(on_event::<UserAddedTexture>()),
drag_n_drop::override_current_shader.run_if(on_event::<DragNDropShader>()),
screenshot::screenshot_and_version_shader_on_spacebar,
utils::cam_switch_system,
utils::quit,
utils::switch_level,
utils::toggle_transparency,
utils::toggle_window_passthrough,
UserConfig::runtime_updater.run_if(on_event::<KeyboardInput>()),
UserConfig::runtime_updater.run_if(on_event::<WindowResized>()),
),
)
// 2d Only Sytsems
.add_systems(
Update,
(
// utils::max_mon_res, // We're currently not using the maximum resolution of the primary monitor.
utils::update_mouse_pos,
texture_tooling::swap_2d_tex_from_idx,
utils::size_quad
.run_if(in_state(AppState::TwoD))
.run_if(on_event::<WindowResized>()),
),
//
);

#[cfg(feature = "ui")]
shadplay.add_plugins(HelpUIPlugin);

shadplay.run();

Ok(())
Expand Down
Loading

0 comments on commit db23f6a

Please sign in to comment.