Skip to content

Commit

Permalink
added suspension mechanism for project manager
Browse files Browse the repository at this point in the history
- forces the manager to "sleep" when nothing happens in it to prevent redundant CPU/GPU load
- makes it possible to keep the manager open together with the editor/game and still have full CPU/GPU power available for editor/game
  • Loading branch information
mrDIMAS committed Dec 25, 2024
1 parent df729e5 commit 8f002d3
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 19 deletions.
70 changes: 51 additions & 19 deletions project-manager/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,34 +129,54 @@ fn main() {
.expect("Unable to destroy graphics context!");
}
Event::AboutToWait => {
let elapsed = previous.elapsed();
previous = Instant::now();
lag += elapsed.as_secs_f32();

let ui = engine.user_interfaces.first_mut();
while let Some(message) = ui.poll_message() {
project_manager.handle_ui_message(&message, ui);
}

while lag >= fixed_time_step {
engine.update(fixed_time_step, window_target, &mut lag, Default::default());
if project_manager.is_active(ui) {
let elapsed = previous.elapsed();
previous = Instant::now();
lag += elapsed.as_secs_f32();

let mut processed = 0;
while let Some(message) = ui.poll_message() {
project_manager.handle_ui_message(&message, ui);
processed += 1;
}
if processed > 0 {
project_manager
.update_loop_state
.request_update_in_next_frame();
}

project_manager.update(engine.user_interfaces.first_mut());
while lag >= fixed_time_step {
engine.update(
fixed_time_step,
window_target,
&mut lag,
Default::default(),
);

lag -= fixed_time_step;
}
project_manager.update(engine.user_interfaces.first_mut());

if let GraphicsContext::Initialized(ref ctx) = engine.graphics_context {
let window = &ctx.window;
window.set_cursor_icon(translate_cursor_icon(
engine.user_interfaces.first_mut().cursor(),
));
lag -= fixed_time_step;
}

ctx.window.request_redraw();
if let GraphicsContext::Initialized(ref ctx) = engine.graphics_context {
let window = &ctx.window;
window.set_cursor_icon(translate_cursor_icon(
engine.user_interfaces.first_mut().cursor(),
));

ctx.window.request_redraw();
}

project_manager.update_loop_state.decrease_counter();
}
}
Event::WindowEvent { event, .. } => {
match event {
WindowEvent::Focused(focus) => {
project_manager.focused = focus;
}
WindowEvent::CloseRequested => window_target.exit(),
WindowEvent::Resized(size) => {
if let Err(e) = engine.set_frame_size(size.into()) {
Expand Down Expand Up @@ -186,11 +206,23 @@ fn main() {
set_ui_scaling(ui, scale_factor as f32);
}
WindowEvent::RedrawRequested => {
engine.render().unwrap();
let ui = engine.user_interfaces.first();
if project_manager.is_active(ui) {
engine.render().unwrap();
}
}
_ => (),
}

// Any action in the window, other than a redraw request forces the project manager to
// do another update pass which then pushes a redraw request to the event
// queue. This check prevents infinite loop of this kind.
if !matches!(event, WindowEvent::RedrawRequested) {
project_manager
.update_loop_state
.request_update_in_current_frame();
}

if let Some(os_event) = translate_event(&event) {
for ui in engine.user_interfaces.iter_mut() {
ui.process_os_event(&os_event);
Expand Down
51 changes: 51 additions & 0 deletions project-manager/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,41 @@ enum Mode {
},
}

pub struct UpdateLoopState(u32);

impl Default for UpdateLoopState {
fn default() -> Self {
// Run at least a second from the start to ensure that all OS-specific stuff was done.
Self(60)
}
}

impl UpdateLoopState {
pub fn request_update_in_next_frame(&mut self) {
if !self.is_warming_up() {
self.0 = 2;
}
}

pub fn request_update_in_current_frame(&mut self) {
if !self.is_warming_up() {
self.0 = 1;
}
}

pub fn is_warming_up(&self) -> bool {
self.0 > 2
}

pub fn decrease_counter(&mut self) {
self.0 = self.0.saturating_sub(1);
}

pub fn is_suspended(&self) -> bool {
self.0 == 0
}
}

pub struct ProjectManager {
pub root_grid: Handle<UiNode>,
create: Handle<UiNode>,
Expand Down Expand Up @@ -102,6 +137,8 @@ pub struct ProjectManager {
upgrade_tool: Option<UpgradeTool>,
settings_window: Option<SettingsWindow>,
no_projects_warning: Handle<UiNode>,
pub focused: bool,
pub update_loop_state: UpdateLoopState,
}

fn make_project_item(
Expand Down Expand Up @@ -613,9 +650,15 @@ impl ProjectManager {
upgrade_tool: None,
settings_window: None,
no_projects_warning,
focused: true,
update_loop_state: Default::default(),
}
}

pub fn is_active(&self, ui: &UserInterface) -> bool {
!self.update_loop_state.is_suspended() && self.focused || ui.captured_node().is_some()
}

fn refresh(&mut self, ui: &mut UserInterface) {
let items = make_project_items(&self.settings, &self.search_text, &mut ui.build_ctx());
ui.send_message(WidgetMessage::visibility(
Expand Down Expand Up @@ -692,6 +735,14 @@ impl ProjectManager {

pub fn update(&mut self, ui: &mut UserInterface) {
self.handle_modes(ui);

if let Some(active_tooltip) = ui.active_tooltip() {
if !active_tooltip.shown {
// Keep the manager running until the current tooltip is not shown.
self.update_loop_state.request_update_in_next_frame();
}
}

if self.log.update(65536, ui) {
ui.send_message(TextMessage::text(
self.message_count,
Expand Down

0 comments on commit 8f002d3

Please sign in to comment.