Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b1623ee
Updated uninstalled info
davo0411 Jun 16, 2025
fc1fde4
Update Feature.h
davo0411 Jun 16, 2025
44cc983
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 16, 2025
ef5c009
Update Feature.h
davo0411 Jun 17, 2025
de122cd
Update Feature.h
davo0411 Jun 17, 2025
e16aab3
duplication removal
davo0411 Jun 17, 2025
49ef751
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 17, 2025
1417037
punctuation
davo0411 Jun 17, 2025
b39c244
Update Feature.cpp
davo0411 Jun 17, 2025
ea4fb32
Update TerrainHelper.h
davo0411 Jun 17, 2025
d7e005c
Update TerrainHelper.h
davo0411 Jun 18, 2025
5126e41
Update Feature.cpp
davo0411 Jun 18, 2025
008f22e
Merge branch 'dev' into version-info
davo0411 Jun 18, 2025
8cc0958
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 18, 2025
f2cbd29
1
davo0411 Jun 18, 2025
953d4cd
Merge branch 'version-info' of https://github.com/davo0411/skyrim-com…
davo0411 Jun 18, 2025
a2e2728
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 18, 2025
483040b
Update Feature.cpp
davo0411 Jun 18, 2025
cbb92d4
Merge branch 'version-info' of https://github.com/davo0411/skyrim-com…
davo0411 Jun 18, 2025
d60675f
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 18, 2025
a933efb
Update Feature.cpp
davo0411 Jun 18, 2025
c4e7274
Merge branch 'version-info' of https://github.com/davo0411/skyrim-com…
davo0411 Jun 18, 2025
6867bb0
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Jun 18, 2025
560b498
Merge branch 'dev' into version-info
alandtse Jun 18, 2025
d0d695d
Update Feature.cpp
davo0411 Jun 18, 2025
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
43 changes: 31 additions & 12 deletions src/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "Features/VolumetricLighting.h"
#include "Features/WaterEffects.h"
#include "Features/WetnessEffects.h"
#include "Utils/Format.h"

#include "State.h"

Expand All @@ -42,21 +43,43 @@ void Feature::Load(json& o_json)
SI_Error rc = ini.LoadFile(ini_path.c_str());

if (rc < 0) {
if (!FeatureIssues::IsObsoleteFeature(GetShortName()))
if (FeatureIssues::IsObsoleteFeature(GetShortName())) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. This doesn't make sense. If the file is deleted we don't have to talk about it.

// Handle obsolete features
version = "obsolete"; // Set version so it shows error color in UI
failedLoadedMessage = std::format("{} is an obsolete feature that has been removed.", GetShortName());
FeatureIssues::FeatureFileInfo fileInfo = FeatureIssues::GetFeatureFileInfo(GetShortName());
FeatureIssues::AddFeatureIssue(GetShortName(), "N/A", failedLoadedMessage,
FeatureIssues::FeatureIssueInfo::IssueType::OBSOLETE, fileInfo, "");
} else {
logger::info("{} failed to load, feature disabled", ini_filename);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. I don't think you understand the code. The ini is missing because they didn't install or deleted it. Why is that an issue to raise?

// Set error message for missing file
std::string requiredVersion = "Unknown";
auto iter = FeatureVersions::FEATURE_MINIMAL_VERSIONS.find(GetShortName());
if (iter != FeatureVersions::FEATURE_MINIMAL_VERSIONS.end()) {
requiredVersion = Util::CleanVersionString(iter->second.string());
}
failedLoadedMessage = std::format("The {} file is missing. This feature is not installed! Version required: {}", ini_filename, requiredVersion);

// Add to feature issues
FeatureIssues::FeatureFileInfo fileInfo = FeatureIssues::GetFeatureFileInfo(GetShortName());
FeatureIssues::AddFeatureIssue(GetShortName(), "unknown", failedLoadedMessage,
FeatureIssues::FeatureIssueInfo::IssueType::VERSION_MISMATCH, fileInfo, requiredVersion);
}
loaded = false;
return;
}

bool hasError = false;
std::string errorVersion;
std::string requiredVersion = "Unknown"; // Store required version for later use
FeatureIssues::FeatureIssueInfo::IssueType errorType = FeatureIssues::FeatureIssueInfo::IssueType::UNKNOWN;

