Skip to content
Open
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
26 changes: 26 additions & 0 deletions src/Data/Config/Property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "Data/Defines/Armor.h"

#include <algorithm>

namespace Data
{
bool AnyOfProperty::Match(const RE::GFxValue& a_value) const
Expand All @@ -21,6 +23,25 @@ namespace Data
_subProperties.push_back(a_property);
}

void AnyOfProperty::RemoveZeroNumberMatches()
{
_subProperties.erase(
std::remove_if(
_subProperties.begin(),
_subProperties.end(),
[](const std::shared_ptr<Property>& a_property)
{
auto matchProperty = std::dynamic_pointer_cast<MatchProperty>(a_property);
return matchProperty && matchProperty->IsZeroNumber();
}),
_subProperties.end());
}

bool AnyOfProperty::Empty() const
{
return _subProperties.empty();
}

bool MatchProperty::Match(const RE::GFxValue& a_value) const
{
if (a_value.IsArray()) {
Expand All @@ -39,6 +60,11 @@ namespace Data
return a_value == _value;
}

bool MatchProperty::IsZeroNumber() const
{
return _value.IsNumber() && _value.GetNumber() == 0;
}

bool RangeProperty::Match(const RE::GFxValue& a_value) const
{
if (!a_value.IsNumber()) {
Expand Down
6 changes: 6 additions & 0 deletions src/Data/Config/Property.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ namespace Data

void AddProperty(const std::string& a_name, std::shared_ptr<Property> a_property) override;

void RemoveZeroNumberMatches();

[[nodiscard]] bool Empty() const;

private:
std::vector<std::shared_ptr<Property>> _subProperties;
};
Expand All @@ -44,6 +48,8 @@ namespace Data

bool Match(const RE::GFxValue& a_value) const override;

[[nodiscard]] bool IsZeroNumber() const;

private:
std::string _cachedString;
RE::GFxValue _value;
Expand Down
114 changes: 108 additions & 6 deletions src/Data/Config/Rule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,55 @@ namespace Data
_customData.insert({ "iconSource"s, nullptr });
}

if (auto i = _properties.find("formId"s); i != _properties.end()) {
if (auto matchProperty = std::dynamic_pointer_cast<MatchProperty>(i->second);
matchProperty && matchProperty->IsZeroNumber()) {
return false;
}

if (auto anyOfProperty = std::dynamic_pointer_cast<AnyOfProperty>(i->second)) {
anyOfProperty->RemoveZeroNumberMatches();
if (anyOfProperty->Empty()) {
return false;
}
}
}

return !_properties.empty() && !_customData.empty();
}

void Rule::Classify(
const std::unordered_set<std::string>& a_nonIconAssignKeys,
const std::unordered_set<std::string>& a_allMatchKeys)
{
_passBehavior = PassBehavior::SkipIfUnmatched;
_trivialAssign = true;

for (const auto& property : _properties) {
const auto& name = property.first;
if (name == "iconLabel" || name == "iconColor") {
_passBehavior = PassBehavior::AlwaysReeval;
break;
}

if (a_nonIconAssignKeys.contains(name)) {
_passBehavior = PassBehavior::ReevalIfModified;
}
}

for (const auto& data : _customData) {
const auto& name = data.first;
if (name.rfind("icon", 0) == 0) {
continue;
}

if (a_allMatchKeys.contains(name)) {
_trivialAssign = false;
break;
}
}
}

bool Rule::ValidateIconSource(std::string a_iconSource)
{
if (auto i = _validatedSources.find(a_iconSource); i != _validatedSources.end()) {
Expand All @@ -48,12 +94,17 @@ namespace Data
return valid;
}

void Rule::SetInfo(RE::GFxValue* a_entryObject, bool& a_needsIconUpdate) const
bool Rule::SetInfo(
RE::GFxValue* a_entryObject,
bool& a_needsIconUpdate,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const
{
assert(a_entryObject);

if (!Match(a_entryObject)) {
return;
if (!Match(a_entryObject, a_formIdCache, a_formTypeCache, a_keywordsCache)) {
return false;
}

a_needsIconUpdate |= HasInfo();
Expand All @@ -65,13 +116,19 @@ namespace Data

a_entryObject->SetMember(name.c_str(), value);
}

return true;
}

void Rule::SetIcon(RE::GFxValue* a_entryObject) const
void Rule::SetIcon(
RE::GFxValue* a_entryObject,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const
{
assert(a_entryObject);

if (!Match(a_entryObject)) {
if (!Match(a_entryObject, a_formIdCache, a_formTypeCache, a_keywordsCache)) {
return;
}

Expand All @@ -84,11 +141,56 @@ namespace Data
}
}

bool Rule::Match(const RE::GFxValue* a_entryObject) const
Rule::PassBehavior Rule::GetPassBehavior() const
{
return _passBehavior;
}

bool Rule::IsTrivialAssign() const
{
return _trivialAssign;
}

const std::map<std::string, std::shared_ptr<Property>>& Rule::GetProperties() const
{
return _properties;
}

const std::map<std::string, CustomData>& Rule::GetCustomData() const
{
return _customData;
}

bool Rule::Match(
const RE::GFxValue* a_entryObject,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const
{
assert(a_entryObject);

for (const auto& [name, prop] : _properties) {
if (name == "formId") {
if (!prop->Match(a_formIdCache)) {
return false;
}
continue;
}

if (name == "formType") {
if (!prop->Match(a_formTypeCache)) {
return false;
}
continue;
}

if (name == "keywords") {
if (!prop->Match(a_keywordsCache)) {
return false;
}
continue;
}

RE::GFxValue value;
a_entryObject->GetMember(name.c_str(), &value);

Expand Down
42 changes: 39 additions & 3 deletions src/Data/Config/Rule.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,57 @@
#include "CustomData.h"
#include "Property.h"

#include <unordered_set>

namespace Data
{
class Rule final : public IPropertyContainer, public ICustomDataContainer
{
public:
enum class PassBehavior
{
SkipIfUnmatched,
ReevalIfModified,
AlwaysReeval
};

void AddProperty(const std::string& a_name, std::shared_ptr<Property> a_property) override;

void AddCustomData(const std::string& a_name, const CustomData& a_data) override;

bool Validate();

void SetInfo(RE::GFxValue* a_entryObject, bool& a_needsIconUpdate) const;
void Classify(
const std::unordered_set<std::string>& a_nonIconAssignKeys,
const std::unordered_set<std::string>& a_allMatchKeys);

bool SetInfo(
RE::GFxValue* a_entryObject,
bool& a_needsIconUpdate,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const;

void SetIcon(
RE::GFxValue* a_entryObject,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const;

[[nodiscard]] PassBehavior GetPassBehavior() const;

[[nodiscard]] bool IsTrivialAssign() const;

[[nodiscard]] const std::map<std::string, std::shared_ptr<Property>>& GetProperties() const;

void SetIcon(RE::GFxValue* a_entryObject) const;
[[nodiscard]] const std::map<std::string, CustomData>& GetCustomData() const;

private:
bool Match(const RE::GFxValue* a_entryObject) const;
bool Match(
const RE::GFxValue* a_entryObject,
const RE::GFxValue& a_formIdCache,
const RE::GFxValue& a_formTypeCache,
const RE::GFxValue& a_keywordsCache) const;

bool HasInfo() const;

Expand All @@ -29,5 +63,7 @@ namespace Data

std::map<std::string, std::shared_ptr<Property>> _properties;
std::map<std::string, CustomData> _customData;
PassBehavior _passBehavior = PassBehavior::SkipIfUnmatched;
bool _trivialAssign = true;
};
}
Loading