Add image element
This commit is contained in:
parent
3d222ec2aa
commit
d75930218c
|
@ -3,6 +3,7 @@ use crate::{
|
|||
parse_attributes::set_attribute,
|
||||
};
|
||||
use bevy::{
|
||||
asset::AssetServer,
|
||||
ecs::{entity::Entity, system::Command, world::World},
|
||||
hierarchy::{BuildWorldChildren, Children, DespawnRecursive, Parent},
|
||||
prelude::default,
|
||||
|
@ -10,7 +11,7 @@ use bevy::{
|
|||
text::{Text, TextLayoutInfo, TextStyle},
|
||||
transform::components::Transform,
|
||||
ui::{
|
||||
node_bundles::{NodeBundle, TextBundle},
|
||||
node_bundles::{ImageBundle, NodeBundle, TextBundle},
|
||||
widget::TextFlags,
|
||||
*,
|
||||
},
|
||||
|
@ -28,11 +29,12 @@ pub fn apply_mutations(
|
|||
templates: &mut HashMap<String, BevyTemplate>,
|
||||
root_entity: Entity,
|
||||
world: &mut World,
|
||||
asset_server: &AssetServer,
|
||||
) {
|
||||
for new_template in mutations.templates {
|
||||
templates.insert(
|
||||
new_template.name.to_owned(),
|
||||
BevyTemplate::from_dioxus(&new_template),
|
||||
BevyTemplate::from_dioxus(&new_template, asset_server),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -63,8 +65,11 @@ pub fn apply_mutations(
|
|||
stack.push(entity);
|
||||
}
|
||||
Mutation::CreateTextNode { value, id } => {
|
||||
let entity =
|
||||
BevyTemplateNode::from_dioxus(&TemplateNode::Text { text: value }).spawn(world);
|
||||
let entity = BevyTemplateNode::from_dioxus(
|
||||
&TemplateNode::Text { text: value },
|
||||
asset_server,
|
||||
)
|
||||
.spawn(world);
|
||||
element_id_to_bevy_ui_entity.insert(id, entity);
|
||||
bevy_ui_entity_to_element_id.insert(entity, id);
|
||||
stack.push(entity);
|
||||
|
@ -177,6 +182,7 @@ pub fn apply_mutations(
|
|||
mut visibility,
|
||||
mut z_index,
|
||||
mut text,
|
||||
mut image,
|
||||
) = world
|
||||
.query::<(
|
||||
&mut Style,
|
||||
|
@ -187,6 +193,7 @@ pub fn apply_mutations(
|
|||
&mut Visibility,
|
||||
&mut ZIndex,
|
||||
Option<&mut Text>,
|
||||
Option<&mut UiImage>,
|
||||
)>()
|
||||
.get_mut(world, element_id_to_bevy_ui_entity[&id])
|
||||
.unwrap();
|
||||
|
@ -202,6 +209,8 @@ pub fn apply_mutations(
|
|||
&mut visibility,
|
||||
&mut z_index,
|
||||
text.as_deref_mut(),
|
||||
image.as_deref_mut(),
|
||||
asset_server,
|
||||
);
|
||||
}
|
||||
Mutation::SetText { value, id } => {
|
||||
|
@ -242,23 +251,28 @@ enum BevyTemplateNode {
|
|||
style: StyleComponents,
|
||||
children: Box<[Self]>,
|
||||
},
|
||||
ImageNode {
|
||||
image: UiImage,
|
||||
style: StyleComponents,
|
||||
children: Box<[Self]>,
|
||||
},
|
||||
IntrinsicTextNode(Text),
|
||||
}
|
||||
|
||||
impl BevyTemplate {
|
||||
fn from_dioxus(template: &Template) -> Self {
|
||||
fn from_dioxus(template: &Template, asset_server: &AssetServer) -> Self {
|
||||
Self {
|
||||
roots: template
|
||||
.roots
|
||||
.iter()
|
||||
.map(BevyTemplateNode::from_dioxus)
|
||||
.map(|node| BevyTemplateNode::from_dioxus(node, asset_server))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BevyTemplateNode {
|
||||
fn from_dioxus(node: &TemplateNode) -> Self {
|
||||
fn from_dioxus(node: &TemplateNode, asset_server: &AssetServer) -> Self {
|
||||
match node {
|
||||
TemplateNode::Element {
|
||||
tag: "node",
|
||||
|
@ -266,10 +280,13 @@ impl BevyTemplateNode {
|
|||
attrs,
|
||||
children,
|
||||
} => {
|
||||
let (style, _) = parse_template_attributes(attrs);
|
||||
let (style, _, _) = parse_template_attributes(attrs, Color::NONE, asset_server);
|
||||
Self::Node {
|
||||
style,
|
||||
children: children.iter().map(Self::from_dioxus).collect(),
|
||||
children: children
|
||||
.iter()
|
||||
.map(|node| Self::from_dioxus(node, asset_server))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
TemplateNode::Element {
|
||||
|
@ -278,11 +295,31 @@ impl BevyTemplateNode {
|
|||
attrs,
|
||||
children,
|
||||
} => {
|
||||
let (style, text) = parse_template_attributes(attrs);
|
||||
let (style, text, _) = parse_template_attributes(attrs, Color::NONE, asset_server);
|
||||
Self::TextNode {
|
||||
text,
|
||||
style,
|
||||
children: children.iter().map(Self::from_dioxus).collect(),
|
||||
children: children
|
||||
.iter()
|
||||
.map(|node| Self::from_dioxus(node, asset_server))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
TemplateNode::Element {
|
||||
tag: "image",
|
||||
namespace: Some("bevy_ui"),
|
||||
attrs,
|
||||
children,
|
||||
} => {
|
||||
let (style, _, image) =
|
||||
parse_template_attributes(attrs, Color::WHITE, asset_server);
|
||||
Self::ImageNode {
|
||||
image,
|
||||
style,
|
||||
children: children
|
||||
.iter()
|
||||
.map(|node| Self::from_dioxus(node, asset_server))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
TemplateNode::Text { text } => {
|
||||
|
@ -364,6 +401,35 @@ impl BevyTemplateNode {
|
|||
.push_children(&children)
|
||||
.id()
|
||||
}
|
||||
BevyTemplateNode::ImageNode {
|
||||
image,
|
||||
style,
|
||||
children,
|
||||
} => {
|
||||
let children = children
|
||||
.iter()
|
||||
.map(|child| child.spawn(world))
|
||||
.collect::<Box<[_]>>();
|
||||
world
|
||||
.spawn(NodeBundle {
|
||||
border_color: style.border_color.clone(),
|
||||
..default()
|
||||
})
|
||||
.insert((
|
||||
ImageBundle {
|
||||
image: image.clone(),
|
||||
style: style.style.clone(),
|
||||
background_color: style.background_color.clone(),
|
||||
transform: style.transform.clone(),
|
||||
visibility: style.visibility.clone(),
|
||||
z_index: style.z_index.clone(),
|
||||
..default()
|
||||
},
|
||||
style.outline.clone(),
|
||||
))
|
||||
.push_children(&children)
|
||||
.id()
|
||||
}
|
||||
Self::IntrinsicTextNode(text) => world
|
||||
.spawn(TextBundle {
|
||||
text: text.clone(),
|
||||
|
@ -374,9 +440,17 @@ impl BevyTemplateNode {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_template_attributes(attributes: &[TemplateAttribute]) -> (StyleComponents, Text) {
|
||||
let mut style = StyleComponents::default();
|
||||
fn parse_template_attributes(
|
||||
attributes: &[TemplateAttribute],
|
||||
background_color: Color,
|
||||
asset_server: &AssetServer,
|
||||
) -> (StyleComponents, Text, UiImage) {
|
||||
let mut style = StyleComponents {
|
||||
background_color: BackgroundColor(background_color),
|
||||
..default()
|
||||
};
|
||||
let mut text = Text::from_section("", TextStyle::default());
|
||||
let mut image = UiImage::default();
|
||||
for attribute in attributes {
|
||||
if let TemplateAttribute::Static {
|
||||
name,
|
||||
|
@ -395,12 +469,15 @@ fn parse_template_attributes(attributes: &[TemplateAttribute]) -> (StyleComponen
|
|||
&mut style.visibility,
|
||||
&mut style.z_index,
|
||||
Some(&mut text),
|
||||
Some(&mut image),
|
||||
asset_server,
|
||||
);
|
||||
}
|
||||
}
|
||||
(style, text)
|
||||
(style, text, image)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct StyleComponents {
|
||||
style: Style,
|
||||
border_color: BorderColor,
|
||||
|
@ -410,17 +487,3 @@ struct StyleComponents {
|
|||
visibility: Visibility,
|
||||
z_index: ZIndex,
|
||||
}
|
||||
|
||||
impl Default for StyleComponents {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
style: Default::default(),
|
||||
border_color: Default::default(),
|
||||
outline: Default::default(),
|
||||
background_color: Color::NONE.into(),
|
||||
transform: Default::default(),
|
||||
visibility: Default::default(),
|
||||
z_index: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,4 +93,12 @@ pub mod dioxus_elements {
|
|||
pub const text_color: AttributeDescription = ("text_color", None, false);
|
||||
node_attributes!();
|
||||
}
|
||||
|
||||
pub struct image;
|
||||
impl image {
|
||||
pub const TAG_NAME: &'static str = "image";
|
||||
pub const NAME_SPACE: Option<&'static str> = NAME_SPACE;
|
||||
pub const image_asset_path: AttributeDescription = ("image_asset_path", None, false);
|
||||
node_attributes!();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,15 @@ impl HotReloadingContext for HotReloadContext {
|
|||
return Some(attribute);
|
||||
}
|
||||
}
|
||||
if element_name_rust == dioxus_elements::image::TAG_NAME {
|
||||
let attribute = match attribute_name_rust {
|
||||
"image_asset_path" => Some(("image_asset_path", None)),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(attribute) = attribute {
|
||||
return Some(attribute);
|
||||
}
|
||||
}
|
||||
if let dioxus_elements::node::TAG_NAME | dioxus_elements::text::TAG_NAME = element_name_rust
|
||||
{
|
||||
match attribute_name_rust {
|
||||
|
@ -127,6 +136,10 @@ impl HotReloadingContext for HotReloadContext {
|
|||
dioxus_elements::text::TAG_NAME,
|
||||
dioxus_elements::text::NAME_SPACE,
|
||||
)),
|
||||
dioxus_elements::image::TAG_NAME => Some((
|
||||
dioxus_elements::image::TAG_NAME,
|
||||
dioxus_elements::image::NAME_SPACE,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use bevy::{
|
||||
asset::{AssetPath, AssetServer},
|
||||
math::Quat,
|
||||
render::{color::Color, view::Visibility},
|
||||
text::{Text, TextAlignment},
|
||||
|
@ -18,6 +19,8 @@ pub fn set_attribute(
|
|||
visibility: &mut Visibility,
|
||||
z_index: &mut ZIndex,
|
||||
text: Option<&mut Text>,
|
||||
image: Option<&mut UiImage>,
|
||||
asset_server: &AssetServer,
|
||||
) {
|
||||
#[allow(unused_variables, unreachable_code)]
|
||||
match (name, value) {
|
||||
|
@ -198,6 +201,9 @@ pub fn set_attribute(
|
|||
("text_color", value) if text.is_some() => {
|
||||
text.unwrap().sections[0].style.color = parse_color(value);
|
||||
}
|
||||
("image_asset_path", value) if image.is_some() => {
|
||||
image.unwrap().texture = asset_server.load(AssetPath::parse(value));
|
||||
}
|
||||
_ => panic!("Encountered unsupported bevy_dioxus attribute `{name}: {value}`."),
|
||||
}
|
||||
}
|
||||
|
|
33
src/tick.rs
33
src/tick.rs
|
@ -6,6 +6,7 @@ use crate::{
|
|||
DioxusUiRoot, UiContext, UiRoot,
|
||||
};
|
||||
use bevy::{
|
||||
asset::AssetServer,
|
||||
ecs::{
|
||||
entity::Entity,
|
||||
world::{Mut, World},
|
||||
|
@ -104,23 +105,31 @@ fn render_ui(root_entity: Entity, ui_root: &mut UiRoot, world: &mut World) {
|
|||
crate::hot_reload::update_templates(world, &mut ui_root.virtual_dom);
|
||||
|
||||
if ui_root.needs_rebuild {
|
||||
let mutations = ui_root.virtual_dom.rebuild();
|
||||
world.resource_scope(|world, asset_server: Mut<AssetServer>| {
|
||||
apply_mutations(
|
||||
mutations,
|
||||
&mut ui_root.element_id_to_bevy_ui_entity,
|
||||
&mut ui_root.bevy_ui_entity_to_element_id,
|
||||
&mut ui_root.templates,
|
||||
root_entity,
|
||||
world,
|
||||
&asset_server,
|
||||
);
|
||||
});
|
||||
ui_root.needs_rebuild = false;
|
||||
}
|
||||
|
||||
let mutations = ui_root.virtual_dom.render_immediate();
|
||||
world.resource_scope(|world, asset_server: Mut<AssetServer>| {
|
||||
apply_mutations(
|
||||
ui_root.virtual_dom.rebuild(),
|
||||
mutations,
|
||||
&mut ui_root.element_id_to_bevy_ui_entity,
|
||||
&mut ui_root.bevy_ui_entity_to_element_id,
|
||||
&mut ui_root.templates,
|
||||
root_entity,
|
||||
world,
|
||||
&asset_server,
|
||||
);
|
||||
ui_root.needs_rebuild = false;
|
||||
}
|
||||
|
||||
apply_mutations(
|
||||
ui_root.virtual_dom.render_immediate(),
|
||||
&mut ui_root.element_id_to_bevy_ui_entity,
|
||||
&mut ui_root.bevy_ui_entity_to_element_id,
|
||||
&mut ui_root.templates,
|
||||
root_entity,
|
||||
world,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue