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

Simple main menu UI example.

parent bff1e898
No related branches found
No related tags found
No related merge requests found
assets/kenny/panelInset_beigeLight.png

629 B

assets/kenny/panelInset_blue.png

626 B

assets/kenny/panelInset_brown.png

626 B

assets/kenny/panel_beige.png

786 B

assets/kenny/panel_beigeLight.png

785 B

assets/kenny/panel_blue.png

785 B

assets/kenny/panel_brown.png

799 B

......@@ -130,7 +130,7 @@ pub fn extract_nine_patch(
extracted_quads.push(top_middle_quad);
// Bottom
let bottom_y_pos = layout.posy + (layout.width - border.bottom);
let bottom_y_pos = layout.posy + (layout.height - border.bottom);
let bottom_left_quad = ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
......@@ -245,7 +245,7 @@ pub fn extract_nine_patch(
},
uv_min: Some(Vec2::new(
border.left / image_size.x,
border.bottom / image_size.y,
border.top / image_size.y,
)),
uv_max: Some(Vec2::new(
(image_size.x - border.right) / image_size.x,
......
use bevy::{
math::Vec2,
prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut, World},
window::{WindowDescriptor, Windows},
PipelinedDefaultPlugins,
};
use bevy_kayak_ui::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
use kayak_components::{NinePatch, Text};
use kayak_core::{
context::KayakContext,
layout_cache::Space,
styles::{LayoutType, Style, StyleProp, Units},
widget, Children, EventType, Index, OnEvent,
};
use kayak_ui::components::App;
use kayak_ui::core::rsx;
#[widget]
fn BlueButton(context: KayakContext, children: Children, styles: Option<Style>) {
let (blue_button_handle, blue_button_hover_handle) = {
let world = context.get_global_state::<World>();
if world.is_err() {
return;
}
let mut world = world.unwrap();
let (handle1, handle2) = {
let asset_server = world.get_resource::<AssetServer>().unwrap();
let handle1: Handle<bevy::render2::texture::Image> =
asset_server.load("../assets/kenny/buttonSquare_blue.png");
let handle2: Handle<bevy::render2::texture::Image> =
asset_server.load("../assets/kenny/buttonSquare_blue_pressed.png");
(handle1, handle2)
};
let mut image_manager = world.get_resource_mut::<ImageManager>().unwrap();
let blue_button_handle = image_manager.get(&handle1);
let blue_button_hover_handle = image_manager.get(&handle2);
(blue_button_handle, blue_button_hover_handle)
};
let current_button_handle = *context.create_state::<u16>(blue_button_handle).unwrap();
dbg!(current_button_handle);
let button_styles = Style {
width: StyleProp::Value(Units::Pixels(200.0)),
height: StyleProp::Value(Units::Pixels(50.0)),
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
..styles.clone().unwrap_or_default()
};
let button_id = self.get_id();
let on_event = OnEvent::new(move |context, event| match event.event_type {
EventType::Click => {
dbg!("Clicked!");
context.set_current_id(button_id);
context.set_state::<u16>(blue_button_hover_handle);
}
_ => {
context.set_state::<u16>(blue_button_handle);
}
});
rsx! {
<NinePatch
border={Space {
left: 10.0,
right: 10.0,
top: 10.0,
bottom: 10.0,
}}
handle={current_button_handle}
styles={Some(button_styles)}
on_event={Some(on_event)}
>
{children}
</NinePatch>
}
}
fn startup(
mut commands: Commands,
windows: Res<Windows>,
asset_server: Res<AssetServer>,
mut image_manager: ResMut<ImageManager>,
) {
commands.spawn_bundle(UICameraBundle::new());
let window_size = if let Some(window) = windows.get_primary() {
Vec2::new(window.width(), window.height())
} else {
panic!("Couldn't find primary window!");
};
let handle: Handle<bevy::render2::texture::Image> = asset_server.load("kenny/panel_brown.png");
let panel_brown_handle = image_manager.get(&handle);
let context = BevyContext::new(window_size.x, window_size.y, |styles, context| {
// Hack to trick the proc macro for right now..
let parent_id: Option<Index> = None;
let nine_patch_styles = Style {
layout_type: StyleProp::Value(LayoutType::Column),
width: StyleProp::Value(Units::Pixels(512.0)),
height: StyleProp::Value(Units::Pixels(512.0)),
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
..Style::default()
};
let app_styles = Style {
padding_left: StyleProp::Value(Units::Stretch(1.0)),
padding_right: StyleProp::Value(Units::Stretch(1.0)),
padding_top: StyleProp::Value(Units::Stretch(1.0)),
padding_bottom: StyleProp::Value(Units::Stretch(1.0)),
..styles.clone()
};
let header_styles = Style {
width: StyleProp::Value(Units::Pixels(432.0)),
height: StyleProp::Value(Units::Pixels(64.0)),
bottom: StyleProp::Value(Units::Stretch(1.0)),
..Style::default()
};
let play_button_styles = Style {
width: StyleProp::Value(Units::Pixels(54.0)),
height: StyleProp::Value(Units::Pixels(45.0)),
..Style::default()
};
let options_button_text_styles = Style {
width: StyleProp::Value(Units::Pixels(102.0)),
height: StyleProp::Value(Units::Pixels(45.0)),
..Style::default()
};
let options_button_styles = Style {
top: StyleProp::Value(Units::Pixels(15.0)),
..Style::default()
};
rsx! {
<App styles={Some(app_styles)}>
<NinePatch
styles={Some(nine_patch_styles)}
border={Space {
left: 30.0,
right: 30.0,
top: 30.0,
bottom: 30.0,
}}
handle={panel_brown_handle}
>
<Text
styles={Some(header_styles)}
size={50.0}
content={"Name My Game Plz".to_string()}
/>
<BlueButton>
<Text styles={Some(play_button_styles)} size={30.0} content={"Play".to_string()} />
</BlueButton>
<BlueButton styles={Some(options_button_styles)}>
<Text styles={Some(options_button_text_styles)} size={30.0} content={"Options".to_string()} />
</BlueButton>
<BlueButton styles={Some(options_button_styles)}>
<Text styles={Some(play_button_styles)} size={30.0} content={"Quit".to_string()} />
</BlueButton>
</NinePatch>
</App>
}
});
commands.insert_resource(context);
}
fn main() {
BevyApp::new()
.insert_resource(WindowDescriptor {
width: 1270.0,
height: 720.0,
title: String::from("UI Example"),
..Default::default()
})
.add_plugins(PipelinedDefaultPlugins)
.add_plugin(BevyKayakUIPlugin)
.add_startup_system(startup)
.run();
}
......@@ -38,6 +38,7 @@ impl KayakContext {
&mut self,
initial_state: T,
) -> Option<Ref<T>> {
dbg!(self.current_id);
if self.component_states.contains_key(&self.current_id) {
let states = self.component_states.get_mut(&self.current_id).unwrap();
if !states.contains::<T>() {
......@@ -62,10 +63,12 @@ impl KayakContext {
}
pub fn set_state<T: resources::Resource + Clone>(&mut self, state: T) {
dbg!(self.current_id);
if self.component_states.contains_key(&self.current_id) {
let states = self.component_states.get(&self.current_id).unwrap();
if states.contains::<T>() {
let mut mutate_t = states.get_mut::<T>().unwrap();
dbg!("Mutating state!");
self.widget_manager.dirty_nodes.push(self.current_id);
*mutate_t = state;
} else {
......
......@@ -49,6 +49,10 @@ pub struct Style {
pub padding_right: StyleProp<Units>,
pub padding_top: StyleProp<Units>,
pub padding_bottom: StyleProp<Units>,
pub margin_left: StyleProp<Units>,
pub margin_right: StyleProp<Units>,
pub margin_top: StyleProp<Units>,
pub margin_bottom: StyleProp<Units>,
}
impl Default for Style {
......@@ -70,6 +74,10 @@ impl Default for Style {
padding_right: StyleProp::Default,
padding_top: StyleProp::Default,
padding_bottom: StyleProp::Default,
margin_left: StyleProp::Default,
margin_right: StyleProp::Default,
margin_top: StyleProp::Default,
margin_bottom: StyleProp::Default,
}
}
}
......@@ -164,5 +172,21 @@ impl Style {
StyleProp::Inherit => self.padding_bottom = other.padding_bottom.clone(),
_ => (),
}
match self.margin_left {
StyleProp::Inherit => self.margin_left = other.margin_left.clone(),
_ => (),
}
match self.margin_right {
StyleProp::Inherit => self.margin_right = other.margin_right.clone(),
_ => (),
}
match self.margin_top {
StyleProp::Inherit => self.margin_top = other.margin_top.clone(),
_ => (),
}
match self.margin_bottom {
StyleProp::Inherit => self.margin_bottom = other.margin_bottom.clone(),
_ => (),
}
}
}
......@@ -139,6 +139,7 @@ impl WidgetManager {
right: crate::styles::StyleProp::Default,
top: crate::styles::StyleProp::Default,
width: crate::styles::StyleProp::Default,
..Style::default()
};
for dirty_node_index in self.dirty_render_nodes.drain(..) {
let dirty_widget = self.current_widgets[dirty_node_index].as_ref().unwrap();
......
use std::collections::HashSet;
use crate::{
arc_function::build_arc_function,
attribute::Attribute,
......@@ -95,60 +97,101 @@ impl Children {
_ => {
let mut iter = children_quotes.iter();
let first = iter.next().unwrap();
let second = iter.next().unwrap();
let first = build_arc_function(quote! { child1 }, first.clone(), true, 0);
let second = build_arc_function(quote! { child2 }, second.clone(), true, 1);
// First get shared and non-shared attributes..
let mut child_attributes_list = Vec::new();
for i in 0..children_quotes.len() {
child_attributes_list.push(self.get_clonable_attributes(i));
}
let children_attributes0: Vec<_> = self.get_clonable_attributes(0);
let children_attributes1: Vec<_> = self.get_clonable_attributes(1);
let (children_attributes0, children_attributes1, matching) =
handle_tuple_attributes(&children_attributes0, &children_attributes1);
let mut all_attributes = HashSet::new();
for child_attributes in child_attributes_list.iter() {
for child_attribute in child_attributes {
all_attributes.insert(child_attribute.to_string());
}
}
let base_matching: Vec<proc_macro2::TokenStream> = matching
let base_matching: Vec<proc_macro2::TokenStream> = all_attributes
.iter()
.map(|a| {
format!("base_{}", a.to_string())
.to_string()
.parse()
.unwrap()
})
.map(|a| format!("base_{}", a).to_string().parse().unwrap())
.collect();
let all_attributes: Vec<proc_macro2::TokenStream> =
all_attributes.iter().map(|a| a.parse().unwrap()).collect();
let base_clone = quote! {
#(let #base_matching = #matching.clone();)*
#(let #base_matching = #all_attributes.clone();)*
};
let base_clones_inner = quote! {
#(let #matching = #base_matching.clone();)*
#(let #all_attributes = #base_matching.clone();)*
};
let cloned_attrs0 = quote! {
#(let #children_attributes0 = #children_attributes0.clone();)*
};
let cloned_attrs1 = quote! {
#(let #children_attributes1 = #children_attributes1.clone();)*
};
let mut output = Vec::new();
output.push(quote! { #base_clone });
for i in 0..children_quotes.len() {
output.push(quote! { #base_clones_inner });
let name: proc_macro2::TokenStream = format!("child{}", i).parse().unwrap();
let child =
build_arc_function(quote! { #name }, children_quotes[i].clone(), true, i);
output.push(quote! { #child });
}
let tuple_of_tuples = iter.fold(
quote! {
#base_clone
#cloned_attrs0
#base_clones_inner
#first
#base_clones_inner
#cloned_attrs1
#second
},
|renderable, current| quote!((#renderable, #current)),
);
// let first = iter.next().unwrap();
// let second = iter.next().unwrap();
// let first = build_arc_function(quote! { child1 }, first.clone(), true, 0);
// let second = build_arc_function(quote! { child2 }, second.clone(), true, 1);
// let children_attributes0: Vec<_> = self.get_clonable_attributes(0);
// let children_attributes1: Vec<_> = self.get_clonable_attributes(1);
// let (children_attributes0, children_attributes1, matching) =
// handle_tuple_attributes(&children_attributes0, &children_attributes1);
// let base_matching: Vec<proc_macro2::TokenStream> = matching
// .iter()
// .map(|a| {
// format!("base_{}", a.to_string())
// .to_string()
// .parse()
// .unwrap()
// })
// .collect();
// let base_clone = quote! {
// #(let #base_matching = #matching.clone();)*
// };
// let base_clones_inner = quote! {
// #(let #matching = #base_matching.clone();)*
// };
// let cloned_attrs0 = quote! {
// #(let #children_attributes0 = #children_attributes0.clone();)*
// };
// let cloned_attrs1 = quote! {
// #(let #children_attributes1 = #children_attributes1.clone();)*
// };
// let tuple_of_tuples = iter.fold(
// quote! {
// #base_clone
// #cloned_attrs0
// #base_clones_inner
// #first
// #base_clones_inner
// #cloned_attrs1
// #second
// },
// |renderable, current| quote!((#renderable, #current)),
// );
quote! {
Some(std::sync::Arc::new(move |parent_id: Option<kayak_core::Index>, context: &mut kayak_core::context::KayakContext| {
#tuple_of_tuples
#(#output)*
}))
}
// quote! {}
}
}
}
......
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