Skip to content

Commit

Permalink
Merge pull request #17 from subalterngames/panel_background_optimization
Browse files Browse the repository at this point in the history
Panel background optimization
  • Loading branch information
subalterngames authored Nov 27, 2023
2 parents 288dbc0 + 9eca2c4 commit 941b685
Show file tree
Hide file tree
Showing 18 changed files with 249 additions and 100 deletions.
2 changes: 1 addition & 1 deletion audio/src/export/export_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use common::open_file::Extension;
use serde::{Deserialize, Serialize};

/// This determines what we're exporting to.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize, Default)]
#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize, Default, Hash)]
pub enum ExportType {
#[default]
Wav,
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ These are the optimizations:

- In `audio`, `Synthesizer` (which no longer exists) ran a very fast infinite loop to send samples to `Player`, and the loop needlessly consumed CPU resources. I replaced this loop with a bunch of `Arc<Mutex<T>>` values that are shared between `Conn` and `Player`. As a result of removing `Synthesizer` I had to reorganize all of the exporter code. There are a lot of small changes that I'm not going to list here because let's be real, no one reads verbose changelogs, but the most noticeable change is that `Exporter` is a field in `Conn` and is no longer shared (there is no `Arc<Mutex<Exporter>>` anywhere in the code). This change affects a *lot* of the codebase, but it's mostly just refactoring with zero functional differences.
- In `input`, `Input` checked for key downs and presses very inefficently. I only had to change two lines of code to make it much faster. This optimizes CPU usage by roughly 10%.
- A tiny optimization to drawing panel backgrounds. This required refactoring throughout `render`. I think that there are more tiny optimizations that could be made in `render` that cumulatively might make more of a difference.

This update doesn't have any new features or bug fixes. In the future, I'm going to reserve major releases (0.x.0) for big new features, but I had to rewrite so much of Cacophony's code, and the results are such a big improvement, that I'm making this a major release anyway.

Expand Down
22 changes: 12 additions & 10 deletions render/src/export_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@ pub(crate) struct ExportPanel {
}

impl ExportPanel {
pub fn new(config: &Ini, text: &Text) -> Self {
pub fn new(config: &Ini, renderer: &Renderer, text: &Text) -> Self {
let window_grid_size = get_window_grid_size(config);
let h: u32 = 3;
let y = window_grid_size[1] / 2 - 1;
let w = window_grid_size[0] / 4;
let x = window_grid_size[0] / 2 - w / 2;
let panel = Panel::new(PanelType::ExportState, [x, y], [w, h], text);
let position = [x, y];
let size = [w, h];
let panel = Panel::new(PanelType::ExportState, position, size, renderer, text);
let popup = Popup::new(PanelType::ExportState);
let decaying = text.get("EXPORT_PANEL_APPENDING_DECAY");
let decaying_label = Label::new(
[
panel.rect.position[0] + panel.rect.size[0] / 2
- decaying.chars().count() as u32 / 2,
panel.rect.position[1] + 1,
position[0] + size[0] / 2 - decaying.chars().count() as u32 / 2,
position[1] + 1,
],
decaying,
);
let writing = text.get("EXPORT_PANEL_WRITING");
let writing_label = Label::new(
[
panel.rect.position[0] + panel.rect.size[0] / 2
- writing.chars().count() as u32 / 2,
panel.rect.position[1] + 1,
position[0] + size[0] / 2 - writing.chars().count() as u32 / 2,
position[1] + 1,
],
writing,
);
Expand All @@ -63,8 +63,10 @@ impl Drawable for ExportPanel {
let samples = format!("{}/{}", exported_samples, total_samples);
// Draw the string.
let w = samples.chars().count() as u32;
let x = self.panel.rect.position[0] + self.panel.rect.size[0] / 2 - w / 2;
let y = self.panel.rect.position[1] + 1;
let x = self.panel.background.grid_rect.position[0]
+ self.panel.background.grid_rect.size[0] / 2
- w / 2;
let y = self.panel.background.grid_rect.position[1] + 1;
let label = Label {
position: [x, y],
text: samples,
Expand Down
74 changes: 57 additions & 17 deletions render/src/export_settings_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ use crate::Focus;
use audio::export::{ExportSetting, ExportType, MultiFileSuffix};
use audio::exporter::{Exporter, MP3_BIT_RATES};
use common::IndexedValues;
use hashbrown::HashMap;
use serde::de::DeserializeOwned;
use serde::Serialize;
use text::ValueMap;
use util::KV_PADDING;

/// Export settings panel.
pub(crate) struct ExportSettingsPanel {
/// The position of the panel.
/// The panel position.
position: [u32; 2],
/// The width of the panel.
/// The panel width.
width: u32,
/// The title label for the panel.
title: Label,
Expand All @@ -26,10 +27,12 @@ pub(crate) struct ExportSettingsPanel {
quality: KeyListCorners,
/// String values of multi-file suffixes.
multi_file_suffixes: ValueMap<MultiFileSuffix>,
/// Panel background sizes per export type.
backgrounds: HashMap<ExportType, PanelBackground>,
}

impl ExportSettingsPanel {
pub fn new(config: &Ini, text: &Text) -> Self {
pub fn new(config: &Ini, renderer: &Renderer, exporter: &Exporter, text: &Text) -> Self {
let (open_file_position, open_file_size) = get_open_file_rect(config);
let position = [
open_file_position[0],
Expand Down Expand Up @@ -72,6 +75,49 @@ impl ExportSettingsPanel {
text,
);

// Calculate the background sizes per export type.
let mut backgrounds = HashMap::new();
backgrounds.insert(
ExportType::Wav,
PanelBackground::new(
position,
[width, exporter.wav_settings.index.get_length() as u32 + 3],
renderer,
),
);
backgrounds.insert(
ExportType::Mid,
PanelBackground::new(
position,
[width, exporter.mid_settings.index.get_length() as u32 + 2],
renderer,
),
);
backgrounds.insert(
ExportType::MP3,
PanelBackground::new(
position,
[width, exporter.mp3_settings.index.get_length() as u32 + 4],
renderer,
),
);
backgrounds.insert(
ExportType::Ogg,
PanelBackground::new(
position,
[width, exporter.ogg_settings.index.get_length() as u32 + 4],
renderer,
),
);
backgrounds.insert(
ExportType::Flac,
PanelBackground::new(
position,
[width, exporter.flac_settings.index.get_length() as u32 + 4],
renderer,
),
);

Self {
position,
width,
Expand All @@ -81,6 +127,7 @@ impl ExportSettingsPanel {
mp3_bit_rate,
quality,
multi_file_suffixes,
backgrounds,
}
}

Expand Down Expand Up @@ -315,26 +362,19 @@ impl Drawable for ExportSettingsPanel {
fn update(&self, renderer: &Renderer, state: &State, conn: &Conn, text: &Text, _: &PathsState) {
// Get the focus.
let focus = state.panels[state.focus.get()] == PanelType::ExportSettings;
// Get the height of the panel.
let e = conn.exporter.export_type.get();
let h = match &e {
ExportType::Wav => conn.exporter.wav_settings.index.get_length() + 2,
ExportType::Mid => conn.exporter.mid_settings.index.get_length() + 1,
ExportType::MP3 => conn.exporter.mp3_settings.index.get_length() + 3,
ExportType::Ogg => conn.exporter.ogg_settings.index.get_length() + 3,
ExportType::Flac => conn.exporter.flac_settings.index.get_length() + 3,
} as u32
+ 1;

// Draw the panel.
let color: ColorKey = if focus {
ColorKey::FocusDefault
} else {
ColorKey::NoFocus
};
let rect = Rectangle::new(self.position, [self.width, h]);
renderer.rectangle(&rect, &ColorKey::Background);
renderer.border(&rect, &color);
let background = &self.backgrounds[&conn.exporter.export_type.get()];
renderer.rectangle_pixel(
background.background.position,
background.background.size,
&color,
);
renderer.rectangle_lines(&background.border, &color);
renderer.rectangle(&self.title_rect, &ColorKey::Background);
renderer.text(&self.title, &color);

Expand Down
4 changes: 4 additions & 0 deletions render/src/field_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ mod key_width;
mod label;
mod label_ref;
mod list;
mod panel_background;
mod rectangle;
mod rectangle_pixel;
pub(super) mod util;
mod width;
pub(crate) use boolean::Boolean;
Expand All @@ -20,6 +22,8 @@ pub(crate) use label::Label;
pub(crate) use label_rectangle::LabelRectangle;
pub(crate) use label_ref::LabelRef;
pub(crate) use list::List;
pub(crate) use panel_background::PanelBackground;
pub(crate) use rectangle::Rectangle;
pub(crate) use rectangle_pixel::RectanglePixel;
pub(super) use width::Width;
mod label_rectangle;
40 changes: 40 additions & 0 deletions render/src/field_params/panel_background.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use super::{Rectangle, RectanglePixel};
use crate::Renderer;

/// A background rectangle and a border rectangle, both in pixel units.
#[derive(Clone)]
pub(crate) struct PanelBackground {
/// The background.
pub background: RectanglePixel,
/// The border.
pub border: RectanglePixel,
/// The rectangle in grid units.
pub grid_rect: Rectangle,
}

impl PanelBackground {
pub fn new(position: [u32; 2], size: [u32; 2], renderer: &Renderer) -> Self {
let background = RectanglePixel::new(
renderer.grid_to_pixel(position),
renderer.grid_to_pixel(size),
);
let border = renderer.get_border_rect(position, size);
let grid_rect = Rectangle::new(position, size);
Self {
background,
border,
grid_rect,
}
}

/// Adjust the size by a delta in grid units.
pub fn resize_by(&mut self, delta: [u32; 2], renderer: &Renderer) {
self.grid_rect.size[0] += delta[0];
self.grid_rect.size[1] += delta[1];
let delta = renderer.grid_to_pixel(delta);
self.background.size[0] += delta[0];
self.background.size[1] += delta[1];
self.border.size[0] += delta[0];
self.border.size[1] += delta[1];
}
}
14 changes: 14 additions & 0 deletions render/src/field_params/rectangle_pixel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// A rectangle has a position and a size.
#[derive(Clone)]
pub(crate) struct RectanglePixel {
/// The position in pixel units.
pub position: [f32; 2],
/// The size in pixel units.
pub size: [f32; 2],
}

impl RectanglePixel {
pub fn new(position: [f32; 2], size: [f32; 2]) -> Self {
Self { position, size }
}
}
4 changes: 2 additions & 2 deletions render/src/links_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub(crate) struct LinksPanel {
}

impl LinksPanel {
pub fn new(config: &Ini, text: &Text, input: &Input) -> Self {
pub fn new(config: &Ini, renderer: &Renderer, text: &Text, input: &Input) -> Self {
// Get each label. The x coordinate is right now at 0.
let mut y = MAIN_MENU_HEIGHT + 1;
let mut tooltips = Tooltips::default();
Expand Down Expand Up @@ -70,7 +70,7 @@ impl LinksPanel {
discord.position[0] = label_x;
github.position[0] = label_x;
// Define the panel.
let panel = Panel::new(PanelType::Links, [x, y], [w, h], text);
let panel = Panel::new(PanelType::Links, [x, y], [w, h], renderer, text);
let labels = [website, discord, github];
let popup = Popup::new(PanelType::Links);
Self {
Expand Down
7 changes: 4 additions & 3 deletions render/src/main_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ pub(crate) struct MainMenu {
impl MainMenu {
pub fn new(
config: &Ini,
renderer: &Renderer,
input: &Input,
text: &mut Text,
renderer: &Renderer,
remote_version: Option<String>,
) -> Self {
// Get the width of the panel.
Expand All @@ -80,6 +80,7 @@ impl MainMenu {
PanelType::MainMenu,
position,
[width, MAIN_MENU_HEIGHT],
renderer,
text,
);
// Add an update notice to the title.
Expand All @@ -95,8 +96,8 @@ impl MainMenu {
);

// Get the fields.
let mut x = panel.rect.position[0] + 2;
let y = panel.rect.position[1] + 1;
let mut x = position[0] + 2;
let y = position[1] + 1;
let help = Self::label_from_key("MAIN_MENU_HELP", &mut x, y, text);
x += 4;
let mut tooltips = Tooltips::default();
Expand Down
7 changes: 4 additions & 3 deletions render/src/music_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,21 @@ pub(crate) struct MusicPanel {
}

impl MusicPanel {
pub fn new(config: &Ini, text: &Text) -> Self {
pub fn new(config: &Ini, renderer: &Renderer, text: &Text) -> Self {
// Get the width of the panel.
let mut width = get_tracks_panel_width(config);
// Get the panel.
let panel = Panel::new(
PanelType::Music,
MUSIC_PANEL_POSITION,
[width, MUSIC_PANEL_HEIGHT],
renderer,
text,
);

// Move the (x, y) coordinates inward by 1.
let x = panel.rect.position[0] + 1;
let mut y = panel.rect.position[1] + 1;
let x = MUSIC_PANEL_POSITION[0] + 1;
let mut y = MUSIC_PANEL_POSITION[1] + 1;
// Shorten the width for the fields.
width -= 2;
let w_usize = width as usize;
Expand Down
Loading

0 comments on commit 941b685

Please sign in to comment.