mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
Merge pull request #1695
This commit is contained in:
@@ -428,6 +428,8 @@ pub struct Prefs {
|
||||
pub recent_presets: Vec<String>,
|
||||
/// Character panel: recently used font families, newest first.
|
||||
pub recent_fonts: Vec<String>,
|
||||
/// Effects & Presets: the starred effects' ids, in the order starred.
|
||||
pub effects_favorites: Vec<String>,
|
||||
/// Preview panel: every shortcut's options.
|
||||
pub preview: crate::preview::PreviewSettings,
|
||||
/// View ▸ Simulate Output ▸ My Custom RGB.
|
||||
@@ -468,6 +470,7 @@ impl Default for Prefs {
|
||||
recent_footage: vec![],
|
||||
recent_presets: vec![],
|
||||
recent_fonts: vec![],
|
||||
effects_favorites: vec![],
|
||||
preview: crate::preview::PreviewSettings::default(),
|
||||
custom_rgb: crate::viewer::CustomRgb::default(),
|
||||
comp_presets: vec![],
|
||||
@@ -597,6 +600,9 @@ impl Prefs {
|
||||
pub fn normalize(&mut self) {
|
||||
self.version = PREFS_VERSION;
|
||||
self.comp_presets.retain(CompPreset::is_valid);
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
self.effects_favorites.retain(|id| !id.is_empty() && seen.insert(id.clone()));
|
||||
self.effects_favorites.truncate(MAX_EFFECTS_FAVORITES);
|
||||
if !is_choice(WINDOW_GRAPHICS, &self.startup.window_graphics) {
|
||||
self.startup.window_graphics = Startup::default().window_graphics;
|
||||
}
|
||||
@@ -715,6 +721,7 @@ impl Prefs {
|
||||
recent_footage: std::mem::take(&mut self.recent_footage),
|
||||
recent_presets: std::mem::take(&mut self.recent_presets),
|
||||
recent_fonts: std::mem::take(&mut self.recent_fonts),
|
||||
effects_favorites: std::mem::take(&mut self.effects_favorites),
|
||||
preview: std::mem::take(&mut self.preview),
|
||||
comp_presets: std::mem::take(&mut self.comp_presets),
|
||||
..d
|
||||
@@ -916,6 +923,23 @@ impl Prefs {
|
||||
push_mru(&mut self.recent_fonts, family, 30);
|
||||
}
|
||||
|
||||
/// Is effect `id` starred in Effects & Presets?
|
||||
pub fn is_effect_favorite(&self, id: &str) -> bool {
|
||||
self.effects_favorites.iter().any(|f| f == id)
|
||||
}
|
||||
|
||||
/// Star effect `id` in Effects & Presets, or un-star it; true when it is starred now.
|
||||
pub fn toggle_effect_favorite(&mut self, id: &str) -> bool {
|
||||
if self.is_effect_favorite(id) {
|
||||
self.effects_favorites.retain(|f| f != id);
|
||||
false
|
||||
} else {
|
||||
self.effects_favorites.push(id.to_string());
|
||||
self.effects_favorites.truncate(MAX_EFFECTS_FAVORITES);
|
||||
self.is_effect_favorite(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// The recent fonts the Character panel shows (at most Number of Recent Fonts to Display).
|
||||
pub fn recent_fonts_shown(&self) -> &[String] {
|
||||
let n = (self.type_.recent_fonts as usize).min(self.recent_fonts.len());
|
||||
@@ -933,6 +957,9 @@ impl Prefs {
|
||||
}
|
||||
}
|
||||
|
||||
/// Most effects Effects & Presets keeps starred (a hand-edited settings file can hold more).
|
||||
const MAX_EFFECTS_FAVORITES: usize = 1000;
|
||||
|
||||
fn push_mru(list: &mut Vec<String>, v: &str, max: usize) {
|
||||
list.retain(|x| x != v);
|
||||
list.insert(0, v.to_string());
|
||||
|
||||
@@ -212,6 +212,34 @@ fn prefs_commands_get_set_reset_and_persist() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Effects & Presets' starred effects live in the settings (#1692): they come back in the next
|
||||
/// session, un-starring sticks too, Reset All keeps them, and a hand-edited list loses its
|
||||
/// repeats and empty ids on load.
|
||||
#[test]
|
||||
fn effects_favorites_persist_across_sessions() {
|
||||
let store = Arc::new(MemoryConfig::default());
|
||||
let mut s = Session { config: Some(store.clone()), ..Default::default() };
|
||||
assert!(s.prefs.toggle_effect_favorite("ADBE Gaussian Blur 2"));
|
||||
assert!(s.prefs.toggle_effect_favorite("ADBE Glo2"));
|
||||
s.save_prefs();
|
||||
let reopen = |store: &Arc<MemoryConfig>| {
|
||||
let mut s = Session { config: Some(store.clone()), ..Default::default() };
|
||||
s.load_settings();
|
||||
s
|
||||
};
|
||||
let mut s2 = reopen(&store);
|
||||
assert_eq!(s2.prefs.effects_favorites, ["ADBE Gaussian Blur 2", "ADBE Glo2"]);
|
||||
assert!(!s2.prefs.toggle_effect_favorite("ADBE Glo2"), "un-starred");
|
||||
s2.save_prefs();
|
||||
let mut s3 = reopen(&store);
|
||||
assert_eq!(s3.prefs.effects_favorites, ["ADBE Gaussian Blur 2"]);
|
||||
s3.execute("prefs.reset", json!({})).unwrap();
|
||||
assert!(s3.prefs.is_effect_favorite("ADBE Gaussian Blur 2"), "Reset All keeps the stars");
|
||||
let edited = store.read(PREFS_FILE).unwrap().replace("\"effectsFavorites\": [", "\"effectsFavorites\": [\"\", \"ADBE Glo2\", \"ADBE Glo2\", ");
|
||||
store.write(PREFS_FILE, &edited).unwrap();
|
||||
assert_eq!(reopen(&store).prefs.effects_favorites, ["ADBE Glo2", "ADBE Gaussian Blur 2"]);
|
||||
}
|
||||
|
||||
/// Composition Settings presets the user saves live in the settings: they persist, a save with
|
||||
/// an existing name replaces it, they survive Reset All, and invalid ones (from a hand-edited
|
||||
/// settings file) are dropped on load.
|
||||
|
||||
@@ -195,7 +195,7 @@ fn effect_row(
|
||||
}
|
||||
app.auto.add(&format!("{auto_prefix}.{}", e.id), r, e.name);
|
||||
// Favourite star (always shown when starred, else on hover).
|
||||
let fav = app.ui.effects_favorites.contains(e.id);
|
||||
let fav = app.session.prefs.is_effect_favorite(e.id);
|
||||
let sresp = ui.interact(star.intersect(list), egui::Id::new((auto_prefix, e.id, "star")), Sense::click());
|
||||
if fav || resp.hovered() || sresp.hovered() {
|
||||
let gold = Color32::from_rgb(0xe8, 0xc0, 0x40);
|
||||
@@ -203,11 +203,9 @@ fn effect_row(
|
||||
}
|
||||
app.auto.add(&format!("{auto_prefix}.{}.star", e.id), star, if fav { "Remove from Favorites" } else { "Add to Favorites" });
|
||||
if sresp.clicked() {
|
||||
if fav {
|
||||
app.ui.effects_favorites.remove(e.id);
|
||||
} else {
|
||||
app.ui.effects_favorites.insert(e.id.to_string());
|
||||
}
|
||||
// Kept in the settings, so the stars are there next time (#1692).
|
||||
app.session.prefs.toggle_effect_favorite(e.id);
|
||||
app.session.save_prefs();
|
||||
return;
|
||||
}
|
||||
if resp.double_clicked() {
|
||||
@@ -364,7 +362,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
let lookup = |id: &str| reg.iter().find(|e| e.id == id);
|
||||
|
||||
// Favorites and Recently Used.
|
||||
let favs: Vec<_> = app.ui.effects_favorites.iter().filter_map(|id| lookup(id)).filter(|e| keep(e)).collect();
|
||||
let favs: Vec<_> = app.session.prefs.effects_favorites.iter().filter_map(|id| lookup(id)).filter(|e| keep(e)).collect();
|
||||
if !favs.is_empty() && folder_row(app, ui, &lp, list, &mut y, "favorites", "Favorites", 0.0, searching, Some(Icon::Star)) {
|
||||
let mut favs = favs;
|
||||
favs.sort_by_key(|e| e.name);
|
||||
|
||||
@@ -643,9 +643,6 @@ pub struct UiState {
|
||||
/// Levels (Individual Controls) editor: shown channel per effect uid.
|
||||
#[serde(default)]
|
||||
pub fx_levels_channel: BTreeMap<u64, usize>,
|
||||
/// Effects & Presets: favourite effect ids (starred).
|
||||
#[serde(default)]
|
||||
pub effects_favorites: BTreeSet<String>,
|
||||
/// Effects & Presets: recently applied effect ids, most recent first.
|
||||
#[serde(default)]
|
||||
pub effects_recent: Vec<String>,
|
||||
@@ -734,7 +731,6 @@ impl Default for UiState {
|
||||
fx_curve_channel: BTreeMap::new(),
|
||||
fx_curve_pencil: BTreeSet::new(),
|
||||
fx_levels_channel: BTreeMap::new(),
|
||||
effects_favorites: BTreeSet::new(),
|
||||
effects_recent: Vec::new(),
|
||||
effects_view: EffectsView::default(),
|
||||
snapping: true,
|
||||
|
||||
Reference in New Issue
Block a user