Struct thyme::Context

source ·
pub struct Context { /* private fields */ }
Expand description

The main Thyme Context that holds internal PersistentState and is responsible for creating Frames.

This is created by build on ContextBuilder after resource registration is complete.

Implementations§

source§

impl Context

source

pub fn wants_mouse(&self) -> bool

Returns true if thyme wants to use the mouse in the current frame, generally because the mouse is over a Thyme widget. If this returns true, you probably want Thyme to handle input this frame, while if it returns false, your application or game logic should handle input.

source

pub fn wants_keyboard(&self) -> bool

Returns true if thyme wants to use keyboard input in the current frame, generally because a widget that accepts text input is keyboard focused. If this returns true, you probably don’t want to handle keyboard events in your own application code.

source

pub fn mouse_time_in_current_widget(&self) -> u32

Returns the amount of time, in milliseconds, that the mouse has been hovering (inside) of the widget that it is currently inside. If hovered is true in a WidgetState, then the mouse has been hovering that widget for this amount of time.

source

pub fn set_scale_factor(&mut self, scale: f32)

Sets the scale factor, sometimes referred to as HiDPI factor for the monitor. This is normally handled by the IO backend, which will set the scale factor based on a scale factor changed event. User code should not need to call this.

source

pub fn scale_factor(&self) -> f32

Returns the current scale factor being used internally by Thyme. See set_scale_factor

source

pub fn set_display_size(&mut self, size: Point)

Set the display size in logical pixels (physical pixels divided by the scale factor). This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.

source

pub fn display_size(&self) -> Point

Returns the current display size being used internally by Thyme. See set_display_size

source

pub fn add_mouse_wheel(&mut self, delta: Point)

Add mouse wheel event, with delta being the amount of device-dependant logical scrolling. This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.

source

pub fn set_input_modifiers(&mut self, input_modifiers: InputModifiers)

Set the input modifiers - the status of keys such as ctrl and shift. This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.

source

pub fn set_mouse_pressed(&mut self, pressed: bool, index: usize)

Set the mouse pressed state for a given mouse button.

Inputs:
  • button pressed state
  • index: 0 = LeftClick, 1 = Right Click, 2 = Middle Click This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.
source

pub fn push_character(&mut self, c: char)

Pushes a character (that was received from the keyboard) to thyme, to be dispatched to the appropriate widget based on keyboard focus in the next Frame. This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.

source

pub fn mouse_pos(&self) -> Point

Returns the current mouse position, based on mouse cursor movement. The scale factor must be taken into account to convert physical pixels to the logical pixels used by this. This may be useful is you want to get Thyme’s last mouse position outside of a Thyme frame for the rest of your application to use.

source

pub fn set_mouse_pos(&mut self, pos: Point)

Set mouse position, based on mouse cursor movement. The scale factor must be taken into account to convert physical pixels to the logical pixels used by this. This is normally handled by the IO backend, which will set this in response to a window resize event. User code should not need to call this.

source

pub fn add_theme_file<P: Into<PathBuf>>(&mut self, path: P)

Adds the specified path as a source file for the resources being used by the theme for this context. This will only work if the theme was set up to read source data from files, i.e. using ContextBuilder#register_theme_from_files This does not rebuild the theme; you will need to call rebuild_all for that.

Examples found in repository?
examples/demo.rs (line 88)
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    pub fn check_context_changes<R: Renderer>(&mut self, context: &mut Context, renderer: &mut R) {
        if let Some(old_choice) = self.old_theme_choice.take() {
            context.remove_theme_file(old_choice.path());
            context.add_theme_file(self.theme_choice.path());
        }

        if self.reload_assets {
            if let Err(e) = context.rebuild_all(renderer) {
                log::error!("Unable to rebuild theme: {}", e);
            }
            self.reload_assets = false;
        } else if !self.live_reload_disabled {
            if let Err(e) = context.check_live_reload(renderer) {
                log::error!("Unable to live reload theme: {}", e);
            }
        }
    }
source

pub fn remove_theme_file<P: Into<PathBuf>>(&mut self, path: P)

Removes the theme source file with the specified path from the resources being used by the theme for this context, if it is present. If it is not present, does nothing. This does not rebuild the theme; you will need to call rebuild_all for that.

Examples found in repository?
examples/demo.rs (line 87)
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    pub fn check_context_changes<R: Renderer>(&mut self, context: &mut Context, renderer: &mut R) {
        if let Some(old_choice) = self.old_theme_choice.take() {
            context.remove_theme_file(old_choice.path());
            context.add_theme_file(self.theme_choice.path());
        }

        if self.reload_assets {
            if let Err(e) = context.rebuild_all(renderer) {
                log::error!("Unable to rebuild theme: {}", e);
            }
            self.reload_assets = false;
        } else if !self.live_reload_disabled {
            if let Err(e) = context.check_live_reload(renderer) {
                log::error!("Unable to live reload theme: {}", e);
            }
        }
    }
source

pub fn rebuild_all<R: Renderer>( &mut self, renderer: &mut R ) -> Result<(), Error>

Rebuilds this context, reloading all asset data. Notably, files on disk that were used in building the context are re-read. If any errors are encountered in reading or parsing files, this will return Err and no changes are made to the context.

Examples found in repository?
examples/demo.rs (line 92)
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    pub fn check_context_changes<R: Renderer>(&mut self, context: &mut Context, renderer: &mut R) {
        if let Some(old_choice) = self.old_theme_choice.take() {
            context.remove_theme_file(old_choice.path());
            context.add_theme_file(self.theme_choice.path());
        }

        if self.reload_assets {
            if let Err(e) = context.rebuild_all(renderer) {
                log::error!("Unable to rebuild theme: {}", e);
            }
            self.reload_assets = false;
        } else if !self.live_reload_disabled {
            if let Err(e) = context.check_live_reload(renderer) {
                log::error!("Unable to live reload theme: {}", e);
            }
        }
    }
source

pub fn check_live_reload<R: Renderer>( &mut self, renderer: &mut R ) -> Result<(), Error>

Checks the internal live reload thread to see if any file notifications have occurred since the last check. If so, will fully rebuild the theme. If any errors are encountered in the process of rebuilding the theme, will return the Err and no changes are made to the current theme. Note that if you built the context with live reload disabled (see BuildOptions), this function will do nothing.

Examples found in repository?
examples/demo.rs (line 97)
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    pub fn check_context_changes<R: Renderer>(&mut self, context: &mut Context, renderer: &mut R) {
        if let Some(old_choice) = self.old_theme_choice.take() {
            context.remove_theme_file(old_choice.path());
            context.add_theme_file(self.theme_choice.path());
        }

        if self.reload_assets {
            if let Err(e) = context.rebuild_all(renderer) {
                log::error!("Unable to rebuild theme: {}", e);
            }
            self.reload_assets = false;
        } else if !self.live_reload_disabled {
            if let Err(e) = context.check_live_reload(renderer) {
                log::error!("Unable to live reload theme: {}", e);
            }
        }
    }
source

pub fn save(&self) -> SavedContext

Generates a SavedContext from the current context state. This can be serialized to a file and restored later using load to restore the Context state.

source

pub fn load(&mut self, save: SavedContext)

Restores the specified SavedContext to this Context, restoring the overall UI state. The SavedContext passed in should be generated from save.

source

pub fn create_frame(&mut self) -> Frame

Creates a Frame, the main object that should pass through your UI building functions and is responsible for constructing the widget tree. This method should be called each frame you want to draw / interact with the UI.