if (FeatureIssues::IsObsoleteFeature(GetShortName())) {
hasError = true;
version = "obsolete"; // Set version so it shows error color in UI
errorVersion = "N/A";
errorType = FeatureIssues::FeatureIssueInfo::IssueType::OBSOLETE;
failedLoadedMessage = std::format("{} is an obsolete feature that has been removed", GetShortName());
failedLoadedMessage = std::format("{} is an obsolete feature that has been removed.", GetShortName());
} else if (auto value = ini.GetValue("Info", "Version")) {
try {
REL::Version featureVersion(std::regex_replace(value, std::regex("-"), "."));
Expand All @@ -71,6 +94,8 @@ void Feature::Load(json& o_json)
} else {
// Version compatibility check
auto& minimalFeatureVersion = iter->second;
std::string rawVersion = minimalFeatureVersion.string();
requiredVersion = Util::CleanVersionString(rawVersion);
bool oldFeature = featureVersion.compare(minimalFeatureVersion) == std::strong_ordering::less;
bool majorVersionMismatch = featureVersion.major() < minimalFeatureVersion.major();

Expand All @@ -82,8 +107,7 @@ void Feature::Load(json& o_json)
errorVersion = value;
errorType = FeatureIssues::FeatureIssueInfo::IssueType::VERSION_MISMATCH;

std::string minimalVersionString = minimalFeatureVersion.string();
minimalVersionString = minimalVersionString.substr(0, minimalVersionString.size() - 2);
std::string minimalVersionString = Util::CleanVersionString(minimalFeatureVersion.string());

if (majorVersionMismatch) {
failedLoadedMessage = std::format("{} {} is too old, major version incompatibility detected. Required: {}", GetShortName(), value, minimalVersionString);
Expand All @@ -100,11 +124,6 @@ void Feature::Load(json& o_json)
errorType = FeatureIssues::FeatureIssueInfo::IssueType::VERSION_MISMATCH;
failedLoadedMessage = std::format("{} {} has invalid version format: {}", GetShortName(), value, e.what());
}
} else {
hasError = true;
errorVersion = "unknown";
errorType = FeatureIssues::FeatureIssueInfo::IssueType::VERSION_MISMATCH;
failedLoadedMessage = std::format("{} missing version info; not successfully loaded", ini_filename);
}

if (hasError) {
Expand Down Expand Up @@ -181,7 +200,7 @@ bool Feature::ValidateCache(CSimpleIniA& a_ini)
logger::info("Change in version detected. Installed {} but {} in Disk Cache", version, versionInCache);
return false;
} else {
logger::info("Installed version and cached version match.");
logger::info("Installed version and cached version match");
}
}

Expand Down Expand Up @@ -262,4 +281,4 @@ bool Feature::ToggleAtBootSetting()
state->SetFeatureDisabled(featureName, !disabled);

return state->IsFeatureDisabled(featureName); // Return the new state
}
}
31 changes: 17 additions & 14 deletions src/Feature.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "Menu.h"
#include "Utils/Format.h"

