mirror of https://github.com/Leinnan/rpack.git
Use bevy packages instead of main one
This commit is contained in:
parent
0f63f9860b
commit
bc20f9b8b9
|
|
@ -12,15 +12,19 @@ exclude = ["assets", "tiles", "*.rpack_gen.json", "justfile"]
|
|||
|
||||
[features]
|
||||
default = ["bevy"]
|
||||
bevy = ["dep:bevy"]
|
||||
bevy = ["dep:bevy_app", "dep:bevy_platform", "dep:bevy_math", "dep:bevy_image", "dep:bevy_asset", "dep:bevy_ecs", "dep:bevy_reflect", "dep:bevy_ui", "dep:bevy_derive", "dep:bevy_sprite"]
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.16", optional = true, default-features = false, features = [
|
||||
"bevy_asset",
|
||||
"bevy_sprite",
|
||||
"bevy_image",
|
||||
"bevy_ui"
|
||||
] }
|
||||
bevy_math = { version = "0.16", optional = true }
|
||||
bevy_image = { version = "0.16", optional = true }
|
||||
bevy_app = { version = "0.16", optional = true }
|
||||
bevy_asset = { version = "0.16", optional = true }
|
||||
bevy_ecs = { version = "0.16", optional = true }
|
||||
bevy_reflect = { version = "0.16", optional = true }
|
||||
bevy_ui = { version = "0.16", optional = true }
|
||||
bevy_derive = { version = "0.16", optional = true }
|
||||
bevy_platform = { version = "0.16", optional = true }
|
||||
bevy_sprite = { version = "0.16", optional = true }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
thiserror = "2"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
extern crate alloc;
|
||||
use alloc::borrow::Cow;
|
||||
#[cfg(feature = "bevy")]
|
||||
use bevy_asset::Asset;
|
||||
#[cfg(feature = "bevy")]
|
||||
use bevy_reflect::Reflect;
|
||||
|
||||
#[cfg(feature = "bevy")]
|
||||
/// Contains the Bevy plugin for handling `Rpack` assets and atlases.
|
||||
|
|
@ -20,7 +24,7 @@ pub mod prelude {
|
|||
|
||||
/// Defines a rectangle in pixels with the origin at the top-left of the texture atlas.
|
||||
#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[cfg_attr(feature = "bevy", derive(bevy::prelude::Reflect))]
|
||||
#[cfg_attr(feature = "bevy", derive(Reflect))]
|
||||
pub struct SerializableRect {
|
||||
/// Horizontal position the rectangle begins at.
|
||||
pub x: u32,
|
||||
|
|
@ -34,7 +38,7 @@ pub struct SerializableRect {
|
|||
|
||||
/// Represents a single frame within a texture atlas, including its identifier and position.
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[cfg_attr(feature = "bevy", derive(bevy::prelude::Reflect))]
|
||||
#[cfg_attr(feature = "bevy", derive(Reflect))]
|
||||
pub struct AtlasFrame {
|
||||
/// A unique identifier for the frame.
|
||||
pub key: String,
|
||||
|
|
@ -44,7 +48,7 @@ pub struct AtlasFrame {
|
|||
|
||||
/// Represents an entire texture atlas asset, including its metadata and frames.
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[cfg_attr(feature = "bevy", derive(bevy::prelude::Asset, bevy::prelude::Reflect))]
|
||||
#[cfg_attr(feature = "bevy", derive(Asset, Reflect))]
|
||||
pub struct AtlasAsset {
|
||||
/// The overall dimensions of the texture atlas in pixels (width, height).
|
||||
pub size: [u32; 2],
|
||||
|
|
@ -60,7 +64,7 @@ pub struct AtlasAsset {
|
|||
|
||||
/// Represents metadata associated with the texture atlas format.
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[cfg_attr(feature = "bevy", derive(bevy::prelude::Reflect))]
|
||||
#[cfg_attr(feature = "bevy", derive(Reflect))]
|
||||
pub struct AtlasMetadata {
|
||||
/// The version of the texture atlas format.
|
||||
pub format_version: u32,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
use crate::{AtlasAsset, SerializableRect};
|
||||
use bevy::asset::{AssetLoader, AsyncReadExt};
|
||||
use bevy::ecs::system::SystemParam;
|
||||
use bevy::image::ImageSampler;
|
||||
use bevy::platform::collections::HashMap;
|
||||
use bevy::prelude::*;
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::{Asset, AssetApp, Assets, Handle, ReflectAsset};
|
||||
use bevy_asset::{AssetLoader, AsyncReadExt};
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::system::{Res, SystemParam};
|
||||
use bevy_image::{Image, ImageSampler, TextureAtlas, TextureAtlasLayout};
|
||||
use bevy_math::{URect, UVec2};
|
||||
use bevy_platform::collections::HashMap;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_sprite::Sprite;
|
||||
use bevy_ui::widget::ImageNode;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors that can occur while accessing and creating components from [`RpackAtlasAsset`].
|
||||
|
|
@ -19,6 +25,7 @@ pub enum RpackAtlasError {
|
|||
|
||||
/// This is an asset containing the texture atlas image, the texture atlas layout, and a map of the original file names to their corresponding indices in the texture atlas.
|
||||
#[derive(Asset, Debug, Reflect)]
|
||||
#[reflect(Asset, Debug)]
|
||||
pub struct RpackAtlasAsset {
|
||||
/// The texture atlas image.
|
||||
pub image: Handle<Image>,
|
||||
|
|
@ -180,7 +187,7 @@ pub enum RpackAtlasAssetError {
|
|||
/// A Bevy [`LoadDirectError`](bevy::asset::LoadDirectError) that occured
|
||||
/// while loading a [`RpackAtlasAsset::image`](crate::RpackAtlasAsset::image).
|
||||
#[error("could not load asset: {0}")]
|
||||
LoadDirect(Box<bevy::asset::LoadDirectError>),
|
||||
LoadDirect(Box<bevy_asset::LoadDirectError>),
|
||||
/// An error that can occur if there is
|
||||
/// trouble loading the image asset of
|
||||
/// an atlas.
|
||||
|
|
@ -188,8 +195,8 @@ pub enum RpackAtlasAssetError {
|
|||
LoadingImageAsset(String),
|
||||
}
|
||||
|
||||
impl From<bevy::asset::LoadDirectError> for RpackAtlasAssetError {
|
||||
fn from(value: bevy::asset::LoadDirectError) -> Self {
|
||||
impl From<bevy_asset::LoadDirectError> for RpackAtlasAssetError {
|
||||
fn from(value: bevy_asset::LoadDirectError) -> Self {
|
||||
Self::LoadDirect(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +216,7 @@ pub struct RpackAtlasAssetLoaderSettings {
|
|||
impl Default for RpackAtlasAssetLoaderSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
image_sampler: ImageSampler::Descriptor(bevy::image::ImageSamplerDescriptor::nearest()),
|
||||
image_sampler: ImageSampler::Descriptor(bevy_image::ImageSamplerDescriptor::nearest()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,9 +236,9 @@ impl AssetLoader for RpackAtlasAssetLoader {
|
|||
|
||||
async fn load(
|
||||
&self,
|
||||
reader: &mut dyn bevy::asset::io::Reader,
|
||||
reader: &mut dyn bevy_asset::io::Reader,
|
||||
settings: &RpackAtlasAssetLoaderSettings,
|
||||
load_context: &mut bevy::asset::LoadContext<'_>,
|
||||
load_context: &mut bevy_asset::LoadContext<'_>,
|
||||
) -> Result<Self::Asset, Self::Error> {
|
||||
let mut file = String::new();
|
||||
reader.read_to_string(&mut file).await?;
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ impl SkylinePacker {
|
|||
}
|
||||
|
||||
pub fn find_skyline(&self, w: u32, h: u32) -> Option<(usize, Rect)> {
|
||||
let mut bottom = std::u32::MAX;
|
||||
let mut width = std::u32::MAX;
|
||||
let mut bottom = u32::MAX;
|
||||
let mut width = u32::MAX;
|
||||
let mut index = None;
|
||||
let mut rect = Rect::new(0, 0, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use crate::helpers::DroppedFileHelper;
|
||||
use crate::view_settings::ViewSettings;
|
||||
use crossbeam::queue::SegQueue;
|
||||
use egui::containers::menu::MenuButton;
|
||||
use egui::{
|
||||
|
|
@ -12,9 +14,6 @@ use rpack_cli::{
|
|||
packer::SkylinePacker, ImageFile, Spritesheet, SpritesheetBuildConfig, SpritesheetError,
|
||||
};
|
||||
use texture_packer::{Rect, TexturePackerConfig};
|
||||
|
||||
use crate::helpers::DroppedFileHelper;
|
||||
use crate::view_settings::ViewSettings;
|
||||
static INPUT_QUEUE: Lazy<SegQueue<AppImageAction>> = Lazy::new(SegQueue::new);
|
||||
pub const MY_ACCENT_COLOR32: Color32 = Color32::from_rgb(230, 102, 1);
|
||||
pub const GIT_HASH: &str = env!("GIT_HASH");
|
||||
|
|
@ -198,7 +197,6 @@ impl Application {
|
|||
/// Called once before the first frame.
|
||||
#[allow(dead_code, unused_variables, unused_mut)]
|
||||
pub fn new(cc: &eframe::CreationContext<'_>, config_file: Option<String>) -> Self {
|
||||
crate::fonts::setup_custom_fonts(&cc.egui_ctx);
|
||||
// This is also where you can customize the look and feel of egui using
|
||||
// `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
|
||||
egui_extras::install_image_loaders(&cc.egui_ctx);
|
||||
|
|
@ -213,6 +211,13 @@ impl Application {
|
|||
} else {
|
||||
Default::default()
|
||||
};
|
||||
cc.egui_ctx.all_styles_mut(|style| {
|
||||
for font_id in style.text_styles.values_mut() {
|
||||
font_id.size *= 1.4;
|
||||
}
|
||||
});
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
crate::fonts::load_fonts(&cc.egui_ctx);
|
||||
let mut app = Self {
|
||||
last_editor_paths,
|
||||
view_settings,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
pub fn setup_custom_fonts(ctx: &egui::Context) {
|
||||
use std::{ffi::OsString, path::PathBuf, slice::Iter, str::FromStr};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn load_fonts(ctx: &egui::Context) {
|
||||
// Start with the default fonts (we will be adding to them rather than replacing them).
|
||||
let mut fonts = egui::FontDefinitions::default();
|
||||
if let Ok((regular, semibold)) = get_fonts() {
|
||||
|
|
@ -29,35 +32,33 @@ pub fn setup_custom_fonts(ctx: &egui::Context) {
|
|||
.entry(egui::FontFamily::Monospace)
|
||||
.or_default()
|
||||
.push("regular".to_owned());
|
||||
|
||||
// Tell egui to use these fonts:
|
||||
ctx.set_fonts(fonts);
|
||||
}
|
||||
|
||||
ctx.all_styles_mut(|style| {
|
||||
for font_id in style.text_styles.values_mut() {
|
||||
font_id.size *= 1.4;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||
let regular = include_bytes!("../static/JetBrainsMonoNL-Regular.ttf").to_vec();
|
||||
let semibold = include_bytes!("../static/JetBrainsMono-SemiBold.ttf").to_vec();
|
||||
|
||||
Ok((regular, semibold))
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||
let Some(regular) =
|
||||
try_get_font_from_list(&["JetBrainsMonoNL-Regular", "SFNSRounded", "aptos"])
|
||||
get_fonts_from_list(
|
||||
&["SFNSRounded", "aptos"],
|
||||
&["SFNSRounded", "aptos-semibold"],
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn get_fonts_from_list(
|
||||
regular: &[&'static str],
|
||||
semibold: &[&'static str],
|
||||
) -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||
let Some(regular) = regular
|
||||
.iter()
|
||||
.find_map(|f| try_get_font_path_from_os(f).and_then(|path| std::fs::read(path).ok()))
|
||||
else {
|
||||
anyhow::bail!("Failed to find a suitable font");
|
||||
};
|
||||
let Some(semibold) =
|
||||
try_get_font_from_list(&["JetBrainsMono-SemiBold", "SFNSRounded", "aptos-semibold"])
|
||||
let Some(semibold) = semibold
|
||||
.iter()
|
||||
.find_map(|f| try_get_font_path_from_os(f).and_then(|path| std::fs::read(path).ok()))
|
||||
else {
|
||||
anyhow::bail!("Failed to find a suitable font");
|
||||
};
|
||||
|
|
@ -65,75 +66,140 @@ fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
|||
Ok((regular, semibold))
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn try_get_font_from_list(font_names: &[&str]) -> Option<Vec<u8>> {
|
||||
for font_name in font_names {
|
||||
if let Some(font) = try_get_font(font_name) {
|
||||
return Some(font);
|
||||
#[allow(unused)]
|
||||
trait FontLoader {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf>;
|
||||
}
|
||||
|
||||
impl FontLoader for &PathBuf {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf> {
|
||||
font_file_names.iter().find_map(|f| {
|
||||
if self.join(f).exists() {
|
||||
Some(self.join(f))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl FontLoader for &str {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf> {
|
||||
let path = PathBuf::from_str(self).ok()?;
|
||||
font_file_names.iter().find_map(|f| {
|
||||
if path.join(f).exists() {
|
||||
Some(path.join(f))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl FontLoader for (&str, &str) {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf> {
|
||||
let path = PathBuf::from_str(self.0).ok()?;
|
||||
let path = path.join(self.1);
|
||||
path.check_for_font(font_file_names)
|
||||
}
|
||||
}
|
||||
impl FontLoader for Iter<'_, &'static str> {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf> {
|
||||
for path in self.into_iter().flat_map(|s| PathBuf::from_str(s).ok()) {
|
||||
if let Some(font_path) = path.check_for_font(font_file_names) {
|
||||
return Some(font_path);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl FontLoader for (Option<OsString>, &str) {
|
||||
fn check_for_font(self, font_file_names: &[PathBuf]) -> Option<PathBuf> {
|
||||
let path = self
|
||||
.0
|
||||
.and_then(|f| PathBuf::from_str(&f.to_string_lossy()).ok())?;
|
||||
let path = path.join(self.1);
|
||||
path.check_for_font(font_file_names)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn try_get_font(font_name: &str) -> Option<Vec<u8>> {
|
||||
use std::path::Path;
|
||||
pub fn try_get_font_path_from_os(font_name: &str) -> Option<PathBuf> {
|
||||
let file_paths_to_check = if font_name.ends_with(".ttf") || font_name.ends_with(".otf") {
|
||||
vec![PathBuf::from(font_name)]
|
||||
} else {
|
||||
vec![
|
||||
PathBuf::from(format!("{}.ttf", font_name)),
|
||||
PathBuf::from(format!("{}.otf", font_name)),
|
||||
]
|
||||
};
|
||||
get_font_paths()
|
||||
.iter()
|
||||
.find_map(|dir| dir.check_for_font(&file_paths_to_check))
|
||||
}
|
||||
|
||||
for dir in font_dirs() {
|
||||
if let Ok(font) = std::fs::read(Path::new(&dir).join(format!("{}.ttf", font_name))) {
|
||||
return Some(font);
|
||||
}
|
||||
if let Ok(font) = std::fs::read(Path::new(&dir).join(format!("{}.otf", font_name))) {
|
||||
return Some(font);
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn build_path_from_env(env_var: &str, subpath: &str) -> Option<PathBuf> {
|
||||
std::env::var(env_var)
|
||||
.ok()
|
||||
.and_then(|d| PathBuf::from_str(d.as_str()).map(|p| p.join(subpath)).ok())
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(unused)]
|
||||
pub fn get_system_fonts() -> Vec<String> {
|
||||
get_font_paths()
|
||||
.iter()
|
||||
.flat_map(|s| {
|
||||
let dir = std::fs::read_dir(s).ok()?;
|
||||
let dir_entries: Vec<String> = dir
|
||||
.flat_map(|e| {
|
||||
let entry = e.ok()?;
|
||||
if entry.file_name().to_string_lossy().ends_with("ttf")
|
||||
|| entry.file_name().to_string_lossy().ends_with("otf")
|
||||
{
|
||||
Some(
|
||||
entry
|
||||
.file_name()
|
||||
.to_string_lossy()
|
||||
.replace(".ttf", "")
|
||||
.replace(".otf", ""),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Some(dir_entries)
|
||||
})
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn font_dirs() -> Vec<String> {
|
||||
let mut dirs = Vec::new();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
dirs.push("/usr/share/fonts".into());
|
||||
dirs.push("/usr/share/fonts/truetype".into());
|
||||
}
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
dirs.push("/System/Library/Fonts".into());
|
||||
if let Some(resources_font_dir) = std::env::current_exe().ok().and_then(|p| {
|
||||
p.ancestors()
|
||||
.nth(2)
|
||||
.map(|p| p.join("Resources/fonts").to_string_lossy().into_owned())
|
||||
}) {
|
||||
dirs.push(resources_font_dir);
|
||||
}
|
||||
}
|
||||
if let Some(home) =
|
||||
std::env::var_os("HOME").and_then(|s| PathBuf::from_str(&s.to_string_lossy()).ok())
|
||||
{
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
dirs.push(format!("{}/Library/Fonts", home.display()));
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
dirs.push(format!("{}/.local/share/fonts", home.display()));
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn get_font_paths() -> Vec<PathBuf> {
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(path) = build_path_from_env("LOCALAPPDATA", "Microsoft/Windows/Fonts") {
|
||||
vec![path]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Ok(dir) = std::env::var("APPDATA") {
|
||||
let font_path = std::path::Path::new(&dir).join("../Local/Microsoft/Windows/Fonts/");
|
||||
dirs.push(font_path.display().to_string());
|
||||
let mut results = vec![
|
||||
PathBuf::from_str("/usr/share/fonts").unwrap_or_default(),
|
||||
PathBuf::from_str("/usr/share/fonts/truetype").unwrap_or_default(),
|
||||
];
|
||||
if let Some(path) = build_path_from_env("HOME", ".local/share/fonts") {
|
||||
results.push(path);
|
||||
}
|
||||
results
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let mut results = vec![PathBuf::from_str("/System/Library/Fonts").unwrap_or_default()];
|
||||
if let Some(path) = build_path_from_env("HOME", "Library/Fonts") {
|
||||
results.push(path);
|
||||
}
|
||||
results
|
||||
}
|
||||
}
|
||||
|
||||
dirs
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue