Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write a Guide / Tutorial #505

Open
9 of 33 tasks
mitchmindtree opened this issue Jul 11, 2015 · 22 comments
Open
9 of 33 tasks

Write a Guide / Tutorial #505

mitchmindtree opened this issue Jul 11, 2015 · 22 comments

Comments

@mitchmindtree
Copy link
Contributor

mitchmindtree commented Jul 11, 2015

The Guide should probably be structured to look something like this:

  • 1. What is Conrod
    • A brief summary of 2D GUI, Conrod use-cases.
    • some screenshots / video demos
    • list the available widgets
    • link to examples
    • A brief intro to "Immediate Mode" aka OMG why do I construct the Widget EVERY FRAME?!
      • how does IMGUI work (explain caching etc)
      • why did we use IMGUI (pros/cons)
    • The "Builder Pattern" (why use it, how it works)
  • 2. Using Conrod (to create a basic app GUI)
    • A walk-through showing how to use Conrod to make a GUI with a small demonstration app.
    • Setup a basic window using glium.
    • Create a demo App struct with some dummy data.
    • Writing a ui function for the app.
    • Generate a list of IDs using the widget_ids! macro (not yet implemented).
    • Draw a basic widget (i.e. Button).
    • Demo Positionable, Colorable, etc traits (show where to find all available builder methods / traits for a widget in the docs).
    • Slightly more complicated widget (DropDownList)
    • Attach widgets to a parent "canvas" (demo different internal canvasses).
  • 3. Using and Customising Themes
    • Explanation of how Conrod uses Themes.
    • How to use a Theme (load from json).
    • How to make a custom Theme (use in demo app from previous chapter).
    • How to add custom widget styling to a Theme.
  • 4. Designing custom Widgets using Conrod's Widget trait
    • Start with basics by demoing how to make a Button.
    • Discuss how widget state is stored within the Graph and how each of the different types of IDs/indices relate to each other.
    • Move on to a more advanced example composing a widget from other widgets.
  • 5. How to use Conrod with your own backend
    • Demo how to use conrod's render::Primitives to draw to a custom backend.
  • 6. Contributing to Conrod
    • Details about the library innards
    • New widgets are welcome etc

I think it'd make sense to do this in markdown for now (i.e. a GUIDE.md) but I'm open to any other suggestions 👍

@olsonjeffery
Copy link

Hi, I know it's not super helpful to just make a request without offering to help, but would it worth considering adding discussion tuts around using conrod as the GUI layer while using lower-level (than piston) frameworks (like glium or gfx-rs) for actual graphics?

That's my current situation. I'm using gfx-rs for the main graphics b/c im doing a 2d charmap/tilemap thing on a plane mesh + shader stuff. I would like to use piston for the GUI portion while taking on all the piston-idiomatic baggage (or taking it on the degree least neccesary.. eg how to use piston when i'm creating windows via raw glutin calls?).

@mitchmindtree
Copy link
Contributor Author

@olsonjeffery good point! I've edited the comment above with a 5th chapter. No problem btw, any ideas / requests are welcome 👍

@jarrett
Copy link
Contributor

jarrett commented Jul 30, 2015

I'm starting to use Conrod heavily on a real project, and I need it to be documented for possible future devs. So I was thinking I might just take a stab at this guide. What form should it take? A Markdown file? A web page? A wiki?

@mitchmindtree
Copy link
Contributor Author

@jarrett that would be great! Yeah I think a GUIDE.md at the top level is probably a good idea for now 👍 I'll add it to the top comment.

@Phlosioneer
Copy link

List of available widgets is outdated - Image widget added in #696.

@mitchmindtree
Copy link
Contributor Author

@Phlosioneer thanks, fixed in #731.

@enricostano
Copy link
Contributor

Some broken link fixed #829

@zen3ger
Copy link

zen3ger commented Jan 12, 2017

I'm newbie in rust and conrod (and github), however I wanted to help people on how to get started with conrod. I thought it could be usefull to document how I go along the bulletpoints here. I'm about to do a simple demoapp based on how things are layed out under 2) point.

so far I have this code:
https://github.com/zen3ger/conrod-guessing_game

I'm open to any suggestions!

@lukors
Copy link

lukors commented Jul 16, 2017

I think having a placeholder "hello world" example for the "Using Conrod" chapter would be great. I can't find a simple minimal example, and since that part of the guide is not written yet, and I don't seem to be able to figure it out on my own, I don't know where to start with this library.