struct Feature
{
Expand Down Expand Up @@ -57,8 +58,11 @@ struct Feature

/**
* Whether to print the INI version missing message when this feature is unloaded
* Default false to prevent duplicate error messages. This is handled by failedLoadedMessage in Feature.cpp.
* Retains functionality for author to include custom error message.
* Set to "true" in header file of individual feature.
*/
virtual bool DrawFailLoadMessage() const { return true; }
Comment thread
davo0411 marked this conversation as resolved.
virtual bool DrawFailLoadMessage() const { return false; }

/**
* Get feature summary and key features for hover tooltip and unloaded UI
Expand All @@ -69,28 +73,27 @@ struct Feature

virtual void SetupResources() {}
virtual void Reset() {}

virtual void DrawSettings() {}
virtual void DrawUnloadedUI()
{
auto [description, keyFeatures] = GetFeatureSummary();

if (!description.empty() || !keyFeatures.empty()) {
ImGui::TextColored(Menu::GetSingleton()->GetTheme().StatusPalette.Error, "This feature is not installed!");
if (!failedLoadedMessage.empty()) {
ImGui::TextColored(Menu::GetSingleton()->GetTheme().StatusPalette.Error, "%s", failedLoadedMessage.c_str());
Comment thread
davo0411 marked this conversation as resolved.
ImGui::Spacing();
}

if (!description.empty()) {
ImGui::TextWrapped("%s", description.c_str());
ImGui::Spacing();
}
if (!description.empty()) {
ImGui::TextWrapped("%s", description.c_str());
ImGui::Spacing();
}

if (!keyFeatures.empty()) {
ImGui::TextWrapped("Key features:");
for (const auto& feature : keyFeatures) {
ImGui::BulletText("%s", feature.c_str());
}
ImGui::Spacing();
if (!keyFeatures.empty()) {
ImGui::TextWrapped("Key features:");
for (const auto& feature : keyFeatures) {
ImGui::BulletText("%s", feature.c_str());
}
ImGui::Spacing();
}
}

Expand Down
13 changes: 7 additions & 6 deletions src/FeatureIssues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Menu.h"
#include "State.h"
#include "Util.h"
#include "Utils/Format.h"

namespace FeatureIssues
{
Expand Down Expand Up @@ -484,11 +485,11 @@ namespace FeatureIssues
ImGui::Spacing();
}
if (!issue.version.empty()) {
ImGui::TextWrapped("Current Version: %s", issue.version.c_str());
ImGui::TextWrapped("Current Version: %s", Util::CleanVersionString(issue.version).c_str());
ImGui::Spacing();
}
if (issue.IsVersionMismatch() && !issue.minimumVersionRequired.empty()) {
ImGui::TextWrapped("Minimum Required: %s", issue.minimumVersionRequired.c_str());
ImGui::TextWrapped("Minimum Required: %s", Util::CleanVersionString(issue.minimumVersionRequired).c_str());
ImGui::Spacing();
}
ImGui::TextWrapped("Issue: %s", issue.rejectionReason.c_str());
Expand Down Expand Up @@ -577,15 +578,15 @@ namespace FeatureIssues
if (!issue.replacementFeatureModLink.empty()) {
std::string buttonText = issue.minimumVersionRequired.empty() ?
("Download Latest " + issue.replacementFeatureDisplayName) :
("Download " + issue.replacementFeatureDisplayName + " " + issue.minimumVersionRequired + "+");
("Download " + issue.replacementFeatureDisplayName + " " + Util::CleanVersionString(issue.minimumVersionRequired) + "+");

if (ImGui::SmallButton(buttonText.c_str())) {
ShellExecuteA(0, 0, issue.replacementFeatureModLink.c_str(), 0, 0, SW_SHOW);
}

if (auto _tt = Util::HoverTooltipWrapper()) {
if (!issue.minimumVersionRequired.empty()) {
ImGui::Text("Download %s version %s or later", issue.replacementFeatureDisplayName.c_str(), issue.minimumVersionRequired.c_str());
ImGui::Text("Download %s version %s or later", issue.replacementFeatureDisplayName.c_str(), Util::CleanVersionString(issue.minimumVersionRequired).c_str());
} else {
ImGui::Text("Download the latest version of %s", issue.replacementFeatureDisplayName.c_str());
}
Expand All @@ -594,12 +595,12 @@ namespace FeatureIssues
// Show message when no download link is available
std::string updateText = issue.minimumVersionRequired.empty() ?
"Update Required" :
("Update to " + issue.minimumVersionRequired + "+ Required");
("Update to " + Util::CleanVersionString(issue.minimumVersionRequired) + "+ Required");

ImGui::TextWrapped("%s", updateText.c_str());
if (auto _tt = Util::HoverTooltipWrapper()) {
if (!issue.minimumVersionRequired.empty()) {
ImGui::Text("This feature needs to be updated to version %s or later. Check the mod page manually.", issue.minimumVersionRequired.c_str());
ImGui::Text("This feature needs to be updated to version %s or later. Check the mod page manually.", Util::CleanVersionString(issue.minimumVersionRequired).c_str());
} else {
ImGui::Text("This feature needs to be updated but no download link is available. Check the mod page manually.");
}
Expand Down
20 changes: 0 additions & 20 deletions src/Features/TerrainHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,6 @@
#include "ShaderCache.h"
#include "State.h"

void TerrainHelper::DrawUnloadedUI()
{
auto [description, keyFeatures] = GetFeatureSummary();

ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::Text("%s", description.c_str());

if (!keyFeatures.empty()) {
ImGui::Spacing();
ImGui::Text("Key Features:");
for (const auto& feature : keyFeatures) {
ImGui::BulletText("%s", feature.c_str());
}
}

ImGui::Spacing();
ImGui::TextWrapped("Note: This feature is only required if a terrain mod you are using specifically requires it, otherwise it does nothing.");
Comment thread
davo0411 marked this conversation as resolved.
ImGui::PopTextWrapPos();
}

void TerrainHelper::DataLoaded()
{
// Get the default landscape texture set for terrain helper
Expand Down
4 changes: 1 addition & 3 deletions src/Features/TerrainHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct TerrainHelper : Feature
virtual std::pair<std::string, std::vector<std::string>> GetFeatureSummary() override
{
return {
"Provides enhanced terrain material support for terrain mods that require additional texture slots and parallax mapping capabilities.",
"Provides enhanced terrain material support for terrain mods that require additional texture slots and parallax mapping capabilities.\nNote: This feature is only required if a terrain mod you are using specifically requires it, otherwise it does nothing.",
{ "Extended texture slot support for terrain materials",
"Parallax mapping integration for terrain textures",
"Automatic terrain material detection and setup",
Expand All @@ -45,8 +45,6 @@ struct TerrainHelper : Feature
virtual void DataLoaded() override;
virtual bool SupportsVR() override { return true; };
virtual std::string GetFeatureModLink() override { return MakeNexusModURL(MOD_ID); }
virtual void DrawUnloadedUI() override;
virtual bool DrawFailLoadMessage() const override { return false; };

void SetShaderResouces(ID3D11DeviceContext* a_context);
bool TESObjectLAND_SetupMaterial(RE::TESObjectLAND* land);
Expand Down
5 changes: 0 additions & 5 deletions src/Features/TerrainVariation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,4 @@ void TerrainVariation::LoadSettings(json& o_json)
void TerrainVariation::SaveSettings(json& o_json)
{
o_json = settings;
}

bool TerrainVariation::DrawFailLoadMessage() const
{
return false;
}
4 changes: 1 addition & 3 deletions src/Features/TerrainVariation.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct TerrainVariation : Feature
return {
"Terrain Variation reduces the repeating pattern effect on terrain textures.\n"
"This technique creates more natural-looking terrain by adding variation to texture sampling.",
{ "Reduces terrain texture tiling",
{ "Removes terrain texture tiling",
"Adjustable distance-based blending",
"Improved terrain visual quality",
"Compatible with Extended Materials parallax" }
Expand Down Expand Up @@ -56,9 +56,7 @@ struct TerrainVariation : Feature
1.0f, // shadowRayDirFactor
1 // hashQuality - default to high quality
};

virtual void DrawSettings() override;
virtual bool DrawFailLoadMessage() const override;
virtual void LoadSettings(json& o_json) override;
virtual void SaveSettings(json& o_json) override;
virtual void RestoreDefaultSettings() override
Expand Down
4 changes: 0 additions & 4 deletions src/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,6 @@ void Menu::DrawSettings()
ImGui::EndTable();
}

if (hasFailedMessage && feat->DrawFailLoadMessage()) {
ImGui::TextColored(themeSettings.StatusPalette.Error, feat->failedLoadedMessage.c_str());
}

if (!isDisabled) {
if (ImGui::BeginChild("##FeatureConfigFrame", { 0, 0 }, true)) {
if (isLoaded) {
Expand Down
8 changes: 8 additions & 0 deletions src/Utils/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ namespace Util
return v.substr(0, v.find_last_of("."));
}

std::string CleanVersionString(const std::string& versionString)
{
if (versionString.size() >= 2 && versionString.substr(versionString.size() - 2) == "-0") {
return versionString.substr(0, versionString.size() - 2);
}
return versionString;
}

std::string DefinesToString(const std::vector<std::pair<const char*, const char*>>& defines)
{
std::string result;
Expand Down
2 changes: 2 additions & 0 deletions src/Utils/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace Util
{
std::string GetFormattedVersion(const REL::Version& version);

std::string CleanVersionString(const std::string& versionString);

std::string DefinesToString(const std::vector<std::pair<const char*, const char*>>& defines);
std::string DefinesToString(const std::vector<D3D_SHADER_MACRO>& defines);

Expand Down