Skip to content
Snippets Groups Projects
Commit 0c3dccb9 authored by StarArawn's avatar StarArawn
Browse files

Added a bevy feature to kayak_ui. No functionaltiy should have changed.

parent dfdee362
No related branches found
No related tags found
No related merge requests found
Showing
with 228 additions and 203 deletions
...@@ -1870,6 +1870,7 @@ dependencies = [ ...@@ -1870,6 +1870,7 @@ dependencies = [
"bevy", "bevy",
"derivative", "derivative",
"flo_binding", "flo_binding",
"kayak_font",
"kayak_render_macros", "kayak_render_macros",
"morphorm", "morphorm",
"resources", "resources",
......
...@@ -11,16 +11,16 @@ members = ["bevy_kayak_ui", "kayak_core", "kayak_render_macros", "kayak_font"] ...@@ -11,16 +11,16 @@ members = ["bevy_kayak_ui", "kayak_core", "kayak_render_macros", "kayak_font"]
default = ["bevy_renderer"] default = ["bevy_renderer"]
bevy_renderer = [ bevy_renderer = [
"bevy_kayak_ui", "bevy_kayak_ui",
"kayak_font",
"kayak_core/bevy_renderer", "kayak_core/bevy_renderer",
"kayak_font/bevy_renderer",
"bevy", "bevy",
] ]
[dependencies] [dependencies]
bevy = { version = "0.6.0", optional = true } bevy = { version = "0.6.0", optional = true }
kayak_core = { path = "kayak_core" }
bevy_kayak_ui = { path = "bevy_kayak_ui", optional = true } bevy_kayak_ui = { path = "bevy_kayak_ui", optional = true }
kayak_font = { path = "kayak_font", optional = true } kayak_core = { path = "kayak_core" }
kayak_font = { path = "kayak_font" }
kayak_render_macros = { path = "kayak_render_macros" } kayak_render_macros = { path = "kayak_render_macros" }
[dev-dependencies] [dev-dependencies]
......
...@@ -23,17 +23,17 @@ mod ui_pass_driver; ...@@ -23,17 +23,17 @@ mod ui_pass_driver;
pub mod unified; pub mod unified;
pub mod node { pub mod node {
pub const UI_PASS_DEPENDENCIES: &str = "ui_pass_dependencies"; pub const UI_PASS_DEPENDENCIES: &str = "kayak_ui_pass_dependencies";
pub const UI_PASS_DRIVER: &str = "ui_pass_driver"; pub const UI_PASS_DRIVER: &str = "kayak_ui_pass_driver";
} }
pub mod draw_ui_graph { pub mod draw_ui_graph {
pub const NAME: &str = "draw_ui"; pub const NAME: &str = "kayak_draw_ui";
pub mod input { pub mod input {
pub const VIEW_ENTITY: &str = "view_entity"; pub const VIEW_ENTITY: &str = "kayak_view_entity";
} }
pub mod node { pub mod node {
pub const MAIN_PASS: &str = "ui_pass"; pub const MAIN_PASS: &str = "kayak_ui_pass";
} }
} }
......
...@@ -45,20 +45,22 @@ pub fn extract_texts( ...@@ -45,20 +45,22 @@ pub fn extract_texts(
let chars_layouts = font.get_layout( let chars_layouts = font.get_layout(
CoordinateSystem::PositiveYDown, CoordinateSystem::PositiveYDown,
Alignment::Start, Alignment::Start,
Vec2::new(layout.posx, layout.posy + line_height), (layout.posx, layout.posy + line_height),
Vec2::new(layout.width, layout.height), (layout.width, layout.height),
content, content,
line_height, line_height,
font_size, font_size,
); );
for char_layout in chars_layouts { for char_layout in chars_layouts {
let position = Vec2::new(char_layout.position.0, char_layout.position.1);
let size = Vec2::new(char_layout.size.0, char_layout.size.1);
extracted_texts.push(ExtractQuadBundle { extracted_texts.push(ExtractQuadBundle {
extracted_quad: ExtractedQuad { extracted_quad: ExtractedQuad {
font_handle: Some(font_handle.clone()), font_handle: Some(font_handle.clone()),
rect: Rect { rect: Rect {
min: char_layout.position, min: position,
max: char_layout.position + char_layout.size, max: position + size,
}, },
color: to_bevy_color(background_color), color: to_bevy_color(background_color),
vertex_index: 0, vertex_index: 0,
......
...@@ -7,7 +7,7 @@ use bevy::{ ...@@ -7,7 +7,7 @@ use bevy::{
RenderApp, RenderStage, RenderApp, RenderStage,
}, },
}; };
use kayak_font::{FontTextureCache, KayakFontPlugin}; use kayak_font::bevy::{FontTextureCache, KayakFontPlugin};
mod extract; mod extract;
mod font_mapping; mod font_mapping;
......
...@@ -32,7 +32,10 @@ use bevy::{ ...@@ -32,7 +32,10 @@ use bevy::{
utils::HashMap, utils::HashMap,
}; };
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use kayak_font::{FontRenderingPipeline, FontTextureCache, KayakFont}; use kayak_font::{
bevy::{FontRenderingPipeline, FontTextureCache},
KayakFont,
};
use super::{Dpi, UNIFIED_SHADER_HANDLE}; use super::{Dpi, UNIFIED_SHADER_HANDLE};
use crate::{render::ui_pass::TransparentUI, WindowSize}; use crate::{render::ui_pass::TransparentUI, WindowSize};
......
...@@ -7,13 +7,14 @@ edition = "2021" ...@@ -7,13 +7,14 @@ edition = "2021"
[features] [features]
default = [] default = []
bevy_renderer = ["bevy"] bevy_renderer = ["bevy", "kayak_font/bevy_renderer"]
[dependencies] [dependencies]
as-any = "0.2" as-any = "0.2"
derivative = "2.2" derivative = "2.2"
bevy = { version = "0.6.0", optional = true } bevy = { version = "0.6.0", optional = true }
flo_binding = { git = "https://github.com/StarArawn/flo_binding.git", rev = "c78431a56df5ec082b7e1c271871e6c0ac75e81e" } flo_binding = { git = "https://github.com/StarArawn/flo_binding.git", rev = "c78431a56df5ec082b7e1c271871e6c0ac75e81e" }
kayak_font = { path = "../kayak_font" }
kayak_render_macros = { path = "../kayak_render_macros" } kayak_render_macros = { path = "../kayak_render_macros" }
morphorm = { git = "https://github.com/geom3trik/morphorm", rev = "1243152d4cebea46fd3e5098df26402c73acae91" } morphorm = { git = "https://github.com/geom3trik/morphorm", rev = "1243152d4cebea46fd3e5098df26402c73acae91" }
resources = "1.1" resources = "1.1"
...@@ -5,10 +5,14 @@ edition = "2021" ...@@ -5,10 +5,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["bevy_renderer"]
bevy_renderer = ["bevy"]
[dependencies] [dependencies]
anyhow = { version = "1.0" } anyhow = { version = "1.0" }
bevy = { version = "0.6.0" } bevy = { version = "0.6.0", optional = true }
bytemuck = "1.7.2" bytemuck = "1.7.2"
serde = "1.0" serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde_path_to_error = "0.1" serde_path_to_error = "0.1"
...@@ -5,7 +5,7 @@ use bevy::{ ...@@ -5,7 +5,7 @@ use bevy::{
window::WindowDescriptor, window::WindowDescriptor,
DefaultPlugins, DefaultPlugins,
}; };
use kayak_font::{Alignment, KayakFont, KayakFontPlugin}; use kayak_font::{Alignment, KayakFont, bevy::KayakFontPlugin};
mod renderer; mod renderer;
use renderer::FontRenderPlugin; use renderer::FontRenderPlugin;
......
use bevy::{ use bevy::{
prelude::{Assets, Commands, Handle, Query, Res}, prelude::{Assets, Commands, Handle, Query, Res},
sprite::Rect, sprite::Rect, math::Vec2,
}; };
use kayak_font::{CoordinateSystem, KayakFont}; use kayak_font::{CoordinateSystem, KayakFont};
...@@ -21,20 +21,23 @@ pub fn extract( ...@@ -21,20 +21,23 @@ pub fn extract(
let layouts = font.get_layout( let layouts = font.get_layout(
CoordinateSystem::PositiveYUp, CoordinateSystem::PositiveYUp,
text.horz_alignment, text.horz_alignment,
text.position, (text.position.x, text.position.y),
text.size, (text.size.x, text.size.y),
&text.content, &text.content,
text.line_height, text.line_height,
text.font_size, text.font_size,
); );
for layout in layouts { for layout in layouts {
let position = Vec2::new(layout.position.0, layout.position.1);
let size = Vec2::new(layout.size.0, layout.size.1);
extracted_texts.push(ExtractCharBundle { extracted_texts.push(ExtractCharBundle {
extracted_quad: ExtractedChar { extracted_quad: ExtractedChar {
font_handle: Some(font_handle.clone()), font_handle: Some(font_handle.clone()),
rect: Rect { rect: Rect {
min: layout.position, min: position,
max: layout.position + layout.size, max: position + size,
}, },
color: text.color, color: text.color,
vertex_index: 0, vertex_index: 0,
......
...@@ -11,7 +11,7 @@ use bevy::{ ...@@ -11,7 +11,7 @@ use bevy::{
RenderApp, RenderStage, RenderApp, RenderStage,
}, },
}; };
use kayak_font::FontTextureCache; use kayak_font::bevy::FontTextureCache;
use self::pipeline::{DrawUI, FontPipeline, QuadMeta}; use self::pipeline::{DrawUI, FontPipeline, QuadMeta};
......
...@@ -28,7 +28,10 @@ use bevy::{ ...@@ -28,7 +28,10 @@ use bevy::{
sprite::Rect, sprite::Rect,
}; };
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use kayak_font::{FontRenderingPipeline, FontTextureCache, KayakFont}; use kayak_font::{
bevy::{FontRenderingPipeline, FontTextureCache},
KayakFont,
};
use super::FONT_SHADER_HANDLE; use super::FONT_SHADER_HANDLE;
...@@ -169,7 +172,7 @@ impl FromWorld for FontPipeline { ...@@ -169,7 +172,7 @@ impl FromWorld for FontPipeline {
}, },
depth_stencil: None, depth_stencil: None,
multisample: MultisampleState { multisample: MultisampleState {
count: 1, count: 4,
mask: !0, mask: !0,
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
......
use std::collections::HashMap; use std::collections::HashMap;
use bevy::{ #[cfg(feature = "bevy_renderer")]
asset::{AssetLoader, AssetPath, BoxedFuture, LoadContext, LoadedAsset}, use bevy::{prelude::Handle, reflect::TypeUuid, render::texture::Image};
math::Vec2,
prelude::Handle,
reflect::TypeUuid,
render::texture::Image,
};
use crate::Sdf; use crate::Sdf;
#[cfg(feature = "bevy_renderer")]
#[derive(Debug, Clone, TypeUuid)] #[derive(Debug, Clone, TypeUuid)]
#[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"] #[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"]
pub struct KayakFont { pub struct KayakFont {
...@@ -18,10 +14,17 @@ pub struct KayakFont { ...@@ -18,10 +14,17 @@ pub struct KayakFont {
char_ids: HashMap<char, u32>, char_ids: HashMap<char, u32>,
} }
#[cfg(not(feature = "bevy_renderer"))]
#[derive(Debug, Clone)]
pub struct KayakFont {
pub sdf: Sdf,
char_ids: HashMap<char, u32>,
}
#[derive(Default, Debug, Clone, Copy)] #[derive(Default, Debug, Clone, Copy)]
pub struct LayoutRect { pub struct LayoutRect {
pub position: Vec2, pub position: (f32, f32),
pub size: Vec2, pub size: (f32, f32),
pub content: char, pub content: char,
} }
...@@ -39,9 +42,10 @@ pub enum Alignment { ...@@ -39,9 +42,10 @@ pub enum Alignment {
} }
impl KayakFont { impl KayakFont {
pub fn new(sdf: Sdf, atlas_image: Handle<Image>) -> Self { pub fn new(sdf: Sdf, #[cfg(feature = "bevy_renderer")] atlas_image: Handle<Image>) -> Self {
Self { Self {
sdf, sdf,
#[cfg(feature = "bevy_renderer")]
atlas_image, atlas_image,
char_ids: HashMap::default(), char_ids: HashMap::default(),
} }
...@@ -68,8 +72,8 @@ impl KayakFont { ...@@ -68,8 +72,8 @@ impl KayakFont {
Some(val) => ( Some(val) => (
val.left, val.left,
val.top, val.top,
val.size().x * font_size, val.size().0 * font_size,
val.size().y * font_size, val.size().1 * font_size,
), ),
None => (0.0, 0.0, 0.0, 0.0), None => (0.0, 0.0, 0.0, 0.0),
}; };
...@@ -85,8 +89,8 @@ impl KayakFont { ...@@ -85,8 +89,8 @@ impl KayakFont {
&self, &self,
axis_alignment: CoordinateSystem, axis_alignment: CoordinateSystem,
alignment: Alignment, alignment: Alignment,
position: Vec2, position: (f32, f32),
max_size: Vec2, max_size: (f32, f32),
content: &String, content: &String,
line_height: f32, line_height: f32,
font_size: f32, font_size: f32,
...@@ -94,7 +98,7 @@ impl KayakFont { ...@@ -94,7 +98,7 @@ impl KayakFont {
let mut positions_and_size = Vec::new(); let mut positions_and_size = Vec::new();
let max_glyph_size = self.sdf.max_glyph_size(); let max_glyph_size = self.sdf.max_glyph_size();
let font_ratio = font_size / self.sdf.atlas.size; let font_ratio = font_size / self.sdf.atlas.size;
let resized_max_glyph_size = (max_glyph_size.x * font_ratio, max_glyph_size.y * font_ratio); let resized_max_glyph_size = (max_glyph_size.0 * font_ratio, max_glyph_size.1 * font_ratio);
// TODO: Make this configurable? // TODO: Make this configurable?
let split_chars = vec![' ', '\t', '-', '\n']; let split_chars = vec![' ', '\t', '-', '\n'];
...@@ -117,7 +121,7 @@ impl KayakFont { ...@@ -117,7 +121,7 @@ impl KayakFont {
let mut last_width = 0.0; let mut last_width = 0.0;
for word in content.split(&split_chars[..]) { for word in content.split(&split_chars[..]) {
let word_width = self.get_word_width(word, font_size); let word_width = self.get_word_width(word, font_size);
if x + word_width > max_size.x { if x + word_width > max_size.0 {
y -= shift_sign * line_height; y -= shift_sign * line_height;
line_widths.push((x, line_starting_index, positions_and_size.len())); line_widths.push((x, line_starting_index, positions_and_size.len()));
line_starting_index = positions_and_size.len(); line_starting_index = positions_and_size.len();
...@@ -130,8 +134,8 @@ impl KayakFont { ...@@ -130,8 +134,8 @@ impl KayakFont {
Some(val) => ( Some(val) => (
val.left, val.left,
val.top, val.top,
val.size().x * font_size, val.size().0 * font_size,
val.size().y * font_size, val.size().1 * font_size,
), ),
None => (0.0, 0.0, 0.0, 0.0), None => (0.0, 0.0, 0.0, 0.0),
}; };
...@@ -142,8 +146,8 @@ impl KayakFont { ...@@ -142,8 +146,8 @@ impl KayakFont {
let position_y = y + (shift_sign * top * font_size); let position_y = y + (shift_sign * top * font_size);
positions_and_size.push(LayoutRect { positions_and_size.push(LayoutRect {
position: Vec2::new(position_x, position_y), position: (position_x, position_y),
size: Vec2::new(resized_max_glyph_size.0, resized_max_glyph_size.1), size: (resized_max_glyph_size.0, resized_max_glyph_size.1),
content: c, content: c,
}); });
...@@ -172,50 +176,17 @@ impl KayakFont { ...@@ -172,50 +176,17 @@ impl KayakFont {
for (line_width, starting_index, end_index) in line_widths { for (line_width, starting_index, end_index) in line_widths {
let shift_x = match alignment { let shift_x = match alignment {
Alignment::Start => 0.0, Alignment::Start => 0.0,
Alignment::Middle => (max_size.x - line_width) / 2.0, Alignment::Middle => (max_size.0 - line_width) / 2.0,
Alignment::End => max_size.x - line_width, Alignment::End => max_size.0 - line_width,
}; };
for i in starting_index..end_index { for i in starting_index..end_index {
let layout_rect = &mut positions_and_size[i]; let layout_rect = &mut positions_and_size[i];
layout_rect.position.x += position.x + shift_x; layout_rect.position.0 += position.0 + shift_x;
layout_rect.position.y += position.y; layout_rect.position.1 += position.1;
} }
} }
positions_and_size positions_and_size
} }
} }
#[derive(Default)]
pub struct KayakFontLoader;
impl AssetLoader for KayakFontLoader {
fn load<'a>(
&'a self,
bytes: &'a [u8],
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
Box::pin(async move {
let path = load_context.path();
let path = path.with_extension("png");
let atlas_image_path = AssetPath::new(path, None);
let mut font = KayakFont::new(
Sdf::from_bytes(bytes),
load_context.get_handle(atlas_image_path.clone()),
);
font.generate_char_ids();
load_context
.set_default_asset(LoadedAsset::new(font).with_dependency(atlas_image_path));
Ok(())
})
}
fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["kayak_font"];
EXTENSIONS
}
}
use bevy::math::Vec2;
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
fn from_u32<'de, D>(deserializer: D) -> Result<char, D::Error> fn from_u32<'de, D>(deserializer: D) -> Result<char, D::Error>
...@@ -40,7 +39,7 @@ impl Rect { ...@@ -40,7 +39,7 @@ impl Rect {
self.top - self.bottom self.top - self.bottom
} }
pub fn size(&self) -> Vec2 { pub fn size(&self) -> (f32, f32) {
Vec2::new(self.width(), self.height()) (self.width(), self.height())
} }
} }
...@@ -2,144 +2,183 @@ mod atlas; ...@@ -2,144 +2,183 @@ mod atlas;
mod font; mod font;
mod glyph; mod glyph;
mod metrics; mod metrics;
mod renderer;
mod sdf; mod sdf;
pub use atlas::*; pub use atlas::*;
use bevy::{
prelude::{
AddAsset, AssetEvent, Assets, Commands, EventReader, Handle, Local, Plugin, Res, ResMut,
},
render::{
render_resource::{FilterMode, TextureFormat, TextureUsages},
texture::Image,
RenderApp, RenderStage,
},
utils::HashSet,
};
pub use font::*; pub use font::*;
pub use glyph::*; pub use glyph::*;
pub use metrics::*; pub use metrics::*;
pub use sdf::*; pub use sdf::*;
pub use renderer::*; #[cfg(feature = "bevy_renderer")]
mod renderer;
pub struct KayakFontPlugin; #[cfg(feature = "bevy_renderer")]
pub mod bevy {
pub use crate::renderer::*;
use crate::{KayakFont, Sdf};
use bevy::{
asset::{AssetLoader, AssetPath, BoxedFuture, LoadContext, LoadedAsset},
prelude::{
AddAsset, AssetEvent, Assets, Commands, EventReader, Handle, Local, Plugin, Res, ResMut,
},
render::{
render_resource::{FilterMode, TextureFormat, TextureUsages},
texture::Image,
RenderApp, RenderStage,
},
utils::HashSet,
};
pub struct KayakFontPlugin;
impl Plugin for KayakFontPlugin { impl Plugin for KayakFontPlugin {
fn build(&self, app: &mut bevy::prelude::App) { fn build(&self, app: &mut bevy::prelude::App) {
app.add_asset::<KayakFont>() app.add_asset::<KayakFont>()
.add_asset_loader(KayakFontLoader) .add_asset_loader(KayakFontLoader)
.add_system(init_font_texture); .add_system(init_font_texture);
let render_app = app.sub_app_mut(RenderApp); let render_app = app.sub_app_mut(RenderApp);
render_app render_app
.init_resource::<FontTextureCache>() .init_resource::<FontTextureCache>()
.init_resource::<ExtractedFonts>() .init_resource::<ExtractedFonts>()
.add_system_to_stage(RenderStage::Extract, extract_fonts) .add_system_to_stage(RenderStage::Extract, extract_fonts)
.add_system_to_stage(RenderStage::Prepare, prepare_fonts); .add_system_to_stage(RenderStage::Prepare, prepare_fonts);
}
} }
}
pub fn init_font_texture( pub fn init_font_texture(
mut not_processed: Local<Vec<Handle<KayakFont>>>, mut not_processed: Local<Vec<Handle<KayakFont>>>,
mut font_events: EventReader<AssetEvent<KayakFont>>, mut font_events: EventReader<AssetEvent<KayakFont>>,
mut images: ResMut<Assets<Image>>, mut images: ResMut<Assets<Image>>,
fonts: Res<Assets<KayakFont>>, fonts: Res<Assets<KayakFont>>,
) { ) {
// quick and dirty, run this for all textures anytime a texture is created. // quick and dirty, run this for all textures anytime a texture is created.
for event in font_events.iter() { for event in font_events.iter() {
match event { match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
not_processed.push(handle.clone_weak()); not_processed.push(handle.clone_weak());
}
_ => (),
} }
_ => (),
} }
}
let not_processed_fonts = not_processed.drain(..).collect::<Vec<_>>(); let not_processed_fonts = not_processed.drain(..).collect::<Vec<_>>();
for font_handle in not_processed_fonts { for font_handle in not_processed_fonts {
if let Some(font) = fonts.get(&font_handle) { if let Some(font) = fonts.get(&font_handle) {
if let Some(mut texture) = images.get_mut(&font.atlas_image) { if let Some(mut texture) = images.get_mut(&font.atlas_image) {
texture.texture_descriptor.format = TextureFormat::Rgba8Unorm; texture.texture_descriptor.format = TextureFormat::Rgba8Unorm;
texture.sampler_descriptor.min_filter = FilterMode::Linear; texture.sampler_descriptor.min_filter = FilterMode::Linear;
texture.sampler_descriptor.mipmap_filter = FilterMode::Linear; texture.sampler_descriptor.mipmap_filter = FilterMode::Linear;
texture.sampler_descriptor.mag_filter = FilterMode::Linear; texture.sampler_descriptor.mag_filter = FilterMode::Linear;
texture.texture_descriptor.usage = TextureUsages::TEXTURE_BINDING texture.texture_descriptor.usage = TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST | TextureUsages::COPY_DST
| TextureUsages::COPY_SRC; | TextureUsages::COPY_SRC;
} else { } else {
not_processed.push(font_handle.clone_weak()); not_processed.push(font_handle.clone_weak());
}
} }
} }
} }
}
#[derive(Default)] #[derive(Default)]
pub struct ExtractedFonts { pub struct ExtractedFonts {
pub fonts: Vec<(Handle<KayakFont>, KayakFont)>, pub fonts: Vec<(Handle<KayakFont>, KayakFont)>,
} }
fn extract_fonts( fn extract_fonts(
mut not_processed: Local<Vec<Handle<KayakFont>>>, mut not_processed: Local<Vec<Handle<KayakFont>>>,
mut commands: Commands, mut commands: Commands,
font_assets: Res<Assets<KayakFont>>, font_assets: Res<Assets<KayakFont>>,
mut events: EventReader<AssetEvent<KayakFont>>, mut events: EventReader<AssetEvent<KayakFont>>,
textures: Res<Assets<Image>>, textures: Res<Assets<Image>>,
) { ) {
let mut extracted_fonts = ExtractedFonts { fonts: Vec::new() }; let mut extracted_fonts = ExtractedFonts { fonts: Vec::new() };
let mut changed_assets = HashSet::default(); let mut changed_assets = HashSet::default();
let mut removed = Vec::new(); let mut removed = Vec::new();
for event in events.iter() { for event in events.iter() {
match event { match event {
AssetEvent::Created { handle } => { AssetEvent::Created { handle } => {
changed_assets.insert(handle.clone_weak()); changed_assets.insert(handle.clone_weak());
} }
AssetEvent::Modified { handle } => { AssetEvent::Modified { handle } => {
changed_assets.insert(handle.clone_weak()); changed_assets.insert(handle.clone_weak());
} }
AssetEvent::Removed { handle } => { AssetEvent::Removed { handle } => {
if !changed_assets.remove(handle) { if !changed_assets.remove(handle) {
removed.push(handle.clone_weak()); removed.push(handle.clone_weak());
}
} }
} }
} }
}
for handle in not_processed.drain(..) { for handle in not_processed.drain(..) {
changed_assets.insert(handle); changed_assets.insert(handle);
} }
for handle in changed_assets { for handle in changed_assets {
let font_asset = font_assets.get(&handle).unwrap(); let font_asset = font_assets.get(&handle).unwrap();
if let Some(image) = textures.get(&font_asset.atlas_image) { if let Some(image) = textures.get(&font_asset.atlas_image) {
if !image if !image
.texture_descriptor .texture_descriptor
.usage .usage
.contains(TextureUsages::COPY_SRC) .contains(TextureUsages::COPY_SRC)
|| image.texture_descriptor.format != TextureFormat::Rgba8Unorm || image.texture_descriptor.format != TextureFormat::Rgba8Unorm
{ {
not_processed.push(handle);
continue;
}
} else {
not_processed.push(handle); not_processed.push(handle);
continue; continue;
} }
} else {
not_processed.push(handle); let font = font_asset.clone();
continue; extracted_fonts.fonts.push((handle, font));
} }
let font = font_asset.clone(); commands.insert_resource(extracted_fonts);
extracted_fonts.fonts.push((handle, font));
} }
commands.insert_resource(extracted_fonts); fn prepare_fonts(
} mut extracted_fonts: ResMut<ExtractedFonts>,
mut font_texture_cache: ResMut<FontTextureCache>,
) {
let fonts: Vec<_> = extracted_fonts.fonts.drain(..).collect();
for (handle, font) in fonts {
font_texture_cache.add(handle, font);
}
}
fn prepare_fonts( #[derive(Default)]
mut extracted_fonts: ResMut<ExtractedFonts>, pub struct KayakFontLoader;
mut font_texture_cache: ResMut<FontTextureCache>,
) { impl AssetLoader for KayakFontLoader {
let fonts: Vec<_> = extracted_fonts.fonts.drain(..).collect(); fn load<'a>(
for (handle, font) in fonts { &'a self,
font_texture_cache.add(handle, font); bytes: &'a [u8],
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
Box::pin(async move {
let path = load_context.path();
let path = path.with_extension("png");
let atlas_image_path = AssetPath::new(path, None);
let mut font = KayakFont::new(
Sdf::from_bytes(bytes),
load_context.get_handle(atlas_image_path.clone()),
);
font.generate_char_ids();
load_context
.set_default_asset(LoadedAsset::new(font).with_dependency(atlas_image_path));
Ok(())
})
}
fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["kayak_font"];
EXTENSIONS
}
} }
} }
...@@ -84,7 +84,7 @@ impl FontTextureCache { ...@@ -84,7 +84,7 @@ impl FontTextureCache {
queue, queue,
pipeline, pipeline,
atlas_texture, atlas_texture,
font.sdf.max_glyph_size(), Vec2::new(font.sdf.max_glyph_size().0, font.sdf.max_glyph_size().1),
); );
} else { } else {
was_processed = false; was_processed = false;
...@@ -291,8 +291,8 @@ impl FontTextureCache { ...@@ -291,8 +291,8 @@ impl FontTextureCache {
aspect: TextureAspect::All, aspect: TextureAspect::All,
}, },
Extent3d { Extent3d {
width: glyph_size.x as u32, width: glyph_size.0 as u32,
height: glyph_size.y as u32, height: glyph_size.1 as u32,
depth_or_array_layers: 1, depth_or_array_layers: 1,
}, },
); );
......
use crate::{atlas::Atlas, glyph::Glyph, metrics::Metrics}; use crate::{atlas::Atlas, glyph::Glyph, metrics::Metrics};
use bevy::math::Vec2;
use serde::Deserialize; use serde::Deserialize;
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
...@@ -10,7 +9,7 @@ pub struct Sdf { ...@@ -10,7 +9,7 @@ pub struct Sdf {
kerning: Vec<KerningData>, kerning: Vec<KerningData>,
} }
#[derive(serde::Deserialize, Debug, Clone, Copy)] #[derive(Deserialize, Debug, Clone, Copy)]
pub struct KerningData { pub struct KerningData {
pub unicode1: u32, pub unicode1: u32,
pub unicode2: u32, pub unicode2: u32,
...@@ -48,16 +47,16 @@ impl Sdf { ...@@ -48,16 +47,16 @@ impl Sdf {
value value
} }
pub fn max_glyph_size(&self) -> Vec2 { pub fn max_glyph_size(&self) -> (f32, f32) {
let mut size = Vec2::new(0.0, 0.0); let mut size = (0.0, 0.0);
self.glyphs.iter().for_each(|glyph| { self.glyphs.iter().for_each(|glyph| {
if let Some(atlas_bounds) = glyph.atlas_bounds { if let Some(atlas_bounds) = glyph.atlas_bounds {
let atlas_size = atlas_bounds.size(); let atlas_size = atlas_bounds.size();
if atlas_size.x > size.x { if atlas_size.0 > size.0 {
size.x = atlas_size.x; size.0 = atlas_size.0;
} }
if atlas_size.y > size.y { if atlas_size.1 > size.1 {
size.y = atlas_size.y; size.1 = atlas_size.1;
} }
} }
}); });
...@@ -70,7 +69,7 @@ impl Sdf { ...@@ -70,7 +69,7 @@ impl Sdf {
fn test_sdf_loader() { fn test_sdf_loader() {
use crate::SDFType; use crate::SDFType;
let sdf = Sdf::from_string(include_str!("../assets/roboto.kayak_font").to_string()); let sdf = Sdf::from_string(include_str!("../assets/roboto.kayak_font").to_string());
assert!(sdf.max_glyph_size() == Vec2::new(30.0, 36.0)); assert!(sdf.max_glyph_size() == (30.0, 36.0));
assert!(sdf.atlas.width == 212); assert!(sdf.atlas.width == 212);
assert!(sdf.atlas.height == 212); assert!(sdf.atlas.height == 212);
assert!(matches!(sdf.atlas.sdf_type, SDFType::Msdf)); assert!(matches!(sdf.atlas.sdf_type, SDFType::Msdf));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment