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