Skip to content
Snippets Groups Projects
Unverified Commit 4b45882c authored by John's avatar John Committed by GitHub
Browse files

Merge pull request #83 from TheRawMeatball/split-renderer

Split the renderer
parents 137c421a 1bcca74a
No related branches found
No related tags found
No related merge requests found
Showing
with 303 additions and 44 deletions
......@@ -442,11 +442,24 @@ dependencies = [
"ndk-glue 0.5.0",
]
[[package]]
name = "bevy_kayak_renderer"
version = "0.0.1"
dependencies = [
"bevy",
"bytemuck",
"kayak_font",
"serde",
"serde_json",
"serde_path_to_error",
]
[[package]]
name = "bevy_kayak_ui"
version = "0.0.1"
dependencies = [
"bevy",
"bevy_kayak_renderer",
"bytemuck",
"kayak_core",
"kayak_font",
......
[package]
name = "bevy_kayak_renderer"
version = "0.0.1"
edition = "2021"
[dependencies]
bytemuck = "1.7.2"
bevy = { version = "0.6.0" }
kayak_font = { path = "../kayak_font" }
serde = "1.0"
serde_json = "1.0"
serde_path_to_error = "0.1"
use bevy::{
prelude::*,
window::{WindowCreated, WindowResized},
};
pub mod camera;
pub mod render;
pub use camera::*;
#[derive(Default)]
pub struct BevyKayakRendererPlugin;
impl Plugin for BevyKayakRendererPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_system(update_window_size)
.init_resource::<WindowSize>()
.add_plugin(render::BevyKayakUIRenderPlugin)
.add_plugin(camera::KayakUICameraPlugin);
}
}
/// Tracks the bevy window size.
#[derive(Default, Debug, Clone, Copy, PartialEq)]
pub struct WindowSize(pub f32, pub f32);
fn update_window_size(
mut window_resized_events: EventReader<WindowResized>,
mut window_created_events: EventReader<WindowCreated>,
) {
let mut changed_window_ids = Vec::new();
// handle resize events. latest events are handled first because we only want to resize each
// window once
for event in window_resized_events.iter().rev() {
if changed_window_ids.contains(&event.id) {
continue;
}
changed_window_ids.push(event.id);
}
// handle resize events. latest events are handled first because we only want to resize each
// window once
for event in window_created_events.iter().rev() {
if changed_window_ids.contains(&event.id) {
continue;
}
changed_window_ids.push(event.id);
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Corner<T> {
pub top_left: T,
pub top_right: T,
pub bottom_left: T,
pub bottom_right: T,
}
use bevy::{
core_pipeline::node::MAIN_PASS_DRIVER,
prelude::{Commands, Plugin, Res},
render::{
camera::ActiveCameras,
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
render_phase::{DrawFunctions, RenderPhase},
RenderApp, RenderStage,
},
};
use crate::{
render::{
ui_pass::MainPassUINode, ui_pass_driver::UIPassDriverNode, unified::UnifiedRenderPlugin,
},
UICameraBundle,
};
use self::ui_pass::TransparentUI;
mod ui_pass;
mod ui_pass_driver;
pub mod unified;
pub mod node {
pub const UI_PASS_DEPENDENCIES: &str = "kayak_ui_pass_dependencies";
pub const UI_PASS_DRIVER: &str = "kayak_ui_pass_driver";
}
pub mod draw_ui_graph {
pub const NAME: &str = "kayak_draw_ui";
pub mod input {
pub const VIEW_ENTITY: &str = "kayak_view_entity";
}
pub mod node {
pub const MAIN_PASS: &str = "kayak_ui_pass";
}
}
pub struct BevyKayakUIRenderPlugin;
impl Plugin for BevyKayakUIRenderPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
let render_app = app.sub_app_mut(RenderApp);
render_app
.init_resource::<DrawFunctions<TransparentUI>>()
.add_system_to_stage(RenderStage::Extract, extract_core_pipeline_camera_phases);
// .add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<TransparentUI>);
let pass_node_ui = MainPassUINode::new(&mut render_app.world);
let mut graph = render_app.world.get_resource_mut::<RenderGraph>().unwrap();
let mut draw_ui_graph = RenderGraph::default();
draw_ui_graph.add_node(draw_ui_graph::node::MAIN_PASS, pass_node_ui);
let input_node_id = draw_ui_graph.set_input(vec![SlotInfo::new(
draw_ui_graph::input::VIEW_ENTITY,
SlotType::Entity,
)]);
draw_ui_graph
.add_slot_edge(
input_node_id,
draw_ui_graph::input::VIEW_ENTITY,
draw_ui_graph::node::MAIN_PASS,
MainPassUINode::IN_VIEW,
)
.unwrap();
graph.add_sub_graph(draw_ui_graph::NAME, draw_ui_graph);
graph.add_node(node::UI_PASS_DEPENDENCIES, EmptyNode);
graph.add_node(node::UI_PASS_DRIVER, UIPassDriverNode);
graph
.add_node_edge(node::UI_PASS_DEPENDENCIES, node::UI_PASS_DRIVER)
.unwrap();
graph
.add_node_edge(MAIN_PASS_DRIVER, node::UI_PASS_DRIVER)
.unwrap();
app.add_plugin(UnifiedRenderPlugin);
}
}
pub fn extract_core_pipeline_camera_phases(
mut commands: Commands,
active_cameras: Res<ActiveCameras>,
) {
if let Some(camera_2d) = active_cameras.get(UICameraBundle::UI_CAMERA) {
if let Some(entity) = camera_2d.entity {
commands
.get_or_spawn(entity)
.insert(RenderPhase::<TransparentUI>::default());
}
}
}
use bevy::{
math::Vec2,
prelude::{Assets, Commands, HandleUntyped, Plugin, Res},
reflect::TypeUuid,
render::{
color::Color, render_phase::DrawFunctions, render_resource::Shader, texture::Image,
RenderApp, RenderStage,
},
sprite::Rect,
render::{render_phase::DrawFunctions, render_resource::Shader, RenderApp, RenderStage},
window::Windows,
};
use kayak_core::{render_primitive::RenderPrimitive, styles::Corner, Binding, Bound};
use kayak_font::KayakFont;
use crate::{
render::{
ui_pass::TransparentUI,
unified::pipeline::{DrawUI, QuadMeta, UnifiedPipeline},
},
BevyContext, FontMapping, ImageManager, WindowSize,
WindowSize,
};
use self::pipeline::{ExtractQuadBundle, ExtractedQuad, ImageBindGroups, UIQuadType};
use self::pipeline::ImageBindGroups;
pub mod font;
pub mod image;
mod nine_patch;
mod pipeline;
mod quad;
pub mod pipeline;
mod text;
pub const UNIFIED_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 7604018236855288450);
......@@ -39,15 +29,14 @@ impl Plugin for UnifiedRenderPlugin {
let unified_shader = Shader::from_wgsl(include_str!("shader.wgsl"));
shaders.set_untracked(UNIFIED_SHADER_HANDLE, unified_shader);
app.add_plugin(font::TextRendererPlugin)
.add_plugin(image::ImageRendererPlugin);
app.add_plugin(text::TextRendererPlugin);
let render_app = app.sub_app_mut(RenderApp);
render_app
.init_resource::<ImageBindGroups>()
.init_resource::<UnifiedPipeline>()
.init_resource::<QuadMeta>()
.add_system_to_stage(RenderStage::Extract, extract)
.add_system_to_stage(RenderStage::Extract, extract_baseline)
.add_system_to_stage(RenderStage::Prepare, pipeline::prepare_quads)
.add_system_to_stage(RenderStage::Queue, pipeline::queue_quads);
......@@ -64,83 +53,17 @@ impl Plugin for UnifiedRenderPlugin {
pub struct Dpi(f32);
pub fn extract(
pub fn extract_baseline(
mut commands: Commands,
context: Option<Res<BevyContext>>,
fonts: Res<Assets<KayakFont>>,
font_mapping: Res<FontMapping>,
image_manager: Res<ImageManager>,
images: Res<Assets<Image>>,
windows: Res<Windows>,
window_size: Res<Binding<WindowSize>>,
window_size: Res<WindowSize>,
) {
if context.is_none() {
return;
}
let context = context.unwrap();
let render_primitives = if let Ok(context) = context.kayak_context.read() {
context.widget_manager.build_render_primitives()
} else {
vec![]
};
// dbg!(&render_primitives);
let dpi = if let Some(window) = windows.get_primary() {
window.scale_factor() as f32
} else {
1.0
};
let mut extracted_quads = Vec::new();
for render_primitive in render_primitives {
match render_primitive {
RenderPrimitive::Text { .. } => {
let text_quads = font::extract_texts(&render_primitive, &fonts, &font_mapping, dpi);
extracted_quads.extend(text_quads);
}
RenderPrimitive::Image { .. } => {
let image_quads = image::extract_images(&render_primitive, &image_manager, dpi);
extracted_quads.extend(image_quads);
}
RenderPrimitive::Quad { .. } => {
let quad_quads = quad::extract_quads(&render_primitive, 1.0);
extracted_quads.extend(quad_quads);
}
RenderPrimitive::NinePatch { .. } => {
let nine_patch_quads =
nine_patch::extract_nine_patch(&render_primitive, &image_manager, &images, dpi);
extracted_quads.extend(nine_patch_quads);
}
RenderPrimitive::Clip { layout } => {
extracted_quads.push(ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
min: Vec2::new(layout.posx, layout.posy) * dpi,
max: Vec2::new(layout.posx + layout.width, layout.posy + layout.height)
* dpi,
},
color: Color::default(),
vertex_index: 0,
char_id: 0,
z_index: layout.z_index,
font_handle: None,
quad_type: UIQuadType::Clip,
type_index: 0,
border_radius: Corner::default(),
image: None,
uv_min: None,
uv_max: None,
},
});
}
_ => {}
}
}
commands.insert_resource(window_size.get());
commands.insert_resource(*window_size);
commands.insert_resource(Dpi(dpi));
commands.spawn_batch(extracted_quads);
}
......@@ -38,8 +38,8 @@ use kayak_font::{
};
use super::{Dpi, UNIFIED_SHADER_HANDLE};
use crate::{render::ui_pass::TransparentUI, WindowSize};
use kayak_core::styles::Corner;
use crate::render::ui_pass::TransparentUI;
use crate::{Corner, WindowSize};
pub struct UnifiedPipeline {
view_layout: BindGroupLayout,
......@@ -300,7 +300,7 @@ impl FromWorld for UnifiedPipeline {
#[derive(Debug, Bundle)]
pub struct ExtractQuadBundle {
pub(crate) extracted_quad: ExtractedQuad,
pub extracted_quad: ExtractedQuad,
}
#[derive(Debug, Clone, Copy, PartialEq)]
......
use bevy::{
prelude::{Assets, Plugin, Res, ResMut},
prelude::{Plugin, Res, ResMut},
render::{
render_asset::RenderAssets,
renderer::{RenderDevice, RenderQueue},
......@@ -7,47 +7,21 @@ use bevy::{
RenderApp, RenderStage,
},
};
use kayak_font::{
bevy::{FontTextureCache, KayakFontPlugin},
KayakFont,
};
mod extract;
mod font_mapping;
use crate::BevyContext;
use kayak_font::bevy::{FontTextureCache, KayakFontPlugin};
use super::pipeline::UnifiedPipeline;
pub use extract::extract_texts;
pub use font_mapping::*;
#[derive(Default)]
pub struct TextRendererPlugin;
impl Plugin for TextRendererPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_plugin(KayakFontPlugin)
.init_resource::<FontMapping>()
.add_system(process_loaded_fonts);
app.add_plugin(KayakFontPlugin);
let render_app = app.sub_app_mut(RenderApp);
render_app.add_system_to_stage(RenderStage::Queue, create_and_update_font_cache_texture);
}
}
fn process_loaded_fonts(
mut font_mapping: ResMut<FontMapping>,
fonts: Res<Assets<KayakFont>>,
bevy_context: Option<Res<BevyContext>>,
) {
if let Some(context) = bevy_context {
if context.is_added() {
font_mapping.mark_all_as_new();
}
font_mapping.add_loaded_to_kayak(&fonts, &context);
}
}
fn create_and_update_font_cache_texture(
device: Res<RenderDevice>,
queue: Res<RenderQueue>,
......
......@@ -8,6 +8,7 @@ bytemuck = "1.7.2"
bevy = { version = "0.6.0" }
kayak_core = { path = "../kayak_core" }
kayak_font = { path = "../kayak_font" }
bevy_kayak_renderer = { path = "../bevy_kayak_renderer" }
serde = "1.0"
serde_json = "1.0"
serde_path_to_error = "0.1"
......@@ -7,17 +7,16 @@ use bevy::{
};
mod bevy_context;
mod camera;
mod cursor;
mod key;
mod render;
use crate::cursor::convert_cursor_icon;
pub use bevy_context::BevyContext;
pub use camera::*;
pub use bevy_kayak_renderer::camera::*;
use kayak_core::{bind, Binding, InputEvent, MutableBound};
pub use render::unified::font::FontMapping;
pub use render::unified::image::ImageManager;
pub use render::font::FontMapping;
pub use render::image::ImageManager;
#[derive(Default)]
pub struct BevyKayakUIPlugin;
......@@ -25,8 +24,8 @@ pub struct BevyKayakUIPlugin;
impl Plugin for BevyKayakUIPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.insert_resource(bind(WindowSize::default()))
.add_plugin(render::BevyKayakUIRenderPlugin)
.add_plugin(camera::KayakUICameraPlugin)
.add_plugin(bevy_kayak_renderer::BevyKayakRendererPlugin)
.add_plugin(render::BevyKayakUIExtractPlugin)
.add_system(update_window_size)
.add_system(process_events.exclusive_system())
.add_system(update.exclusive_system());
......
......@@ -4,12 +4,12 @@ use bevy::{
sprite::Rect,
};
use kayak_core::render_primitive::RenderPrimitive;
use kayak_core::styles::Corner;
use kayak_font::{Alignment, CoordinateSystem, KayakFont};
use crate::{
use crate::to_bevy_color;
use bevy_kayak_renderer::{
render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType},
to_bevy_color,
Corner,
};
use super::font_mapping::FontMapping;
......
use bevy::prelude::{Assets, Plugin, Res, ResMut};
use kayak_font::KayakFont;
mod extract;
mod font_mapping;
use crate::BevyContext;
pub use extract::extract_texts;
pub use font_mapping::*;
#[derive(Default)]
pub struct TextRendererPlugin;
impl Plugin for TextRendererPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.init_resource::<FontMapping>()
.add_system(process_loaded_fonts);
}
}
fn process_loaded_fonts(
mut font_mapping: ResMut<FontMapping>,
fonts: Res<Assets<KayakFont>>,
bevy_context: Option<Res<BevyContext>>,
) {
if let Some(context) = bevy_context {
if context.is_added() {
font_mapping.mark_all_as_new();
}
font_mapping.add_loaded_to_kayak(&fonts, &context);
}
}
use bevy::{math::Vec2, prelude::Res, render::color::Color, sprite::Rect};
use kayak_core::render_primitive::RenderPrimitive;
use crate::{
use crate::ImageManager;
use bevy_kayak_renderer::{
render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType},
ImageManager,
Corner,
};
pub fn extract_images(
......@@ -33,7 +34,12 @@ pub fn extract_images(
font_handle: None,
quad_type: UIQuadType::Image,
type_index: 0,
border_radius,
border_radius: Corner {
top_left: border_radius.top_left,
top_right: border_radius.top_right,
bottom_left: border_radius.bottom_left,
bottom_right: border_radius.bottom_right,
},
image: image_manager
.get_handle(handle)
.and_then(|a| Some(a.clone_weak())),
......
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