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

Implement Columns that show Variables #566

Merged
merged 1 commit into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 89 additions & 10 deletions src/component/splits/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ use serde::{Deserialize, Serialize};
pub struct ColumnSettings {
/// The name of the column.
pub name: String,
/// The kind of the column.
#[serde(flatten)]
pub kind: ColumnKind,
}

/// The kind of a column. It can either be a column that shows a variable or a
/// time.
#[derive(Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ColumnKind {
/// A column that shows a variable.
Variable(VariableColumn),
/// A column that shows a time.
Time(TimeColumn),
}

/// A column that shows a time.
#[derive(Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct TimeColumn {
/// Specifies the value a segment starts out with before it gets replaced
/// with the current attempt's information when splitting.
pub start_with: ColumnStartWith,
Expand All @@ -39,6 +59,13 @@ pub struct ColumnSettings {
pub timing_method: Option<TimingMethod>,
}

/// A column that shows a variable.
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct VariableColumn {
/// The name of the variable to visualize.
pub variable_name: String,
}

/// Specifies the value a segment starts out with before it gets replaced
/// with the current attempt's information when splitting.
#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -107,6 +134,14 @@ impl Default for ColumnSettings {
fn default() -> Self {
ColumnSettings {
name: String::from("Column"),
kind: ColumnKind::Time(TimeColumn::default()),
}
}
}