I feel like if I had that, I might be able to figure things out using the documentation from there.

If anyone knows where I can find a minimal example like this, or want to add this to the "Using Conrod" chapter as a placeholder, that would be much appreciated.

@bobgates
Copy link
Contributor

Okay, I have a simple little hello world, but what to do with it? Post it on github and link? I'm new to this open source practice.

Also: is the guide somewhere on github? I haven't been able to find it easily, but that's not to say it isn't there. I'd like to have a go at 2 above - having spent a couple of days going through exactly the exercise that is envisaged for it.

How should code be linked to the guide? I can put short examples in the text, but it might be useful to have all the code available too.

@mitchmindtree
Copy link
Contributor Author

@bobgates great, I really appreciate your interest in helping out with this!

The guide is included within the conrod repo as doc-comments within a public module in the src repo - conrod/src/guide/. This allows users to generate the guide from the src using cargo doc and also means we can use docs.rs for hosting it. It also means we can use cargo test to test the inline code examples.

I think the first chapter should be a decent example of how to handle links etc, but just let us know if anything is unclear from that point.

How should code be linked to the guide? I can put short examples in the text, but it might be useful to have all the code available too.

Agreed! Perhaps we could have an examples/tutorial/ subdirectory with example names like examples/tutorial/hello_world_01.rs for each piece of code that is relevant to the hello world tutorial as an example. As a reference, I quite like the way glium does this by providing the updated source for each major step in the tutorial as 01.rs, 02.rs, etc.

@Ironmaggot
Copy link

Hello, a newb to conrod and rust here. It is a bit hard to figure out conrod using the examples alone. Specifically, it is difficult to differentiate what is and what isn't the boilerplate code. So, I propose a "Quick Start" chapter for the guide. That "Quick Start" chapter should contain the essential code which every conrod program would need to function - in other words a general use template. The template would explain what each region of the code is meant for and the comments in that template would also mark down where the rest of the program is placed according to conrod custom.

Uses for reader:

  • Beginner - will be able to compare the template with the examples to learn the code.
  • Experienced - can copy the template into one's new project to start building the UI right away.

@mitchmindtree
Copy link
Contributor Author

@Ironmaggot perhaps this could be based around the hello_world.rs example - I think it is probably the simplest example that doesn't use the support module.

@Ironmaggot
Copy link

Ironmaggot commented Aug 28, 2017

@mitchmindtree I tried to use hello_world.rs example and tried to transform it into a "spiritual" representation of what I meant. I most probably got things wrong in this example, but I hope people can understand what I am trying to convey with this.

There are a couple of problems with hello_world.rs though. Most of the other examples seemed to have a separate "Ids" section. I take that such a section is necessary once the UI gets more complex than the hello_world.rs. I think that there should be a dedicated section for that in the template as well. Similarly, there should be sections for other things which become required once a program gets more complex. Although, due to my lack of knowledge about conrod, I can't think of any.

Another section that I didn't know where to place was the section where the "juice" of the app should go. You know, the part of the app for which one builds the UI and how it should behave in relation to the other sections.

In the example below, I wrote the /* comments */. I don't know enough conrod to template'ify it more.

Example of what a template could look like - Click to expand
//! A simple example that demonstrates using conrod within a basic `winit` window loop, using
//! `glium` to render the `conrod::render::Primitives` to screen.

#[cfg(all(feature="winit", feature="glium"))] #[macro_use] extern crate conrod;

fn main() {
    feature::main();
}

#[cfg(all(feature="winit", feature="glium"))]
mod feature {
    use conrod::{self, widget, Colorable, Positionable, Widget};
    use conrod::backend::glium::glium::{self, Surface};

