Skip to content
Snippets Groups Projects
Commit 542013bb authored by Maccesch's avatar Maccesch
Browse files

Merge remote-tracking branch 'upstream/main' into feature/grid-layout

parents 4aa58707 a046e334
No related branches found
No related tags found
No related merge requests found
Showing
with 104 additions and 59 deletions
assets/lato-light - Copy.png

66.5 KiB

{
"file": "lato-light.ttf",
"char_range_start": "0x20",
"char_range_end": "0x7f"
}
\ No newline at end of file
assets/lato-light.kttf-cached.png

144 KiB

File added
assets/main_menu/kayak.png

30.6 KiB

{
"file": "roboto.ttf",
"char_range_start": "0x20",
"char_range_end": "0x7f"
}
\ No newline at end of file
assets/roboto.kttf-cached.png

150 KiB

File added
# Chapter 1 - Installing and hello world!
Kayak UI is quite easy to setup! First make sure you add it to your cargo.toml file in your project.
Because a crate has yet to be released this currently this looks like:
```toml
kayak_ui = { git = "https://github.com/StarArawn/kayak_ui/", rev = "9b212e230a5325a3ac6897390ded0bc358eebc80"}
kayak_ui = "0.1"
```
Once you've added Kayak UI to your bevy project you can now start to use it! In order for you to copy and run this in your own project don't forget to move the `roboto.kayak_font` and the `roboto.png` files to your asset folder. Optionally you can also generate your own font! See: [Chapter 5 - Fonts](./chapter_5.md)
Once you've added Kayak UI to your bevy project you can now start to use it! In order for you to copy and run this in your own project don't forget to move the `roboto.kayak_font` and the `roboto.png` files to your asset folder. Optionally you can also generate your own font! See: [Chapter 5 - Fonts](./chapter_6.md)
Hello World Example:
```rust
......@@ -20,8 +19,6 @@ fn startup(
) {
font_mapping.set_default(asset_server.load("roboto.kayak_font"));
commands.spawn(UICameraBundle::new());
let mut widget_context = KayakRootContext::new();
let parent_id = None;
......
......@@ -8,7 +8,8 @@ Kayak UI builds out UI using a tree structure. A widget can be defined as any ob
### Widgets are entities
Kayak UI uses Bevy ECS. Each widget is considered an entity with a collection of data. Typically an widget and it's entity can contain whatever data desired, but some common components are:
- Mount - A component tag used to know that a widget was spawned and added to the tree.
- KStyle - Used to describe how a widget looks. Kayak uses this component to dictate UI rendering.
- KStyle - Used to pass in styles from outside of a widget.
- ComputedStyles - The actual styles of a widget. Styles define the look and layout of the widget. Kayak uses this component to dictate UI rendering.
- KChildren - A collection of entities that are added to the tree in a deferred way. These entities are coming from higher up the hierarchy.
- OnEvent - A mini/micro bevy system that lets you respond to UI input events.
- OnChange - A mini/micro system which allows changes to state based on value changes to state.
......@@ -23,6 +24,7 @@ It's advised to have bundles that correspond to a group of components on a widge
pub struct BackgroundBundle {
pub background: Background,
pub styles: KStyle,
pub computed_styles: ComputedStyles,
pub children: KChildren,
pub on_event: OnEvent,
pub widget_name: WidgetName,
......
......@@ -27,6 +27,7 @@ impl Widget for MyButtonProps { }
pub struct MyButtonBundle {
pub props: MyButtonProps,
pub styles: KStyle,
pub computed_styles: ComputedStyles,
pub children: KChildren,
// This allows us to hook into on click events!
pub on_event: OnEvent,
......@@ -39,6 +40,7 @@ impl Default for MyButtonBundle {
Self {
props: MyButtonProps::default(),
styles: KStyle::default(),
computed_styles: ComputedStyles::default(),
children: KChildren::default(),
on_event: OnEvent::default(),
// Kayak uses this component to find out more information about your widget.
......@@ -76,6 +78,7 @@ pub fn my_button_render(
rsx! {
<BackgroundBundle
styles={background_styles}
// We pass the children to the background bundle!
children={children.clone()}
/>
......
......@@ -4,7 +4,18 @@ Kayak UI uses SDF(signed distance fields) for rendering fonts. More specifically
- Fast rendering!
- No need for a new asset for each font size. MSDF's can size to any font size!
Font's are stored as an atlased image and a json file which tells Kayak about the font glyphs. Check out `roboto.kayak_font` and `roboto.png` in the `assets` folder.
Fonts are stored in two different ways. First a font can be defined as a Kayak TTF(kttf) file.
These font files are relatively simple and simply link to a ttf font:
```json
{
"file": "roboto.ttf",
"char_range_start": "0x20",
"char_range_end": "0x7f"
}
```
The char range is a defined as u32 char values. 0x20 through 0x7f represents most of the standard English language characters. Font's using this method are processed in native rust into MSDF's. The output is cached as the generation can take a while.
Fonts are also stored as an atlased image and a json file which tells Kayak about the font glyphs. These fonts are generated using `msdf-atlas-gen`. Check out `roboto.kayak_font` and `roboto.png` in the `assets` folder. The cached file name will be located next to the kttf file and have the file format of: `{font_name}.kttf-cached.png`.
## Generating new fonts.
In order to create a new font you need to use the `msdf-atlas-gen` tool. This can be found at:
......
......@@ -225,10 +225,10 @@ fn startup(
}}
>
<TextWidgetBundle
styles={text_styles.clone()}
text={TextProps {
size: 13.0,
content: "You can check if the cursor is over the UI or on a focusable widget using the BevyContext resource.".to_string(),
user_styles: text_styles.clone(),
..Default::default()
}}
/>
......@@ -241,13 +241,13 @@ fn startup(
styles={button_styles}
/>
<TextWidgetBundle
styles={KStyle {
top: Units::Pixels(10.0).into(),
..text_styles
}}
text={TextProps {
size: 11.0,
content: "Go ahead and click the button! The tile won't move.".to_string(),
user_styles: KStyle {
top: Units::Pixels(10.0).into(),
..text_styles
},
..Default::default()
}}
/>
......
......@@ -6,7 +6,7 @@ fn startup(
mut font_mapping: ResMut<FontMapping>,
asset_server: Res<AssetServer>,
) {
font_mapping.set_default(asset_server.load("lato-light.kayak_font"));
font_mapping.set_default(asset_server.load("lato-light.kttf"));
let image = asset_server.load("panel.png");
......
......@@ -39,13 +39,13 @@ fn my_widget_render(
rsx! {
<ElementBundle>
<KButtonBundle
styles={KStyle {
left: Units::Stretch(1.0).into(),
right: Units::Stretch(1.0).into(),
..Default::default()
}}
button={KButton {
text: "Show Window".into(),
user_styles: KStyle {
left: Units::Stretch(1.0).into(),
right: Units::Stretch(1.0).into(),
..Default::default()
}
}}
on_event={OnEvent::new(
move |In((event_dispatcher_context, _, mut event, _entity)): In<(EventDispatcherContext, WidgetState, Event, Entity)>,
......@@ -109,7 +109,7 @@ fn startup(
mut font_mapping: ResMut<FontMapping>,
asset_server: Res<AssetServer>,
) {
font_mapping.set_default(asset_server.load("lato-light.kayak_font"));
font_mapping.set_default(asset_server.load("lato-light.kttf"));
// Camera 2D forces a clear pass in bevy.
// We do this because our scene is not rendering anything else.
......
......@@ -256,14 +256,14 @@ fn update_theme_demo(
rsx! {
<ElementBundle>
<TextWidgetBundle
styles={KStyle {
height: StyleProp::Value(Units::Pixels(28.0)),
..Default::default()
}}
text={TextProps {
content: select_lbl,
size: 14.0,
line_height: Some(28.0),
user_styles: KStyle {
height: StyleProp::Value(Units::Pixels(28.0)),
..Default::default()
},
..Default::default()
}}
/>
......@@ -278,10 +278,10 @@ fn update_theme_demo(
}}
>
<TextWidgetBundle
styles={text_styles}
text={TextProps {
content: "Lorem ipsum dolor...".into(),
size: 12.0,
user_styles: text_styles,
..Default::default()
}}
/>
......
......@@ -86,20 +86,23 @@ fn menu_button_render(
styles={KStyle {
width: Units::Stretch(1.0).into(),
height: Units::Pixels(40.0).into(),
bottom: Units::Pixels(30.0).into(),
left: Units::Pixels(50.0).into(),
right: Units::Pixels(50.0).into(),
..KStyle::default()
}}
on_event={on_event}
>
<TextWidgetBundle
styles={KStyle {
top: Units::Stretch(1.0).into(),
bottom: Units::Stretch(1.0).into(),
..Default::default()
}}
text={TextProps {
alignment: Alignment::Middle,
content: button_text,
size: 28.0,
user_styles: KStyle {
top: Units::Stretch(1.0).into(),
bottom: Units::Stretch(1.0).into(),
..Default::default()
},
..Default::default()
}}
/>
......@@ -120,7 +123,7 @@ fn startup(
asset_server: Res<AssetServer>,
mut preload_resource: ResMut<PreloadResource>,
) {
font_mapping.set_default(asset_server.load("lato-light.kayak_font"));
font_mapping.set_default(asset_server.load("lato-light.kttf"));
let mut widget_context = KayakRootContext::new();
widget_context.add_plugin(KayakWidgetsContextPlugin);
......@@ -133,6 +136,7 @@ fn startup(
let panel1_image = asset_server.load("main_menu/panel1.png");
let logo_image = asset_server.load("main_menu/logo.png");
let kayak_image = asset_server.load("main_menu/kayak.png");
let button_image = asset_server.load("main_menu/button.png");
let button_image_hover = asset_server.load("main_menu/button-hover.png");
......@@ -185,6 +189,16 @@ fn startup(
..KStyle::default()
}}
>
<KImageBundle
image={KImage(kayak_image)}
styles={KStyle {
width: Units::Pixels(310.0).into(),
height: Units::Pixels(104.0).into(),
top: Units::Pixels(25.0).into(),
bottom: Units::Pixels(25.0).into(),
..KStyle::default()
}}
/>
<KImageBundle
image={KImage(logo_image)}
styles={KStyle {
......@@ -194,21 +208,12 @@ fn startup(
..KStyle::default()
}}
/>
<ElementBundle
id={"button_area"}
styles={KStyle {
left: Units::Pixels(50.0).into(),
right: Units::Pixels(50.0).into(),
..Default::default()
}}
>
<MenuButtonBundle button={MenuButton { text: "Play".into() }} />
<MenuButtonBundle button={MenuButton { text: "Options".into() }} />
<MenuButtonBundle
button={MenuButton { text: "Quit".into() }}
on_event={handle_click_close}
/>
</ElementBundle>
<MenuButtonBundle button={MenuButton { text: "Play".into() }} />
<MenuButtonBundle button={MenuButton { text: "Options".into() }} />
<MenuButtonBundle
button={MenuButton { text: "Quit".into() }}
on_event={handle_click_close}
/>
</NinePatchBundle>
</KayakAppBundle>
}
......
......@@ -14,19 +14,26 @@ pub struct MyQuad {
fn my_quad_update(
In((_widget_context, entity)): In<(KayakWidgetContext, Entity)>,
mut query: Query<(&MyQuad, &mut KStyle, &mut OnEvent)>,
mut query: Query<(&MyQuad, &KStyle, &mut ComputedStyles, &mut OnEvent)>,
) -> bool {
if let Ok((quad, mut style, mut on_event)) = query.get_mut(entity) {
if style.render_command.resolve() != RenderCommand::Quad {
style.render_command = StyleProp::Value(RenderCommand::Quad);
style.position_type = StyleProp::Value(KPositionType::SelfDirected);
style.left = StyleProp::Value(Units::Pixels(quad.pos.x));
style.top = StyleProp::Value(Units::Pixels(quad.pos.y));
style.width = StyleProp::Value(Units::Pixels(quad.size.x));
style.height = StyleProp::Value(Units::Pixels(quad.size.y));
style.background_color = StyleProp::Value(quad.color);
style.z_index = StyleProp::Value(quad.z_index);
}
if let Ok((quad, style, mut computed_styles, mut on_event)) = query.get_mut(entity) {
*computed_styles = KStyle::default()
.with_style(KStyle {
render_command: StyleProp::Value(RenderCommand::Quad),
position_type: StyleProp::Value(KPositionType::SelfDirected),
left: StyleProp::Value(Units::Pixels(quad.pos.x)),
top: StyleProp::Value(Units::Pixels(quad.pos.y)),
width: StyleProp::Value(Units::Pixels(quad.size.x)),
height: StyleProp::Value(Units::Pixels(quad.size.y)),
z_index: StyleProp::Value(quad.z_index),
..Default::default()
})
.with_style(style)
.with_style(KStyle {
background_color: StyleProp::Value(quad.color),
..Default::default()
})
.into();
*on_event = OnEvent::new(
move |In((event_dispatcher_context, _, mut event, entity)): In<(
......@@ -65,6 +72,7 @@ impl Widget for MyQuad {}
pub struct MyQuadBundle {
my_quad: MyQuad,
styles: KStyle,
computed_styles: ComputedStyles,
on_event: OnEvent,
widget_name: WidgetName,
}
......@@ -75,6 +83,7 @@ impl Default for MyQuadBundle {
my_quad: Default::default(),
styles: KStyle::default(),
on_event: OnEvent::default(),
computed_styles: ComputedStyles::default(),
widget_name: MyQuad::default().get_name(),
}
}
......
......@@ -6,7 +6,13 @@ fn startup(
mut font_mapping: ResMut<FontMapping>,
asset_server: Res<AssetServer>,
) {
font_mapping.set_default(asset_server.load("roboto.kayak_font"));
let font_asset = asset_server.load("roboto.kayak_font");
font_mapping.set_default(font_asset.clone());
// You can force the entire font to use subpixel rendering.
// Note: The subpixel settings on the text widget or render command
// will be ignored if this setting is used.
font_mapping.force_subpixel(&font_asset);
// Camera 2D forces a clear pass in bevy.
// We do this because our scene is not rendering anything else.
......
......@@ -15,6 +15,7 @@ struct CurrentCountState {
struct CurrentCountBundle {
count: CurrentCount,
styles: KStyle,
computed_styles: ComputedStyles,
widget_name: WidgetName,
}
......@@ -23,6 +24,7 @@ impl Default for CurrentCountBundle {
Self {
count: CurrentCount::default(),
styles: KStyle::default(),
computed_styles: ComputedStyles::default(),
widget_name: CurrentCount::default().get_name(),
}
}
......@@ -83,7 +85,7 @@ fn startup(
mut font_mapping: ResMut<FontMapping>,
asset_server: Res<AssetServer>,
) {
font_mapping.set_default(asset_server.load("lato-light.kayak_font"));
font_mapping.set_default(asset_server.load("lato-light.kttf"));
// Camera 2D forces a clear pass in bevy.
// We do this because our scene is not rendering anything else.
......
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