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

feat(layouts): override layout anchor points with user settings #108

Merged
merged 5 commits into from
Jan 12, 2024
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
Binary file modified installer/core/Interface/Translations/SoulsyHUD_czech.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_english.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_french.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_german.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_italian.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_japanese.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_polish.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_russian.txt
Binary file not shown.
Binary file modified installer/core/Interface/Translations/SoulsyHUD_spanish.txt
Binary file not shown.
1,256 changes: 639 additions & 617 deletions installer/core/mcm/config/SoulsyHUD/config.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions installer/core/mcm/config/SoulsyHUD/settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ bGroupPotions = 0
bCycleAmmo = 1
bColorizeIcons = 1
bEquipSetsUnequip = 1
uAnchorLocation = none
sSKSEIdentifier = SOLS
bDebugMode = 0
sLogLevel = info
Expand Down
3 changes: 3 additions & 0 deletions src/controller/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ impl Controller {
}
}

// Apply any new anchor relocations to the current layout.
Layout::refresh();

self.cache.introspect();
}

Expand Down
43 changes: 42 additions & 1 deletion src/controller/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use once_cell::sync::Lazy;
use strum::Display;

use super::keys::Hotkey;
use crate::plugin::HudElement;
use crate::{layouts::shared::NamedAnchor, plugin::HudElement};