    pub fn main() {
        /* GRAPHICS OPTIONS--------------------------------------------------------------------
        Define window details here. If you have an .ini file where users can set preferences for 
        graphics options, this would be the place they are read and stored. Place here graphics 
        settings such as resolution, vsync on/off, multisampling level, etc. Contents of this 
        section will be used in INITIALIZATION PROCEDURES. */

        const WIDTH: u32 = 400;
        const HEIGHT: u32 = 200;

        /* INITIALIZATION PROCEDURES--------------------------------------------
        Following blocks of code build the necessary infrastructure for conrod's 
        functioning.*/

        // Building the window
        let mut events_loop = glium::glutin::EventsLoop::new();
        let window = glium::glutin::WindowBuilder::new()
            .with_title("Hello Conrod!")
            .with_dimensions(WIDTH, HEIGHT);
        let context = glium::glutin::ContextBuilder::new()
            .with_vsync(true)
            .with_multisampling(4);
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        // construct our `Ui`.
        let mut ui = conrod::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();

        // Generate the widget identifiers.
        widget_ids!(struct Ids { text });
        let ids = Ids::new(ui.widget_id_generator());

        // Add a `Font` to the `Ui`'s `font::Map` from file.
        const FONT_PATH: &'static str =
            concat!(env!("CARGO_MANIFEST_DIR"), "/assets/fonts/NotoSans/NotoSans-Regular.ttf");
        ui.fonts.insert_from_file(FONT_PATH).unwrap();

        // A type used for converting `conrod::render::Primitives` into `Command`s that can be used
        // for drawing to the glium `Surface`.
        let mut renderer = conrod::backend::glium::Renderer::new(&display).unwrap();

        // The image map describing each of our widget->image mappings (in our case, none).
        let image_map = conrod::image::Map::<glium::texture::Texture2d>::new();

        let mut events = Vec::new();

        'render: loop {
            /* RENDERING LOOP'S INFRASTRUCTURE--------------------------------------
            Following code is the plumbing which should be present in every render loop
            for conrod to function as intended. This section gets the events ready 
            for processing. (Needs some sort of laconic explanation WHY the things here 
            are the way they are.)*/

            events.clear();

            // Get all the new events since the last frame.
            events_loop.poll_events(|event| { events.push(event); });

            // If there are no new events, wait for one.
            if events.is_empty() {
                events_loop.run_forever(|event| {
                    events.push(event);
                    glium::glutin::ControlFlow::Break
                });
            }

            // Process the events.
            for event in events.drain(..) {

                /* INPUT PROCESSING------------------------------------------------------
                Use this section of the code to process the input. Add new matches here
                for input as you develop functionality for them. This section's responsibility
                should be to receive the input events and prepare them for "ui" event 
                handling. */

                // Break from the loop upon `Escape` or closed window.
                match event.clone() {
                    glium::glutin::Event::WindowEvent { event, .. } => {
                        match event {
                            glium::glutin::WindowEvent::Closed |
                            glium::glutin::WindowEvent::KeyboardInput {
                                input: glium::glutin::KeyboardInput {
                                    virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape),
                                    ..
                                },
                                ..
                            } => break 'render,
                            _ => (),
                        }
                    }
                    _ => (),
                };

                // Use the `winit` backend feature to convert the winit event to a conrod input.
                let input = match conrod::backend::winit::convert_event(event, &display) {
                    None => continue,
                    Some(input) => input,
                };

                // Handle the input with the `Ui`.
                ui.handle_event(input);

                // Set the widgets.
                let ui = &mut ui.set_widgets();

               /* BUILDING OF THE USER INTERFACE-----------------------------------
                This is the place where you write the code for the elements of your UI.
                This section should be responsible for all your widgets, buttons,
                primitives and text which will appear on the screen during the use. */

                // "Hello World!" in the middle of the screen.
                widget::Text::new("Hello World!")
                    .middle_of(ui.window)
                    .color(conrod::color::WHITE)
                    .font_size(32)
                    .set(ids.text, ui);
            }

            // Draw the `Ui` if it has changed.
            if let Some(primitives) = ui.draw_if_changed() {
                renderer.fill(&display, primitives, &image_map);
                let mut target = display.draw();
                target.clear_color(0.0, 0.0, 0.0, 1.0);
                renderer.draw(&display, &mut target, &image_map).unwrap();
                target.finish().unwrap();
            }
        }
    }
}

#[cfg(not(all(feature="winit", feature="glium")))]
mod feature {
    pub fn main() {
        println!("This example requires the `winit` and `glium` features. \
                 Try running `cargo run --release --features=\"winit glium\" --example <example_name>`");
    }
}

@lukors
Copy link

lukors commented Mar 17, 2018

Nice work @Ironmaggot! That helps clear some things up. I think that could serve as a good base, if we can just get one working template that can be used to build programs on with comments, that would be incredibly useful for people.

I'm very interested in helping out with this. However, I'm in the same boat as you @Ironmaggot in that I don't know enough to build on that template.

I would really appreciate some help from someone who knows this library better than I do. Even after starting on an app and having a functional UI, I'm having trouble expanding it because I don't understand how the library is structured.