impl Default for TimeColumn {
fn default() -> Self {
TimeColumn {
start_with: ColumnStartWith::Empty,
update_with: ColumnUpdateWith::DontUpdate,
update_trigger: ColumnUpdateTrigger::Contextual,
Expand Down Expand Up @@ -152,12 +187,62 @@ pub fn update_state(
segment_index: usize,
current_split: Option<usize>,
method: TimingMethod,
) {
match &column_settings.kind {
ColumnKind::Variable(column) => {
state.value.clear();
if let Some(value) = segment.variables().get(column.variable_name.as_str()) {
state.value.push_str(value);
} else if Some(segment_index) == current_split {
if let Some(value) = timer
.run()
.metadata()
.custom_variable_value(column.variable_name.as_str())
{
// FIXME: We show the live value of the variable, which means it
// might update frequently. So we possibly should mark it as
// such. However it's currently impossible to tell if it
// actually does update frequently. On top of that, the text
// component would need to support this as well, as it also
// shows the live value of the variable.
state.value.push_str(value);
}
}
state.semantic_color = SemanticColor::Default;
state.visual_color = layout_settings.text_color;
state.updates_frequently = false;
}
ColumnKind::Time(column) => {
update_time_column(
state,
column,
timer,
splits_settings,
layout_settings,
segment,
segment_index,
current_split,
method,
);
}
}
}

fn update_time_column(
state: &mut ColumnState,
column_settings: &TimeColumn,
timer: &Snapshot<'_>,
splits_settings: &SplitsSettings,
layout_settings: &GeneralLayoutSettings,
segment: &Segment,
segment_index: usize,
current_split: Option<usize>,
method: TimingMethod,
) {
let method = column_settings.timing_method.unwrap_or(method);
let resolved_comparison = comparison::resolve(&column_settings.comparison_override, timer);
let comparison = comparison::or_current(resolved_comparison, timer);

let update_value = column_update_value(
let update_value = time_column_update_value(
column_settings,
timer,
segment,
Expand All @@ -166,9 +251,7 @@ pub fn update_state(
method,
comparison,
);

let updated = update_value.is_some();

let ((column_value, semantic_color, formatter), is_live) = update_value.unwrap_or_else(|| {
(
match column_settings.start_with {
Expand Down Expand Up @@ -197,11 +280,8 @@ pub fn update_state(
false,
)
});

let is_empty = column_settings.start_with == ColumnStartWith::Empty && !updated;

state.updates_frequently = is_live && column_value.is_some();

state.value.clear();
if !is_empty {
let _ = match formatter {
Expand Down Expand Up @@ -229,13 +309,12 @@ pub fn update_state(
}
};
}

state.semantic_color = semantic_color;
state.visual_color = semantic_color.visualize(layout_settings);
}

fn column_update_value(
column: &ColumnSettings,
fn time_column_update_value(
column: &TimeColumn,
timer: &Snapshot<'_>,
segment: &Segment,
segment_index: usize,
Expand Down
156 changes: 108 additions & 48 deletions src/component/splits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
use crate::{
platform::prelude::*,
settings::{
CachedImageId, Color, Field, Gradient, ImageData, ListGradient, SettingsDescription, Value,
self, CachedImageId, Color, Field, Gradient, ImageData, ListGradient, SettingsDescription,
Value,
},
timing::{formatter::Accuracy, Snapshot},
util::{Clear, ClearVec},
Expand All @@ -23,11 +24,13 @@ mod tests;
mod column;

pub use column::{
ColumnSettings, ColumnStartWith, ColumnState, ColumnUpdateTrigger, ColumnUpdateWith,
ColumnKind, ColumnSettings, ColumnStartWith, ColumnState, ColumnUpdateTrigger,
ColumnUpdateWith, TimeColumn, VariableColumn,
};

const SETTINGS_BEFORE_COLUMNS: usize = 15;
const SETTINGS_PER_COLUMN: usize = 6;
const SETTINGS_PER_TIME_COLUMN: usize = 6;
const SETTINGS_PER_VARIABLE_COLUMN: usize = 2;

/// The Splits Component is the main component for visualizing all the split
/// times. Each segment is shown in a tabular fashion showing the segment icon,
Expand Down Expand Up @@ -202,19 +205,23 @@ impl Default for Settings {
columns: vec![
ColumnSettings {
name: String::from("Time"),
start_with: ColumnStartWith::ComparisonTime,
update_with: ColumnUpdateWith::SplitTime,
update_trigger: ColumnUpdateTrigger::OnEndingSegment,
comparison_override: None,
timing_method: None,
kind: ColumnKind::Time(TimeColumn {
start_with: ColumnStartWith::ComparisonTime,
update_with: ColumnUpdateWith::SplitTime,
update_trigger: ColumnUpdateTrigger::OnEndingSegment,
comparison_override: None,
timing_method: None,
}),
},
ColumnSettings {
name: String::from("+/−"),
start_with: ColumnStartWith::Empty,
update_with: ColumnUpdateWith::Delta,
update_trigger: ColumnUpdateTrigger::Contextual,
comparison_override: None,
timing_method: None,
kind: ColumnKind::Time(TimeColumn {
start_with: ColumnStartWith::Empty,
update_with: ColumnUpdateWith::Delta,
update_trigger: ColumnUpdateTrigger::Contextual,
comparison_override: None,
timing_method: None,
}),
},
],
}
Expand Down Expand Up @@ -506,32 +513,58 @@ impl Component {
),
]);

settings
.fields
.reserve_exact(SETTINGS_PER_COLUMN * self.settings.columns.len());
settings.fields.reserve_exact(
self.settings
.columns
.iter()
.map(|column| match column.kind {
ColumnKind::Variable(_) => SETTINGS_PER_VARIABLE_COLUMN,
ColumnKind::Time(_) => SETTINGS_PER_TIME_COLUMN,
})
.sum(),
);

for column in &self.settings.columns {
settings
.fields
.push(Field::new("Column Name".into(), column.name.clone().into()));
settings
.fields
.push(Field::new("Start With".into(), column.start_with.into()));
settings
.fields
.push(Field::new("Update With".into(), column.update_with.into()));
settings.fields.push(Field::new(
"Update Trigger".into(),
column.update_trigger.into(),
));
settings.fields.push(Field::new(
"Comparison".into(),
column.comparison_override.clone().into(),
));
settings.fields.push(Field::new(
"Timing Method".into(),
column.timing_method.into(),
));

match &column.kind {
ColumnKind::Variable(column) => {
settings.fields.push(Field::new(
"Column Type".into(),
settings::ColumnKind::Variable.into(),
));
settings.fields.push(Field::new(
"Variable Name".into(),
column.variable_name.clone().into(),
));
}
ColumnKind::Time(column) => {
settings.fields.push(Field::new(
"Column Type".into(),
settings::ColumnKind::Time.into(),
));
settings
.fields
.push(Field::new("Start With".into(), column.start_with.into()));
settings
.fields
.push(Field::new("Update With".into(), column.update_with.into()));
settings.fields.push(Field::new(
"Update Trigger".into(),
column.update_trigger.into(),
));
settings.fields.push(Field::new(
"Comparison".into(),
column.comparison_override.clone().into(),
));
settings.fields.push(Field::new(
"Timing Method".into(),
column.timing_method.into(),
));
}
}
}

settings
Expand Down Expand Up @@ -565,22 +598,49 @@ impl Component {
self.settings.columns.resize(new_len, Default::default());
}
index => {
let index = index - SETTINGS_BEFORE_COLUMNS;
let column_index = index / SETTINGS_PER_COLUMN;
let setting_index = index % SETTINGS_PER_COLUMN;
if let Some(column) = self.settings.columns.get_mut(column_index) {
match setting_index {
0 => column.name = value.into(),
1 => column.start_with = value.into(),
2 => column.update_with = value.into(),
3 => column.update_trigger = value.into(),
4 => column.comparison_override = value.into(),
5 => column.timing_method = value.into(),
_ => unreachable!(),
let mut index = index - SETTINGS_BEFORE_COLUMNS;
for column in &mut self.settings.columns {
if index < 2 {
match index {
0 => column.name = value.into(),
_ => {
column.kind = match settings::ColumnKind::from(value) {
settings::ColumnKind::Time => {
ColumnKind::Time(Default::default())
}
settings::ColumnKind::Variable => {
ColumnKind::Variable(Default::default())
}
}
}
}
return;
}
index -= 2;
match &mut column.kind {
ColumnKind::Variable(column) => {
if index < 1 {
column.variable_name = value.into();
return;
}
index -= 1;
}
ColumnKind::Time(column) => {
if index < 5 {
match index {
0 => column.start_with = value.into(),
1 => column.update_with = value.into(),
2 => column.update_trigger = value.into(),
3 => column.comparison_override = value.into(),
_ => column.timing_method = value.into(),
}
return;
}
index -= 5;
}
}
} else {
panic!("Unsupported Setting Index")
}
panic!("Unsupported Setting Index")
}
}
}
Expand Down
Loading