/// This is the path to players's modified settings.
static SETTINGS_PATH: &str = "./data/MCM/Settings/SoulsyHUD.ini";
Expand Down Expand Up @@ -100,6 +100,8 @@ pub struct UserSettings {
showhide: u32,
/// A hotkey for re-reading the layout from toml and redrawing. uRefreshKey
refresh_layout: u32,
/// Layout anchor override. uAnchorLocation
anchor_loc: NamedAnchor,

/// The number of milliseconds to delay before equipping a selection. Max 2500, min 0.
equip_delay_ms: u32,
Expand Down Expand Up @@ -141,6 +143,7 @@ impl Default for UserSettings {
right: 7,
equipset: 9,
refresh_layout: 8,
anchor_loc: NamedAnchor::None,
how_to_activate: ActivationMethod::Hotkey,
activate: 4,
activate_modifier: -1,
Expand Down Expand Up @@ -184,6 +187,13 @@ impl UserSettings {
settings.read_from_file(SETTINGS_PATH)
}

pub fn refresh_with(fpath: &str) -> Result<()> {
let mut settings = SETTINGS
.lock()
.expect("Unrecoverable runtime problem: cannot acquire settings lock.");
settings.read_from_file(fpath)
}

/// Refresh ourselves from the MCM-controlled file.
pub fn read_from_file(&mut self, fpath: &str) -> Result<()> {
// We'll fall back to defaults at a different level.
Expand Down Expand Up @@ -231,6 +241,7 @@ impl UserSettings {

self.showhide = read_from_ini(self.showhide, "uShowHideKey", controls);
self.refresh_layout = read_from_ini(self.refresh_layout, "uRefreshKey", controls);
self.anchor_loc = read_from_ini(self.anchor_loc.clone(), "uAnchorLocation", options);

self.unarmed_handling = read_from_ini(self.unarmed_handling, "uHowToUnequip", controls);
self.unequip_modifier =
Expand Down Expand Up @@ -404,6 +415,9 @@ impl UserSettings {
pub fn refresh_layout(&self) -> u32 {
self.refresh_layout
}
pub fn anchor_loc(&self) -> &NamedAnchor {
&self.anchor_loc
}
pub fn maxlen(&self) -> u32 {
20
}
Expand Down Expand Up @@ -591,6 +605,31 @@ impl FromIniStr for String {
}
}

impl FromIniStr for NamedAnchor {
fn from_ini(value: &str) -> Option<Self>
where
Self: Sized,
{
if let Ok(v) = value.parse::<i32>() {
match v {
0 => Some(NamedAnchor::None),
1 => Some(NamedAnchor::TopLeft),
2 => Some(NamedAnchor::TopRight),
3 => Some(NamedAnchor::BottomLeft),
4 => Some(NamedAnchor::BottomRight),
5 => Some(NamedAnchor::Center),
6 => Some(NamedAnchor::CenterTop),
7 => Some(NamedAnchor::CenterBottom),
8 => Some(NamedAnchor::LeftCenter),
9 => Some(NamedAnchor::LeftCenter),
_ => Some(NamedAnchor::None),
}
} else {
None
}
}
}

// qualified so we don't collide with the macro strum::Display
// We implement this so the logs contain a human-readable dump of the settings
// at save game load, so people can debug.
Expand All @@ -606,6 +645,7 @@ impl std::fmt::Display for UserSettings {
right cycle key: {}
equipset cycle key: {}
refresh layout key: {}
layout anchor override: {}
how_to_activate: {}
activate consumables: {}
activate_modifier: {}
Expand Down Expand Up @@ -638,6 +678,7 @@ impl std::fmt::Display for UserSettings {
self.right,
self.equipset,
self.refresh_layout,
self.anchor_loc,
self.how_to_activate,
self.activate,
self.activate_modifier,
Expand Down
43 changes: 41 additions & 2 deletions src/layouts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize};
use self::shared::NamedAnchor;
use crate::control::notify;
use crate::controller::control::translated_key;
use crate::controller::user_settings;
use crate::plugin::{LayoutFlattened, Point};

static LAYOUT_PATH: &str = "./data/SKSE/Plugins/SoulsyHUD_Layout.toml";
Expand All @@ -35,7 +36,7 @@ pub fn hud_layout() -> LayoutFlattened {
layout.clone()
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum Layout {
Version1(Box<HudLayout1>),
Expand Down Expand Up @@ -121,6 +122,13 @@ impl Layout {
Layout::Version2(v) => LayoutFlattened::from(&**v),
}
}

pub fn anchor_point(&self) -> Point {
match self {
Layout::Version1(v) => v.anchor_point(),
Layout::Version2(v) => v.anchor_point(),
}
}
}

pub fn anchor_point(
Expand All @@ -137,7 +145,16 @@ pub fn anchor_point(
let width = size.x * global_scale;
let height = size.y * global_scale;

match anchor_name {
let config = *user_settings();
let user_pref_anchor = config.anchor_loc();
eprintln!("{user_pref_anchor}");
let anchor_to_use = if !matches!(user_pref_anchor, &NamedAnchor::None) {
user_pref_anchor
} else {
anchor_name
};

match anchor_to_use {
NamedAnchor::TopLeft => Point {
x: width / 2.0,
y: height / 2.0,
Expand Down Expand Up @@ -322,4 +339,26 @@ mod tests {
);
assert_eq!(pointed.anchor_point(), named.anchor_point());
}

#[test]
fn anchor_points_respect_settings() {
// override the defaults with what we need for this test
let _ = crate::controller::UserSettings::refresh_with("tests/fixtures/test-settings.ini");

let named = Layout::read_from_file("tests/fixtures/named-anchor.toml")
.expect("this test fixture exists and is valid");
// this layout has bottom left as an anchor point
// the test settings override with "center"
let relocated = named.anchor_point();
assert_eq!(
relocated,
Point {
x: 1720.0,
y: 720.0
}
);

let flattened = named.flatten();
assert_eq!(flattened.anchor, relocated);
}
}
22 changes: 22 additions & 0 deletions src/layouts/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,28 @@ where
}
}

impl From<&str> for NamedAnchor {
fn from(s: &str) -> Self {
match s.to_lowercase().as_str() {
"top_left" => NamedAnchor::TopLeft,
"top_right" => NamedAnchor::TopRight,
"bottom_left" => NamedAnchor::BottomLeft,
"bottom_right" => NamedAnchor::BottomRight,
"center" => NamedAnchor::Center,
"center_top" => NamedAnchor::CenterTop,
"top_center" => NamedAnchor::CenterTop,
"center_bottom" => NamedAnchor::CenterBottom,
"bottom_center" => NamedAnchor::CenterBottom,
"left_center" => NamedAnchor::LeftCenter,
"center_left" => NamedAnchor::LeftCenter,
"right_center" => NamedAnchor::RightCenter,
"center_right" => NamedAnchor::RightCenter,
"none" => NamedAnchor::None,
_ => NamedAnchor::None,
}
}
}

// ---------- MeterType

// We can't derive this because it is exposed to C++.
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/all-types.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bBooleanStringF = false
bBooleanEmpty =
sString = String with spaces
sStringEmpty =
uNamedAnchor = "top_left"

[emptysection]

Expand Down
34 changes: 34 additions & 0 deletions tests/fixtures/test-settings.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[Options]
bCycleAmmo = 1
bAutoFade = 1
bGroupPotions = 1
bDebugMode = 1
sSKSEIdentifier = WOMP
bLinkToFavorites = 1
bEquipSetsUnequip = 1
sLogLevel = debug
bCyclingSlowsTime = 1
uFadeTime = 1500
uEquipDelay = 2500
uLongPressMillis = 2750
uAnchorLocation = 5

[Controls]
uRefreshKey = 8
uShowHideKey = 2
uHowToUnequip = 0
bLongPressMatches = 1
iUnequipModifierKey = 184
uPowerCycleKey = 3
uLeftCycleKey = 5
uRightCycleKey = 7
uUtilityCycleKey = 6
uHowToActivate = 0
uHowToggleInMenus = 0
iMenuModifierKey = 42
iUtilityActivateModifier = 274


[Equipsets]
sLastEditedSetName = Mossy
sLastUsedSetName = Spiky