I'm currently reading Conrod code and trying to figure it all out, but if someone who knows more about this would be willing to point me towards where I can find good information/code about it, or write out the basic structure of how it all works, that would be very useful. Either way I will help write this tutorial that hopefully will unlock this library for other people in my situation.

@atoav
Copy link

atoav commented Aug 18, 2018

Conrod seems super nice, but is quite unusable due to its lack of a guide.
The examples are nice to have, but the amount of boilerplate code is too high to be of good use for anybody who just wants to get started. For example it is totally unclear what you would need to import in your own because of all the feature flags etc.

I think 2. Using Conrod (to create a basic app GUI) is meant to adress this – sadly since I first checked out conrod (nearly 1,5 years ago), there has been no progress to this. Does this mean conrod is abandoned?

@luleyleo
Copy link

I took the template that I've created for myself, rewrote, documented and uploaded it.
Maybe this helps a bit until someone finds the time (and motivation) to write the guide.
https://github.com/Finnerale/conrod-boilerplate

@JadedBlueEyes
Copy link

Hey guys, I think it might be a good idea to use mdBook. It's what the Rust book is made in.

@tobia
Copy link

tobia commented Feb 18, 2019

Hello. I just found out about Conrod and I think it's pretty awesome! I'm going to use it for my next project, and contribute whatever I can. But for now, I just want to add to the discussion by saying what is it that I'm struggling with, as a beginner.

I'm finding it really hard to understand the role of all the libraries and frameworks being used. The homepage and the introduction What is Conrod? mention a ton of them: winit, gfx, glium, piston, vulkano, glutin, sdl2, glfw, raw opengl...

I'm sure all of those dependencies have their purpose, their pros and cons. I've been reading some of their documentation, just to understand if they fit my use case or not, but I'm far from having a complete picture.

For example, in my case I'd like to write a cross-platform (Win / Mac / Linux X11) GUI program, to be used both as a standalone utility and as a VST plugin (different build targets.) I don't need 3D graphics, nor a game engine. What combination of backends should I choose? What about people who are developing games? I think a small chapter about backend selection would be of much use, written by somebody who already knows what all those libraries are, their pros and cons.

Also, a short tip on how to use crate imports and/or feature flags to perform said selection would also be useful for us newbies. I'm still learning Rust and right now I can't figure out what piece of code is actually receiving the flags set by --features "winit glium" in the Build and run the examples page!

@JadedBlueEyes
Copy link

FYI, you should probably check out other crates, before you settle on any one.
Some I've found include

@tobia
Copy link

tobia commented Feb 19, 2019

@derpmarine168 thank you. Some I had not seen before. I checked them all, here are my impressions:

  • orbTk uses libSDL as backend, which is a can of worms IMHO and overkill / dependence hell, unless you're developing a game or multimedia app and are committed to SDL for other reasons. Running ldd on a hello world binary scared me out of using it.
  • GTK-rs and GTK in general is great if you're targeting the Linux desktop or writing apps with a large, complex UI, but IMHO not the best choice for a multi-platform small utility/plugin with minimal UI, like what I'm trying to do.
  • Azul seems to bring in parts of Firefox's rendering engine!? 😲 It's a cool idea and a great take on the Electron trainwreck, but maybe a bit overkill? I'll keep it in mind though. Seems polished enough and has abundant documentation. It's somewhat heavier, with a release build hello world taking 6.6MB on disk and 30MB RSS, compared to the Conrod winit glium demo: 4.1MB on disk and 22MB RSS (of course a typical Electron app takes 400MB of RAM, so yes I'm splitting hairs lol)
  • Cedar, Relm, and Limn are experimental/incomplete works in progress, interesting per se, but not something I can build upon right away.
  • Windows GUI is clearly Windows specific.

I will write some code to get familiar with Conrod and Azul, to figure out which one fits my use case better. Thank you for your pointers!

@lucidBrot
Copy link

I managed to get a hello world to work. You can find the files for download, as well as an ugly writeup how I got there under lucidbrot/conrod-howto.

The most helpful thing was when I discovered the guide hidden in the conrod_core source folder. It's worth pointing out that the linked third chapter is not yet linked in the README.

Before you link it now, it is also worth pointing out that it is seemingly not entirely up to date or some things were missing. That may be a layer 8 problem, but perhaps it would need a rework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests