From 2f6acbd7da1c5ee026209214a9c1fda76f348a52 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 10 Apr 2024 21:16:22 +0200 Subject: [PATCH 01/26] Deregister the player before loading a new one --- apps/openmw/mwworld/player.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index b498bb488b..7849ba1458 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -325,6 +325,7 @@ namespace MWWorld player.mObject.mEnabled = true; } + MWBase::Environment::get().getWorldModel()->deregisterLiveCellRef(mPlayer); mPlayer.load(player.mObject); for (size_t i = 0; i < mSaveAttributes.size(); ++i) From fb4edda45dde6cf3ee57e6bf4b28718bb1e91251 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 4 Apr 2024 19:45:29 +0200 Subject: [PATCH 02/26] Validate INFO filters when loading the record --- apps/openmw/mwdialogue/filter.cpp | 19 +++---- apps/openmw/mwdialogue/selectwrapper.cpp | 12 +++- apps/openmw/mwdialogue/selectwrapper.hpp | 4 ++ components/esm3/loadinfo.cpp | 71 +++++++++++++++++++++++- 4 files changed, 94 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 8b67ea28b3..2693811357 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -30,7 +30,7 @@ namespace { bool matchesStaticFilters(const MWDialogue::SelectWrapper& select, const MWWorld::Ptr& actor) { - const ESM::RefId selectId = ESM::RefId::stringRefId(select.getName()); + const ESM::RefId selectId = select.getId(); if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotId) return actor.getCellRef().getRefId() != selectId; if (actor.getClass().isNpc()) @@ -356,19 +356,18 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons { case SelectWrapper::Function_Journal: - return MWBase::Environment::get().getJournal()->getJournalIndex(ESM::RefId::stringRefId(select.getName())); + return MWBase::Environment::get().getJournal()->getJournalIndex(select.getId()); case SelectWrapper::Function_Item: { MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); - return store.count(ESM::RefId::stringRefId(select.getName())); + return store.count(select.getId()); } case SelectWrapper::Function_Dead: - return MWBase::Environment::get().getMechanicsManager()->countDeaths( - ESM::RefId::stringRefId(select.getName())); + return MWBase::Environment::get().getMechanicsManager()->countDeaths(select.getId()); case SelectWrapper::Function_Choice: @@ -546,24 +545,24 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con case SelectWrapper::Function_NotId: - return !(mActor.getCellRef().getRefId() == ESM::RefId::stringRefId(select.getName())); + return mActor.getCellRef().getRefId() != select.getId(); case SelectWrapper::Function_NotFaction: - return !(mActor.getClass().getPrimaryFaction(mActor) == ESM::RefId::stringRefId(select.getName())); + return mActor.getClass().getPrimaryFaction(mActor) != select.getId(); case SelectWrapper::Function_NotClass: - return !(mActor.get()->mBase->mClass == ESM::RefId::stringRefId(select.getName())); + return mActor.get()->mBase->mClass != select.getId(); case SelectWrapper::Function_NotRace: - return !(mActor.get()->mBase->mRace == ESM::RefId::stringRefId(select.getName())); + return mActor.get()->mBase->mRace != select.getId(); case SelectWrapper::Function_NotCell: { std::string_view actorCell = MWBase::Environment::get().getWorld()->getCellName(mActor.getCell()); - return !Misc::StringUtils::ciStartsWith(actorCell, select.getName()); + return !Misc::StringUtils::ciStartsWith(actorCell, select.getCellName()); } case SelectWrapper::Function_SameGender: diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 94f7f73097..0cee8bb009 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -454,5 +454,15 @@ bool MWDialogue::SelectWrapper::selectCompare(bool value) const std::string MWDialogue::SelectWrapper::getName() const { - return Misc::StringUtils::lowerCase(std::string_view(mSelect.mSelectRule).substr(5)); + return Misc::StringUtils::lowerCase(getCellName()); +} + +std::string_view MWDialogue::SelectWrapper::getCellName() const +{ + return std::string_view(mSelect.mSelectRule).substr(5); +} + +ESM::RefId MWDialogue::SelectWrapper::getId() const +{ + return ESM::RefId::stringRefId(getCellName()); } diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index 0d376d957c..f736b504d8 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -95,6 +95,10 @@ namespace MWDialogue std::string getName() const; ///< Return case-smashed name. + + std::string_view getCellName() const; + + ESM::RefId getId() const; }; } diff --git a/components/esm3/loadinfo.cpp b/components/esm3/loadinfo.cpp index 714d59fef4..b091edd3f6 100644 --- a/components/esm3/loadinfo.cpp +++ b/components/esm3/loadinfo.cpp @@ -3,7 +3,65 @@ #include "esmreader.hpp" #include "esmwriter.hpp" +#include #include +#include + +namespace +{ + enum class SelectRuleStatus + { + Valid, + Invalid, + Ignorable + }; + + SelectRuleStatus isValidSelectRule(std::string_view rule) + { + if (rule.size() < 5) + return SelectRuleStatus::Invalid; + if (rule[4] < '0' || rule[4] > '5') // Comparison operators + return SelectRuleStatus::Invalid; + if (rule[1] == '1') // Function + { + int function = Misc::StringUtils::toNumeric(rule.substr(2, 2), -1); + if (function >= 0 && function <= 73) + return SelectRuleStatus::Valid; + return SelectRuleStatus::Invalid; + } + if (rule.size() == 5) // Missing ID + return SelectRuleStatus::Invalid; + if (rule[3] != 'X') + return SelectRuleStatus::Ignorable; + constexpr auto ignorable + = [](bool valid) { return valid ? SelectRuleStatus::Valid : SelectRuleStatus::Ignorable; }; + switch (rule[1]) + { + case '2': + case '3': + case 'C': + return ignorable(rule[2] == 's' || rule[2] == 'l' || rule[2] == 'f'); + case '4': + return ignorable(rule[2] == 'J'); + case '5': + return ignorable(rule[2] == 'I'); + case '6': + return ignorable(rule[2] == 'D'); + case '7': + return ignorable(rule[2] == 'X'); + case '8': + return ignorable(rule[2] == 'F'); + case '9': + return ignorable(rule[2] == 'C'); + case 'A': + return ignorable(rule[2] == 'R'); + case 'B': + return ignorable(rule[2] == 'L'); + default: + return SelectRuleStatus::Invalid; + } + } +} namespace ESM { @@ -69,7 +127,18 @@ namespace ESM SelectStruct ss; ss.mSelectRule = esm.getHString(); ss.mValue.read(esm, Variant::Format_Info); - mSelects.push_back(ss); + auto valid = isValidSelectRule(ss.mSelectRule); + if (ss.mValue.getType() != VT_Int && ss.mValue.getType() != VT_Float) + valid = SelectRuleStatus::Invalid; + if (valid == SelectRuleStatus::Invalid) + Log(Debug::Warning) << "Skipping invalid SCVR for INFO " << mId; + else + { + mSelects.push_back(ss); + if (valid == SelectRuleStatus::Ignorable) + Log(Debug::Info) + << "Found malformed SCVR for INFO " << mId << " at index " << ss.mSelectRule[0]; + } break; } case fourCC("BNAM"): From a4625ea784d25e7408f480a4ceda4ae21e0bc54e Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 11 Apr 2024 22:29:33 +0200 Subject: [PATCH 03/26] Deduplicate dialogue filter parsing --- apps/esmtool/labels.cpp | 11 +- apps/esmtool/record.cpp | 128 ++- apps/opencs/model/tools/topicinfocheck.cpp | 79 +- apps/opencs/model/tools/topicinfocheck.hpp | 2 +- apps/opencs/model/world/infoselectwrapper.cpp | 782 ++++++------------ apps/opencs/model/world/infoselectwrapper.hpp | 171 +--- .../model/world/nestedcoladapterimp.cpp | 57 +- .../view/world/idcompletiondelegate.cpp | 22 +- apps/openmw/mwdialogue/filter.cpp | 159 ++-- apps/openmw/mwdialogue/selectwrapper.cpp | 505 ++++------- apps/openmw/mwdialogue/selectwrapper.hpp | 62 +- components/CMakeLists.txt | 2 +- components/esm3/dialoguecondition.cpp | 204 +++++ components/esm3/dialoguecondition.hpp | 134 +++ components/esm3/loadinfo.cpp | 83 +- components/esm3/loadinfo.hpp | 15 +- 16 files changed, 1002 insertions(+), 1414 deletions(-) create mode 100644 components/esm3/dialoguecondition.cpp create mode 100644 components/esm3/dialoguecondition.hpp diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index 6def8b4a42..83b4a486e1 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -1,5 +1,6 @@ #include "labels.hpp" +#include #include #include #include @@ -572,13 +573,14 @@ std::string_view enchantTypeLabel(int idx) std::string_view ruleFunction(int idx) { - if (idx >= 0 && idx <= 72) + if (idx >= ESM::DialogueCondition::Function_FacReactionLowest + && idx <= ESM::DialogueCondition::Function_PcWerewolfKills) { static constexpr std::string_view ruleFunctions[] = { - "Reaction Low", - "Reaction High", + "Lowest Faction Reaction", + "Highest Faction Reaction", "Rank Requirement", - "NPC? Reputation", + "NPC Reputation", "Health Percent", "Player Reputation", "NPC Level", @@ -648,6 +650,7 @@ std::string_view ruleFunction(int idx) "Flee", "Should Attack", "Werewolf", + "Werewolf Kills", }; return ruleFunctions[idx]; } diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 4526b891e2..cd38dadf3f 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -57,112 +57,82 @@ namespace std::cout << " Cell Name: " << p.mCellName << std::endl; } - std::string ruleString(const ESM::DialInfo::SelectStruct& ss) + std::string ruleString(const ESM::DialogueCondition& ss) { - std::string rule = ss.mSelectRule; + std::string_view type_str = "INVALID"; + std::string_view func_str; - if (rule.length() < 5) - return "INVALID"; - - char type = rule[1]; - char indicator = rule[2]; - - std::string type_str = "INVALID"; - std::string func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1, 3)); - int func = Misc::StringUtils::toNumeric(rule.substr(2, 2), 0); - - switch (type) + switch (ss.mFunction) { - case '1': - type_str = "Function"; - func_str = std::string(ruleFunction(func)); + case ESM::DialogueCondition::Function_Global: + type_str = "Global"; + func_str = ss.mVariable; break; - case '2': - if (indicator == 's') - type_str = "Global short"; - else if (indicator == 'l') - type_str = "Global long"; - else if (indicator == 'f') - type_str = "Global float"; + case ESM::DialogueCondition::Function_Local: + type_str = "Local"; + func_str = ss.mVariable; break; - case '3': - if (indicator == 's') - type_str = "Local short"; - else if (indicator == 'l') - type_str = "Local long"; - else if (indicator == 'f') - type_str = "Local float"; + case ESM::DialogueCondition::Function_Journal: + type_str = "Journal"; + func_str = ss.mVariable; break; - case '4': - if (indicator == 'J') - type_str = "Journal"; + case ESM::DialogueCondition::Function_Item: + type_str = "Item count"; + func_str = ss.mVariable; break; - case '5': - if (indicator == 'I') - type_str = "Item type"; + case ESM::DialogueCondition::Function_Dead: + type_str = "Dead"; + func_str = ss.mVariable; break; - case '6': - if (indicator == 'D') - type_str = "NPC Dead"; + case ESM::DialogueCondition::Function_NotId: + type_str = "Not ID"; + func_str = ss.mVariable; break; - case '7': - if (indicator == 'X') - type_str = "Not ID"; + case ESM::DialogueCondition::Function_NotFaction: + type_str = "Not Faction"; + func_str = ss.mVariable; break; - case '8': - if (indicator == 'F') - type_str = "Not Faction"; + case ESM::DialogueCondition::Function_NotClass: + type_str = "Not Class"; + func_str = ss.mVariable; break; - case '9': - if (indicator == 'C') - type_str = "Not Class"; + case ESM::DialogueCondition::Function_NotRace: + type_str = "Not Race"; + func_str = ss.mVariable; break; - case 'A': - if (indicator == 'R') - type_str = "Not Race"; + case ESM::DialogueCondition::Function_NotCell: + type_str = "Not Cell"; + func_str = ss.mVariable; break; - case 'B': - if (indicator == 'L') - type_str = "Not Cell"; - break; - case 'C': - if (indicator == 's') - type_str = "Not Local"; + case ESM::DialogueCondition::Function_NotLocal: + type_str = "Not Local"; + func_str = ss.mVariable; break; default: + type_str = "Function"; + func_str = ruleFunction(ss.mFunction); break; } - // Append the variable name to the function string if any. - if (type != '1') - func_str = rule.substr(5); - - // In the previous switch, we assumed that the second char was X - // for all types not qual to one. If this wasn't true, go back to - // the error message. - if (type != '1' && rule[3] != 'X') - func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1, 3)); - - char oper = rule[4]; - std::string oper_str = "??"; - switch (oper) + std::string_view oper_str = "??"; + switch (ss.mComparison) { - case '0': + case ESM::DialogueCondition::Comp_Eq: oper_str = "=="; break; - case '1': + case ESM::DialogueCondition::Comp_Ne: oper_str = "!="; break; - case '2': + case ESM::DialogueCondition::Comp_Gt: oper_str = "> "; break; - case '3': + case ESM::DialogueCondition::Comp_Ge: oper_str = ">="; break; - case '4': + case ESM::DialogueCondition::Comp_Ls: oper_str = "< "; break; - case '5': + case ESM::DialogueCondition::Comp_Le: oper_str = "<="; break; default: @@ -170,7 +140,7 @@ namespace } std::ostringstream stream; - stream << ss.mValue; + std::visit([&](auto value) { stream << value; }, ss.mValue); std::string result = Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str()); @@ -842,7 +812,7 @@ namespace EsmTool << std::endl; std::cout << " Type: " << dialogTypeLabel(mData.mData.mType) << std::endl; - for (const ESM::DialInfo::SelectStruct& rule : mData.mSelects) + for (const auto& rule : mData.mSelects) std::cout << " Select Rule: " << ruleString(rule) << std::endl; if (!mData.mResultScript.empty()) diff --git a/apps/opencs/model/tools/topicinfocheck.cpp b/apps/opencs/model/tools/topicinfocheck.cpp index ba99a33a28..fab90d951a 100644 --- a/apps/opencs/model/tools/topicinfocheck.cpp +++ b/apps/opencs/model/tools/topicinfocheck.cpp @@ -171,10 +171,9 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message // Check info conditions - for (std::vector::const_iterator it = topicInfo.mSelects.begin(); - it != topicInfo.mSelects.end(); ++it) + for (const auto& select : topicInfo.mSelects) { - verifySelectStruct((*it), id, messages); + verifySelectStruct(select, id, messages); } } @@ -308,49 +307,15 @@ bool CSMTools::TopicInfoCheckStage::verifyItem( } bool CSMTools::TopicInfoCheckStage::verifySelectStruct( - const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages) + const ESM::DialogueCondition& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages) { CSMWorld::ConstInfoSelectWrapper infoCondition(select); - if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_None) + if (select.mFunction == ESM::DialogueCondition::Function_None) { messages.add(id, "Invalid condition '" + infoCondition.toString() + "'", "", CSMDoc::Message::Severity_Error); return false; } - else if (!infoCondition.variantTypeIsValid()) - { - std::ostringstream stream; - stream << "Value of condition '" << infoCondition.toString() << "' has invalid "; - - switch (select.mValue.getType()) - { - case ESM::VT_None: - stream << "None"; - break; - case ESM::VT_Short: - stream << "Short"; - break; - case ESM::VT_Int: - stream << "Int"; - break; - case ESM::VT_Long: - stream << "Long"; - break; - case ESM::VT_Float: - stream << "Float"; - break; - case ESM::VT_String: - stream << "String"; - break; - default: - stream << "unknown"; - break; - } - stream << " type"; - - messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error); - return false; - } else if (infoCondition.conditionIsAlwaysTrue()) { messages.add( @@ -365,48 +330,48 @@ bool CSMTools::TopicInfoCheckStage::verifySelectStruct( } // Id checks - if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global - && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mGlobals, id, messages)) + if (select.mFunction == ESM::DialogueCondition::Function_Global + && !verifyId(ESM::RefId::stringRefId(select.mVariable), mGlobals, id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Journal - && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mJournals, id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_Journal + && !verifyId(ESM::RefId::stringRefId(select.mVariable), mJournals, id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item - && !verifyItem(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_Item + && !verifyItem(ESM::RefId::stringRefId(select.mVariable), id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead - && !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_Dead + && !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId - && !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_NotId + && !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotFaction - && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mFactions, id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_NotFaction + && !verifyId(ESM::RefId::stringRefId(select.mVariable), mFactions, id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotClass - && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mClasses, id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_NotClass + && !verifyId(ESM::RefId::stringRefId(select.mVariable), mClasses, id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotRace - && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mRaces, id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_NotRace + && !verifyId(ESM::RefId::stringRefId(select.mVariable), mRaces, id, messages)) { return false; } - else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell - && !verifyCell(infoCondition.getVariableName(), id, messages)) + else if (select.mFunction == ESM::DialogueCondition::Function_NotCell + && !verifyCell(select.mVariable, id, messages)) { return false; } diff --git a/apps/opencs/model/tools/topicinfocheck.hpp b/apps/opencs/model/tools/topicinfocheck.hpp index 1bb2fc61dc..3069fbc0ff 100644 --- a/apps/opencs/model/tools/topicinfocheck.hpp +++ b/apps/opencs/model/tools/topicinfocheck.hpp @@ -84,7 +84,7 @@ namespace CSMTools const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifySelectStruct( - const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); + const ESM::DialogueCondition& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); template diff --git a/apps/opencs/model/world/infoselectwrapper.cpp b/apps/opencs/model/world/infoselectwrapper.cpp index fb1adf16d4..d1af341c04 100644 --- a/apps/opencs/model/world/infoselectwrapper.cpp +++ b/apps/opencs/model/world/infoselectwrapper.cpp @@ -6,16 +6,9 @@ #include -const size_t CSMWorld::ConstInfoSelectWrapper::RuleMinSize = 5; - -const size_t CSMWorld::ConstInfoSelectWrapper::FunctionPrefixOffset = 1; -const size_t CSMWorld::ConstInfoSelectWrapper::FunctionIndexOffset = 2; -const size_t CSMWorld::ConstInfoSelectWrapper::RelationIndexOffset = 4; -const size_t CSMWorld::ConstInfoSelectWrapper::VarNameOffset = 5; - const char* CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings[] = { - "Rank Low", - "Rank High", + "Faction Reaction Low", + "Faction Reaction High", "Rank Requirement", "Reputation", "Health Percent", @@ -121,17 +114,17 @@ const char* CSMWorld::ConstInfoSelectWrapper::ComparisonEnumStrings[] = { // static functions -std::string CSMWorld::ConstInfoSelectWrapper::convertToString(FunctionName name) +std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ESM::DialogueCondition::Function name) { - if (name < Function_None) + if (name < ESM::DialogueCondition::Function_None) return FunctionEnumStrings[name]; else return "(Invalid Data: Function)"; } -std::string CSMWorld::ConstInfoSelectWrapper::convertToString(RelationType type) +std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ESM::DialogueCondition::Comparison type) { - if (type < Relation_None) + if (type < ESM::DialogueCondition::Comp_None) return RelationEnumStrings[type]; else return "(Invalid Data: Relation)"; @@ -147,20 +140,21 @@ std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ComparisonType typ // ConstInfoSelectWrapper -CSMWorld::ConstInfoSelectWrapper::ConstInfoSelectWrapper(const ESM::DialInfo::SelectStruct& select) +CSMWorld::ConstInfoSelectWrapper::ConstInfoSelectWrapper(const ESM::DialogueCondition& select) : mConstSelect(select) { - readRule(); + updateHasVariable(); + updateComparisonType(); } -CSMWorld::ConstInfoSelectWrapper::FunctionName CSMWorld::ConstInfoSelectWrapper::getFunctionName() const +ESM::DialogueCondition::Function CSMWorld::ConstInfoSelectWrapper::getFunctionName() const { - return mFunctionName; + return mConstSelect.mFunction; } -CSMWorld::ConstInfoSelectWrapper::RelationType CSMWorld::ConstInfoSelectWrapper::getRelationType() const +ESM::DialogueCondition::Comparison CSMWorld::ConstInfoSelectWrapper::getRelationType() const { - return mRelationType; + return mConstSelect.mComparison; } CSMWorld::ConstInfoSelectWrapper::ComparisonType CSMWorld::ConstInfoSelectWrapper::getComparisonType() const @@ -175,24 +169,21 @@ bool CSMWorld::ConstInfoSelectWrapper::hasVariable() const const std::string& CSMWorld::ConstInfoSelectWrapper::getVariableName() const { - return mVariableName; + return mConstSelect.mVariable; } bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue() const { - if (!variantTypeIsValid()) - return false; - if (mComparisonType == Comparison_Boolean || mComparisonType == Comparison_Integer) { - if (mConstSelect.mValue.getType() == ESM::VT_Float) + if (std::holds_alternative(mConstSelect.mValue)) return conditionIsAlwaysTrue(getConditionFloatRange(), getValidIntRange()); else return conditionIsAlwaysTrue(getConditionIntRange(), getValidIntRange()); } else if (mComparisonType == Comparison_Numeric) { - if (mConstSelect.mValue.getType() == ESM::VT_Float) + if (std::holds_alternative(mConstSelect.mValue)) return conditionIsAlwaysTrue(getConditionFloatRange(), getValidFloatRange()); else return conditionIsAlwaysTrue(getConditionIntRange(), getValidFloatRange()); @@ -203,19 +194,16 @@ bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue() const bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue() const { - if (!variantTypeIsValid()) - return false; - if (mComparisonType == Comparison_Boolean || mComparisonType == Comparison_Integer) { - if (mConstSelect.mValue.getType() == ESM::VT_Float) + if (std::holds_alternative(mConstSelect.mValue)) return conditionIsNeverTrue(getConditionFloatRange(), getValidIntRange()); else return conditionIsNeverTrue(getConditionIntRange(), getValidIntRange()); } else if (mComparisonType == Comparison_Numeric) { - if (mConstSelect.mValue.getType() == ESM::VT_Float) + if (std::holds_alternative(mConstSelect.mValue)) return conditionIsNeverTrue(getConditionFloatRange(), getValidFloatRange()); else return conditionIsNeverTrue(getConditionIntRange(), getValidFloatRange()); @@ -224,170 +212,36 @@ bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue() const return false; } -bool CSMWorld::ConstInfoSelectWrapper::variantTypeIsValid() const -{ - return (mConstSelect.mValue.getType() == ESM::VT_Int || mConstSelect.mValue.getType() == ESM::VT_Float); -} - -const ESM::Variant& CSMWorld::ConstInfoSelectWrapper::getVariant() const -{ - return mConstSelect.mValue; -} - std::string CSMWorld::ConstInfoSelectWrapper::toString() const { std::ostringstream stream; - stream << convertToString(mFunctionName) << " "; + stream << convertToString(getFunctionName()) << " "; if (mHasVariable) - stream << mVariableName << " "; + stream << getVariableName() << " "; - stream << convertToString(mRelationType) << " "; + stream << convertToString(getRelationType()) << " "; - switch (mConstSelect.mValue.getType()) - { - case ESM::VT_Int: - stream << mConstSelect.mValue.getInteger(); - break; - - case ESM::VT_Float: - stream << mConstSelect.mValue.getFloat(); - break; - - default: - stream << "(Invalid value type)"; - break; - } + std::visit([&](auto value) { stream << value; }, mConstSelect.mValue); return stream.str(); } -void CSMWorld::ConstInfoSelectWrapper::readRule() -{ - if (mConstSelect.mSelectRule.size() < RuleMinSize) - throw std::runtime_error("InfoSelectWrapper: rule is to small"); - - readFunctionName(); - readRelationType(); - readVariableName(); - updateHasVariable(); - updateComparisonType(); -} - -void CSMWorld::ConstInfoSelectWrapper::readFunctionName() -{ - char functionPrefix = mConstSelect.mSelectRule[FunctionPrefixOffset]; - std::string functionIndex = mConstSelect.mSelectRule.substr(FunctionIndexOffset, 2); - int convertedIndex = -1; - - // Read in function index, form ## from 00 .. 73, skip leading zero - if (functionIndex[0] == '0') - functionIndex = functionIndex[1]; - - std::stringstream stream; - stream << functionIndex; - stream >> convertedIndex; - - switch (functionPrefix) - { - case '1': - if (convertedIndex >= 0 && convertedIndex <= 73) - mFunctionName = static_cast(convertedIndex); - else - mFunctionName = Function_None; - break; - - case '2': - mFunctionName = Function_Global; - break; - case '3': - mFunctionName = Function_Local; - break; - case '4': - mFunctionName = Function_Journal; - break; - case '5': - mFunctionName = Function_Item; - break; - case '6': - mFunctionName = Function_Dead; - break; - case '7': - mFunctionName = Function_NotId; - break; - case '8': - mFunctionName = Function_NotFaction; - break; - case '9': - mFunctionName = Function_NotClass; - break; - case 'A': - mFunctionName = Function_NotRace; - break; - case 'B': - mFunctionName = Function_NotCell; - break; - case 'C': - mFunctionName = Function_NotLocal; - break; - default: - mFunctionName = Function_None; - break; - } -} - -void CSMWorld::ConstInfoSelectWrapper::readRelationType() -{ - char relationIndex = mConstSelect.mSelectRule[RelationIndexOffset]; - - switch (relationIndex) - { - case '0': - mRelationType = Relation_Equal; - break; - case '1': - mRelationType = Relation_NotEqual; - break; - case '2': - mRelationType = Relation_Greater; - break; - case '3': - mRelationType = Relation_GreaterOrEqual; - break; - case '4': - mRelationType = Relation_Less; - break; - case '5': - mRelationType = Relation_LessOrEqual; - break; - default: - mRelationType = Relation_None; - } -} - -void CSMWorld::ConstInfoSelectWrapper::readVariableName() -{ - if (mConstSelect.mSelectRule.size() >= VarNameOffset) - mVariableName = mConstSelect.mSelectRule.substr(VarNameOffset); - else - mVariableName.clear(); -} - void CSMWorld::ConstInfoSelectWrapper::updateHasVariable() { - switch (mFunctionName) + switch (getFunctionName()) { - case Function_Global: - case Function_Local: - case Function_Journal: - case Function_Item: - case Function_Dead: - case Function_NotId: - case Function_NotFaction: - case Function_NotClass: - case Function_NotRace: - case Function_NotCell: - case Function_NotLocal: + case ESM::DialogueCondition::Function_Global: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_Journal: + case ESM::DialogueCondition::Function_Item: + case ESM::DialogueCondition::Function_Dead: + case ESM::DialogueCondition::Function_NotId: + case ESM::DialogueCondition::Function_NotFaction: + case ESM::DialogueCondition::Function_NotClass: + case ESM::DialogueCondition::Function_NotRace: + case ESM::DialogueCondition::Function_NotCell: + case ESM::DialogueCondition::Function_NotLocal: mHasVariable = true; break; @@ -399,103 +253,103 @@ void CSMWorld::ConstInfoSelectWrapper::updateHasVariable() void CSMWorld::ConstInfoSelectWrapper::updateComparisonType() { - switch (mFunctionName) + switch (getFunctionName()) { // Boolean - case Function_NotId: - case Function_NotFaction: - case Function_NotClass: - case Function_NotRace: - case Function_NotCell: - case Function_PcExpelled: - case Function_PcCommonDisease: - case Function_PcBlightDisease: - case Function_SameSex: - case Function_SameRace: - case Function_SameFaction: - case Function_Detected: - case Function_Alarmed: - case Function_PcCorpus: - case Function_PcVampire: - case Function_Attacked: - case Function_TalkedToPc: - case Function_ShouldAttack: - case Function_Werewolf: + case ESM::DialogueCondition::Function_NotId: + case ESM::DialogueCondition::Function_NotFaction: + case ESM::DialogueCondition::Function_NotClass: + case ESM::DialogueCondition::Function_NotRace: + case ESM::DialogueCondition::Function_NotCell: + case ESM::DialogueCondition::Function_PcExpelled: + case ESM::DialogueCondition::Function_PcCommonDisease: + case ESM::DialogueCondition::Function_PcBlightDisease: + case ESM::DialogueCondition::Function_SameSex: + case ESM::DialogueCondition::Function_SameRace: + case ESM::DialogueCondition::Function_SameFaction: + case ESM::DialogueCondition::Function_Detected: + case ESM::DialogueCondition::Function_Alarmed: + case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcVampire: + case ESM::DialogueCondition::Function_Attacked: + case ESM::DialogueCondition::Function_TalkedToPc: + case ESM::DialogueCondition::Function_ShouldAttack: + case ESM::DialogueCondition::Function_Werewolf: mComparisonType = Comparison_Boolean; break; // Integer - case Function_Journal: - case Function_Item: - case Function_Dead: - case Function_RankLow: - case Function_RankHigh: - case Function_RankRequirement: - case Function_Reputation: - case Function_PcReputation: - case Function_PcLevel: - case Function_PcStrength: - case Function_PcBlock: - case Function_PcArmorer: - case Function_PcMediumArmor: - case Function_PcHeavyArmor: - case Function_PcBluntWeapon: - case Function_PcLongBlade: - case Function_PcAxe: - case Function_PcSpear: - case Function_PcAthletics: - case Function_PcEnchant: - case Function_PcDestruction: - case Function_PcAlteration: - case Function_PcIllusion: - case Function_PcConjuration: - case Function_PcMysticism: - case Function_PcRestoration: - case Function_PcAlchemy: - case Function_PcUnarmored: - case Function_PcSecurity: - case Function_PcSneak: - case Function_PcAcrobatics: - case Function_PcLightArmor: - case Function_PcShortBlade: - case Function_PcMarksman: - case Function_PcMerchantile: - case Function_PcSpeechcraft: - case Function_PcHandToHand: - case Function_PcGender: - case Function_PcClothingModifier: - case Function_PcCrimeLevel: - case Function_FactionRankDifference: - case Function_Choice: - case Function_PcIntelligence: - case Function_PcWillpower: - case Function_PcAgility: - case Function_PcSpeed: - case Function_PcEndurance: - case Function_PcPersonality: - case Function_PcLuck: - case Function_Weather: - case Function_Level: - case Function_CreatureTarget: - case Function_FriendHit: - case Function_Fight: - case Function_Hello: - case Function_Alarm: - case Function_Flee: - case Function_PcWerewolfKills: + case ESM::DialogueCondition::Function_Journal: + case ESM::DialogueCondition::Function_Item: + case ESM::DialogueCondition::Function_Dead: + case ESM::DialogueCondition::Function_FacReactionLowest: + case ESM::DialogueCondition::Function_FacReactionHighest: + case ESM::DialogueCondition::Function_RankRequirement: + case ESM::DialogueCondition::Function_Reputation: + case ESM::DialogueCondition::Function_PcReputation: + case ESM::DialogueCondition::Function_PcLevel: + case ESM::DialogueCondition::Function_PcStrength: + case ESM::DialogueCondition::Function_PcBlock: + case ESM::DialogueCondition::Function_PcArmorer: + case ESM::DialogueCondition::Function_PcMediumArmor: + case ESM::DialogueCondition::Function_PcHeavyArmor: + case ESM::DialogueCondition::Function_PcBluntWeapon: + case ESM::DialogueCondition::Function_PcLongBlade: + case ESM::DialogueCondition::Function_PcAxe: + case ESM::DialogueCondition::Function_PcSpear: + case ESM::DialogueCondition::Function_PcAthletics: + case ESM::DialogueCondition::Function_PcEnchant: + case ESM::DialogueCondition::Function_PcDestruction: + case ESM::DialogueCondition::Function_PcAlteration: + case ESM::DialogueCondition::Function_PcIllusion: + case ESM::DialogueCondition::Function_PcConjuration: + case ESM::DialogueCondition::Function_PcMysticism: + case ESM::DialogueCondition::Function_PcRestoration: + case ESM::DialogueCondition::Function_PcAlchemy: + case ESM::DialogueCondition::Function_PcUnarmored: + case ESM::DialogueCondition::Function_PcSecurity: + case ESM::DialogueCondition::Function_PcSneak: + case ESM::DialogueCondition::Function_PcAcrobatics: + case ESM::DialogueCondition::Function_PcLightArmor: + case ESM::DialogueCondition::Function_PcShortBlade: + case ESM::DialogueCondition::Function_PcMarksman: + case ESM::DialogueCondition::Function_PcMerchantile: + case ESM::DialogueCondition::Function_PcSpeechcraft: + case ESM::DialogueCondition::Function_PcHandToHand: + case ESM::DialogueCondition::Function_PcGender: + case ESM::DialogueCondition::Function_PcClothingModifier: + case ESM::DialogueCondition::Function_PcCrimeLevel: + case ESM::DialogueCondition::Function_FactionRankDifference: + case ESM::DialogueCondition::Function_Choice: + case ESM::DialogueCondition::Function_PcIntelligence: + case ESM::DialogueCondition::Function_PcWillpower: + case ESM::DialogueCondition::Function_PcAgility: + case ESM::DialogueCondition::Function_PcSpeed: + case ESM::DialogueCondition::Function_PcEndurance: + case ESM::DialogueCondition::Function_PcPersonality: + case ESM::DialogueCondition::Function_PcLuck: + case ESM::DialogueCondition::Function_Weather: + case ESM::DialogueCondition::Function_Level: + case ESM::DialogueCondition::Function_CreatureTarget: + case ESM::DialogueCondition::Function_FriendHit: + case ESM::DialogueCondition::Function_Fight: + case ESM::DialogueCondition::Function_Hello: + case ESM::DialogueCondition::Function_Alarm: + case ESM::DialogueCondition::Function_Flee: + case ESM::DialogueCondition::Function_PcWerewolfKills: mComparisonType = Comparison_Integer; break; // Numeric - case Function_Global: - case Function_Local: - case Function_NotLocal: + case ESM::DialogueCondition::Function_Global: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_NotLocal: - case Function_Health_Percent: - case Function_PcHealthPercent: - case Function_PcMagicka: - case Function_PcFatigue: - case Function_PcHealth: + case ESM::DialogueCondition::Function_Health_Percent: + case ESM::DialogueCondition::Function_PcHealthPercent: + case ESM::DialogueCondition::Function_PcMagicka: + case ESM::DialogueCondition::Function_PcFatigue: + case ESM::DialogueCondition::Function_PcHealth: mComparisonType = Comparison_Numeric; break; @@ -511,15 +365,15 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getConditionIntRange() con const int IntMin = std::numeric_limits::min(); const std::pair InvalidRange(IntMax, IntMin); - int value = mConstSelect.mValue.getInteger(); + int value = std::get(mConstSelect.mValue); - switch (mRelationType) + switch (getRelationType()) { - case Relation_Equal: - case Relation_NotEqual: + case ESM::DialogueCondition::Comp_Eq: + case ESM::DialogueCondition::Comp_Ne: return std::pair(value, value); - case Relation_Greater: + case ESM::DialogueCondition::Comp_Gt: if (value == IntMax) { return InvalidRange; @@ -530,10 +384,10 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getConditionIntRange() con } break; - case Relation_GreaterOrEqual: + case ESM::DialogueCondition::Comp_Ge: return std::pair(value, IntMax); - case Relation_Less: + case ESM::DialogueCondition::Comp_Ls: if (value == IntMin) { return InvalidRange; @@ -543,7 +397,7 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getConditionIntRange() con return std::pair(IntMin, value - 1); } - case Relation_LessOrEqual: + case ESM::DialogueCondition::Comp_Le: return std::pair(IntMin, value); default: @@ -557,24 +411,24 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getConditionFloatRange const float FloatMin = -std::numeric_limits::infinity(); const float Epsilon = std::numeric_limits::epsilon(); - float value = mConstSelect.mValue.getFloat(); + float value = std::get(mConstSelect.mValue); - switch (mRelationType) + switch (getRelationType()) { - case Relation_Equal: - case Relation_NotEqual: + case ESM::DialogueCondition::Comp_Eq: + case ESM::DialogueCondition::Comp_Ne: return std::pair(value, value); - case Relation_Greater: + case ESM::DialogueCondition::Comp_Gt: return std::pair(value + Epsilon, FloatMax); - case Relation_GreaterOrEqual: + case ESM::DialogueCondition::Comp_Ge: return std::pair(value, FloatMax); - case Relation_Less: + case ESM::DialogueCondition::Comp_Ls: return std::pair(FloatMin, value - Epsilon); - case Relation_LessOrEqual: + case ESM::DialogueCondition::Comp_Le: return std::pair(FloatMin, value); default: @@ -587,120 +441,120 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getValidIntRange() const const int IntMax = std::numeric_limits::max(); const int IntMin = std::numeric_limits::min(); - switch (mFunctionName) + switch (getFunctionName()) { // Boolean - case Function_NotId: - case Function_NotFaction: - case Function_NotClass: - case Function_NotRace: - case Function_NotCell: - case Function_PcExpelled: - case Function_PcCommonDisease: - case Function_PcBlightDisease: - case Function_SameSex: - case Function_SameRace: - case Function_SameFaction: - case Function_Detected: - case Function_Alarmed: - case Function_PcCorpus: - case Function_PcVampire: - case Function_Attacked: - case Function_TalkedToPc: - case Function_ShouldAttack: - case Function_Werewolf: + case ESM::DialogueCondition::Function_NotId: + case ESM::DialogueCondition::Function_NotFaction: + case ESM::DialogueCondition::Function_NotClass: + case ESM::DialogueCondition::Function_NotRace: + case ESM::DialogueCondition::Function_NotCell: + case ESM::DialogueCondition::Function_PcExpelled: + case ESM::DialogueCondition::Function_PcCommonDisease: + case ESM::DialogueCondition::Function_PcBlightDisease: + case ESM::DialogueCondition::Function_SameSex: + case ESM::DialogueCondition::Function_SameRace: + case ESM::DialogueCondition::Function_SameFaction: + case ESM::DialogueCondition::Function_Detected: + case ESM::DialogueCondition::Function_Alarmed: + case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcVampire: + case ESM::DialogueCondition::Function_Attacked: + case ESM::DialogueCondition::Function_TalkedToPc: + case ESM::DialogueCondition::Function_ShouldAttack: + case ESM::DialogueCondition::Function_Werewolf: return std::pair(0, 1); // Integer - case Function_RankLow: - case Function_RankHigh: - case Function_Reputation: - case Function_PcReputation: - case Function_Journal: + case ESM::DialogueCondition::Function_FacReactionLowest: + case ESM::DialogueCondition::Function_FacReactionHighest: + case ESM::DialogueCondition::Function_Reputation: + case ESM::DialogueCondition::Function_PcReputation: + case ESM::DialogueCondition::Function_Journal: return std::pair(IntMin, IntMax); - case Function_Item: - case Function_Dead: - case Function_PcLevel: - case Function_PcStrength: - case Function_PcBlock: - case Function_PcArmorer: - case Function_PcMediumArmor: - case Function_PcHeavyArmor: - case Function_PcBluntWeapon: - case Function_PcLongBlade: - case Function_PcAxe: - case Function_PcSpear: - case Function_PcAthletics: - case Function_PcEnchant: - case Function_PcDestruction: - case Function_PcAlteration: - case Function_PcIllusion: - case Function_PcConjuration: - case Function_PcMysticism: - case Function_PcRestoration: - case Function_PcAlchemy: - case Function_PcUnarmored: - case Function_PcSecurity: - case Function_PcSneak: - case Function_PcAcrobatics: - case Function_PcLightArmor: - case Function_PcShortBlade: - case Function_PcMarksman: - case Function_PcMerchantile: - case Function_PcSpeechcraft: - case Function_PcHandToHand: - case Function_PcClothingModifier: - case Function_PcCrimeLevel: - case Function_Choice: - case Function_PcIntelligence: - case Function_PcWillpower: - case Function_PcAgility: - case Function_PcSpeed: - case Function_PcEndurance: - case Function_PcPersonality: - case Function_PcLuck: - case Function_Level: - case Function_PcWerewolfKills: + case ESM::DialogueCondition::Function_Item: + case ESM::DialogueCondition::Function_Dead: + case ESM::DialogueCondition::Function_PcLevel: + case ESM::DialogueCondition::Function_PcStrength: + case ESM::DialogueCondition::Function_PcBlock: + case ESM::DialogueCondition::Function_PcArmorer: + case ESM::DialogueCondition::Function_PcMediumArmor: + case ESM::DialogueCondition::Function_PcHeavyArmor: + case ESM::DialogueCondition::Function_PcBluntWeapon: + case ESM::DialogueCondition::Function_PcLongBlade: + case ESM::DialogueCondition::Function_PcAxe: + case ESM::DialogueCondition::Function_PcSpear: + case ESM::DialogueCondition::Function_PcAthletics: + case ESM::DialogueCondition::Function_PcEnchant: + case ESM::DialogueCondition::Function_PcDestruction: + case ESM::DialogueCondition::Function_PcAlteration: + case ESM::DialogueCondition::Function_PcIllusion: + case ESM::DialogueCondition::Function_PcConjuration: + case ESM::DialogueCondition::Function_PcMysticism: + case ESM::DialogueCondition::Function_PcRestoration: + case ESM::DialogueCondition::Function_PcAlchemy: + case ESM::DialogueCondition::Function_PcUnarmored: + case ESM::DialogueCondition::Function_PcSecurity: + case ESM::DialogueCondition::Function_PcSneak: + case ESM::DialogueCondition::Function_PcAcrobatics: + case ESM::DialogueCondition::Function_PcLightArmor: + case ESM::DialogueCondition::Function_PcShortBlade: + case ESM::DialogueCondition::Function_PcMarksman: + case ESM::DialogueCondition::Function_PcMerchantile: + case ESM::DialogueCondition::Function_PcSpeechcraft: + case ESM::DialogueCondition::Function_PcHandToHand: + case ESM::DialogueCondition::Function_PcClothingModifier: + case ESM::DialogueCondition::Function_PcCrimeLevel: + case ESM::DialogueCondition::Function_Choice: + case ESM::DialogueCondition::Function_PcIntelligence: + case ESM::DialogueCondition::Function_PcWillpower: + case ESM::DialogueCondition::Function_PcAgility: + case ESM::DialogueCondition::Function_PcSpeed: + case ESM::DialogueCondition::Function_PcEndurance: + case ESM::DialogueCondition::Function_PcPersonality: + case ESM::DialogueCondition::Function_PcLuck: + case ESM::DialogueCondition::Function_Level: + case ESM::DialogueCondition::Function_PcWerewolfKills: return std::pair(0, IntMax); - case Function_Fight: - case Function_Hello: - case Function_Alarm: - case Function_Flee: + case ESM::DialogueCondition::Function_Fight: + case ESM::DialogueCondition::Function_Hello: + case ESM::DialogueCondition::Function_Alarm: + case ESM::DialogueCondition::Function_Flee: return std::pair(0, 100); - case Function_Weather: + case ESM::DialogueCondition::Function_Weather: return std::pair(0, 9); - case Function_FriendHit: + case ESM::DialogueCondition::Function_FriendHit: return std::pair(0, 4); - case Function_RankRequirement: + case ESM::DialogueCondition::Function_RankRequirement: return std::pair(0, 3); - case Function_CreatureTarget: + case ESM::DialogueCondition::Function_CreatureTarget: return std::pair(0, 2); - case Function_PcGender: + case ESM::DialogueCondition::Function_PcGender: return std::pair(0, 1); - case Function_FactionRankDifference: + case ESM::DialogueCondition::Function_FactionRankDifference: return std::pair(-9, 9); // Numeric - case Function_Global: - case Function_Local: - case Function_NotLocal: + case ESM::DialogueCondition::Function_Global: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_NotLocal: return std::pair(IntMin, IntMax); - case Function_PcMagicka: - case Function_PcFatigue: - case Function_PcHealth: + case ESM::DialogueCondition::Function_PcMagicka: + case ESM::DialogueCondition::Function_PcFatigue: + case ESM::DialogueCondition::Function_PcHealth: return std::pair(0, IntMax); - case Function_Health_Percent: - case Function_PcHealthPercent: + case ESM::DialogueCondition::Function_Health_Percent: + case ESM::DialogueCondition::Function_PcHealthPercent: return std::pair(0, 100); default: @@ -713,21 +567,21 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getValidFloatRange() c const float FloatMax = std::numeric_limits::infinity(); const float FloatMin = -std::numeric_limits::infinity(); - switch (mFunctionName) + switch (getFunctionName()) { // Numeric - case Function_Global: - case Function_Local: - case Function_NotLocal: + case ESM::DialogueCondition::Function_Global: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_NotLocal: return std::pair(FloatMin, FloatMax); - case Function_PcMagicka: - case Function_PcFatigue: - case Function_PcHealth: + case ESM::DialogueCondition::Function_PcMagicka: + case ESM::DialogueCondition::Function_PcFatigue: + case ESM::DialogueCondition::Function_PcHealth: return std::pair(0, FloatMax); - case Function_Health_Percent: - case Function_PcHealthPercent: + case ESM::DialogueCondition::Function_Health_Percent: + case ESM::DialogueCondition::Function_PcHealthPercent: return std::pair(0, 100); default: @@ -768,19 +622,19 @@ template bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue( std::pair conditionRange, std::pair validRange) const { - switch (mRelationType) + switch (getRelationType()) { - case Relation_Equal: + case ESM::DialogueCondition::Comp_Eq: return false; - case Relation_NotEqual: + case ESM::DialogueCondition::Comp_Ne: // If value is not within range, it will always be true return !rangeContains(conditionRange.first, validRange); - case Relation_Greater: - case Relation_GreaterOrEqual: - case Relation_Less: - case Relation_LessOrEqual: + case ESM::DialogueCondition::Comp_Gt: + case ESM::DialogueCondition::Comp_Ge: + case ESM::DialogueCondition::Comp_Ls: + case ESM::DialogueCondition::Comp_Le: // If the valid range is completely within the condition range, it will always be true return rangeFullyContains(conditionRange, validRange); @@ -795,18 +649,18 @@ template bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue( std::pair conditionRange, std::pair validRange) const { - switch (mRelationType) + switch (getRelationType()) { - case Relation_Equal: + case ESM::DialogueCondition::Comp_Eq: return !rangeContains(conditionRange.first, validRange); - case Relation_NotEqual: + case ESM::DialogueCondition::Comp_Ne: return false; - case Relation_Greater: - case Relation_GreaterOrEqual: - case Relation_Less: - case Relation_LessOrEqual: + case ESM::DialogueCondition::Comp_Gt: + case ESM::DialogueCondition::Comp_Ge: + case ESM::DialogueCondition::Comp_Ls: + case ESM::DialogueCondition::Comp_Le: // If ranges do not overlap, it will never be true return !rangesOverlap(conditionRange, validRange); @@ -817,153 +671,47 @@ bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue( return false; } +QVariant CSMWorld::ConstInfoSelectWrapper::getValue() const +{ + return std::visit([](auto value) { return QVariant(value); }, mConstSelect.mValue); +} + // InfoSelectWrapper -CSMWorld::InfoSelectWrapper::InfoSelectWrapper(ESM::DialInfo::SelectStruct& select) +CSMWorld::InfoSelectWrapper::InfoSelectWrapper(ESM::DialogueCondition& select) : CSMWorld::ConstInfoSelectWrapper(select) , mSelect(select) { } -void CSMWorld::InfoSelectWrapper::setFunctionName(FunctionName name) +void CSMWorld::InfoSelectWrapper::setFunctionName(ESM::DialogueCondition::Function name) { - mFunctionName = name; + mSelect.mFunction = name; updateHasVariable(); updateComparisonType(); + if (getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric + && std::holds_alternative(mSelect.mValue)) + { + mSelect.mValue = std::visit([](auto value) { return static_cast(value); }, mSelect.mValue); + } } -void CSMWorld::InfoSelectWrapper::setRelationType(RelationType type) +void CSMWorld::InfoSelectWrapper::setRelationType(ESM::DialogueCondition::Comparison type) { - mRelationType = type; + mSelect.mComparison = type; } void CSMWorld::InfoSelectWrapper::setVariableName(const std::string& name) { - mVariableName = name; + mSelect.mVariable = name; } -void CSMWorld::InfoSelectWrapper::setDefaults() +void CSMWorld::InfoSelectWrapper::setValue(int value) { - if (!variantTypeIsValid()) - mSelect.mValue.setType(ESM::VT_Int); - - switch (mComparisonType) - { - case Comparison_Boolean: - setRelationType(Relation_Equal); - mSelect.mValue.setInteger(1); - break; - - case Comparison_Integer: - case Comparison_Numeric: - setRelationType(Relation_Greater); - mSelect.mValue.setInteger(0); - break; - - default: - // Do nothing - break; - } - - update(); + mSelect.mValue = value; } -void CSMWorld::InfoSelectWrapper::update() +void CSMWorld::InfoSelectWrapper::setValue(float value) { - std::ostringstream stream; - - // Leading 0 - stream << '0'; - - // Write Function - - bool writeIndex = false; - size_t functionIndex = static_cast(mFunctionName); - - switch (mFunctionName) - { - case Function_None: - stream << '0'; - break; - case Function_Global: - stream << '2'; - break; - case Function_Local: - stream << '3'; - break; - case Function_Journal: - stream << '4'; - break; - case Function_Item: - stream << '5'; - break; - case Function_Dead: - stream << '6'; - break; - case Function_NotId: - stream << '7'; - break; - case Function_NotFaction: - stream << '8'; - break; - case Function_NotClass: - stream << '9'; - break; - case Function_NotRace: - stream << 'A'; - break; - case Function_NotCell: - stream << 'B'; - break; - case Function_NotLocal: - stream << 'C'; - break; - default: - stream << '1'; - writeIndex = true; - break; - } - - if (writeIndex && functionIndex < 10) // leading 0 - stream << '0' << functionIndex; - else if (writeIndex) - stream << functionIndex; - else - stream << "00"; - - // Write Relation - switch (mRelationType) - { - case Relation_Equal: - stream << '0'; - break; - case Relation_NotEqual: - stream << '1'; - break; - case Relation_Greater: - stream << '2'; - break; - case Relation_GreaterOrEqual: - stream << '3'; - break; - case Relation_Less: - stream << '4'; - break; - case Relation_LessOrEqual: - stream << '5'; - break; - default: - stream << '0'; - break; - } - - if (mHasVariable) - stream << mVariableName; - - mSelect.mSelectRule = stream.str(); -} - -ESM::Variant& CSMWorld::InfoSelectWrapper::getVariant() -{ - return mSelect.mValue; + mSelect.mValue = value; } diff --git a/apps/opencs/model/world/infoselectwrapper.hpp b/apps/opencs/model/world/infoselectwrapper.hpp index 4ecdc676dc..d8d108444f 100644 --- a/apps/opencs/model/world/infoselectwrapper.hpp +++ b/apps/opencs/model/world/infoselectwrapper.hpp @@ -7,133 +7,13 @@ #include -namespace ESM -{ - class Variant; -} +#include namespace CSMWorld { - // ESM::DialInfo::SelectStruct.mSelectRule - // 012345... - // ^^^ ^^ - // ||| || - // ||| |+------------- condition variable string - // ||| +-------------- comparison type, ['0'..'5']; e.g. !=, <, >=, etc - // ||+---------------- function index (encoded, where function == '1') - // |+----------------- function, ['1'..'C']; e.g. Global, Local, Not ID, etc - // +------------------ unknown - // - - // Wrapper for DialInfo::SelectStruct class ConstInfoSelectWrapper { public: - // Order matters - enum FunctionName - { - Function_RankLow = 0, - Function_RankHigh, - Function_RankRequirement, - Function_Reputation, - Function_Health_Percent, - Function_PcReputation, - Function_PcLevel, - Function_PcHealthPercent, - Function_PcMagicka, - Function_PcFatigue, - Function_PcStrength, - Function_PcBlock, - Function_PcArmorer, - Function_PcMediumArmor, - Function_PcHeavyArmor, - Function_PcBluntWeapon, - Function_PcLongBlade, - Function_PcAxe, - Function_PcSpear, - Function_PcAthletics, - Function_PcEnchant, - Function_PcDestruction, - Function_PcAlteration, - Function_PcIllusion, - Function_PcConjuration, - Function_PcMysticism, - Function_PcRestoration, - Function_PcAlchemy, - Function_PcUnarmored, - Function_PcSecurity, - Function_PcSneak, - Function_PcAcrobatics, - Function_PcLightArmor, - Function_PcShortBlade, - Function_PcMarksman, - Function_PcMerchantile, - Function_PcSpeechcraft, - Function_PcHandToHand, - Function_PcGender, - Function_PcExpelled, - Function_PcCommonDisease, - Function_PcBlightDisease, - Function_PcClothingModifier, - Function_PcCrimeLevel, - Function_SameSex, - Function_SameRace, - Function_SameFaction, - Function_FactionRankDifference, - Function_Detected, - Function_Alarmed, - Function_Choice, - Function_PcIntelligence, - Function_PcWillpower, - Function_PcAgility, - Function_PcSpeed, - Function_PcEndurance, - Function_PcPersonality, - Function_PcLuck, - Function_PcCorpus, - Function_Weather, - Function_PcVampire, - Function_Level, - Function_Attacked, - Function_TalkedToPc, - Function_PcHealth, - Function_CreatureTarget, - Function_FriendHit, - Function_Fight, - Function_Hello, - Function_Alarm, - Function_Flee, - Function_ShouldAttack, - Function_Werewolf, - Function_PcWerewolfKills = 73, - - Function_Global, - Function_Local, - Function_Journal, - Function_Item, - Function_Dead, - Function_NotId, - Function_NotFaction, - Function_NotClass, - Function_NotRace, - Function_NotCell, - Function_NotLocal, - - Function_None - }; - - enum RelationType - { - Relation_Equal, - Relation_NotEqual, - Relation_Greater, - Relation_GreaterOrEqual, - Relation_Less, - Relation_LessOrEqual, - - Relation_None - }; - enum ComparisonType { Comparison_Boolean, @@ -143,25 +23,18 @@ namespace CSMWorld Comparison_None }; - static const size_t RuleMinSize; - - static const size_t FunctionPrefixOffset; - static const size_t FunctionIndexOffset; - static const size_t RelationIndexOffset; - static const size_t VarNameOffset; - static const char* FunctionEnumStrings[]; static const char* RelationEnumStrings[]; static const char* ComparisonEnumStrings[]; - static std::string convertToString(FunctionName name); - static std::string convertToString(RelationType type); + static std::string convertToString(ESM::DialogueCondition::Function name); + static std::string convertToString(ESM::DialogueCondition::Comparison type); static std::string convertToString(ComparisonType type); - ConstInfoSelectWrapper(const ESM::DialInfo::SelectStruct& select); + ConstInfoSelectWrapper(const ESM::DialogueCondition& select); - FunctionName getFunctionName() const; - RelationType getRelationType() const; + ESM::DialogueCondition::Function getFunctionName() const; + ESM::DialogueCondition::Comparison getRelationType() const; ComparisonType getComparisonType() const; bool hasVariable() const; @@ -169,17 +42,12 @@ namespace CSMWorld bool conditionIsAlwaysTrue() const; bool conditionIsNeverTrue() const; - bool variantTypeIsValid() const; - const ESM::Variant& getVariant() const; + QVariant getValue() const; std::string toString() const; protected: - void readRule(); - void readFunctionName(); - void readRelationType(); - void readVariableName(); void updateHasVariable(); void updateComparisonType(); @@ -207,38 +75,29 @@ namespace CSMWorld template bool conditionIsNeverTrue(std::pair conditionRange, std::pair validRange) const; - FunctionName mFunctionName; - RelationType mRelationType; ComparisonType mComparisonType; bool mHasVariable; - std::string mVariableName; private: - const ESM::DialInfo::SelectStruct& mConstSelect; + const ESM::DialogueCondition& mConstSelect; }; - // Wrapper for DialInfo::SelectStruct that can modify the wrapped select struct + // Wrapper for DialogueCondition that can modify the wrapped select struct class InfoSelectWrapper : public ConstInfoSelectWrapper { public: - InfoSelectWrapper(ESM::DialInfo::SelectStruct& select); + InfoSelectWrapper(ESM::DialogueCondition& select); // Wrapped SelectStruct will not be modified until update() is called - void setFunctionName(FunctionName name); - void setRelationType(RelationType type); + void setFunctionName(ESM::DialogueCondition::Function name); + void setRelationType(ESM::DialogueCondition::Comparison type); void setVariableName(const std::string& name); - - // Modified wrapped SelectStruct - void update(); - - // This sets properties based on the function name to its defaults and updates the wrapped object - void setDefaults(); - - ESM::Variant& getVariant(); + void setValue(int value); + void setValue(float value); private: - ESM::DialInfo::SelectStruct& mSelect; + ESM::DialogueCondition& mSelect; void writeRule(); }; diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 0d90ea0d68..86d38f9cd2 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -538,13 +538,11 @@ namespace CSMWorld { Info info = record.get(); - std::vector& conditions = info.mSelects; + auto& conditions = info.mSelects; // default row - ESM::DialInfo::SelectStruct condStruct; - condStruct.mSelectRule = "01000"; - condStruct.mValue = ESM::Variant(); - condStruct.mValue.setType(ESM::VT_Int); + ESM::DialogueCondition condStruct; + condStruct.mIndex = conditions.size(); conditions.insert(conditions.begin() + position, condStruct); @@ -555,7 +553,7 @@ namespace CSMWorld { Info info = record.get(); - std::vector& conditions = info.mSelects; + auto& conditions = info.mSelects; if (rowToRemove < 0 || rowToRemove >= static_cast(conditions.size())) throw std::runtime_error("index out of range"); @@ -569,8 +567,8 @@ namespace CSMWorld { Info info = record.get(); - info.mSelects = static_cast>&>(nestedTable) - .mNestedTable; + info.mSelects + = static_cast>&>(nestedTable).mNestedTable; record.setModified(info); } @@ -578,14 +576,14 @@ namespace CSMWorld NestedTableWrapperBase* InfoConditionAdapter::table(const Record& record) const { // deleted by dtor of NestedTableStoring - return new NestedTableWrapper>(record.get().mSelects); + return new NestedTableWrapper>(record.get().mSelects); } QVariant InfoConditionAdapter::getData(const Record& record, int subRowIndex, int subColIndex) const { Info info = record.get(); - std::vector& conditions = info.mSelects; + auto& conditions = info.mSelects; if (subRowIndex < 0 || subRowIndex >= static_cast(conditions.size())) throw std::runtime_error("index out of range"); @@ -611,19 +609,7 @@ namespace CSMWorld } case 3: { - switch (infoSelectWrapper.getVariant().getType()) - { - case ESM::VT_Int: - { - return infoSelectWrapper.getVariant().getInteger(); - } - case ESM::VT_Float: - { - return infoSelectWrapper.getVariant().getFloat(); - } - default: - return QVariant(); - } + return infoSelectWrapper.getValue(); } default: throw std::runtime_error("Info condition subcolumn index out of range"); @@ -635,7 +621,7 @@ namespace CSMWorld { Info info = record.get(); - std::vector& conditions = info.mSelects; + auto& conditions = info.mSelects; if (subRowIndex < 0 || subRowIndex >= static_cast(conditions.size())) throw std::runtime_error("index out of range"); @@ -647,27 +633,17 @@ namespace CSMWorld { case 0: // Function { - infoSelectWrapper.setFunctionName(static_cast(value.toInt())); - - if (infoSelectWrapper.getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric - && infoSelectWrapper.getVariant().getType() != ESM::VT_Int) - { - infoSelectWrapper.getVariant().setType(ESM::VT_Int); - } - - infoSelectWrapper.update(); + infoSelectWrapper.setFunctionName(static_cast(value.toInt())); break; } case 1: // Variable { infoSelectWrapper.setVariableName(value.toString().toUtf8().constData()); - infoSelectWrapper.update(); break; } case 2: // Relation { - infoSelectWrapper.setRelationType(static_cast(value.toInt())); - infoSelectWrapper.update(); + infoSelectWrapper.setRelationType(static_cast(value.toInt())); break; } case 3: // Value @@ -679,13 +655,11 @@ namespace CSMWorld // QVariant seems to have issues converting 0 if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0) { - infoSelectWrapper.getVariant().setType(ESM::VT_Int); - infoSelectWrapper.getVariant().setInteger(value.toInt()); + infoSelectWrapper.setValue(value.toInt()); } else if (value.toFloat(&conversionResult) && conversionResult) { - infoSelectWrapper.getVariant().setType(ESM::VT_Float); - infoSelectWrapper.getVariant().setFloat(value.toFloat()); + infoSelectWrapper.setValue(value.toFloat()); } break; } @@ -694,8 +668,7 @@ namespace CSMWorld { if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0) { - infoSelectWrapper.getVariant().setType(ESM::VT_Int); - infoSelectWrapper.getVariant().setInteger(value.toInt()); + infoSelectWrapper.setValue(value.toInt()); } break; } diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 3e26ed9250..e39be392f4 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -46,41 +46,41 @@ QWidget* CSVWorld::IdCompletionDelegate::createEditor(QWidget* parent, const QSt switch (conditionFunction) { - case CSMWorld::ConstInfoSelectWrapper::Function_Global: + case ESM::DialogueCondition::Function_Global: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_GlobalVariable); } - case CSMWorld::ConstInfoSelectWrapper::Function_Journal: + case ESM::DialogueCondition::Function_Journal: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Journal); } - case CSMWorld::ConstInfoSelectWrapper::Function_Item: + case ESM::DialogueCondition::Function_Item: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable); } - case CSMWorld::ConstInfoSelectWrapper::Function_Dead: - case CSMWorld::ConstInfoSelectWrapper::Function_NotId: + case ESM::DialogueCondition::Function_Dead: + case ESM::DialogueCondition::Function_NotId: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable); } - case CSMWorld::ConstInfoSelectWrapper::Function_NotFaction: + case ESM::DialogueCondition::Function_NotFaction: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Faction); } - case CSMWorld::ConstInfoSelectWrapper::Function_NotClass: + case ESM::DialogueCondition::Function_NotClass: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Class); } - case CSMWorld::ConstInfoSelectWrapper::Function_NotRace: + case ESM::DialogueCondition::Function_NotRace: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Race); } - case CSMWorld::ConstInfoSelectWrapper::Function_NotCell: + case ESM::DialogueCondition::Function_NotCell: { return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Cell); } - case CSMWorld::ConstInfoSelectWrapper::Function_Local: - case CSMWorld::ConstInfoSelectWrapper::Function_NotLocal: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_NotLocal: { return new CSVWidget::DropLineEdit(display, parent); } diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 2693811357..acf87ccc61 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -31,15 +31,15 @@ namespace bool matchesStaticFilters(const MWDialogue::SelectWrapper& select, const MWWorld::Ptr& actor) { const ESM::RefId selectId = select.getId(); - if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotId) + if (select.getFunction() == ESM::DialogueCondition::Function_NotId) return actor.getCellRef().getRefId() != selectId; if (actor.getClass().isNpc()) { - if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotFaction) + if (select.getFunction() == ESM::DialogueCondition::Function_NotFaction) return actor.getClass().getPrimaryFaction(actor) != selectId; - else if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotClass) + else if (select.getFunction() == ESM::DialogueCondition::Function_NotClass) return actor.get()->mBase->mClass != selectId; - else if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotRace) + else if (select.getFunction() == ESM::DialogueCondition::Function_NotRace) return actor.get()->mBase->mRace != selectId; } return true; @@ -47,7 +47,7 @@ namespace bool matchesStaticFilters(const ESM::DialInfo& info, const MWWorld::Ptr& actor) { - for (const ESM::DialInfo::SelectStruct& select : info.mSelects) + for (const auto& select : info.mSelects) { MWDialogue::SelectWrapper wrapper = select; if (wrapper.getType() == MWDialogue::SelectWrapper::Type_Boolean) @@ -62,7 +62,7 @@ namespace } else if (wrapper.getType() == MWDialogue::SelectWrapper::Type_Numeric) { - if (wrapper.getFunction() == MWDialogue::SelectWrapper::Function_Local) + if (wrapper.getFunction() == ESM::DialogueCondition::Function_Local) { const ESM::RefId& scriptName = actor.getClass().getScript(actor); if (scriptName.empty()) @@ -207,9 +207,8 @@ bool MWDialogue::Filter::testPlayer(const ESM::DialInfo& info) const bool MWDialogue::Filter::testSelectStructs(const ESM::DialInfo& info) const { - for (std::vector::const_iterator iter(info.mSelects.begin()); - iter != info.mSelects.end(); ++iter) - if (!testSelectStruct(*iter)) + for (const auto& select : info.mSelects) + if (!testSelectStruct(select)) return false; return true; @@ -270,11 +269,11 @@ bool MWDialogue::Filter::testSelectStruct(const SelectWrapper& select) const // If the actor is a creature, we pass all conditions only applicable to NPCs. return true; - if (select.getFunction() == SelectWrapper::Function_Choice && mChoice == -1) + if (select.getFunction() == ESM::DialogueCondition::Function_Choice && mChoice == -1) // If not currently in a choice, we reject all conditions that test against choices. return false; - if (select.getFunction() == SelectWrapper::Function_Weather + if (select.getFunction() == ESM::DialogueCondition::Function_Weather && !(MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior())) // Reject weather conditions in interior cells @@ -305,29 +304,31 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co { switch (select.getFunction()) { - case SelectWrapper::Function_Global: + case ESM::DialogueCondition::Function_Global: // internally all globals are float :( return select.selectCompare(MWBase::Environment::get().getWorld()->getGlobalFloat(select.getName())); - case SelectWrapper::Function_Local: + case ESM::DialogueCondition::Function_Local: { return testFunctionLocal(select); } - case SelectWrapper::Function_NotLocal: + case ESM::DialogueCondition::Function_NotLocal: { return !testFunctionLocal(select); } - case SelectWrapper::Function_PcHealthPercent: + case ESM::DialogueCondition::Function_PcHealthPercent: { MWWorld::Ptr player = MWMechanics::getPlayer(); return select.selectCompare( static_cast(player.getClass().getCreatureStats(player).getHealth().getRatio() * 100)); } - case SelectWrapper::Function_PcDynamicStat: + case ESM::DialogueCondition::Function_PcMagicka: + case ESM::DialogueCondition::Function_PcFatigue: + case ESM::DialogueCondition::Function_PcHealth: { MWWorld::Ptr player = MWMechanics::getPlayer(); @@ -336,7 +337,7 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co return select.selectCompare(value); } - case SelectWrapper::Function_HealthPercent: + case ESM::DialogueCondition::Function_Health_Percent: { return select.selectCompare( static_cast(mActor.getClass().getCreatureStats(mActor).getHealth().getRatio() * 100)); @@ -354,26 +355,29 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons switch (select.getFunction()) { - case SelectWrapper::Function_Journal: + case ESM::DialogueCondition::Function_Journal: return MWBase::Environment::get().getJournal()->getJournalIndex(select.getId()); - case SelectWrapper::Function_Item: + case ESM::DialogueCondition::Function_Item: { MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); return store.count(select.getId()); } - case SelectWrapper::Function_Dead: + case ESM::DialogueCondition::Function_Dead: return MWBase::Environment::get().getMechanicsManager()->countDeaths(select.getId()); - case SelectWrapper::Function_Choice: + case ESM::DialogueCondition::Function_Choice: return mChoice; - case SelectWrapper::Function_AiSetting: + case ESM::DialogueCondition::Function_Fight: + case ESM::DialogueCondition::Function_Hello: + case ESM::DialogueCondition::Function_Alarm: + case ESM::DialogueCondition::Function_Flee: { int argument = select.getArgument(); if (argument < 0 || argument > 3) @@ -386,32 +390,65 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons .getAiSetting(static_cast(argument)) .getModified(false); } - case SelectWrapper::Function_PcAttribute: + case ESM::DialogueCondition::Function_PcStrength: + case ESM::DialogueCondition::Function_PcIntelligence: + case ESM::DialogueCondition::Function_PcWillpower: + case ESM::DialogueCondition::Function_PcAgility: + case ESM::DialogueCondition::Function_PcSpeed: + case ESM::DialogueCondition::Function_PcEndurance: + case ESM::DialogueCondition::Function_PcPersonality: + case ESM::DialogueCondition::Function_PcLuck: { ESM::RefId attribute = ESM::Attribute::indexToRefId(select.getArgument()); return player.getClass().getCreatureStats(player).getAttribute(attribute).getModified(); } - case SelectWrapper::Function_PcSkill: + case ESM::DialogueCondition::Function_PcBlock: + case ESM::DialogueCondition::Function_PcArmorer: + case ESM::DialogueCondition::Function_PcMediumArmor: + case ESM::DialogueCondition::Function_PcHeavyArmor: + case ESM::DialogueCondition::Function_PcBluntWeapon: + case ESM::DialogueCondition::Function_PcLongBlade: + case ESM::DialogueCondition::Function_PcAxe: + case ESM::DialogueCondition::Function_PcSpear: + case ESM::DialogueCondition::Function_PcAthletics: + case ESM::DialogueCondition::Function_PcEnchant: + case ESM::DialogueCondition::Function_PcDestruction: + case ESM::DialogueCondition::Function_PcAlteration: + case ESM::DialogueCondition::Function_PcIllusion: + case ESM::DialogueCondition::Function_PcConjuration: + case ESM::DialogueCondition::Function_PcMysticism: + case ESM::DialogueCondition::Function_PcRestoration: + case ESM::DialogueCondition::Function_PcAlchemy: + case ESM::DialogueCondition::Function_PcUnarmored: + case ESM::DialogueCondition::Function_PcSecurity: + case ESM::DialogueCondition::Function_PcSneak: + case ESM::DialogueCondition::Function_PcAcrobatics: + case ESM::DialogueCondition::Function_PcLightArmor: + case ESM::DialogueCondition::Function_PcShortBlade: + case ESM::DialogueCondition::Function_PcMarksman: + case ESM::DialogueCondition::Function_PcMerchantile: + case ESM::DialogueCondition::Function_PcSpeechcraft: + case ESM::DialogueCondition::Function_PcHandToHand: { ESM::RefId skill = ESM::Skill::indexToRefId(select.getArgument()); return static_cast(player.getClass().getNpcStats(player).getSkill(skill).getModified()); } - case SelectWrapper::Function_FriendlyHit: + case ESM::DialogueCondition::Function_FriendHit: { int hits = mActor.getClass().getCreatureStats(mActor).getFriendlyHits(); return hits > 4 ? 4 : hits; } - case SelectWrapper::Function_PcLevel: + case ESM::DialogueCondition::Function_PcLevel: return player.getClass().getCreatureStats(player).getLevel(); - case SelectWrapper::Function_PcGender: + case ESM::DialogueCondition::Function_PcGender: return player.get()->mBase->isMale() ? 0 : 1; - case SelectWrapper::Function_PcClothingModifier: + case ESM::DialogueCondition::Function_PcClothingModifier: { const MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); @@ -428,11 +465,11 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons return value; } - case SelectWrapper::Function_PcCrimeLevel: + case ESM::DialogueCondition::Function_PcCrimeLevel: return player.getClass().getNpcStats(player).getBounty(); - case SelectWrapper::Function_RankRequirement: + case ESM::DialogueCondition::Function_RankRequirement: { const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor); if (faction.empty()) @@ -454,23 +491,23 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons return result; } - case SelectWrapper::Function_Level: + case ESM::DialogueCondition::Function_Level: return mActor.getClass().getCreatureStats(mActor).getLevel(); - case SelectWrapper::Function_PCReputation: + case ESM::DialogueCondition::Function_PcReputation: return player.getClass().getNpcStats(player).getReputation(); - case SelectWrapper::Function_Weather: + case ESM::DialogueCondition::Function_Weather: return MWBase::Environment::get().getWorld()->getCurrentWeather(); - case SelectWrapper::Function_Reputation: + case ESM::DialogueCondition::Function_Reputation: return mActor.getClass().getNpcStats(mActor).getReputation(); - case SelectWrapper::Function_FactionRankDiff: + case ESM::DialogueCondition::Function_FactionRankDifference: { const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor); @@ -482,14 +519,14 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons return rank - npcRank; } - case SelectWrapper::Function_WerewolfKills: + case ESM::DialogueCondition::Function_PcWerewolfKills: return player.getClass().getNpcStats(player).getWerewolfKills(); - case SelectWrapper::Function_RankLow: - case SelectWrapper::Function_RankHigh: + case ESM::DialogueCondition::Function_FacReactionLowest: + case ESM::DialogueCondition::Function_FacReactionHighest: { - bool low = select.getFunction() == SelectWrapper::Function_RankLow; + bool low = select.getFunction() == ESM::DialogueCondition::Function_FacReactionLowest; const ESM::RefId& factionId = mActor.getClass().getPrimaryFaction(mActor); @@ -512,7 +549,7 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons return value; } - case SelectWrapper::Function_CreatureTargetted: + case ESM::DialogueCondition::Function_CreatureTarget: { MWWorld::Ptr target; @@ -539,53 +576,49 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con switch (select.getFunction()) { - case SelectWrapper::Function_False: - - return false; - - case SelectWrapper::Function_NotId: + case ESM::DialogueCondition::Function_NotId: return mActor.getCellRef().getRefId() != select.getId(); - case SelectWrapper::Function_NotFaction: + case ESM::DialogueCondition::Function_NotFaction: return mActor.getClass().getPrimaryFaction(mActor) != select.getId(); - case SelectWrapper::Function_NotClass: + case ESM::DialogueCondition::Function_NotClass: return mActor.get()->mBase->mClass != select.getId(); - case SelectWrapper::Function_NotRace: + case ESM::DialogueCondition::Function_NotRace: return mActor.get()->mBase->mRace != select.getId(); - case SelectWrapper::Function_NotCell: + case ESM::DialogueCondition::Function_NotCell: { std::string_view actorCell = MWBase::Environment::get().getWorld()->getCellName(mActor.getCell()); return !Misc::StringUtils::ciStartsWith(actorCell, select.getCellName()); } - case SelectWrapper::Function_SameGender: + case ESM::DialogueCondition::Function_SameSex: return (player.get()->mBase->mFlags & ESM::NPC::Female) == (mActor.get()->mBase->mFlags & ESM::NPC::Female); - case SelectWrapper::Function_SameRace: + case ESM::DialogueCondition::Function_SameRace: return mActor.get()->mBase->mRace == player.get()->mBase->mRace; - case SelectWrapper::Function_SameFaction: + case ESM::DialogueCondition::Function_SameFaction: return player.getClass().getNpcStats(player).isInFaction(mActor.getClass().getPrimaryFaction(mActor)); - case SelectWrapper::Function_PcCommonDisease: + case ESM::DialogueCondition::Function_PcCommonDisease: return player.getClass().getCreatureStats(player).hasCommonDisease(); - case SelectWrapper::Function_PcBlightDisease: + case ESM::DialogueCondition::Function_PcBlightDisease: return player.getClass().getCreatureStats(player).hasBlightDisease(); - case SelectWrapper::Function_PcCorprus: + case ESM::DialogueCondition::Function_PcCorpus: return player.getClass() .getCreatureStats(player) @@ -594,7 +627,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con .getMagnitude() != 0; - case SelectWrapper::Function_PcExpelled: + case ESM::DialogueCondition::Function_PcExpelled: { const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor); @@ -604,7 +637,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con return player.getClass().getNpcStats(player).getExpelled(faction); } - case SelectWrapper::Function_PcVampire: + case ESM::DialogueCondition::Function_PcVampire: return player.getClass() .getCreatureStats(player) @@ -613,27 +646,27 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con .getMagnitude() > 0; - case SelectWrapper::Function_TalkedToPc: + case ESM::DialogueCondition::Function_TalkedToPc: return mTalkedToPlayer; - case SelectWrapper::Function_Alarmed: + case ESM::DialogueCondition::Function_Alarmed: return mActor.getClass().getCreatureStats(mActor).isAlarmed(); - case SelectWrapper::Function_Detected: + case ESM::DialogueCondition::Function_Detected: return MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, mActor); - case SelectWrapper::Function_Attacked: + case ESM::DialogueCondition::Function_Attacked: return mActor.getClass().getCreatureStats(mActor).getAttacked(); - case SelectWrapper::Function_ShouldAttack: + case ESM::DialogueCondition::Function_ShouldAttack: return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor, MWMechanics::getPlayer()); - case SelectWrapper::Function_Werewolf: + case ESM::DialogueCondition::Function_Werewolf: return mActor.getClass().getNpcStats(mActor).isWerewolf(); diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 0cee8bb009..cc07ec8709 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -10,21 +10,21 @@ namespace { template - bool selectCompareImp(char comp, T1 value1, T2 value2) + bool selectCompareImp(ESM::DialogueCondition::Comparison comp, T1 value1, T2 value2) { switch (comp) { - case '0': + case ESM::DialogueCondition::Comp_Eq: return value1 == value2; - case '1': + case ESM::DialogueCondition::Comp_Ne: return value1 != value2; - case '2': + case ESM::DialogueCondition::Comp_Gt: return value1 > value2; - case '3': + case ESM::DialogueCondition::Comp_Ge: return value1 >= value2; - case '4': + case ESM::DialogueCondition::Comp_Ls: return value1 < value2; - case '5': + case ESM::DialogueCondition::Comp_Le: return value1 <= value2; } @@ -32,409 +32,242 @@ namespace } template - bool selectCompareImp(const ESM::DialInfo::SelectStruct& select, T value1) + bool selectCompareImp(const ESM::DialogueCondition& select, T value1) { - if (select.mValue.getType() == ESM::VT_Int) - { - return selectCompareImp(select.mSelectRule[4], value1, select.mValue.getInteger()); - } - else if (select.mValue.getType() == ESM::VT_Float) - { - return selectCompareImp(select.mSelectRule[4], value1, select.mValue.getFloat()); - } - else - throw std::runtime_error("unsupported variable type in dialogue info select"); + return std::visit( + [&](auto value) { return selectCompareImp(select.mComparison, value1, value); }, select.mValue); } } -MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const -{ - const int index = Misc::StringUtils::toNumeric(mSelect.mSelectRule.substr(2, 2), 0); - - switch (index) - { - case 0: - return Function_RankLow; - case 1: - return Function_RankHigh; - case 2: - return Function_RankRequirement; - case 3: - return Function_Reputation; - case 4: - return Function_HealthPercent; - case 5: - return Function_PCReputation; - case 6: - return Function_PcLevel; - case 7: - return Function_PcHealthPercent; - case 8: - case 9: - return Function_PcDynamicStat; - case 10: - return Function_PcAttribute; - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - case 32: - case 33: - case 34: - case 35: - case 36: - case 37: - return Function_PcSkill; - case 38: - return Function_PcGender; - case 39: - return Function_PcExpelled; - case 40: - return Function_PcCommonDisease; - case 41: - return Function_PcBlightDisease; - case 42: - return Function_PcClothingModifier; - case 43: - return Function_PcCrimeLevel; - case 44: - return Function_SameGender; - case 45: - return Function_SameRace; - case 46: - return Function_SameFaction; - case 47: - return Function_FactionRankDiff; - case 48: - return Function_Detected; - case 49: - return Function_Alarmed; - case 50: - return Function_Choice; - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: - return Function_PcAttribute; - case 58: - return Function_PcCorprus; - case 59: - return Function_Weather; - case 60: - return Function_PcVampire; - case 61: - return Function_Level; - case 62: - return Function_Attacked; - case 63: - return Function_TalkedToPc; - case 64: - return Function_PcDynamicStat; - case 65: - return Function_CreatureTargetted; - case 66: - return Function_FriendlyHit; - case 67: - case 68: - case 69: - case 70: - return Function_AiSetting; - case 71: - return Function_ShouldAttack; - case 72: - return Function_Werewolf; - case 73: - return Function_WerewolfKills; - } - - return Function_False; -} - -MWDialogue::SelectWrapper::SelectWrapper(const ESM::DialInfo::SelectStruct& select) +MWDialogue::SelectWrapper::SelectWrapper(const ESM::DialogueCondition& select) : mSelect(select) { } -MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() const +ESM::DialogueCondition::Function MWDialogue::SelectWrapper::getFunction() const { - char type = mSelect.mSelectRule[1]; - - switch (type) - { - case '1': - return decodeFunction(); - case '2': - return Function_Global; - case '3': - return Function_Local; - case '4': - return Function_Journal; - case '5': - return Function_Item; - case '6': - return Function_Dead; - case '7': - return Function_NotId; - case '8': - return Function_NotFaction; - case '9': - return Function_NotClass; - case 'A': - return Function_NotRace; - case 'B': - return Function_NotCell; - case 'C': - return Function_NotLocal; - } - - return Function_None; + return mSelect.mFunction; } int MWDialogue::SelectWrapper::getArgument() const { - if (mSelect.mSelectRule[1] != '1') - return 0; - - int index = 0; - - std::istringstream(mSelect.mSelectRule.substr(2, 2)) >> index; - - switch (index) + switch (mSelect.mFunction) { // AI settings - case 67: + case ESM::DialogueCondition::Function_Fight: return 1; - case 68: + case ESM::DialogueCondition::Function_Hello: return 0; - case 69: + case ESM::DialogueCondition::Function_Alarm: return 3; - case 70: + case ESM::DialogueCondition::Function_Flee: return 2; // attributes - case 10: + case ESM::DialogueCondition::Function_PcStrength: return 0; - case 51: + case ESM::DialogueCondition::Function_PcIntelligence: return 1; - case 52: + case ESM::DialogueCondition::Function_PcWillpower: return 2; - case 53: + case ESM::DialogueCondition::Function_PcAgility: return 3; - case 54: + case ESM::DialogueCondition::Function_PcSpeed: return 4; - case 55: + case ESM::DialogueCondition::Function_PcEndurance: return 5; - case 56: + case ESM::DialogueCondition::Function_PcPersonality: return 6; - case 57: + case ESM::DialogueCondition::Function_PcLuck: return 7; // skills - case 11: + case ESM::DialogueCondition::Function_PcBlock: return 0; - case 12: + case ESM::DialogueCondition::Function_PcArmorer: return 1; - case 13: + case ESM::DialogueCondition::Function_PcMediumArmor: return 2; - case 14: + case ESM::DialogueCondition::Function_PcHeavyArmor: return 3; - case 15: + case ESM::DialogueCondition::Function_PcBluntWeapon: return 4; - case 16: + case ESM::DialogueCondition::Function_PcLongBlade: return 5; - case 17: + case ESM::DialogueCondition::Function_PcAxe: return 6; - case 18: + case ESM::DialogueCondition::Function_PcSpear: return 7; - case 19: + case ESM::DialogueCondition::Function_PcAthletics: return 8; - case 20: + case ESM::DialogueCondition::Function_PcEnchant: return 9; - case 21: + case ESM::DialogueCondition::Function_PcDestruction: return 10; - case 22: + case ESM::DialogueCondition::Function_PcAlteration: return 11; - case 23: + case ESM::DialogueCondition::Function_PcIllusion: return 12; - case 24: + case ESM::DialogueCondition::Function_PcConjuration: return 13; - case 25: + case ESM::DialogueCondition::Function_PcMysticism: return 14; - case 26: + case ESM::DialogueCondition::Function_PcRestoration: return 15; - case 27: + case ESM::DialogueCondition::Function_PcAlchemy: return 16; - case 28: + case ESM::DialogueCondition::Function_PcUnarmored: return 17; - case 29: + case ESM::DialogueCondition::Function_PcSecurity: return 18; - case 30: + case ESM::DialogueCondition::Function_PcSneak: return 19; - case 31: + case ESM::DialogueCondition::Function_PcAcrobatics: return 20; - case 32: + case ESM::DialogueCondition::Function_PcLightArmor: return 21; - case 33: + case ESM::DialogueCondition::Function_PcShortBlade: return 22; - case 34: + case ESM::DialogueCondition::Function_PcMarksman: return 23; - case 35: + case ESM::DialogueCondition::Function_PcMerchantile: return 24; - case 36: + case ESM::DialogueCondition::Function_PcSpeechcraft: return 25; - case 37: + case ESM::DialogueCondition::Function_PcHandToHand: return 26; // dynamic stats - case 8: + case ESM::DialogueCondition::Function_PcMagicka: return 1; - case 9: + case ESM::DialogueCondition::Function_PcFatigue: return 2; - case 64: + case ESM::DialogueCondition::Function_PcHealth: + return 0; + default: return 0; } - - return 0; } MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const { - static const Function integerFunctions[] = { - Function_Journal, - Function_Item, - Function_Dead, - Function_Choice, - Function_AiSetting, - Function_PcAttribute, - Function_PcSkill, - Function_FriendlyHit, - Function_PcLevel, - Function_PcGender, - Function_PcClothingModifier, - Function_PcCrimeLevel, - Function_RankRequirement, - Function_Level, - Function_PCReputation, - Function_Weather, - Function_Reputation, - Function_FactionRankDiff, - Function_WerewolfKills, - Function_RankLow, - Function_RankHigh, - Function_CreatureTargetted, - // end marker - Function_None, - }; - - static const Function numericFunctions[] = { - Function_Global, - Function_Local, - Function_NotLocal, - Function_PcDynamicStat, - Function_PcHealthPercent, - Function_HealthPercent, - // end marker - Function_None, - }; - - static const Function booleanFunctions[] = { - Function_False, - Function_SameGender, - Function_SameRace, - Function_SameFaction, - Function_PcCommonDisease, - Function_PcBlightDisease, - Function_PcCorprus, - Function_PcExpelled, - Function_PcVampire, - Function_TalkedToPc, - Function_Alarmed, - Function_Detected, - Function_Attacked, - Function_ShouldAttack, - Function_Werewolf, - // end marker - Function_None, - }; - - static const Function invertedBooleanFunctions[] = { - Function_NotId, - Function_NotFaction, - Function_NotClass, - Function_NotRace, - Function_NotCell, - // end marker - Function_None, - }; - - Function function = getFunction(); - - for (int i = 0; integerFunctions[i] != Function_None; ++i) - if (integerFunctions[i] == function) + switch (mSelect.mFunction) + { + case ESM::DialogueCondition::Function_Journal: + case ESM::DialogueCondition::Function_Item: + case ESM::DialogueCondition::Function_Dead: + case ESM::DialogueCondition::Function_Choice: + case ESM::DialogueCondition::Function_Fight: + case ESM::DialogueCondition::Function_Hello: + case ESM::DialogueCondition::Function_Alarm: + case ESM::DialogueCondition::Function_Flee: + case ESM::DialogueCondition::Function_PcStrength: + case ESM::DialogueCondition::Function_PcIntelligence: + case ESM::DialogueCondition::Function_PcWillpower: + case ESM::DialogueCondition::Function_PcAgility: + case ESM::DialogueCondition::Function_PcSpeed: + case ESM::DialogueCondition::Function_PcEndurance: + case ESM::DialogueCondition::Function_PcPersonality: + case ESM::DialogueCondition::Function_PcLuck: + case ESM::DialogueCondition::Function_PcBlock: + case ESM::DialogueCondition::Function_PcArmorer: + case ESM::DialogueCondition::Function_PcMediumArmor: + case ESM::DialogueCondition::Function_PcHeavyArmor: + case ESM::DialogueCondition::Function_PcBluntWeapon: + case ESM::DialogueCondition::Function_PcLongBlade: + case ESM::DialogueCondition::Function_PcAxe: + case ESM::DialogueCondition::Function_PcSpear: + case ESM::DialogueCondition::Function_PcAthletics: + case ESM::DialogueCondition::Function_PcEnchant: + case ESM::DialogueCondition::Function_PcDestruction: + case ESM::DialogueCondition::Function_PcAlteration: + case ESM::DialogueCondition::Function_PcIllusion: + case ESM::DialogueCondition::Function_PcConjuration: + case ESM::DialogueCondition::Function_PcMysticism: + case ESM::DialogueCondition::Function_PcRestoration: + case ESM::DialogueCondition::Function_PcAlchemy: + case ESM::DialogueCondition::Function_PcUnarmored: + case ESM::DialogueCondition::Function_PcSecurity: + case ESM::DialogueCondition::Function_PcSneak: + case ESM::DialogueCondition::Function_PcAcrobatics: + case ESM::DialogueCondition::Function_PcLightArmor: + case ESM::DialogueCondition::Function_PcShortBlade: + case ESM::DialogueCondition::Function_PcMarksman: + case ESM::DialogueCondition::Function_PcMerchantile: + case ESM::DialogueCondition::Function_PcSpeechcraft: + case ESM::DialogueCondition::Function_PcHandToHand: + case ESM::DialogueCondition::Function_FriendHit: + case ESM::DialogueCondition::Function_PcLevel: + case ESM::DialogueCondition::Function_PcGender: + case ESM::DialogueCondition::Function_PcClothingModifier: + case ESM::DialogueCondition::Function_PcCrimeLevel: + case ESM::DialogueCondition::Function_RankRequirement: + case ESM::DialogueCondition::Function_Level: + case ESM::DialogueCondition::Function_PcReputation: + case ESM::DialogueCondition::Function_Weather: + case ESM::DialogueCondition::Function_Reputation: + case ESM::DialogueCondition::Function_FactionRankDifference: + case ESM::DialogueCondition::Function_PcWerewolfKills: + case ESM::DialogueCondition::Function_FacReactionLowest: + case ESM::DialogueCondition::Function_FacReactionHighest: + case ESM::DialogueCondition::Function_CreatureTarget: return Type_Integer; - - for (int i = 0; numericFunctions[i] != Function_None; ++i) - if (numericFunctions[i] == function) + case ESM::DialogueCondition::Function_Global: + case ESM::DialogueCondition::Function_Local: + case ESM::DialogueCondition::Function_NotLocal: + case ESM::DialogueCondition::Function_PcHealth: + case ESM::DialogueCondition::Function_PcMagicka: + case ESM::DialogueCondition::Function_PcFatigue: + case ESM::DialogueCondition::Function_PcHealthPercent: + case ESM::DialogueCondition::Function_Health_Percent: return Type_Numeric; - - for (int i = 0; booleanFunctions[i] != Function_None; ++i) - if (booleanFunctions[i] == function) + case ESM::DialogueCondition::Function_SameSex: + case ESM::DialogueCondition::Function_SameRace: + case ESM::DialogueCondition::Function_SameFaction: + case ESM::DialogueCondition::Function_PcCommonDisease: + case ESM::DialogueCondition::Function_PcBlightDisease: + case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcExpelled: + case ESM::DialogueCondition::Function_PcVampire: + case ESM::DialogueCondition::Function_TalkedToPc: + case ESM::DialogueCondition::Function_Alarmed: + case ESM::DialogueCondition::Function_Detected: + case ESM::DialogueCondition::Function_Attacked: + case ESM::DialogueCondition::Function_ShouldAttack: + case ESM::DialogueCondition::Function_Werewolf: return Type_Boolean; - - for (int i = 0; invertedBooleanFunctions[i] != Function_None; ++i) - if (invertedBooleanFunctions[i] == function) + case ESM::DialogueCondition::Function_NotId: + case ESM::DialogueCondition::Function_NotFaction: + case ESM::DialogueCondition::Function_NotClass: + case ESM::DialogueCondition::Function_NotRace: + case ESM::DialogueCondition::Function_NotCell: return Type_Inverted; - - return Type_None; + default: + return Type_None; + }; } bool MWDialogue::SelectWrapper::isNpcOnly() const { - static const Function functions[] = { - Function_NotFaction, - Function_NotClass, - Function_NotRace, - Function_SameGender, - Function_SameRace, - Function_SameFaction, - Function_RankRequirement, - Function_Reputation, - Function_FactionRankDiff, - Function_Werewolf, - Function_WerewolfKills, - Function_RankLow, - Function_RankHigh, - // end marker - Function_None, - }; - - Function function = getFunction(); - - for (int i = 0; functions[i] != Function_None; ++i) - if (functions[i] == function) + switch (mSelect.mFunction) + { + case ESM::DialogueCondition::Function_NotFaction: + case ESM::DialogueCondition::Function_NotClass: + case ESM::DialogueCondition::Function_NotRace: + case ESM::DialogueCondition::Function_SameSex: + case ESM::DialogueCondition::Function_SameRace: + case ESM::DialogueCondition::Function_SameFaction: + case ESM::DialogueCondition::Function_RankRequirement: + case ESM::DialogueCondition::Function_Reputation: + case ESM::DialogueCondition::Function_FactionRankDifference: + case ESM::DialogueCondition::Function_Werewolf: + case ESM::DialogueCondition::Function_PcWerewolfKills: + case ESM::DialogueCondition::Function_FacReactionLowest: + case ESM::DialogueCondition::Function_FacReactionHighest: return true; - - return false; + default: + return false; + } } bool MWDialogue::SelectWrapper::selectCompare(int value) const @@ -454,15 +287,15 @@ bool MWDialogue::SelectWrapper::selectCompare(bool value) const std::string MWDialogue::SelectWrapper::getName() const { - return Misc::StringUtils::lowerCase(getCellName()); + return Misc::StringUtils::lowerCase(mSelect.mVariable); } std::string_view MWDialogue::SelectWrapper::getCellName() const { - return std::string_view(mSelect.mSelectRule).substr(5); + return mSelect.mVariable; } ESM::RefId MWDialogue::SelectWrapper::getId() const { - return ESM::RefId::stringRefId(getCellName()); + return ESM::RefId::stringRefId(mSelect.mVariable); } diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index f736b504d8..d831b6cea0 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -7,62 +7,9 @@ namespace MWDialogue { class SelectWrapper { - const ESM::DialInfo::SelectStruct& mSelect; + const ESM::DialogueCondition& mSelect; public: - enum Function - { - Function_None, - Function_False, - Function_Journal, - Function_Item, - Function_Dead, - Function_NotId, - Function_NotFaction, - Function_NotClass, - Function_NotRace, - Function_NotCell, - Function_NotLocal, - Function_Local, - Function_Global, - Function_SameGender, - Function_SameRace, - Function_SameFaction, - Function_Choice, - Function_PcCommonDisease, - Function_PcBlightDisease, - Function_PcCorprus, - Function_AiSetting, - Function_PcAttribute, - Function_PcSkill, - Function_PcExpelled, - Function_PcVampire, - Function_FriendlyHit, - Function_TalkedToPc, - Function_PcLevel, - Function_PcHealthPercent, - Function_PcDynamicStat, - Function_PcGender, - Function_PcClothingModifier, - Function_PcCrimeLevel, - Function_RankRequirement, - Function_HealthPercent, - Function_Level, - Function_PCReputation, - Function_Weather, - Function_Reputation, - Function_Alarmed, - Function_FactionRankDiff, - Function_Detected, - Function_Attacked, - Function_ShouldAttack, - Function_CreatureTargetted, - Function_Werewolf, - Function_WerewolfKills, - Function_RankLow, - Function_RankHigh - }; - enum Type { Type_None, @@ -72,13 +19,10 @@ namespace MWDialogue Type_Inverted }; - private: - Function decodeFunction() const; - public: - SelectWrapper(const ESM::DialInfo::SelectStruct& select); + SelectWrapper(const ESM::DialogueCondition& select); - Function getFunction() const; + ESM::DialogueCondition::Function getFunction() const; int getArgument() const; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 7ac01ef169..68411be2fc 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -181,7 +181,7 @@ add_component_dir (esm3 inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache - infoorder timestamp formatversion landrecorddata selectiongroup + infoorder timestamp formatversion landrecorddata selectiongroup dialoguecondition ) add_component_dir (esmterrain diff --git a/components/esm3/dialoguecondition.cpp b/components/esm3/dialoguecondition.cpp new file mode 100644 index 0000000000..ba8f9586ce --- /dev/null +++ b/components/esm3/dialoguecondition.cpp @@ -0,0 +1,204 @@ +#include "dialoguecondition.hpp" + +#include "esmreader.hpp" +#include "esmwriter.hpp" +#include "variant.hpp" + +#include +#include +#include + +namespace ESM +{ + std::optional DialogueCondition::load(ESMReader& esm, ESM::RefId context) + { + std::string rule = esm.getHString(); + ESM::Variant variant; + variant.read(esm, Variant::Format_Info); + if (rule.size() < 5) + { + Log(Debug::Warning) << "Found invalid SCVR rule of size " << rule.size() << " in INFO " << context; + return {}; + } + if (rule[4] < '0' || rule[4] > '5') + { + Log(Debug::Warning) << "Found invalid SCVR comparison operator " << static_cast(rule[4]) << " in INFO " + << context; + return {}; + } + DialogueCondition condition; + if (rule[0] >= '0' && rule[0] <= '9') + condition.mIndex = rule[0] - '0'; + else + { + Log(Debug::Info) << "Found invalid SCVR index " << static_cast(rule[0]) << " in INFO " << context; + condition.mIndex = 0; + } + if (rule[1] == '1') + { + int function = Misc::StringUtils::toNumeric(std::string_view{ rule }.substr(2, 2), -1); + if (function >= Function_FacReactionLowest && function <= Function_PcWerewolfKills) + condition.mFunction = static_cast(function); + else + { + Log(Debug::Warning) << "Encountered invalid SCVR function index " << function << " in INFO " << context; + return {}; + } + } + else if (rule[1] > '1' && rule[1] <= '9' || rule[1] >= 'A' && rule[1] <= 'C') + { + if (rule.size() == 5) + { + Log(Debug::Warning) << "Missing variable for SCVR of type " << rule[1] << " in INFO " << context; + return {}; + } + bool malformed = rule[3] != 'X'; + if (rule[1] == '2') + { + condition.mFunction = Function_Global; + malformed |= rule[2] != 'f' && rule[2] != 'l' && rule[2] != 's'; + } + else if (rule[1] == '3') + { + condition.mFunction = Function_Local; + malformed |= rule[2] != 'f' && rule[2] != 'l' && rule[2] != 's'; + } + else if (rule[1] == '4') + { + condition.mFunction = Function_Journal; + malformed |= rule[2] != 'J'; + } + else if (rule[1] == '5') + { + condition.mFunction = Function_Item; + malformed |= rule[2] != 'I'; + } + else if (rule[1] == '6') + { + condition.mFunction = Function_Dead; + malformed |= rule[2] != 'D'; + } + else if (rule[1] == '7') + { + condition.mFunction = Function_NotId; + malformed |= rule[2] != 'X'; + } + else if (rule[1] == '8') + { + condition.mFunction = Function_NotFaction; + malformed |= rule[2] != 'F'; + } + else if (rule[1] == '9') + { + condition.mFunction = Function_NotClass; + malformed |= rule[2] != 'C'; + } + else if (rule[1] == 'A') + { + condition.mFunction = Function_NotRace; + malformed |= rule[2] != 'R'; + } + else if (rule[1] == 'B') + { + condition.mFunction = Function_NotCell; + malformed |= rule[2] != 'L'; + } + else if (rule[1] == 'C') + { + condition.mFunction = Function_NotLocal; + malformed |= rule[2] != 'f' && rule[2] != 'l' && rule[2] != 's'; + } + if (malformed) + Log(Debug::Info) << "Found malformed SCVR rule in INFO " << context; + } + else + { + Log(Debug::Warning) << "Found invalid SCVR function " << static_cast(rule[1]) << " in INFO " + << context; + return {}; + } + condition.mComparison = static_cast(rule[4]); + condition.mVariable = rule.substr(5); + if (variant.getType() == VT_Int) + condition.mValue = variant.getInteger(); + else if (variant.getType() == VT_Float) + condition.mValue = variant.getFloat(); + else + { + Log(Debug::Warning) << "Found invalid SCVR variant " << variant.getType() << " in INFO " << context; + return {}; + } + return condition; + } + + void DialogueCondition::save(ESMWriter& esm) const + { + auto variant = std::visit([](auto value) { return ESM::Variant(value); }, mValue); + std::string rule; + rule.reserve(5 + mVariable.size()); + rule += static_cast(mIndex + '0'); + const auto appendVariableType = [&]() { + if (variant.getType() == VT_Float) + rule += "fX"; + else + { + int32_t value = variant.getInteger(); + if (static_cast(value) == value) + rule += "sX"; + else + rule += "lX"; + } + }; + if (mFunction == Function_Global) + { + rule += '2'; + appendVariableType(); + } + else if (mFunction == Function_Local) + { + rule += '3'; + appendVariableType(); + } + else if (mFunction == Function_Journal) + rule += "4JX"; + else if (mFunction == Function_Item) + rule += "5IX"; + else if (mFunction == Function_Dead) + rule += "6DX"; + else if (mFunction == Function_NotId) + rule += "7XX"; + else if (mFunction == Function_NotFaction) + rule += "8FX"; + else if (mFunction == Function_NotClass) + rule += "9CX"; + else if (mFunction == Function_NotRace) + rule += "ARX"; + else if (mFunction == Function_NotCell) + rule += "BLX"; + else if (mFunction == Function_NotLocal) + { + rule += 'C'; + appendVariableType(); + } + else + { + rule += "100"; + char* start = rule.data() + rule.size(); + char* end = start; + if (mFunction < Function_PcStrength) + start--; + else + start -= 2; + auto result = std::to_chars(start, end, mFunction); + if (result.ec != std::errc()) + { + Log(Debug::Error) << "Failed to save SCVR rule"; + return; + } + } + rule += static_cast(mComparison); + rule += mVariable; + esm.writeHNString("SCVR", rule); + variant.write(esm, Variant::Format_Info); + } +} diff --git a/components/esm3/dialoguecondition.hpp b/components/esm3/dialoguecondition.hpp new file mode 100644 index 0000000000..15ad4944f5 --- /dev/null +++ b/components/esm3/dialoguecondition.hpp @@ -0,0 +1,134 @@ +#ifndef OPENMW_ESM3_DIALOGUECONDITION_H +#define OPENMW_ESM3_DIALOGUECONDITION_H + +#include +#include +#include +#include + +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct DialogueCondition + { + enum Function : std::int8_t + { + Function_FacReactionLowest = 0, + Function_FacReactionHighest, + Function_RankRequirement, + Function_Reputation, + Function_Health_Percent, + Function_PcReputation, + Function_PcLevel, + Function_PcHealthPercent, + Function_PcMagicka, + Function_PcFatigue, + Function_PcStrength, + Function_PcBlock, + Function_PcArmorer, + Function_PcMediumArmor, + Function_PcHeavyArmor, + Function_PcBluntWeapon, + Function_PcLongBlade, + Function_PcAxe, + Function_PcSpear, + Function_PcAthletics, + Function_PcEnchant, + Function_PcDestruction, + Function_PcAlteration, + Function_PcIllusion, + Function_PcConjuration, + Function_PcMysticism, + Function_PcRestoration, + Function_PcAlchemy, + Function_PcUnarmored, + Function_PcSecurity, + Function_PcSneak, + Function_PcAcrobatics, + Function_PcLightArmor, + Function_PcShortBlade, + Function_PcMarksman, + Function_PcMerchantile, + Function_PcSpeechcraft, + Function_PcHandToHand, + Function_PcGender, + Function_PcExpelled, + Function_PcCommonDisease, + Function_PcBlightDisease, + Function_PcClothingModifier, + Function_PcCrimeLevel, + Function_SameSex, + Function_SameRace, + Function_SameFaction, + Function_FactionRankDifference, + Function_Detected, + Function_Alarmed, + Function_Choice, + Function_PcIntelligence, + Function_PcWillpower, + Function_PcAgility, + Function_PcSpeed, + Function_PcEndurance, + Function_PcPersonality, + Function_PcLuck, + Function_PcCorpus, + Function_Weather, + Function_PcVampire, + Function_Level, + Function_Attacked, + Function_TalkedToPc, + Function_PcHealth, + Function_CreatureTarget, + Function_FriendHit, + Function_Fight, + Function_Hello, + Function_Alarm, + Function_Flee, + Function_ShouldAttack, + Function_Werewolf, + Function_PcWerewolfKills = 73, + + Function_Global, + Function_Local, + Function_Journal, + Function_Item, + Function_Dead, + Function_NotId, + Function_NotFaction, + Function_NotClass, + Function_NotRace, + Function_NotCell, + Function_NotLocal, + + Function_None, // Editor only + }; + + enum Comparison : char + { + Comp_Eq = '0', + Comp_Ne = '1', + Comp_Gt = '2', + Comp_Ge = '3', + Comp_Ls = '4', + Comp_Le = '5', + + Comp_None = ' ', // Editor only + }; + + std::string mVariable; + std::variant mValue = 0; + std::uint8_t mIndex = 0; + Function mFunction = Function_None; + Comparison mComparison = Comp_None; + + static std::optional load(ESMReader& esm, ESM::RefId context); + + void save(ESMWriter& esm) const; + }; +} + +#endif diff --git a/components/esm3/loadinfo.cpp b/components/esm3/loadinfo.cpp index b091edd3f6..8b1147ed45 100644 --- a/components/esm3/loadinfo.cpp +++ b/components/esm3/loadinfo.cpp @@ -3,65 +3,7 @@ #include "esmreader.hpp" #include "esmwriter.hpp" -#include #include -#include - -namespace -{ - enum class SelectRuleStatus - { - Valid, - Invalid, - Ignorable - }; - - SelectRuleStatus isValidSelectRule(std::string_view rule) - { - if (rule.size() < 5) - return SelectRuleStatus::Invalid; - if (rule[4] < '0' || rule[4] > '5') // Comparison operators - return SelectRuleStatus::Invalid; - if (rule[1] == '1') // Function - { - int function = Misc::StringUtils::toNumeric(rule.substr(2, 2), -1); - if (function >= 0 && function <= 73) - return SelectRuleStatus::Valid; - return SelectRuleStatus::Invalid; - } - if (rule.size() == 5) // Missing ID - return SelectRuleStatus::Invalid; - if (rule[3] != 'X') - return SelectRuleStatus::Ignorable; - constexpr auto ignorable - = [](bool valid) { return valid ? SelectRuleStatus::Valid : SelectRuleStatus::Ignorable; }; - switch (rule[1]) - { - case '2': - case '3': - case 'C': - return ignorable(rule[2] == 's' || rule[2] == 'l' || rule[2] == 'f'); - case '4': - return ignorable(rule[2] == 'J'); - case '5': - return ignorable(rule[2] == 'I'); - case '6': - return ignorable(rule[2] == 'D'); - case '7': - return ignorable(rule[2] == 'X'); - case '8': - return ignorable(rule[2] == 'F'); - case '9': - return ignorable(rule[2] == 'C'); - case 'A': - return ignorable(rule[2] == 'R'); - case 'B': - return ignorable(rule[2] == 'L'); - default: - return SelectRuleStatus::Invalid; - } - } -} namespace ESM { @@ -124,21 +66,9 @@ namespace ESM break; case fourCC("SCVR"): { - SelectStruct ss; - ss.mSelectRule = esm.getHString(); - ss.mValue.read(esm, Variant::Format_Info); - auto valid = isValidSelectRule(ss.mSelectRule); - if (ss.mValue.getType() != VT_Int && ss.mValue.getType() != VT_Float) - valid = SelectRuleStatus::Invalid; - if (valid == SelectRuleStatus::Invalid) - Log(Debug::Warning) << "Skipping invalid SCVR for INFO " << mId; - else - { - mSelects.push_back(ss); - if (valid == SelectRuleStatus::Ignorable) - Log(Debug::Info) - << "Found malformed SCVR for INFO " << mId << " at index " << ss.mSelectRule[0]; - } + auto filter = DialogueCondition::load(esm, mId); + if (filter) + mSelects.emplace_back(std::move(*filter)); break; } case fourCC("BNAM"): @@ -189,11 +119,8 @@ namespace ESM esm.writeHNOCString("SNAM", mSound); esm.writeHNOString("NAME", mResponse); - for (std::vector::const_iterator it = mSelects.begin(); it != mSelects.end(); ++it) - { - esm.writeHNString("SCVR", it->mSelectRule); - it->mValue.write(esm, Variant::Format_Info); - } + for (const auto& rule : mSelects) + rule.save(esm); esm.writeHNOString("BNAM", mResultScript); diff --git a/components/esm3/loadinfo.hpp b/components/esm3/loadinfo.hpp index c2756e8d9c..a3fb4abffa 100644 --- a/components/esm3/loadinfo.hpp +++ b/components/esm3/loadinfo.hpp @@ -4,8 +4,10 @@ #include #include -#include "components/esm/defs.hpp" -#include "components/esm/refid.hpp" +#include +#include + +#include "dialoguecondition.hpp" #include "variant.hpp" namespace ESM @@ -47,13 +49,6 @@ namespace ESM }; // 12 bytes DATAstruct mData; - // The rules for whether or not we will select this dialog item. - struct SelectStruct - { - std::string mSelectRule; // This has a complicated format - Variant mValue; - }; - // Journal quest indices (introduced with the quest system in Tribunal) enum QuestStatus { @@ -65,7 +60,7 @@ namespace ESM // Rules for when to include this item in the final list of options // visible to the player. - std::vector mSelects; + std::vector mSelects; // Id of this, previous and next INFO items RefId mId, mPrev, mNext; From 6e79064a57b89bfec0470fc6cfdb469dc651b05c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 12 Apr 2024 18:32:47 +0200 Subject: [PATCH 04/26] Fix editor oddities --- apps/opencs/model/world/infoselectwrapper.cpp | 44 ++++++------------- apps/opencs/model/world/infoselectwrapper.hpp | 5 --- .../model/world/nestedcoladapterimp.cpp | 5 ++- apps/openmw/mwdialogue/filter.cpp | 2 +- apps/openmw/mwdialogue/selectwrapper.cpp | 6 +-- components/esm3/dialoguecondition.cpp | 6 ++- components/esm3/dialoguecondition.hpp | 2 +- 7 files changed, 26 insertions(+), 44 deletions(-) diff --git a/apps/opencs/model/world/infoselectwrapper.cpp b/apps/opencs/model/world/infoselectwrapper.cpp index d1af341c04..2e9ed6e150 100644 --- a/apps/opencs/model/world/infoselectwrapper.cpp +++ b/apps/opencs/model/world/infoselectwrapper.cpp @@ -65,7 +65,7 @@ const char* CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings[] = { "PC Endurance", "PC Personality", "PC Luck", - "PC Corpus", + "PC Corprus", "Weather", "PC Vampire", "Level", @@ -105,37 +105,21 @@ const char* CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings[] = { nullptr, }; -const char* CSMWorld::ConstInfoSelectWrapper::ComparisonEnumStrings[] = { - "Boolean", - "Integer", - "Numeric", - nullptr, -}; - -// static functions - -std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ESM::DialogueCondition::Function name) +namespace { - if (name < ESM::DialogueCondition::Function_None) - return FunctionEnumStrings[name]; - else + std::string_view convertToString(ESM::DialogueCondition::Function name) + { + if (name < ESM::DialogueCondition::Function_None) + return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings[name]; return "(Invalid Data: Function)"; -} + } -std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ESM::DialogueCondition::Comparison type) -{ - if (type < ESM::DialogueCondition::Comp_None) - return RelationEnumStrings[type]; - else + std::string_view convertToString(ESM::DialogueCondition::Comparison type) + { + if (type != ESM::DialogueCondition::Comp_None) + return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings[type - ESM::DialogueCondition::Comp_Eq]; return "(Invalid Data: Relation)"; -} - -std::string CSMWorld::ConstInfoSelectWrapper::convertToString(ComparisonType type) -{ - if (type < Comparison_None) - return ComparisonEnumStrings[type]; - else - return "(Invalid Data: Comparison)"; + } } // ConstInfoSelectWrapper @@ -269,7 +253,7 @@ void CSMWorld::ConstInfoSelectWrapper::updateComparisonType() case ESM::DialogueCondition::Function_SameFaction: case ESM::DialogueCondition::Function_Detected: case ESM::DialogueCondition::Function_Alarmed: - case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcCorprus: case ESM::DialogueCondition::Function_PcVampire: case ESM::DialogueCondition::Function_Attacked: case ESM::DialogueCondition::Function_TalkedToPc: @@ -457,7 +441,7 @@ std::pair CSMWorld::ConstInfoSelectWrapper::getValidIntRange() const case ESM::DialogueCondition::Function_SameFaction: case ESM::DialogueCondition::Function_Detected: case ESM::DialogueCondition::Function_Alarmed: - case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcCorprus: case ESM::DialogueCondition::Function_PcVampire: case ESM::DialogueCondition::Function_Attacked: case ESM::DialogueCondition::Function_TalkedToPc: diff --git a/apps/opencs/model/world/infoselectwrapper.hpp b/apps/opencs/model/world/infoselectwrapper.hpp index d8d108444f..b3b5abe462 100644 --- a/apps/opencs/model/world/infoselectwrapper.hpp +++ b/apps/opencs/model/world/infoselectwrapper.hpp @@ -25,11 +25,6 @@ namespace CSMWorld static const char* FunctionEnumStrings[]; static const char* RelationEnumStrings[]; - static const char* ComparisonEnumStrings[]; - - static std::string convertToString(ESM::DialogueCondition::Function name); - static std::string convertToString(ESM::DialogueCondition::Comparison type); - static std::string convertToString(ComparisonType type); ConstInfoSelectWrapper(const ESM::DialogueCondition& select); diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 86d38f9cd2..c844c5a18f 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -605,7 +605,7 @@ namespace CSMWorld } case 2: { - return infoSelectWrapper.getRelationType(); + return infoSelectWrapper.getRelationType() - ESM::DialogueCondition::Comp_Eq; } case 3: { @@ -643,7 +643,8 @@ namespace CSMWorld } case 2: // Relation { - infoSelectWrapper.setRelationType(static_cast(value.toInt())); + infoSelectWrapper.setRelationType( + static_cast(value.toInt() + ESM::DialogueCondition::Comp_Eq)); break; } case 3: // Value diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index acf87ccc61..295d690ce5 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -618,7 +618,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con return player.getClass().getCreatureStats(player).hasBlightDisease(); - case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcCorprus: return player.getClass() .getCreatureStats(player) diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index cc07ec8709..02c9d29b59 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -26,9 +26,9 @@ namespace return value1 < value2; case ESM::DialogueCondition::Comp_Le: return value1 <= value2; + default: + throw std::runtime_error("unknown compare type in dialogue info select"); } - - throw std::runtime_error("unknown compare type in dialogue info select"); } template @@ -226,7 +226,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const case ESM::DialogueCondition::Function_SameFaction: case ESM::DialogueCondition::Function_PcCommonDisease: case ESM::DialogueCondition::Function_PcBlightDisease: - case ESM::DialogueCondition::Function_PcCorpus: + case ESM::DialogueCondition::Function_PcCorprus: case ESM::DialogueCondition::Function_PcExpelled: case ESM::DialogueCondition::Function_PcVampire: case ESM::DialogueCondition::Function_TalkedToPc: diff --git a/components/esm3/dialoguecondition.cpp b/components/esm3/dialoguecondition.cpp index ba8f9586ce..a6a28307c2 100644 --- a/components/esm3/dialoguecondition.cpp +++ b/components/esm3/dialoguecondition.cpp @@ -45,7 +45,7 @@ namespace ESM return {}; } } - else if (rule[1] > '1' && rule[1] <= '9' || rule[1] >= 'A' && rule[1] <= 'C') + else if ((rule[1] > '1' && rule[1] <= '9') || (rule[1] >= 'A' && rule[1] <= 'C')) { if (rule.size() == 5) { @@ -134,6 +134,8 @@ namespace ESM void DialogueCondition::save(ESMWriter& esm) const { auto variant = std::visit([](auto value) { return ESM::Variant(value); }, mValue); + if (variant.getType() != VT_Float) + variant.setType(VT_Int); std::string rule; rule.reserve(5 + mVariable.size()); rule += static_cast(mIndex + '0'); @@ -189,7 +191,7 @@ namespace ESM start--; else start -= 2; - auto result = std::to_chars(start, end, mFunction); + auto result = std::to_chars(start, end, static_cast(mFunction)); if (result.ec != std::errc()) { Log(Debug::Error) << "Failed to save SCVR rule"; diff --git a/components/esm3/dialoguecondition.hpp b/components/esm3/dialoguecondition.hpp index 15ad4944f5..c06d50b601 100644 --- a/components/esm3/dialoguecondition.hpp +++ b/components/esm3/dialoguecondition.hpp @@ -75,7 +75,7 @@ namespace ESM Function_PcEndurance, Function_PcPersonality, Function_PcLuck, - Function_PcCorpus, + Function_PcCorprus, Function_Weather, Function_PcVampire, Function_Level, From 1930bfeabb522781d5825bdee123a07216e62b13 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 13 Apr 2024 17:09:48 +0100 Subject: [PATCH 05/26] Support coloured terminal output on Windows First try the modern Windowsy way, where we can directly query if escape sequences will be processed. The function is available as far back as Windows 2000, but it just won't return the right flag until the Windows version is new enough. If that fails, fall back to the Unixy way, as not all colour-supporting terminal emulators for Windows use the Win32 API to declare that capability. The implementation isn't identical as isatty wasn't available without adding more headers, and we already have Windows.h in this file, so I might as well use the Win32 API instead of its POSIX-compatibility layer. --- components/debug/debugging.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index e9e50ff836..bfde558c85 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -256,9 +256,17 @@ namespace Debug private: static bool useColoredOutput() { - // Note: cmd.exe in Win10 should support ANSI colors, but in its own way. #if defined(_WIN32) - return 0; + if (getenv("NO_COLOR")) + return false; + + DWORD mode; + if (GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &mode) && mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) + return true; + + // some console emulators may not use the Win32 API, so try the Unixy approach + char* term = getenv("TERM"); + return term && GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_CHAR; #else char* term = getenv("TERM"); bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr)); From a1438f65feccb3e7b2c58b2af99be86891b13bcc Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 30 Mar 2024 02:09:55 +0100 Subject: [PATCH 06/26] Set proper max tiles on initializing navmesh settings --- .../detournavigator/asyncnavmeshupdater.cpp | 11 +- components/detournavigator/makenavmesh.cpp | 26 +---- components/detournavigator/navmeshmanager.cpp | 2 +- components/detournavigator/settings.cpp | 101 +++++++++++++----- components/detournavigator/settings.hpp | 4 - files/settings-default.cfg | 2 +- 6 files changed, 80 insertions(+), 66 deletions(-) diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 03f6062788..1ea7b63429 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -180,13 +180,10 @@ namespace DetourNavigator if (!playerTileChanged && changedTiles.empty()) return; - const int maxTiles - = std::min(mSettings.get().mMaxTilesNumber, navMeshCacheItem->lockConst()->getImpl().getParams()->maxTiles); - std::unique_lock lock(mMutex); if (playerTileChanged) - updateJobs(mWaiting, playerTile, maxTiles); + updateJobs(mWaiting, playerTile, mSettings.get().mMaxTilesNumber); for (const auto& [changedTile, changeType] : changedTiles) { @@ -221,7 +218,7 @@ namespace DetourNavigator lock.unlock(); if (playerTileChanged && mDbWorker != nullptr) - mDbWorker->updateJobs(playerTile, maxTiles); + mDbWorker->updateJobs(playerTile, mSettings.get().mMaxTilesNumber); } void AsyncNavMeshUpdater::wait(WaitConditionType waitConditionType, Loading::Listener* listener) @@ -376,10 +373,8 @@ namespace DetourNavigator return JobStatus::Done; const auto playerTile = *mPlayerTile.lockConst(); - const int maxTiles - = std::min(mSettings.get().mMaxTilesNumber, navMeshCacheItem->lockConst()->getImpl().getParams()->maxTiles); - if (!shouldAddTile(job.mChangedTile, playerTile, maxTiles)) + if (!shouldAddTile(job.mChangedTile, playerTile, mSettings.get().mMaxTilesNumber)) { Log(Debug::Debug) << "Ignore add tile by job " << job.mId << ": too far from player"; navMeshCacheItem->lock()->removeTile(job.mChangedTile); diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index d35ecf499d..e143bf1837 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -480,15 +480,6 @@ namespace DetourNavigator return true; } - template - unsigned long getMinValuableBitsNumber(const T value) - { - unsigned long power = 0; - while (power < sizeof(T) * 8 && (static_cast(1) << power) < value) - ++power; - return power; - } - std::pair getBoundsByZ( const RecastMesh& recastMesh, float agentHalfExtentsZ, const RecastSettings& settings) { @@ -528,10 +519,7 @@ namespace DetourNavigator return { minZ, maxZ }; } } -} // namespace DetourNavigator -namespace DetourNavigator -{ std::unique_ptr prepareNavMeshTileData(const RecastMesh& recastMesh, std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds, const RecastSettings& settings) @@ -621,22 +609,12 @@ namespace DetourNavigator void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh) { - // Max tiles and max polys affect how the tile IDs are caculated. - // There are 22 bits available for identifying a tile and a polygon. - const int polysAndTilesBits = 22; - const auto polysBits = getMinValuableBitsNumber(settings.mDetour.mMaxPolys); - - if (polysBits >= polysAndTilesBits) - throw InvalidArgument("Too many polygons per tile"); - - const auto tilesBits = polysAndTilesBits - polysBits; - dtNavMeshParams params; std::fill_n(params.orig, 3, 0.0f); params.tileWidth = settings.mRecast.mTileSize * settings.mRecast.mCellSize; params.tileHeight = settings.mRecast.mTileSize * settings.mRecast.mCellSize; - params.maxTiles = 1 << tilesBits; - params.maxPolys = 1 << polysBits; + params.maxTiles = settings.mMaxTilesNumber; + params.maxPolys = settings.mDetour.mMaxPolys; const auto status = navMesh.init(¶ms); diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index f4a82b850f..e6f831bb6e 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -181,7 +181,7 @@ namespace DetourNavigator { const auto locked = cached->lockConst(); const auto& navMesh = locked->getImpl(); - const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles); + const int maxTiles = mSettings.mMaxTilesNumber; getTilesPositions(range, [&](const TilePosition& tile) { if (changedTiles.find(tile) != changedTiles.end()) return; diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp index 0470c629e5..5e555050f7 100644 --- a/components/detournavigator/settings.cpp +++ b/components/detournavigator/settings.cpp @@ -3,41 +3,81 @@ #include #include +#include +#include +#include + namespace DetourNavigator { - RecastSettings makeRecastSettingsFromSettingsManager() + namespace { - RecastSettings result; + struct NavMeshLimits + { + int mMaxTiles; + int mMaxPolys; + }; - result.mBorderSize = ::Settings::navigator().mBorderSize; - result.mCellHeight = ::Settings::navigator().mCellHeight; - result.mCellSize = ::Settings::navigator().mCellSize; - result.mDetailSampleDist = ::Settings::navigator().mDetailSampleDist; - result.mDetailSampleMaxError = ::Settings::navigator().mDetailSampleMaxError; - result.mMaxClimb = Constants::sStepSizeUp; - result.mMaxSimplificationError = ::Settings::navigator().mMaxSimplificationError; - result.mMaxSlope = Constants::sMaxSlope; - result.mRecastScaleFactor = ::Settings::navigator().mRecastScaleFactor; - result.mSwimHeightScale = 0; - result.mMaxEdgeLen = ::Settings::navigator().mMaxEdgeLen; - result.mMaxVertsPerPoly = ::Settings::navigator().mMaxVertsPerPoly; - result.mRegionMergeArea = ::Settings::navigator().mRegionMergeArea; - result.mRegionMinArea = ::Settings::navigator().mRegionMinArea; - result.mTileSize = ::Settings::navigator().mTileSize; + template + unsigned long getMinValuableBitsNumber(const T value) + { + unsigned long power = 0; + while (power < sizeof(T) * 8 && (static_cast(1) << power) < value) + ++power; + return power; + } - return result; - } + NavMeshLimits getNavMeshTileLimits(const DetourSettings& settings) + { + // Max tiles and max polys affect how the tile IDs are caculated. + // There are 22 bits available for identifying a tile and a polygon. + constexpr int polysAndTilesBits = 22; + const unsigned long polysBits = getMinValuableBitsNumber(settings.mMaxPolys); - DetourSettings makeDetourSettingsFromSettingsManager() - { - DetourSettings result; + if (polysBits >= polysAndTilesBits) + throw std::invalid_argument("Too many polygons per tile: " + std::to_string(settings.mMaxPolys)); - result.mMaxNavMeshQueryNodes = ::Settings::navigator().mMaxNavMeshQueryNodes; - result.mMaxPolys = ::Settings::navigator().mMaxPolygonsPerTile; - result.mMaxPolygonPathSize = ::Settings::navigator().mMaxPolygonPathSize; - result.mMaxSmoothPathSize = ::Settings::navigator().mMaxSmoothPathSize; + const unsigned long tilesBits = polysAndTilesBits - polysBits; - return result; + return NavMeshLimits{ + .mMaxTiles = static_cast(1 << tilesBits), + .mMaxPolys = static_cast(1 << polysBits), + }; + } + + RecastSettings makeRecastSettingsFromSettingsManager() + { + RecastSettings result; + + result.mBorderSize = ::Settings::navigator().mBorderSize; + result.mCellHeight = ::Settings::navigator().mCellHeight; + result.mCellSize = ::Settings::navigator().mCellSize; + result.mDetailSampleDist = ::Settings::navigator().mDetailSampleDist; + result.mDetailSampleMaxError = ::Settings::navigator().mDetailSampleMaxError; + result.mMaxClimb = Constants::sStepSizeUp; + result.mMaxSimplificationError = ::Settings::navigator().mMaxSimplificationError; + result.mMaxSlope = Constants::sMaxSlope; + result.mRecastScaleFactor = ::Settings::navigator().mRecastScaleFactor; + result.mSwimHeightScale = 0; + result.mMaxEdgeLen = ::Settings::navigator().mMaxEdgeLen; + result.mMaxVertsPerPoly = ::Settings::navigator().mMaxVertsPerPoly; + result.mRegionMergeArea = ::Settings::navigator().mRegionMergeArea; + result.mRegionMinArea = ::Settings::navigator().mRegionMinArea; + result.mTileSize = ::Settings::navigator().mTileSize; + + return result; + } + + DetourSettings makeDetourSettingsFromSettingsManager() + { + DetourSettings result; + + result.mMaxNavMeshQueryNodes = ::Settings::navigator().mMaxNavMeshQueryNodes; + result.mMaxPolys = ::Settings::navigator().mMaxPolygonsPerTile; + result.mMaxPolygonPathSize = ::Settings::navigator().mMaxPolygonPathSize; + result.mMaxSmoothPathSize = ::Settings::navigator().mMaxSmoothPathSize; + + return result; + } } Settings makeSettingsFromSettingsManager() @@ -46,7 +86,12 @@ namespace DetourNavigator result.mRecast = makeRecastSettingsFromSettingsManager(); result.mDetour = makeDetourSettingsFromSettingsManager(); - result.mMaxTilesNumber = ::Settings::navigator().mMaxTilesNumber; + + const NavMeshLimits limits = getNavMeshTileLimits(result.mDetour); + + result.mDetour.mMaxPolys = limits.mMaxPolys; + + result.mMaxTilesNumber = std::min(limits.mMaxTiles, ::Settings::navigator().mMaxTilesNumber.get()); result.mWaitUntilMinDistanceToPlayer = ::Settings::navigator().mWaitUntilMinDistanceToPlayer; result.mAsyncNavMeshUpdaterThreads = ::Settings::navigator().mAsyncNavMeshUpdaterThreads; result.mMaxNavMeshTilesCacheSize = ::Settings::navigator().mMaxNavMeshTilesCacheSize; diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index 45bcf15dbf..1d1f6f5847 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -55,10 +55,6 @@ namespace DetourNavigator inline constexpr std::int64_t navMeshFormatVersion = 2; - RecastSettings makeRecastSettingsFromSettingsManager(); - - DetourSettings makeDetourSettingsFromSettingsManager(); - Settings makeSettingsFromSettingsManager(); } diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 73331867a7..2f236bf55a 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -981,7 +981,7 @@ enable agents paths render = false enable recast mesh render = false # Max number of navmesh tiles (value >= 0) -max tiles number = 512 +max tiles number = 1024 # Min time duration for the same tile update in milliseconds (value >= 0) min update interval ms = 250 From 61c69c5563589b76b1857f0a9624f901e8f0ad69 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 6 Apr 2024 15:35:35 +0200 Subject: [PATCH 07/26] Use proper prefix for CollisionShapeType --- components/detournavigator/debug.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/detournavigator/debug.cpp b/components/detournavigator/debug.cpp index 835f37f999..4dcd5e9857 100644 --- a/components/detournavigator/debug.cpp +++ b/components/detournavigator/debug.cpp @@ -79,13 +79,13 @@ namespace DetourNavigator switch (v) { case CollisionShapeType::Aabb: - return s << "AgentShapeType::Aabb"; + return s << "CollisionShapeType::Aabb"; case CollisionShapeType::RotatingBox: - return s << "AgentShapeType::RotatingBox"; + return s << "CollisionShapeType::RotatingBox"; case CollisionShapeType::Cylinder: - return s << "AgentShapeType::Cylinder"; + return s << "CollisionShapeType::Cylinder"; } - return s << "AgentShapeType::" << static_cast>(v); + return s << "CollisionShapeType::" << static_cast>(v); } std::ostream& operator<<(std::ostream& s, const AgentBounds& v) From d6f3d34f2f75078d8b897a89484dc5fcbc1ea546 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 6 Apr 2024 15:40:42 +0200 Subject: [PATCH 08/26] Remove tiles present on navmesh but outside desired area --- .../detournavigator/navigator.cpp | 90 +++++++++++++++++++ .../detournavigator/navmeshcacheitem.hpp | 9 ++ components/detournavigator/navmeshmanager.cpp | 8 +- 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index b61a88662b..6dcade083a 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -1055,6 +1055,96 @@ namespace } } + TEST_P(DetourNavigatorUpdateTest, update_should_change_covered_area_when_player_moves_without_waiting_for_all) + { + Loading::Listener listener; + Settings settings = makeSettings(); + settings.mMaxTilesNumber = 1; + settings.mWaitUntilMinDistanceToPlayer = 1; + NavigatorImpl navigator(settings, nullptr); + const AgentBounds agentBounds{ CollisionShapeType::Aabb, { 29, 29, 66 } }; + ASSERT_TRUE(navigator.addAgent(agentBounds)); + + GetParam()(navigator); + + { + auto updateGuard = navigator.makeUpdateGuard(); + navigator.update(osg::Vec3f(3000, 3000, 0), updateGuard.get()); + } + + navigator.wait(WaitConditionType::requiredTilesPresent, &listener); + + { + const auto navMesh = navigator.getNavMesh(agentBounds); + ASSERT_NE(navMesh, nullptr); + + const TilePosition expectedTile(4, 4); + const auto usedTiles = getUsedTiles(*navMesh->lockConst()); + EXPECT_THAT(usedTiles, Contains(expectedTile)) << usedTiles; + } + + { + auto updateGuard = navigator.makeUpdateGuard(); + navigator.update(osg::Vec3f(6000, 3000, 0), updateGuard.get()); + } + + navigator.wait(WaitConditionType::requiredTilesPresent, &listener); + + { + const auto navMesh = navigator.getNavMesh(agentBounds); + ASSERT_NE(navMesh, nullptr); + + const TilePosition expectedTile(8, 4); + const auto usedTiles = getUsedTiles(*navMesh->lockConst()); + EXPECT_THAT(usedTiles, Contains(expectedTile)) << usedTiles; + } + } + + TEST_P(DetourNavigatorUpdateTest, update_should_change_covered_area_when_player_moves_with_db) + { + Loading::Listener listener; + Settings settings = makeSettings(); + settings.mMaxTilesNumber = 1; + settings.mWaitUntilMinDistanceToPlayer = 1; + NavigatorImpl navigator(settings, std::make_unique(":memory:", settings.mMaxDbFileSize)); + const AgentBounds agentBounds{ CollisionShapeType::Aabb, { 29, 29, 66 } }; + ASSERT_TRUE(navigator.addAgent(agentBounds)); + + GetParam()(navigator); + + { + auto updateGuard = navigator.makeUpdateGuard(); + navigator.update(osg::Vec3f(3000, 3000, 0), updateGuard.get()); + } + + navigator.wait(WaitConditionType::requiredTilesPresent, &listener); + + { + const auto navMesh = navigator.getNavMesh(agentBounds); + ASSERT_NE(navMesh, nullptr); + + const TilePosition expectedTile(4, 4); + const auto usedTiles = getUsedTiles(*navMesh->lockConst()); + EXPECT_THAT(usedTiles, Contains(expectedTile)) << usedTiles; + } + + { + auto updateGuard = navigator.makeUpdateGuard(); + navigator.update(osg::Vec3f(6000, 3000, 0), updateGuard.get()); + } + + navigator.wait(WaitConditionType::requiredTilesPresent, &listener); + + { + const auto navMesh = navigator.getNavMesh(agentBounds); + ASSERT_NE(navMesh, nullptr); + + const TilePosition expectedTile(8, 4); + const auto usedTiles = getUsedTiles(*navMesh->lockConst()); + EXPECT_THAT(usedTiles, Contains(expectedTile)) << usedTiles; + } + } + struct AddHeightfieldSurface { static constexpr std::size_t sSize = 65; diff --git a/components/detournavigator/navmeshcacheitem.hpp b/components/detournavigator/navmeshcacheitem.hpp index ec76b56a46..120a374195 100644 --- a/components/detournavigator/navmeshcacheitem.hpp +++ b/components/detournavigator/navmeshcacheitem.hpp @@ -131,6 +131,15 @@ namespace DetourNavigator function(position, tile.mVersion, *meshTile); } + template + void forEachTilePosition(Function&& function) const + { + for (const auto& [position, tile] : mUsedTiles) + function(position); + for (const TilePosition& position : mEmptyTiles) + function(position); + } + private: struct Tile { diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index e6f831bb6e..ea20f8bc34 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -13,8 +13,6 @@ #include -#include - namespace { /// Safely reset shared_ptr with definite underlying object destrutor call. @@ -179,9 +177,9 @@ namespace DetourNavigator { std::map tilesToPost = changedTiles; { + const int maxTiles = mSettings.mMaxTilesNumber; const auto locked = cached->lockConst(); const auto& navMesh = locked->getImpl(); - const int maxTiles = mSettings.mMaxTilesNumber; getTilesPositions(range, [&](const TilePosition& tile) { if (changedTiles.find(tile) != changedTiles.end()) return; @@ -192,6 +190,10 @@ namespace DetourNavigator else if (!shouldAdd && presentInNavMesh) tilesToPost.emplace(tile, ChangeType::mixed); }); + locked->forEachTilePosition([&](const TilePosition& tile) { + if (!shouldAddTile(tile, playerTile, maxTiles)) + tilesToPost.emplace(tile, ChangeType::remove); + }); } mAsyncNavMeshUpdater.post(agentBounds, cached, playerTile, mWorldspace, tilesToPost); Log(Debug::Debug) << "Cache update posted for agent=" << agentBounds << " playerTile=" << playerTile From 17bd571a65e5d445cea4b84eb0309fa0976f1da8 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 12 Apr 2024 18:37:56 +0200 Subject: [PATCH 09/26] Do not repost failed jobs Failures should not happen except for some weird corner cases. Retrying is unlikely to help in such situation. --- .../detournavigator/asyncnavmeshupdater.cpp | 23 ++----------------- .../detournavigator/asyncnavmeshupdater.hpp | 2 -- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 1ea7b63429..bb04c2af07 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -343,7 +343,8 @@ namespace DetourNavigator removeJob(job); break; case JobStatus::Fail: - repost(job); + unlockTile(job->mId, job->mAgentBounds, job->mChangedTile); + removeJob(job); break; case JobStatus::MemoryCacheMiss: { @@ -608,26 +609,6 @@ namespace DetourNavigator writeToFile(shared->lockConst()->getImpl(), mSettings.get().mNavMeshPathPrefix, navMeshRevision); } - void AsyncNavMeshUpdater::repost(JobIt job) - { - unlockTile(job->mId, job->mAgentBounds, job->mChangedTile); - - if (mShouldStop || job->mTryNumber > 2) - return; - - const std::lock_guard lock(mMutex); - - if (mPushed.emplace(job->mAgentBounds, job->mChangedTile).second) - { - ++job->mTryNumber; - insertPrioritizedJob(job, mWaiting); - mHasJob.notify_all(); - return; - } - - mJobs.erase(job); - } - bool AsyncNavMeshUpdater::lockTile( std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile) { diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 9b95d4f4b3..09119556cd 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -197,8 +197,6 @@ namespace DetourNavigator void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const; - void repost(JobIt job); - bool lockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile); void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile); From 50f4471750d934c238244ae5e408d69bf681dc0c Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 6 Apr 2024 01:10:48 +0200 Subject: [PATCH 10/26] Use R-tree for dynamic priority of navmesh async job --- .../detournavigator/asyncnavmeshupdater.cpp | 271 +++++++++++++++- .../detournavigator/asyncnavmeshupdater.cpp | 305 ++++++++++++------ .../detournavigator/asyncnavmeshupdater.hpp | 75 ++++- components/detournavigator/changetype.hpp | 10 +- components/detournavigator/debug.cpp | 2 - components/detournavigator/navmeshmanager.cpp | 2 +- components/detournavigator/stats.cpp | 8 +- components/detournavigator/stats.hpp | 11 +- .../tilecachedrecastmeshmanager.cpp | 3 +- components/resource/stats.cpp | 11 +- 10 files changed, 572 insertions(+), 126 deletions(-) diff --git a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp index bc1288f5f6..51ab37b123 100644 --- a/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp +++ b/apps/openmw_test_suite/detournavigator/asyncnavmeshupdater.cpp @@ -267,7 +267,6 @@ namespace updater.wait(WaitConditionType::allJobsDone, &mListener); updater.stop(); const std::set present{ - TilePosition(-2, 0), TilePosition(-1, -1), TilePosition(-1, 0), TilePosition(-1, 1), @@ -278,6 +277,7 @@ namespace TilePosition(0, 2), TilePosition(1, -1), TilePosition(1, 0), + TilePosition(1, 1), }; for (int x = -5; x <= 5; ++x) for (int y = -5; y <= 5; ++y) @@ -336,4 +336,273 @@ namespace EXPECT_EQ(tile->mTileId, 2); EXPECT_EQ(tile->mVersion, navMeshFormatVersion); } + + TEST_F(DetourNavigatorAsyncNavMeshUpdaterTest, repeated_tile_updates_should_be_delayed) + { + mRecastMeshManager.setWorldspace(mWorldspace, nullptr); + + mSettings.mMaxTilesNumber = 9; + mSettings.mMinUpdateInterval = std::chrono::milliseconds(250); + + AsyncNavMeshUpdater updater(mSettings, mRecastMeshManager, mOffMeshConnectionsManager, nullptr); + const auto navMeshCacheItem = std::make_shared(1, mSettings); + + std::map changedTiles; + + for (int x = -3; x <= 3; ++x) + for (int y = -3; y <= 3; ++y) + changedTiles.emplace(TilePosition{ x, y }, ChangeType::update); + + updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); + + updater.wait(WaitConditionType::allJobsDone, &mListener); + + { + const AsyncNavMeshUpdaterStats stats = updater.getStats(); + EXPECT_EQ(stats.mJobs, 0); + EXPECT_EQ(stats.mWaiting.mDelayed, 0); + } + + updater.post(mAgentBounds, navMeshCacheItem, mPlayerTile, mWorldspace, changedTiles); + + { + const AsyncNavMeshUpdaterStats stats = updater.getStats(); + EXPECT_EQ(stats.mJobs, 49); + EXPECT_EQ(stats.mWaiting.mDelayed, 49); + } + + updater.wait(WaitConditionType::allJobsDone, &mListener); + + { + const AsyncNavMeshUpdaterStats stats = updater.getStats(); + EXPECT_EQ(stats.mJobs, 0); + EXPECT_EQ(stats.mWaiting.mDelayed, 0); + } + } + + struct DetourNavigatorSpatialJobQueueTest : Test + { + const AgentBounds mAgentBounds{ CollisionShapeType::Aabb, osg::Vec3f(1, 1, 1) }; + const std::shared_ptr mNavMeshCacheItemPtr; + const std::weak_ptr mNavMeshCacheItem = mNavMeshCacheItemPtr; + const std::string_view mWorldspace = "worldspace"; + const TilePosition mChangedTile{ 0, 0 }; + const std::chrono::steady_clock::time_point mProcessTime{}; + const TilePosition mPlayerTile{ 0, 0 }; + const int mMaxTiles = 9; + }; + + TEST_F(DetourNavigatorSpatialJobQueueTest, should_store_multiple_jobs_per_tile) + { + std::list jobs; + SpatialJobQueue queue; + + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, "worldspace1", mChangedTile, + ChangeType::remove, mProcessTime)); + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, "worldspace2", mChangedTile, + ChangeType::update, mProcessTime)); + + ASSERT_EQ(queue.size(), 2); + + const auto job1 = queue.pop(mChangedTile); + ASSERT_TRUE(job1.has_value()); + EXPECT_EQ((*job1)->mWorldspace, "worldspace1"); + + const auto job2 = queue.pop(mChangedTile); + ASSERT_TRUE(job2.has_value()); + EXPECT_EQ((*job2)->mWorldspace, "worldspace2"); + + EXPECT_EQ(queue.size(), 0); + } + + struct DetourNavigatorJobQueueTest : DetourNavigatorSpatialJobQueueTest + { + }; + + TEST_F(DetourNavigatorJobQueueTest, pop_should_return_nullptr_from_empty) + { + JobQueue queue; + ASSERT_FALSE(queue.hasJob()); + ASSERT_FALSE(queue.pop(mPlayerTile).has_value()); + } + + TEST_F(DetourNavigatorJobQueueTest, push_on_change_type_remove_should_add_to_removing) + { + const std::chrono::steady_clock::time_point processTime{}; + + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::remove, processTime); + + JobQueue queue; + queue.push(job); + + EXPECT_EQ(queue.getStats().mRemoving, 1); + } + + TEST_F(DetourNavigatorJobQueueTest, pop_should_return_last_removing) + { + std::list jobs; + JobQueue queue; + + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(0, 0), + ChangeType::remove, mProcessTime)); + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(1, 0), + ChangeType::remove, mProcessTime)); + + ASSERT_TRUE(queue.hasJob()); + const auto job = queue.pop(mPlayerTile); + ASSERT_TRUE(job.has_value()); + EXPECT_EQ((*job)->mChangedTile, TilePosition(1, 0)); + } + + TEST_F(DetourNavigatorJobQueueTest, push_on_change_type_not_remove_should_add_to_updating) + { + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, mProcessTime); + + JobQueue queue; + queue.push(job); + + EXPECT_EQ(queue.getStats().mUpdating, 1); + } + + TEST_F(DetourNavigatorJobQueueTest, pop_should_return_nearest_to_player_tile) + { + std::list jobs; + + JobQueue queue; + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(0, 0), + ChangeType::update, mProcessTime)); + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(1, 0), + ChangeType::update, mProcessTime)); + + ASSERT_TRUE(queue.hasJob()); + const auto job = queue.pop(TilePosition(1, 0)); + ASSERT_TRUE(job.has_value()); + EXPECT_EQ((*job)->mChangedTile, TilePosition(1, 0)); + } + + TEST_F(DetourNavigatorJobQueueTest, push_on_processing_time_more_than_now_should_add_to_delayed) + { + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point processTime = now + std::chrono::seconds(1); + + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, processTime); + + JobQueue queue; + queue.push(job, now); + + EXPECT_EQ(queue.getStats().mDelayed, 1); + } + + TEST_F(DetourNavigatorJobQueueTest, pop_should_return_when_delayed_job_is_ready) + { + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point processTime = now + std::chrono::seconds(1); + + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, processTime); + + JobQueue queue; + queue.push(job, now); + + ASSERT_FALSE(queue.hasJob(now)); + ASSERT_FALSE(queue.pop(mPlayerTile, now).has_value()); + + ASSERT_TRUE(queue.hasJob(processTime)); + EXPECT_TRUE(queue.pop(mPlayerTile, processTime).has_value()); + } + + TEST_F(DetourNavigatorJobQueueTest, update_should_move_ready_delayed_to_updating) + { + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point processTime = now + std::chrono::seconds(1); + + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, processTime); + + JobQueue queue; + queue.push(job, now); + + ASSERT_EQ(queue.getStats().mDelayed, 1); + + queue.update(mPlayerTile, mMaxTiles, processTime); + + EXPECT_EQ(queue.getStats().mDelayed, 0); + EXPECT_EQ(queue.getStats().mUpdating, 1); + } + + TEST_F(DetourNavigatorJobQueueTest, update_should_move_ready_delayed_to_removing_when_out_of_range) + { + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point processTime = now + std::chrono::seconds(1); + + std::list jobs; + const JobIt job = jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, processTime); + + JobQueue queue; + queue.push(job, now); + + ASSERT_EQ(queue.getStats().mDelayed, 1); + + queue.update(TilePosition(10, 10), mMaxTiles, processTime); + + EXPECT_EQ(queue.getStats().mDelayed, 0); + EXPECT_EQ(queue.getStats().mRemoving, 1); + EXPECT_EQ(job->mChangeType, ChangeType::remove); + } + + TEST_F(DetourNavigatorJobQueueTest, update_should_move_updating_to_removing_when_out_of_range) + { + std::list jobs; + + JobQueue queue; + queue.push(jobs.emplace( + jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, mChangedTile, ChangeType::update, mProcessTime)); + queue.push(jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(10, 10), + ChangeType::update, mProcessTime)); + + ASSERT_EQ(queue.getStats().mUpdating, 2); + + queue.update(TilePosition(10, 10), mMaxTiles); + + EXPECT_EQ(queue.getStats().mUpdating, 1); + EXPECT_EQ(queue.getStats().mRemoving, 1); + } + + TEST_F(DetourNavigatorJobQueueTest, clear_should_remove_all) + { + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point processTime = now + std::chrono::seconds(1); + + std::list jobs; + const JobIt removing = jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, + TilePosition(0, 0), ChangeType::remove, mProcessTime); + const JobIt updating = jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, + TilePosition(1, 0), ChangeType::update, mProcessTime); + const JobIt delayed = jobs.emplace(jobs.end(), mAgentBounds, mNavMeshCacheItem, mWorldspace, TilePosition(2, 0), + ChangeType::update, processTime); + + JobQueue queue; + queue.push(removing); + queue.push(updating); + queue.push(delayed, now); + + ASSERT_EQ(queue.getStats().mRemoving, 1); + ASSERT_EQ(queue.getStats().mUpdating, 1); + ASSERT_EQ(queue.getStats().mDelayed, 1); + + queue.clear(); + + EXPECT_EQ(queue.getStats().mRemoving, 0); + EXPECT_EQ(queue.getStats().mUpdating, 0); + EXPECT_EQ(queue.getStats().mDelayed, 0); + } } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index bb04c2af07..fe6d0625f5 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -16,8 +16,9 @@ #include +#include + #include -#include #include #include #include @@ -49,40 +50,6 @@ namespace DetourNavigator return false; } - auto getPriority(const Job& job) noexcept - { - return std::make_tuple(-static_cast>(job.mState), job.mProcessTime, - job.mChangeType, job.mTryNumber, job.mDistanceToPlayer, job.mDistanceToOrigin); - } - - struct LessByJobPriority - { - bool operator()(JobIt lhs, JobIt rhs) const noexcept { return getPriority(*lhs) < getPriority(*rhs); } - }; - - void insertPrioritizedJob(JobIt job, std::deque& queue) - { - const auto it = std::upper_bound(queue.begin(), queue.end(), job, LessByJobPriority{}); - queue.insert(it, job); - } - - auto getDbPriority(const Job& job) noexcept - { - return std::make_tuple(static_cast>(job.mState), job.mChangeType, - job.mDistanceToPlayer, job.mDistanceToOrigin); - } - - struct LessByJobDbPriority - { - bool operator()(JobIt lhs, JobIt rhs) const noexcept { return getDbPriority(*lhs) < getDbPriority(*rhs); } - }; - - void insertPrioritizedDbJob(JobIt job, std::deque& queue) - { - const auto it = std::upper_bound(queue.begin(), queue.end(), job, LessByJobDbPriority{}); - queue.insert(it, job); - } - auto getAgentAndTile(const Job& job) noexcept { return std::make_tuple(job.mAgentBounds, job.mChangedTile); @@ -97,16 +64,6 @@ namespace DetourNavigator settings.mRecast, settings.mWriteToNavMeshDb); } - void updateJobs(std::deque& jobs, TilePosition playerTile, int maxTiles) - { - for (JobIt job : jobs) - { - job->mDistanceToPlayer = getManhattanDistance(job->mChangedTile, playerTile); - if (!shouldAddTile(job->mChangedTile, playerTile, maxTiles)) - job->mChangeType = ChangeType::remove; - } - } - std::size_t getNextJobId() { static std::atomic_size_t nextJobId{ 1 }; @@ -134,7 +91,7 @@ namespace DetourNavigator } Job::Job(const AgentBounds& agentBounds, std::weak_ptr navMeshCacheItem, - std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, int distanceToPlayer, + std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, std::chrono::steady_clock::time_point processTime) : mId(getNextJobId()) , mAgentBounds(agentBounds) @@ -143,11 +100,148 @@ namespace DetourNavigator , mChangedTile(changedTile) , mProcessTime(processTime) , mChangeType(changeType) - , mDistanceToPlayer(distanceToPlayer) - , mDistanceToOrigin(getManhattanDistance(changedTile, TilePosition{ 0, 0 })) { } + void SpatialJobQueue::clear() + { + mValues.clear(); + mIndex.clear(); + mSize = 0; + } + + void SpatialJobQueue::push(JobIt job) + { + auto it = mValues.find(job->mChangedTile); + + if (it == mValues.end()) + { + it = mValues.emplace_hint(it, job->mChangedTile, std::deque()); + mIndex.insert(IndexValue(IndexPoint(job->mChangedTile.x(), job->mChangedTile.y()), it)); + } + + it->second.push_back(job); + + ++mSize; + } + + std::optional SpatialJobQueue::pop(TilePosition playerTile) + { + const IndexPoint point(playerTile.x(), playerTile.y()); + const auto it = mIndex.qbegin(boost::geometry::index::nearest(point, 1)); + + if (it == mIndex.qend()) + return std::nullopt; + + const UpdatingMap::iterator mapIt = it->second; + std::deque& tileJobs = mapIt->second; + JobIt result = tileJobs.front(); + tileJobs.pop_front(); + + --mSize; + + if (tileJobs.empty()) + { + mValues.erase(mapIt); + mIndex.remove(*it); + } + + return result; + } + + void SpatialJobQueue::update(TilePosition playerTile, int maxTiles, std::vector& removing) + { + for (auto it = mValues.begin(); it != mValues.end();) + { + if (shouldAddTile(it->first, playerTile, maxTiles)) + { + ++it; + continue; + } + + for (JobIt job : it->second) + { + job->mChangeType = ChangeType::remove; + removing.push_back(job); + } + + mSize -= it->second.size(); + mIndex.remove(IndexValue(IndexPoint(it->first.x(), it->first.y()), it)); + it = mValues.erase(it); + } + } + + bool JobQueue::hasJob(std::chrono::steady_clock::time_point now) const + { + return !mRemoving.empty() || mUpdating.size() > 0 + || (!mDelayed.empty() && mDelayed.front()->mProcessTime <= now); + } + + void JobQueue::clear() + { + mRemoving.clear(); + mDelayed.clear(); + mUpdating.clear(); + } + + void JobQueue::push(JobIt job, std::chrono::steady_clock::time_point now) + { + if (job->mProcessTime > now) + { + mDelayed.push_back(job); + return; + } + + if (job->mChangeType == ChangeType::remove) + { + mRemoving.push_back(job); + return; + } + + mUpdating.push(job); + } + + std::optional JobQueue::pop(TilePosition playerTile, std::chrono::steady_clock::time_point now) + { + if (!mRemoving.empty()) + { + const JobIt result = mRemoving.back(); + mRemoving.pop_back(); + return result; + } + + if (const std::optional result = mUpdating.pop(playerTile)) + return result; + + if (mDelayed.empty() || mDelayed.front()->mProcessTime > now) + return std::nullopt; + + const JobIt result = mDelayed.front(); + mDelayed.pop_front(); + return result; + } + + void JobQueue::update(TilePosition playerTile, int maxTiles, std::chrono::steady_clock::time_point now) + { + mUpdating.update(playerTile, maxTiles, mRemoving); + + while (!mDelayed.empty() && mDelayed.front()->mProcessTime <= now) + { + const JobIt job = mDelayed.front(); + mDelayed.pop_front(); + + if (shouldAddTile(job->mChangedTile, playerTile, maxTiles)) + { + mUpdating.push(job); + } + else + { + job->mChangeType = ChangeType::remove; + mRemoving.push_back(job); + } + } + } + AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager, OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr&& db) : mSettings(settings) @@ -183,42 +277,44 @@ namespace DetourNavigator std::unique_lock lock(mMutex); if (playerTileChanged) - updateJobs(mWaiting, playerTile, mSettings.get().mMaxTilesNumber); + { + Log(Debug::Debug) << "Player tile has been changed to " << playerTile; + mWaiting.update(playerTile, mSettings.get().mMaxTilesNumber); + } for (const auto& [changedTile, changeType] : changedTiles) { if (mPushed.emplace(agentBounds, changedTile).second) { - const auto processTime = changeType == ChangeType::update - ? mLastUpdates[std::tie(agentBounds, changedTile)] + mSettings.get().mMinUpdateInterval - : std::chrono::steady_clock::time_point(); + const auto processTime = [&, changedTile = changedTile, changeType = changeType] { + if (changeType != ChangeType::update) + return std::chrono::steady_clock::time_point(); + const auto lastUpdate = mLastUpdates.find(std::tie(agentBounds, changedTile)); + if (lastUpdate == mLastUpdates.end()) + return std::chrono::steady_clock::time_point(); + return lastUpdate->second + mSettings.get().mMinUpdateInterval; + }(); - const JobIt it = mJobs.emplace(mJobs.end(), agentBounds, navMeshCacheItem, worldspace, changedTile, - changeType, getManhattanDistance(changedTile, playerTile), processTime); + const JobIt it = mJobs.emplace( + mJobs.end(), agentBounds, navMeshCacheItem, worldspace, changedTile, changeType, processTime); Log(Debug::Debug) << "Post job " << it->mId << " for agent=(" << it->mAgentBounds << ")" - << " changedTile=(" << it->mChangedTile << ") " + << " changedTile=(" << it->mChangedTile << ")" << " changeType=" << it->mChangeType; - if (playerTileChanged) - mWaiting.push_back(it); - else - insertPrioritizedJob(it, mWaiting); + mWaiting.push(it); } } - if (playerTileChanged) - std::sort(mWaiting.begin(), mWaiting.end(), LessByJobPriority{}); - Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs"; - if (!mWaiting.empty()) + if (mWaiting.hasJob()) mHasJob.notify_all(); lock.unlock(); if (playerTileChanged && mDbWorker != nullptr) - mDbWorker->updateJobs(playerTile, mSettings.get().mMaxTilesNumber); + mDbWorker->update(playerTile); } void AsyncNavMeshUpdater::wait(WaitConditionType waitConditionType, Loading::Listener* listener) @@ -310,7 +406,7 @@ namespace DetourNavigator { const std::lock_guard lock(mMutex); result.mJobs = mJobs.size(); - result.mWaiting = mWaiting.size(); + result.mWaiting = mWaiting.getStats(); result.mPushed = mPushed.size(); } result.mProcessing = mProcessingTiles.lockConst()->size(); @@ -332,7 +428,8 @@ namespace DetourNavigator if (JobIt job = getNextJob(); job != mJobs.end()) { const JobStatus status = processJob(*job); - Log(Debug::Debug) << "Processed job " << job->mId << " with status=" << status; + Log(Debug::Debug) << "Processed job " << job->mId << " with status=" << status + << " changeType=" << job->mChangeType; switch (status) { case JobStatus::Done: @@ -366,7 +463,9 @@ namespace DetourNavigator JobStatus AsyncNavMeshUpdater::processJob(Job& job) { - Log(Debug::Debug) << "Processing job " << job.mId << " by thread=" << std::this_thread::get_id(); + Log(Debug::Debug) << "Processing job " << job.mId << " for agent=(" << job.mAgentBounds << ")" + << " changedTile=(" << job.mChangedTile << ")" + << " changeType=" << job.mChangeType << " by thread=" << std::this_thread::get_id(); const auto navMeshCacheItem = job.mNavMeshCacheItem.lock(); @@ -378,6 +477,7 @@ namespace DetourNavigator if (!shouldAddTile(job.mChangedTile, playerTile, mSettings.get().mMaxTilesNumber)) { Log(Debug::Debug) << "Ignore add tile by job " << job.mId << ": too far from player"; + job.mChangeType = ChangeType::remove; navMeshCacheItem->lock()->removeTile(job.mChangedTile); return JobStatus::Done; } @@ -545,9 +645,8 @@ namespace DetourNavigator bool shouldStop = false; const auto hasJob = [&] { - shouldStop = mShouldStop; - return shouldStop - || (!mWaiting.empty() && mWaiting.front()->mProcessTime <= std::chrono::steady_clock::now()); + shouldStop = mShouldStop.load(); + return shouldStop || mWaiting.hasJob(); }; if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob)) @@ -560,9 +659,15 @@ namespace DetourNavigator if (shouldStop) return mJobs.end(); - const JobIt job = mWaiting.front(); + const TilePosition playerTile = *mPlayerTile.lockConst(); - mWaiting.pop_front(); + JobIt job = mJobs.end(); + + if (const std::optional nextJob = mWaiting.pop(playerTile)) + job = *nextJob; + + if (job == mJobs.end()) + return job; Log(Debug::Debug) << "Pop job " << job->mId << " by thread=" << std::this_thread::get_id(); @@ -571,9 +676,9 @@ namespace DetourNavigator if (!lockTile(job->mId, job->mAgentBounds, job->mChangedTile)) { - Log(Debug::Debug) << "Failed to lock tile by job " << job->mId << " try=" << job->mTryNumber; - ++job->mTryNumber; - insertPrioritizedJob(job, mWaiting); + Log(Debug::Debug) << "Failed to lock tile by job " << job->mId; + job->mProcessTime = std::chrono::steady_clock::now() + mSettings.get().mMinUpdateInterval; + mWaiting.push(job); return mJobs.end(); } @@ -653,7 +758,7 @@ namespace DetourNavigator { Log(Debug::Debug) << "Enqueueing job " << job->mId << " by thread=" << std::this_thread::get_id(); const std::lock_guard lock(mMutex); - insertPrioritizedJob(job, mWaiting); + mWaiting.push(job); mHasJob.notify_all(); } @@ -667,40 +772,47 @@ namespace DetourNavigator void DbJobQueue::push(JobIt job) { const std::lock_guard lock(mMutex); - insertPrioritizedDbJob(job, mJobs); if (isWritingDbJob(*job)) - ++mWritingJobs; + mWriting.push_back(job); else - ++mReadingJobs; + mReading.push(job); mHasJob.notify_all(); } std::optional DbJobQueue::pop() { std::unique_lock lock(mMutex); - mHasJob.wait(lock, [&] { return mShouldStop || !mJobs.empty(); }); - if (mJobs.empty()) + + const auto hasJob = [&] { return mShouldStop || mReading.size() > 0 || mWriting.size() > 0; }; + + mHasJob.wait(lock, hasJob); + + if (mShouldStop) return std::nullopt; - const JobIt job = mJobs.front(); - mJobs.pop_front(); - if (isWritingDbJob(*job)) - --mWritingJobs; - else - --mReadingJobs; + + if (const std::optional job = mReading.pop(mPlayerTile)) + return job; + + if (mWriting.empty()) + return std::nullopt; + + const JobIt job = mWriting.front(); + mWriting.pop_front(); + return job; } - void DbJobQueue::update(TilePosition playerTile, int maxTiles) + void DbJobQueue::update(TilePosition playerTile) { const std::lock_guard lock(mMutex); - updateJobs(mJobs, playerTile, maxTiles); - std::sort(mJobs.begin(), mJobs.end(), LessByJobDbPriority{}); + mPlayerTile = playerTile; } void DbJobQueue::stop() { const std::lock_guard lock(mMutex); - mJobs.clear(); + mReading.clear(); + mWriting.clear(); mShouldStop = true; mHasJob.notify_all(); } @@ -708,7 +820,10 @@ namespace DetourNavigator DbJobQueueStats DbJobQueue::getStats() const { const std::lock_guard lock(mMutex); - return DbJobQueueStats{ .mWritingJobs = mWritingJobs, .mReadingJobs = mReadingJobs }; + return DbJobQueueStats{ + .mReadingJobs = mReading.size(), + .mWritingJobs = mWriting.size(), + }; } DbWorker::DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr&& db, TileVersion version, @@ -737,8 +852,10 @@ namespace DetourNavigator DbWorkerStats DbWorker::getStats() const { - return DbWorkerStats{ .mJobs = mQueue.getStats(), - .mGetTileCount = mGetTileCount.load(std::memory_order_relaxed) }; + return DbWorkerStats{ + .mJobs = mQueue.getStats(), + .mGetTileCount = mGetTileCount.load(std::memory_order_relaxed), + }; } void DbWorker::stop() diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 09119556cd..f3d624a8a6 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -14,6 +14,9 @@ #include "tileposition.hpp" #include "waitconditiontype.hpp" +#include +#include + #include #include #include @@ -49,11 +52,8 @@ namespace DetourNavigator const std::weak_ptr mNavMeshCacheItem; const std::string mWorldspace; const TilePosition mChangedTile; - const std::chrono::steady_clock::time_point mProcessTime; - unsigned mTryNumber = 0; + std::chrono::steady_clock::time_point mProcessTime; ChangeType mChangeType; - int mDistanceToPlayer; - const int mDistanceToOrigin; JobState mState = JobState::Initial; std::vector mInput; std::shared_ptr mRecastMesh; @@ -61,12 +61,65 @@ namespace DetourNavigator std::unique_ptr mGeneratedNavMeshData; Job(const AgentBounds& agentBounds, std::weak_ptr navMeshCacheItem, - std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, int distanceToPlayer, + std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, std::chrono::steady_clock::time_point processTime); }; using JobIt = std::list::iterator; + class SpatialJobQueue + { + public: + std::size_t size() const { return mSize; } + + void clear(); + + void push(JobIt job); + + std::optional pop(TilePosition playerTile); + + void update(TilePosition playerTile, int maxTiles, std::vector& removing); + + private: + using IndexPoint = boost::geometry::model::point; + using UpdatingMap = std::map>; + using IndexValue = std::pair; + + std::size_t mSize = 0; + UpdatingMap mValues; + boost::geometry::index::rtree> mIndex; + }; + + class JobQueue + { + public: + JobQueueStats getStats() const + { + return JobQueueStats{ + .mRemoving = mRemoving.size(), + .mUpdating = mUpdating.size(), + .mDelayed = mDelayed.size(), + }; + } + + bool hasJob(std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()) const; + + void clear(); + + void push(JobIt job, std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()); + + std::optional pop( + TilePosition playerTile, std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()); + + void update(TilePosition playerTile, int maxTiles, + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now()); + + private: + std::vector mRemoving; + SpatialJobQueue mUpdating; + std::deque mDelayed; + }; + enum class JobStatus { Done, @@ -83,7 +136,7 @@ namespace DetourNavigator std::optional pop(); - void update(TilePosition playerTile, int maxTiles); + void update(TilePosition playerTile); void stop(); @@ -92,10 +145,10 @@ namespace DetourNavigator private: mutable std::mutex mMutex; std::condition_variable mHasJob; - std::deque mJobs; + SpatialJobQueue mReading; + std::deque mWriting; + TilePosition mPlayerTile; bool mShouldStop = false; - std::size_t mWritingJobs = 0; - std::size_t mReadingJobs = 0; }; class AsyncNavMeshUpdater; @@ -112,7 +165,7 @@ namespace DetourNavigator void enqueueJob(JobIt job); - void updateJobs(TilePosition playerTile, int maxTiles) { mQueue.update(playerTile, maxTiles); } + void update(TilePosition playerTile) { mQueue.update(playerTile); } void stop(); @@ -169,7 +222,7 @@ namespace DetourNavigator std::condition_variable mDone; std::condition_variable mProcessed; std::list mJobs; - std::deque mWaiting; + JobQueue mWaiting; std::set> mPushed; Misc::ScopeGuarded mPlayerTile; NavMeshTilesCache mNavMeshTilesCache; diff --git a/components/detournavigator/changetype.hpp b/components/detournavigator/changetype.hpp index e6d0bce0a9..63a43e88fb 100644 --- a/components/detournavigator/changetype.hpp +++ b/components/detournavigator/changetype.hpp @@ -6,15 +6,9 @@ namespace DetourNavigator enum class ChangeType { remove = 0, - mixed = 1, - add = 2, - update = 3, + add = 1, + update = 2, }; - - inline ChangeType addChangeType(const ChangeType current, const ChangeType add) - { - return current == add ? current : ChangeType::mixed; - } } #endif diff --git a/components/detournavigator/debug.cpp b/components/detournavigator/debug.cpp index 4dcd5e9857..5ce1464bdd 100644 --- a/components/detournavigator/debug.cpp +++ b/components/detournavigator/debug.cpp @@ -184,8 +184,6 @@ namespace DetourNavigator { case ChangeType::remove: return stream << "ChangeType::remove"; - case ChangeType::mixed: - return stream << "ChangeType::mixed"; case ChangeType::add: return stream << "ChangeType::add"; case ChangeType::update: diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index ea20f8bc34..3b62866ed7 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -188,7 +188,7 @@ namespace DetourNavigator if (shouldAdd && !presentInNavMesh) tilesToPost.emplace(tile, locked->isEmptyTile(tile) ? ChangeType::update : ChangeType::add); else if (!shouldAdd && presentInNavMesh) - tilesToPost.emplace(tile, ChangeType::mixed); + tilesToPost.emplace(tile, ChangeType::remove); }); locked->forEachTilePosition([&](const TilePosition& tile) { if (!shouldAddTile(tile, playerTile, maxTiles)) diff --git a/components/detournavigator/stats.cpp b/components/detournavigator/stats.cpp index 1d7dcac553..da56f91a38 100644 --- a/components/detournavigator/stats.cpp +++ b/components/detournavigator/stats.cpp @@ -9,16 +9,18 @@ namespace DetourNavigator void reportStats(const AsyncNavMeshUpdaterStats& stats, unsigned int frameNumber, osg::Stats& out) { out.setAttribute(frameNumber, "NavMesh Jobs", static_cast(stats.mJobs)); - out.setAttribute(frameNumber, "NavMesh Waiting", static_cast(stats.mWaiting)); + out.setAttribute(frameNumber, "NavMesh Removing", static_cast(stats.mWaiting.mRemoving)); + out.setAttribute(frameNumber, "NavMesh Updating", static_cast(stats.mWaiting.mUpdating)); + out.setAttribute(frameNumber, "NavMesh Delayed", static_cast(stats.mWaiting.mDelayed)); out.setAttribute(frameNumber, "NavMesh Pushed", static_cast(stats.mPushed)); out.setAttribute(frameNumber, "NavMesh Processing", static_cast(stats.mProcessing)); if (stats.mDb.has_value()) { - out.setAttribute( - frameNumber, "NavMesh DbJobs Write", static_cast(stats.mDb->mJobs.mWritingJobs)); out.setAttribute( frameNumber, "NavMesh DbJobs Read", static_cast(stats.mDb->mJobs.mReadingJobs)); + out.setAttribute( + frameNumber, "NavMesh DbJobs Write", static_cast(stats.mDb->mJobs.mWritingJobs)); out.setAttribute(frameNumber, "NavMesh DbCache Get", static_cast(stats.mDb->mGetTileCount)); out.setAttribute(frameNumber, "NavMesh DbCache Hit", static_cast(stats.mDbGetTileHits)); diff --git a/components/detournavigator/stats.hpp b/components/detournavigator/stats.hpp index c644f1db87..0b62b9e669 100644 --- a/components/detournavigator/stats.hpp +++ b/components/detournavigator/stats.hpp @@ -11,10 +11,17 @@ namespace osg namespace DetourNavigator { + struct JobQueueStats + { + std::size_t mRemoving = 0; + std::size_t mUpdating = 0; + std::size_t mDelayed = 0; + }; + struct DbJobQueueStats { - std::size_t mWritingJobs = 0; std::size_t mReadingJobs = 0; + std::size_t mWritingJobs = 0; }; struct DbWorkerStats @@ -35,7 +42,7 @@ namespace DetourNavigator struct AsyncNavMeshUpdaterStats { std::size_t mJobs = 0; - std::size_t mWaiting = 0; + JobQueueStats mWaiting; std::size_t mPushed = 0; std::size_t mProcessing = 0; std::size_t mDbGetTileHits = 0; diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 0bab808300..3e3927bf65 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -10,7 +10,6 @@ #include -#include #include #include @@ -416,7 +415,7 @@ namespace DetourNavigator if (tile == mChangedTiles.end()) mChangedTiles.emplace(tilePosition, changeType); else - tile->second = addChangeType(tile->second, changeType); + tile->second = changeType == ChangeType::remove ? changeType : tile->second; } std::map TileCachedRecastMeshManager::takeChangedTiles(const UpdateGuard* guard) diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index 65b009deff..9bb90635d1 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -49,6 +49,8 @@ namespace Resource std::vector generateAllStatNames() { + constexpr std::size_t itemsPerPage = 24; + constexpr std::string_view firstPage[] = { "FrameNumber", "", @@ -76,6 +78,8 @@ namespace Resource "", }; + static_assert(std::size(firstPage) == itemsPerPage); + constexpr std::string_view caches[] = { "Node", "Shape", @@ -100,7 +104,9 @@ namespace Resource constexpr std::string_view navMesh[] = { "NavMesh Jobs", - "NavMesh Waiting", + "NavMesh Removing", + "NavMesh Updating", + "NavMesh Delayed", "NavMesh Pushed", "NavMesh Processing", "NavMesh DbJobs Write", @@ -129,7 +135,8 @@ namespace Resource for (std::string_view name : cellPreloader) statNames.emplace_back(name); - statNames.emplace_back(); + while (statNames.size() % itemsPerPage != 0) + statNames.emplace_back(); for (std::string_view name : navMesh) statNames.emplace_back(name); From 910c88325a69f4166a468ae30b643641f9410ed0 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 7 Apr 2024 15:22:02 +0200 Subject: [PATCH 11/26] Add a setting to wait for all navmesh jobs on exit --- apps/openmw/mwworld/worldimp.cpp | 6 ++++++ components/settings/categories/navigator.hpp | 1 + docs/source/reference/modding/settings/navigator.rst | 10 ++++++++++ files/settings-default.cfg | 3 +++ 4 files changed, 20 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ec58f779d0..74335a1534 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -591,6 +591,12 @@ namespace MWWorld // Must be cleared before mRendering is destroyed if (mProjectileManager) mProjectileManager->clear(); + + if (Settings::navigator().mWaitForAllJobsOnExit) + { + Log(Debug::Verbose) << "Waiting for all navmesh jobs to be done..."; + mNavigator->wait(DetourNavigator::WaitConditionType::allJobsDone, nullptr); + } } void World::setRandomSeed(uint32_t seed) diff --git a/components/settings/categories/navigator.hpp b/components/settings/categories/navigator.hpp index d6d7adcd56..c65dd3392e 100644 --- a/components/settings/categories/navigator.hpp +++ b/components/settings/categories/navigator.hpp @@ -63,6 +63,7 @@ namespace Settings SettingValue mEnableNavMeshDiskCache{ mIndex, "Navigator", "enable nav mesh disk cache" }; SettingValue mWriteToNavmeshdb{ mIndex, "Navigator", "write to navmeshdb" }; SettingValue mMaxNavmeshdbFileSize{ mIndex, "Navigator", "max navmeshdb file size" }; + SettingValue mWaitForAllJobsOnExit{ mIndex, "Navigator", "wait for all jobs on exit" }; }; } diff --git a/docs/source/reference/modding/settings/navigator.rst b/docs/source/reference/modding/settings/navigator.rst index 55b9e19b19..6fafdcdfd2 100644 --- a/docs/source/reference/modding/settings/navigator.rst +++ b/docs/source/reference/modding/settings/navigator.rst @@ -245,6 +245,16 @@ Absent pieces usually mean a bug in recast mesh tiles building. Allows to do in-game debug. Potentially decreases performance. +wait for all jobs on exit +------------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Wait until all queued async navmesh jobs are processed before exiting the engine. +Useful when a benchmark generates jobs to write into navmeshdb faster than they are processed. + Expert settings *************** diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 2f236bf55a..10c25bb430 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -999,6 +999,9 @@ write to navmeshdb = true # Approximate maximum file size of navigation mesh cache stored on disk in bytes (value > 0) max navmeshdb file size = 2147483648 +# Wait until all queued async navmesh jobs are processed before exiting the engine (true, false) +wait for all jobs on exit = false + [Shadows] # Enable or disable shadows. Bear in mind that this will force OpenMW to use shaders as if "[Shaders]/force shaders" was set to true. From ea029b06eabc98d620ac63b9f6c60730708e601a Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 13 Apr 2024 18:51:45 +0100 Subject: [PATCH 12/26] Remove unused define --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93da5feec4..9e6e788c05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -710,7 +710,6 @@ if (WIN32) if (USE_DEBUG_CONSOLE AND BUILD_OPENMW) set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") - set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS $<$:_CONSOLE>) elseif (BUILD_OPENMW) # Turn off debug console, debug output will be written to visual studio output instead set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS") From 901a17ab81a4814d51dc7b5531cfef3cbdcabec3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 13 Apr 2024 19:01:34 +0100 Subject: [PATCH 13/26] Make comments stop lying --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e6e788c05..3360ac2e2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ else() endif(APPLE) if (WIN32) - option(USE_DEBUG_CONSOLE "whether a debug console should be enabled for debug builds, if false debug output is redirected to Visual Studio output" ON) + option(USE_DEBUG_CONSOLE "Whether a console should be displayed if OpenMW isn't launched from the command line. Does not affect the Release configuration." ON) endif() if(MSVC) @@ -711,7 +711,7 @@ if (WIN32) set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") elseif (BUILD_OPENMW) - # Turn off debug console, debug output will be written to visual studio output instead + # Turn off implicit console, you won't see stdout unless launching OpenMW from a command line shell or look at openmw.log set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS") set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS") endif() From 1ad9e5f9e897cce9d67058c40e32a9e4b10f2044 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 14 Apr 2024 08:17:10 +0400 Subject: [PATCH 14/26] Rework editor icons --- CI/before_script.msvc.sh | 22 +- CI/install_debian_deps.sh | 2 +- CMakeLists.txt | 10 +- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/main.cpp | 2 +- apps/opencs/model/world/tablemimedata.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 215 ++++++------ apps/opencs/view/doc/view.cpp | 43 ++- apps/opencs/view/filter/editwidget.cpp | 2 +- apps/opencs/view/render/mask.hpp | 9 +- .../view/render/pagedworldspacewidget.cpp | 8 +- apps/opencs/view/render/pathgridmode.cpp | 4 +- .../view/render/unpagedworldspacewidget.cpp | 1 - apps/opencs/view/render/worldspacewidget.hpp | 3 +- apps/opencs/view/world/recordbuttonbar.cpp | 2 +- apps/opencs/view/world/table.cpp | 4 +- .../model/world/testuniversalid.cpp | 29 +- files/opencs/activator.png | Bin 562 -> 0 bytes files/opencs/activator.svg | 126 +++++++ files/opencs/apparatus.png | Bin 364 -> 0 bytes files/opencs/apparatus.svg | 58 ++++ files/opencs/armor.png | Bin 473 -> 0 bytes files/opencs/armor.svg | 58 ++++ files/opencs/attribute.png | Bin 326 -> 0 bytes files/opencs/attribute.svg | 46 +++ files/opencs/birthsign.png | Bin 444 -> 0 bytes files/opencs/birthsign.svg | 94 +++++ files/opencs/body-part.png | Bin 418 -> 0 bytes files/opencs/body-part.svg | 58 ++++ files/opencs/book.png | Bin 323 -> 0 bytes files/opencs/book.svg | 166 +++++++++ files/opencs/brush-circle.png | Bin 1540 -> 0 bytes files/opencs/brush-circle.svg | 51 +++ files/opencs/brush-custom.png | Bin 2475 -> 0 bytes files/opencs/brush-custom.svg | 56 +++ files/opencs/brush-point.png | Bin 787 -> 0 bytes files/opencs/brush-point.svg | 65 ++++ files/opencs/brush-square.png | Bin 761 -> 0 bytes files/opencs/brush-square.svg | 52 +++ files/opencs/camera-first-person.png | Bin 750 -> 0 bytes files/opencs/camera-first-person.svg | 63 ++++ files/opencs/camera-free.png | Bin 783 -> 0 bytes files/opencs/camera-free.svg | 76 ++++ files/opencs/camera-orbit.png | Bin 1096 -> 0 bytes files/opencs/camera-orbit.svg | 62 ++++ files/opencs/cell.png | Bin 1212 -> 0 bytes files/opencs/cell.svg | 83 +++++ files/opencs/class.png | Bin 588 -> 0 bytes files/opencs/class.svg | 186 ++++++++++ files/opencs/clothing.png | Bin 369 -> 0 bytes files/opencs/clothing.svg | 101 ++++++ files/opencs/container.png | Bin 421 -> 0 bytes files/opencs/container.svg | 93 +++++ files/opencs/creature.png | Bin 463 -> 0 bytes files/opencs/creature.svg | 189 ++++++++++ files/opencs/debug-profile.png | Bin 431 -> 0 bytes files/opencs/debug-profile.svg | 115 +++++++ files/opencs/dialogue-greeting.png | Bin 386 -> 0 bytes files/opencs/dialogue-info.png | Bin 306 -> 0 bytes files/opencs/dialogue-info.svg | 89 +++++ files/opencs/dialogue-journal.png | Bin 288 -> 0 bytes files/opencs/dialogue-persuasion.png | Bin 362 -> 0 bytes files/opencs/dialogue-regular.png | Bin 221 -> 0 bytes files/opencs/dialogue-topic-infos.png | Bin 306 -> 0 bytes files/opencs/dialogue-topics.png | Bin 282 -> 0 bytes files/opencs/dialogue-topics.svg | 89 +++++ files/opencs/dialogue-voice.png | Bin 294 -> 0 bytes files/opencs/door.png | Bin 381 -> 0 bytes files/opencs/door.svg | 77 +++++ files/opencs/editing-instance.png | Bin 986 -> 0 bytes files/opencs/editing-instance.svg | 51 +++ files/opencs/editing-pathgrid.png | Bin 2297 -> 0 bytes files/opencs/editing-pathgrid.svg | 83 +++++ files/opencs/editing-terrain-movement.png | Bin 1745 -> 0 bytes files/opencs/editing-terrain-movement.svg | 58 ++++ files/opencs/editing-terrain-shape.png | Bin 1399 -> 0 bytes files/opencs/editing-terrain-shape.svg | 43 +++ files/opencs/editing-terrain-texture.png | Bin 2100 -> 0 bytes files/opencs/editing-terrain-texture.svg | 82 +++++ files/opencs/editing-terrain-vertex-paint.png | Bin 2545 -> 0 bytes files/opencs/editing-terrain-vertex-paint.svg | 111 ++++++ files/opencs/enchantment.png | Bin 422 -> 0 bytes files/opencs/enchantment.svg | 54 +++ files/opencs/error-log.png | Bin 518 -> 0 bytes files/opencs/error-log.svg | 134 ++++++++ files/opencs/faction.png | Bin 389 -> 0 bytes files/opencs/faction.svg | 73 ++++ files/opencs/filter.png | Bin 299 -> 0 bytes files/opencs/filter.svg | 61 ++++ files/opencs/global-variable.png | Bin 282 -> 0 bytes files/opencs/global-variable.svg | 86 +++++ files/opencs/gmst.png | Bin 338 -> 0 bytes files/opencs/gmst.svg | 114 ++++++ files/opencs/info.png | Bin 1234 -> 0 bytes files/opencs/info.svg | 85 +++++ files/opencs/ingredient.png | Bin 490 -> 0 bytes files/opencs/ingredient.svg | 97 ++++++ files/opencs/instance.png | Bin 618 -> 0 bytes files/opencs/instance.svg | 126 +++++++ files/opencs/journal-topic-infos.png | Bin 300 -> 0 bytes files/opencs/journal-topic-infos.svg | 97 ++++++ files/opencs/journal-topics.png | Bin 273 -> 0 bytes files/opencs/journal-topics.svg | 73 ++++ files/opencs/land-heightmap.png | Bin 193 -> 0 bytes files/opencs/land-heightmap.svg | 86 +++++ files/opencs/land-texture.png | Bin 288 -> 0 bytes files/opencs/land-texture.svg | 97 ++++++ files/opencs/levelled-creature.png | Bin 521 -> 0 bytes files/opencs/levelled-creature.svg | 198 +++++++++++ files/opencs/levelled-item.png | Bin 516 -> 0 bytes files/opencs/levelled-item.svg | 137 ++++++++ files/opencs/light.png | Bin 384 -> 0 bytes files/opencs/light.svg | 105 ++++++ files/opencs/lighting-lamp.png | Bin 953 -> 0 bytes files/opencs/lighting-lamp.svg | 40 +++ files/opencs/lighting-moon.png | Bin 1590 -> 0 bytes files/opencs/lighting-moon.svg | 50 +++ files/opencs/lighting-sun.png | Bin 1804 -> 0 bytes files/opencs/lighting-sun.svg | 143 ++++++++ files/opencs/list-added.png | Bin 166 -> 0 bytes files/opencs/list-added.svg | 101 ++++++ files/opencs/list-base.png | Bin 184 -> 0 bytes files/opencs/list-base.svg | 120 +++++++ files/opencs/list-modified.png | Bin 457 -> 0 bytes files/opencs/list-modified.svg | 101 ++++++ files/opencs/list-removed.png | Bin 134 -> 0 bytes files/opencs/list-removed.svg | 108 ++++++ files/opencs/lockpick.png | Bin 317 -> 0 bytes files/opencs/lockpick.svg | 108 ++++++ files/opencs/magic-effect.png | Bin 356 -> 0 bytes files/opencs/magic-effect.svg | 194 +++++++++++ files/opencs/menu-close.png | Bin 438 -> 0 bytes files/opencs/menu-close.svg | 202 +++++++++++ files/opencs/menu-exit.png | Bin 257 -> 0 bytes files/opencs/menu-exit.svg | 101 ++++++ files/opencs/menu-merge.png | Bin 219 -> 0 bytes files/opencs/menu-merge.svg | 126 +++++++ files/opencs/menu-new-addon.png | Bin 282 -> 0 bytes files/opencs/menu-new-addon.svg | 124 +++++++ files/opencs/menu-new-game.png | Bin 230 -> 0 bytes files/opencs/menu-new-game.svg | 111 ++++++ files/opencs/menu-new-window.png | Bin 213 -> 0 bytes files/opencs/menu-new-window.svg | 123 +++++++ files/opencs/menu-open.png | Bin 241 -> 0 bytes files/opencs/menu-open.svg | 111 ++++++ files/opencs/menu-preferences.png | Bin 385 -> 0 bytes files/opencs/menu-preferences.svg | 232 +++++++++++++ files/opencs/menu-redo.png | Bin 323 -> 0 bytes files/opencs/menu-redo.svg | 122 +++++++ files/opencs/menu-reload.png | Bin 447 -> 0 bytes files/opencs/menu-reload.svg | 111 ++++++ files/opencs/menu-save.png | Bin 302 -> 0 bytes files/opencs/menu-save.svg | 70 ++++ files/opencs/menu-search.png | Bin 408 -> 0 bytes files/opencs/menu-search.svg | 157 +++++++++ files/opencs/menu-status-bar.png | Bin 188 -> 0 bytes files/opencs/menu-status-bar.svg | 131 +++++++ files/opencs/menu-undo.png | Bin 323 -> 0 bytes files/opencs/menu-undo.svg | 130 +++++++ files/opencs/menu-verify.png | Bin 487 -> 0 bytes files/opencs/menu-verify.svg | 109 ++++++ files/opencs/metadata.png | Bin 389 -> 0 bytes files/opencs/metadata.svg | 173 ++++++++++ files/opencs/miscellaneous.png | Bin 466 -> 0 bytes files/opencs/miscellaneous.svg | 118 +++++++ files/opencs/multitype.png | Bin 1708 -> 0 bytes files/opencs/multitype.svg | 117 +++++++ files/opencs/npc.png | Bin 465 -> 0 bytes files/opencs/npc.svg | 316 +++++++++++++++++ files/opencs/object.png | Bin 447 -> 0 bytes files/opencs/object.svg | 118 +++++++ files/opencs/pathgrid.png | Bin 407 -> 0 bytes files/opencs/pathgrid.svg | 175 ++++++++++ files/opencs/potion.png | Bin 442 -> 0 bytes files/opencs/potion.svg | 146 ++++++++ files/opencs/probe.png | Bin 304 -> 0 bytes files/opencs/probe.svg | 134 ++++++++ files/opencs/qt.png | Bin 405 -> 0 bytes files/opencs/qt.svg | 180 ++++++++++ files/opencs/race.png | Bin 451 -> 0 bytes files/opencs/race.svg | 160 +++++++++ files/opencs/random.png | Bin 1892 -> 0 bytes files/opencs/record-add.png | Bin 238 -> 0 bytes files/opencs/record-add.svg | 134 ++++++++ files/opencs/record-clone.png | Bin 275 -> 0 bytes files/opencs/record-clone.svg | 158 +++++++++ files/opencs/record-delete.png | Bin 151 -> 0 bytes files/opencs/record-delete.svg | 142 ++++++++ files/opencs/record-down.png | Bin 150 -> 0 bytes files/opencs/record-down.svg | 144 ++++++++ files/opencs/record-edit.png | Bin 220 -> 0 bytes files/opencs/record-edit.svg | 132 +++++++ files/opencs/record-next.png | Bin 248 -> 0 bytes files/opencs/record-next.svg | 143 ++++++++ files/opencs/record-preview.png | Bin 334 -> 0 bytes files/opencs/record-preview.svg | 178 ++++++++++ files/opencs/record-previous.png | Bin 265 -> 0 bytes files/opencs/record-previous.svg | 143 ++++++++ files/opencs/record-revert.png | Bin 323 -> 0 bytes files/opencs/record-revert.svg | 154 +++++++++ files/opencs/record-touch.png | Bin 289 -> 0 bytes files/opencs/record-touch.svg | 143 ++++++++ files/opencs/record-up.png | Bin 150 -> 0 bytes files/opencs/record-up.svg | 144 ++++++++ files/opencs/region-map.png | Bin 428 -> 0 bytes files/opencs/region-map.svg | 155 +++++++++ files/opencs/region.png | Bin 605 -> 0 bytes files/opencs/region.svg | 143 ++++++++ files/opencs/repair.png | Bin 367 -> 0 bytes files/opencs/repair.svg | 119 +++++++ files/opencs/resources-icon.png | Bin 194 -> 0 bytes files/opencs/resources-icon.svg | 178 ++++++++++ files/opencs/resources-mesh.png | Bin 586 -> 0 bytes files/opencs/resources-mesh.svg | 153 +++++++++ files/opencs/resources-music.png | Bin 354 -> 0 bytes files/opencs/resources-music.svg | 216 ++++++++++++ files/opencs/resources-sound.png | Bin 222 -> 0 bytes files/opencs/resources-sound.svg | 142 ++++++++ files/opencs/resources-texture.png | Bin 288 -> 0 bytes files/opencs/resources-texture.svg | 154 +++++++++ files/opencs/resources-video.png | Bin 277 -> 0 bytes files/opencs/resources-video.svg | 155 +++++++++ files/opencs/resources.qrc | 324 ++++++++---------- files/opencs/run-game.png | Bin 642 -> 0 bytes files/opencs/run-game.svg | 135 ++++++++ files/opencs/run-log.png | Bin 294 -> 0 bytes files/opencs/run-log.svg | 83 +++++ files/opencs/run-openmw.png | Bin 388 -> 0 bytes files/opencs/run-openmw.svg | 133 +++++++ files/opencs/scalable/editor-icons.svg | 32 +- files/opencs/scene-exterior-arrows.png | Bin 511 -> 0 bytes files/opencs/scene-exterior-arrows.svg | 145 ++++++++ files/opencs/scene-exterior-borders.png | Bin 429 -> 0 bytes files/opencs/scene-exterior-borders.svg | 135 ++++++++ files/opencs/scene-exterior-markers.png | Bin 497 -> 0 bytes files/opencs/scene-exterior-markers.svg | 148 ++++++++ files/opencs/scene-exterior-status-0.png | Bin 1932 -> 0 bytes files/opencs/scene-exterior-status-0.svg | 167 +++++++++ files/opencs/scene-exterior-status-1.png | Bin 1912 -> 0 bytes files/opencs/scene-exterior-status-1.svg | 168 +++++++++ files/opencs/scene-exterior-status-2.png | Bin 1969 -> 0 bytes files/opencs/scene-exterior-status-2.svg | 168 +++++++++ files/opencs/scene-exterior-status-3.png | Bin 1946 -> 0 bytes files/opencs/scene-exterior-status-3.svg | 168 +++++++++ files/opencs/scene-exterior-status-4.png | Bin 1943 -> 0 bytes files/opencs/scene-exterior-status-4.svg | 168 +++++++++ files/opencs/scene-exterior-status-5.png | Bin 1924 -> 0 bytes files/opencs/scene-exterior-status-5.svg | 168 +++++++++ files/opencs/scene-exterior-status-6.png | Bin 1980 -> 0 bytes files/opencs/scene-exterior-status-6.svg | 168 +++++++++ files/opencs/scene-exterior-status-7.png | Bin 1957 -> 0 bytes files/opencs/scene-exterior-status-7.svg | 168 +++++++++ files/opencs/scene-view-fog.png | Bin 298 -> 0 bytes files/opencs/scene-view-instance.png | Bin 1774 -> 0 bytes files/opencs/scene-view-instance.svg | 155 +++++++++ files/opencs/scene-view-pathgrid.png | Bin 569 -> 0 bytes files/opencs/scene-view-pathgrid.svg | 136 ++++++++ files/opencs/scene-view-status-0.png | Bin 3547 -> 0 bytes files/opencs/scene-view-status-0.svg | 158 +++++++++ files/opencs/scene-view-status-1.png | Bin 1774 -> 0 bytes files/opencs/scene-view-status-1.svg | 154 +++++++++ files/opencs/scene-view-status-10.png | Bin 777 -> 0 bytes files/opencs/scene-view-status-10.svg | 148 ++++++++ files/opencs/scene-view-status-11.png | Bin 2424 -> 0 bytes files/opencs/scene-view-status-11.svg | 171 +++++++++ files/opencs/scene-view-status-12.png | Bin 923 -> 0 bytes files/opencs/scene-view-status-12.svg | 148 ++++++++ files/opencs/scene-view-status-13.png | Bin 2287 -> 0 bytes files/opencs/scene-view-status-13.svg | 171 +++++++++ files/opencs/scene-view-status-14.png | Bin 1302 -> 0 bytes files/opencs/scene-view-status-14.svg | 152 ++++++++ files/opencs/scene-view-status-15.png | Bin 2701 -> 0 bytes files/opencs/scene-view-status-15.svg | 175 ++++++++++ files/opencs/scene-view-status-16.png | Bin 2580 -> 0 bytes files/opencs/scene-view-status-17.png | Bin 3077 -> 0 bytes files/opencs/scene-view-status-18.png | Bin 2947 -> 0 bytes files/opencs/scene-view-status-19.png | Bin 3470 -> 0 bytes files/opencs/scene-view-status-2.png | Bin 569 -> 0 bytes files/opencs/scene-view-status-2.svg | 135 ++++++++ files/opencs/scene-view-status-20.png | Bin 2491 -> 0 bytes files/opencs/scene-view-status-21.png | Bin 3009 -> 0 bytes files/opencs/scene-view-status-22.png | Bin 2872 -> 0 bytes files/opencs/scene-view-status-23.png | Bin 3394 -> 0 bytes files/opencs/scene-view-status-24.png | Bin 2731 -> 0 bytes files/opencs/scene-view-status-25.png | Bin 3200 -> 0 bytes files/opencs/scene-view-status-26.png | Bin 3125 -> 0 bytes files/opencs/scene-view-status-27.png | Bin 3627 -> 0 bytes files/opencs/scene-view-status-28.png | Bin 2695 -> 0 bytes files/opencs/scene-view-status-29.png | Bin 3125 -> 0 bytes files/opencs/scene-view-status-3.png | Bin 2169 -> 0 bytes files/opencs/scene-view-status-3.svg | 158 +++++++++ files/opencs/scene-view-status-30.png | Bin 3096 -> 0 bytes files/opencs/scene-view-status-31.png | Bin 3547 -> 0 bytes files/opencs/scene-view-status-4.png | Bin 753 -> 0 bytes files/opencs/scene-view-status-4.svg | 135 ++++++++ files/opencs/scene-view-status-5.png | Bin 2097 -> 0 bytes files/opencs/scene-view-status-5.svg | 158 +++++++++ files/opencs/scene-view-status-6.png | Bin 1104 -> 0 bytes files/opencs/scene-view-status-6.svg | 139 ++++++++ files/opencs/scene-view-status-7.png | Bin 2462 -> 0 bytes files/opencs/scene-view-status-7.svg | 162 +++++++++ files/opencs/scene-view-status-8.png | Bin 298 -> 0 bytes files/opencs/scene-view-status-8.svg | 144 ++++++++ files/opencs/scene-view-status-9.png | Bin 1990 -> 0 bytes files/opencs/scene-view-status-9.svg | 167 +++++++++ files/opencs/scene-view-terrain.png | Bin 2580 -> 0 bytes files/opencs/scene-view-terrain.svg | 145 ++++++++ files/opencs/scene-view-water.png | Bin 753 -> 0 bytes files/opencs/scene-view-water.svg | 136 ++++++++ files/opencs/scene.png | Bin 401 -> 0 bytes files/opencs/scene.svg | 178 ++++++++++ files/opencs/script.png | Bin 256 -> 0 bytes files/opencs/script.svg | 143 ++++++++ files/opencs/selection-mode-cube-corner.png | Bin 1422 -> 0 bytes files/opencs/selection-mode-cube-corner.svg | 62 ++++ files/opencs/selection-mode-cube-sphere.png | Bin 1428 -> 0 bytes files/opencs/selection-mode-cube.png | Bin 1391 -> 0 bytes files/opencs/selection-mode-cube.svg | 58 ++++ files/opencs/selection-mode-sphere.svg | 72 ++++ files/opencs/skill.png | Bin 318 -> 0 bytes files/opencs/skill.svg | 143 ++++++++ files/opencs/sound-generator.png | Bin 429 -> 0 bytes files/opencs/sound-generator.svg | 142 ++++++++ files/opencs/sound.png | Bin 222 -> 0 bytes files/opencs/sound.svg | 165 +++++++++ files/opencs/spell.png | Bin 319 -> 0 bytes files/opencs/spell.svg | 264 ++++++++++++++ files/opencs/start-script.png | Bin 359 -> 0 bytes files/opencs/start-script.svg | 155 +++++++++ files/opencs/static.png | Bin 208 -> 0 bytes files/opencs/static.svg | 154 +++++++++ files/opencs/stop-openmw.png | Bin 252 -> 0 bytes files/opencs/stop-openmw.svg | 147 ++++++++ files/opencs/transform-move.png | Bin 879 -> 0 bytes files/opencs/transform-move.svg | 60 ++++ files/opencs/transform-rotate.png | Bin 1391 -> 0 bytes files/opencs/transform-rotate.svg | 62 ++++ files/opencs/transform-scale.png | Bin 436 -> 0 bytes files/opencs/transform-scale.svg | 60 ++++ files/opencs/weapon.png | Bin 394 -> 0 bytes files/opencs/weapon.svg | 142 ++++++++ 341 files changed, 19217 insertions(+), 373 deletions(-) delete mode 100644 files/opencs/activator.png create mode 100644 files/opencs/activator.svg delete mode 100644 files/opencs/apparatus.png create mode 100644 files/opencs/apparatus.svg delete mode 100644 files/opencs/armor.png create mode 100644 files/opencs/armor.svg delete mode 100644 files/opencs/attribute.png create mode 100644 files/opencs/attribute.svg delete mode 100644 files/opencs/birthsign.png create mode 100644 files/opencs/birthsign.svg delete mode 100644 files/opencs/body-part.png create mode 100644 files/opencs/body-part.svg delete mode 100644 files/opencs/book.png create mode 100644 files/opencs/book.svg delete mode 100644 files/opencs/brush-circle.png create mode 100644 files/opencs/brush-circle.svg delete mode 100644 files/opencs/brush-custom.png create mode 100644 files/opencs/brush-custom.svg delete mode 100644 files/opencs/brush-point.png create mode 100644 files/opencs/brush-point.svg delete mode 100644 files/opencs/brush-square.png create mode 100644 files/opencs/brush-square.svg delete mode 100644 files/opencs/camera-first-person.png create mode 100644 files/opencs/camera-first-person.svg delete mode 100644 files/opencs/camera-free.png create mode 100644 files/opencs/camera-free.svg delete mode 100644 files/opencs/camera-orbit.png create mode 100644 files/opencs/camera-orbit.svg delete mode 100644 files/opencs/cell.png create mode 100644 files/opencs/cell.svg delete mode 100644 files/opencs/class.png create mode 100644 files/opencs/class.svg delete mode 100644 files/opencs/clothing.png create mode 100644 files/opencs/clothing.svg delete mode 100644 files/opencs/container.png create mode 100644 files/opencs/container.svg delete mode 100644 files/opencs/creature.png create mode 100644 files/opencs/creature.svg delete mode 100644 files/opencs/debug-profile.png create mode 100644 files/opencs/debug-profile.svg delete mode 100644 files/opencs/dialogue-greeting.png delete mode 100644 files/opencs/dialogue-info.png create mode 100644 files/opencs/dialogue-info.svg delete mode 100644 files/opencs/dialogue-journal.png delete mode 100644 files/opencs/dialogue-persuasion.png delete mode 100644 files/opencs/dialogue-regular.png delete mode 100644 files/opencs/dialogue-topic-infos.png delete mode 100644 files/opencs/dialogue-topics.png create mode 100644 files/opencs/dialogue-topics.svg delete mode 100644 files/opencs/dialogue-voice.png delete mode 100644 files/opencs/door.png create mode 100644 files/opencs/door.svg delete mode 100644 files/opencs/editing-instance.png create mode 100644 files/opencs/editing-instance.svg delete mode 100644 files/opencs/editing-pathgrid.png create mode 100644 files/opencs/editing-pathgrid.svg delete mode 100644 files/opencs/editing-terrain-movement.png create mode 100644 files/opencs/editing-terrain-movement.svg delete mode 100644 files/opencs/editing-terrain-shape.png create mode 100644 files/opencs/editing-terrain-shape.svg delete mode 100644 files/opencs/editing-terrain-texture.png create mode 100644 files/opencs/editing-terrain-texture.svg delete mode 100644 files/opencs/editing-terrain-vertex-paint.png create mode 100644 files/opencs/editing-terrain-vertex-paint.svg delete mode 100644 files/opencs/enchantment.png create mode 100644 files/opencs/enchantment.svg delete mode 100644 files/opencs/error-log.png create mode 100644 files/opencs/error-log.svg delete mode 100644 files/opencs/faction.png create mode 100644 files/opencs/faction.svg delete mode 100644 files/opencs/filter.png create mode 100644 files/opencs/filter.svg delete mode 100644 files/opencs/global-variable.png create mode 100644 files/opencs/global-variable.svg delete mode 100644 files/opencs/gmst.png create mode 100644 files/opencs/gmst.svg delete mode 100644 files/opencs/info.png create mode 100644 files/opencs/info.svg delete mode 100644 files/opencs/ingredient.png create mode 100644 files/opencs/ingredient.svg delete mode 100644 files/opencs/instance.png create mode 100644 files/opencs/instance.svg delete mode 100644 files/opencs/journal-topic-infos.png create mode 100644 files/opencs/journal-topic-infos.svg delete mode 100644 files/opencs/journal-topics.png create mode 100644 files/opencs/journal-topics.svg delete mode 100644 files/opencs/land-heightmap.png create mode 100644 files/opencs/land-heightmap.svg delete mode 100644 files/opencs/land-texture.png create mode 100644 files/opencs/land-texture.svg delete mode 100644 files/opencs/levelled-creature.png create mode 100644 files/opencs/levelled-creature.svg delete mode 100644 files/opencs/levelled-item.png create mode 100644 files/opencs/levelled-item.svg delete mode 100644 files/opencs/light.png create mode 100644 files/opencs/light.svg delete mode 100644 files/opencs/lighting-lamp.png create mode 100644 files/opencs/lighting-lamp.svg delete mode 100644 files/opencs/lighting-moon.png create mode 100644 files/opencs/lighting-moon.svg delete mode 100644 files/opencs/lighting-sun.png create mode 100644 files/opencs/lighting-sun.svg delete mode 100644 files/opencs/list-added.png create mode 100644 files/opencs/list-added.svg delete mode 100644 files/opencs/list-base.png create mode 100644 files/opencs/list-base.svg delete mode 100644 files/opencs/list-modified.png create mode 100644 files/opencs/list-modified.svg delete mode 100644 files/opencs/list-removed.png create mode 100644 files/opencs/list-removed.svg delete mode 100644 files/opencs/lockpick.png create mode 100644 files/opencs/lockpick.svg delete mode 100644 files/opencs/magic-effect.png create mode 100644 files/opencs/magic-effect.svg delete mode 100644 files/opencs/menu-close.png create mode 100644 files/opencs/menu-close.svg delete mode 100644 files/opencs/menu-exit.png create mode 100644 files/opencs/menu-exit.svg delete mode 100644 files/opencs/menu-merge.png create mode 100644 files/opencs/menu-merge.svg delete mode 100644 files/opencs/menu-new-addon.png create mode 100644 files/opencs/menu-new-addon.svg delete mode 100644 files/opencs/menu-new-game.png create mode 100644 files/opencs/menu-new-game.svg delete mode 100644 files/opencs/menu-new-window.png create mode 100644 files/opencs/menu-new-window.svg delete mode 100644 files/opencs/menu-open.png create mode 100644 files/opencs/menu-open.svg delete mode 100644 files/opencs/menu-preferences.png create mode 100644 files/opencs/menu-preferences.svg delete mode 100644 files/opencs/menu-redo.png create mode 100644 files/opencs/menu-redo.svg delete mode 100644 files/opencs/menu-reload.png create mode 100644 files/opencs/menu-reload.svg delete mode 100644 files/opencs/menu-save.png create mode 100644 files/opencs/menu-save.svg delete mode 100644 files/opencs/menu-search.png create mode 100644 files/opencs/menu-search.svg delete mode 100644 files/opencs/menu-status-bar.png create mode 100644 files/opencs/menu-status-bar.svg delete mode 100644 files/opencs/menu-undo.png create mode 100644 files/opencs/menu-undo.svg delete mode 100644 files/opencs/menu-verify.png create mode 100644 files/opencs/menu-verify.svg delete mode 100644 files/opencs/metadata.png create mode 100644 files/opencs/metadata.svg delete mode 100644 files/opencs/miscellaneous.png create mode 100644 files/opencs/miscellaneous.svg delete mode 100644 files/opencs/multitype.png create mode 100644 files/opencs/multitype.svg delete mode 100644 files/opencs/npc.png create mode 100644 files/opencs/npc.svg delete mode 100644 files/opencs/object.png create mode 100644 files/opencs/object.svg delete mode 100644 files/opencs/pathgrid.png create mode 100644 files/opencs/pathgrid.svg delete mode 100644 files/opencs/potion.png create mode 100644 files/opencs/potion.svg delete mode 100644 files/opencs/probe.png create mode 100644 files/opencs/probe.svg delete mode 100644 files/opencs/qt.png create mode 100644 files/opencs/qt.svg delete mode 100644 files/opencs/race.png create mode 100644 files/opencs/race.svg delete mode 100644 files/opencs/random.png delete mode 100644 files/opencs/record-add.png create mode 100644 files/opencs/record-add.svg delete mode 100644 files/opencs/record-clone.png create mode 100644 files/opencs/record-clone.svg delete mode 100644 files/opencs/record-delete.png create mode 100644 files/opencs/record-delete.svg delete mode 100644 files/opencs/record-down.png create mode 100644 files/opencs/record-down.svg delete mode 100644 files/opencs/record-edit.png create mode 100644 files/opencs/record-edit.svg delete mode 100644 files/opencs/record-next.png create mode 100644 files/opencs/record-next.svg delete mode 100644 files/opencs/record-preview.png create mode 100644 files/opencs/record-preview.svg delete mode 100644 files/opencs/record-previous.png create mode 100644 files/opencs/record-previous.svg delete mode 100644 files/opencs/record-revert.png create mode 100644 files/opencs/record-revert.svg delete mode 100644 files/opencs/record-touch.png create mode 100644 files/opencs/record-touch.svg delete mode 100644 files/opencs/record-up.png create mode 100644 files/opencs/record-up.svg delete mode 100644 files/opencs/region-map.png create mode 100644 files/opencs/region-map.svg delete mode 100644 files/opencs/region.png create mode 100644 files/opencs/region.svg delete mode 100644 files/opencs/repair.png create mode 100644 files/opencs/repair.svg delete mode 100644 files/opencs/resources-icon.png create mode 100644 files/opencs/resources-icon.svg delete mode 100644 files/opencs/resources-mesh.png create mode 100644 files/opencs/resources-mesh.svg delete mode 100644 files/opencs/resources-music.png create mode 100644 files/opencs/resources-music.svg delete mode 100644 files/opencs/resources-sound.png create mode 100644 files/opencs/resources-sound.svg delete mode 100644 files/opencs/resources-texture.png create mode 100644 files/opencs/resources-texture.svg delete mode 100644 files/opencs/resources-video.png create mode 100644 files/opencs/resources-video.svg delete mode 100644 files/opencs/run-game.png create mode 100644 files/opencs/run-game.svg delete mode 100644 files/opencs/run-log.png create mode 100644 files/opencs/run-log.svg delete mode 100644 files/opencs/run-openmw.png create mode 100644 files/opencs/run-openmw.svg delete mode 100644 files/opencs/scene-exterior-arrows.png create mode 100644 files/opencs/scene-exterior-arrows.svg delete mode 100644 files/opencs/scene-exterior-borders.png create mode 100644 files/opencs/scene-exterior-borders.svg delete mode 100644 files/opencs/scene-exterior-markers.png create mode 100644 files/opencs/scene-exterior-markers.svg delete mode 100644 files/opencs/scene-exterior-status-0.png create mode 100644 files/opencs/scene-exterior-status-0.svg delete mode 100644 files/opencs/scene-exterior-status-1.png create mode 100644 files/opencs/scene-exterior-status-1.svg delete mode 100644 files/opencs/scene-exterior-status-2.png create mode 100644 files/opencs/scene-exterior-status-2.svg delete mode 100644 files/opencs/scene-exterior-status-3.png create mode 100644 files/opencs/scene-exterior-status-3.svg delete mode 100644 files/opencs/scene-exterior-status-4.png create mode 100644 files/opencs/scene-exterior-status-4.svg delete mode 100644 files/opencs/scene-exterior-status-5.png create mode 100644 files/opencs/scene-exterior-status-5.svg delete mode 100644 files/opencs/scene-exterior-status-6.png create mode 100644 files/opencs/scene-exterior-status-6.svg delete mode 100644 files/opencs/scene-exterior-status-7.png create mode 100644 files/opencs/scene-exterior-status-7.svg delete mode 100644 files/opencs/scene-view-fog.png delete mode 100644 files/opencs/scene-view-instance.png create mode 100644 files/opencs/scene-view-instance.svg delete mode 100644 files/opencs/scene-view-pathgrid.png create mode 100644 files/opencs/scene-view-pathgrid.svg delete mode 100644 files/opencs/scene-view-status-0.png create mode 100644 files/opencs/scene-view-status-0.svg delete mode 100644 files/opencs/scene-view-status-1.png create mode 100644 files/opencs/scene-view-status-1.svg delete mode 100644 files/opencs/scene-view-status-10.png create mode 100644 files/opencs/scene-view-status-10.svg delete mode 100644 files/opencs/scene-view-status-11.png create mode 100644 files/opencs/scene-view-status-11.svg delete mode 100644 files/opencs/scene-view-status-12.png create mode 100644 files/opencs/scene-view-status-12.svg delete mode 100644 files/opencs/scene-view-status-13.png create mode 100644 files/opencs/scene-view-status-13.svg delete mode 100644 files/opencs/scene-view-status-14.png create mode 100644 files/opencs/scene-view-status-14.svg delete mode 100644 files/opencs/scene-view-status-15.png create mode 100644 files/opencs/scene-view-status-15.svg delete mode 100644 files/opencs/scene-view-status-16.png delete mode 100644 files/opencs/scene-view-status-17.png delete mode 100644 files/opencs/scene-view-status-18.png delete mode 100644 files/opencs/scene-view-status-19.png delete mode 100644 files/opencs/scene-view-status-2.png create mode 100644 files/opencs/scene-view-status-2.svg delete mode 100644 files/opencs/scene-view-status-20.png delete mode 100644 files/opencs/scene-view-status-21.png delete mode 100644 files/opencs/scene-view-status-22.png delete mode 100644 files/opencs/scene-view-status-23.png delete mode 100644 files/opencs/scene-view-status-24.png delete mode 100644 files/opencs/scene-view-status-25.png delete mode 100644 files/opencs/scene-view-status-26.png delete mode 100644 files/opencs/scene-view-status-27.png delete mode 100644 files/opencs/scene-view-status-28.png delete mode 100644 files/opencs/scene-view-status-29.png delete mode 100644 files/opencs/scene-view-status-3.png create mode 100644 files/opencs/scene-view-status-3.svg delete mode 100644 files/opencs/scene-view-status-30.png delete mode 100644 files/opencs/scene-view-status-31.png delete mode 100644 files/opencs/scene-view-status-4.png create mode 100644 files/opencs/scene-view-status-4.svg delete mode 100644 files/opencs/scene-view-status-5.png create mode 100644 files/opencs/scene-view-status-5.svg delete mode 100644 files/opencs/scene-view-status-6.png create mode 100644 files/opencs/scene-view-status-6.svg delete mode 100644 files/opencs/scene-view-status-7.png create mode 100644 files/opencs/scene-view-status-7.svg delete mode 100644 files/opencs/scene-view-status-8.png create mode 100644 files/opencs/scene-view-status-8.svg delete mode 100644 files/opencs/scene-view-status-9.png create mode 100644 files/opencs/scene-view-status-9.svg delete mode 100644 files/opencs/scene-view-terrain.png create mode 100644 files/opencs/scene-view-terrain.svg delete mode 100644 files/opencs/scene-view-water.png create mode 100644 files/opencs/scene-view-water.svg delete mode 100644 files/opencs/scene.png create mode 100644 files/opencs/scene.svg delete mode 100644 files/opencs/script.png create mode 100644 files/opencs/script.svg delete mode 100644 files/opencs/selection-mode-cube-corner.png create mode 100644 files/opencs/selection-mode-cube-corner.svg delete mode 100644 files/opencs/selection-mode-cube-sphere.png delete mode 100644 files/opencs/selection-mode-cube.png create mode 100644 files/opencs/selection-mode-cube.svg create mode 100644 files/opencs/selection-mode-sphere.svg delete mode 100644 files/opencs/skill.png create mode 100644 files/opencs/skill.svg delete mode 100644 files/opencs/sound-generator.png create mode 100644 files/opencs/sound-generator.svg delete mode 100644 files/opencs/sound.png create mode 100644 files/opencs/sound.svg delete mode 100644 files/opencs/spell.png create mode 100644 files/opencs/spell.svg delete mode 100644 files/opencs/start-script.png create mode 100644 files/opencs/start-script.svg delete mode 100644 files/opencs/static.png create mode 100644 files/opencs/static.svg delete mode 100644 files/opencs/stop-openmw.png create mode 100644 files/opencs/stop-openmw.svg delete mode 100644 files/opencs/transform-move.png create mode 100644 files/opencs/transform-move.svg delete mode 100644 files/opencs/transform-rotate.png create mode 100644 files/opencs/transform-rotate.svg delete mode 100644 files/opencs/transform-scale.png create mode 100644 files/opencs/transform-scale.svg delete mode 100644 files/opencs/weapon.png create mode 100644 files/opencs/weapon.svg diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 269cc44707..3919507bd1 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -347,6 +347,16 @@ add_qt_style_dlls() { QT_STYLES[$CONFIG]="${QT_STYLES[$CONFIG]} $@" } +declare -A QT_IMAGEFORMATS +QT_IMAGEFORMATS["Release"]="" +QT_IMAGEFORMATS["Debug"]="" +QT_IMAGEFORMATS["RelWithDebInfo"]="" +add_qt_image_dlls() { + local CONFIG=$1 + shift + QT_IMAGEFORMATS[$CONFIG]="${QT_IMAGEFORMATS[$CONFIG]} $@" +} + if [ -z $PLATFORM ]; then PLATFORM="$(uname -m)" fi @@ -913,12 +923,13 @@ printf "Qt ${QT_VER}... " DLLSUFFIX="" fi if [ "${QT_VER:0:1}" -eq "6" ]; then - add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets}${DLLSUFFIX}.dll + add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets,Svg}${DLLSUFFIX}.dll else - add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll + add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets,Svg}${DLLSUFFIX}.dll fi add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll" add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll" + add_qt_image_dlls $CONFIGURATION "$(pwd)/plugins/imageformats/qsvg${DLLSUFFIX}.dll" done echo Done. } @@ -1112,6 +1123,13 @@ fi echo " $(basename $DLL)" cp "$DLL" "${DLL_PREFIX}styles" done + + echo "- Qt Image Format DLLs..." + mkdir -p ${DLL_PREFIX}imageformats + for DLL in ${QT_IMAGEFORMATS[$CONFIGURATION]}; do + echo " $(basename $DLL)" + cp "$DLL" "${DLL_PREFIX}imageformats" + done echo done #fi diff --git a/CI/install_debian_deps.sh b/CI/install_debian_deps.sh index b7784cf3f0..d29f16f55f 100755 --- a/CI/install_debian_deps.sh +++ b/CI/install_debian_deps.sh @@ -36,7 +36,7 @@ declare -rA GROUPED_DEPS=( libsdl2-dev libqt5opengl5-dev qttools5-dev qttools5-dev-tools libopenal-dev libunshield-dev libtinyxml-dev libbullet-dev liblz4-dev libpng-dev libjpeg-dev libluajit-5.1-dev librecast-dev libsqlite3-dev ca-certificates libicu-dev - libyaml-cpp-dev + libyaml-cpp-dev libqt5svg5 libqt5svg5-dev " # These dependencies can alternatively be built and linked statically. diff --git a/CMakeLists.txt b/CMakeLists.txt index 93da5feec4..5de8934968 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,9 +249,9 @@ find_package(LZ4 REQUIRED) if (USE_QT) find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5) if (QT_VERSION_MAJOR VERSION_EQUAL 5) - find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL LinguistTools REQUIRED) + find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL LinguistTools Svg REQUIRED) else() - find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets LinguistTools REQUIRED) + find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets LinguistTools Svg REQUIRED) endif() message(STATUS "Using Qt${QT_VERSION}") endif() @@ -834,6 +834,12 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE) configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY) configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY) configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY) + + get_property(QT_QSVG_PLUGIN_PATH TARGET Qt${QT_VERSION_MAJOR}::QSvgPlugin PROPERTY LOCATION_RELEASE) + get_filename_component(QT_QSVG_PLUGIN_DIR "${QT_QSVG_PLUGIN_PATH}" DIRECTORY) + get_filename_component(QT_QSVG_PLUGIN_GROUP "${QT_QSVG_PLUGIN_DIR}" NAME) + get_filename_component(QT_QSVG_PLUGIN_NAME "${QT_QSVG_PLUGIN_PATH}" NAME) + configure_file("${QT_QSVG_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QSVG_PLUGIN_GROUP}/${QT_QSVG_PLUGIN_NAME}" COPYONLY) endif () install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c2f249171a..3353a4586f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -250,9 +250,9 @@ target_link_libraries(openmw-cs-lib ) if (QT_VERSION_MAJOR VERSION_EQUAL 6) - target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::OpenGLWidgets) + target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::OpenGLWidgets Qt::Svg) else() - target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL) + target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::Svg) endif() if (WIN32) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index e7f980dc0d..62fb29e600 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -81,7 +81,7 @@ int runApplication(int argc, char* argv[]) Application application(argc, argv); - application.setWindowIcon(QIcon(":./openmw-cs.png")); + application.setWindowIcon(QIcon(":openmw-cs")); CS::Editor editor(argc, argv); #ifdef __linux__ diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index a966a53eee..a40698bc27 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -58,7 +58,7 @@ std::string CSMWorld::TableMimeData::getIcon() const if (tmpIcon != id.getIcon()) { - return ":/multitype.png"; // icon stolen from gnome TODO: get new icon + return ":multitype"; } tmpIcon = id.getIcon(); diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 9daf87e20a..0ebccd6253 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -23,158 +23,137 @@ namespace constexpr TypeData sNoArg[] = { { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", ":placeholder" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", - ":./global-variable.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":./gmst.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":./skill.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":./class.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":./faction.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":./race.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":./sound.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":./script.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":./region.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", - ":./birthsign.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":./spell.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", - ":./dialogue-topics.png" }, + ":global-variable" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":gmst" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":skill" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":class" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":faction" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":race" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":sound" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":script" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":region" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", ":birthsign" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":spell" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", ":dialogue-topics" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", - ":./journal-topics.png" }, + ":journal-topics" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos", - ":./dialogue-topic-infos.png" }, + ":dialogue-info" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", - ":./journal-topic-infos.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":./cell.png" }, + ":journal-topic-infos" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":cell" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", - ":./enchantment.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", - ":./body-part.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", - ":./object.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", - ":./instance.png" }, - { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", - ":./region-map.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":./filter.png" }, - { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", - ":./resources-mesh" }, - { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":./resources-icon" }, + ":enchantment" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", ":body-part" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", ":object" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", ":instance" }, + { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", ":region-map" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":filter" }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", ":resources-mesh" }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":resources-icon" }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", - ":./resources-music" }, + ":resources-music" }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", ":resources-sound" }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", - ":./resources-texture" }, - { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", - ":./resources-video" }, + ":resources-texture" }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", ":resources-video" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", - ":./debug-profile.png" }, + ":debug-profile" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SelectionGroup, "Selection Groups", "" }, - { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":run-log" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", - ":./sound-generator.png" }, + ":sound-generator" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", - ":./magic-effect.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", - ":./land-heightmap.png" }, + ":magic-effect" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", ":land-heightmap" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures", - ":./land-texture.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", - ":./pathgrid.png" }, + ":land-texture" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", ":pathgrid" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", - ":./start-script.png" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", - ":./metadata.png" }, + ":start-script" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", ":metadata" }, }; constexpr TypeData sIdArg[] = { { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", - ":./global-variable.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./gmst.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./region.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":./dialogue-topics.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", - ":./journal-topics.png" }, + ":global-variable" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":gmst" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":skill" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":class" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":faction" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":race" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":sound" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":script" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":region" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":birthsign" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":spell" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":dialogue-topics" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", ":journal-topics" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", - ":./dialogue-topic-infos.png" }, + ":dialogue-info" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", - ":./journal-topic-infos.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":./object.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", - ":./activator.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", - ":./apparatus.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", - ":./container.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":./creature.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", - ":./ingredient.png" }, + ":journal-topic-infos" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":cell" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":cell" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":object" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":activator" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":potion" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":apparatus" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":armor" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":book" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":clothing" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":container" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":creature" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":door" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":ingredient" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList, - "Creature Levelled List", ":./levelled-creature.png" }, + "Creature Levelled List", ":levelled-creature" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, "Item Levelled List", - ":./levelled-item.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" }, + ":levelled-item" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":light" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":lockpick" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, "Miscellaneous", - ":./miscellaneous.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, - { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, - { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", - ":./instance.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, - { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":./scene.png" }, - { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", - ":./record-preview.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", - ":./enchantment.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":./body-part.png" }, - { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":./resources-mesh" }, - { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":./resources-icon" }, - { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":./resources-music" }, + ":miscellaneous" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":npc" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":probe" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":repair" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":static" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":weapon" }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", ":instance" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":filter" }, + { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":scene" }, + { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", ":edit-preview" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", ":enchantment" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":body-part" }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":resources-mesh" }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":resources-icon" }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":resources-music" }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", - ":./resources-sound" }, - { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", - ":./resources-texture" }, - { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":./resources-video" }, + ":resources-sound" }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", ":resources-texture" }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":resources-video" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", - ":./debug-profile.png" }, + ":debug-profile" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", - ":./sound-generator.png" }, + ":sound-generator" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", - ":./magic-effect.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":./land-heightmap.png" }, + ":magic-effect" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":land-heightmap" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture", - ":./land-texture.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":./pathgrid.png" }, + ":land-texture" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":pathgrid" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", - ":./start-script.png" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":./metadata.png" }, + ":start-script" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":metadata" }, }; constexpr TypeData sIndexArg[] = { { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, - "Verification Results", ":./menu-verify.png" }, + "Verification Results", ":menu-verify" }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", - ":./error-log.png" }, - { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", - ":./menu-search.png" }, + ":error-log" }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", ":menu-search" }, }; struct WriteToStream diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index e1bf7e6ac6..f5cdb1b8fc 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -71,30 +71,30 @@ void CSVDoc::View::setupFileMenu() { QMenu* file = menuBar()->addMenu(tr("File")); - QAction* newGame = createMenuEntry("New Game", ":./menu-new-game.png", file, "document-file-newgame"); + QAction* newGame = createMenuEntry("New Game", ":menu-new-game", file, "document-file-newgame"); connect(newGame, &QAction::triggered, this, &View::newGameRequest); - QAction* newAddon = createMenuEntry("New Addon", ":./menu-new-addon.png", file, "document-file-newaddon"); + QAction* newAddon = createMenuEntry("New Addon", ":menu-new-addon", file, "document-file-newaddon"); connect(newAddon, &QAction::triggered, this, &View::newAddonRequest); - QAction* open = createMenuEntry("Open", ":./menu-open.png", file, "document-file-open"); + QAction* open = createMenuEntry("Open", ":menu-open", file, "document-file-open"); connect(open, &QAction::triggered, this, &View::loadDocumentRequest); - QAction* save = createMenuEntry("Save", ":./menu-save.png", file, "document-file-save"); + QAction* save = createMenuEntry("Save", ":menu-save", file, "document-file-save"); connect(save, &QAction::triggered, this, &View::save); mSave = save; file->addSeparator(); - QAction* verify = createMenuEntry("Verify", ":./menu-verify.png", file, "document-file-verify"); + QAction* verify = createMenuEntry("Verify", ":menu-verify", file, "document-file-verify"); connect(verify, &QAction::triggered, this, &View::verify); mVerify = verify; - QAction* merge = createMenuEntry("Merge", ":./menu-merge.png", file, "document-file-merge"); + QAction* merge = createMenuEntry("Merge", ":menu-merge", file, "document-file-merge"); connect(merge, &QAction::triggered, this, &View::merge); mMerge = merge; - QAction* loadErrors = createMenuEntry("Error Log", ":./error-log.png", file, "document-file-errorlog"); + QAction* loadErrors = createMenuEntry("Error Log", ":error-log", file, "document-file-errorlog"); connect(loadErrors, &QAction::triggered, this, &View::loadErrorLog); QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata"); @@ -102,10 +102,10 @@ void CSVDoc::View::setupFileMenu() file->addSeparator(); - QAction* close = createMenuEntry("Close", ":./menu-close.png", file, "document-file-close"); + QAction* close = createMenuEntry("Close", ":menu-close", file, "document-file-close"); connect(close, &QAction::triggered, this, &View::close); - QAction* exit = createMenuEntry("Exit", ":./menu-exit.png", file, "document-file-exit"); + QAction* exit = createMenuEntry("Exit", ":menu-exit", file, "document-file-exit"); connect(exit, &QAction::triggered, this, &View::exit); connect(this, &View::exitApplicationRequest, &mViewManager, &ViewManager::exitApplication); @@ -140,17 +140,16 @@ void CSVDoc::View::setupEditMenu() mUndo = mDocument->getUndoStack().createUndoAction(this, tr("Undo")); setupShortcut("document-edit-undo", mUndo); connect(mUndo, &QAction::changed, this, &View::undoActionChanged); - mUndo->setIcon(QIcon(QString::fromStdString(":./menu-undo.png"))); + mUndo->setIcon(QIcon(QString::fromStdString(":menu-undo"))); edit->addAction(mUndo); mRedo = mDocument->getUndoStack().createRedoAction(this, tr("Redo")); connect(mRedo, &QAction::changed, this, &View::redoActionChanged); setupShortcut("document-edit-redo", mRedo); - mRedo->setIcon(QIcon(QString::fromStdString(":./menu-redo.png"))); + mRedo->setIcon(QIcon(QString::fromStdString(":menu-redo"))); edit->addAction(mRedo); - QAction* userSettings - = createMenuEntry("Preferences", ":./menu-preferences.png", edit, "document-edit-preferences"); + QAction* userSettings = createMenuEntry("Preferences", ":menu-preferences", edit, "document-edit-preferences"); connect(userSettings, &QAction::triggered, this, &View::editSettingsRequest); QAction* search = createMenuEntry(CSMWorld::UniversalId::Type_Search, edit, "document-edit-search"); @@ -161,10 +160,10 @@ void CSVDoc::View::setupViewMenu() { QMenu* view = menuBar()->addMenu(tr("View")); - QAction* newWindow = createMenuEntry("New View", ":./menu-new-window.png", view, "document-view-newview"); + QAction* newWindow = createMenuEntry("New View", ":menu-new-window", view, "document-view-newview"); connect(newWindow, &QAction::triggered, this, &View::newView); - mShowStatusBar = createMenuEntry("Toggle Status Bar", ":./menu-status-bar.png", view, "document-view-statusbar"); + mShowStatusBar = createMenuEntry("Toggle Status Bar", ":menu-status-bar", view, "document-view-statusbar"); connect(mShowStatusBar, &QAction::toggled, this, &View::toggleShowStatusBar); mShowStatusBar->setCheckable(true); mShowStatusBar->setChecked(CSMPrefs::get()["Windows"]["show-statusbar"].isTrue()); @@ -289,7 +288,7 @@ void CSVDoc::View::setupAssetsMenu() { QMenu* assets = menuBar()->addMenu(tr("Assets")); - QAction* reload = createMenuEntry("Reload", ":./menu-reload.png", assets, "document-assets-reload"); + QAction* reload = createMenuEntry("Reload", ":menu-reload", assets, "document-assets-reload"); connect(reload, &QAction::triggered, &mDocument->getData(), &CSMWorld::Data::assetsChanged); assets->addSeparator(); @@ -341,9 +340,9 @@ void CSVDoc::View::setupDebugMenu() QAction* runDebug = debug->addMenu(mGlobalDebugProfileMenu); runDebug->setText(tr("Run OpenMW")); setupShortcut("document-debug-run", runDebug); - runDebug->setIcon(QIcon(QString::fromStdString(":./run-openmw.png"))); + runDebug->setIcon(QIcon(QString::fromStdString(":run-openmw"))); - QAction* stopDebug = createMenuEntry("Stop OpenMW", ":./stop-openmw.png", debug, "document-debug-shutdown"); + QAction* stopDebug = createMenuEntry("Stop OpenMW", ":stop-openmw", debug, "document-debug-shutdown"); connect(stopDebug, &QAction::triggered, this, &View::stop); mStopDebug = stopDebug; @@ -355,16 +354,16 @@ void CSVDoc::View::setupHelpMenu() { QMenu* help = menuBar()->addMenu(tr("Help")); - QAction* helpInfo = createMenuEntry("Help", ":/info.png", help, "document-help-help"); + QAction* helpInfo = createMenuEntry("Help", ":info", help, "document-help-help"); connect(helpInfo, &QAction::triggered, this, &View::openHelp); - QAction* tutorial = createMenuEntry("Tutorial", ":/info.png", help, "document-help-tutorial"); + QAction* tutorial = createMenuEntry("Tutorial", ":info", help, "document-help-tutorial"); connect(tutorial, &QAction::triggered, this, &View::tutorial); - QAction* about = createMenuEntry("About OpenMW-CS", ":./info.png", help, "document-help-about"); + QAction* about = createMenuEntry("About OpenMW-CS", ":info", help, "document-help-about"); connect(about, &QAction::triggered, this, &View::infoAbout); - QAction* aboutQt = createMenuEntry("About Qt", ":./qt.png", help, "document-help-qt"); + QAction* aboutQt = createMenuEntry("About Qt", ":qt", help, "document-help-qt"); connect(aboutQt, &QAction::triggered, this, &View::infoAboutQt); } diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 50735bf703..0d7ab679b2 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -44,7 +44,7 @@ CSVFilter::EditWidget::EditWidget(CSMWorld::Data& data, QWidget* parent) mHelpAction = new QAction(tr("Help"), this); connect(mHelpAction, &QAction::triggered, this, &EditWidget::openHelp); - mHelpAction->setIcon(QIcon(":/info.png")); + mHelpAction->setIcon(QIcon(":info")); addAction(mHelpAction); auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this); openHelpShortcut->associateAction(mHelpAction); diff --git a/apps/opencs/view/render/mask.hpp b/apps/opencs/view/render/mask.hpp index 7f767e19ac..1c84d886d3 100644 --- a/apps/opencs/view/render/mask.hpp +++ b/apps/opencs/view/render/mask.hpp @@ -12,11 +12,10 @@ namespace CSVRender { // elements that are part of the actual scene Mask_Hidden = 0x0, - Mask_Reference = 0x2, - Mask_Pathgrid = 0x4, - Mask_Water = 0x8, - Mask_Fog = 0x10, - Mask_Terrain = 0x20, + Mask_Reference = 0x1, + Mask_Pathgrid = 0x2, + Mask_Water = 0x4, + Mask_Terrain = 0x8, // used within models Mask_ParticleSystem = 0x100, diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 214618a627..58523ab595 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -160,7 +160,6 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget::S { WorldspaceWidget::addVisibilitySelectorButtons(tool); tool->addButton(Button_Terrain, Mask_Terrain, "Terrain"); - tool->addButton(Button_Fog, Mask_Fog, "Fog", "", true); } void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool) @@ -170,9 +169,10 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::Sce /// \todo replace EditMode with suitable subclasses tool->addButton(new TerrainShapeMode(this, mRootNode, tool), "terrain-shape"); tool->addButton(new TerrainTextureMode(this, mRootNode, tool), "terrain-texture"); - tool->addButton( - new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain vertex paint editing"), "terrain-vertex"); - tool->addButton(new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain movement"), "terrain-move"); + const QIcon vertexIcon = QIcon(":scenetoolbar/editing-terrain-vertex-paint"); + const QIcon movementIcon = QIcon(":scenetoolbar/editing-terrain-movement"); + tool->addButton(new EditMode(this, vertexIcon, Mask_Reference, "Terrain vertex paint editing"), "terrain-vertex"); + tool->addButton(new EditMode(this, movementIcon, Mask_Reference, "Terrain movement"), "terrain-move"); } void CSVRender::PagedWorldspaceWidget::handleInteractionPress(const WorldspaceHitResult& hit, InteractionType type) diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index 5c45e2b31f..8550195e8c 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -36,8 +36,8 @@ class QWidget; namespace CSVRender { PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent) - : EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), - parent) + : EditMode(worldspaceWidget, QIcon(":scenetoolbar/editing-pathgrid"), + Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), parent) , mDragMode(DragMode_None) , mFromNode(0) , mSelectionMode(nullptr) diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 899918c3b9..fee43b5de5 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -347,7 +347,6 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget: { WorldspaceWidget::addVisibilitySelectorButtons(tool); tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true); - tool->addButton(Button_Fog, Mask_Fog, "Fog"); } std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction() diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 505d985ffa..06470d2883 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -222,8 +222,7 @@ namespace CSVRender Button_Reference = 0x1, Button_Pathgrid = 0x2, Button_Water = 0x4, - Button_Fog = 0x8, - Button_Terrain = 0x10 + Button_Terrain = 0x8 }; virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool); diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 67270bd1ed..1333a4a7da 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -92,7 +92,7 @@ CSVWorld::RecordButtonBar::RecordButtonBar(const CSMWorld::UniversalId& id, CSMW if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View) { QToolButton* viewButton = new QToolButton(this); - viewButton->setIcon(QIcon(":/cell.png")); + viewButton->setIcon(QIcon(":cell")); viewButton->setToolTip("Open a scene view of the cell this record is located in"); buttonsLayout->addWidget(viewButton); connect(viewButton, &QToolButton::clicked, this, &RecordButtonBar::viewRecord); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 4212e952e8..b7be2b90c8 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -385,7 +385,7 @@ CSVWorld::Table::Table(const CSMWorld::UniversalId& id, bool createAndDelete, bo mViewAction = new QAction(tr("View"), this); connect(mViewAction, &QAction::triggered, this, &Table::viewRecord); - mViewAction->setIcon(QIcon(":/cell.png")); + mViewAction->setIcon(QIcon(":cell")); addAction(mViewAction); CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this); viewShortcut->associateAction(mViewAction); @@ -417,7 +417,7 @@ CSVWorld::Table::Table(const CSMWorld::UniversalId& id, bool createAndDelete, bo mHelpAction = new QAction(tr("Help"), this); connect(mHelpAction, &QAction::triggered, this, &Table::openHelp); - mHelpAction->setIcon(QIcon(":/info.png")); + mHelpAction->setIcon(QIcon(":info")); addAction(mHelpAction); CSMPrefs::Shortcut* openHelpShortcut = new CSMPrefs::Shortcut("help", this); openHelpShortcut->associateAction(mHelpAction); diff --git a/apps/opencs_tests/model/world/testuniversalid.cpp b/apps/opencs_tests/model/world/testuniversalid.cpp index 54538a591d..871a5218d4 100644 --- a/apps/opencs_tests/model/world/testuniversalid.cpp +++ b/apps/opencs_tests/model/world/testuniversalid.cpp @@ -149,39 +149,36 @@ namespace CSMWorld Params{ UniversalId(UniversalId::Type_None), UniversalId::Type_None, UniversalId::Class_None, UniversalId::ArgumentType_None, "-", "-", ":placeholder" }, Params{ UniversalId(UniversalId::Type_RegionMap), UniversalId::Type_RegionMap, UniversalId::Class_NonRecord, - UniversalId::ArgumentType_None, "Region Map", "Region Map", ":./region-map.png" }, + UniversalId::ArgumentType_None, "Region Map", "Region Map", ":region-map" }, Params{ UniversalId(UniversalId::Type_RunLog), UniversalId::Type_RunLog, UniversalId::Class_Transient, - UniversalId::ArgumentType_None, "Run Log", "Run Log", ":./run-log.png" }, + UniversalId::ArgumentType_None, "Run Log", "Run Log", ":run-log" }, Params{ UniversalId(UniversalId::Type_Lands), UniversalId::Type_Lands, UniversalId::Class_RecordList, - UniversalId::ArgumentType_None, "Lands", "Lands", ":./land-heightmap.png" }, + UniversalId::ArgumentType_None, "Lands", "Lands", ":land-heightmap" }, Params{ UniversalId(UniversalId::Type_Icons), UniversalId::Type_Icons, UniversalId::Class_ResourceList, - UniversalId::ArgumentType_None, "Icons", "Icons", ":./resources-icon" }, + UniversalId::ArgumentType_None, "Icons", "Icons", ":resources-icon" }, Params{ UniversalId(UniversalId::Type_Activator, "a"), UniversalId::Type_Activator, - UniversalId::Class_RefRecord, UniversalId::ArgumentType_Id, "Activator", "Activator: a", - ":./activator.png" }, + UniversalId::Class_RefRecord, UniversalId::ArgumentType_Id, "Activator", "Activator: a", ":activator" }, Params{ UniversalId(UniversalId::Type_Gmst, "b"), UniversalId::Type_Gmst, UniversalId::Class_Record, - UniversalId::ArgumentType_Id, "Game Setting", "Game Setting: b", ":./gmst.png" }, + UniversalId::ArgumentType_Id, "Game Setting", "Game Setting: b", ":gmst" }, Params{ UniversalId(UniversalId::Type_Mesh, "c"), UniversalId::Type_Mesh, UniversalId::Class_Resource, - UniversalId::ArgumentType_Id, "Mesh", "Mesh: c", ":./resources-mesh" }, + UniversalId::ArgumentType_Id, "Mesh", "Mesh: c", ":resources-mesh" }, Params{ UniversalId(UniversalId::Type_Scene, "d"), UniversalId::Type_Scene, UniversalId::Class_Collection, - UniversalId::ArgumentType_Id, "Scene", "Scene: d", ":./scene.png" }, + UniversalId::ArgumentType_Id, "Scene", "Scene: d", ":scene" }, Params{ UniversalId(UniversalId::Type_Reference, "e"), UniversalId::Type_Reference, - UniversalId::Class_SubRecord, UniversalId::ArgumentType_Id, "Instance", "Instance: e", - ":./instance.png" }, + UniversalId::Class_SubRecord, UniversalId::ArgumentType_Id, "Instance", "Instance: e", ":instance" }, Params{ UniversalId(UniversalId::Type_Search, 42), UniversalId::Type_Search, UniversalId::Class_Transient, - UniversalId::ArgumentType_Index, "Global Search", "Global Search: 42", ":./menu-search.png" }, + UniversalId::ArgumentType_Index, "Global Search", "Global Search: 42", ":menu-search" }, Params{ UniversalId("Instance: f"), UniversalId::Type_Reference, UniversalId::Class_SubRecord, - UniversalId::ArgumentType_Id, "Instance", "Instance: f", ":./instance.png" }, + UniversalId::ArgumentType_Id, "Instance", "Instance: f", ":instance" }, Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::stringRefId("g")), UniversalId::Type_Reference, - UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", "Instance: g", - ":./instance.png" }, + UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", "Instance: g", ":instance" }, Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::index(ESM::REC_SKIL, 42)), UniversalId::Type_Reference, UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", - "Instance: SKIL:0x2a", ":./instance.png" }, + "Instance: SKIL:0x2a", ":instance" }, }; INSTANTIATE_TEST_SUITE_P(ValidParams, CSMWorldUniversalIdValidPerTypeTest, ValuesIn(validParams)); diff --git a/files/opencs/activator.png b/files/opencs/activator.png deleted file mode 100644 index ded6ab835b801a7f9b1972cccbcb57e54948999d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 562 zcmV-20?qx2P)2ail&r>6(So8D<98nKcAJ!2|93wA=j+{bP2-o?~!8moH=lbf;1&Gnq`vWIbRESj5&K)e*-aT_RMTz&k^i zW%O?J!(cF25}==eVXy-pfI9AfQ{)OyGq?dZcmz=jZ6Xc$Ihw>urBWT{890KA38yZO zpl9q}unUp|tRvNdpTw92eQc#bF_%+YphG=Lw|M)(hRbRnxCCY!@>!DQeuP#9v{-|n zpYpmBT{cpFl!p-ukV8OzVTmGXJs5rzdlA@dD$i;SCMlW_5_bWbKo*PxDHf)N6q8FF zp!+!q)tDKOfLjwz9#S7jvJn5 zyd3%nfp_g}!88a^P@b}Iaj-zLOrnk|pgd&?-5p#F zAjIXxd8xG&dH2HpT%$++%2V!09$5>??Rv8C-;>S6d-Ukz*8l(j07*qoM6N<$f>?F# A-v9sr diff --git a/files/opencs/activator.svg b/files/opencs/activator.svg new file mode 100644 index 0000000000..11a23003da --- /dev/null +++ b/files/opencs/activator.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/apparatus.png b/files/opencs/apparatus.png deleted file mode 100644 index 4e95397dfadb913e58762e6f3607a6d77c7da01b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364 zcmV-y0h9iTP)m?Q`zu z8)G)TQm_4kc4NmOp-XBlfgyN1tT$$QFh*W9#`(eZcOOZqlLr5hR~vAIOB1-JV@mQ? zoqEz^w!1Gq--3FZ4L3C&%4IEaWC17s8!KH{AkWV6W1X7dZ|xUVC1G+8T!mf$0000< KMNUMnLSTXoZj%iF diff --git a/files/opencs/apparatus.svg b/files/opencs/apparatus.svg new file mode 100644 index 0000000000..1345efee56 --- /dev/null +++ b/files/opencs/apparatus.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + diff --git a/files/opencs/armor.png b/files/opencs/armor.png deleted file mode 100644 index 6f5cc83c592493c87acae0136c03088f34f25373..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 473 zcmV;~0Ve*5P)_DCOd#+$Fb7 zD6OM%K}pGVZ#!F(gM%Y+Q?AHCPLgjke*a;%oozJx)Nh{e=Y3}8H66$C4a77}sj9{I zeM1=GfT}yo3e}sEZ`-!?r?yDiBsi7gLZJ|>oKnDb-7kh{r8J2b4gF83OOtz2UcFXD z;dg}}=W1IWScCr1fD4>1Y3PO|X`|o@+NCw%9(te%bC4ts1?Ql{F15}9%)%6Ca*~Ww zFamq9q790cWexHnAJGlGPCc<$Ay-GDmD+3mRxkF6h4bop-WkaObdF#?w);1Dgj%F_ znm=$uucr+p6P$iXUb=ZP;Sc44BGc?y?ufh<``h|gnuMjvS8ZoqL5nIEXq2=$| z?qUx^2b3hTK^SF|V{BcRet3pcxMOG^IwFw`!VHCK)Hl(+xP|4oX5z*Vn$nOwhO&^k P00000NkvXXu0mjf$y3bG diff --git a/files/opencs/armor.svg b/files/opencs/armor.svg new file mode 100644 index 0000000000..e7925a23bc --- /dev/null +++ b/files/opencs/armor.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + diff --git a/files/opencs/attribute.png b/files/opencs/attribute.png deleted file mode 100644 index c12456717990aead1a152c0868643699df2b9afd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmV-M0lEH(P)U02@)tmpWqV& zKTz-mo~?9d=M4-M*=)xvh~%pO!h0A8SluK_nZt + + + + + + + + + + + + + + diff --git a/files/opencs/birthsign.png b/files/opencs/birthsign.png deleted file mode 100644 index 861dbd4d108807eb704333665f0542a49fa99226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 444 zcmV;t0Ym8|8w+J+ zd%?<1Y;0UXNFvw>TG-f#wGUvewI=a9F*n?V2;#ux%;cQ;yPoN=APD;WzVJM6Qgl%i zZ@_ArrccUU^W8)-#RK2>9|+fzB=O|LA$|k53pPw-Z3yN_uJH+`6*W->@b82xaF3R2 zZ*T^&(N$a(EP$7`Sm@F9kd=qrX+V=@*%%EzU6C6{QG~QGypPHAd`}w;33hZV#VY)A z3)(T-Tw36OfydflK(`|atF9#~c1=_5md*xS4HeCnDLTi;IU{!)D2D$4`fx9nYc!}t zr{E?&gFhoy;XLsjenP$v)}|8{x#d=WxN8l;h=0?hSDZ1W|E&B9Y{T8R^+vBMkt__u z0>Mx6%eSrX=|QaN;dtRPZBNo>BHDU2n6+IwVaYbrS#cbfZ&YnIqKO)G>TO+(Dzb?k mU~?CHZsNv&p5zw&C;kS%t-~3F{lQ-V0000 + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/body-part.png b/files/opencs/body-part.png deleted file mode 100644 index 8baec720247c579b9f3dd1b1e36b0a1226fca66c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 418 zcmV;T0bTxyP)hY0fIqb2@_aCwg-TT;UH=GopooqTUfa_`F8&F`@Ws~$9NM~7=};Am{s{q z?6dMb_XKI077eImCOk_^d0i=rsE>AqdqIsekhvh0OP_U!(6KG9%6JRu&8 zi|o48fGMtg-#1KAvqg4ZY9K_maZA`#kshel{~AEN1RE-lTVSGTtz8W6gCLkv0R}Dd zs@5(BnUV+bj@Zy%**h3=WNcZCK2JCUuTsl$nc#wh+%4$dKC#Qq%we`vY5-vcyg_Pl zormN{2)D_ + + + + + + + + + + + + + + + + diff --git a/files/opencs/book.png b/files/opencs/book.png deleted file mode 100644 index fdecb1585abea4e4e5b21014be31d4bbb2f45465..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323 zcmV-J0lfZ+P)l;uAOAr)6aNuK@efw=DJFC>MLrVj`?+-`|t#uu#EX%Ic(=<)@ z5AKpTu$s*^<|FWiW*E*7LxUW#*_YZFb0UTCi`008uTfP6L11LDDA;ITabcw*<2!4A zaDYrfE>Xs~JhMlq=g8%79Tnef5#nkfgc6l{zt~In(p8E VUU1*+fjIyG002ovPDHLkV1k1HfwBMq diff --git a/files/opencs/book.svg b/files/opencs/book.svg new file mode 100644 index 0000000000..b34827d7b1 --- /dev/null +++ b/files/opencs/book.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/brush-circle.png b/files/opencs/brush-circle.png deleted file mode 100644 index 22e92c1c7f85ebd8e3c62d7e3805d0015dc180bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1540 zcmV+f2K)JmP)WFU8GbZ8()Nlj2>E@cM*00n4CL_t(&-tCxwNYr;2 z$6w#?T|wqNoriYKGVL&>8AWT0(IDO0g!%*<2}>&2A8pwm$-@1haAOPmu|kqD&4MvV zgkco;vEgV~8^mZ4NiH-wbXP~Foal)u*xmQLKl*;hA?Nwy?(`bI;ke`OzR&Z#KcDCG z{yfhE3s}GcUT7$@c__2ir{sIP)~p?HZCf_#En50)bfZPnQUj_w@N`kaohJ$QmiwvB zYwh-&2kugv9ybIsYkjKdzP@Wif5$}yeeqQP*HOmrrseIG*#(!}r8aF|3G6s_J9lSy z>kX?GNCyZg>X3IyO5@|iwAP-aj5c?Y!;?AOn~^o_S-*UwztBE5SZvX?WB|Wv>1)a^ z+}d2RsdHWkeDY=UjyHPm$>+gXdtJ5_m5n(?=XwsN1SWeXt7gzr+|_cx>3ek4s`(uN zw;bz4-N_xzb4nmM_`ZbH3k|v354V?Pj7---ezhmDr1NT3`sl#^SddVrN}CT{*E#@P z$tyoQUcKkcY#kjbt1ovBJvvA4%{4$E)|8=}Snx0I;*W z^+sl`PmRQ$5JCw{Ky+W3g%Ab6#}i0h2}$5dg1rS``AC0ZEC`r(O+V8}p+w-P z|El!oC6ET32ua|6s`DCveQdBet7gy=)zz;VwAjZ6i-Y}y3EcEu39K~p-awO-@^(l9 z?e?4pI?A|3*OH67S`I{$Kyg>g0gJ9B>nP*x_M8Xd4z83kAcS}wI23#q416)^8E}`{ z^t)+!djXujM@RFkJ&Dl>KEK+N==4203UD_qZ*RDE)2wxXAA(ZHOrIa6lwDzqIhkE> z$*)@ateW3Z(s{Ki8U#u@uU1(#zr(Lu`eb&&rKx072=OWK+Jy2y08~v`PPdPYu{zzGUx!Ke-WfyLpW{=zs{5GL?IV+{SKP3Tx=88?7w;byPfOF{K z=@X@O=VzKu`PH7p6Qyg^0e>6H zgQ5Sw16fkaUrmy6JCzVZ>;@VpeEqGI^6M93E+mBb6WAQ2I>W$5DWxlJCv!pwRZ6J| zA>IQ1Fm77Kc)cy9Y&HKA{G4@G)nutncSC10bOPT;>5j7)L03!=m{U^9R^x8aqOt?A zf)L_O;AYTQH>H$YW;IrsCmag;><2y!(GSE20U?AM^w}nacm?>!(0hQ7q?Ddu$&6^Y z8|C25%W5@HV_Z}KKLfu2b}8kw$`@rGci?5G5(p}j(}1Fom-ll#j7tJRYH~Krne+oE=^;t42|~z + + + + + + + + + + + + + + + + + diff --git a/files/opencs/brush-custom.png b/files/opencs/brush-custom.png deleted file mode 100644 index 58c0485502842819d68420eb1e6528d9a923732c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2475 zcmV;c2~_rpP)WFU8GbZ8()Nlj2>E@cM*00|FCL_t(&-tAd=R8-d) z|Gme|zzj1Ci-Lf_;1UIKX0GRd9QzTUOGi*aK??(<9E(G^WJ^;efRf!_kO?c zoBMzl_QD>^m?!D1|0a!mbj`PuBMsUqBF?5TNPI7scI~_8z?y{OPEX*qRry0kY0mGK zT3ZJ=`sEnbaH-2n^EUlqa^}+@;Ps@ykEuCJy=`s1IEFRprT$qpiqPFMYfFfPYg2`o z^%HxIo~u1~?%=r=z=FnK;#Pe2yMwOiKZ}G zm?<7it6A(*jI^9IfkZ!jWvs$tO5hmQc(H4r)rVG%C>4B^E{rg6n>4AjFa1p=Z!^cg zth=@(6DWAcO2S!0N$PXS{qz-USe}z}3~R74 zUd>|88p1PZtCI$1?~a?YT%D@q+xv^!-o(znbRa#jd7y?9#} zVRml>sNUU}F@4Kp5tx~llbEO}JOzN+*LOm6&dPz+01&!zn+pT|nS$v$n{6oiQ z>ZF0$dEJL@&0RS_?QEcSBmjWt!L+rAB-gC0s9s?)jpo6$7Iur9wqpZ1>~ReAY`QfL z0Am!(^2+>G-vO$c7huD-dv^g8RQrV!d7IhqzXSqmU4aJxb*hrvwY_O^a%FB&Kuc2} zq5Zfje)ByaKf|1h2lx56HYX3PyRk88U1^E%;+z>FgrSu34-inc8V3VFtt{w7`{htI zFThp>-1ao!)Tv5t6Ob9Ty@_#X;{hONZSk_7R-78-ZL{U1VCxrVJR@A~VtQ7!Cf@3ZKz~%X2=EngawY`abrzA5gu%&6L#Yfit(_t}p?%ctW#+1!_eXT7TZ<|HVGmOzBmKIxCk%nWv zOg6^LAmVKSkp^wDQS5vA%IPoexC=h^v%AtauN>Yu;!a7rpT+be09>UqBJGn;U;n(l zWR{hc0RZ~+>5~hKr>GcQZT+dK;N z*w5}tQ?4EPD9of=2!OXSUiH@kd#p%LpZZ59RkM{4vJ-#`0N-IT=gjQuvU<*nBSg&E zy7COHo)8#cm7fx3(kFQhg!~Y|uiKHzcAEhC;CyV7`s_}* z_Tmo!Fpb^{s`pXWx#Oev);dWqcWnsy`sH1%(u-vmt3+0DW!#O&A_0# z>ysq5w&+$b$<;Gq-K6p{VyM1e2)j9ySIxHPQ z`u{{JEpwZIx6Kj_02Tg`C)@=;#qK)$QK3zi<5(cN(ORWWDnBIc~Y5=~JA%X10_yrkMMeAT|b zKi=>NLtX-K62KUTq?WYy|>nFEB{Sb%ftG;x8TbqJ?hI= zvpn}d6{S%u%h$+5_GkAVv&-4D4sU-cfEWNX0mK0~06+oYw;t~cjbD4A=WAuhD*&KU z8L{&3y+&_#EFpgJ{>hPj8>*&;nDuY6JSVT0`e$n7-HsV0vic^8LZ?x5yVc<1XK)7I zfrJ9UWxMjguK%Y2L{myn2qZn)*jksm^YdVH!y62ENv$ks=a(^L@kmY4_@MiZvEioL zH$BEh+ z^Fz$~IjN;tL&cmml;t@&%X12&SoV!Z9&+$lbiy7_z}szpyQI|&;IB_~YjNqK{c~a) zDt8Fi_k8>g8N|Lz)(m{7 z(>)XSR4c;^h3i^bkhWPOH@XYFU2VfT1gTIZY@n2$vgZcwsqRict`R~;0662&bcRwI z@9G&Aoy+DsoLd1*6Qs4%5g>%H4(CcjNH~CM0FCzMS(H+Zqhvny4;*fQ7m`&^0NVhJ zwcpwg;3$ADl+yHP`hmj(5`h5D1L$cFUd}EmS^z3aspV1pJkJ=IX$LRh5EL;Kzz2`& z3IJixQxCulpcueK040>tYykII3WN4002ovPDHLkV1mV9x7Yvx diff --git a/files/opencs/brush-custom.svg b/files/opencs/brush-custom.svg new file mode 100644 index 0000000000..9eb59597cc --- /dev/null +++ b/files/opencs/brush-custom.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/brush-point.png b/files/opencs/brush-point.png deleted file mode 100644 index 19b2354f8c2dd5a053dc937d8fcc004d2d855fc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 787 zcmV+u1MK{XP)WFU8GbZ8()Nlj2>E@cM*00MVOL_t(&-tCw_Xca*a z#((#cQV~=H5hRe-QZz^`1W`e!Nar6&Fuegm6olA_!B~Ve3L1DI+E@krKoBHd5ELOO zX+-c3qLmOu4TP6Gn^{>NFE1}}$=lN#IQI7TZf?HanQwL$N-3q3QvM044vp2TLu2*L z{%@t|6ITK#0sOB3%q%N307>za6u4X{8V!``GUe^^nk%rL8Cq?ob8@FHpk`)wfga%Rzp?_c z&Jke7yLGpHIxC3rTY!0BZ)E%m&{s*^@Gif-;l?jV!;dAs%nd-^1&x_yl9tWv05B58 zLXa!D<$(>}>)ej~KE!QR(%WQdG|;A*T?F<=Lz%nLL{aj<8{k<3V@^t%PZogte%;J2 z0cU_g;25yrvp<@2LF2}61ug)?z!y(m2Z5847URsEstcWR+6;0JI49|8V=5 zlKP8utTGba*MQSa>VY%>#Qtn%+stea@WJ^W;Jl>IAup_^C+m>$AzAeTcRW!6JOZ8o zJ0(rDqbuv+3Ty{ncyYesS2yq#=#jM4j-F1&z+gC8a63Xy+6`Q9S4k%U9B(nUFG&E= zHhC9tqRA^ESU)8RAYzlr7BN`^ZYBdD=5RC1% + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/brush-square.png b/files/opencs/brush-square.png deleted file mode 100644 index 08628772e7c5f5fdb2a97335e2ef9e597f913419..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 761 zcmVWFU8GbZ8()Nlj2>E@cM*00Lb}L_t(&-tCw>XcSQt zhQHaQR0I`41c{`z6bTXwLDa%ir1Jq0Ei4xVQ4k`C_=rVFqhN%fXk!)d2O%JWMH)p2 zJ{l2xAXo`ed_dTT%^A2X%do*@=U$l~mYJQIy?g&T=ltjX7b;Y!P@%#^Z!S(+c zutU;(PBP{cIvh+MU-fcsHFWhF*nBk + + + + + + + + + + + + + + + + + diff --git a/files/opencs/camera-first-person.png b/files/opencs/camera-first-person.png deleted file mode 100644 index b497198df53e72097e982ae69e8515f04691bd22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 750 zcmVaEbKv)>L=(;a!^5v2zvAj z1QCQD1@Yp^o4pj`p{LqwrFap&^_H802L%zEw9>@1hmB2}-Pz|M4aPQ&jcjxx`-eTu zn_=Jk&ztw=y@41pV#N5DP{aDMhya}48*VA3^hoT8h-5`%Rz$wbPwa@u6A?LOy7A*8 z@=*>)MMNe{Ca@yE$2(JvpXz6|*1CImH7dPMgdFbo5|&CO78e&urBcky%#h3F0B!?s zqEKo@NWk7N@O_{8`FR?R1{)h2EG#T^rY=UMG)e;genAif)a!MWQrNalv)SxSt(!<- zdA}f?PLt2)snu$1Zf-I?J>8jFGBJn~BC^&icq^5PRIAmFXkA27re>n^BJ#CQGOCHl zxhQo;c7)ubmr=9cjR(uyFIK;W2j)LlHIH6yFR7>Ab+_o9G_DqMi{4}9q#mvXKH3k- zXW&|{otRdtA+H)jGGUQ(93*HxD;Kf_)9!&u(LNJ|kbqA5U_Q7jlc<9c4Su_ezE?`yC_ + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/camera-free.png b/files/opencs/camera-free.png deleted file mode 100644 index d8e7ccae5d2f855382885f1061703b259d49ca28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 783 zcmV+q1MvKbP)(}D*$c+=mIbg;GGa6<9W3tkC6OGYsN{o zH<@oA$uP;YBm-_2?WqS(VovFPc%|jTN4^?S3d-UL3DR_qf{zEQ55)mKGT$_ zQ~VnMcN&=M0)S5>4>+~@$E}uWZEcO|bej2mzIwP^BgY7vC*`Vu8sux_$l3+&?Ch{u zEK=A1d>RJHgHDN9Z&1L3MeHfNpp}&s#^Z4g4Gl4wOtM@qo2C(`zJZqw`i)zRowf^_ znwrA)_BH~60J7OEW@ctg)1XrV9s~Gd<1;CQcwsT#WtV(;c^QhL0025VIrXd^-o2GR)T8VQ2E>>O*6~JpD zgkHzL9e@VFU(3fZ3`|T+pja%TzrP>7y}hQXPY5yRg*N2L9=6f%Uh1RvlPokTV9;yL z;H4(Eu+8$yWIfTqT*QDm+8-e#_lgRxZIhA(2QV5{aZfzX7uA{Hv>(xTpXC N002ovPDHLkV1g$)RCoXY diff --git a/files/opencs/camera-free.svg b/files/opencs/camera-free.svg new file mode 100644 index 0000000000..ee1ed5afa0 --- /dev/null +++ b/files/opencs/camera-free.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/camera-orbit.png b/files/opencs/camera-orbit.png deleted file mode 100644 index 1aedf2847971c5fcc02a1083528d20aa56dae115..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1096 zcmV-O1h@N%P)xK6 zs``+so>A3`E^$RwUsu)b|L7G^)qdd9RYInK2Sj9Yt+8A`Y^l*u4m>Amr~y^o0sI2k zYlL37rYJYh&Hp8|6SxJ~2iyhh1g-{JYWkFc8Q=nN8u%daoSCgQa1wZWJ+bG0jt<@N zSvhi>=mmO#Iba%y00nLYihv7j6Jrais48MvXdETLG2mF>IhVG|zzk3~$0sKznVXxV zx3`yKvB-R+r;7z^U>#{hx)OH-j{*n8*zFoeh_TT)`W5I2JZCzS0ad*|&F{Z4F)_jD z=qSb*`uh4985u!DeiD(L8_j9g4=vybB1Zv4EHsHv1)lR*y?AQ_V^61fy4)CJV`H?n zwb9zzN~u($TrLC5Ze~{rJSPb}=Vesyrz##SYryrxYcm-Tkr?>8PCL!b%|uZ|rBb1* ztBaPF7SacC(*&L~P7=>l?_mJ;W?O-0XWOP`ld*c2hK7dd?(U|ir-#A8!Nncr?JNdd zKkPuHy{4&BFV0@)VEcjX9c|_vRow$TReQaoql4k$;o7D_5xJD{j5>~3pfRcmz&D#R z;QHY!z-@u&45TS@Kvk!Kp*rCq@Vtn;pKhhrcly&;ibTHjyAfc zasBXN;DlJl)g-Qpvurep`UB7Te5HP?t-y<^z3~PM-wV7U#@?+-T-`QBKow0QZ#D62 z8MqZyfE^7G-2~hRyeg*9qe+a$QSGeH0uKhBQ`&SbrpP0f`sG=xnQX^QFMidJX0R)W~04@VR0v`hJWfi^Y_W{=r z4X`JD7(0PozzskXFrWS|1K$A`f$xD*;5onL-%oOKa&mHVa&mJ1d;AG=w4*5!t!mr= O0000 + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/cell.png b/files/opencs/cell.png deleted file mode 100644 index 4c3fbe25154dfc8dfb1e6cbe8422c1dec6d932ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1212 zcmV;t1Vj6YP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Yuva2`@{nsjb36|t>ImSa(@1U38$KXp6LT(b? z!v!*mCZ8jlQ2X!SPXFK%F`ldo(I@W>E}LwUj7c=xwMjO1ea;v2GkMU{{)0fJkh;D4 zHtjR??&c8e)Gv>E3T4KLGtf`u8Bj-N!DQOS8AxT*^L(c?{j$AV&b&3OA$H^AyA1%N zIw)00nz9-^Wn@uQpiwhqTAyBqMlrXL8Miyfj`ryRynS}S&g7}rM<~enY2XhSO+CAF z>{f&hto>wu_#s9U%>8wTUGFva-nP|c>w%P~xu~C|tTPxcfKpdCj}dS?GeVD%Fd~*% z0D1+R3q~PMEI_-n<;s~mw^bG{DA7uj04Y*LS6$Q~Nypi59S?P|IEm zuX)p&uW&@>%CHnhFows|pflx_u?OmXv@WxWJ65PmMgyXZ!Q6Pl3WRW47wHOhy`Y|Y#|oMx8Bl~XN8?Jmdw`f9O?`Jh>+W%7*;S~Jerw3n;;UHfnx+e z8I_A#S-=20CzYv#8^ult5@qCuPvF&7oNQ_wEg-_F*8pm;bwHN24*e5sL=R=B&XRM^ zyWpZrE_?OXJMVq)#VvjbOI*^D3)-jH;)*Y!#F9#`Qnh0HS6>6wSX0f78(OK^=9+Jz#gt9=4ep&H<+VA-DK{W zw-eTCUcV^15;S(e@>p)%Yn8;EYeSnWd$*)kOH!y!J>3e?8Yo|Ak-L`dc z_)t&D{xlZd6!zc&MEsxjQUAEkJsW+|btmhMJ zH|)9}Uer?D&iB%^Yt`n%{dsQ=r`_&&^rH_Q-%5Iy=|!TW-BX~yR?(;OSm|Z3zpm(0 z%r1ld#~8g#L`PcjcQeudxU@{m!+ds<00006VoOIv08Ic*08J?m1UUcz010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;t2)|DG{B3eS81_0DVbBK~y-)?UT_7z#t4nFVb}i zE@HNEif*He6dWl1XoV;dZ2j%~G^P{>^MKig3jGD%Y#}y2|d& a1zKE!{xaOcA~d)F0000 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/class.png b/files/opencs/class.png deleted file mode 100644 index 272f2630c73d086f867547ae82e327357ad42bab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmV-S0<-;zP)S5pWQIE9E{VUbhuDoLsnEUW~xE`}%) ziy+uUk2Fb<%D+GaJ-I6^G=X5D1n;g&5mE>u3N}F`l89ckQWO$`g}Gfn-(}x&Ug5xp z`SE7v&3n7gwra$6-8Mq+;kj+wty&I(;2O06xl*ZAR?LWF3~7q<6#d2=hvQUCG^)GX;gn2tue^W9CSDt%`?s>y|i zVdOlC?eGlr-9JGiBYS8aX#@2DhCu6U(yWigw?WcAV|6pCE>i_*{6~?0j=u#%>}(U; zGxrg{1p+C~q!%aIhOR=PU>=h`vHp|46n`+q_*OiD90`-?H+~1BOpu5sxWfMkdd`RF aSZ)Cr5YXn`)Nl6y0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/clothing.png b/files/opencs/clothing.png deleted file mode 100644 index e42988e749a5f1fac8802bd485d421ccb380e145..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)GZP~e*mBJJhvqMVpmy~Ss8eQZ51Qu6?;c>!EJ0!{6y6|k#GrD=A4sQlsaD% ze-kD=&Y>up~P!=?d;Z%3z$G?lCy^<`Vwn zoH*y?!dmnPRObS{xTHorwoLYCj>UW(wtIF5aZY0bRqr~%-`_8O*9m_IbCrMZ=6^?S P00000NkvXXu0mjfT;7+t diff --git a/files/opencs/clothing.svg b/files/opencs/clothing.svg new file mode 100644 index 0000000000..9b1ffb54b3 --- /dev/null +++ b/files/opencs/clothing.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/container.png b/files/opencs/container.png deleted file mode 100644 index 336a05dbfed774ed2ac8e9c425c983ec216986fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 421 zcmV;W0b2fvP)bh=@ z#9mPprE)z@Oso*?=Xw5Quz8^+X=2QpZ#VQG29gMfOI5hS*`%1?{dCu(D^_2(3>5J-h7Af09NZJ@aX;pxdPn$ z8<({GmkZ4r+NtVX0f0O9sS + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/creature.png b/files/opencs/creature.png deleted file mode 100644 index 003684dca0bab3c8eaa63de379fb7e8698db2b9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmV;=0WkiFP)-!I!h5dZSNYvLa@_9un?@R zEUXkHB1E(>g|WQk5GyN7!CC_8?Supy13ABUW@QzHr~{jMd2inA-0hw*{|wLi<2bH) zp0~v^!{P8S%d#D-DgUJVRwU22+ikDaYN_cghI45O@Db^&ej%-xAW4#3W(pfju$Jff zL=XghCQ*&?ecz;M`bmfDYqO6An0(BI13U@tsi_*!I9DH6r$J8*ibufkL_tO_jZCND zy3C_EBi}gsG1J{k(^zxlCM#u!ZIKi<9&f3oYkj%PGtI{^PR0z-pj(pd-@A z#Tv)Yqv=Je^hINCuxb!f9O0|jae|GXsoM)Woz6q0QVF?vw^0<8!H;mg@0wtmLEo=d ztJiF}tCK5knu-x4l0KjnZrQXrH%4P?*9NPGx$EkG#&5~!$U^oL`&a+~002ovPDHLk FV1o0m&g=jH diff --git a/files/opencs/creature.svg b/files/opencs/creature.svg new file mode 100644 index 0000000000..e7fe8cf5a3 --- /dev/null +++ b/files/opencs/creature.svg @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/debug-profile.png b/files/opencs/debug-profile.png deleted file mode 100644 index ddb01da4373c24e073eaa8780f2a1925d8e4c291..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmV;g0Z{&lP)x>!fO`r}B#0U}7m4vO)L ze%-f*hFHKny78>*7F6o@9Wyw`w8k^_qV`xoD_*dn!6nV&UgIg6aviSFfm>|H0>X%5 zQd1npNnrg&n7}Hkw7k!d?}ls~p#o=dHZco_+K(su!yk}`Ij#M#W;5-=wLhRn(*6;! zg%6!v)B=)qB(|seE1ch2 z2}Yb(WEZv+3nAUa;B+8qvZK_S`?_ojxuzu|$ Zb6>EKPtoppBdGuY002ovPDHLkV1knC#q + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/dialogue-greeting.png b/files/opencs/dialogue-greeting.png deleted file mode 100644 index de6b22b42c4a025ab1f1674f20b1e7dfae20b3e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 386 zcmV-|0e$|7P)g_X0E&S{nb=LSc*vm9boZbGbPdA>kqglYIGRXLjbko82{06uAI1#t2n5=kl^3 z&<2$&y^T_9z4gD`og38jvtbxInZveO=)b3Fnh&jPK%;k(Z4y&$x{3MF5%DL@`3)`! zo`5Nv4&VW5j%6c_pP_D+We;#4T!7rl8IZgq(xLbU{sI$`Sx7x&eNXNdj@Wwz=jJPr zz#*7{As7R-H=GfQPEpg+pm3=`7IdBi8O|qoiR0K6_vDrJBgJ*{ANWh#`$aOUVAJ^{ zSx(>wy-lQl`+FrPH8mVdvUnNGUsI3CU*j*}hQ#y&X};1EERMEkt*s|XvQo2h3flEA gqwt)V+>A7UK)-ht$8>{E1Ew{Z+ zIBXzN^;~9d=2DJ5&G$JXIM1BoT3~ux%beSpqjgn9@VTFs%nA>qJYDk1=oix!i_xbJlLj`N(U)D7#Qcs-tSlrx}w> zIDfDi6f?2Za_oq-Dwn&UA%9=?q1+PlyLR(5!#Ef|G3*havwUje67@fE56gZ0%O7jc z)UaFp?ZMvn$vumuihcHozUnIwKUOa}r6*7QCU@zL`0JSyyE=jXW$<+Mb6Mw<&;$VZ CHFqQc diff --git a/files/opencs/dialogue-info.svg b/files/opencs/dialogue-info.svg new file mode 100644 index 0000000000..a0b4f4236e --- /dev/null +++ b/files/opencs/dialogue-info.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/dialogue-journal.png b/files/opencs/dialogue-journal.png deleted file mode 100644 index 086cb8a4221c2db4048edb3ab5e1251c3f79514b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Ftc zi(`m|;L%`1zC#8)K8w0qXQr#(Pk5}`F)@Bgt%PtAW9#m&?wF|79G6w+Ha`A*)UVcS zrG?IW+lAFrjh0)gH@)*Ip0Km|o6;hojm+$C=10FOI=A_Wm&2k$nb)=+7QUCc-@OVp z?B-^Yp5VJEkJW2aMrh>zH?2&e$@~$f$2{HyUs!SFI&BN}%=1vb-z^Y=hR7j!nE8PTZV#1@3uBGL- z5HI02ptm|+WCDbLxZ^smoU5FmEO-?w`!CeJ1^M2w8%+kB>gsBRlbQ~WhBPmux*x;a zlD&W*!X`=Ly*e+bmOnET@9@5~*1b56y_!}t;Dl=$?CUmo0KSf5wfX{!5C8xG07*qo IM6N<$g2phI0RR91 diff --git a/files/opencs/dialogue-regular.png b/files/opencs/dialogue-regular.png deleted file mode 100644 index 933afc595220dcbe46ba10a4582325a7907a300f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_WYcr-bcN;5 SZ!iHmjlt8^&t;ucLK6UMEmtZ4 diff --git a/files/opencs/dialogue-topic-infos.png b/files/opencs/dialogue-topic-infos.png deleted file mode 100644 index 6242eddf4f0858ab3300580784fc9ef193e42c11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FST zi(`m|;L;#NzC#8)IZUq(o!NXTf5S(yBPaAH+4OK4DhR&o>A7UK)-ht$8>{E1Ew{Z+ zIBXzN^;~9d=2DJ5&G$JXIM1BoT3~ux%beSpqjgn9@VTFs%nA>qJYDk1=oix!i_xbJlLj`N(U)D7#Qcs-tSlrx}w> zIDfDi6f?2Za_oq-Dwn&UA%9=?q1+PlyLR(5!#Ef|G3*havwUje67@fE56gZ0%O7jc z)UaFp?ZMvn$vumuihcHozUnIwKUOa}r6*7QCU@zL`0JSyyE=jXW$<+Mb6Mw<&;$VZ CHFqQc diff --git a/files/opencs/dialogue-topics.png b/files/opencs/dialogue-topics.png deleted file mode 100644 index caa6d7e7cb15c81562831671e9c04d5e06a4a284..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FbW zi(`m|;N4(PzC#8)K3v=9Rfc`y^V`E(=w!3_rxeFZ_Cr2LUEVDd>5JI(#>6<;ys)On z(0a!Ad5N2!+FY13`9Rt-#!0)cM>%a14t2bQh$+S(6oCEG2WVCo7-OPbundXxZ0Wukc_xTgUSQI~(jL$`u^ouiG5)jz7G| zaV9VSL6bLgAKLDD8pU)bb#)4(!#)N3L(w5`cCV8zT(!O7o4-Q*!|zL1uHkApVeT|h d`t!=YjE_44d}XR8wE_Lb;OXk;vd$@?2>>MvZcYFI diff --git a/files/opencs/dialogue-topics.svg b/files/opencs/dialogue-topics.svg new file mode 100644 index 0000000000..57dd0b9444 --- /dev/null +++ b/files/opencs/dialogue-topics.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/dialogue-voice.png b/files/opencs/dialogue-voice.png deleted file mode 100644 index 1d67745e55293ba97bbb01e45f0418ae4458f278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FJQ zi(`m|;M8DmzC#KEtc&tus@D|pmd`u7k=gW<79 z27A5>?Q++YpIMxBVXexd4Cb@XLmCn##5T?}QT4rK(WkGvUeb)$<;?A5XVYmJJP`*} z&Wc`-kkt4%Kf~(4#hmL$y0X_;9k839bHHV#_PUKm35MKty*&N(9gJ3Li@s)UD4Du( z)8X$8*BNu~&(xlgVdlYf;APVF(~sQd1@2XR$9mRswtKSL)<4mWKbqc1INew}rRSJT q@@WRyc@44A73H#XXIypt!M5&q{5KJe)&4*~GI+ZBxvXn|be6?^HEU#c@1Bo-3uA zGA@eZ3z}tFwv^s2r>aO;QWnS~y_N|K}y$Tiv( z{06qbmOTM?xj`L+E=NCd> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-instance.png b/files/opencs/editing-instance.png deleted file mode 100644 index 7349e8f66d16e18748f4e8b9bde1c84fd442395f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmV<0110>4P)CV&*+YdCX})M$nSl?H356&sOe$6?D28}%+6R)*OMzJ!l%|CHCNY+=(afNoFp*TH2ifNg-ujvj%#1t&W zUJOJZ48l4Rrl*8Y}TAHezVWx7}st zJ2LZlMD)To%+Jj2%}nAE=-o(>nI~{J&f*T7%*=5mp*P@OY>9}^@d_5>?TDD%Oa|7V zEi(r<&<(|^%xo+72Qe};&oy9bY;kOCOG`^zS6A1B|I5Uc7s){1M(h=%Hez~>cq=C1 zqXtZUTrLsuGX^&+gs#T^vS8I>0~TcFfg0I+nDH-+uEzH`*(?Xnm1@(!#)#$Eotf+E zW_mvcm6oEB@w4z3cA@jKI}j25(S=jErpO+`z|4I4ABJs0dxLki;;GDRFNNVuGZ^TP zA4_ZxKfe-Z=JX4Uc?VB6kgvd;@_zt+YlZ`TN`rP5LyB=vUuZyC#D0y4VKuYA3_EM` zrC(iELU{OLc8d#PL^;vU?XnTu-l7u9B8Oc@$s~fuZ}j$fgf-~DW#)JFEc$N`r>vB!!x+4$PQzBX(PVEH<+E7 zN9ywGL{l8d%pDOi6I(K~Eh1(_#Ei^bT@t&t%CwY4?>5|wwi32uBBHY<^!ngPv)k#3 zcmXr929IUt;R`%JyR;6oO0P7xRI|kxgBjcyy!OWag zM4PcWB1Ynk!pyYp+L5(l6@JIo%v@Hdf1qq?#?|ea@58*3yxTH!Nw;n4ixY`f3_l-A z#rS!cn3-oHVsuIHu~>&qnc2}JP9;hy>_k^)jwmbio24^tFQ*iTurxDw_sC4O048i}|4DQ~&?~07*qo IM6N<$fb%7 diff --git a/files/opencs/editing-instance.svg b/files/opencs/editing-instance.svg new file mode 100644 index 0000000000..92e20fade3 --- /dev/null +++ b/files/opencs/editing-instance.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-pathgrid.png b/files/opencs/editing-pathgrid.png deleted file mode 100644 index 0ec024cadfd143c477ae6067bf1833e3cd0e44d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2297 zcmVc8Am&1B0ZWnCTKwGH-0%Z{m0-`d3umnOJvP@>a zd;3Q|VjKto0X;n@&wumH+mPu8GVrvpJpkiQOF$qPJ_i_UoG8Nb zBmvV-g^ZN4os_b}DQYMZwx_*uq5u`_KLM<2z2tWcrKxz@utiEaLrU5H1R9=4d>d1v9k8rnfnfNOQ_esj82$iZ^*b7kh5@z*zi9c#Ok^#p5?wk-g`D*av(H^ai?FmSqEIt-k>*%d%R#p8-|_JAtlXvUEcF z!O!!j{HXx*&WMLbD-IQWHIg|2%LI1dN_i-Db5>#)}P zPry|`U#;~cTI)l=C%{}F6*vzao4Rbw-0P|n{U;<}zoGTfEH+z0y|6tSX(9tg2)wa6 zQV#E`&Hmt?J;s~b30MMr2#f~W0v9T!YU9ev2mA|21YQ9y6GDt6dU$$}+8m!-2?6oZGdad;WU=K#;iC9I?NY3z- z9lgd-<4eYFWZeKB?cj^ntoVFv=73{L`IrMpN1qVy{3`!IUJ<2P7ZI~O*v7#THW>$Z zaPIn<#F8=>w0n2;=vTp!QhI@{#+ZppsmI)TdZDXdNIx8!WjT==p{rIIQimv|*1O+7 z35)_dtEJ1T>Yt@P+pVJHo>1O+_NU}Ftm$>?$lAS*w2voT-KAjA420*g#`Y`XPR^mg zbm3I5Hg?jZCMmOTMd#rh?$C|)d)CwDi#OSwH=$}n_Z}UQ;-Fg=>s@!5&^Q=5!EXj= z%Udk!52R~K3tKOb3)XW$f1sCA%Hh8zvFGw_2Lfwnw65$_Kt*~F+V5URyY2I#uKXio z`xheYlm`2CPj(@te8!DN5imz76#-zs@pW5Rx<9aGQQM@iUdGsMspx$_m1$k(Y#!g` zZkNOgpiC(>sxi51?s_Ki^NVgPL5N%cV<@@!_5AK{zq?k)iI@ZQP)c11&}-V(nJN1| z8P|5>M2ww6b*Ed{eZkNpCBw7R$Pp2Dj0OA=7!NG4fFnQ@h`7EDz?crg%KiB1O}>gP z>>99`FRopLRd?j;+~QmNNhyy=DOUoy@#OCX-;oYI6}C4QW55`MZFk#$`IG;i6j!oJ zsk;EblyaMt@<_+!w+(bG@2>3y#e6w%J_!{iv5y6W5)&@tX0cXExfQ4ce&S9xRw=atVDO0BU)pi?)G<}| zcYWPw9J(%_uz1&BM5&Z(fsIP3o28UCFa&rN z*kDy}-d^7Km0$17?t@3ij&ZP#WgF?R@{ZSZV&^u%r7oFSN~x&Z1P<^kb;XLgwJ-aG zDA?!qb5s@wD*?r)rw95{^s!qy)rehM2A4(|`fZN zBRg(J>g#qGuo1WxC{Rkh9|(pY5w>@ddlfuEQ|84u(fdM${+UwBK5mP>1Q_IAmZqL4 z;-@7bPRPT+EkMzYN=Xus41oscu?=tg!UUVExs zzL$XGWaI{`=Ceo3`p?fU%jhwYruKkkld->Kc6RaAYn;~or#H64@5|w|1jO5~sM~jU z#if%IzsmU;j%7DAWsYUzb)saKZJ_;{zr>6;t*9wi`B4NkSm~gvl11J2iP6lF_aEw1 zKQxuzAdC}TY_)T>`*OMlb4{7kQ9oecqHcP5qF+Iie~ zd}wbXwssyk8|2TL02hxLCsuBpSh;)G_`iHDe|I1lzN6(2iWan>1uba7*~0$-e38f_ T< + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-terrain-movement.png b/files/opencs/editing-terrain-movement.png deleted file mode 100644 index 40777334bd2102cb5ca7af8e8acbb53d8d9144a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1745 zcmV;?1}^!DP)ZU)JZy0Y&#ho zRFY$*pha7-wia5)(c)BRm?{NQ1KcBH~i{TM7s z3P~Et$7Hj6&*>j~c3gKNrX@K1vCqu@vG=_9p67kv=RD`!3mIgPK?WIQkU<6)CbZUt zTI=xnoI{-_;$wjIz+AurF945;NXJOe<&7}$0_H6KOjOM?_ zIB`vg&(11PrB~;x(cv7$;cjC#ci5ViE?dK);U}VoyEuV0j(9Ebl!(OL*tcC$e~Vl8 z^jp5RWSqMCrm#m|C}BbUad@@M;47F>?9nv{E!~DIauw4G5)_nz(}RlU&cM9TX=@Cu zuOEiA)G#Z48<6kZK?64zR<0KVt;kyRqndDaA6#h*}0EwwETma4xzKG~l-HY*X=8;75tG*}B`vJ`clroo40f8Q-f+;cVnUk9!fkv?~= z4!9e*RYdlt%sC3!rIf0));w(_^+koeR#Y(Art+g${ zcAzNTewEgGldHyKz%wEeO_}7=z;@5`uCvzSD)1BF9T71zt91Q_Nq*Jzf)DhrfS83< zZw1T`d*p=_OWz4vUg@{jvA5o&CGiX}RYYdG|C51bp67iFz!xkC67kC*sVT_q(jQIjk4m_H6{K#^5DiISOwe<>=2P}ri~W^`+*}O z@{KC3{nG(e*@~YoDD=h^g%XVCjsJjr625}H9q@Qt@asa40$1HNz-AGNxkKPApi)Fm z4k5KAuBbJs#_~}%n(O3q8&E4E8@1M7b$0fkh&+{k&+KabZl7i1+6lg@C*`ca$vLTd~~D_bIFd(1&#nW0o5Y%$Mo1Ltt$sCd&l{T+ABT6 zIf=a?iI9TMLD>2)LrcGXE~L2G$>yvTPlx}%BoK*2Vv$Isp{%UzSzszq3cOKPR(3cN ziKHgFQbApo;z#WPO$WMdWwEE!Ww{FF&P6c;?+w78y3JsZh>mM*O^dmG}tz4FUIjoE=_hpH)(&b&(^!ZX}6+QXjUm nT~{*5AcG7t$RL9ZE=2qnRg&Tl5w(j<00000NkvXXu0mjfGE+`o diff --git a/files/opencs/editing-terrain-movement.svg b/files/opencs/editing-terrain-movement.svg new file mode 100644 index 0000000000..6c1417fdd0 --- /dev/null +++ b/files/opencs/editing-terrain-movement.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-terrain-shape.png b/files/opencs/editing-terrain-shape.png deleted file mode 100644 index a11bd95d54b2affd7f555875cc1e1a4f19cbf6bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1399 zcmV--1&I2IP)^@RA}Dqm}{_3RT#&AYrpQ~mJFsQQ%7$#<1&U+%8X1?ViD0K zUFd>|G`gEmI5IdLx7?;0B`L{=`lk_+GMYwAnxWVgrNop}hQ{UeuD(2HX1C`(ayiWT z@czH;y`Ht!v!3U_{?D^F6i`3`1r$&~0R>b|c<&o}@0*^@J=|Gxya7-G^Z^3!CNM$L z{>t7fs$|FOd++A~G4LJGOwt9w0br~5zSMhvewE9BMSL3YAg~wcAnBKsO(S5ZbFN_s zVJ1*q85wbvM3vrlfHlB4;CkR|U@TAuJO{J~RsmB04~zhoo+-8588|)}xEGi%X-sOo zC-5F{45(qRdjKmXg@oN?;4xq}F!^*2;!ZQ-y?_sZ%Ylo5eZV%L9dJbyMHzrxE_V=! zqA03o&j6nTJ8f9mlZ>SIzPs^s9`KB$GVgtLTq^0Xy_*RP25yzKHnC@IV1;w8YY1TmFe#Z4mq!jufQ`U-prdhqnQ8oB z;C4wX613QC>heUojR1Z#8EsPTXkvUW&;@8K=^uM{9q=yjGOz>~;+%UZgzyEh2xyd+ zU+2A_Wzm=b%$IaDu}LdnQ4~d2hY+v`ya?=)l=I%N1@=lBm~yVRQEw4Y7w87GDR(qs zHy>y%sk1#70i&ZRy3bT=4KPB|j>Mb@c+&38lE_kg+|qq4r98zz`&=&9BZSb-##aFc zz4z;ZmU*170jveymNZ(@NMJp%(R*JlX)9?MaGv)*_TC=?J_L5>a=A9ST<%)C)MHcp zuWr@;IPiNph3cA2-ewiGj#bpjCTB-ePHqSO0*Y+0k>$Mg-Y+%EbW6=y0hCGVZO^wD zJuk95)Iw78)SQelV>B=dIBb5-1*S+klD@=sfr-FKV6mh@sqx0Zr@$6Tci9HLj4EH6 z3bmBfC6BT>lhHqb+7{hOz-&p!tqJS~bd|Ix57mZRP^Tq@#Z@4qb&Nj!fl^7+z4v{s zz&t8xPM$eGIp;16A&iw&T*12Iopa+t2;WO8$}?VU{C)%|cY3_tyJ_j#ax#UioLU2% zb4^1Coh5yi$L4*zL&JeLfX2WLl73EPZk^F?m=!Vy+$iZlYQ1ZKmG&Jmy__m%+Dg>1 zNc00{0W%~8@BK}{Vx!xrg#8%nM4tlwwrrM2nwpZ)epYKXc<*bPOpmkXt~7o3Dx;Yz z&qyC&3ve^gQ_|`@wq2cbYeNVC9VKnbW7El0Z8^~0Xmi4dr;$081H^HBJdWd)*=+VD zpfzwAur-^_Zi?ghKU}w_?OE%QUd?8+b>lc*ld!32m$r*h<_<|8#c^DAE>FY zW9i=q+%0Lh*&QZt&CQ4Pc`Ca>yt7mzsn>IsK9O^FeslKR*An7707Qj>tatR zhgI#jN|IW&%<(Ce>G-+&u~oyeQa}L(6i`3`1r$&f@h_U)TWhmzf$#tT002ovPDHLk FV1klJek1?@ diff --git a/files/opencs/editing-terrain-shape.svg b/files/opencs/editing-terrain-shape.svg new file mode 100644 index 0000000000..8f16b10dbf --- /dev/null +++ b/files/opencs/editing-terrain-shape.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-terrain-texture.png b/files/opencs/editing-terrain-texture.png deleted file mode 100644 index 4a88353eeaac24d726a6a9f1e9f374e46149b095..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2100 zcmV-42+Q}0P)`5VVS=bX89oOH}v?XF=|PH1F?2`lX)Z6vh~ z*^PuEUkGYi5oG(Pi?fu(x=O5Lm)*o%D~Rk0SueU+P}GZ{3*A7o>844I)2P!ljx(O~ zf3g3We`dj6TDFDxygg@r=llGg=leXr-$0l!VZww76DG_jiwTJPHwuqTOiZ*jG&BV2 z>gv?Y%*;w4=95<)6B84eotQ7O_|? zkw8Tt5Gc;e%hN4ewhT#dnf=^ zRWTZkaR#sM--ENn=y1M>QAj0o06|dJ@QBY7&oRgEIi;j*CJ$vxr z0ga7~+`4rOK@jkGJgi>5ntAi)q0{LA7#JAf+_`hq*4CoYXb=Pev)N2RK>;Z#DWSD` zdV08c@uJe$*jTM7O7*Ezr<{K&0~U)V(rh+Y0f+T^eb%^f<0M5<5Jiy}FJ7>D^Jen% z^HEh5Ns>?$g-x3_F?a6VAtsh2iR9#DCQh8l#fuk_B#GA6R;*SlilQ)f>{vV=504)| zrnR+Ic=F`Q3`J4O%x1G}Hk)s@wY7QwPzK&-P5{5(Pj`1W8jXg^%1UBmV?(CgvSkY$ z9UXW)9wtnfKuJjn>FMbJJbwI``uchKtJM-8 zACFe6{Y~8OF#Ee1h|I{ysM2b+hdmxomQJUWf^`kxcDqSSOQWu?j?~mt;^X5n7!1_Z z)NuX!bqodrdc7XE+f7qb6Mny+`}gm&e*JoSdwYq9h(HuYo;`cUix)4LJ9jRhfBrd> zCQV}T;>C1!cJlDy!y#r@6h-Lk>zm>C`^(0UA1^<8^k|4jgtyFDv32X#VvEJ169j>~ zckgoO&>`;JxkF@RBmgT`tYFEKC5WOJTpXLt#)%UrFquq4c0y4UdV713Wf_e|Gi)yO z_V$vSo6Fj@YeVJ_1Ol|Qv`|%5#fT9jaJgKhq@<9Smq%J!8lot2L13+x-0V&-C~AQ&3QV#bOzz zsi&uhef#z)r%#{Wr4dE(_1(L72Qo7=hXgP%FuL&3CMG5ZyWP&Zb?fl^{g};W zGBY#TyLT^%iHXBL(ACw&&Ye4%Jb5wz-+%u-Yu2pci!Z)-_vk@=eLc^gKc}OkgM0Vx zq0wlFii$#2RcdQ%Q51!ooE!`W0|0}AgLHLuVYk}@f*^DUw?s}#N-Cc{d-kf*(o*A_ zH*ct^siC8zgHfYK4J!?&)5(Sn8+iKkDF+W8M3&`H-M)PJlFG_Tva_>?{O-(|Gi=_x znK5I=0O0j{@p`@F<>g^AnW(9$Va%8@!?NUZxrm90p}f4Dh=>S&`spWMU0t0OumQez zyO2C>+O+bhsHjyVM~*ZGyHAinAb{KLX6MeGq@|^W1Rp=#jn5q%J}i)>FetY2?u= zo;_RkdcEbTsi~`qii(U=r%nan$&)AS-o2YESFQ~4ipS%@WHPaF<3@Bk9hH@pbar-z z+HtUrPMn7;2^E7t?byb!*~1kZEHkCgzen9bH0y#oR*W4lFH}InX@W8 zJKI=aU;o~k4Q9sWa-r2~k!2aZUO(&|pU;ORNvvMInv*9_`hNN4mykLC?)!k8ot<4i za^%QWf*=eryQ-=<91c=bQ?XjD==FLkDk`{s{W@`RaYMSy|Bebir_*V@diClb68^C+ zG%`>QtP%vl==b}Hjg6(Ww3LjDjL`H|Rh27OuJGfJKcXlK8jS{3RegXJur)U~`}ilZ zSS+%|V)YO=q`YjgAcNU99|H)nIzyA7bIVC0Khr+@__syF( zRaI40MN!my_wK2Mg@yfziHY9-tqCQO(x eVZwy@MENh + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/editing-terrain-vertex-paint.png b/files/opencs/editing-terrain-vertex-paint.png deleted file mode 100644 index 2b3f0beac06ded34f85eec3c01b2e6ef37e1b1e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2545 zcmVrQ9s?yL|X0Rk9VgeW^f_AM;I z1yLeQjSlKK1ENv|*2prH%8m{&E{Kk!BghCO1QDEoVW)x$2!xOzBqW`5x|2?KI{mi$ z?tB==DzTZTA@o^8+$hS|D{KKUh_E(zRb z14C_N#yZwL(ADwy@Ju&6%!Ug=1BN0a22A!7tJO$sk9UgpBE@0HjC+TG5a7_U6R;$4y4NQo6aGJ1ca!>o* z@ja7~5bFXQ?ZE9R>_TloIM=9R$jH%1NlC$>g9qX9c#xNuhxqt-06-`dLTPC!Y&IKm zb8{o!#zyJn;Zk%kWb{l)hUTdQtF1+Y$A`VO4cHe7t=bFrGWLAZ^b>!h<7{Kcci%Yg zK50j?Q_2wtpxY8a6Eid~kJVpzV<$UX-zJV4Ga5~Pe|XE5Eh-_zJbU(RSgqD?qgX5! zWMyTcyu2LSwr$hgE|=y^Of;QuY(nwT6G-dSMQ`DvQRQt?8p3U+G_y2#80bRYIV0g( zR>lcbRLMW`3rvccHifL6+{g0R(Tkl9H0PIdkSnIXO850II60uw}~@WMpJu(4axsQ&fcMQ>MaZHpA=j zprW!8rALqAk-G<=vq53hH9)WT!W$0aK%@l+b$R`H!k5<+?rHij1}5A4+{;%b+sG43 zr&`g!8v)FAa2g9@PeN5aRo*JPZ2A4K^O4fAGax#^xJ6m>>Km5FfAhq*B@+w=@$S3t z!Y~Zj?RMz8j{EPwA1;>*0MOjrj8|TI2`@hTT*Rz139W6YsjS4--8;imGqZ$tvTjwp zK9FDtTBsGLiHg^a2q@?4_6x=`>?#i2WMHyAZ7^T`!ccMU#J+$<)KTL%VgDIT9@xWT z&CYc2vMV6|h=ltl4uIrL2h2%eVjN$&;Y~7O(lqq$-TOORq3b$k&U^@&nVqp>#R>?* zcdNCwwiespe;-fHoW+>GNnnkB$aNlhf7vOk5NbtNo$#;10plcBg>DQO%*`+niUWd* zeN5eONHCUQS8;%hnUJ?(Vz&6Z{Cj}*ZVli7=NyC*fB+vK6Y$nij*cz?Ge&kmuim}n z_|$G@65olw{^oYvJunx2`}X~w_{EDBVbaum5JGUY^bi&1DCAT-Y+AG$*E#|V!G*O@r*HS-n0>e zhL1wdfB^u2hDJYDuUbi;eeQW3fcWpVxxj)Q1XGGDW@rxeNBut*j=pLbcpk$JBMRwza;Y9ym2P<=|TZ928Iv|YD+`} z34HwrXUNbIBaky-2pDz1Q}07jVIk}`8{94zukp2z2MT@#UzkBR07?LhKoD!8I8e9) zRF8n^I?69qV&;s8(Xm}R5DKB>(|tI1rVIt$dm2(8L=~?O2!^1yhK(wL(M?(_>cAJB zqQ+Y6E>`}-Jy4;0uT~s5b3SWjVIwnpuCsxuafBqtQ(V3t(O3NCqA+>FJ;=!F0)HDv zNF^}GB%t5GVff;-!rR9V>JC*S&WK7X+Jg8K3#wZU`45K)n^0R+{5dXNW5uTM3V+iM~CdYpsG4_BBHwD z0zCWQQey|rFjGN5%b~42b>h>cLzgU2&R`Y=)K^`=wS8OAb$EecGsRL?TLV^o1{ba# zk(>0$5>UGSK+zuMmNs+kNl&TU5a)77`%VvvopRbos;gigw*WDT$)JV~1AxK+m6#Fs z`yqWi7X}v)$y;SOQaeyHS75nOw1OZa=x>Bt@;WTe3}{ylDs90l%PQr|Yp#|yD7Uqp zo;WnyMs4mF4fkEohwmytTS^u;i2^Y=hsHP@m4^-6#X{=u_Y@4#0{6-Fn%r$131y8C zMG8<#p=&Cn#!A>vY*uK?#U)1Vk#)siL-|<;n*8pN^t8<7ddigf!Cntj#bh&F<%LwY zr=hyX6v)&B0N@5=S=C1blcx;cJ0E~W3Bh@Kvm*M6mkD3gulYFmFY| zb&q)_kUf)LPr3udFp%oI1ou~eR>Z*3r9>%TyX){z7k+zQC2lai7bHC?bGe$FzknJl z#D + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/enchantment.png b/files/opencs/enchantment.png deleted file mode 100644 index 9bd54b8f0a97d6bad0ca2b8303eb8771339fffed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 422 zcmV;X0a^ZuP)`EUcf$;B8Z*% z>};*X&LYVLY(x+QE6*WVi6-lB!X|G1@DyAKJNtbzv$LBGf`1O<>*F}yV|{ImnX7KC zeP%i=%koL>zJnJpXUM~T=g*bO6BCxZiW|*&po$;l5e;R(ODZ%I=4N0V$4Qu}T8x2XR6gQXh Q_W%F@07*qoM6N<$g5>ME`~Uy| diff --git a/files/opencs/enchantment.svg b/files/opencs/enchantment.svg new file mode 100644 index 0000000000..02849172f3 --- /dev/null +++ b/files/opencs/enchantment.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/files/opencs/error-log.png b/files/opencs/error-log.png deleted file mode 100644 index df698d14531014feb9f4bd4b8f6cb7e0a6e79fe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 518 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_pf zf~Tj8V~B-+?_^)^!wv#%!mLx9az&?fami_EaEbY^tq9Ps@(eq|wP?W)Mx~~T&#%=v zUY(sRp0D)6-e}b$AYYtbYGHswzt4=u5fR32!1AmELWs z{eA3L=(WljtVdH$X{xm^V->5+IK=Sgkn)^^oHhsN-3>n1+t6rjvR{>XPL~|}@x%6T`X{OjY>=$&eym3zu zI(3&ND0F-5Ukg1WQH_M2m)$Dg|8G&?`1QNr_-kbx_wQRR0lw$cZUBRx!PC{xWt~$( F697;y!(jjb diff --git a/files/opencs/error-log.svg b/files/opencs/error-log.svg new file mode 100644 index 0000000000..1feb39dfe6 --- /dev/null +++ b/files/opencs/error-log.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/faction.png b/files/opencs/faction.png deleted file mode 100644 index b58756bdc0c2e5edd09b119ba45125e99865a94b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 389 zcmV;00eb$4P)Xe;-rdM9~DL6@;ujZ9};_xF|BVh(9Rstehb2mk|dd9PotQ3O$H6;bE<^S(pqsuru;sjPir(dKbhltOh0n0V%k|NOy|KU}wdjgE ze**TV!H=I>vAwR>vMT3L}+_PTX2bpU + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/filter.png b/files/opencs/filter.png deleted file mode 100644 index 55f442377c439062fa99b406f9c858c12f2b0848..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Gs& zi(`m|VDgvGpMRfcVCm`UQRvF}@ZUZ{nwfjb!JV0xm&v=lX4Cre^=m3y)US5V6M77f z_#GJYl6Vh$9375~ z+{F*273}4oq>CK=VX@&0V^H%Mx9iOhnMzn&el*`Fj(dzS2^3eyc`WZZw~+f diff --git a/files/opencs/filter.svg b/files/opencs/filter.svg new file mode 100644 index 0000000000..12ae65d398 --- /dev/null +++ b/files/opencs/filter.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/global-variable.png b/files/opencs/global-variable.png deleted file mode 100644 index e1642ac355598da6a2809471b43133e22cbe54a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FbW zi(`m|U~+;4YtIYE2d`hBW)g`$d*q17hxhmQ^E#C233M}mh72z!W5$YXnymt!?!BWKf*D_5_+H!?OhU$ttL9edHzhHcXx1a$|?WW4rO_}3N8 z7|_HyT_s>KYrs2o1DzcWIjJ$PHb^mCS-^GW0(;3eIRl0F%r_@@m@%x7OnD)ru&piY z6iZvHct8y6Y()({2CZ2fAzvgr@)-?vx?&sFF}&Q%F{PZvuz+a+Q^6XB%pC^}4Cl;h c+sDEXyxrti4!`L+puZSAUHx3vIVCg!0DN0y;s5{u diff --git a/files/opencs/global-variable.svg b/files/opencs/global-variable.svg new file mode 100644 index 0000000000..00221d24c8 --- /dev/null +++ b/files/opencs/global-variable.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/gmst.png b/files/opencs/gmst.png deleted file mode 100644 index 2605fb4b963e630449816116c7797b3f33375514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmV-Y0j>UtP)f3SO9Tl1deS-Kw<-~48kGd zy%I-u3JR9M@$bE7*LARA7!tj6j;?7bE$tnAzcdR#b5b?P%tqx_N@9#2sv?*U^E}@| z2z&4SeH_Ok)c_D|nx;}@3?{lOemi=AGA`!JOFh7pL}E@Kk$d8OuJ7~}0CJriiU5c& za1ZzsV{NMygt=zIaL|MDHURbhY^rlmW^QBvYIYoK3nedMqtD6;hymc<++PpicpkaL z!`3zS833Y-3Kjv_V`%wq^-Wl(834U+X0#vuGh_Y@0NKgJRemv=X$iD!$+f)96a~WG k8f1N?5c`_T{{tdDZx42HY+xwFFaQ7m07*qoM6N<$f|hQAAOHXW diff --git a/files/opencs/gmst.svg b/files/opencs/gmst.svg new file mode 100644 index 0000000000..2d96e4cc39 --- /dev/null +++ b/files/opencs/gmst.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/info.png b/files/opencs/info.png deleted file mode 100644 index d7bdad6cb1699891de65fecd17cd3708daa198bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1234 zcmV;@1TFiCP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000C*NklHfC5|6kQxOCK;pF6$>yOUvN{{oXKg_O7%ev#Js}93B zx(csOlVdV55i?Q5)K$m3?{^#CuJqxy*#3C`_dL(*_4#~1pZjhE0P!S`t5jh^eD*-N zcFV7PMzbwE)nt`x^oKq9hWoP~!P$$lB*XCPgHzb~6<|0rjV;}Px@`!u#FvkGBjJ&N zJR$GRmHRHhcpTtb{sw9I6M;>3JoolrP!=435SNwWsf1?&8vS7DQ6Q|%2`BY-khZB6I$mXk<%-G=2IHYDvGLE@efXxh&qe)l=VwOOIwWkpO)FQm!lPH!ac z+X33z*r@8`FnlUAG`_{R6U=n}}?_frzFX2;XrXLenH7^asJ-@l--g zAoYp5Qx5pdw3E$~AeQSO<_QqfRgfyW4VAxv7{|fA^cfRKol}8DwS$hz*`ABR$)-!- z^q=ti*VJc2B= z{Vq6pd*+wTwF| zXK+$93~tQ_{u2m)^&5nk>H4|gq;SZ;0@AV*2&o=(RLgW!eVWg5bca2Dy?I-%SrSHiG1k`J&$cW3uW^)C>kdqZ1kSXtwbQG#ZmL&sNh^+4%TM8^4Su wuEH6$(Z + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/ingredient.png b/files/opencs/ingredient.png deleted file mode 100644 index f31e6f581301293160756054ba1c1f3a11eb40e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 490 zcmVoHmlChIkX9kMIER zh5Vc(=5jexHXVStNVgMVKf=ePP&xfBw*RHPVF1lr@DGGTB3J|O0DG_1bHr2Sbps$> zft4YOU<_=SB#*CF5%Zkq=_`u|K-{HH{}4}rt$@uEW8*DkIKsIAGXU`b7q-Tkdn^lV zoO}y$#$t-#dBi2~P_^B`9^wH9NZ?!(0`R)~ z5JyK~SCR53{6S(3B_G5WIP)_79q@JP1~dNxpQV`q*$@=j(JRFbR_x{hyVZp07*qoM6N<$g8u2!4FCWD diff --git a/files/opencs/ingredient.svg b/files/opencs/ingredient.svg new file mode 100644 index 0000000000..af2f736e64 --- /dev/null +++ b/files/opencs/ingredient.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/instance.png b/files/opencs/instance.png deleted file mode 100644 index ce63e64ed66830118ed9c25e6b817be8d9f96909..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+s!VP)UGq2zJSnbXnj}@gMNyS!ybGM&f17qqb7rHS+D`Y8@40%+--0DA>#p^QU(d|223)fMBN$mC(w)k z4GvZmAEh}@Fb1OF2(ejk0HnZEnjQQCEEsFc_-E0<*y$JX(e8;4?*ff34gF>F=DUc>^9NrYBwnAHePvXegqyAk9fnD9R{FTuppn z(}j)$y~ah`(K!Qu0Ven-O30eiwe|+ZC-5(zmp~tw;HqP6`xZSy{wv%*KmnSxw(ghb z&ob;9JKJbI*%VEW;5KX9U~h&&@A0+jJdMG+d-I|G3k+|{pCe3}VE_OC07*qoM6N<$ Ef&wfNegFUf diff --git a/files/opencs/instance.svg b/files/opencs/instance.svg new file mode 100644 index 0000000000..fe344c905d --- /dev/null +++ b/files/opencs/instance.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/journal-topic-infos.png b/files/opencs/journal-topic-infos.png deleted file mode 100644 index 4cc4464897026d9042d46c8051d636549f86aeaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1G6o zi(`m|U~e!d-(dxw>>D3)7W6&Vn4;wLa9&W>tfPtd zS8aS>ExmC{;Ki6+sTUlIIa7A@Z(Q>Ai-xn8XVJO*C7dN*)-_Y+Dl}VKy9#dj+~BbL z;ln#ux2jp~DTrR4{PK;~`xZ|=12#b$%VS?70$EaSI~zV_I4Qku!3L-AU7Vlv*?X)f zM?uqfcy)1SS8^OY3XRXXoXXn!62%etxQq4ojuyVy<4PH%>7;_I}2_J=z_9{}X#o%~lUn1NxM~)78&qol`;+01)we2mk;8 diff --git a/files/opencs/journal-topic-infos.svg b/files/opencs/journal-topic-infos.svg new file mode 100644 index 0000000000..4351d0668b --- /dev/null +++ b/files/opencs/journal-topic-infos.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/journal-topics.png b/files/opencs/journal-topics.png deleted file mode 100644 index d4e58a288503ea273e85169fceede9099d0c32e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Gy) zi(`m|;N8iu`3@=Yw1%72T33WWczdPcd4d<44|9F)rYTPP@sSgGAI&*^Mak)FXpvst zSD9~dJlVO`L9xeLe`N(8=1o51*8AR^>C@LK?mdA5KMvfKeSNx2#J0si#A1rV(j#Uq z=X`D*zP$ea;=2L`%^h#v_ncaiKD$nfmvPmb0yBjjYnC~t-xc`47v}o^5O3oj?knC- zF$Y=g1XUw~^-szROsOlZTz~Ue>4Go1Q#w~4JCgmx;blVQdwb#THHTlE6WYsoSGw$B TaB+Gs&^rvCu6{1-oD!M + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/land-heightmap.png b/files/opencs/land-heightmap.png deleted file mode 100644 index 5b460a0024e053cf0a97a0f720ad087d98025c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_Wq3 z#WBP}@a-f=z6Jvhmd1VS|7^W)ypcn~Vn&AW9?9xRzBgir81~d;)TK@H>gzE1{`H=% zLuvPdP}zBN94?nBWv!am*ijIE-g0kw&%=K)ib1-Gp~r8DD2IQIe`p=fkrDD*L)ydt mN8HA3_go_D?Plsds9@O2wP?>w9q|gF^$eb_elF{r5}E*R0Yd`- diff --git a/files/opencs/land-heightmap.svg b/files/opencs/land-heightmap.svg new file mode 100644 index 0000000000..701b246640 --- /dev/null +++ b/files/opencs/land-heightmap.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/land-texture.png b/files/opencs/land-texture.png deleted file mode 100644 index a96c4bf8c7b8c1334857e79e33ddb9230423c3f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Ftc zi(`m|;M%~8LWdPNR_}iI`OWcH&r74-SDXxte!pw?M+G587SGe0awbQ5alYG@JA1mX zFlSzPo6D7RJ=IDj3$!ZARN}k}Pbx789-Q;}_96Ep1^pIDHyRV#|Jd)DVYpY*@*z9Z z>kk{3q!`WLdQF^*H~Q?^T%O~PcO>N)|BBJcn|pQ1;lGjnFA7qX=j>Es5U~5GBK^Kl z=7>S>hIT90J15KLXuEC`3eB26@s0K$hY!|Yvxp`=!nrE9M=(02@;u6{1-oD!M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/levelled-creature.png b/files/opencs/levelled-creature.png deleted file mode 100644 index e6cb1f54c7235440dae1d180e59054655ddb11be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 521 zcmV+k0`~ohP)UtAI8s#7eXfu@Ee@-ED*vf}K`c z2x4KQf|Z~)NuhQIkCaKa^#D@_1-n>iWuc9NM-g#%{pOjsY(NBcV3_0o=Xh`58pc1x z)b)U(3sdCaRJc_U4Vav?#JS7;>%ckLcAxj+Q4<)uv{*iB=c-A z6^3B~tOI=(64K2^x8Mihli*3qvR+E1l4*V6YDF+rT!rkDuh_O-hgioyrr5^zHu%xe zRRcQS19;e0iiaSd6Q_OO@02O{DRdWX5RTO3xTh-CkhO=gM`)30^8iWwKJ<}-Yph(L zklRofP7Tf>{x~`z4JtTA$eY+E0h4K`9Bq`z18}Z10c;xINdS%jj%h$FU<)RV7Qp+# zQxrc47Lx-0j=BRJxu8fO*U=gYDPI1j*dX^xbIXuV7*+n#ky^O})qrk>s1`0twhJW3 z7IM@NjT1{wsBiLMX3#8&b{^BaWVJ9sxvcBUg@Q-h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/levelled-item.png b/files/opencs/levelled-item.png deleted file mode 100644 index 3c819c56d0da9b019a056fa2088284d5231f13dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)f*^`uVPz7?FYptr zQrOs8Sz4qJQ9(@O4@j=Cvk=kFP82L`BtZ*BNuzLgKC|vD8(kRY<9*+m*;_7~`E!cJ zVw%lnGh+Tp)6}H+TogsIVmS>wpFmn_Hk;>OEkol9dEFNa-aW=DN~Mw+r(4K$iIXJh zp~1JM8TW4kCY=bv23^gmi|_zj7hF%Efp|!DCap4Y!RC2tdCQr`uaQSKH_lA~7!88p zfi(wM^OgKQ48t*5pV|}bajcJ8D~{tiI9Jla-{1)1mK9%u4MFU0G#WCbfbD~|scjP1 zFmv2DVD)*XE!z4v{tdyq&F}EDHa^22+BoAHNCAQQ!uT7>xrS_bLGvk^Pf87}!z)Q> zPFDjhdj1yi1mXh17q9L@_YELDGjYZtzk!H%d@-D1YHj8D8=O+yz^)ZU=w3-{_$qd+ zx!+)qXZ!$IQIKiozhGiWvqb7#sY>3f9Crl>pFHC^qFn_cn^47IHN;Kwj^k*cUj75l zAS8EB!4QwI;Uh!xU|-7juV8A3D-c`da#=afBVP8!0{j5|jM1noWfZ3X0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/light.png b/files/opencs/light.png deleted file mode 100644 index 55d03bcd127699d3790a7161a24fea83a25011e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmV-`0e}99P)1R5%f>k}+xmQ4ogTY64=B!XkZ0v3Q7xbzpZ%Z)%gmGw3Y> zDHE{YUBS}U93agWAq0;Qq9E-0&EkN_?4po?#|$&`|MS0jujwi*2!f68`@dP1Eh}2e zbfcztL2U%lLrsq}2>?9;+NNoGi=UoF0Jwp@0qP2nxJ6FXnC4ko056{BJxQ%7iXlo~ zt-gQBnF@p%6%$m9B}PRP6}iMG8Q?MJQ<}ptEb2h!a#-9X&+~R2P-`Xuk{y!Q+N2&; zec}ZJ90OLwJ@X$Z;MlX11-W({$FjR;&hjh*l+7XeL&+ryXT;Ygfm}iDFa~s=B#BJ# zK=MxQr+h};G>r0OPQ8$5tX^~M;Dh+CT;hJp4ea02P-RT*QJc|sr9JuzA&IXjiYh;r eUIjl;u=pK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/lighting-lamp.png b/files/opencs/lighting-lamp.png deleted file mode 100644 index c86517aa5743089b95ced316e29c48c1ffd2d940..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 953 zcmV;q14jIbP)WFU8GbZ8()Nlj2>E@cM*00SLKL_t(&-tCx8h?Z3p z$A5Qb>4f^GlEI*$PKw18Du@P(REvR04T^A)ZE7L4sR&(*l8SCLiqM5p`B9)2ilWO% zON`1^EgYK=g>pf5bo0;~j0bTlNS)LH8HS!jHuwyC?-{+h5EQF~&|0(F}@7|)KXl|~TQQe*sT^+Ju| zw=zSkxTJQdJF~f6^)|j$9f*&gjh(-k?e-Vy%j(nWVzpEKCY~8Y=c#A1gFU;R1m4JY zuT$NV8UK#@f_g-~7NPUCx>kKvy&G${2FWTm)|0@AZ0DZMyzzM$-#1G798_Oa4~E>O z&R2g9dGB~^X&Q&|%~7PPS*Hz{5%Lk>ZQ#jKRHp%N0{a1hxxjP4rFh<67XrYPsIUON zKs9!616{!KF?82NI=vZk3osnxHg!fl2s8oB*|=)JNbGF$7`pdECuMcWOn;;v1csuw z0eCEmR5e8A0zZzSdlp!ndGH3%8slN$-h>lKDLu@LUI7dQp#;1I90cx+qIwnh6j&E> zcj&DO`9ezRZaq9ebd>`_vte5;hZksedWLr#*Tifrr3F;5hJIN~!<9@>^v}wN*$d4VS-I1qB5K1qB5K b|1SOl59>{tmAIp600000NkvXXu0mjfg0iP7 diff --git a/files/opencs/lighting-lamp.svg b/files/opencs/lighting-lamp.svg new file mode 100644 index 0000000000..5d34d68817 --- /dev/null +++ b/files/opencs/lighting-lamp.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + diff --git a/files/opencs/lighting-moon.png b/files/opencs/lighting-moon.png deleted file mode 100644 index 36a6e9b5b1e449bda6101995cfb62a1e67ff1c93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1590 zcmV-62Fdw}P)WFU8GbZ8()Nlj2>E@cM*00o*!L_t(&-tAazOjB1F ze$P3#^tQEdTRsHC21C@yoTE<0N9J_kYDArxx?nQMHr-}|h9zuf(TK^WnHrtZWZBH3 z$u?!OWy>@J6Jn$UmkJC8Ma4}%CVmhRrmZWq_x7H%A1xEH1=?QBO#1xkpPqA`=e^H4 z?*~8_VT2Jz7-2lYAPVk0u2I+ynsX=e(ganGynnwGf&ycb+aM&%A@@`Sl(;4D7c1o2ttX z-10#l0RUOLwlu~VZA=5e+}-}Z)?W|p?F9fiB<}`8J}oO(yI{%kUA%^0KNLhslumYB zzI578afT2u>7)$ipj(H>HGPVXP!9|^k2hMX>j1z#A}6tl5P%l0eqZoqAFq!mkFlOL zTPpu)wp5-10L##q85ViGbZu!|bZpGb&MR%_P9HmLAFq&cTS%vm)FA{qU)y3rrYEP( zi5SN=)Eja4F!E^G+S18MDM@vL5Lq+JWcoV8yi%+99nk2s285C3k5 z{P2@k6l|0fO=Q&RbpGNugp2_uINE45d|$Y6Tc{$i;&%W5U`lG*9l>BMz!*pRJsD#y zuU6+zGi9A?JyUxVALc&lai&;@^7eA z5i4X_ZfdEoUuLbUuuX&j002_7al2U%^hX~qtNn@a9K#p`N?9+Zw0p=_7^7GKq$dQ& z03eWMxv%Hut=yl#+<9rd)(f@{=L$di)NC*a<(Ob$ED^p04e#bWr8RTdZMJv6-L>VX zVFliV4Yue7tEFrDob2u(18g_z!=9P zgt4c2LE!m)K-kmJ07#;A%69L5aa&9C-sLfjNGJw20`MAv`hnrlxC oddX6yCUaqg5k?qcgz-e>waqbso&W#<07*qoM6N<$g1ZCWz5oCK diff --git a/files/opencs/lighting-moon.svg b/files/opencs/lighting-moon.svg new file mode 100644 index 0000000000..0441eb3bd5 --- /dev/null +++ b/files/opencs/lighting-moon.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + diff --git a/files/opencs/lighting-sun.png b/files/opencs/lighting-sun.png deleted file mode 100644 index a54d0ab12498af2b0f3117d17f3ff8738d46f9d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1804 zcmV+n2lM!eP)WFU8GbZ8()Nlj2>E@cM*00wYLL_t(&-tC!fj9gV2 z$A9PCdD|WK%*^f#&;eWHmODi&TC!+gBq1mXvGI-K7paAU))EtA_@YKsQvDzXKJ<%; zEoUkp7T7<|9QEvh(#=75sSD4h%klgV)||{lZfO|WxL~H=#ZgZet_?b=%@cGqumEE zqdyNzPb56w%CE_42gh&#o#;z(4XeWOIpq1^8&2hxE zel655BrgXCqAdS+XsfCEJI&PK{YDqnvkP^-F3LUC z;fGBv=rdEL9~fOszO9RVA@n3xcIi*r$qL`w@l?#*uSB2${IemVo&1f!9hk}WP;PG( z%R$Jzg=pKWY}ae?>l^RiW9?R4IaX>0*gMI?T$?4jejn7R)t zzmhWfaT)7@csD{=&=@1Ao}y7ZaSYM5P1&V=dVns(HQT`#5ZSH@6Gtw4E1{jdY$hz| zV*3vf*E}9ceJv)EHz5;Qgq3KW3@|lKQ0~Vs_j-uzL&`4g(@x%6C~bz)3+ZBNBO=}# z?c5l%I#+?PfZ#mBGeMPL_z-@jcNCG`qU_RhSG<|iPX0!Wdnl6LvMiFj9fUl$hRslC zf?CUn-=9V-S*L9Gz0fPMcJh&FPikgx`khjCER)Hb=6LxT^-abR=~Y;hpIX+am%aq_ zP19pdv);^BI~Ht!9^eto`}bi2(|W|3E^-(W+f-r7!%VK1@mmpzt_xhA5As3A)0lXH zhJU&T=+jO}qNS%p zfOim)fBlkKXhxeLr*pSAlJ%WgL&LfN@!PGGIGrI}ur|(gAY2SSGToMb- zV1pS#tyfL(?-N1g_$^j;9mwd1(kP~mDfbij{R4>nq510xX(Cg$JBH}|rC;u?G)n(~ zz@I~`1k)g>oWdV_WeU-UbZ0dEU`nP}A!4bPAR)Uj^gWA zrZAPqRiXOW6q<+cnzBcS3Lv zX5v=xSAz5)RzgHxhS(uxyF;z!Z%;h+)o&TmMyL+)q6_i3VK-q3xJNbt&lQ~EjRbXiDX2%aefE5Q!>_cYk=d_dm8^K7MS}~`*k8-GY zgXWOF5Y#VR3}Ni5+D;>)Qy3qDDv**3UAtV-?X + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/list-added.png b/files/opencs/list-added.png deleted file mode 100644 index 4da26598392003d3c6299dce9754157a4110db91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP%y&N z#WBP}FnP+{pEDbU4!CrtO^9=1`@_D9F>y}A1V#(fLn>{Jj5-GU88T}cTYdWkmrQ?T z;84bR!$n2BafZR{jVBwY2EA!YOkgNdSkx*%qucmHLYF2VGsFF*Z0C&UbS(wi!QkoY K=d#Wzp$P!;nKK>$ diff --git a/files/opencs/list-added.svg b/files/opencs/list-added.svg new file mode 100644 index 0000000000..ecfa8595e5 --- /dev/null +++ b/files/opencs/list-added.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/list-base.png b/files/opencs/list-base.png deleted file mode 100644 index 336d4c59c1c75d3833f70a8bcd003bdae158519f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP%z8W z#WBP}F!{^Zuc-@I3<4KPE}71Hvf;l+PST7X1=ka74L=eb1)3QeqTBKqJmh19+7&gX zB^Wa-;dd3B0mnGe(4V`9BK774`a&*;x%xM+6R$JwkwWp*N4 cz#KjXiEZrSZVbYXKwB9+UHx3vIVCg!07UFG%>V!Z diff --git a/files/opencs/list-base.svg b/files/opencs/list-base.svg new file mode 100644 index 0000000000..a050b15629 --- /dev/null +++ b/files/opencs/list-base.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/list-modified.png b/files/opencs/list-modified.png deleted file mode 100644 index 8b269a31d3c79efccadfdc2c816f49a8b85ca9a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 457 zcmV;)0XF`LP)GAh8oHtOUiMO0X1s z0l~&r!GML0ub?(!6Ks^klol$I7f4}gGV6D*?lQXsiG>%=&iy&}%$?aW=0B}>yKF)9 z+a5u&NQ30Iz#fQ!1<&9-T)L{U<}4>b^BC1@Te217661P_BX%~jk%8$xU4wWPp?0bw z>S{C(;nbxWVu$7x;$blAx~@vDMQxV&=7)=GjDNmu2rO=}DC7HcN7Dke2RJjV z2c(arludxYAqniT(5y*vA2_>mG;B?ie0+g8>B^DKeOm0ZHaVIoOfiw(pD&PJsH*g7 z_ERZ0H^EyFs$Rus7W{b|2Gab(k@PJ71U30p*fHactLJ^ljS!w0tE9`cl#K$RM6$^( zm$~IO{tkEqU9bpFsZCRBu=^abS|%V7A`>j~kjjPu`TsrQ#Cu3};!OnJS=Dj^l0ifs z)IL}TlR)0eE4TnBG|NPT8Db&uAKPG!e_?$A%cF++611oh00000NkvXXu0mjfI6TI4 diff --git a/files/opencs/list-modified.svg b/files/opencs/list-modified.svg new file mode 100644 index 0000000000..6efcab4cd4 --- /dev/null +++ b/files/opencs/list-modified.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/list-removed.png b/files/opencs/list-removed.png deleted file mode 100644 index 618a202bb9c7503e8aa98d8157bb57c3db3657da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP|(8D z#WBP}FnP~Ap(75Q35#5eJ>IWi4B=oF+Y<4k|Jd=PsV$xXGTblp8fNosZWQp{$nD0v cz{!b;Az%~Jq!PoTQlJ?Op00i_>zopr0P%Ap*Z=?k diff --git a/files/opencs/list-removed.svg b/files/opencs/list-removed.svg new file mode 100644 index 0000000000..157d4ab5e1 --- /dev/null +++ b/files/opencs/list-removed.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/lockpick.png b/files/opencs/lockpick.png deleted file mode 100644 index 7b1865f50457b6a0343f95f2c686cf376a1e70f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 317 zcmV-D0mA-?P)%d$vB zro97xu#ew?*80t}Sj&Jzpa`G2HJ}UQ7|+fC8)oaa8QidDkDYktEuO2kxic}#)`6}T zi8vToj^{-a^WB7BroxWC>$*-+6iJ$<9GbC=9k5;C1bBlTPexh)`4>QpE1KYzt%1*7 znD1HvzyWX!yaK-1a4UcqS2M=2mcZ9O_!|Hm0`Gu1<$GVub=5r>iy80%Qd4^5D_tZ$ P00000NkvXXu0mjf6UBX9 diff --git a/files/opencs/lockpick.svg b/files/opencs/lockpick.svg new file mode 100644 index 0000000000..b7e8ca1c3d --- /dev/null +++ b/files/opencs/lockpick.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/magic-effect.png b/files/opencs/magic-effect.png deleted file mode 100644 index 44b682bf4ff359ce3c8076379cf27ccffa46f673..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmV-q0h|7bP)lRa+2KoEs@SH42TG5Cp;C=F>5lI=2gq;(PM(4>e2 z=SgAnJ;T6yy^bg{lD#|g-u(CtcsF5XS#ClIpMu-A{b-tIH$lyZ>$>g?sj8}@pt*xH z47|wcx?8^U-a96U(EGKxU!9}NFa9g!BL&`U3O->g9{4lI9{fqZY)}CIg>FZPOGw}N zUL@Hy`G@O!AGp451Pel(Q{==1D@~$!l)NT(Fs{x5aHKY|71*9DYSVc~k#sw%k+)QBlC#AB{V&8Va@&b + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-close.png b/files/opencs/menu-close.png deleted file mode 100644 index 81bc986775089a2ab8b8113096c890a47785e84f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 438 zcmV;n0ZIOeP)_eP4v08QYouW`+TlKHqY~h g-$r@ga{kZ#4H#~PogGl%VgLXD07*qoM6N<$f?Wu@<^TWy diff --git a/files/opencs/menu-close.svg b/files/opencs/menu-close.svg new file mode 100644 index 0000000000..6bd1e9f275 --- /dev/null +++ b/files/opencs/menu-close.svg @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-exit.png b/files/opencs/menu-exit.png deleted file mode 100644 index f583536fb695627bb749c8e742df32f37e845995..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;j%S zi(`m|;L)Iif`<%vyo1~x&RF8ZkbH=3ZcCYHl8VLdecLiWy^yWD(y6Q2cS+!%Y#@8Z zSM!a%V%(O;BsO`JOV0bbL}HSw`BWdBlPzbN0#X;7xgOJ;J>z9nzN|tI-)sxE$?|lw*K7*&LpUXO@geCy5 CkYic^ diff --git a/files/opencs/menu-exit.svg b/files/opencs/menu-exit.svg new file mode 100644 index 0000000000..e1256eab72 --- /dev/null +++ b/files/opencs/menu-exit.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-merge.png b/files/opencs/menu-merge.png deleted file mode 100644 index c76288ae168580eb28605cca6c82876f8a467639..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_Wn2 z#WBP}@Mw@DUxNY<^VjMR;fMaatbV!a%-QCPCsLE&TJ4%}>Aw1B#;w;HZPGQD8ukf2 zx>Fs0vQ(K>N8;+q*)wc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-new-addon.png b/files/opencs/menu-new-addon.png deleted file mode 100644 index df137b2b204cb94cddfe6bc5bc329166f3bd0c23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1FbW zi(`m|;L=IFe1{ZxS{o~EAE>$cFN$M5XTG67GU&z$gXm3P*ne%c33&Br`ObTm(;sHX z2B&I1pA?od-|(3E`}>h>Z^Seb*T(MsKJ(4qc=OsMf!R|g86B&sI-#?mfc442-en9I zTI(~MChy4*O3V4?((D$wvpkC_sD5|Xw)DRo5Obi@&TU?oclyq6(>vU+-;`lY>2dcjb9C=}__=+$ cM*mmV)hqqBP323C1p14?)78&qol`;+0L{H`dH?_b diff --git a/files/opencs/menu-new-addon.svg b/files/opencs/menu-new-addon.svg new file mode 100644 index 0000000000..46aaa1e1ec --- /dev/null +++ b/files/opencs/menu-new-addon.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-new-game.png b/files/opencs/menu-new-game.png deleted file mode 100644 index 701daf34b179e4c2e507788fd38366f9d83c9c07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;iE) zi(`m|;M?Fpz6J#j*K1#|%-&+5~5+}}`+Zp=FKa9hVk!j1d-CNBj$lkWtcHpe!-tP?^(cYK51uD5Gc}kTEZqVBl zDLgA>p=XQoO?FjSQZyelF{r5}E+txm0xk diff --git a/files/opencs/menu-new-game.svg b/files/opencs/menu-new-game.svg new file mode 100644 index 0000000000..416a774d30 --- /dev/null +++ b/files/opencs/menu-new-game.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-new-window.png b/files/opencs/menu-new-window.png deleted file mode 100644 index 4a42da0d1288678a5bc4bd01a4713834f3aba7a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_W(8 z#WBP}@a&{$p#}vGSHs)$^uoTgA7tmVnEGvoX1z%3>!%tAt}Cx-oFeqH%A{SOp(AOn zXt?jRv)ayGv32JvZ#ABcopUPXz_;0VuQ|n6A9K0&wD|l2aS6jfwst<34O1?yxy3DK zydi13!awf=jv^LL@`8(RT)7eT%${Ml{*m{uI=*idtt{Qkm|Cl~`N^Y5DWH=WJYD@< J);T3K0RY~_Pj&zR diff --git a/files/opencs/menu-new-window.svg b/files/opencs/menu-new-window.svg new file mode 100644 index 0000000000..33262366dc --- /dev/null +++ b/files/opencs/menu-new-window.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-open.png b/files/opencs/menu-open.png deleted file mode 100644 index 3766e17549830ca741e42055f9de51faa0263226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;jxQ zi(`m|;M-tFp#}vGm)F(5Ch65K@NVz>D)x6iTdze%m~rV@Zk-L%icB>&T|bV^hKmsy{PJL1`?c#)bI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-preferences.png b/files/opencs/menu-preferences.png deleted file mode 100644 index 4644297ad0dd75a7847000ec23f824e5845c0662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_p9 zb;Q%fF~q`u=_FgeLk2vplYKfC7fe@ae<-uT$iT3~EtJho@4%^2p+9SuczMr`2zYsN z?VtZwt(GqNkg;~^)^E8zmPaJcE4CzmEOdCk@QL=zR*Oykm)1@{T=zVtY0vl0No6|^ z$lX7BeG^x*)07%TTaOBPkK~VA-{g21IGArL|M+i`-ckvvC!zkq>6wkDCt@O)RmGa8<0ehNE3bfxb Z|CL*E(B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-redo.png b/files/opencs/menu-redo.png deleted file mode 100644 index 0cd0eedcaeb898e79a55e1f572c52256d9d5d481..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Gj# zi(`m|;MGa`e1{Aqj$UUIYI0C&WbywnC$Tt&(c9s(e*uFDyTfLmLKYo1jtHJ~g`W8B zIWKp$C1rm4R$G0)di`6Y^S`^F{;m_1$!!-kyL3#@plN<{nTYFqpU=e&Mgm3)-Z->R zh$s~OY9M~d^p1;H?c&h7l=#PCS+ z#x9>|~QaJOhytpOOywJKnq=q3<%szi> TOZHS?05EvE`njxgN@xNAl(>K= diff --git a/files/opencs/menu-redo.svg b/files/opencs/menu-redo.svg new file mode 100644 index 0000000000..f19f236e7e --- /dev/null +++ b/files/opencs/menu-redo.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-reload.png b/files/opencs/menu-reload.png deleted file mode 100644 index 2b780598c4162eed952e978ae557e465278f0085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmV;w0YLtVP)PGS7Qaa1b3$&sEeJkZubf1&Oe51JYd%SmYmz3wBv^o(wk+$D21{nnZwrGZXc+SW z?9#EOUGQ_ZZSO}>RD<6Z{?7v9$co&fRtdfkP6Xa(l2fKC!{2Ih3qDMZ0v}@AU{6Bz z4(jNO1#)#r3uRV}v;g-K{YpLs<(!;BrWnu@NS^$@qVk*tsTRUcr#b)47VhEL^(1Fbv;Z*HtX0>tt#fj9#%sAm8G002ovPDHLkV1nW%zJve( diff --git a/files/opencs/menu-reload.svg b/files/opencs/menu-reload.svg new file mode 100644 index 0000000000..aef27dd104 --- /dev/null +++ b/files/opencs/menu-reload.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-save.png b/files/opencs/menu-save.png deleted file mode 100644 index 4be88765bef48fc5b571e98b8c942dcca95934f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1F4L zi(`m|;Mw44p=Jf1Cl_Bo42|*+dhL7Uv*KOXLjgznjQ?h)nJCWA;Sg9_Cvx^rqJ+}c zYf(pM_~> z + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-search.png b/files/opencs/menu-search.png deleted file mode 100644 index 1ec63f0e82853a56d41b8678e540d32c5ad6b33d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 408 zcmV;J0cZY+P)lD$gAKoo`NXTd`Jc>ocFP49~&C^lABR^qz&11?yp zm59X#wel4#Oav`$7oWhqf`y2}HYV|#T@ohljE!EHopaB*_vG$Pg!p4fyFU!WE2Y#{ zS(ZXdDT<=FNYnJduK9^oMbP{VUZ$y?B#Gn>$mii-sv7T2QOvn>6~I4mZd{t-TIPpw zJB&STup`#sJ~*2WZA?W`RC+~(-}KQA%+eTh#$^IOi~i-(3|B4j41DV;I)(3fG*Q1s zp7cu56K8{0HzZ#GpKGnx^E~gsU6M~kZD16dj<`-(sxp6z*yb!@vX4m@lh}}UGz@IP z#u)c8*>Ra@yU>TTEPGsR2Xj*`eH;YA8~LEBt(GW04_C@zZ*?@c3lHwoJtl~mq|ZdV z69!sIKBzJ6!tY4zpo_^h(CnreJhk434>vphDf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-status-bar.png b/files/opencs/menu-status-bar.png deleted file mode 100644 index dfb72b1e13cf674dbce6c9d72f7bc493882cb6a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP%zKa z#WBP}@NG~uUxNV$^Vh0^$am^ZoGB`5)ip2r|L{!P_R@`UpB@jh%aV)V{ajc=@47y* zVR|#&`010T^k<3ex@Fp0+=ulye8}|Mct*u|y8P;wPY*JcOjh<-X)^hUSoEY9dTuf{ hNj|3YCvUr#p|??9r90x`8xx?-44$rjF6*2UngED1KT-ey diff --git a/files/opencs/menu-status-bar.svg b/files/opencs/menu-status-bar.svg new file mode 100644 index 0000000000..a6b4d15d1e --- /dev/null +++ b/files/opencs/menu-status-bar.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-undo.png b/files/opencs/menu-undo.png deleted file mode 100644 index bd177ce65a62cc08404295d3c98e550cf8280b0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323 zcmV-J0lfZ+P)rf1ZvFO7F0=P1S)EDdcINxOnVs8R&-+XBegA~lT!yPk5k(d9JH8IX@Flsj zIBh_&LUh9?6d%h9vbZUVjRqH`RNEx13Hbd+QS>C-(RgkVB$kpUSFj<%vlN1N$TxTo zt}D4*jQD|%as&YQ0bfYY9GYe9&;(c^tXo8qOj(u%xH}XCftKpr1d`0gOx4g@za{=t z0}A)JbraSt$j&lm=N9=E?{h{2$)yiTf+nWOyodOI8QVZJipM5!Hkvq1=-jYK_yOTy VK0Na~gXjPN002ovPDHLkV1lPsh4=sf diff --git a/files/opencs/menu-undo.svg b/files/opencs/menu-undo.svg new file mode 100644 index 0000000000..1fffc9959d --- /dev/null +++ b/files/opencs/menu-undo.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/menu-verify.png b/files/opencs/menu-verify.png deleted file mode 100644 index a7878ebb3f6c4c77230f8c080c0115dd7aefb765..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 487 zcmVQSK@^4eAtF{Hh@^M-7uZ;7z)DyvLBUEPpkRpF z2qM7;f{l%!2o|vj+KO8UHnC8_GL;ZWIxPf=g&`np*6&U-i&;|`yl`gbo_o%n$F5=g zGt9W(^SnX0ZPPT|9HtCNVdxbO(-+ev*uz{F?$1HP dUz_|ie*;IC(~hX{6SDvS002ovPDHLkV1m_N&5r;8 diff --git a/files/opencs/menu-verify.svg b/files/opencs/menu-verify.svg new file mode 100644 index 0000000000..d72d229edd --- /dev/null +++ b/files/opencs/menu-verify.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/metadata.png b/files/opencs/metadata.png deleted file mode 100644 index 34c78ffd61e30acaef3cc30960d59fe30979cc50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 389 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_p9 zb;8rdF~q`uYVbkc!wNh-S6BXe!Er$1XZhB5lilTFn|}$k$2?+bN|AK`_H##Y%0=Pi zGbfaqOl&Nte{=o3IEKSujtOtQv4#^z&}Z)2DEnZqRMCC6Ep$|)Sbu~y#5zhbWEi_K ztmey;%ICH@yCCoX4PA+OX$h@+&Mqi-oPY6NuH=Kdf`h@*dKZdWwa+U};AYTX&E{Hb z794Q)wJO7WhcEkXcD*$Ez~FEU%PZr9_qKJsy8l!9 b=5OW&4^?AKLb7;(eq!)+^>bP0l+XkK>c5Fr diff --git a/files/opencs/metadata.svg b/files/opencs/metadata.svg new file mode 100644 index 0000000000..acccf4f4b7 --- /dev/null +++ b/files/opencs/metadata.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/miscellaneous.png b/files/opencs/miscellaneous.png deleted file mode 100644 index b21f6e214104dea351f88a07146c7ba39a7a0ef5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 466 zcmV;@0WJQCP)j`*G%o6Ip3@pIU+alT>M0xlkk^ZUQfIINLJm;K=`oy>00itedRicMbo*@=7 zu7g@)f$k;cQ4>5!M^r7#GHm;m{8@j1d^0e^rT*-I?nm%nL=K^a;evb)^BVaooa)W< zYXZzUDjGA5Fc6Jlt}yl#Tsa^EY<@uRM)-(uI55L4!41M?;XVRW7{gC^Lb!$ST>{M8 zyuSpOi84#qm;mu1c@5#dNbZ-wC~vmmw2#PRBhEAC2A#U3;(i76W6VanLIq85fO#52 z4f6|kO)?(R#HQMT#2uLH;2q|PSVv1y6Pyye#1Q66OFi-W4a7I1tasx* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/multitype.png b/files/opencs/multitype.png deleted file mode 100644 index 05676e2de06f52ed563842c0d8d5fe888e771a70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1708 zcmV;d22=ToP)Ekc{Xm)1$i(h%(W|y+oEr<7?dfwtd#j#`W=aP>d z{Klc7H5<=7{e+;hy*X@yKVZUq?i4 zwO3e@!G|P^!(or}?!k~`kEAO{$F}cz#3sg{3&0P1(d=|*h1f=?&#>o%AFaH$e$%&( zCcpYbeo!8L>X@CoEdYlP$VMk_e_E;SmyycuyWV|&ckAwbwN+#9acONB=QAe%`g85g zH&E@iod6;bn-{oqZ9N@%@ZheOe*Kfv-#ZvS|D|L3b4wE8w?86b)mZh-T_4^*G%~g$ zYpfX~Bq?T~8c|g$Bb#~Y@B^Is*HscP?7XYa=6&BGojHTWoS3(ZU(D&M1C7<|2DaS${;V-n#adHzn{ShMW>FI)Q~}3ey~f9%Ji_B&dzPWK zTZmWA5(YOQJ|NB^;t?Qdi|sq#n|cZRmn6b8Ngv;K--l|2#|kb1pCO@A7*DDgAeu8f z^-tQD|IXUGKfvTGFYw0rPl>*cq_qNsbBH(^!-K(v{_7~09e%z5%qC6DP1+f;|v)6^AAy?KhWT4UYl2y54^&(gnT2X6_$JOAlM zqY+M>_!B2zyF^81@e)xSleP&p2O_Mh3{a5_!=VIBk|G(47@`O&fp%EUwdr>_e(D?# z@7+z_?e2c&A<3S4!P*Pd0b5n8X576Y<({$4xFkh`+!8k(t3f2FBiuD-Sav3;*upcBMI}oUzpb00mn@`^GyL18u-r*S=7+t zfR-MD|0e#6fK%<<`a~om0t!CNqd(3QWSnrDo zP6WmEW+KjEIE)goD41YkD2k~s!)Il&fMy3LB4TD1ZuB09h&Z1i&f_DP12I9=VNSs! z4#Pw+bAY1iu7|DY;g~nX6y}ImPym_jTxUMa^FCmRgcK2nx&pB?K}$ZwT;Yi*Vg{y& z7>Xh0vEp!69?}fM3h|lt1O85n(BpJIfPSKi^GIpb6uei=9EO#Ki_Iy|1me zH!ISwq&|qlK(4k(04E{^fRcUzQbPpI5pg&dzzp$L9K}S6%?yfuXGn>mXT+h!6tf~6 zW_`su?=eHJG^vyc5a%-Bfr=Rp%jshhK?Iz+UZcPSyjmZSi2yoBt%{j|7;~`Uo$qNN zEA8cBUP>nIs1`d-sv}!5F)YSDomea@RV+iHn3maMiii?b3bCnTQnW}ZQ#y89#2Ed= zH0@pq2sidYy1#ohKjVM!-5uA7TfQL}uU_XFlKfBGWrvVStfP3p1E6w$lx?ICV zh*z6j0Zs!`K;HjjA|kE?k(A6VKLv%?InV_nVE+cordT0F3*6fP0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/npc.png b/files/opencs/npc.png deleted file mode 100644 index 5b5b199be6186c4f92444bc7c541ead7c432b1e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmV;?0WSWDP)n;ZJAq-;U_^C_I~x44It#4 zD2aIvJm^_64{n7djq_agg1#oa*#JW73TPs<5sfH{ri9D~Lk81x1>dW9%?1p(Lzop2 z6TQ(Q<)NJa3VeNRUN;+HIskPb?^=eOkObD?<`7{h{nvjy)oL|Cn6`G5NPJ&P>1%ZO zTx(3cM(kG6meG6Rb#o^hz}lBQiz7sVHE8ZYkY{tMhHOAe?2;E$%x9V}_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/object.png b/files/opencs/object.png deleted file mode 100644 index 4f552151dbd78992f83ed7939f25356e38fc4f79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmV;w0YLtVP)7PS= z*9Sq+2ez%0S|W<&BuVxuw!$#{C_oa&ED+Zm$9V#)q-nZ_$RkFGD%iN|y6VL5Km^w4^@K7r`^EyY56&bcZxpns_ca?oa) zMDuE1;wh>l8)eQ}WImHzx3JEu8KkGNoX~NCGXr-RLQP27?L|@a;`_ehVj7<3wW;ra zb3i-_M_%Iw$G;Iy@g+(Dp$=h({#uj=#D(CDDPn=OA=c&)A7?0!F9rf);xR1~RRmpv pA(9{HoY+O&6wG>H_+t}O{0UfliPDznHH!cM002ovPDHLkV1iEIw{idg diff --git a/files/opencs/object.svg b/files/opencs/object.svg new file mode 100644 index 0000000000..717269b9d6 --- /dev/null +++ b/files/opencs/object.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/pathgrid.png b/files/opencs/pathgrid.png deleted file mode 100644 index 710ff1357671fa93ec555d6aa6d8371cd3b7bc93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmV;I0cie-P)TYau?D8ExwHVX%@F@`6X(dOv@DZHsZ3MQacNQhhSp_>k)V5${9(#QB-cc&txT0a}923tyX z1*C%Z_s#@ue_?ZoO9R&48}V_XsJ7xeC2p@#{R7`+c|HR#b1?t_002ovPDHLkV1nXj BseJ$d diff --git a/files/opencs/pathgrid.svg b/files/opencs/pathgrid.svg new file mode 100644 index 0000000000..ba16efcacf --- /dev/null +++ b/files/opencs/pathgrid.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/potion.png b/files/opencs/potion.png deleted file mode 100644 index cb173bb9ed177e2f3023c14e1f5ebb287ce4b6a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmV;r0Y(0aP)jWg=2$J kPKlGAKL|sL9m(EaKL|R9ppk7OQ~&?~07*qoM6N<$g6eX=b^rhX diff --git a/files/opencs/potion.svg b/files/opencs/potion.svg new file mode 100644 index 0000000000..b59d12683f --- /dev/null +++ b/files/opencs/potion.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/probe.png b/files/opencs/probe.png deleted file mode 100644 index 2e405d365324ef5da69e824106dd73ff5523bacc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Fqb zi(`m|;M~c(c@G(gxF&04WH4wZF)d4IedFjW+0r1|&^AfZh-LQ&;Svvz8O4iLxaQZ) zQMa|+c7Nx4t4+PnB^(7LCTuobmcRDvExj71`-#_{FitF7z0QH}o?GCShTRVzC|Xbb z$l8A9xr5M0ZPrr>b7H(%g?_lG-;6Vw|8Z|n`oW&Kg$_*dKLTwbLfU z&3hL{#Bx7&S71L~7U7{LEzh)WgNae2T7lXHkv`Uj(z*Rl<{A5MeIc~#)U-E~WW^2E z=3e}I^oY9pj+;xROOO9BR9qx(rr=(BaLYSh-Y2oUx#tDc0)5Ni>FVdQ&MBb@09{0M A!T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/qt.png b/files/opencs/qt.png deleted file mode 100644 index 381cb2251fcb072234d49752cdc5e1a79ff6e675..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 405 zcmV;G0c!qPx#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy8gxZibW?9;ba!ELWdKlNX>N2bPDNB8b~7$DE-^7j^FlWO008Yt zL_t(IPhTD(84M=q?cdCl(i2XFH5286JKydjx#l+M23-Aew2+z^VBE z*Ka`BFzj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/race.png b/files/opencs/race.png deleted file mode 100644 index aeed2fdf3e9d06145a1d295db4de35a82c218159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 451 zcmV;!0X+VRP)SNxYz;AK(%dS)qf! z;&WQailP#BIwFi4WR+^hNoMKYGq4f>*u{6OFfD3~(l#v#1vJhj>d*MKH3adBF&w@I zc4~Mb0AU|sgzNSvjG?BQvAb$7_`rLA3};IXj$}Yw#TOxF0z;!-++K(&MrFjsldLtw98R&h7uk$c%vkwEJ4JXmY(by9VWY`U`51e?PKoxJv*4002ovPDHLkV1jxF#RC8U diff --git a/files/opencs/race.svg b/files/opencs/race.svg new file mode 100644 index 0000000000..cd7778127e --- /dev/null +++ b/files/opencs/race.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/random.png b/files/opencs/random.png deleted file mode 100644 index 2667630f5c27ba416a3810aab36cbf9d8e872b3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1892 zcmV-q2b=hbP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv000KlNklpRqG7~cP6+fQxn#$KDE z5D_zj8DqvFA*T*9MJ1UWMOQ{X1xHX-0i@If6F$PdRYx^tNRh0cR&iiKn}ps=nqHFr~ue=tqpc zf2|ihDwU1^dmYjbB(uu3!5=r)L2<8!{HoFVuo36;Pr;FEuj2DK;o5D{5HMY4 z60j-Ie~L)P)Z{oOl<#H*uen(Uu}B1|REpr>VA$B$;M$c-8s%#6<~vnrtgS#p%?&iw zRicGd#nnYH^^37lfSQDcfLJI{*4N%fU3DeKhX-Z_r-o}){0&D39>iiXcsw3fnwg=g zzLG7wKJdG@uA#2tPh@ALAuTB$HddBO9Rgw7w=qyn;zB_#c5IUnkj6QCo`32%aUPs512Z)V~KuTgfUOaoq&bfNj zwB4?+=h|hjC@aQ}tw9L%^+Nv1OdLu{KuJ+9e7!sv9RhpfVwkf9`B-IX38N)T2;g%x z)K+0za1bsQ=CX5c2zW+XGS(5*Co>P?Qb7(DFIohXrAx6hR6?sUsY4(>Hk$GB^h9`g zIGhCngh;kv_;okCaL$}K2C@@yucmxfx2u(3{p}pY&V0zCcH^&-B3!*($P(djI1mxz zuC`i*b?#za0)Y1VogPkr6iddBf99q>n%(GfEZ?-Q_?3v>3l%I;R1D^YXI?UUfc2 z)wNQxSORb=D}$YLsyy>hD!e`2k$YT@>sKyJ1E)PtNr=Ob3m1aNu|r`_CN-fhfw<^B z%*fDNP1)7TwZVJaTZj)Hu`Bn+)nYtss6h=;e&)mxlwZB97yNQz4ld+nqbN6v1<%Wt z!$U08B@i36hxz#a^M#uWoNm32miz4Ht0Yc01Uxq@9quA$T>>$YQbzgiwL#!zB^PHc zJ5_#$sMS_Z!E-Xx$TsBbA+RTc86J4W8g90-Yb$S6G?1lr8b{Lh>-4;Ul$xwtn3$N5 z{>QRqSA%EEQ{gJqLm*nZn|c4Hci!MnoA2U$UJm33lGstBZl{K$%7p?aaLL#Sg+e%R z?Wcifr6-dyb=0julr)?f?C;jNUE6Rol~eGRrg{|RokV(S;xuq-I42&Loq6LgV@JzQ zl~eG{w0&^lJLnQ1_n&#&*Ts(7e83+!*5Yh#HV*EO*C@GVBzWGIFKY`%RY0|w0o{rPQlZYW#HM_=-vW9AFr`CGFm-t z|3)kIs8PeI%TAS3@CSFRk)M-=)WleWz|;1{z}DJwOy?GG?bk@cLbu{2Sv0ftTpRp; zeHFQIN0A&KrFYb3mYpi6;Cu&rn3^orydkDVGJhYhIO1ScaZ&!4cr{&lMOg{f*xJIH z9F&@ybOUB0Nft@^d=RF~mtlpODG3}hot{(hom)4-Vuh*7+H$4-NT!|BoE*3c$>t4H zx2~76ZdWU(r#U1f1hyoCkw*wwLK#SmmBLNr3=49^1bjY;<6Mo~Y0vjY?E;@?KV@#V zeC|-HO@c;g8mXmWp_-m2#zn!B53 zfR)8c!(+KN5rHF5?!d8EQNuOWRgh5eD;rqI6Ad{>4?`BYi@k(2aL_AC!FPvlp(CiW zGGF=a50jZM8e&p~*IGBwz;QnB1PPgCIC(T3vC^Gv&uOWX;-ui(+0b79cTcmKZE+V1 zhqjZPcjJ#sC_Hrx2{F5II3=Eh3>R>0SO0&HQ*9#Ft1KioR;xY{!;P<5Z8dIfX|7zc eeAzcW&;J1sm8E}EEyuCpMi}?|hzR%iZHk zJe59AX}ey$?yK3>CC^Kq_8)j-tzNL~$78dD%Fo=6@~nULg0EP3bK>nYJH0jpDfk_B z?N<6cd*eEXmt}%(33VU%8@z4aefoEgOJv8ax$HYvzI8WheW;ccdfct`nvGk>|L>+n jOj2c*S;ykkx*NCy4{KiiuC&J#=vD?#S3j3^P6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-clone.png b/files/opencs/record-clone.png deleted file mode 100644 index 262a67a42400f360345c578cd216bddb8bc6e06e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Gay zi(`m|;M-tBzC#8)J-36*)UMfS{*<>-{wXG%fEMn*;m#ro6@SrUh1_vcAE0Tc zo3F>>yP>_`U1R2<|IB}q*e`!Pl(xH_%`E;O>rVdblLdLtFr08|GMM+OYG=shhdPJ9 z>E!Zueml^#>)eN0IYy?;uvN_=!Ha5mc7IVz2-PzbunHCMnKCiyh=lvf-Hncway!EP VX4GnG8Ua1T;OXk;vd$@?2>{spXMX?y diff --git a/files/opencs/record-clone.svg b/files/opencs/record-clone.svg new file mode 100644 index 0000000000..3014b2b4e0 --- /dev/null +++ b/files/opencs/record-clone.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-delete.png b/files/opencs/record-delete.png deleted file mode 100644 index 817988a5d1a4cf18b48b67d4b74fdd4b6fd3ed46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP|(xU z#WBP}FgZbj^{@hq#KgY^r&WL0cQI^InR52Ti4z~*|F2KmYMcGPu_a={RRd;KPDVF2 uH@2y^*#~ABUSW!LxWU2`yO@bto{2%Zg@;pGV;L{dPzFy|KbLh*2~7YHqbe@| diff --git a/files/opencs/record-delete.svg b/files/opencs/record-delete.svg new file mode 100644 index 0000000000..9a21973542 --- /dev/null +++ b/files/opencs/record-delete.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-down.png b/files/opencs/record-down.png deleted file mode 100644 index 92fe788602136102ed33598031e7493325540320..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6Vm)0PLp07OCrD@=n9jLfMwywJ zxjA1t`04)tJv}Rg{(my}cbakW(Qm$^Xa4W2d~t2d&$@4|8{>bAB^7(_ejmvO1ov;B xxTNvzSDAr@K~2Jq-8-eX*H_hev&U;NGbG-S&@#X6+Yhve!PC{xWt~$(695OAIXeIV diff --git a/files/opencs/record-down.svg b/files/opencs/record-down.svg new file mode 100644 index 0000000000..9febe57065 --- /dev/null +++ b/files/opencs/record-down.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-edit.png b/files/opencs/record-edit.png deleted file mode 100644 index 8b94e163410880ebd3efbeb68b3aa23e595d2c65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf67JIrlhG?8mPEcTwkd%;+`18+M zl81-q|HO#dKz@Y69AAULw*Lit|NRHa&fti2+{NUk5t6#=+QaYj4>GoMYWeW2EjKeX z`0+OVpyuBr?{BDSi`uizFn>6SN6Sa+Ezixm|B{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-next.png b/files/opencs/record-next.png deleted file mode 100644 index 76866e4734c63dec80da28d7ef38c1def25bfa37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;ix} zi(`m|U~+=QmIK$XoA*l`H+&d$FVdQ&MBb@0N+hhmH+?% diff --git a/files/opencs/record-next.svg b/files/opencs/record-next.svg new file mode 100644 index 0000000000..bbc44e7459 --- /dev/null +++ b/files/opencs/record-next.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-preview.png b/files/opencs/record-preview.png deleted file mode 100644 index e3adb6ede41e99738350327d8717ed043c7bd82f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 334 zcmV-U0kQsxP) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-previous.png b/files/opencs/record-previous.png deleted file mode 100644 index 2009d84e04a2571e0f1ea41facdc882b0a50b24d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;j@W zi(`m|U~+`PtbXg~J7mVmU$%XL}t!8Yo;lrq-|1mdFrLEF93td?C#@rFF-R8+#P^LUdZZ znRi*VF*?k?+}Op(7+b_0YiMS7j)6(afOo|~&JI%vNy-2Dx3+Muj^YtNki)o3h5N)k z-Xr#nYzJBlGv=^0gfQ`*WDPPlD4D3m@a0^HLYi8reC-ux2AP!_#>qu$4}sob@O1Ta JS?83{1OOiSTl@e3 diff --git a/files/opencs/record-previous.svg b/files/opencs/record-previous.svg new file mode 100644 index 0000000000..2479c8bd49 --- /dev/null +++ b/files/opencs/record-previous.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-revert.png b/files/opencs/record-revert.png deleted file mode 100644 index bd177ce65a62cc08404295d3c98e550cf8280b0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323 zcmV-J0lfZ+P)rf1ZvFO7F0=P1S)EDdcINxOnVs8R&-+XBegA~lT!yPk5k(d9JH8IX@Flsj zIBh_&LUh9?6d%h9vbZUVjRqH`RNEx13Hbd+QS>C-(RgkVB$kpUSFj<%vlN1N$TxTo zt}D4*jQD|%as&YQ0bfYY9GYe9&;(c^tXo8qOj(u%xH}XCftKpr1d`0gOx4g@za{=t z0}A)JbraSt$j&lm=N9=E?{h{2$)yiTf+nWOyodOI8QVZJipM5!Hkvq1=-jYK_yOTy VK0Na~gXjPN002ovPDHLkV1lPsh4=sf diff --git a/files/opencs/record-revert.svg b/files/opencs/record-revert.svg new file mode 100644 index 0000000000..11920a329a --- /dev/null +++ b/files/opencs/record-revert.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-touch.png b/files/opencs/record-touch.png deleted file mode 100644 index 808e1b6c4b40b233d4ccd470fc4958386d33c8bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmV++0p9+JP)PEE!@CU zBv}dg!@$fxGe5Jl3>zXWow}|Qgb-FXq?AD0w%-ev0ww6yZf*L6{}V{jEJd?F38ZM4 zqTL+!vbjHR_fj-0nP7}biZ0PdKl_uM`%+wiGu)x+a1GvZv37z`dBh>+9eR#~P + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/record-up.png b/files/opencs/record-up.png deleted file mode 100644 index c8bfa4a34274561e236984ebc4d486d05017bd71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6Vm)0PLp07OCrDHr=sETEZQ%9& zr98`-?(?x(vuT!khNyD9EW5v%2MG3UujSt8x&3F|x7LmE$r>MXKi0M%`u~15d!nIJ xiE-$^-{((stZA9}F#g{&PlK;MJkHV#46n~i6gX-JZv|S!;OXk;vd$@?2>`lgIN|^R diff --git a/files/opencs/record-up.svg b/files/opencs/record-up.svg new file mode 100644 index 0000000000..351cb14d4a --- /dev/null +++ b/files/opencs/record-up.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/region-map.png b/files/opencs/region-map.png deleted file mode 100644 index 7631847beef75552d7e2b1949259627987600c98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 428 zcmV;d0aN~oP)lpYv1?F3dfp;iHt}kX!rUZtv1xl#xXO414!0&U0@qnv?^=M45CNIfjVPRmCG|D z=mLT^S;hHfLLl#18)`DqYXqKo*N)?uae^rU-w_jmXWp|$${Fe2eqvU#Q+!enb~CdV z>Fp&?Y0=FWStmpSrPGJYDWGKpkaKCBc{u%y41luSs=7vL&$5c%37?6htE z`_NyTN&o>+-#$39Yzk W4f$`6a&e*n0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/region.png b/files/opencs/region.png deleted file mode 100644 index 2ebaeb02850fe497f5ae24daef767139916e2fbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 605 zcmV-j0;2tiP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vGf5&!@T5&_cPe*6Fc02*{fSaefwW^{L9a%BKeVQFr3 zE>1;MAa*k@H7+qRNAp5A0004?Nkl3&4 zKk!Qef*>(s(8?|rTKK37b!F(cSmp!zE>IcSXc12RDJNUdYGI>~`UcSoF2AGl1)26x<_0EyjB|^!!pf!M z>)cWwoHYiq|4+acSk7--Kn1ID3zeS^5tqFuhlq38@G1WKjCq@%?{UFO)xUpD$%3c- zhDan^H}>i80qLnU1zlN@r>{~O#F^p56I8BeGMVv_eIPwO?yoe54P_3&-00000NkvXXu0mjf|El^g diff --git a/files/opencs/region.svg b/files/opencs/region.svg new file mode 100644 index 0000000000..4458c7e376 --- /dev/null +++ b/files/opencs/region.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/repair.png b/files/opencs/repair.png deleted file mode 100644 index 1b5a9ccc11a5ca12b2589ac4700a344148164d88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 367 zcmV-#0g(QQP)Y01WK2NB3Fo%#|vBX=dNN*`3{4rS9G=&-1ipSxQjH zwAPv2l|mK|VHn1BHV~~G?ovD>9)gjORYpOR{400?ecQHG);EbChz00HQS^(yF*J{k z<9sJcav=E*KETEZ5ln(0(D;ra3jzEW=oY9fym~nVE!a<5Yo}?tCZ2-^h~WlsjlViX zb1~od&rf`zR2e5}yPz>)osqhxihwKhaAR6s6?uu7)=|2^_AEPGMXqS3@JuW(x&$(b z9lq2! + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-icon.png b/files/opencs/resources-icon.png deleted file mode 100644 index d84c90d5dc841c6b893970f5d791205528ba7f42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_V?) z#WBP}@a?3Fd<_a5uBy@X%k5u3-|6^bilFZ8FAJyF2=2MpY&0i2Cg6{u+a(#LPnxPV zmyaxFwA#k7TC`U9RLX|(_~p!3;=exL)xYKR(U~kx9DS=Nt?lVxXZ}3-nD4ou35ws# p%}bYXCaC^+p0Kp~?C-xab7HTCtlSkQDG0Qm!PC{xWt~$(69B`5N6P>J diff --git a/files/opencs/resources-icon.svg b/files/opencs/resources-icon.svg new file mode 100644 index 0000000000..2054ba0b2e --- /dev/null +++ b/files/opencs/resources-icon.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-mesh.png b/files/opencs/resources-mesh.png deleted file mode 100644 index fdfa3528b1314612ff417ff703f78f534d905b75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmV-Q0=4~#P)H27(lHr9~iiGm;ivAZw9}R+b4B)AV`9W>6O$_i8TlG zy5S^WiCxkBFv%D_EY}|`zl9zq4`M#C=74zQ-G1qsqMjth)07MDq|3-_?DNsx;NPOH@g+vY{!P!?vx+x6@1Y-H z2L=s4ZIh>Tzx+FX>3{?@W$pZbBN|R>_)X`@E^8X%m)MdG7H154?wnQcXl$&zIN#KN Y0mg952>$ihJ^%m!07*qoM6N<$f+7YBbpQYW diff --git a/files/opencs/resources-mesh.svg b/files/opencs/resources-mesh.svg new file mode 100644 index 0000000000..ba93da8091 --- /dev/null +++ b/files/opencs/resources-mesh.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-music.png b/files/opencs/resources-music.png deleted file mode 100644 index 53775109c5bfe6b2f7981aacd9bcf9526ec74002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wk0|TRo zr;B5Vg%$VZ%>fhhr<&qv-{{t!633XgThcg)hE;}!1OLs8UZuru3cDDI_woC@b z2@iXE1dcy8VR+)QKrORFY=fGJJ_9eS_d`>Lj9|NfP`$`F21~&gT|x^OS6|r6u<6$M z^ZYIk`IslDT;N{t;t= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-sound.png b/files/opencs/resources-sound.png deleted file mode 100644 index 86871611f5deae184cf6b986797020563c5c3ce7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;i2$ zi(`m|;M7Thd<_ab&YYdcn@< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-texture.png b/files/opencs/resources-texture.png deleted file mode 100644 index a96c4bf8c7b8c1334857e79e33ddb9230423c3f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1Ftc zi(`m|;M%~8LWdPNR_}iI`OWcH&r74-SDXxte!pw?M+G587SGe0awbQ5alYG@JA1mX zFlSzPo6D7RJ=IDj3$!ZARN}k}Pbx789-Q;}_96Ep1^pIDHyRV#|Jd)DVYpY*@*z9Z z>kk{3q!`WLdQF^*H~Q?^T%O~PcO>N)|BBJcn|pQ1;lGjnFA7qX=j>Es5U~5GBK^Kl z=7>S>hIT90J15KLXuEC`3eB26@s0K$hY!|Yvxp`=!nrE9M=(02@;u6{1-oD!M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources-video.png b/files/opencs/resources-video.png deleted file mode 100644 index d86bc6025e729f7eee1a5e4d3e9fba20d30dacc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkQ1G~? zi(`m|U~<9&0fS#ZfBt2kdGN#uk4b_5|2J zp~Sbuu*A+oUwD^7&-o)qN_aCoqy>r(9NBQug7?Sw_wpJE+KsdJG4pyJUM8v1c9~&< ziq4WowzDi!MdBT~4v$VStY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/resources.qrc b/files/opencs/resources.qrc index eef5c01bf8..786040623c 100644 --- a/files/opencs/resources.qrc +++ b/files/opencs/resources.qrc @@ -1,109 +1,102 @@ - openmw-cs.png - activator.png - list-added.png - apparatus.png - armor.png - attribute.png - list-base.png - birthsign.png - body-part.png - book.png - cell.png - class.png - clothing.png - container.png - creature.png - debug-profile.png - dialogue-info.png - dialogue-journal.png - dialogue-regular.png - dialogue-greeting.png - dialogue-persuasion.png - dialogue-voice.png - dialogue-topics.png - dialogue-topic-infos.png - journal-topic-infos.png - journal-topics.png - door.png - enchantment.png - error-log.png - faction.png - filter.png - global-variable.png - gmst.png - info.png - ingredient.png - instance.png - land-heightmap.png - land-texture.png - levelled-creature.png - levelled-item.png - light.png - lockpick.png - magic-effect.png - probe.png - menu-close.png - menu-exit.png - menu-new-addon.png - menu-new-game.png - menu-new-window.png - menu-merge.png - menu-open.png - menu-preferences.png - menu-reload.png - menu-redo.png - menu-save.png - menu-search.png - menu-status-bar.png - menu-undo.png - menu-verify.png - metadata.png - miscellaneous.png - list-modified.png - npc.png - object.png - pathgrid.png - potion.png - qt.png - race.png - random.png - list-removed.png - region.png - region-map.png - repair.png - run-log.png - run-openmw.png - scene.png - script.png - skill.png - start-script.png - stop-openmw.png - sound-generator.png - sound.png - spell.png - static.png - weapon.png - multitype.png - record-next.png - record-previous.png - record-down.png - record-up.png - record-delete.png - record-preview.png - record-clone.png - record-add.png - record-edit.png - record-touch.png - record-revert.png - resources-icon.png - resources-mesh.png - resources-music.png - resources-sound.png - resources-texture.png - resources-video.png + activator.svg + apparatus.svg + armor.svg + attribute.svg + birthsign.svg + body-part.svg + book.svg + cell.svg + class.svg + clothing.svg + container.svg + creature.svg + debug-profile.svg + dialogue-info.svg + dialogue-topics.svg + door.svg + record-add.svg + record-clone.svg + record-delete.svg + record-edit.svg + record-preview.svg + record-touch.svg + record-revert.svg + enchantment.svg + error-log.svg + faction.svg + filter.svg + global-variable.svg + gmst.svg + info.svg + ingredient.svg + instance.svg + journal-topic-infos.svg + journal-topics.svg + land-heightmap.svg + land-texture.svg + levelled-creature.svg + levelled-item.svg + light.svg + list-base.svg + list-added.svg + list-modified.svg + list-removed.svg + lockpick.svg + magic-effect.svg + menu-close.svg + menu-exit.svg + menu-merge.svg + menu-new-addon.svg + menu-new-game.svg + menu-new-window.svg + menu-open.svg + menu-preferences.svg + menu-redo.svg + menu-reload.svg + menu-save.svg + menu-search.svg + menu-status-bar.svg + menu-undo.svg + menu-verify.svg + metadata.svg + miscellaneous.svg + multitype.svg + npc.svg + object.svg + openmw-cs.png + pathgrid.svg placeholder.png + potion.svg + probe.svg + qt.svg + race.svg + record-down.svg + record-next.svg + record-previous.svg + record-up.svg + region.svg + region-map.svg + repair.svg + resources-icon.svg + resources-mesh.svg + resources-music.svg + resources-sound.svg + resources-texture.svg + resources-video.svg + run-log.svg + run-openmw.svg + scene.svg + script.svg + skill.svg + sound-generator.svg + sound.svg + spell.svg + start-script.svg + static.svg + stop-openmw.svg + weapon.svg raster/startup/big/create-addon.png @@ -112,76 +105,59 @@ raster/startup/small/configure.png - lighting-moon.png - lighting-sun.png - lighting-lamp.png - camera-first-person.png - camera-free.png - camera-orbit.png - run-game.png - scene-view-instance.png - scene-view-terrain.png - scene-view-water.png - scene-view-pathgrid.png - scene-view-fog.png - scene-view-status-0.png - scene-view-status-1.png - scene-view-status-2.png - scene-view-status-3.png - scene-view-status-4.png - scene-view-status-5.png - scene-view-status-6.png - scene-view-status-7.png - scene-view-status-8.png - scene-view-status-9.png - scene-view-status-10.png - scene-view-status-11.png - scene-view-status-12.png - scene-view-status-13.png - scene-view-status-14.png - scene-view-status-15.png - scene-view-status-16.png - scene-view-status-17.png - scene-view-status-18.png - scene-view-status-19.png - scene-view-status-20.png - scene-view-status-21.png - scene-view-status-22.png - scene-view-status-23.png - scene-view-status-24.png - scene-view-status-25.png - scene-view-status-26.png - scene-view-status-27.png - scene-view-status-28.png - scene-view-status-29.png - scene-view-status-30.png - scene-view-status-31.png - scene-exterior-arrows.png - scene-exterior-borders.png - scene-exterior-markers.png - scene-exterior-status-0.png - scene-exterior-status-1.png - scene-exterior-status-2.png - scene-exterior-status-3.png - scene-exterior-status-4.png - scene-exterior-status-5.png - scene-exterior-status-6.png - scene-exterior-status-7.png - editing-instance.png - editing-pathgrid.png - editing-terrain-movement.png - editing-terrain-shape.png - editing-terrain-texture.png - editing-terrain-vertex-paint.png - transform-move.png - transform-rotate.png - transform-scale.png - selection-mode-cube.png - selection-mode-cube-corner.png - selection-mode-cube-sphere.png - brush-point.png - brush-square.png - brush-circle.png - brush-custom.png + lighting-moon.svg + lighting-sun.svg + lighting-lamp.svg + camera-first-person.svg + camera-free.svg + camera-orbit.svg + run-game.svg + scene-view-instance.svg + scene-view-terrain.svg + scene-view-water.svg + scene-view-pathgrid.svg + scene-view-status-0.svg + scene-view-status-1.svg + scene-view-status-2.svg + scene-view-status-3.svg + scene-view-status-4.svg + scene-view-status-5.svg + scene-view-status-6.svg + scene-view-status-7.svg + scene-view-status-8.svg + scene-view-status-9.svg + scene-view-status-10.svg + scene-view-status-11.svg + scene-view-status-12.svg + scene-view-status-13.svg + scene-view-status-14.svg + scene-view-status-15.svg + scene-exterior-arrows.svg + scene-exterior-borders.svg + scene-exterior-markers.svg + scene-exterior-status-0.svg + scene-exterior-status-1.svg + scene-exterior-status-2.svg + scene-exterior-status-3.svg + scene-exterior-status-4.svg + scene-exterior-status-5.svg + scene-exterior-status-6.svg + scene-exterior-status-7.svg + editing-instance.svg + editing-pathgrid.svg + editing-terrain-movement.svg + editing-terrain-shape.svg + editing-terrain-texture.svg + editing-terrain-vertex-paint.svg + transform-move.svg + transform-rotate.svg + transform-scale.svg + selection-mode-cube.svg + selection-mode-cube-corner.svg + selection-mode-sphere.svg + brush-point.svg + brush-square.svg + brush-circle.svg + brush-custom.svg diff --git a/files/opencs/run-game.png b/files/opencs/run-game.png deleted file mode 100644 index f5038654fa1a3238be2f3124e12c06e75e206773..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 642 zcmV-|0)737P)e5SHDZcKoowLq~M@~ICt?c(50iZn{;z2E~1kPPC5%Z zI_RRKh@*dmx=4jiPNIvmIw%Nj?#}PhL{m&lle=6fT;P(+{d(W`<-NNXB6m3joB~b( zr+`zyDKMc5)XzSrs)p`q0buMKBsR3x(45S4=GV`^Bx62F5x!uZ)z{6Lw$6G*=4ull zDI>eg4@mN`gO>(~ghjvG|&9nJxE-j)Fz5R0#@>#ijNlJqYDxT zNxO-sv0Z3vFrH5&_#4JAW4C%3d)|!sbBK>NzJ`jAh0JkdHrgi;1N)5+ zFX({8AxfdNq%s1Dz&OR#w!4p8p|r$)3?#@ip3K8(-cL)`5Fd9LL;f{Y{sjgRMQO<_ z+NKBFhrb2GyDauF=qQE2DZT^cPxDx=m;fUd)JTTiD}YvRlRF8lj6j^d-T?eMfIsC? zJw4Vwf&M|JQtuXkU#7tnsoNvKu;EFhtAcOm_4850tPnsl2gQ500MZ0_l|~r5N+l5Q z>m7hs?(%31b!wq<2=x72;!slC;z`P$@v2z@%FhW!@Ld2uHjXx9L1P5|{9LX8{6~hZ zQkt|0;3q}>2fxG5m&)? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/run-log.png b/files/opencs/run-log.png deleted file mode 100644 index 463ead176d4c5e367262864fcbcf4e5a19d23ca8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=G_YAk0{w5XjGVuN& z)o`BQMRLN785QCkyc;B4)-e8`JbCheX5LKZB)*j94l{-of+-9<%MbD>o@Q8)?Qn0C z;^~GZOH?L!-(%d!ZprqCHS3JxO>Rw1O@-*`OorT+jTHhb0;j&oP_b4FoFlGb#4yG3 k&)>hDhYYqVtY>04?6v!2)}vJ`fv#onboFyt=akR{0N)K>X#fBK diff --git a/files/opencs/run-log.svg b/files/opencs/run-log.svg new file mode 100644 index 0000000000..404f74a6d4 --- /dev/null +++ b/files/opencs/run-log.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/run-openmw.png b/files/opencs/run-openmw.png deleted file mode 100644 index 1033d62baa120ce5c3ae4e2da94d122f88051a7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_p9 zb==d%F~q_@`Op9V_RKs6Mn;Ejwn!AzDzNdKKKJL0mxr>C+%oock}3-3zi-zsP&|7? zqUkEbf@l9X2{_+l*vM(uTp-P0#M1HfSq=Ne^2QqsvmIG@8FsU!T*%qrnCoz+F-PDc zTLbT`uc8?z#3wjrRxk^uY3oV7lA5qR$D^3>j`ahEI`$)SOC%Y-9eTdsVUF`6@qK@$ z&;BjEq*7C0^8}HO3mG;XS5|mMnK%gvaU7p8dBQ)%-;-sSTRKm&E0{(kGg@W~CkuGk ZGJNsgqSE=Fa~{x344$rjF6*2UngEJofxiF% diff --git a/files/opencs/run-openmw.svg b/files/opencs/run-openmw.svg new file mode 100644 index 0000000000..f0ae78619e --- /dev/null +++ b/files/opencs/run-openmw.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scalable/editor-icons.svg b/files/opencs/scalable/editor-icons.svg index d41fdbde60..921c5f6d8d 100644 --- a/files/opencs/scalable/editor-icons.svg +++ b/files/opencs/scalable/editor-icons.svg @@ -8973,9 +8973,9 @@ height="100%" /> ;4DjL?#JK{<}`s9f!E^74Ncv2KxA?P znqS4>A5Mm5XZ+3RAsrteZUE@6ruIe*{@%QT2Z+HR#NdaTy6eD4apiOpRVR;q>U#s< z5dl4!@m)>rgBbjmf4MAT@Lz#jRoz?zw#1dInmQ0b+3!ohi5sB#Xd!|BF_B`hs`>b+ zZw+3k>gMJWZ!#-Y-K^MlYm70*n7>43YK=AEIdD4$-z`}kbRKvHY{lT;pH_`tk;1Jh z+E#V518gihk#XQpDcoa0(A;hJmDA@`6*Pm$IwA{8PjHzYIJPH+Y0*RP(g095rQkfOn@hH01mOI6nDCH0_U@xo^N`RX2O% zMq^$-6^6hEP3;bF3AoB6bo4Cn*|siYj4@_e`~+R?wcq}e9b^Ci002ovPDHLkV1jzv B=%)Yx diff --git a/files/opencs/scene-exterior-arrows.svg b/files/opencs/scene-exterior-arrows.svg new file mode 100644 index 0000000000..1f923c91bf --- /dev/null +++ b/files/opencs/scene-exterior-arrows.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-borders.png b/files/opencs/scene-exterior-borders.png deleted file mode 100644 index ec5040dc88138bb66b1aaabcd88783a2c365d44e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmV;e0aE^nP)$3h|I3oKieQ2xAZ*62h3o`-Ct?@h&0sWquc{c$*OV%}M|O zA}3W^-2ag!@feN|5P-hSpP9G?L?Df*EnQ((7G!h|QaAGT4x9nF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-markers.png b/files/opencs/scene-exterior-markers.png deleted file mode 100644 index 6fffcbbcca32de0ce0ebee5fce5e48dda8bbbed2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 497 zcmVK@@=Df8_46t`^H?Z3BXZt&%2)_NV`VG) z3>H`H?6g)81e;X*0x2X!(9+U2AU2B1F08wg>RxhF#)SlOzHVS<&N*{t284KsdSr3E zUjG7ocrb@=zVCnj)5T8@27d><2MEKE`~6NnpGRxW^?Jp!EDXaS3`62LCYQ@`xm+*| z1Iw~r_W1Eg0-3a0S*=!?PNy7?N0d@5mrHEhMr%!@(V*Y&v)k<$4u|x5J(46zC2nd3 zY&IL#>ow2M&rBv0Mxzm77^0M7KA+=x9^>(tLZQH5Fd&mjC-hTV1=zMtx7%gE-@g{) zI1T`w=h1GrS*=!7DiunlQfiMlwGN!mXJ)e*+wGQOu}G~}BaY)YbF|iEv)NRCp;S7M zBni!ClXAICtJT8uJQj-uolb`!2mmlm6QvZUY5r5+=vUyA)*90^IUEkSu8Y2$&{j9<6;?)(17zjcKY0HqXB6ydrqFJs`%bukQs+wJyy@~OT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-0.png b/files/opencs/scene-exterior-status-0.png deleted file mode 100644 index 6fa47b4394f11ea2b334f8ce599bd5ad1315836e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1932 zcmV;72Xpv|P)vn>RZ-ZHAlsfOLT2;bBHbM##y@!CK3}zyN_j0KebQ@bED4c%1C)Z2J5A@%#M* z0)eqLGG+om&sHc`u3SlTb2GiYy(pz6dMT=OydNsARwd~rpi*x7Bp|z&1t&N(R8mgcxbRL%Xxy^0ve>d^3#U$-=VPr!DaFvx(74BA zu^4%Id0f7H8Nc73xXhr4{QVu3kWz|REJl8Q{`hC$8oBuWeg+2zlflo}iSzb2V1Zvf@@Wnt`` z5J@IbhElmn)dx^0Um7+Z>jVB74FyM10Dfla<6Y%|i8PdU0!yYMQoOf64OpgpX}LB& zl9=Y+hHK4*Xebz&j6eZOFU6YiVF!G`0l%6e@Rh)ifqwx3U;*$zq@nb0DH6$WM6$0X zqQRQe(NM5=G6H#MUkS#{1b7S34}4lgBCg;q0e%Gpf%TDw(vvquL~AgnD;f&+O-A5d z${%=-jSb(d$Ik$VfqGy!@U)v+4?F@q3Vaf{8+dTqMA9;{?a0;6XefAPG6HEpS~L_K zo(Av(P9{|%a>jZ5PT+@1se7!o06ztu5RrB_z7!B37uYZjA_0IzeCj5$N}|Wl0$YL4 z0&87=u}Et@cF7wAtkycmT8kso<1UfSKp6PkbR#ll9k>DTGN9FI`92Zpa31{u@FCz! zfCqdO*eoJl3BB`kz(L?R@DvaM9u|?fi^$JiMAlD-h?)lQ7lDh;5fE8mJ zcc6{{e-x2#yU)!)uZVopdHfLY25KA>OTa6@FM$t;$Vs>1ZlFj+)+O}|JwRMU7AJkb4|r2Vo^+q@0@{GD z0TsXockri-h^jpH)%UxK+u2^#bj9<$mz|#PPV~6js1Jw%7aW;qfQNxKB2u07>``E! zb3&tt+?h1~8z-9=fX7^V&2vT1KNb!5>}|lSK);B5urgeii&kY=&{%7gRw%8?D#LZR zpWa@w#-+GFd!F}Ux4;h1^SXe0MWjGPD%@fIEwBT4#q+#C!iLWS`$gnOB60|5aDWr- z*IMh{!0W(H5m_!Gg+LV$_dM^rZmmxMe*#+ZtB;H-hBBoTSUY|OZUYvpG_9~;v1lu|pawU3I((=OtF6_IZw zJ^wOrFVJK&)Q;2NDk(y#LgiD~5d#oyuWCA;){{`(yWPqPgMu5BU1S4`JT)_ zT-m9$t~17jL}XtQh}WD>pLGYlSwz0)#-0E^4y<>2{}@myBL7L4|7E4r9&7C(G+&5p zFU`IY@Kh`D^+bNx+mreGzWvTq4*^#l;IE6wfdoJet~&PthehQ331e$qhN%Yff&D-` zn$M>Se6qVxHc$-wBN__Y6r^>)T_YY4k)I_+q$%Ng(IO(-lg2k_ty_&TDS6!8(-s4l zqM=~_q}OSseI*tP#`FW7QxO5qE`7Y~ITw)!0l&L4>=BWt5+qdXYDxBVJnn!Op?!r4 zg*79mqM_jBsT&%lM*mVI;v&-Q^Z9Dy@%a5BayZH3>$KKCF~+=z=8@?D$C}a3Fok|# zAzHtCw2geb3mR?AM+O`bb0Z@8$1imUN2N6uk&J12+z%8fpMN3NV6C}U@z(T2L%}nX z6Bykv@zxh}|Hpc}!3i3j>mw3=t2^fxZ#@YF(L9#Q;VjF0pKXefAb zPF|}_K;#_Yn@(1_Ro)AY67gvTVB@n7{D1XkuBb9xS2+KUa^B``-sbI=wf_QPyj)Vl Sbo&wj0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-1.png b/files/opencs/scene-exterior-status-1.png deleted file mode 100644 index 2e1ed0f6503621aec50b177487c8c906a7e33c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmV-;2Z#8HP)J3 z{$a>(n{2#@$z@ihIp6O&=Q-y*&xJ7=lTnF`W^xb&JAt}U zVt7qeKYOKP?d>HJi4YElNu^R`G8sxsOX=z9Ash}9 zi9`n1I5rvprckb&HER~l&CPUmbs-|Ow6suCQi5}idGqGc(9poag9mA9YGV2F!v5^fMHn3*R8d9kgBEt6V+lj?utY5#L%F0Ssty+aKg;8BpC;}xV zB`jOEjKhZypC?mZUJgJk7GuehCG6R=hnX{HQd3h?uuWVr4|I2Tvt`Q`_U+rpv}x0r zJ$p8pOy+`joO6sHKfa(@s30D&*0N~PB4*5(!Q#b>iN#{<*s+79OPA8u*9SmxaWNu7 zadGiAl}29$<~ZjlE-t3Cvy+O73Y>F@2z`Bh=PjO2rztNl=k)2*gu~(NW!_NLyZ%=p zWC28kbUIB%MFoS;zy;wF4u?5=_G~Wrg6_jH`M;CeM7`7|>dn>EAy)}Fz!Z#Bi3l!Z zJAh*c>ejleN?^*S9+L6s=z)t=Ns+;&GyejRaHs_9t_qP{0@D$hkW+mCK|)2iOu8HR zdomvF&ja|;sZX@s0@(JIHLbwp;fPGx)KdgZlTgtFm&sBg@*Z4gPbA~f_Mr&G5Hl5L z&kuXxy&m|vJb}*wehmBri1@Dcf%cU(f6kN0I8UVXLLvs7J(7$^yM`iAjtNy`?P!2+ z0eXP@RJGj~yve|?fGDt_ePzv|D zsSUuRz+=FtfIEN(M@*z>T&e3n*P4t+&kRMN2q;R%qp1-9-{!-lPF0V3i{A$PP(gs+#d0`MLMVf{_rB5dePyIO#3E1o$*iB_iXzWe*u+Znf5)0D6Iis`{oUFvk;! z7-K4}wFiM)jWJ@aO?j{E_Fi29)aL6E$piTFKshjTFvdNoJ-{DS^*jE#8R$~gZ+VOF z0^R{m0k;E-RJAn-f@gurs(Qblw;q`7*SG$+8+_Ip)+17zs2|Sa%Y0aT26z#88Tcje zVO2fk6|Ms&s_Oil^Fk+(QPoK~zi$Tqrm9c*=i7nTfv*EIfQ5eJ59<-B-S@Q*`HI_m zplTfu*qI#}Rac=}caF<`8F$jV- z;2u?tsp<^BnSTp30xt(a5Xn;bJg`+&f269rfR!F_w*1-{vkrI*Sgoozt7?_MD9Z#v z@IAlQy})Zg3t{=#K*TUzM8LW8d*FItk`x)ify>yA>-L}ODASYMfJMNImk5uIK5p*} zg5bNpSbY_^1vsgyO_zB8ZJP{<9|}sZ|1!J5^xW&){T?KBj2u`h)9)$ z1lMl?k_YP69?#7}LlIf+i9DpLuLnVp0Co<>aF){JB2wv``+%zcC1>n|BJ!4V?j2RF z&KYY0<^wnT6x|NhKsV@$oZHm<6hb3nZ5_<$&i~i7zJdYFFp@-*s>G zmU;*{=K+61RkvjUTIs8EH?Uh(*JO>&^%>@FpaR$m9Ki5}e1Q+u3zY&>fWIc=QI|(( zZS!r!1FHJ79FMHcYA?2^>WZB4g~pf`Yi(W@_kG$V;8Zdm?HRJ2789y=IIy+{XdR9S zaBS)mZO?g+JP3q+%dk;ZpUw)QhkY$69f`#~@QIjEl^{6Ve>fSBo*w={BQo&GlZf|7 zb0`#gIFrfTud2IqEI!{D^Al_B3m6_932>YpI2q<~9;n2a8wZY&@124M4(9#6o`}61 zk&6ANI-&!iHRzFXBeZxJm?)ueCC=iUy)fdP?M%j_M~5abpfJ1ZOZ)G^v)$QC9CR-B zNaEd&vR}OW6cEMmcs`qR%BG&dKTTZLtzGt2UdZb|c~!1eEnVVRfsIMBkqa2el8Iv)&X5~Lbb6jeDWvBN50000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-2.png b/files/opencs/scene-exterior-status-2.png deleted file mode 100644 index 8ccd356aa985d5ac2accd33ca59e08b23ed6ad92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1969 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 DE;gUX diff --git a/files/opencs/scene-exterior-status-2.svg b/files/opencs/scene-exterior-status-2.svg new file mode 100644 index 0000000000..2d1ab9bbf8 --- /dev/null +++ b/files/opencs/scene-exterior-status-2.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-3.png b/files/opencs/scene-exterior-status-3.png deleted file mode 100644 index 70fdc4111e7ef5edc5a6dcf03c356f7c5fd45212..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1946 zcmV;L2W9w)P)0oO{S+0uC?~BPAk&OWC8qkv(IU zxXVgl=*lLOh(&CVfs2$#j={C0J^_$$C?D%C3z2jJuOaf?wC)2463W4)S`?U_h(%6h z0Q~TP|mF`)!G52d`2Rb8gFJhj-*>h?S z{B7XAL@csDL*S!<=YW3#dH&RTM}1Z4-!mlgMW9YXIb+W!V!+uSC1Q~koe{Vb6WWBe zJpsNNXaa6m)q3CXh5)Yt5nx(smkkP9he0qcZ{nfU6R*$i8j>U+cqUjH({?7QY^N zMnrCM&H=m#Jf^C9ynYy$J@Sh8$h7Vdk!}Fr1f291p9OpmC=ro9-m?3QG1pmZPXK3t>8kp! zCosVi$TP+iTWj|M*BN8PTATD<+2Xyr04UGYBa#8|=Yc|CRC|njP}_jNsOm5LcP(&S zRe$C!z8N?KoC0nDW~l1^APAlYhN$W!KW`Z@-mh={zrnt0b?Ff)k5_bM@p(Qh?gU-} zUI+dNj8)Zre#51}AXS~3c3)@!QmT4&+W%F+KUDQ`|9u1S4)8Eg22A&f-=#;SeAkb^ z;ydpCJ!6)990b9uKAvyvXmP($BhUhz@MM+&_W%=B_2#s(JAqZ+2sNsDeVYCaA2u6- zM|^oL^i40^?hQY7An+#8q^e&nk5}}^$VeO*oO5CXF*33|UNQK?1tTW<61O7=f^mL< z>L3UX0Jo@WR8`A-GXEK<23`+>Ag{xQ&jV{z^;uQj3{-i*9pz8Pn5Dpbz#>(>MpaAv zLs=>ag5UVHz71>#>Ilo%+aiXMA_C5x%YlKw)skZb2QFog4%mI_Xn~$w3(NpsxWs)DPh^U!z7qsN9N5?%!yPs~CL+boxi6{e`)Rr_i^zM< zxkIWtB28BVOa-p-CAb#&E5d#Cm8JO?0^U_0_#BavH;*;+ef#4@#+V9gZA?{HrGa?Y z$LZ5P(Q8%pw_f)c@GW4PkN0l^<*NGc4)f=T$O`A&W(@b%FDUJIG2oeY;?EP=dc2|U zTa9bHrKSL%dcZ$X)wLY}Rr&7R2y9W+#T|4LeTBIhC<4|1doaw-6nJN6p>e>I!1zQg z(waeNt@X!bz>S&}bwAww=r<)cZ2vkWZJO^iS&YmCf z&OVulMIP>qz&v1tPt10GdpADm<9T}`7CF>q`Hg>cwBQdPJq|=LJd#Or4qe$~d`_kO zt6woN7-+X>e_%%<7FmB;o>eYD3yT@ gm0szUUb$lBKd<9oYUzj4#sB~S07*qoM6N<$g0j+%I{*Lx diff --git a/files/opencs/scene-exterior-status-3.svg b/files/opencs/scene-exterior-status-3.svg new file mode 100644 index 0000000000..401f19a5fa --- /dev/null +++ b/files/opencs/scene-exterior-status-3.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-4.png b/files/opencs/scene-exterior-status-4.png deleted file mode 100644 index 2f2b907fc843d8534d1128b17d2f312ece43f287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1943 zcmV;I2Wa?-P) zSbh%KfCdv}&UqzNn{K{faMU(yhHona7X-20Vu+n)8}gXFNTPp8tSq-iJ6V*M&C9Kl z4#=ptO)uQubNr*{vdg8Vx3qP{^huiL-t#->e8120JEL^yd6)RSdPNy$>##+m)S+k}z3r$G`j4{;J)lpMZ!}|5> zDK9T)|Ni}K+O&zGp&D)t26L1CWM5}tG6gF+P15G{4+AdBjfyzAz;*s#=fh$$73N$vA?gmhP-v=>v zT8QKlcrQwoK^z{7CtIAGjKk$~}n! zV4?CAl-TrecA9$|t~F=lk#KA*0_7;Z0BbG{JKzHj_=P-y8{ikfzkm=h8(0-^8w9M@y4YHaBh%+Dk?lYf_`*aZGHxBX3h;iQ(`orm5jo~O z`ULP1;LCsqd>q&$A}6wX=br=nfjk7US$qz79(Wme5%`dZyyiCC3Ct6bH97r4ACMN28*{$j3%nsB zkGapc0$sq@ff`_)JNV;9MAddbWL?F*t7lo;OP=Sw;PiZ3w#VH@{Xhyh>&WZ^?g#D` zk>xqh9s%|`C$x&lEjiWZE}6Akz54Z!b#gou2&Hrn`Uv^sh_B=0?wc#_sQzG&+ z5jg-fIl$TWTdnm@;8o!JBC<$C<^aopwC8!>b8CGH_#@D1W*2;HL@^vvN`bXDa|X5m z&8k2Luwc_>d$2#%e8Y~|KA;YGeiV7^cDlXY^Stl4V)a#EF>p>qT1R>Q7*MQ~YO&Tn zEFzD)i2qGQzM1p<3&0&fTY7$=rT2lG+EA)q`4o28Sm0|t%i4aNn}x)5vxSx*Etbs%er24h{z*3 zhi~^gSYSFvsI-wAQ~g z#yn?(>cNQs$C{DOFpqwq0d)Vy61Yliv)+GP?}bK)_;dikrl%hG|LV=$*4k)e!^}I%8Jn>g do3ZQG{tH-lb!h)yw=Dnw002ovPDHLkV1g+Rt~3Au diff --git a/files/opencs/scene-exterior-status-4.svg b/files/opencs/scene-exterior-status-4.svg new file mode 100644 index 0000000000..aebc14b932 --- /dev/null +++ b/files/opencs/scene-exterior-status-4.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-5.png b/files/opencs/scene-exterior-status-5.png deleted file mode 100644 index b294c1b15a24c28c488c804da184b9402cbae4ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 zcmV-~2YdL5P)41!SOM2ni=rYE_%`Q7LDJm>p8=RD_}=eaO0<1!|Zu}ltvU0)h}G^LPha_wU#AImN0YXOqMQPN<1EC`}XZDU%s6F{(b-=kq9C} zBoeu-(&!(6dCoZ^kqA9KJycay;haN6=su+3(&I*@sILyhDC-cD4y0<6bKy@=ql zb}i7je@^S^OG;qsrW9R?*w}%K)JuuMWwQGKBpmuM)?E@J`2^mF$i%$r0|*i-!DTbO zz(2bZv4IhQ{~35-defm4U^^RYD}f(NIP{?l5t+IvRRYYAP{~A>%~2upE?j4ibtPh* z!x4xhW;)KE8TP>YJn&Nm0=K{~fPVo|-?h%~Y^<#)kVvT~QhqiO1I`}lO2m#1N1zfD zs=?Z^0N)CvfX}IFr!RO@fER!mu&A@Kw)~=q7z5TG>Pp0Vha>PF2}iGSne@e4yc^gB ztOnKtkNT;rf%||5fzJXr0(Xv@NJ(kA8#r~aD-rwma0E(#lCDH7JqqAY`7oKIs@>k= z*8^KbMQdu5mR>O(+Xp&pR}fIkgX0<(r<+=JQ!{83fE>z~_! zqpJEHZ}FYLo4`B34ZsprJs1SRVEy~EFI1Lpemt^e)4K5LEW5vfZyw2ff#6+SFJ z4?GLJ2s{sbL{(q+3fBXZRdr$Bd7%f$s_NBwzi$Tqp{kGg=No{Rfo}pcfyI8~kLVGp z+xLL;75BFNb6Q^rg5WtH&o|~;+$-t@GQcrUrVY3UxLs9m$$NJ%u-O}-MOClQ8{h52 zW(Tm!r`Jkf^uj~l@b6v){2oZD>PPF64WGftZX6h#J1s^KBhS|*8y@Lwtex*u+$%v4 z-0T-<4uaqiaI31uRduG{%)bMgffs`yh~_AK8hBDwf2OKCfkqEFSAJ`ZSr5Dh{7_Y| zRnQr44hu70As#Te6I ztxc%v<~$Iu`Z#^uZ}fIm{gEGg82A*h$jAF9fjU(^oiqPyBC^prx6_r%y+>BoG+hXI zp_TYtB5$Xgt2cK4)LZH<;FJgaEmeIg2T-H0&b`1cRb7`ecDv6ow*XbZlfZsgDqk)X z_;9^YIWQIYdsian3J9$&zKxi#s=vLLZQ2}+3X#vx+~A(3ym?qwAMc3O69)M0LR(ElVJhpfohDI zHh7GD_Y^dEFdyjiL~MbfHRO@fQCd6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-6.png b/files/opencs/scene-exterior-status-6.png deleted file mode 100644 index 872568b266adfe23d89f24a761119fb1d6a27110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1980 zcmV;t2SfOYP)=iJ`gOWWHtrC2uU2x|kK&N^7xw3)ac zxJAq>i2P_+!VuI8YaOY&jfF{VV<+3hBFuCkwi-jMGa%zJiX+)i0%9)9hJ%<2m~z=j z1u~k#TDiUF?2n#{mn)^Ww4G$>^WXcP_nhRX$l%ln@m8`5RthLOYJC`+U)^O<1AsQMQsIIQY7&9#U z`i3%j%9JT%6CP}DZ>O-ZkXf^4v3T)f)~{dB$&)A1TC;E8J}N6Ksi>%+sHljQD_4@6 zo10iB*4EZ``qProMa#;{qN=KjqeqVtiA31He?NJ7c>oj?6tHB;687xb!_=u$DJdx# zwnIE@66);iq@|^W0|yQ;Y0@NS%$Pwu9>3%pYb|5Oj2YG}G%OJ?#!y*VNoi>*ixw@S zprC-QTeq@e#R|H+y8#FU0w|>j1OnGo8l4P;thEFJ0XjN5$j{HmT8mPO?(Xi39*@Oh zm10J4Occcq2?X@L&z&hpked$U>iZ*o> z052e*~7H^cJkSIP8G`8Mr?h4!xfya09#y{1XTQV}UvC zwIw-e68SvPs(cyKFD0VEn(s%$p{D)_+=KRQ$C#l2Zvnc1yG5kk6}$<+E+7OfXs<2F zzA7SGgE4nU!y)O9z&zy-zG`DVSL^W;z)oNdumO15O}T=LEXR%@MOt;Lb)aF@ttAOd`Eun`%s4qO3v zC(!D&e7lIWIgdUAd=+>Q@PMxaD@5c-Qt$i{uod_#uoh?s?h}!?i^%IPA`1pXL=6J? zcHoTj_!8hw;5wyLrt|D!t@RDYnA5;HV4;Y-;|SdD2n4m(d${5q*qO#LP z^)a9<-H50(fWHFd0aFticcAtFe-V+NxaVfzl!*M;d3*ujRSbR%E{s$;5Fba;7wq!fYmO&=DDKhPej9gJ0AE0&?O>YDT~z1 zM62Cc&{%sxX@%12&9X?%lkK%7b6kph+w;6z-2(NV=N$oV6OjTDDRqbW_dq@HmgjlF zqzzvIUJ#MzMPvt1>i{R)@3ht%fOmmkh{$9Sxeh1?;-2UI+^zL3U@y>W#%6r2PciIP zN`bXDaRycabt*##uwdh6ZDwbzZv6W8EkGsk+GXU?TeOhk%P#u|Y6z+{(#n}NUE zOm+Y9RmG2A4){QI;1fi$I(q8I{rW_M*1EHQl(nTT9Sn!j8r)nu*RVKddTYO8iM8ANJIbYdZ0q^VB@xBM110BJyGq zpjua*JAs`d@>J5;T`t2^0QtZRz(Jd-mZl55zq`<_z&c#y;16rfu&>#CFFjr~cHj4#g{shb%hzL+SvF=E- zi^#oz-(4A+L}YD}gciG6l06uYJK&F_eGe%V*7VMfhC@61Bd`>upU0ZME=Z}giMWVt z^7(v=2+$HxP;%I9B>HCSsdRlGIpqT$e^{Sl}Firv9Xj3=t`8K>vH z(QxS4K!-he_Cj6ZGso+Jkj+%9(>a_)o4T|+Q*pom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-exterior-status-7.png b/files/opencs/scene-exterior-status-7.png deleted file mode 100644 index c19431025c42cbe98696a531473daf375240d7a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1957 zcmV;W2U_@vP)&$+#~m(pvRaw}|t#L>7;XB`YSF%$NJ zTa5V$B5z}fLr^b_I#YEU3zOPnC!1g=#dIJR#SrTZ$asw6NH(_-1XGp`2QdmPRW5jYbKF!=zFv(&;oqhYqE+wUux!`+wJt*R6MS0Q8pM1=PC zb_xp%>G}rF372p<%<0poGr3~he{jEhg`}%`bQUasawwh!jX8R3Xq)c)Qu06dMK*FIfW8Ebol1X4YBHzjAK7b&h99+6xf%(Zq z?07H0{|Y=by7FKvV4Et63xHJ;4t?oDL`JP`jRP-9C})aGcXUH3pTKqY*<>Pie@_G! zAZ9(zo>hC`e**4JCSo6C3EToN0sjP|{?t0HsiHVPOCp~G8YGl6;anmHoc%#E5v%Ko zz@3=T7Od?L@C`sKaEGck`Gz+V*bc;iSxptiLobSmF<|W-$wW+hA}~Y3(N|o1>S8T^ z6xaqV16Bi1`Kil*`+$dmTY(#ayZTHdCwGGD`1sq&L~KV-1cm{_lZn`YJ^+8ghsk(V zJ?brfJ+NLxZgS26yaGI~s{6ctG@!s0!0bK{DFH|(V((>DMzgT^hd>$dJzzQz0)}^; z^{ut10cVWKch2F-H2dR2J;`z&dY)YE`{H zL%+j^&1PV!FRul@>4m$z;m3{u{s6S9>Q_n|%co#u2M!F*oe?95kvB>k%b#efD4ym^ z-0mO zzf{$0RrN~$P?ipY;1_6p4iN$8TvrY(0V*ZOL~!8Jc13PWd*z5< zHLVBc0I!}WJnDSh-V_AE&wR6b0Qfv`LRG8JGyZ)bUqq^$a}TTPQ{Ll$SJfY9jDH=t z1*l1nj8q+6aCHqLWfBrxhjqXY_l>VvlUap&B2w*%%uv<0gCJ-GHh0Bvw@p71ks{~Z z7gY7V4BZz+N2#i!x}(o}OU(d2_JDt+sxNc{RN=dG3$RU9S9a6g?kmjAKq2rvu+Qbn z{A_{ubQYQjtO6z_6S0mgLTkN0Mod%H-)4BErrYsigQ`B7p`UGxX|UF2W${sKTML1o z0}aVU?5&;%OcxW{>~LW1AAu>o5dkVjS01eQ9=Qt$`y)f0s;=l3LU;RKGPExi_rM>+ zgdPwCXFH}Q6R~YQ5txsd=Ww?379^525$}<;p-|}VbUHm%RkvkWe5NtxH`dxME?4gB z3vit6ycu@h2ZCfG_F7K_7Gg|Y=QZ+^TTti4yki$|Ycdi0cb1{m<&oSzT6_dhA))X> zoW(hNZp1sgDw&8q(i4Hjz!;yHUHYzWe8R``u4E#1xVL1Fo;*`I{OKcAK+NUJ(rl7* z)Y?|#b1Lm${fdCAfG&$(0qjmDVlQ5jXO;61sRr^9c`)0ma=E+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-fog.png b/files/opencs/scene-view-fog.png deleted file mode 100644 index 65ea108ac54205654d7fff77793bd02a80e49274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DWND0s)y z#W5s<_3bQ2zGed+7U?7Z>+guMU!A)6KqlYWu-V)kC#TtN-hSa;q1>T#;dy^$YR|Jq z&8Z2ma4VQ+`21V!0{*o^%lY3J+x{0`C^b9u@sy1#H?NYM@ocW$mA4}I_8wTTd$WPp zfvHb`rQ>uigK`UR4g=GXr)CX;huF**7#|f$AK*x2mTq7u+{v5JvZ0aJp<%}zHUp;{ z2iO!GV)B?J6mt@o1r+qQGxi9WZD8aOn9l$G$W7fm=J=0#g&%9h6+0hVe>iwx)%U|Q tdse4w?-&2FKP=_Mb0bryqQl=+`Cbc3rY~%JH6Q3t22WQ%mvv4FO#nbqZubBH diff --git a/files/opencs/scene-view-instance.png b/files/opencs/scene-view-instance.png deleted file mode 100644 index 6f5e7cb2ac6c688073347515a1b874df3cbb33cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774 zcmVe5m|JWVRUF2@GdsIGyR*C9ZttyKE|IpO7D1?h7TR(X zx+N&YHzht1HAG`H#>Hfs_OPUkBK|lD=Yt%Rt}G z78rX#&)^isKspTqYpHX)yY7_hUlXu$gKMFVv8}R>xv~tpB8O3gMaQ6LDuzQ*1mZwc zQPCZy6P2#{Lofc;cyQ=KNE3Qr({5y1dewxDQs0kSgE zVASg&84U=A!kiu9XcWBzL-6_oXllOj;@y$9XB1IVNtW$6Vl#$XTyTna?d7f}#r0^%x{g=g#C z?hhu`$XydqwyuU{io(t!S-*W*wu}(Dczh^~B}*2dcve0{oeqN@FV1!LqNU{mW=jkO zHVJ}2u>L5z3D_5n!yy6`Gpa4nK86<|d>@rIN$>Qxb*|dQB4b}vWy|vlEqXK$1>t;PKDMsPrnJ~Bl?Cs_-tYeUO$5Ep%6%qO?ytKi&8zTHm5?ZC(0!s~eo+ZtDG1!eV+tH7#LD8KEZ zjOt~J60Y}N8OF!;hwF0^8l zT3KDsC@Rtfn5YleQgOzosOQ6KUeg|T-_1VGuemmEY@$QwmDu%-bF%vV3xP?}{$L$43%j7C!GWs-Xm?*2)yGV;lH zyY16)bgIu>orYg~jNlK}P;7EcBK8l2QCnFKQPiQ4!*_LJKEZ$AIf6VmK|U3=rqo?Rz^<}~kCW}2%DWIgs$qkP&`nV5wAa_TIi96r;69|*q01lX<)Ov!lM z{lEQj5A`@-Ctsh*^Kk*>{IU|O;gynf35_&g*|K3pqQUa{42Lh}@Eu9;6R7wI%iF*} zO#Nm;(Tx5aZ^Sgh9$t|nqq*OQvWLpxuvzg}_hp=KZl&JFfd&#)Y`*Gz64LkpME!VM zNcpmURDC|Fc*ai?0%%tGUPYGK5TN?s!*N)@kKuzsN7K%i6 z72lV$O{ErDDJy6l4na~Ppnr8tIv>|wbgz!%0yKa{k5;i9yJgpXX8pF2NF0SmhO>bi z7ZTe2_xgB)01b%O2pRt>tpY!!etmoeq?MR07*qoM6N<$f~KHTxBvhE diff --git a/files/opencs/scene-view-instance.svg b/files/opencs/scene-view-instance.svg new file mode 100644 index 0000000000..771432bebf --- /dev/null +++ b/files/opencs/scene-view-instance.svg @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-pathgrid.png b/files/opencs/scene-view-pathgrid.png deleted file mode 100644 index edb350b8b5842e835fd05cb269890e896f6ada8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fr0V0 zr;B4q2J73Yw%*K+0&V5yw^;tL3LQDN-aa8QHCcJdrp+5frkDiQHz_zt*>_FZwrFZX zwz}9xe<{b_)(PhvM2ffXD?XWXZu5r+3B^Y_p1(PFCiQ-8S(%^aPhln}1>we^zmHkY z2Q8C7`C-$^4|@A|H6PUVuet3b&G2*9rDY4ag^eYq*LE-eS~AO3F;B44fBo&?_&NOd zZCcE8FUapOiMVk=;doIW|LkupdWvcGiZ5=kH5NZq$k_8rW**!Bc?=%<&0m^%6|db= z;`r_%{pa$j8QZv=r`>X1b3!=Y>@4S<9Y%q#x>_CINFSO1m`@{T!kyPLpEK`rHoRaI z%X7FP%iXY^?NsQpHQbX=vEA1`u~YtON#N>oNCI*WBW`TX0bMhPcgULq^@TJ)2HV zt!6uorW2?cu#X*iAq&D*QJv}JJv7{`b z)k3KM*eZYFL)TW66f~aPJF}y=)@%9?f9oU5wna#G*e`x3zp>f2=Wcn!|x{ B>*N3c diff --git a/files/opencs/scene-view-pathgrid.svg b/files/opencs/scene-view-pathgrid.svg new file mode 100644 index 0000000000..b1a0c8845e --- /dev/null +++ b/files/opencs/scene-view-pathgrid.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-0.png b/files/opencs/scene-view-status-0.png deleted file mode 100644 index 1906fd89cd46cca2821b24049ba5e9312ad6cdd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3547 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-1.png b/files/opencs/scene-view-status-1.png deleted file mode 100644 index 6f5e7cb2ac6c688073347515a1b874df3cbb33cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774 zcmVe5m|JWVRUF2@GdsIGyR*C9ZttyKE|IpO7D1?h7TR(X zx+N&YHzht1HAG`H#>Hfs_OPUkBK|lD=Yt%Rt}G z78rX#&)^isKspTqYpHX)yY7_hUlXu$gKMFVv8}R>xv~tpB8O3gMaQ6LDuzQ*1mZwc zQPCZy6P2#{Lofc;cyQ=KNE3Qr({5y1dewxDQs0kSgE zVASg&84U=A!kiu9XcWBzL-6_oXllOj;@y$9XB1IVNtW$6Vl#$XTyTna?d7f}#r0^%x{g=g#C z?hhu`$XydqwyuU{io(t!S-*W*wu}(Dczh^~B}*2dcve0{oeqN@FV1!LqNU{mW=jkO zHVJ}2u>L5z3D_5n!yy6`Gpa4nK86<|d>@rIN$>Qxb*|dQB4b}vWy|vlEqXK$1>t;PKDMsPrnJ~Bl?Cs_-tYeUO$5Ep%6%qO?ytKi&8zTHm5?ZC(0!s~eo+ZtDG1!eV+tH7#LD8KEZ zjOt~J60Y}N8OF!;hwF0^8l zT3KDsC@Rtfn5YleQgOzosOQ6KUeg|T-_1VGuemmEY@$QwmDu%-bF%vV3xP?}{$L$43%j7C!GWs-Xm?*2)yGV;lH zyY16)bgIu>orYg~jNlK}P;7EcBK8l2QCnFKQPiQ4!*_LJKEZ$AIf6VmK|U3=rqo?Rz^<}~kCW}2%DWIgs$qkP&`nV5wAa_TIi96r;69|*q01lX<)Ov!lM z{lEQj5A`@-Ctsh*^Kk*>{IU|O;gynf35_&g*|K3pqQUa{42Lh}@Eu9;6R7wI%iF*} zO#Nm;(Tx5aZ^Sgh9$t|nqq*OQvWLpxuvzg}_hp=KZl&JFfd&#)Y`*Gz64LkpME!VM zNcpmURDC|Fc*ai?0%%tGUPYGK5TN?s!*N)@kKuzsN7K%i6 z72lV$O{ErDDJy6l4na~Ppnr8tIv>|wbgz!%0yKa{k5;i9yJgpXX8pF2NF0SmhO>bi z7ZTe2_xgB)01b%O2pRt>tpY!!etmoeq?MR07*qoM6N<$f~KHTxBvhE diff --git a/files/opencs/scene-view-status-1.svg b/files/opencs/scene-view-status-1.svg new file mode 100644 index 0000000000..3dbfa1622a --- /dev/null +++ b/files/opencs/scene-view-status-1.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-10.png b/files/opencs/scene-view-status-10.png deleted file mode 100644 index 1216c180fe3976e85e0377406721156f179de0fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 777 zcmV+k1NQuhP)e5S-)!(K@@&FcL5352o@qSf?yD96|7Xm!hnU^rO+-G zrqcWkijcy>Lb0(`Q>Cy7qNO4M5sO?S{;mWCiD$gq9ly7GZ=BszJo32x0W;k3-n^MN z`@QeInO$}xi$)D@roq@#=xqrgLKD3S5`_~3r*Q!==%$p@fb6t-)Frg?vPa*3RG2en zottDp^id&A-TvOk|Lv&rHS>Ti7JMwZsWJfIOB9(_)M`&dKcfLRqVEvih@)Un z7X-Ki=)d_ezkO5eu+0GYx{dppDZ<(|F_<&9W7)?i`cOmyupsZFf3;w{VPifBvW7&k za(vJ&P2^aYs0O<{1p%gyfazy80a$A%!El!cVBbx~e5521uw9HzN@pC>$0zzI8CY>; zLiA980qiG$zlA+O2$0RQGFGN^0f5oP_g@^FDF)bKKP4S5OtK5GUMxD6)lc`pqgOqef8N7MWN7)s1RdJf zc8?WcyaO=%xm0k!0JX-AT0(GgfZAPNof>g-#yKYW&=egl2XPojTgr<$0B!|~S3+BHuihsFP<0MM20{ju41^L=5~y|$8BkNG zTp(mXNub(2WI#=!a)FQmC4p-9kO4J?$^}9Olmx2X8=ryPcVeLfuP^vR!JqeyGEhVL zuM9K-JoA~$fd6f*hGhR0l6y0UQGRLK80IA!zl0hGo`d)e^!6c1cMT8=00000NkvXX Hu0mjfK>uAc diff --git a/files/opencs/scene-view-status-10.svg b/files/opencs/scene-view-status-10.svg new file mode 100644 index 0000000000..8263818403 --- /dev/null +++ b/files/opencs/scene-view-status-10.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-11.png b/files/opencs/scene-view-status-11.png deleted file mode 100644 index dbe8276f07bb8180ff786c28c5db6b5e134a52ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2424 zcmV-;35WKHP)e5SZiz)*A@O|cJ}Qxe&Bb#CTU|kI3`ZPfgr#b3@u(e z;SqjRO;HpTQdLg#qixhSQl(a?tturys4Clx23>(~z1iKSj?ckaD&=icvp=R4=#8BU^td0hB;j9rEtk|bJr4T{4|77?^ozE#yTsC2bB7BA?4S*!u0E!?)bYIN7y0? zK6Yj0t~@}%UjoPLIGs>H^~di9+%%uP124y{U=K50Y3tev3EYF!{=DZ|TR`cjz9IsC zNs5G{T^!9Vi9C&&wY03or_}GTNC6mk{U^157T5PjDZ&y#w2&iMrEhTj4?N!sQB=VC=$=Js%*IuVPpMDG1C6RofVUN31oj4j z|1-q^$UxTZQ0~p;RW*PZ{dxDG%BGBg`d%WIGvo$^3a8UoQ{PGjAQ@3dUI7`{N%a<` ze=e`ujqDGelK_4g-zKskJqPu73h?3sFo=m~n69k*ta zqfEzfJFGg+kzvpkrWpk!={V>)2_yaxycA*~Q9^G(jx~&U{Li0iJ+?6)tVt+bl!uJ;1u*LMFc}T-`3VOl;Xo*azJXylJzli6UwQt}fdjH32@R+};gfb> zV(BoNzF9yL*ry5T-xN^f1tyUAc$>gB8qa<%sTP(B(;r>nxz8Ay}35i`aph? z9__oOHF;JtncE4P0iTQ+Zo!C+8v zPgE!}v{4>2i>C1~X+2%wTfUQ>RADF9KkWCQ?9nnjke`iEID)1RK89}KHkM{5qhrK} zYpwtm6Wi8t;EYLDrZPec{IXAcb2x&!lLs4y*t0P~tOc#Dvw`uY%2Bh5w0hi;XVZzK z-!8$5$`y~utoIF$;I9WxV0%Fd!bES&EjR2&AlDR?WPn)g3rHBGKx8&#QnJW5a}*=7 zt0V$`>QLh_8>Pjk*44@s9@yZh`Q`mq!|y6{tmqtc!&X>?vcg4dQnZoIo!746(cBbt zP#ko*{3x~Yq*am&EqtBaf6gPm5CZnE(R;Ux;C?$K=?xxEk7dbhr>B=&jZ_rI72pg! zD+#eC>?C8Nk3|31J8J$?VlzIyGRuN9w_GSLe}p8HgD`nvU(<0cF-fF#6W;4}B10!4 z*UYQTo^?jVo*)*t9&BVgx>|mY9C( znU<#t7Z}k-vRJeBF=VBupnqr-ZyavJ)_fb>6lF~}+*q}MhnX_4qKfk_QMw$Ea@r0y z_A4Obua4SUmJYiI!>EgAJbr9KtO+~E4It)Q9XUy>b1ix_^f>X<6YF6$o6vrx3+-pm zVZA*CS1F%g9Q9#ovQE~vB8M)oi2u06>~n{kCIuf4aH@79tnxmP=s^X1rb&mx{XXp2 zQU$ZoD1$#w;H&JZ_-Md`U@(O81v*(W3iEE-H9Nf0Pwyr8L>O6LOzKoDtg5MfpD~|m z;L#p2!Leo;^n!pBpIkt=`#MT8Y-s6oA(f+@l(LLAldxd?*eQ~89C!xICvxZtNV~o) z$eBJDV?guKqZs_}G2~hGI7C7D14o5?2z&pNiwH6B3zP6JfiE@#$>ST7c0tDe=bp$Y zWgPYqU`~o^0BL^3JFo3UajFTebY9uEX|)`%>^#H3moV_xHQ?jmvBb+_U?430EAG~; zHq{`e9rncPEGyb?yHNV=Qlur@@LBIITyDQW*(MDwWKBpMevtE@AIMUpVRT&n8m(JtP35VX@wlkTefb+_v|(__l#oO6B}SM=uWs~eN9UTanDKa0)O_lw zeVpI5^M~Sl@9u|05m{jsabd&{lNbbj>X6UlbIo`>*hC&s4bW~5n`&xb`G!TmYb+Q+ zzLCR4Z}dDq)mbHe!F%1FwgJqT>Y7@Ph<}0J0$-)PE}zHmHK3W!HzNaPI{93TPh^0) zk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-12.png b/files/opencs/scene-view-status-12.png deleted file mode 100644 index ba6d1f3235bea33a17748c01fd6c16f9df53c5b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 923 zcmV;M17!S(P)e5SkH^oKop)yva+Ci7k?po76lhCdhieMq8AnM>fZF` z!HT;pD0E(BMOa)Mi?N5$JxxHO=(Y{t5RMO=PC|e{+ajmf*`a#=9|@VV`B&wnWn*Hs zEdo7wdkiK!8`>3tX-BDwKox<49;hT#(1C@gTOWbcWo{IA99;Q%8snd%K0$rBy)gG{ zl=#YgSoqqX0?d?;;X4%mW7^g7P;aw;`*0k#RhqCcdPdG%`x4 z8%jdNovA6mopgg3IQgGoxC|m|Nk@SOicy%E1ax}H#e=N%qT zf=Fl7_nPBbtgJBy0lg52Jd%!gLj?v__(MWkAoc*`mh)yT7AtEkK!AvV#47f}xny5x zcH#aA_sRv3c%jW%zgeuTu^<5g1QLD!Z;EBLg<%&#K)Vr%+R5x+-Y>^n=xQe6jJjctte}Om{JsxP1KjDNNdO^jyo4LzMa{=zW+R> z7YHQ5o%<@00?_|~qHwEcFLaN`8KV6791&t3-Se1ti8g-FY6$;(U5HLg1ZtmfyAouX z5)#mN4d6eAUhD=v=$SIs?}ljad=#B8n?kj5&7yS7?5a`;#2Al57Y%rH5ag(jfVY|e zy&*bZw}gV%rMHXv*3mxZxxL3zq9s#T)E>UtXd|#6R-`*~Ej%B(T^W1a|51;;jpsO1 ztz(s|JIklu(`szSWQ`>dAOIjir}Y)on*g|51<*dEG7LD)rNUxmjU^F?U__sXp0*CR z>mN2C8IR<}dE6XNZ5AtQoB#m=w0H4!6ToM2E~KPFeO%$NmYqg99H#9pz%OWxn;lu( z6WhdD0Sy|*MIb|N8}!QQ_f-U@9fK+YRRjupz2O07$UCzgTp)2TYc6z@ESOK0G xr6PbUkTt+{IFhRb4D@@)Is&GItOHL`_ybdd-_5S~u(1FD002ovPDHLkV1gW>mmL5A diff --git a/files/opencs/scene-view-status-12.svg b/files/opencs/scene-view-status-12.svg new file mode 100644 index 0000000000..2e16eb8256 --- /dev/null +++ b/files/opencs/scene-view-status-12.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-13.png b/files/opencs/scene-view-status-13.png deleted file mode 100644 index 3651cd609417d6b77e862e22d97af1f2fa9f45dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2287 zcmVe5n0stgSsll}_c5=|qc2+8LI*V1Hb8-8DKCMxP*6I> zg>E(*bs_#CU<`2+O^k}}N{lA{p;0zbffbD#-HmaDZOe9dODL2o3(G^h6qcn6ebM)G zrZdxd+kc!>9*2EBE&q5i~xPdiFaBJgQP z;DJQ;IAJz!cNuBERG#CO8aOy3QfM~vTzy4(dCO#3I4%3Ky;RMPw`sd;g}`xp ztODmsF$!5pCJ{D)gMm}fKOBOO4hA7vL2H02biVBO4!?M@=FDOJ_ zt_^m9`(=h%%*#zM!^A5X@C7l*8=+Wj$XYlLDar9L84NI+jPMT!7&`)?5Zb%@;P(1Z zTX*}#%2TIQLt?VVY$Rj!mQStz87{wg$>9ZN@xbyVGZI7&P3~bJF$w9J^WaRI1Bcau zA>T0Wwsqm7#(QXO@5UU`QHp^Fo7yPyX!C{88I&P$JS2i7hHq4ql^tO$)aSlhrfWdv z5zpsotiRLs8@hg;@aFS@IU;{J%W62VHr0w@^5W&b09LJ9hU^6y5Cs9f18&@EZbyCn zZ7ei%nCCEq=LyyuLMs7#LK2c_Rg%moTA*vhk3quskh1zi3chvlB^qo!=S^ zASg+gYvhnjmxW+i+*M!G1kqnv%oO%~FwEiXKzPHMin3a2!gO|_i}c>F={jih^WE;v!ec2GZ(T*F3u*lYSdTD+<>>rFy-+ryqYjbq>!hNI;m} zTir1PrwPa~kEEyod9gj9pobPBvmupsolFZyYlI=)FR{QcR+jg%9x>Gtvyts(QDv*E z=h4iG5-|=ED7q41%*NZl#IcF=7CDzQ&bq+n5n&Kv|0$FFdmaR*M;Rw;NG+lj_t=2)y_<^c^p)hythPCxeSDuTsi zQsJ)?e33H|A9Q;W42F;wFQ}5yJU>MFt=^}6hv0uPE|3&vk12!khbS=~$~-#6R_bMH zYoO~qT_N@uykM8Ty&Krh6}>v|@2BK-&BCIR9p{2^OICt#^!p%)s zl43`7y9bFJWm4K@^g9Xj{#Ca;_@@(P36!;eN^n1j=$?3{P$@bKwl;Sq-S9 zMY-FRuO7nAU%QDAgP&u=TLhm&Ytj)(OuDgD?cecA12u1#|5ew%oOI!3XQl}Y0}uKM z`ZmJdcc75hIgx$$;2PC)McN>u%V;P_HtVu&#tQ}MHk`fZ#@1~ck>s$e=NWfH1C|i{ z$tHr2i@-;Xq-pb9zjW+mS-BbkeHW6`5l%4dQ)JS8v@0VXmj>EKyiLC&3;Y_5vAg5Y z>UuVoCh?dOq6~X(<6JB1x;)5TnXAHo(%ONK>u#v<)pQ8Ujsed!FHvY4eF{$ZNpGC= zDBskBYju*-enko`B8r!(&C38;RL1nU6kbZ;D>Zm+oann6f%mGaaP5uXBgG`(---p# z7OuhIkQc9?s6y$YIk?p2rErEYUzea5xOT{zC;>%J%6>bK2N#CgZr&yXL}o}Vk4L{3 zD*~zkyGl#(Wv3lgEdzM=nXNDz4S2Pz8rzZ$=<$bftKW;o_K~gfzXjJrrM-N~PvB-s zY7a<7-$!4MWq_Io_U_$_za2jY(cyqK&Wy%;UC0r`5b4{shP+>pD5&EwsWeR@W3;cU z=kcjdIMe;7WWY>MJ`>}`GGG$vaVDmIbYna*;L-VZawE_B2*muLp~b>JTpvFAP0lHg zwbxh?m=*BMQx8Od?f;L}eKRoGXeOqy*!Rw?Ge9q)SqIMo_#er`s%*S$50L->002ov JPDHLkV1kn3TNwZV diff --git a/files/opencs/scene-view-status-13.svg b/files/opencs/scene-view-status-13.svg new file mode 100644 index 0000000000..1f2b3ab398 --- /dev/null +++ b/files/opencs/scene-view-status-13.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-14.png b/files/opencs/scene-view-status-14.png deleted file mode 100644 index 4bddb7ebc3fbdb999de2277e1837413dec770eec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1302 zcmV+x1?l>UP)e5nN5fsMHI)YduBt3$wd$~@jGA)A_~R?jE5-VA&OuW zRDviuxE_oiG#*^Z7vw`Bpa+Fqym-?@4|@uHi2;^Yr8b_2a`33w!1ABGac>44LZ2?*$6 zF{en`#(Hv_(D=74b>Yu>+%wU-B)bE)J}9KC5B}aJ|1jwIJmbLDvG}Bvlxqh7en5GC z&8yX~rT$XGWLJS~;>+0RLWh+M&o}Z5{ZGDJ?7~ z@!5J8BMUH7zDxVXjO;btkw6e8HbN?QN6pHLl-4b)$jc1~G`$W@f29M!YP|#vH>Csl z3g!DhsUWamoAfQQjWWt4K3gAT2gYMFQRf8S?+W#2vJspJsTof)LJ zB7G`5v8uN5fe(+h)aa2Gk;qqv?-@~dtgOe^3N$_im>b1Zh%$%K^dnV)%f83jeKKPD z=Nno*Ga(Kd@YhzGKFKIpsrxV;abQ_*b9T}BZu{>|&SJyqaER8Qw7}5#kGj*Egux5c z<8#3F&v)tl(bRhNJ6vYi0ZG@7clOJfrf8H6sUI0u24DYEs*-Y36BewDtitwUaD za+#3vfsc>3)Rr&t0pC|2ZCs>oT3$;LNTLAv2HN8sTuaT_V0=T&OYh`SDiId}6JqYY zIkfSIFAdbHE4!i&xKil|tv8G$bZn{+@cf-Tnh@MUUTpd+cqGv3t=l&Ae=nvYC+;g~ zzlPcEF;@sTk+BN!tG-u>ejw1cC}B5|Y7A$OhYK-CoEAvNOX0zv;JLKDgg@xBCmUX{dqZ4;>6EwIV2&rAK5O5{HKUj z2>}5OiE*6z0UMhCA%eAq;d&D!K8WQ5Rw^SPcpzbpZWp%5tfuLE6e8ca#<*lI0*NT( znvzSl*W8~ROGMZ68z3?P(SW?2e3fHpUr}LB?0VD1b|Ez${|KWNextSQ$Vu`SWWpL} zs$W|cG=975%yTOqlCM|E%UtTaP-@X)8nO#7clkngZMjHx;@=``=w8FT$Hei2xrXYT zpHZqkrvklP)iU4T$}}N`eUAbDw9#S~^u^i|v1S{pb#_X%e>tgii=ZXp*x^;B5{NL~ zid{5%`9q3_0H13D`h;r#I;}KX_v(ve$WiLI)E!r}Qhgu^4u3evY5lZ0AF`^9G~T%| z6Kb1w6seA~#uI0EtvxPlxuQ^I1Oxyi z>smA4oxo)3VqPwdC&x?ue?>q5U9scqCcqbSE~HFF`drCHpzJW}!jY6s0)Eumc(P;A zdZj)vD5zfJTsu%j8103p5cvXuLe!XJk%b+|p}az-F6=-dYRs{S^B^PM%H_Q0*SQ?; zD|~7%6B-KeqK(uJB>y*7xT;E8FuqE#zWm-98qHgMBu!}Ozzd1L0kFZn;oU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-15.png b/files/opencs/scene-view-status-15.png deleted file mode 100644 index bdd43407c9e2539051fdea0b759500923bbb98f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2701 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 Hu0mjf@MR^( diff --git a/files/opencs/scene-view-status-15.svg b/files/opencs/scene-view-status-15.svg new file mode 100644 index 0000000000..a8a3ce8573 --- /dev/null +++ b/files/opencs/scene-view-status-15.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-16.png b/files/opencs/scene-view-status-16.png deleted file mode 100644 index b0051eb1273c586e5ccfc4b3d371e7b8cb86127c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2580 zcmV+v3hVWWP)e5S9@$z=M_KSz1NNtJI>pA$2br2hCl*sD72+4Wp#EJ8MJ8_(c zWBcBn^U>=Drj$}rX_|bc_*ysL{mwbR^ZWhIXMpe(Mj(tp7=bVXVFbbmgc10kML@vJ zv|nX*?5oNg}`=47^3Q351AQ%kgNI^tNg2B;o zxN5b-yw7*+?RWqBEqwgg9eL~mh$_3ES+}1M7X${g^M1J0&;n};EOKI83_fC*_(Y(& zqesfkOo5!tR9+l)#FUBJf8UwiA7ts80zvojzVlsQ#Y$R$aH1%D7uUugtU z5TH0G11#w&JaM9xdWoV4<5Sac^j~#vo;vl>>-hYUsrASOsEB7IC%_%M3$z*$3N0Ca zNs=^*ECVHV4{?{2mz4%-$%$~S$p$64Sr8u+4Kl6~uqZ5AX|#1PpFaTQMY+&7GzRsp zj(1Tb-+q)rzHk9A@7;5FYh@XyiYiV@1QU`QZB9X_mB17q>u>4o(PSf?RI1QgD#|l6 z2M$+1tVlCKcmFWV`4*s}I1eJU8eS9$osx0%41(3(b?i?^j(_Ki6e8lH&%LVARlfVm zo)0n43Pf~1DpDsAiu}UlBvE78-H52F?nOM7L`<6H2l2S~qHd`(JYe}&$*#VU*Bu=_$p=Wj; z&fmNPm8{xojVT~ zTQc@<-?$b~nGjUbrXp}tjYfhtOz=jt9rChL;OX)b@Gbc76R`#@(>pr{?|*UyCcU%4 znmtvbK_3Z$z-RG!S2P-E>2N{!z$ip$1lYWO6^2tnoufR7ru28>>@^bn;lI59kMHB- zP)9-qsEFrer0}6*>*|99qn>k_5c|{){m%YjjXBi>nJI~UUERHo_>|fh9wj@XWBDp;5@dj-dUjfXJ?a5#|~k zWfi!WK^Fn;>6!cNm%a4$7vI{ssiMZ5mc(CDc}w=^nVCgV4IzDGWzH91D_5j}2{&In zq-fm?(&p^-CKRy|kzqnvL3T)-gd(jW(Kfa_!HAvc=oyreDngz)o&K#R%QY}QISsDC z5zuKQWo*jJ))wY~0gDeV9*hX+G}8Ixx$Ex;X{Ll4kJn4>CBE_v>65etw_9EIQ zri;+Rl*b!#3|dI74WJ#ic61|ZMu;^U5J@jg&&>MOy=WbMpP8FSo=?hJoDsNIpn@=| z&tl>l6ts-FEX>aNASEe*#YXFCY6n$N)tE>#=y3J>5V%*_AAk8{C04KV_YO~Jh^HmF zW_f(lBU|k*sjR>P$tWa}M68}{@q(DS968nYvX4p_xfC++7 zce5F2;E_0a68Mk`xY^?19l@ANFVd%Xc$}?4#HmXZlU#|!-ZMDL?Kj2{C1XrsXv~e& z%TS#CBaHp#C$A~yJdbA&iGy!L7nL#u;|qHH`eI7Yc26k*L=j(a~Mun@^c1VbgmZSAi z3`>=9n8|k>E~y|p6E>|Wf)woZmD@Ik?ZG*M>7xBqyevfx{OJb~%oJ34ZiU+he zOhFEM5drE5Ax+8Ao$Ro#zF96W%vNx43Ful(M*ha*`*eLOWFOJ1gJTm=gox`Sbx_yP2CMV3puWwi zbPc;hh(DO;k_D&>x9xc0XBg{^T~C!smLnX9xS#PRehBc+57E;lLPeEtb;)$~4T?@WE0;+Yb=%Nsd2cLf0rTr}Du@V(%YyYsuECpIr~}MguIiOnR5jN0i`^56(kDW|ER` zPUDDEab%-77Zk_9_>xpn<3D(Rr`f3qzb?mNr;kK82?Xaob3WY^o>ii8 z5EbWS@pBKYCvoDB7qn}4z-Z7*=9GjW79`To$_87P(mmpSC{@(B58l6Y0qRCoTT$%E zafe87m?xqiMP2dXWREc7Zv#5i4UFCsC)r{Dh#PgGfhK#8Vjmbgc=_BJZiniAk9vRX z0@Q%tczN${QOmDamgMpd5YGq4+zL)oM#m8nC)zVyvfAabshI<3KKb|Oic{V9VfSS# zKn=8S?@PbKf%d&8igR?xYkoAKpN&M7e5S7~e<+{^GnWNRlKU9LHgFat5!TJl_p)+B}oKJXNQLNyS0K zN$^JESWE(OQGzQ>DB|=8)}h3tS6F5c;*-IL2C~d zeF4;31?YGQ3yU%Mcr7HO2`h^7kdbDAPNRXK(;^&+GVF-PuUxk&0xlpTAm|O6pe{2%n-Ge9+IOLfH z3Yx%%;&2h*KstTL%1D~kEF_7!&VC1m z`i8NQPz=>39tO$@mZ&#l{djhr z#UhPHIW9db9fSSDuT=@6At7-Ox*`&;O?i*Bc62-&_ASgSPq3Bw%%MnyB_|u~Mn5Iq z*_I9j!(pjRC31F?1{bG8sB5f4c|kVfi6o9+Xobo%gLT5RfLwu@ zF_lJo&16)$B6#fAW~MWMBR!aVp76+ z(z$&baY~d8=drU^)=-%kvzSD5RQLvb;;SehaY_4@b0Gi{e_f} zN^-L3RTMQdlEJYl^b9*;N+hr;%Ro8|prT<7NhU`&t5=Vo#VSD}tqVBm@*_hfB3I8- z^f)hNWrr{^^$ za>$ypLXiwdY#$g^dlr1C(h#Et4c;F2GR-NClYGXf=eRY*IJ?FeXDc#G z<~K%8U6h+iL>R>DJwyByW3`2Aa<*Xd;NT?Br+-G-~45Mr@7N~p>xtTTXw9cp_KuJkww1c%3VZAxaQT2*n9 zp)%MClS~txgHH9OjsdW0x4p5Jtq4yzl-pz}vlY13>%fgZM{-AfCFQ$TR>+WR1}d#N z4byWA8#8TYwO-Ki&WV}itk2I^szuneJlYZh_T9Z1?4ffvdJr5M!unhb&P)biloBW~ z+zei@SkNEkVJATMZCQs6wJR_-;o&c~_aV)iBBmG()PF*Bx~IjC!BKTZNdcPHR3SUf ziVHV-Ia+-wE6plV&T!NN;abliTFJ@t(k&86i)Vq(Q*(H}eL(7TxWBzrg&y1Y(9bMJ z{qy6rJUesD$kwZId@78m9^6SR^7!yZFXH24s7g2CtuY@e^njU4p;Gap5{D_3UaDAG zBCVvV!mcaYmD#3u3{xM});}UkW7ozy7^$kTu2mUKGErL5i*3Esz=={g9N{X9^W;vI z-FLRN4^)(;;i>r-J~;i}FW7S`<>Bt0-uFboXxe4Z*i>xR;$2q|Pwd$SftdeH@XVO# zVP-(1qE^hWSRqxdDCVhZam*u9t!DYv3_K0SI9#OhuhrL5Rng%}M?Y+4Q^I64P_UAm zoUAEqBXZMu~X?F;C#NB$bh{gkq9_lAH{PoOoUz+6SB{ zq2*TboaCfBzP7S#sT{JPSnEACyCBP>v8G%aaZPiRv-7AT##x~_bG-+v%k4D3LmHX( zE-|hESI$c-(6nXq@SXy*s>>5ZSzRsl?HL#*8*jhbhV?n5dASLbVEKsovz`c6Q^gsUJ$H)heEV)8-_}F@0yIE}4@&Hw(fjXhqr=aIgODBGy+GaRszj&}h_{ zC&oL5-BSCo`{1!-Z{5VW0$e%E-Dv%WjX!V7G-?;AANQM6v5Q#s1w%M><}w~COGnF0 z2qrEGD{VNGYExU12a8d_>C0_=R=N$YeAp3ld%Rj!)|&5XB{WG!3eh6x3Ijk#WpI zGwnv2fs)xBK!b%$ih#2wZH#pPzRP=L+_P|;+_fo#l2u2$8mcG}n2>HW?6$Con-9 zbe5cqarcauazul+fiY=dV)lje@1K&(p#tbm&r1O)53)cSH*Pvyo0s{tFP21sj>DD7 zPj4iY`<3(8AKmv8@{8|mtSLhZwE`@usl}GaZ8)*h_k-X^QTUp_@(mf z7dd|_0Oe&Ykag?UeYbaT=(nLy?0}U2Z+Cud-@`u@wCZQpSCQbiP64z2DSYm7s6Zrd~Vc4L<+j7nI7K&cA&BG6TyDEHkjoz%m2>7YzIZmGX!F T1D;N|00000NkvXXu0mjf3R>E# diff --git a/files/opencs/scene-view-status-18.png b/files/opencs/scene-view-status-18.png deleted file mode 100644 index 7d92726876877243fc3ab99bc163adde658d58bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2947 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 diff --git a/files/opencs/scene-view-status-2.png b/files/opencs/scene-view-status-2.png deleted file mode 100644 index edb350b8b5842e835fd05cb269890e896f6ada8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fr0V0 zr;B4q2J73Yw%*K+0&V5yw^;tL3LQDN-aa8QHCcJdrp+5frkDiQHz_zt*>_FZwrFZX zwz}9xe<{b_)(PhvM2ffXD?XWXZu5r+3B^Y_p1(PFCiQ-8S(%^aPhln}1>we^zmHkY z2Q8C7`C-$^4|@A|H6PUVuet3b&G2*9rDY4ag^eYq*LE-eS~AO3F;B44fBo&?_&NOd zZCcE8FUapOiMVk=;doIW|LkupdWvcGiZ5=kH5NZq$k_8rW**!Bc?=%<&0m^%6|db= z;`r_%{pa$j8QZv=r`>X1b3!=Y>@4S<9Y%q#x>_CINFSO1m`@{T!kyPLpEK`rHoRaI z%X7FP%iXY^?NsQpHQbX=vEA1`u~YtON#N>oNCI*WBW`TX0bMhPcgULq^@TJ)2HV zt!6uorW2?cu#X*iAq&D*QJv}JJv7{`b z)k3KM*eZYFL)TW66f~aPJF}y=)@%9?f9oU5wna#G*e`x3zp>f2=Wcn!|x{ B>*N3c diff --git a/files/opencs/scene-view-status-2.svg b/files/opencs/scene-view-status-2.svg new file mode 100644 index 0000000000..656c5d9d39 --- /dev/null +++ b/files/opencs/scene-view-status-2.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-20.png b/files/opencs/scene-view-status-20.png deleted file mode 100644 index bb950d94e3cd482bda6b4dafdabd85c5f072b0fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2491 zcmV;s2}JgZP)e5S7~rl*A@QWB3ZVDEP0W43tQf>SqzxPO%t{ufdYmC z6K2ZKCWVkLlr%GKGijJk^QV(clFqbbrVt28X{OAyglq(c)eaC=8w@tWyDWK;ZQ1fF zOM0*8KI_Q}OMu|abUJ!7)|I7u?>XOh&iT#}5P2dDL>P!L5Mdy~K!kw^1OKxO@Z_2H z`}B_czAi5>U$bk?lcie|O$K~&`oiA#KKSQzWJ{WCdy@`eZF%{-<%>$UWTz)XmSyFS z<2dvW4&(EROM7?kKd^;B_$CX;qybpBcI~dzMB~<_^JXB4Soa44As?9$K@`#M>cQD+ z8%Dj}eSd%dA3vp!A3GwC4S=P}+C}rWGRAqH!|!f`Fd>0qp(wCKlw!V7TYHqgpV*{s z4zBl&KzMPoy=$s{8fLh1WTCva# zJVV1&R2`H)l04$|bNN%#V5ZB%n-tqOG&+Xk=c{0jHxM%%@5tGPkEPU5T};r<6idS5 z=0oxmaW*c`lCFFevdLt%ZvZXrUC?Pnxx0Umn={P{eTnSBF;#I~8!MQPFR84M`~v&=&4Cpo-P-%P9-U^M87$w55j z`?pUmYQ;nKC0OXEtsA)mhHY^9%yP&k*`tD%$d|F<5ie4b5;)_OSk|=zDnQjHr5Wm5 z99|;sIqvO0{#G`|>U{RjUX4CBn)KQt_4Ik9YFmp~QkacoDlmqgrxak_v#!~J#5g^& zDb+6DtXJ}1l|yETr5Y>t{q3`GA!**-QBc9q%Ibp)`0=8)PS(4>MpwIyn@x-x$PZ?d zsS+#p)^?X7zj68)iEQ#6-EK;~47t(K#c{9y?$@#c@QuRiR&n>y?-CDxN3;vsUFYO%Um%J-4{4#6V0z*DU< zn_gLqGaZ2D(wl*0rTIdXR;&0{-_`{|Ye)d;bD7y>5TkWbe6zDFP@J94-)ywQP3gc= zLrV@(rpT9X-sYMK^$$v>Vd0E?L{nNFJ6}zZB&F~~C5Jt1>Vz&zgA!9RE=Wm)U;^B| z;n4TN^lFlIsF9|iGLVK!iF(R#9L{u(!0weW*LQ=@NlQd8kyBZ1ldm^AeiKrmO&iz0 z85bM9gN3bZMy_Iq*dMEDXw#D1$@IdN%`8x4G(0M7?s4}I;?T(p&}l`vq+qICK&rw5 z!cyw3p$)hu#XJOvFlZDJ**k~3=s#!jB`36@&(#kp~dziyY;Ss26TQhQK z#1?o?ZYCWc$$uUPkf-E1ZB)&SulI3$medDh>lbjgRPRt3|K`DaMBvU1D}J=<4>ab# zy5@-zk?ApeNFn4y6<4_>bBj=vlPQtYyqZ=_7Ks(Vy|Y^+l|T$NA4RnY%%Eh%EuR%1 zjpf0`vuRekJ5?0M`@r2gjIo}&?I(^NdFM`_!vDW-1j0A5_mo;Yv&^Q~N~h&u3dvku zvlG?~GwPZgpt*=<{w#^94^5imos%X_1u(I#$}j8exzxOvM1FO91iSgA@ToZ-Ochh> zk#A-EPQM-+fO?RnR(5jyPBZm~LQASr3#`~3F1MD+TKVGnh&Slr^M{QRbePo*Q;$7| zPoXd~NiMLYac_*Qf``{4W3&hPUB_T=s=9BgsP^w%9~ppp!Lp}Uypofe@Ta-KV)y$4 zqn;73uAgQV7NKB7SmPkZCD4x-l54l$ppO+TDG31rB>c<00DAi|bl9&wFjZ8$cdp+V zfO^sLXQt;-$_WWzfecW3J3^ry4+M38dTX@Wt+46 zrOFe>6ggDyd(`!@0jLIl^6bVxQ!T$-Ha%B~08^y)ZnsRs9>>NJR@@#MMJlRoQg{E* zj$>bb@vX(F-us|+(g3K2Hf`MS2K9^=7Zh7{^s|u-h&=n*c)7M|QW#h5sOzKyP%mac zs5AV6CJ=3hdvHg^W2TCFZ)A-y5Mdy~K!kw^1OHbH{1*iRX$TX{yo3M%002ovPDHLk FV1iZi(t`j1 diff --git a/files/opencs/scene-view-status-21.png b/files/opencs/scene-view-status-21.png deleted file mode 100644 index 76ad0022c7f67085facec469df788cb98e833bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3009 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%0AX=J2{Z0+3?Vo+)M;sU7CbTV@+ zi?hOi?|giO*4(j_fA%QE{=?1Eam9sPue)7*?SZ;mBZ z?Hw3Wn$LDqDl!84l>zZJwRb5^9o@=8$chLJA;;j5px-Uqcl?YURCe#$rFGSmkvTbD z9FpEM{S6Eaqo~dTK0eJg>QUy*P9_tC2R13*Hw4&xe6$Qj9Eo%(YGF=>zc^V5@8O~? zt!ki1WTLLQ!w0CSS>_b}ER7Y#-qSZoO&whnYS3%;ey4J6u9YI-yf?5hBA|nSb4XGa zse5<6Ljz7HrW8POxKS7nD_)H$8l!;A)7#)e&^lo%hYM9mE6uFXFqS&SI0 z6EI`Kpx3u-A?1aqext>LpPAYir}MHbWOwv=PS!N(3v(=#fC6LhRosQRdsf-nC~j5+ zSpYRIPR75aLsrC4<6=K}{4^~q%z=TV?mu>#xZ!be^58w}z_IdLk&*mNv(^Imv~>0; z*C67YCDzIG%f;RdW0`*0p^`JTbk^>md}|ujw|0{9hsPh$%n3073A}`nr)rzfN%gd1 z$$Swx1Vtznis3yceBa?RrM0V<7UpH(%3u}B#QBMxeBOZ$yM1>tj8N#F70bNn5jyvj zA_lZPr)zEcBd2Q6sT1ht#q$Jf1?pt@abQX+8wl4Cy0MUZhf&y8*V;u&adEM>WBXPr zuq07rL>L{fY@~vW6lw>rb4K#4>0k&0xjkOdIVBy2p`aLEhe|6cGcAGU%uW?p@9OOn z#VP3!ZGtMnTHK(P6wL9#5fxP9L&h~kT*ncQMr4__j-IOKV%O$pTQo3~3Y~;*Eh3(6 zPSPqG+LR^pvP4!&tDESdUq4EIKK;S>?|N=l_>2vlwx#njMJ%Cbth~O}2w@ujQI-~D z3mOfK5Z`+o{Z4v!|1m;0)(W#{YuR8GPN>8#*8n?G4=2j18wE60EG?vP1Yr^(KsQ73 zFs>fVr!Losl50sJu0P&)ptOo~kX6^wv*F-JABc;k-vKBQ&qt0NrEQ!4O4kDa;WI)+ zp_WwCvvJB)Wv5Dh_xXk4Jf zIn>$HOXYy-l7egx=vOal3{c@qAxFHYZ$Pv64Jx-R$`^O!Ucm8->L%@>M;=oaE?B_u zIcGPbBuaeJB3@RkUh|~c6uoKjTq{*Jw$mcuea!8~U8lv6Y>K7yB$HNr;*63FYL&&w zqD0}rsgpG};yaN}RWvXL=rGeyhY*jzD1b&E46die`B_?HYp2p-@1;CMJbXqd?LSdL z^Rv?FctwNO*y(t*_~U)g2emcmB5Rl!t8cySchL33?bjFTnU8rOV%ochzEGAg$fLZB zG#`vsC9L=;4trWU?fQncF5+4dtOaK{QWNnKnZ;eo2S};!eOjjdWaV{&s`vuC1tF=Uv6$LTN?4bDc_&(9Xcd7{eZkGRw==b*L*T@1*8 zJS=C1mL(x(lL`GH$DAY@8v;4j*6lDdtrgw0m|`L$z*^_-J$#n$M~vky?;W6=w0JGs zoGc>FjfrU#eL<^j?-5Xux~9%SZ4J735eKBuTUM_AZAMb;(+ehw-Q)3&47f%^`*By{ z3{7N2T-RlBcJ??tkrCl~b7HI)4(T{ECn_5?TbE-JRHTlnb5L7@E?$BIQuvBhDE5Tt zOz+X^Z(N$6DKY@L)M0mM=%fl?M_A+lB7W#(jnCdcwBf@K-uD-$l<{SA zP+Nm8ehmkt@_W|Z^%wMvUtTxY8VX#Cs{#M=VyJx8h)bDr4r*)A#mjI&Dq}}Lnh)cS zWIXF|ZaDN6pdw{VorBsMbnyx}Fje`Lcn@Z4z>oSXq2lVx_`d^JKjxD)2K_%5V2yvp z`0qoLkNj`FT?j(c!gvnlqzr(3rj6ke2mT)hSm3Mbv~wU3LetK8&cc5IkG8pvXC04x P00000NkvXXu0mjf1n>V~ diff --git a/files/opencs/scene-view-status-27.png b/files/opencs/scene-view-status-27.png deleted file mode 100644 index 30eb053b9b4bb475553ec6327b6a18f825d682de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3627 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 B92)=t diff --git a/files/opencs/scene-view-status-29.png b/files/opencs/scene-view-status-29.png deleted file mode 100644 index eff610666206b1692cb06fc999ee0a870130b692..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3125 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 P00000NkvXXu0mjfdX@eE diff --git a/files/opencs/scene-view-status-3.png b/files/opencs/scene-view-status-3.png deleted file mode 100644 index ddf27c2db1e4ecafbf5bda486daf7c5084c0adfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2169 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 diff --git a/files/opencs/scene-view-status-3.svg b/files/opencs/scene-view-status-3.svg new file mode 100644 index 0000000000..56b471de20 --- /dev/null +++ b/files/opencs/scene-view-status-3.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-30.png b/files/opencs/scene-view-status-30.png deleted file mode 100644 index 63ce7d0d254ec549590fd8a9d12e5f57aa0d250d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3096 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-5.png b/files/opencs/scene-view-status-5.png deleted file mode 100644 index 63d37f8be5b5c20e1e45fae96325ee73faf5ed43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2097 zcmV-12+sG3P)e5n0ag*R~^T{bL@R&eP8j$t%7aEv6HlMj@F5fw59PH zS|vh3sHqTtB!D8S0zyC$r9vPf)Cy7wrKuDU6)m)agxbcXiR#30p-Gb%+&E5ZH(9T5 zJGR%m-g9$RW>e1kV#}Ktdk@`z0BvB0x5y(E{aZyeQ%O z$ypPUiXlmT_T7g1U&RAibpQljMUCq@Ua+bP^-2n5_WTp;J6=Xjwgn26T^x&GdwCg( z$s!7gce(QuTRF;vY=a5F(M6e{jW+4X0B%hxcD0@B`<8am+ zt7vYlf1f?4cvqb+P>Wwve$E;k!`dsy@u==5@|||HkB8vgxB*Ysc``i*vPCZZF;PhOB4C#&u3dJomL(GF&x0=ZJY7A{A@@u84d4W zfiOCP2ea+yml}!Yyv;*Xa2kMI7LuMg_CnZgC%|} z82~BY;>xk^$~EiocCQalJ+TKClM(G*ZnR(i2z#6kbklm?=?&pQyP$cS!81F!g9=Vo zoq!_JL`aZk0%1*lLit4RVOw8mF57GAx@!P&_!K>lcG(Em?yb;?BF?p4L(J2Ik_;P~2mMIlXeXsrWnh73iUL{~e6I%^2>z635;>xR%ti35myp829Z?Uld$PoH1n*hpYOPInH4=a{ zbOW*BZm1F+25H_got=0BoQ z@X~K9+36Kd&>fob`TQ!gip$=CX|NK$4WIN4;p6se8hkSy!iw$!&s3L*+#OVLW?cT`DZl#7x$fugD3HUdEUhOaKTo9r zwgRzHNvOCS+eqLKECtVc*F5!@tL~+mEX%VQ1_A$8P1s+(9g|Z5ym9h0_N`CH#gPCF zr-ZfhHYf(Z)FEpQ{qA?p6VU=`ptFkt5LqBIOKKa{UQ+SJy=fNG@!YrWqf_JQUN81P zv6Ig93jTEF13X@k3Xh*Y0mD&junF2~69@14lsjh}!1Fb|JNx;IF|vxd605}9Exu|2 z&?npRcl!O`5bbtY%tpBTM^G%rAkw#M3#ng~B53WHRsLJ>MF5ux{_t`(S=461Pt8KC zq_*x0TsRs%RNXT3i?+^!t?lo-tNJV*#P42-tur2m*ub?TWi)G znvBZGH*n|--uWRBuYa$vcLWdzVk1Jre~-QbU!`?@_6sQfJb6tjkW?V4KvIFE0!amu b3IP8B)7_VjEAYZ800000NkvXXu0mjfiKg~Z diff --git a/files/opencs/scene-view-status-5.svg b/files/opencs/scene-view-status-5.svg new file mode 100644 index 0000000000..5a74f8e829 --- /dev/null +++ b/files/opencs/scene-view-status-5.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-6.png b/files/opencs/scene-view-status-6.png deleted file mode 100644 index 051aa64ae7bbd4d2e6bd51697eeb7be5063b1f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1104 zcmV-W1h4yvP)e5m`!NZKorL(*(zG~=0Om@5c~pBu;`&4^x{FqgNRj% z=t)5lp?(}(!B(uOP!PYM7s0DmJrulp5Ja>^5JXFB!B&f(C}>^nZg%{=B$KAw)?LkR zDw04lGjAp{|Nnp9dy`$Ik}FXlQ6Q26b6US%48>pJ_nj~}Og%UUO#eie5(5WNeT%O!L7J0vc)b9aWSEa(8zgIK-{!u`eU5hu zVk11da&;2}r}6Q$WfKEVZaZLZj<+Ph*U{I`!8P4I8{F6s_tK3#VkhDfU||lX($XOW zrZOC|skD~3Aa>kqf{26;GB+LW@z9L_WOu~HPN04Y@XhWggqNXs2|||L$Rh*M^!T%s zuP4}nznv1GBEl&$RhnQArV(P0e2HNvgdYbTWv)afVDLa>A@w$ZuXJO>?~u<7;_4~Q zRS@w%UCmq3%d!zLP#|)_va1fcXNoae7Ku&{Nk>lmCWw?RW0jqNV1`6Hv9LJ^@PLSW znoDadB<>hdY#dH?3B#)bM^75`*< z$yh%JRrYO{%DwARI!n^>e)Wy=n2HkcF|WWc22r#)1pz*k0d%*@edtvh)vc<@^4=5b z%ilJw{$4oAC`N??%GD+wS~;!vy61!U+hTZXUvcNlfTuQXKfs?bXcxer4G$h!i;aLR z3kf-`>$#5saGK^H4RMvf0WR~&6)OR6N$)xL+R*&$!1Hcgrb^taRK>${NPWTx$l|k3 zKFR=m3g1daT}8%^byYfzjB>IK` diff --git a/files/opencs/scene-view-status-6.svg b/files/opencs/scene-view-status-6.svg new file mode 100644 index 0000000000..4321be4269 --- /dev/null +++ b/files/opencs/scene-view-status-6.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-7.png b/files/opencs/scene-view-status-7.png deleted file mode 100644 index 6b2e5fdc16cacc0ea7449461bd470b6eaf3b0b51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2462 zcmV;P31Rk$P)e5SZQoj*BL!;=FL81Y~$V7KtyeqorEJMlm(kL{o+EO)*x~Pjl6=^FV5?!K_ZYd--fd&+_B?ZFLIv6lG;N8Z?>v(L> z_Fm6@<2SYk>@l_E{PC0C-21+}o$uUpzkBZhlg}grlMIZDfvmlr-F#<{tCMjwHjJaK z-t>89-qk-QIvtk-WPT?kgHbZd)0uy2qQQ&tq_GT2aGzzpTXkDqKD|C|xdeV)4F$s{ ziCn0Pfpt{9&P1eRoq@j*%*#=LeyN5+5fdjul*J8SWF< zXwQVfP!C1Xq4u%Nu76BaI+htIiO2-_hYpNj8wmclTmztk!tB<|CNho802%!@2fjdH zWjX-bc9P}oI?IyL1T_>`$vPhn*6E?<)k@m(blXIx8g&B${+wwo-H{T<(5#J{!4mn0i@ z=QvE;mZvz-PZlq<`>=TNeB@5gfNV6Pt+N}IwN0p~xQQ8737K(L#t4G-22fAHo`*csXX5`q3*uMnLQcmZuC z+_;?D-av*@YW|H`6|Z4!nu7r=g!64aEL$=kd6bAk@-ANc1XrqRk*)fX9dAQBbza%! zgP$8=s#(HRzBYm-`I>~pm|;DLT=)?{MR`|H!imn{s}FI^N;kTF8vE&_ zSO**pR^W+##AF00l1873E4|A4W2GfWMV%oIc((Cd>;q?`8{hA{!2Qe*<~R*MUO~BZ z^!iY3nS#fb&4=A;!JYO_{Q1ZkJep`hhRcGF+xpPp^@H_c=b8|T9t&tOt`5AuU&W0+ z<<0gGww*gt(yn8QIG`J1r3;=YlBUXrvd^VC^RvnNhj+YKxO5>tla+=*Foe<%F2UH^ zf=ANgP|?wc+a4cgI}C6P02i!_CzcbjfQNe-G6T9{wDd7|@hWQdgget^RH)x-*@434 zi!|1o?sni0hfm^*)8i2&y=Bck$hH6(*6**8@nfvZjz<;a`L)hIJQ8Qrw5`jbx>v!$ zg8firE`$-D0Y^lWAMxGK2v|Qt)e+4jI-rA3u^Mr_)rT*;^I@}CH1Jmlerbe_C@pcL<3Un{Cvj}4;(MBJK#Ma5qf7C&tqRnY zZ)(|DMBCtVUk7yX31$PzLsq!gEQU#zaq{w21Z!(BC)tIvCJz!M?xc(|L&1wEa;aPC z`qRO8;<@Sll*qn6)n>yj+)J-E#L zJhI;#-86C|BlF91o#vPG60A7U(2b4jS8EIQBc5jj_&EfBsD|KqZP&m@^`xC^Xlo6s z!w!O+g-)8Cl+#|`E4B>ie0XaCoQ#J$8^df1`4Bh{mY4Z%Ch&^k4FkS7Nr^X__z>=z_x|GH^X887fC02c{WwHfvq z2}?!ApO^am{yn+VQn#pFk@*ep?yA-vAG9=QSO<&)_o1CtC)GBC-&BmbfkI8Ef^AOHXW07*qoM6N<$f_NmQ#{d8T diff --git a/files/opencs/scene-view-status-7.svg b/files/opencs/scene-view-status-7.svg new file mode 100644 index 0000000000..bcaefa0bba --- /dev/null +++ b/files/opencs/scene-view-status-7.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-8.png b/files/opencs/scene-view-status-8.png deleted file mode 100644 index 65ea108ac54205654d7fff77793bd02a80e49274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DWND0s)y z#W5s<_3bQ2zGed+7U?7Z>+guMU!A)6KqlYWu-V)kC#TtN-hSa;q1>T#;dy^$YR|Jq z&8Z2ma4VQ+`21V!0{*o^%lY3J+x{0`C^b9u@sy1#H?NYM@ocW$mA4}I_8wTTd$WPp zfvHb`rQ>uigK`UR4g=GXr)CX;huF**7#|f$AK*x2mTq7u+{v5JvZ0aJp<%}zHUp;{ z2iO!GV)B?J6mt@o1r+qQGxi9WZD8aOn9l$G$W7fm=J=0#g&%9h6+0hVe>iwx)%U|Q tdse4w?-&2FKP=_Mb0bryqQl=+`Cbc3rY~%JH6Q3t22WQ%mvv4FO#nbqZubBH diff --git a/files/opencs/scene-view-status-8.svg b/files/opencs/scene-view-status-8.svg new file mode 100644 index 0000000000..5f6107f774 --- /dev/null +++ b/files/opencs/scene-view-status-8.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-status-9.png b/files/opencs/scene-view-status-9.png deleted file mode 100644 index 72d0d9fb774b64180d1c73eba960683569ad160e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1990 zcmV;%2RZnOP)e5m|JWV*BQtEGdnvwyW?H2@3(rPQDZDSCZyO2K?Y+m zw0PGI5b+QtMR^FQs!;P#DQX+3Qmd$sec&aciQ1}Bo2qS;#5R}2DF(-F6B3fjV2Hsf zzJc+5z3aX2&h$HjXBn1tuw5In6(gN27IK*0UZ(t`}# z?+o0wk=;v}ExX+!%~!~C+#_ZVu6ZjAi9FZa-qtp}SQbv-eOc`{wii3VV(;6!+r7cW zaR+1*=PnRU6}c7xStbrLY6;;qarm5}X2uL0=fi$wf(d8C=EraL887 z1;e;{eH>p5T*Jud1oFv81!f*>YEj^EJs87SR6&B{kswH7_(6MX>ruu+_uO*JN(rdh z)y(A!{E-UTe0Wo#j4(y<)9DCmYu97lnomwwJQ$@X5t~oc;F~sLQjW zF-JtdFM*Ehel7YnGP8?G17@(=E0vlN&R+~ZrT||0L$0(Z`Z4~utyZFkJWS5y> z1Ot|AG(E8%HpzmqX)peGq8poYEhx2HaDFO;Yk?@Lvv}BOb{6HYVAa{Qcjh7nJ`z^3 zdH=K6yJrtXQCz--9wo2m34G^winAJA6!m|O1+d}q4S2Y`7_oQ)?f>`;ripQEEOwxG zCWNd02&yRB@;o?;B)je=!U%pjq`Wzuz~PUMw@$I&E_)F-xjpsd)zj`WyGbGc4hS+D zH$A3BeROgLzdv>c``0)Tr|@>(n1jm#lu9?Zs0c-IG@@dX79!J7NL8oY%F!BONVl$Z z;2)o8n`U>UbxYb#R?AYZoo>%hACkpiHI~Teo1BBaVjVVAtYw3un|$uOdKHhCI?+q( zV89q>|Sqyf@-Qfk{EBl}|?YoG+maM^V*v zysb|MVedcNv*RZ|Mfe48kwh0|VmPEiw~8Kd zwr+b8MR`t)O?mOBlik=?ZpR$0vi56psL$qMr5dig;(}jMFGtjp?&ED^sWAFycS{Q^ zheMNb99{@qzc(#w+Rk|a6!|W9N!FH9n;EUcK0No-4#-vsJy!zK7X=(L3kZ(vG3_v7u*MQ_(I8qlVc$q*xLlF#iGGqAowO% z4nCO(AR3LKF59G8Mvwd)?V7zo^~Wm-zmUjV^^~HnD{S(#e8?i7Bl74;NN{hhg;@}A z=JSh)4-KNaz>dyQKXN$QNvX;hD+!DKXFg^24{x_R7n*dr{W>3^CRy)zB761dQ8W{L zkyXI^6A^eC>L3UvbTRnhAyg6kJ43T55fl`rz%#Ir!eJny9$GHsQh#@wfQ}D7z~sM9 zp-eX81TD(%yBoAa*oU8ALX5%ZXW?Cfue1V=`HjgqA&dTh0tqiwoWB_RSF@cIK%U?9 z&g-wDGDkueomZaTy+vEF>^#HZs~P;D0X~I_?Hp_kOvKf{rhK)kACrricGxppie&VR z`%&}l8ss|c_;Tb1F85rdYLkmj61C1YA9({(as#3|-XB)}d~8nrq2cRQZ)yVG@902% zflUn3dEDp7#m{1-?dgT|1AjG|*DVTatjK4t_80PbVO`k=+Y`)tKXffYpfVQpU{q z3?$D&M%A=f=zj>>1D3J-YuR2X19Y~`jO(@xu=<}F*taN?J27>!<9x;mFj^?%;8`C2 Y3skl6XO~B$%K!iX07*qoM6N<$f>T$({r~^~ diff --git a/files/opencs/scene-view-status-9.svg b/files/opencs/scene-view-status-9.svg new file mode 100644 index 0000000000..5d101ad1f4 --- /dev/null +++ b/files/opencs/scene-view-status-9.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-terrain.png b/files/opencs/scene-view-terrain.png deleted file mode 100644 index b0051eb1273c586e5ccfc4b3d371e7b8cb86127c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2580 zcmV+v3hVWWP)e5S9@$z=M_KSz1NNtJI>pA$2br2hCl*sD72+4Wp#EJ8MJ8_(c zWBcBn^U>=Drj$}rX_|bc_*ysL{mwbR^ZWhIXMpe(Mj(tp7=bVXVFbbmgc10kML@vJ zv|nX*?5oNg}`=47^3Q351AQ%kgNI^tNg2B;o zxN5b-yw7*+?RWqBEqwgg9eL~mh$_3ES+}1M7X${g^M1J0&;n};EOKI83_fC*_(Y(& zqesfkOo5!tR9+l)#FUBJf8UwiA7ts80zvojzVlsQ#Y$R$aH1%D7uUugtU z5TH0G11#w&JaM9xdWoV4<5Sac^j~#vo;vl>>-hYUsrASOsEB7IC%_%M3$z*$3N0Ca zNs=^*ECVHV4{?{2mz4%-$%$~S$p$64Sr8u+4Kl6~uqZ5AX|#1PpFaTQMY+&7GzRsp zj(1Tb-+q)rzHk9A@7;5FYh@XyiYiV@1QU`QZB9X_mB17q>u>4o(PSf?RI1QgD#|l6 z2M$+1tVlCKcmFWV`4*s}I1eJU8eS9$osx0%41(3(b?i?^j(_Ki6e8lH&%LVARlfVm zo)0n43Pf~1DpDsAiu}UlBvE78-H52F?nOM7L`<6H2l2S~qHd`(JYe}&$*#VU*Bu=_$p=Wj; z&fmNPm8{xojVT~ zTQc@<-?$b~nGjUbrXp}tjYfhtOz=jt9rChL;OX)b@Gbc76R`#@(>pr{?|*UyCcU%4 znmtvbK_3Z$z-RG!S2P-E>2N{!z$ip$1lYWO6^2tnoufR7ru28>>@^bn;lI59kMHB- zP)9-qsEFrer0}6*>*|99qn>k_5c|{){m%YjjXBi>nJI~UUERHo_>|fh9wj@XWBDp;5@dj-dUjfXJ?a5#|~k zWfi!WK^Fn;>6!cNm%a4$7vI{ssiMZ5mc(CDc}w=^nVCgV4IzDGWzH91D_5j}2{&In zq-fm?(&p^-CKRy|kzqnvL3T)-gd(jW(Kfa_!HAvc=oyreDngz)o&K#R%QY}QISsDC z5zuKQWo*jJ))wY~0gDeV9*hX+G}8Ixx$Ex;X{Ll4kJn4>CBE_v>65etw_9EIQ zri;+Rl*b!#3|dI74WJ#ic61|ZMu;^U5J@jg&&>MOy=WbMpP8FSo=?hJoDsNIpn@=| z&tl>l6ts-FEX>aNASEe*#YXFCY6n$N)tE>#=y3J>5V%*_AAk8{C04KV_YO~Jh^HmF zW_f(lBU|k*sjR>P$tWa}M68}{@q(DS968nYvX4p_xfC++7 zce5F2;E_0a68Mk`xY^?19l@ANFVd%Xc$}?4#HmXZlU#|!-ZMDL?Kj2{C1XrsXv~e& z%TS#CBaHp#C$A~yJdbA&iGy!L7nL#u;|qHH`eI7Yc26k*L=j(a~Mun@^c1VbgmZSAi z3`>=9n8|k>E~y|p6E>|Wf)woZmD@Ik?ZG*M>7xBqyevfx{OJb~%oJ34ZiU+he zOhFEM5drE5Ax+8Ao$Ro#zF96W%vNx43Ful(M*ha*`*eLOWFOJ1gJTm=gox`Sbx_yP2CMV3puWwi zbPc;hh(DO;k_D&>x9xc0XBg{^T~C!smLnX9xS#PRehBc+57E;lLPeEtb;)$~4T?@WE0;+Yb=%Nsd2cLf0rTr}Du@V(%YyYsuECpIr~}MguIiOnR5jN0i`^56(kDW|ER` zPUDDEab%-77Zk_9_>xpn<3D(Rr`f3qzb?mNr;kK82?Xaob3WY^o>ii8 z5EbWS@pBKYCvoDB7qn}4z-Z7*=9GjW79`To$_87P(mmpSC{@(B58l6Y0qRCoTT$%E zafe87m?xqiMP2dXWREc7Zv#5i4UFCsC)r{Dh#PgGfhK#8Vjmbgc=_BJZiniAk9vRX z0@Q%tczN${QOmDamgMpd5YGq4+zL)oM#m8nC)zVyvfAabshI<3KKb|Oic{V9VfSS# zKn=8S?@PbKf%d&8igR?xYkoAKpN&M7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene-view-water.png b/files/opencs/scene-view-water.png deleted file mode 100644 index 246c5aae929d28b3f7e8b86c0ab7b3a89da14bfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmVe5mc2_HK^Vs0*x5dg|4;!y$M9CDxE-i1fo zI}mAtNQQrjohWGD0nH#t=R5KOVYLuc=J!ku5J{?mm^}sU+EFz)Ofb1$QSlfcTeXIa z3mpSQdH`}4<#!N1?4OOWL75h5*V)D25r8;R|Ezv91Be6xNTi>f>M%>{r30fO(=rYQ`o12j$oWV>mngq3*$ zEMOOAFYH20SO~(PMdVe$9L1Uw6>|gN)i2wHI&}!G;MT&q(VBN;ANd0^t~E$B%mJ_b z>w$f^JNaYj;rUgE4i<8r=~b&;@E6BBM7!a8glH6XqZl{E2j8of$vr6%IaM#~G{Sj4PF)2EmJFVQtJOPp>GK{! z#^Ufw>Uew(F8? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/scene.png b/files/opencs/scene.png deleted file mode 100644 index a9fc03f7699a715592edd31db78ad47ac514f006..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_p9 zb;Z-gF~q_@IYEL|Lh-@t*V$Z0!W(|@3;h57`SWl7MU6jL1fn1C7%foY7O>~x;9$^< zV?46nan?dM8J17ifB*j7{6vn)P~L3ze@4}JjVcW#`~vyxj{+3ZSROGu*l=r^OTSW5 z+@a{usPC|cS&bod0`rpcLq{C+94D=3J@wbg?14$Z0;WjA3G&=u&!s9@b3Lg^NoPKq zx442?}xUyxj@&tLlBR3uPh;*bY?0g_T;e2NvgD_{~i9UU^lm<3m=10dDY-l)k mC|qH;aK}@(V7oL928Qm_H3#l%PWuYpUXO@geCwN2ZUMx diff --git a/files/opencs/scene.svg b/files/opencs/scene.svg new file mode 100644 index 0000000000..a516d6b596 --- /dev/null +++ b/files/opencs/scene.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/script.png b/files/opencs/script.png deleted file mode 100644 index 29d622e19f742602321a65b981b63b35a845d401..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;ir{ zi(`m|;M&QFe9a0xtw&dGZ{E$cJ(#^Zb@G;FhmxN7OJAz1%{|Ctac-y2H3{cs)kS&_ zncu8tk#ERT1(t)Rzy*9WmOoDA;y$eY3YfYl_PA)s{owN+d}Ufd6E zODZw+YwuWfDs%xd`aABT4!&+SdkJ+6JHv3vv zuiCSAGn15p?Xv3V1u2W}-(vc^?i%}}O@^y~eYJ1@R5GndeerRi>lr*<{an^LB{Ts5 D&n9F^ diff --git a/files/opencs/script.svg b/files/opencs/script.svg new file mode 100644 index 0000000000..76f3b7b28c --- /dev/null +++ b/files/opencs/script.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/selection-mode-cube-corner.png b/files/opencs/selection-mode-cube-corner.png deleted file mode 100644 index b69ef1782fef094243f5e5f68b96218b2699bcd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1422 zcmV;91#$X`P)Z~{#<2u7WO5QIbr28@YH;v<5TiAK0TNO{Ep#7Be#Qfs8hpsg*BVoT|Zw)dRv zptniE0)3nd7`w)2@3Yp~d;fc_|G*#yF^EC*6(W)&B8&Z)%iIC7*}yX3S>Q1s6DSV^ z0^?lQeN|OIxn~4K$u0%P0`rV9+1A=}padvZ)nB5|8NdaafT^l_=8g*xkx{@%UDvZsy6k9N3fS<dDnc;A_+^=n?s(VCarihfP>LYy}@ATrC;Xo^} zMpZvl)pEZNx~i@QE{MqHSO{=|kE35dW>D2xK#_>N=C^=2Rows_5s~j>Ty^t+4@4x_ zPXS$DXcbT(B5Px~3Jt*H#+V8b8RDye=nF;wTSY`-D5A_-+f|wT6%a+XF(%xXW$sU9 z0*;BueqZi^8z!$2kww6tKzu(rTEOd8s;2<6ftMY}ndo_59q=`vR7m>pvvRPHv^})!U19o|ycTH83 z2fE#Y1Kg{#M5IH#L!pqh)~*MNfrG%i z;c&Rh@2wjX0RYxofcsU|yVK#w@o}z%yOHi3{^Ph?0y^%gGtk=v=d{;kVOdIB^&H|e z5s^4m?YLJ2xZM++X}^?@lduBs+5&=UW8Ks|8b+<6IW3pQAz381TqgJEic`RZdqF^( zi8Q=bIH#b{2GggxDS0&IuB0t7oh#`N(Ude4*935^hhsYnRa0UrsZ-XCFEm^B>^*p5 z(H#>Y3+HAVw|R+)G)%Wn(({oKGg3|6NouEV+EPC(?>e%^S_~FrEkPT(Zk~YWa%Rjt zCbrZThD_qxaLMs)u@cY`n)_ri1fKGe^Kv`V^J&PQ&XtUZX-Z6^H7=3q-z}zQLq8!zkme{7RU22*v`1-M!>qa z?#~zp<2YE)1M5{|?QX35qs2Y>S5ZpkGjLy1DAX(>52$LTuL5*mi4@MhSdo=ADYrIb zG{)ZMvW=1jux_LZD8qV(tn2NsDoW`wR~JKzSUU|kDWr-m$KC6ezDMO6iNI`c*{U1ImEWzFuUi`x-E&VBF!A#JTOa`1pZL zAW&75(kJrWL~H<#ipT-~L;b!3zvHzn8h>mPp6Pj*^;}FK_|d5CjZX}~-L3>Ch{&5j zyRTLvy#MgtK;4OL`K84~oSt`|bt7P$pGR$POdf!UTwr}~`1Sc72$vjxqtI*0doW|{ z!it=!H}ls-8)4b~h?~oR8PRTF_3g&=yE|Pt`_YQZ=XT`QWR7Lpo<)={*p2H1uB%2^ z??hEm%G6tsU3!xQSKK|p#l%W-+cP3%tdTu)e6AFfZ-oEbX&*Hy`WJ*pna&~pM zyIS$RNpSwJK&P#kH=elEGTQ4o75Wy}2@vOYFr>AfVHZx5RCk7i%O|lNjrEv7F>n?* z;Aew)z<+2&Bov^1@3pKMBwYFl+jhRnShvguGY;86(*9Uk diff --git a/files/opencs/selection-mode-cube-corner.svg b/files/opencs/selection-mode-cube-corner.svg new file mode 100644 index 0000000000..63d5f73c56 --- /dev/null +++ b/files/opencs/selection-mode-cube-corner.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/selection-mode-cube-sphere.png b/files/opencs/selection-mode-cube-sphere.png deleted file mode 100644 index cb5432eea6f3e668540da5ef909db8937546f3ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1428 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 diff --git a/files/opencs/selection-mode-cube.svg b/files/opencs/selection-mode-cube.svg new file mode 100644 index 0000000000..e03138bafe --- /dev/null +++ b/files/opencs/selection-mode-cube.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/selection-mode-sphere.svg b/files/opencs/selection-mode-sphere.svg new file mode 100644 index 0000000000..9f8ed79340 --- /dev/null +++ b/files/opencs/selection-mode-sphere.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/skill.png b/files/opencs/skill.png deleted file mode 100644 index 0ef7cb1cb7eb771b6ffc154a04239e908d7902d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmV-E0m1%>P){+JVsf%67$h%QQlms+#U}%j z#7H7U3cxh#Ad=t%R_J4es#gSu1{@atS6qNBL>0i-0pr{Ey*(b1U#Q5DH5HG&MVx^} z3P#YJuE3M#$E2A_igwhONPx|Ypbe9Z?~7=8`cu7t6hN-EzRu@)JY!V-0AP@yMw+z3 Q1poj507*qoM6N<$g3nBYc>n+a diff --git a/files/opencs/skill.svg b/files/opencs/skill.svg new file mode 100644 index 0000000000..21ae4d12c8 --- /dev/null +++ b/files/opencs/skill.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/sound-generator.png b/files/opencs/sound-generator.png deleted file mode 100644 index 79833df9c36be3f7693f32e60ae3bf39bbd9ff21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmV;e0aE^nP)H1=6R;S0V^yyQTqL8bXP7v>qmG4(T=OJSw8W(~k3Bxd5 z38d+2E^Vw;>L+4}xFXJLXHY#X$kxF870sdu>JMtCX3*;R1Mn{cwz$q=zR8z*p87L2 z&_OD+1&E^=KaSz{Gk%YJ?c(CFpW-Gk7!xkoFcYQ;tVb~d*E`USUC_IhlFbj|2~m3o zRSn#YLRjY+@Ru#P-Kt4$0JcHBf<{|tzry5 Xbk3C9O!f{e00000NkvXXu0mjfLg2Qp diff --git a/files/opencs/sound-generator.svg b/files/opencs/sound-generator.svg new file mode 100644 index 0000000000..4e27f19f41 --- /dev/null +++ b/files/opencs/sound-generator.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/sound.png b/files/opencs/sound.png deleted file mode 100644 index 86871611f5deae184cf6b986797020563c5c3ce7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP;i2$ zi(`m|;M7Thd<_ab&YYdcn@< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/spell.png b/files/opencs/spell.png deleted file mode 100644 index 5890ea751b40483621bb334e57cd1bfabb8c155b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmV-F0l@x=P)3$eLy(<*LW8GyUB_QiON@i7d;v&Ld(k^d!u2Gx@6y_deauH(Q;0>#iS z21qdF)xD~^oT%n66@X|Um%DN8`(B<3E!@aL?DWCL&uR;-l=q_S27NdeaHRKnBH6}; zbHf33(<&k^73jdwDDmq$D+X;b{lBa-o@t~WeJ*002ovPDHLkV1f|fiGTnA diff --git a/files/opencs/spell.svg b/files/opencs/spell.svg new file mode 100644 index 0000000000..e726d85a7e --- /dev/null +++ b/files/opencs/spell.svg @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/start-script.png b/files/opencs/start-script.png deleted file mode 100644 index 73ed157b9ed2c2366388723f8e5b25fff4bc3b97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmV-t0hs=YP)Q%iD#FbuV^VUy_zGW14pjAq*dWSMD~X{RfgUV_h! zasz4tfSa9O0ryxh=a?XB zf=o_JY^ti7sR{sWwoTKF2s#(|144HJfK!Jo%YqE1X-W|M{1Zd~{5ylcrur;`3~-I8 zuIr0ees$m;`MIkGG46U-GxZ99s|LS>;vs3-Lt1pt{7g}-u;fDPya%O?-LK1jXrETj zY5{PM3os7K82hm0O4G9UrzV_I}Un^?hcdO-#kvH8dF z#R=Wh@(Uh6k0j)d-_HyP1Xtj^h`ff5tb+0Uij%io@C{l + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/static.png b/files/opencs/static.png deleted file mode 100644 index 9f458e5d04a64ca5f077f3718b92f0fabbbbc857..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_W6< z#WBP}@a-f+u?7Vm=jeCr-|cx{$S>NnV)Blgt<$GWVL5T_R>w*s<6{<@22bxanl89j zwW_Q!xy_<|+l7kYlOk`X1TFe5x9Lrw1&d$x5>D3%+}k6 z&#_5$VsgdvYi>W{A66Z%dwhQ%)8(Hsf8Ot&`Y$-2`QiK?t)5lqGJ&pP@O1TaS?83{ F1OVZBQ%e8< diff --git a/files/opencs/static.svg b/files/opencs/static.svg new file mode 100644 index 0000000000..8e8ce541ce --- /dev/null +++ b/files/opencs/static.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/stop-openmw.png b/files/opencs/stop-openmw.png deleted file mode 100644 index d8f80967244e7a3fcb143d5617a0287666c7ca81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=d3- zBeIx*fm;ZK886+f`vVk|Dshb{3C>R|DNig)We7;j%q!9Ja}7}_GuAWJGc|_p9 zW$)?Y7-Hd{{OA9FduAR3Bcnq%TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/opencs/transform-move.png b/files/opencs/transform-move.png deleted file mode 100644 index 1e5bd573d3bc6f57af8f81aea55e2d0ac8d18c78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmV-#1CacQP)e5n9XVwK@i8MXIBgo4N5K|*(VT0f+7g!0R;5{Ja{mA z@dNY{@BzH*NhA0SUc4$ILayQq=!yqXK_dnsyX~*$qqmZs&Q6@}6?F!Nt*NR0*S|id zyOJbnuQmg12HFh#vl&=;us$bu%mCAv;9x)Dei_q8v;fHbMbqgnnY4Qp`C6Y~~AnLIB#dksQ2* z92;Xs*h&mZUVM$5IM08V&<60Q>-GOtfL&yUdt%`74V$!+-*OVyxWL_8!|eA>aB!#h zXhWS)ek^S3u~rbh)eXzK8%i}%tnCEg=VWxr+M(OiC!+7t03VhUJF&yf*DPIR%iWv= zF);u@FVP2&-N~8{X3Pc^eIfh(aL~c=P{?4D`}gTJJ2|z*js(d%X+ci(n_%73X4_?N z01%Kqf5u3BhU0(xy6R_ozQ4RL!(4dy-MUf2r>{nF+M*h7P@E)?4fjF`JAI6Yu$$F0 znOZj;F;DMToE`8v?D}31@h9FbQi&Dnc{dNFC^IjrI!H=iUfCp3KKk^fF~2q&{J_sz ziG?VrytL4LWi}?3F2-JH1wqX7{FIWO0JYXf%o>Ap7;U|Lda>f&03RtIvHTf&f%Tua zu5S2*gO%Ruk1}E#Kq_C#d=u#kx(l%t_Be>% zauAIMGa)V~u^hD~HB4wn*eXASiYI6bLF^smFEao_SY}0LZkAz{}D~GShS2LiaHk>uCYe zO0T%1{8ze+AxlsB5aIVcm_c{C2pn6;HUn)2+6*+vz%SBJ5jawBdHVnW002ovPDHLk FV1fq_mMQ=M diff --git a/files/opencs/transform-move.svg b/files/opencs/transform-move.svg new file mode 100644 index 0000000000..1b9490f001 --- /dev/null +++ b/files/opencs/transform-move.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + diff --git a/files/opencs/transform-rotate.png b/files/opencs/transform-rotate.png deleted file mode 100644 index b6c6bc58a78f2da3deedea488870a5c481cdb758..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1391 zcmV-#1(5oQP)e5m`jKpMHt7cW+p4XgBVakA|Zr5D2dT1DyY$eN)AR8 z6x3)`FbYO67d0y4E9(Pq@sI@rV!(qaXb=Q1iifzMlA!olA31MuX^<;)s{8_Z3Nl~v=R6}M?eqb{IXqttU*vo6t#F?^T&pvT7|IV~{7$8<_+l_lhfagmK&zp3O6zsh zUqgk0@jG;P(H!*zG*%cKqBE2Oq6a6oDic>nQIiZ~CTpU6hl%FMSLYGk=^n$07l*Jr z7wP4#1`U*o<6mJ!4<`mBF-(!6r^*A!EhhR)tpg&bt@_#Wye9p|8Ni4OQE;3kGG1l8 zD9898i2k7pLvA*4l(5MX37lfyL^coX6S8(_-N*qHoC5Ht5Fs{|Iwbm(?UjQ{U8*~& z%0&M9Y#!LRBl}OPBV&8(Mh<}XU2@ozaAh+m8ydgtl6t!|!*+@GU1Vn^o&C_m^na59 zjJ}Oi?R67d*>8mxTIA>pDkymwBe&Hon_B?6M0L6ksW{q&VfO`rG6~$ri2Sqp(vl3u z(bHf&8G;ey07_)@&Dza3hzy5p~j0qXa?lyaGVt} zvkyg=3CO60Ond~!o8awiisiir0Kbv6cH9g|#8^)EH&s?QAH%OKkD*tN>m!WKl*in@ z*8wJPa*Y>ZjQ<|s11`|0Z48!Y#e>kjY=l*IFGO>@>EH8T*dY#_QvgVw39l7+3)9(5 zW?$l%B|he7If*NaMSM7nxnEl}~1$!kY2PWUINOcJ+Mda;n;12U4NEe1SRghD`U) zCvqDc=1@&AMTLcgZ-&ZfQ<+Q4ZuF7s=Qm&mM#f=i&^7hrOSX x`4dZw{sg1nqHaqYfi?nd1lkC+5g0iF{{kJs-=Z!HNr(Ud002ovPDHLkV1lUTiDdu) diff --git a/files/opencs/transform-rotate.svg b/files/opencs/transform-rotate.svg new file mode 100644 index 0000000000..29bc3fdad5 --- /dev/null +++ b/files/opencs/transform-rotate.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + diff --git a/files/opencs/transform-scale.png b/files/opencs/transform-scale.png deleted file mode 100644 index c641259bd731fe3203d2404fa98a4203793e2d00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 436 zcmV;l0ZaagP)e5SX&Z;Fbr(bUyk7Q^h{n)kKi}d1f>&ZfG)3sI&E4M{@O1hSw2yaHDd6n$M4k88P^9I{+1@$z9x{Ur(%KoHO( z=VqWg7?rIF3P6!&1K)`R`+yXPrx18DV6NA(f)r?u(66k>$*>MIY!*m?b`xj63xF7) z0J3gk0JJrMmJm0wrEKLoqyRVZ%BbSw>-_}m%j06+kCGaNe0LO e86X4yz`z^kUV6rk&j!T+0000 + + + + + + + + + + + + + + + + diff --git a/files/opencs/weapon.png b/files/opencs/weapon.png deleted file mode 100644 index e2c1d3dc164fe4da0dc6bb9ea6ae6bb6cc6d2411..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmV;50d@X~P)adGKj;`d+DAT@201E=Rt?)kr*leX6P{U2k@J$V@f z!JJwsJh}(ukQ@VR7jn}qz!iDJ(~qcgAQQ5L&J|W&82Xe~ARY8E`hl$GS;+xt7UYA{ zz%)gd(POff1z*K5~FCU6u!Fw7_|An$o5`3DfF2qalS#zpY- zUGxyp%5^w9Q-A6N3($&5>YP7$p4SY+aAPe%pe0DfTKlQ{Q55MLd(H&>ft;cr0UTn! z#@y3c>O0WEQtV-z#AY3JnQTWQFF^knjeP+`QZWOvnF*ljoEO%LcfO+@VE%RpW2Ol% ozL8phl-XIoP8VEnA>PQ_Uo!rSNh?8@vH$=807*qoM6N<$g2$kv7XSbN diff --git a/files/opencs/weapon.svg b/files/opencs/weapon.svg new file mode 100644 index 0000000000..6168812305 --- /dev/null +++ b/files/opencs/weapon.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 58afe1ba23fe7c0fafd4e163fedf161ffd6bf9a1 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Mar 2024 19:46:31 +0300 Subject: [PATCH 15/26] Support red-green normal maps --- apps/opencs/model/world/data.cpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 1 + components/resource/imagemanager.cpp | 3 +-- components/shader/shadervisitor.cpp | 20 ++++++++++++++++++++ components/shader/shadervisitor.hpp | 1 + files/shaders/compatibility/bs/default.frag | 3 +++ files/shaders/compatibility/groundcover.frag | 6 +++++- files/shaders/compatibility/objects.frag | 6 +++++- files/shaders/compatibility/terrain.frag | 6 +++++- 9 files changed, 42 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 470ce04131..4198e1b980 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -152,6 +152,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data mResourceSystem = std::make_unique(mVFS.get(), expiryDelay, &mEncoder.getStatelessEncoder()); + // FIXME: this is severely out of date (see #7595) Shader::ShaderManager::DefineMap defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines(); Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index dc71e455b2..d5c5321f8e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -446,6 +446,7 @@ namespace MWRender globalDefines["useOVR_multiview"] = "0"; globalDefines["numViews"] = "1"; globalDefines["disableNormals"] = "1"; + globalDefines["reconstructNormalZ"] = "0"; for (auto itr = lightDefines.begin(); itr != lightDefines.end(); itr++) globalDefines[itr->first] = itr->second; diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index a7d2ef61a1..e7cc9f03e5 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -78,8 +78,7 @@ namespace Resource } break; } - // not bothering with checks for other compression formats right now, we are unlikely to ever use those - // anyway + // not bothering with checks for other compression formats right now default: return true; } diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 7bce9de2a6..3867f1f43e 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -184,6 +184,7 @@ namespace Shader , mAdditiveBlending(false) , mDiffuseHeight(false) , mNormalHeight(false) + , mReconstructNormalZ(false) , mTexStageRequiringTangents(-1) , mSoftParticles(false) , mNode(nullptr) @@ -429,6 +430,7 @@ namespace Shader normalMapTex->setFilter(osg::Texture::MAG_FILTER, diffuseMap->getFilter(osg::Texture::MAG_FILTER)); normalMapTex->setMaxAnisotropy(diffuseMap->getMaxAnisotropy()); normalMapTex->setName("normalMap"); + normalMap = normalMapTex; int unit = texAttributes.size(); if (!writableStateSet) @@ -440,6 +442,23 @@ namespace Shader mRequirements.back().mNormalHeight = normalHeight; } } + + if (normalMap != nullptr && normalMap->getImage(0)) + { + // Special handling for red-green normal maps (e.g. BC5 or R8G8). + switch (normalMap->getImage(0)->getPixelFormat()) + { + case GL_RG: + case GL_RG_INTEGER: + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: + { + mRequirements.back().mReconstructNormalZ = true; + mRequirements.back().mNormalHeight = false; + } + } + } + if (mAutoUseSpecularMaps && diffuseMap != nullptr && specularMap == nullptr && diffuseMap->getImage(0)) { std::string specularMapFileName = diffuseMap->getImage(0)->getFileName(); @@ -629,6 +648,7 @@ namespace Shader defineMap["diffuseParallax"] = reqs.mDiffuseHeight ? "1" : "0"; defineMap["parallax"] = reqs.mNormalHeight ? "1" : "0"; + defineMap["reconstructNormalZ"] = reqs.mReconstructNormalZ ? "1" : "0"; writableStateSet->addUniform(new osg::Uniform("colorMode", reqs.mColorMode)); addedState->addUniform("colorMode"); diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index a8e79ec995..9ce0819bd3 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -110,6 +110,7 @@ namespace Shader bool mDiffuseHeight; // true if diffuse map has height info in alpha channel bool mNormalHeight; // true if normal map has height info in alpha channel + bool mReconstructNormalZ; // used for red-green normal maps (e.g. BC5) // -1 == no tangents required int mTexStageRequiringTangents; diff --git a/files/shaders/compatibility/bs/default.frag b/files/shaders/compatibility/bs/default.frag index 77131c6a52..d2c8de0b22 100644 --- a/files/shaders/compatibility/bs/default.frag +++ b/files/shaders/compatibility/bs/default.frag @@ -77,6 +77,9 @@ void main() vec3 specularColor = getSpecularColor().xyz; #if @normalMap vec4 normalTex = texture2D(normalMap, normalMapUV); +#if @reconstructNormalZ + normalTex.z = sqrt(1.0 - dot(normalTex.xy, normalTex.xy)); +#endif vec3 viewNormal = normalToView(normalTex.xyz * 2.0 - 1.0); specularColor *= normalTex.a; #else diff --git a/files/shaders/compatibility/groundcover.frag b/files/shaders/compatibility/groundcover.frag index dfdd6518c3..aab37d465d 100644 --- a/files/shaders/compatibility/groundcover.frag +++ b/files/shaders/compatibility/groundcover.frag @@ -59,7 +59,11 @@ void main() gl_FragData[0].a = alphaTest(gl_FragData[0].a, alphaRef); #if @normalMap - vec3 viewNormal = normalToView(texture2D(normalMap, normalMapUV).xyz * 2.0 - 1.0); + vec4 normalTex = texture2D(normalMap, normalMapUV); +#if @reconstructNormalZ + normalTex.z = sqrt(1.0 - dot(normalTex.xy, normalTex.xy)); +#endif + vec3 viewNormal = normalToView(normalTex.xyz * 2.0 - 1.0); #else vec3 viewNormal = normalToView(normalize(passNormal)); #endif diff --git a/files/shaders/compatibility/objects.frag b/files/shaders/compatibility/objects.frag index 56c7abf27c..eb5b79a0c2 100644 --- a/files/shaders/compatibility/objects.frag +++ b/files/shaders/compatibility/objects.frag @@ -167,7 +167,11 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes; gl_FragData[0].a = alphaTest(gl_FragData[0].a, alphaRef); #if @normalMap - vec3 viewNormal = normalToView(texture2D(normalMap, normalMapUV + offset).xyz * 2.0 - 1.0); + vec4 normalTex = texture2D(normalMap, normalMapUV + offset); +#if @reconstructNormalZ + normalTex.z = sqrt(1.0 - dot(normalTex.xy, normalTex.xy)); +#endif + vec3 viewNormal = normalToView(normalTex.xyz * 2.0 - 1.0); #else vec3 viewNormal = normalize(gl_NormalMatrix * passNormal); #endif diff --git a/files/shaders/compatibility/terrain.frag b/files/shaders/compatibility/terrain.frag index abc7425eb0..f45f1f024e 100644 --- a/files/shaders/compatibility/terrain.frag +++ b/files/shaders/compatibility/terrain.frag @@ -63,7 +63,11 @@ void main() #endif #if @normalMap - vec3 viewNormal = normalToView(texture2D(normalMap, adjustedUV).xyz * 2.0 - 1.0); + vec4 normalTex = texture2D(normalMap, adjustedUV); +#if @reconstructNormalZ + normalTex.z = sqrt(1.0 - dot(normalTex.xy, normalTex.xy)); +#endif + vec3 viewNormal = normalToView(normalTex.xyz * 2.0 - 1.0); #else vec3 viewNormal = normalize(gl_NormalMatrix * passNormal); #endif From cf6b95ae7cf739c00fe00919bc1959b99deca515 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 23 Mar 2024 23:10:29 +0300 Subject: [PATCH 16/26] Document some technical details regarding normal-mapping --- .../modding/texture-modding/texture-basics.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/source/reference/modding/texture-modding/texture-basics.rst b/docs/source/reference/modding/texture-modding/texture-basics.rst index 78ae007704..8bbf018fba 100644 --- a/docs/source/reference/modding/texture-modding/texture-basics.rst +++ b/docs/source/reference/modding/texture-modding/texture-basics.rst @@ -25,6 +25,19 @@ Content creators need to know that OpenMW uses the DX format for normal maps, an See the section `Automatic use`_ further down below for detailed information. +The RGB channels of the normal map are used to store XYZ components of tangent space normals and the alpha channel of the normal map may be used to store a height map used for parallax. + +This is different from the setup used in Bethesda games that use the traditional pipeline, which may store specular information in the alpha channel. + +Special pixel formats that only store two color channels exist and are used by Bethesda games that employ a PBR-based pipeline. Compressed red-green formats are optimized for use with normal maps and suffer from far less quality degradation than S3TC-compressed normal maps of equivalent size. + +OpenMW supports the use of such pixel formats. When a red-green normal map is provided, the Z component of the normal will be reconstructed based on XY components it stores. +Naturally, since these formats cannot provide an alpha channel, they do not support parallax. + +Keep in mind, however, that while the necessary hardware support is widespread for compressed red-green formats, it is less ubiquitous than the support for S3TC family of compressed formats. +Should you run into the consequences of this, you might want to convert such textures into an uncompressed red-green format such as R8G8. +Be careful not to try and convert such textures into a full-color format as the previously non-existent blue channel would then be used. + Specular Mapping ################ From 3c0c1717a98951f6e0809911aaef12be3d29d37b Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 28 Mar 2024 07:43:33 +0300 Subject: [PATCH 17/26] Fix red-green normal map handling for terrain --- apps/opencs/model/world/data.cpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 1 - components/sceneutil/util.cpp | 14 ++++++++++++++ components/sceneutil/util.hpp | 2 ++ components/shader/shadervisitor.cpp | 15 +++++---------- components/terrain/material.cpp | 15 ++++++++++++++- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4198e1b980..470ce04131 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -152,7 +152,6 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data mResourceSystem = std::make_unique(mVFS.get(), expiryDelay, &mEncoder.getStatelessEncoder()); - // FIXME: this is severely out of date (see #7595) Shader::ShaderManager::DefineMap defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines(); Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d5c5321f8e..dc71e455b2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -446,7 +446,6 @@ namespace MWRender globalDefines["useOVR_multiview"] = "0"; globalDefines["numViews"] = "1"; globalDefines["disableNormals"] = "1"; - globalDefines["reconstructNormalZ"] = "0"; for (auto itr = lightDefines.begin(); itr != lightDefines.end(); itr++) globalDefines[itr->first] = itr->second; diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index ab600de11d..a5629ee092 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -286,4 +286,18 @@ namespace SceneUtil mOperationQueue->add(operation); } + bool isRedGreenPixelFormat(GLenum format) + { + switch (format) + { + case GL_RG: + case GL_RG_INTEGER: + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: + return true; + } + + return false; + } + } diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 29fee09176..0f4b82bbe0 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -112,6 +112,8 @@ namespace SceneUtil protected: osg::ref_ptr mOperationQueue; }; + + bool isRedGreenPixelFormat(GLenum format); } #endif diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 3867f1f43e..600e35a22a 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -445,17 +446,11 @@ namespace Shader if (normalMap != nullptr && normalMap->getImage(0)) { - // Special handling for red-green normal maps (e.g. BC5 or R8G8). - switch (normalMap->getImage(0)->getPixelFormat()) + // Special handling for red-green normal maps (e.g. BC5 or R8G8) + if (SceneUtil::isRedGreenPixelFormat(normalMap->getImage(0)->getPixelFormat())) { - case GL_RG: - case GL_RG_INTEGER: - case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: - case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: - { - mRequirements.back().mReconstructNormalZ = true; - mRequirements.back().mNormalHeight = false; - } + mRequirements.back().mReconstructNormalZ = true; + mRequirements.back().mNormalHeight = false; } } diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index fafe2dcb58..10dbeb9838 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -271,18 +272,30 @@ namespace Terrain stateset->addUniform(UniformCollection::value().mBlendMap); } + bool parallax = it->mNormalMap && it->mParallax; + bool reconstructNormalZ = false; + if (it->mNormalMap) { stateset->setTextureAttributeAndModes(2, it->mNormalMap); stateset->addUniform(UniformCollection::value().mNormalMap); + + // Special handling for red-green normal maps (e.g. BC5 or R8G8). + const osg::Image* image = it->mNormalMap->getImage(0); + if (image && SceneUtil::isRedGreenPixelFormat(image->getPixelFormat())) + { + reconstructNormalZ = true; + parallax = false; + } } Shader::ShaderManager::DefineMap defineMap; defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0"; defineMap["blendMap"] = (!blendmaps.empty()) ? "1" : "0"; defineMap["specularMap"] = it->mSpecular ? "1" : "0"; - defineMap["parallax"] = (it->mNormalMap && it->mParallax) ? "1" : "0"; + defineMap["parallax"] = parallax ? "1" : "0"; defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0"; + defineMap["reconstructNormalZ"] = reconstructNormalZ ? "1" : "0"; Stereo::shaderStereoDefines(defineMap); stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap)); From b016f414d5251e2ea7979bba6ad737487f94d920 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 15 Apr 2024 17:06:40 +0200 Subject: [PATCH 18/26] Add INFO record unit test --- apps/openmw_test_suite/esm3/testsaveload.cpp | 78 ++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/apps/openmw_test_suite/esm3/testsaveload.cpp b/apps/openmw_test_suite/esm3/testsaveload.cpp index 2629442563..afffbbb3d6 100644 --- a/apps/openmw_test_suite/esm3/testsaveload.cpp +++ b/apps/openmw_test_suite/esm3/testsaveload.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -603,6 +604,83 @@ namespace ESM EXPECT_EQ(result.mIcon, record.mIcon); } + TEST_P(Esm3SaveLoadRecordTest, infoShouldNotChange) + { + DialInfo record = { + .mData = { + .mType = ESM::Dialogue::Topic, + .mDisposition = 1, + .mRank = 2, + .mGender = ESM::DialInfo::NA, + .mPCrank = 3, + }, + .mSelects = { + ESM::DialogueCondition{ + .mVariable = {}, + .mValue = 42, + .mIndex = 0, + .mFunction = ESM::DialogueCondition::Function_Level, + .mComparison = ESM::DialogueCondition::Comp_Eq + }, + ESM::DialogueCondition{ + .mVariable = generateRandomString(32), + .mValue = 0, + .mIndex = 1, + .mFunction = ESM::DialogueCondition::Function_NotLocal, + .mComparison = ESM::DialogueCondition::Comp_Eq + }, + }, + .mId = generateRandomRefId(32), + .mPrev = generateRandomRefId(32), + .mNext = generateRandomRefId(32), + .mActor = generateRandomRefId(32), + .mRace = generateRandomRefId(32), + .mClass = generateRandomRefId(32), + .mFaction = generateRandomRefId(32), + .mPcFaction = generateRandomRefId(32), + .mCell = generateRandomRefId(32), + .mSound = generateRandomString(32), + .mResponse = generateRandomString(32), + .mResultScript = generateRandomString(32), + .mFactionLess = false, + .mQuestStatus = ESM::DialInfo::QS_None, + }; + + DialInfo result; + saveAndLoadRecord(record, GetParam(), result); + + EXPECT_EQ(result.mData.mType, record.mData.mType); + EXPECT_EQ(result.mData.mDisposition, record.mData.mDisposition); + EXPECT_EQ(result.mData.mRank, record.mData.mRank); + EXPECT_EQ(result.mData.mGender, record.mData.mGender); + EXPECT_EQ(result.mData.mPCrank, record.mData.mPCrank); + EXPECT_EQ(result.mId, record.mId); + EXPECT_EQ(result.mPrev, record.mPrev); + EXPECT_EQ(result.mNext, record.mNext); + EXPECT_EQ(result.mActor, record.mActor); + EXPECT_EQ(result.mRace, record.mRace); + EXPECT_EQ(result.mClass, record.mClass); + EXPECT_EQ(result.mFaction, record.mFaction); + EXPECT_EQ(result.mPcFaction, record.mPcFaction); + EXPECT_EQ(result.mCell, record.mCell); + EXPECT_EQ(result.mSound, record.mSound); + EXPECT_EQ(result.mResponse, record.mResponse); + EXPECT_EQ(result.mResultScript, record.mResultScript); + EXPECT_EQ(result.mFactionLess, record.mFactionLess); + EXPECT_EQ(result.mQuestStatus, record.mQuestStatus); + EXPECT_EQ(result.mSelects.size(), record.mSelects.size()); + for (size_t i = 0; i < result.mSelects.size(); ++i) + { + const auto& resultS = result.mSelects[i]; + const auto& recordS = record.mSelects[i]; + EXPECT_EQ(resultS.mVariable, recordS.mVariable); + EXPECT_EQ(resultS.mValue, recordS.mValue); + EXPECT_EQ(resultS.mIndex, recordS.mIndex); + EXPECT_EQ(resultS.mFunction, recordS.mFunction); + EXPECT_EQ(resultS.mComparison, recordS.mComparison); + } + } + INSTANTIATE_TEST_SUITE_P(FormatVersions, Esm3SaveLoadRecordTest, ValuesIn(getFormats())); } } From 231ec03ef4bcc4a27820ddbe4cc617751c093b44 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Mon, 15 Apr 2024 17:30:11 +0000 Subject: [PATCH 19/26] swedish calendar translation --- files/data/l10n/Calendar/sv.yaml | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 files/data/l10n/Calendar/sv.yaml diff --git a/files/data/l10n/Calendar/sv.yaml b/files/data/l10n/Calendar/sv.yaml new file mode 100644 index 0000000000..f3ac2b915b --- /dev/null +++ b/files/data/l10n/Calendar/sv.yaml @@ -0,0 +1,50 @@ +# Swedish does not actually upper-case first letter on months and weekday names, so I'm doing them lower case right now. + +month1: "januari" +month2: "februari" +month3: "mars" +month4: "april" +month5: "maj" +month6: "juni" +month7: "juli" +month8: "augusti" +month9: "september" +month10: "oktober" +month11: "november" +month12: "december" + +# There are no different grammatical forms of the months in Swedish + +monthInGenitive1: "januari" +monthInGenitive2: "februari" +monthInGenitive3: "mars" +monthInGenitive4: "april" +monthInGenitive5: "maj" +monthInGenitive6: "juni" +monthInGenitive7: "juli" +monthInGenitive8: "augusti" +monthInGenitive9: "september" +monthInGenitive10: "oktober" +monthInGenitive11: "november" +monthInGenitive12: "december" + +# Standard Swedish date format: d MMMM YYYY +# Source: http://www4.sprakochfolkminnen.se/cgi-bin/srfl/visasvar.py?sok=datum&svar=26089 +# Example: "23 Februari 1337" +dateFormat: "{day} {month} {year, number, :: group-off}" + +# The Swedish week starts with monday actually, but whatever. + +weekday1: "söndag" +weekday2: "måndag" +weekday3: "tisdag" +weekday4: "onsdag" +weekday5: "torsdag" +weekday6: "fredag" +weekday7: "lördag" + +# In Swedish, as with German, we don't use AM/PM but instead a 24h clock. +# But instead of that, we could use "förmiddag" and "eftermiddag", which is basically "morning" and "afternoon" +am: "förmiddag" +pm: "eftermiddag" +day: "dag" From 9448a30caffac31f5372c03accc17e2ea61adb18 Mon Sep 17 00:00:00 2001 From: Joakim Berg Date: Mon, 15 Apr 2024 17:53:17 +0000 Subject: [PATCH 20/26] Accidental upper case in a comment --- files/data/l10n/Calendar/sv.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/data/l10n/Calendar/sv.yaml b/files/data/l10n/Calendar/sv.yaml index f3ac2b915b..858e586412 100644 --- a/files/data/l10n/Calendar/sv.yaml +++ b/files/data/l10n/Calendar/sv.yaml @@ -30,7 +30,7 @@ monthInGenitive12: "december" # Standard Swedish date format: d MMMM YYYY # Source: http://www4.sprakochfolkminnen.se/cgi-bin/srfl/visasvar.py?sok=datum&svar=26089 -# Example: "23 Februari 1337" +# Example: "23 februari 1337" dateFormat: "{day} {month} {year, number, :: group-off}" # The Swedish week starts with monday actually, but whatever. From f184d8f390f084a99cd2276d9ea1c6bad5ea4848 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 15 Apr 2024 00:02:12 +0200 Subject: [PATCH 21/26] Use RAII for AVIOContext, AVFormatContext, AVCodecContext and AVFrame pointers --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 200 +++++++++++-------------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 35 ++++- 2 files changed, 122 insertions(+), 113 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index a6f3d0336f..9e7a2be3a8 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -1,15 +1,41 @@ #include "ffmpeg_decoder.hpp" -#include - #include +#include #include +#include #include #include namespace MWSound { + void AVIOContextDeleter::operator()(AVIOContext* ptr) const + { + if (ptr->buffer != nullptr) + av_freep(&ptr->buffer); + +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100) + avio_context_free(&ptr); +#else + av_free(ptr); +#endif + } + + void AVFormatContextDeleter::operator()(AVFormatContext* ptr) const + { + avformat_close_input(&ptr); + } + + void AVCodecContextDeleter::operator()(AVCodecContext* ptr) const + { + avcodec_free_context(&ptr); + } + + void AVFrameDeleter::operator()(AVFrame* ptr) const + { + av_frame_free(&ptr); + } int FFmpeg_Decoder::readPacket(void* user_data, uint8_t* buf, int buf_size) { @@ -75,7 +101,7 @@ namespace MWSound return false; std::ptrdiff_t stream_idx = mStream - mFormatCtx->streams; - while (av_read_frame(mFormatCtx, &mPacket) >= 0) + while (av_read_frame(mFormatCtx.get(), &mPacket) >= 0) { /* Check if the packet belongs to this stream */ if (stream_idx == mPacket.stream_index) @@ -102,12 +128,12 @@ namespace MWSound do { /* Decode some data, and check for errors */ - int ret = avcodec_receive_frame(mCodecCtx, mFrame); + int ret = avcodec_receive_frame(mCodecCtx.get(), mFrame.get()); if (ret == AVERROR(EAGAIN)) { if (mPacket.size == 0 && !getNextPacket()) return false; - ret = avcodec_send_packet(mCodecCtx, &mPacket); + ret = avcodec_send_packet(mCodecCtx.get(), &mPacket); av_packet_unref(&mPacket); if (ret == 0) continue; @@ -187,137 +213,95 @@ namespace MWSound close(); mDataStream = mResourceMgr->get(fname); - if ((mFormatCtx = avformat_alloc_context()) == nullptr) + AVIOContextPtr ioCtx(avio_alloc_context(nullptr, 0, 0, this, readPacket, writePacket, seek)); + if (ioCtx == nullptr) + throw std::runtime_error("Failed to allocate AVIO context"); + + AVFormatContext* formatCtx = avformat_alloc_context(); + if (formatCtx == nullptr) throw std::runtime_error("Failed to allocate context"); - try + formatCtx->pb = ioCtx.get(); + + // avformat_open_input frees user supplied AVFormatContext on failure + if (avformat_open_input(&formatCtx, fname.c_str(), nullptr, nullptr) != 0) + throw std::runtime_error("Failed to open input"); + + AVFormatContextPtr formatCtxPtr(std::exchange(formatCtx, nullptr)); + + if (avformat_find_stream_info(formatCtxPtr.get(), nullptr) < 0) + throw std::runtime_error("Failed to find stream info"); + + AVStream** stream = nullptr; + for (size_t j = 0; j < formatCtxPtr->nb_streams; j++) { - mFormatCtx->pb = avio_alloc_context(nullptr, 0, 0, this, readPacket, writePacket, seek); - if (!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), nullptr, nullptr) != 0) + if (formatCtxPtr->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - // "Note that a user-supplied AVFormatContext will be freed on failure". - if (mFormatCtx) - { - if (mFormatCtx->pb != nullptr) - { - if (mFormatCtx->pb->buffer != nullptr) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = nullptr; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = nullptr; - } - avformat_free_context(mFormatCtx); - } - mFormatCtx = nullptr; - throw std::runtime_error("Failed to allocate input stream"); + stream = &formatCtxPtr->streams[j]; + break; } + } - if (avformat_find_stream_info(mFormatCtx, nullptr) < 0) - throw std::runtime_error("Failed to find stream info in " + fname); + if (stream == nullptr) + throw std::runtime_error("No audio streams"); - for (size_t j = 0; j < mFormatCtx->nb_streams; j++) - { - if (mFormatCtx->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) - { - mStream = &mFormatCtx->streams[j]; - break; - } - } - if (!mStream) - throw std::runtime_error("No audio streams in " + fname); + const AVCodec* codec = avcodec_find_decoder((*stream)->codecpar->codec_id); + if (codec == nullptr) + throw std::runtime_error("No codec found for id " + std::to_string((*stream)->codecpar->codec_id)); - const AVCodec* codec = avcodec_find_decoder((*mStream)->codecpar->codec_id); - if (!codec) - { - std::string ss = "No codec found for id " + std::to_string((*mStream)->codecpar->codec_id); - throw std::runtime_error(ss); - } + AVCodecContext* codecCtx = avcodec_alloc_context3(codec); + if (codecCtx == nullptr) + throw std::runtime_error("Failed to allocate codec context"); - AVCodecContext* avctx = avcodec_alloc_context3(codec); - avcodec_parameters_to_context(avctx, (*mStream)->codecpar); + avcodec_parameters_to_context(codecCtx, (*stream)->codecpar); // This is not needed anymore above FFMpeg version 4.0 #if LIBAVCODEC_VERSION_INT < 3805796 - av_codec_set_pkt_timebase(avctx, (*mStream)->time_base); + av_codec_set_pkt_timebase(avctx, (*stream)->time_base); #endif - mCodecCtx = avctx; + AVCodecContextPtr codecCtxPtr(std::exchange(codecCtx, nullptr)); - if (avcodec_open2(mCodecCtx, codec, nullptr) < 0) - throw std::runtime_error(std::string("Failed to open audio codec ") + codec->long_name); + if (avcodec_open2(codecCtxPtr.get(), codec, nullptr) < 0) + throw std::runtime_error(std::string("Failed to open audio codec ") + codec->long_name); - mFrame = av_frame_alloc(); + AVFramePtr frame(av_frame_alloc()); + if (frame == nullptr) + throw std::runtime_error("Failed to allocate frame"); - if (mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8P) - mOutputSampleFormat = AV_SAMPLE_FMT_U8; - // FIXME: Check for AL_EXT_FLOAT32 support - // else if (mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP) - // mOutputSampleFormat = AV_SAMPLE_FMT_S16; - else - mOutputSampleFormat = AV_SAMPLE_FMT_S16; + if (codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_U8P) + mOutputSampleFormat = AV_SAMPLE_FMT_U8; + // FIXME: Check for AL_EXT_FLOAT32 support + // else if (codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_FLT || codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_FLTP) + // mOutputSampleFormat = AV_SAMPLE_FMT_S16; + else + mOutputSampleFormat = AV_SAMPLE_FMT_S16; - mOutputChannelLayout = (*mStream)->codecpar->channel_layout; - if (mOutputChannelLayout == 0) - mOutputChannelLayout = av_get_default_channel_layout(mCodecCtx->channels); + mOutputChannelLayout = (*stream)->codecpar->channel_layout; + if (mOutputChannelLayout == 0) + mOutputChannelLayout = av_get_default_channel_layout(codecCtxPtr->channels); - mCodecCtx->channel_layout = mOutputChannelLayout; - } - catch (...) - { - if (mStream) - avcodec_free_context(&mCodecCtx); - mStream = nullptr; + codecCtxPtr->channel_layout = mOutputChannelLayout; - if (mFormatCtx != nullptr) - { - if (mFormatCtx->pb->buffer != nullptr) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = nullptr; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = nullptr; - - avformat_close_input(&mFormatCtx); - } - } + mIoCtx = std::move(ioCtx); + mFrame = std::move(frame); + mFormatCtx = std::move(formatCtxPtr); + mCodecCtx = std::move(codecCtxPtr); + mStream = stream; } void FFmpeg_Decoder::close() { - if (mStream) - avcodec_free_context(&mCodecCtx); mStream = nullptr; + mCodecCtx.reset(); av_packet_unref(&mPacket); av_freep(&mDataBuf); - av_frame_free(&mFrame); + mFrame.reset(); swr_free(&mSwr); - if (mFormatCtx) - { - if (mFormatCtx->pb != nullptr) - { - // mFormatCtx->pb->buffer must be freed by hand, - // if not, valgrind will show memleak, see: - // - // https://trac.ffmpeg.org/ticket/1357 - // - if (mFormatCtx->pb->buffer != nullptr) - { - av_freep(&mFormatCtx->pb->buffer); - } -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100) - avio_context_free(&mFormatCtx->pb); -#else - av_freep(&mFormatCtx->pb); -#endif - } - avformat_close_input(&mFormatCtx); - } - + mFormatCtx.reset(); + mIoCtx.reset(); mDataStream.reset(); } @@ -436,10 +420,7 @@ namespace MWSound FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs) : Sound_Decoder(vfs) - , mFormatCtx(nullptr) - , mCodecCtx(nullptr) , mStream(nullptr) - , mFrame(nullptr) , mFrameSize(0) , mFramePos(0) , mNextPts(0.0) @@ -470,5 +451,4 @@ namespace MWSound { close(); } - } diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index 9d15888fcf..ed3297403e 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -32,14 +32,43 @@ extern "C" namespace MWSound { + struct AVIOContextDeleter + { + void operator()(AVIOContext* ptr) const; + }; + + using AVIOContextPtr = std::unique_ptr; + + struct AVFormatContextDeleter + { + void operator()(AVFormatContext* ptr) const; + }; + + using AVFormatContextPtr = std::unique_ptr; + + struct AVCodecContextDeleter + { + void operator()(AVCodecContext* ptr) const; + }; + + using AVCodecContextPtr = std::unique_ptr; + + struct AVFrameDeleter + { + void operator()(AVFrame* ptr) const; + }; + + using AVFramePtr = std::unique_ptr; + class FFmpeg_Decoder final : public Sound_Decoder { - AVFormatContext* mFormatCtx; - AVCodecContext* mCodecCtx; + AVIOContextPtr mIoCtx; + AVFormatContextPtr mFormatCtx; + AVCodecContextPtr mCodecCtx; AVStream** mStream; AVPacket mPacket; - AVFrame* mFrame; + AVFramePtr mFrame; std::size_t mFrameSize; std::size_t mFramePos; From 443e341ae763cc906324e2445b52b894be87b610 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 16 Apr 2024 02:52:25 +0300 Subject: [PATCH 22/26] Generalize unsized pixel format computation --- components/sceneutil/util.cpp | 117 ++++++++++++++++++++++++++-- components/sceneutil/util.hpp | 4 +- components/shader/shadervisitor.cpp | 10 ++- components/terrain/material.cpp | 13 +++- 4 files changed, 132 insertions(+), 12 deletions(-) diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index a5629ee092..21a753df12 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -286,18 +286,125 @@ namespace SceneUtil mOperationQueue->add(operation); } - bool isRedGreenPixelFormat(GLenum format) + GLenum computeUnsizedPixelFormat(GLenum format) { switch (format) { - case GL_RG: - case GL_RG_INTEGER: + // Try compressed formats first, they're more likely to be used + + // Generic + case GL_COMPRESSED_ALPHA_ARB: + return GL_ALPHA; + case GL_COMPRESSED_INTENSITY_ARB: + return GL_INTENSITY; + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: + return GL_LUMINANCE_ALPHA; + case GL_COMPRESSED_LUMINANCE_ARB: + return GL_LUMINANCE; + case GL_COMPRESSED_RGB_ARB: + return GL_RGB; + case GL_COMPRESSED_RGBA_ARB: + return GL_RGBA; + + // S3TC + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + return GL_RGB; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return GL_RGBA; + + // RGTC + case GL_COMPRESSED_RED_RGTC1_EXT: + case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: + return GL_RED; case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: - return true; + return GL_RG; + + // PVRTC + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + return GL_RGB; + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + return GL_RGBA; + + // ETC + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + return GL_RED; + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: + return GL_RG; + case GL_ETC1_RGB8_OES: + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + return GL_RGB; + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + return GL_RGBA; + + // ASTC + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: + case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: + case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: + case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: + case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: + case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: + case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: + case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: + case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: + case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: + case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: + case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: + case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: + case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: + return GL_RGBA; + + // Plug in some holes computePixelFormat has, you never know when these could come in handy + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; } - return false; + return osg::Image::computePixelFormat(format); } } diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 0f4b82bbe0..b76f46a688 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -113,7 +113,9 @@ namespace SceneUtil osg::ref_ptr mOperationQueue; }; - bool isRedGreenPixelFormat(GLenum format); + // Compute the unsized format equivalent to the given pixel format + // Unlike osg::Image::computePixelFormat, this also covers compressed formats + GLenum computeUnsizedPixelFormat(GLenum format); } #endif diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 600e35a22a..2676ea3168 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -447,10 +447,14 @@ namespace Shader if (normalMap != nullptr && normalMap->getImage(0)) { // Special handling for red-green normal maps (e.g. BC5 or R8G8) - if (SceneUtil::isRedGreenPixelFormat(normalMap->getImage(0)->getPixelFormat())) + switch (SceneUtil::computeUnsizedPixelFormat(normalMap->getImage(0)->getPixelFormat())) { - mRequirements.back().mReconstructNormalZ = true; - mRequirements.back().mNormalHeight = false; + case GL_RG: + case GL_RG_INTEGER: + { + mRequirements.back().mReconstructNormalZ = true; + mRequirements.back().mNormalHeight = false; + } } } diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 10dbeb9838..09d2680acd 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -282,10 +282,17 @@ namespace Terrain // Special handling for red-green normal maps (e.g. BC5 or R8G8). const osg::Image* image = it->mNormalMap->getImage(0); - if (image && SceneUtil::isRedGreenPixelFormat(image->getPixelFormat())) + if (image) { - reconstructNormalZ = true; - parallax = false; + switch (SceneUtil::computeUnsizedPixelFormat(image->getPixelFormat())) + { + case GL_RG: + case GL_RG_INTEGER: + { + reconstructNormalZ = true; + parallax = false; + } + } } } From a7021bf9cc6cfc9111505e95ebb83d2921d2f13e Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 16 Apr 2024 01:10:39 +0100 Subject: [PATCH 23/26] Clear std stream errors when reopening Prior errors are no longer relevant. Shouldn't make a difference unless you've tried printing something before the streams were set up. --- components/debug/debugging.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index bfde558c85..0699d0912b 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -73,16 +73,19 @@ namespace Debug { _wfreopen(L"CON", L"r", stdin); freopen("CON", "r", stdin); + std::cin.clear(); } if (!outRedirected) { _wfreopen(L"CON", L"w", stdout); freopen("CON", "w", stdout); + std::cout.clear(); } if (!errRedirected) { _wfreopen(L"CON", L"w", stderr); freopen("CON", "w", stderr); + std::cerr.clear(); } return true; From 61364c874f09f61870b66a6414496f741a2030ac Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 16 Apr 2024 01:14:20 +0100 Subject: [PATCH 24/26] Warn future me off wasting their time again --- components/debug/debugging.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index 0699d0912b..e6caf2b09d 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -61,6 +61,10 @@ namespace Debug bool outRedirected = isRedirected(STD_OUTPUT_HANDLE); bool errRedirected = isRedirected(STD_ERROR_HANDLE); + // Note: Do not spend three days reinvestigating this PowerShell bug thinking its our bug. + // https://gitlab.com/OpenMW/openmw/-/merge_requests/408#note_447467393 + // The handles look valid, but GetFinalPathNameByHandleA can't tell what files they go to and writing to them doesn't work. + if (AttachConsole(ATTACH_PARENT_PROCESS)) { fflush(stdout); From d8f19c6e7b8fac335cd42b599bb68cab82b75159 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Tue, 16 Apr 2024 03:29:47 +0300 Subject: [PATCH 25/26] Changelog (two-channel normal maps, #7932) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeb030bda5..8f2ee0eb63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -225,6 +225,7 @@ Feature #7875: Disable MyGUI windows snapping Feature #7914: Do not allow to move GUI windows out of screen Feature #7923: Don't show non-existent higher ranks for factions with fewer than 9 ranks + Feature #7932: Support two-channel normal maps Task #5896: Do not use deprecated MyGUI properties Task #6085: Replace boost::filesystem with std::filesystem Task #6149: Dehardcode Lua API_REVISION From 83e3718bed550faefca66080eb66fb227fcd3f0a Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 16 Apr 2024 13:14:36 +0100 Subject: [PATCH 26/26] . c l a n g - f o r m a t --- components/debug/debugging.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index e6caf2b09d..67e7ecaaf3 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -63,7 +63,8 @@ namespace Debug // Note: Do not spend three days reinvestigating this PowerShell bug thinking its our bug. // https://gitlab.com/OpenMW/openmw/-/merge_requests/408#note_447467393 - // The handles look valid, but GetFinalPathNameByHandleA can't tell what files they go to and writing to them doesn't work. + // The handles look valid, but GetFinalPathNameByHandleA can't tell what files they go to and writing to them + // doesn't work. if (AttachConsole(ATTACH_PARENT_PROCESS)) {