Examples found in repository?
examples/demo_glium.rs (line 60)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use glium::glutin::{window::WindowBuilder};
    use glium::{Display, Surface};

    // initialize our very basic logger so error messages go to stdout
    thyme::log::init(log::Level::Warn).unwrap();

    let window_size = [1280.0, 720.0];
    let events_loop = EventLoop::new();

    // create glium display
    let builder = WindowBuilder::new()
        .with_title("Thyme Demo")
        .with_inner_size(glium::glutin::dpi::LogicalSize::new(window_size[0], window_size[1]));
    let context = glium::glutin::ContextBuilder::new();
    let display = Display::new(builder, context, &events_loop)?;

    // create thyme backend
    let mut renderer = thyme::GliumRenderer::new(&display)?;
    let mut io = thyme::WinitIo::new(&events_loop, window_size.into())?;
    let mut context_builder = thyme::ContextBuilder::with_defaults();

    demo::register_assets(&mut context_builder);

    let mut context = context_builder.build(&mut renderer, &mut io)?;

    let mut party = demo::Party::default();

    let mut last_frame = std::time::Instant::now();
    let frame_time = std::time::Duration::from_millis(16);
    
    // run main loop
    events_loop.run(move |event, _, control_flow| match event {
        Event::MainEventsCleared => {
            if std::time::Instant::now() > last_frame + frame_time {
                display.gl_window().window().request_redraw();
            }
            *control_flow = ControlFlow::WaitUntil(last_frame + frame_time);
        },
        Event::RedrawRequested(_) => {
            last_frame = std::time::Instant::now();

            party.check_context_changes(&mut context, &mut renderer);

            let mut target = display.draw();
            target.clear_color(0.21404, 0.21404, 0.21404, 1.0); // manual sRGB conversion for 0.5

            bench::run("thyme", || {
                display.gl_window().window().set_cursor_visible(!party.theme_has_mouse_cursor());

                let mut ui = context.create_frame();

                bench::run("frame", || {
                    demo::build_ui(&mut ui, &mut party);
                });

                bench::run("draw", || {
                    renderer.draw_frame(&mut target, ui).unwrap();
                });
            });

            target.finish().unwrap();
        },
        Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit,
        event => {
            io.handle_event(&mut context, &event);
        }
    })
}
More examples
Hide additional examples
examples/demo_gl.rs (line 75)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // initialize our very basic logger so error messages go to stdout
    thyme::log::init(log::Level::Warn).unwrap();

    // create glium display
    let event_loop = glutin::event_loop::EventLoop::new();
    let window_builder = glutin::window::WindowBuilder::new()
        .with_title("Hello world!")
        .with_inner_size(glutin::dpi::LogicalSize::new(1280.0, 720.0));

    let windowed_context = glutin::ContextBuilder::new()
        .with_gl(glutin::GlRequest::Specific(
            glutin::Api::OpenGl,
            (OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION),
        ))
        .build_windowed(window_builder, &event_loop)?;

    let windowed_context = unsafe {
        windowed_context
            .make_current().map_err(|(_context, e)| e)?
    };

    {
        let gl_context = windowed_context.context();
        gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _)
    }

    // create thyme backend
    let mut renderer = thyme::GLRenderer::new();
    let mut context_builder = thyme::ContextBuilder::with_defaults();

    demo::register_assets(&mut context_builder);

    let window_size = [1280.0, 720.0];
    let mut io = thyme::WinitIo::new(&event_loop, window_size.into())?;
    let mut context = context_builder.build(&mut renderer, &mut io)?;
    let mut party = demo::Party::default();

    let mut last_frame = std::time::Instant::now();
    let frame_time = std::time::Duration::from_millis(16);

    // run main loop
    event_loop.run(move |event, _, control_flow| match event {
        Event::MainEventsCleared => {
            if std::time::Instant::now() > last_frame + frame_time {
                windowed_context.window().request_redraw();
            }
            *control_flow = ControlFlow::WaitUntil(last_frame + frame_time);
        }
        Event::RedrawRequested(_) => {
            last_frame = std::time::Instant::now();

            party.check_context_changes(&mut context, &mut renderer);

            renderer.clear_color(0.5, 0.5, 0.5, 1.0);

            bench::run("thyme", || {
                windowed_context.window().set_cursor_visible(!party.theme_has_mouse_cursor());

                let mut ui = context.create_frame();

                bench::run("frame", || {
                    demo::build_ui(&mut ui, &mut party);
                });

                bench::run("draw", || {
                    renderer.draw_frame(ui);
                });
            });

            windowed_context.swap_buffers().unwrap();
        }
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => *control_flow = ControlFlow::Exit,
        event => {
            io.handle_event(&mut context, &event);
        }
    })
}
examples/demo_wgpu.rs (line 72)
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use winit::{ window::WindowBuilder };

    // initialize our very basic logger so error messages go to stdout
    thyme::log::init(log::Level::Warn).unwrap();

    let window_size = [1280.0, 720.0];
    let events_loop = EventLoop::new();

    // create winit window
    let window = WindowBuilder::new()
        .with_title("Thyme WGPU Demo")
        .with_inner_size(winit::dpi::LogicalSize::new(window_size[0], window_size[1]))
        .build(&events_loop)?;

    // setup WGPU
    let instance_desc = wgpu::InstanceDescriptor {
        backends: wgpu::Backends::PRIMARY,
        dx12_shader_compiler: wgpu::Dx12Compiler::Fxc,
    };
    let instance = wgpu::Instance::new(instance_desc);
    let surface = unsafe { instance.create_surface(&window).map_err(thyme::Error::WgpuSurface)? };
    let (_adapter, device, queue) = futures::executor::block_on(setup_wgpu(&instance, &surface));
    let surface_config = get_surface_config(window_size[0] as u32, window_size[1] as u32);
    surface.configure(&device, &surface_config);

    // create thyme backend
    let mut renderer = thyme::WgpuRenderer::new(Arc::clone(&device), Arc::clone(&queue));
    let mut io = thyme::WinitIo::new(&events_loop, window_size.into())?;
    let mut context_builder = thyme::ContextBuilder::with_defaults();

    demo::register_assets(&mut context_builder);

    let mut context = context_builder.build(&mut renderer, &mut io)?;

    let mut party = demo::Party::default();

    let mut last_frame = std::time::Instant::now();
    let frame_time = std::time::Duration::from_millis(16);

    // run main loop
    events_loop.run(move |event, _, control_flow| match event {
        Event::MainEventsCleared => {
            if std::time::Instant::now() > last_frame + frame_time {
                window.request_redraw();
            }
            *control_flow = ControlFlow::WaitUntil(last_frame + frame_time);
        },
        Event::RedrawRequested(_) => {
            last_frame = std::time::Instant::now();

            party.check_context_changes(&mut context, &mut renderer);

            let frame = surface.get_current_texture().unwrap();
            let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default());
            let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });

            bench::run("thyme", || {
                window.set_cursor_visible(!party.theme_has_mouse_cursor());

                let mut ui = context.create_frame();

                bench::run("frame", || {
                    demo::build_ui(&mut ui, &mut party);
                });

                bench::run("draw", || {
                    {
                        let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
                            label: None,
                            color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                                view: &view,
                                resolve_target: None,
                                ops: wgpu::Operations {
                                    load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.5, g: 0.5, b: 0.5, a: 1.0 }),
                                    store: true,
                                },
                            })],
                            depth_stencil_attachment: None,
                        });

                        renderer.draw_frame(ui, &mut render_pass);
                    }

                    queue.submit(Some(encoder.finish()));
                    frame.present();
                });
            });
        },
        Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit,
        event => {
            // recreate swap chain on resize, but also still pass the event to thyme
            if let Event::WindowEvent { event: WindowEvent::Resized(_), ..} = event {
                let size: (u32, u32) = window.inner_size().into();

                let surface_config = get_surface_config(size.0, size.1);
                surface.configure(&device, &surface_config);
            }

            io.handle_event(&mut context, &event);
        }
    })
}

Auto Trait Implementations§

§

impl !RefUnwindSafe for Context

§

impl !Send for Context

§

impl !Sync for Context

§

impl Unpin for Context

§

impl !UnwindSafe for Context

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>