Merge branch openmw:master into mwdialogue-bindings
|
@ -225,6 +225,7 @@
|
||||||
Feature #7875: Disable MyGUI windows snapping
|
Feature #7875: Disable MyGUI windows snapping
|
||||||
Feature #7914: Do not allow to move GUI windows out of screen
|
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 #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 #5896: Do not use deprecated MyGUI properties
|
||||||
Task #6085: Replace boost::filesystem with std::filesystem
|
Task #6085: Replace boost::filesystem with std::filesystem
|
||||||
Task #6149: Dehardcode Lua API_REVISION
|
Task #6149: Dehardcode Lua API_REVISION
|
||||||
|
|
|
@ -347,6 +347,16 @@ add_qt_style_dlls() {
|
||||||
QT_STYLES[$CONFIG]="${QT_STYLES[$CONFIG]} $@"
|
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
|
if [ -z $PLATFORM ]; then
|
||||||
PLATFORM="$(uname -m)"
|
PLATFORM="$(uname -m)"
|
||||||
fi
|
fi
|
||||||
|
@ -913,12 +923,13 @@ printf "Qt ${QT_VER}... "
|
||||||
DLLSUFFIX=""
|
DLLSUFFIX=""
|
||||||
fi
|
fi
|
||||||
if [ "${QT_VER:0:1}" -eq "6" ]; then
|
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
|
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
|
fi
|
||||||
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||||
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${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
|
done
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
|
@ -1112,6 +1123,13 @@ fi
|
||||||
echo " $(basename $DLL)"
|
echo " $(basename $DLL)"
|
||||||
cp "$DLL" "${DLL_PREFIX}styles"
|
cp "$DLL" "${DLL_PREFIX}styles"
|
||||||
done
|
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
|
echo
|
||||||
done
|
done
|
||||||
#fi
|
#fi
|
||||||
|
|
|
@ -36,7 +36,7 @@ declare -rA GROUPED_DEPS=(
|
||||||
libsdl2-dev libqt5opengl5-dev qttools5-dev qttools5-dev-tools libopenal-dev
|
libsdl2-dev libqt5opengl5-dev qttools5-dev qttools5-dev-tools libopenal-dev
|
||||||
libunshield-dev libtinyxml-dev libbullet-dev liblz4-dev libpng-dev libjpeg-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
|
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.
|
# These dependencies can alternatively be built and linked statically.
|
||||||
|
|
|
@ -234,7 +234,7 @@ else()
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
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()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -249,9 +249,9 @@ find_package(LZ4 REQUIRED)
|
||||||
if (USE_QT)
|
if (USE_QT)
|
||||||
find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5)
|
find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5)
|
||||||
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
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()
|
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()
|
endif()
|
||||||
message(STATUS "Using Qt${QT_VERSION}")
|
message(STATUS "Using Qt${QT_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
|
@ -710,9 +710,8 @@ if (WIN32)
|
||||||
if (USE_DEBUG_CONSOLE AND BUILD_OPENMW)
|
if (USE_DEBUG_CONSOLE AND BUILD_OPENMW)
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
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 LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
||||||
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_CONSOLE>)
|
|
||||||
elseif (BUILD_OPENMW)
|
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_DEBUG "/SUBSYSTEM:WINDOWS")
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS")
|
||||||
endif()
|
endif()
|
||||||
|
@ -834,6 +833,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_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("${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)
|
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 ()
|
endif ()
|
||||||
|
|
||||||
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime)
|
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "." COMPONENT Runtime)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "labels.hpp"
|
#include "labels.hpp"
|
||||||
|
|
||||||
|
#include <components/esm3/dialoguecondition.hpp>
|
||||||
#include <components/esm3/loadalch.hpp>
|
#include <components/esm3/loadalch.hpp>
|
||||||
#include <components/esm3/loadbody.hpp>
|
#include <components/esm3/loadbody.hpp>
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
|
@ -572,13 +573,14 @@ std::string_view enchantTypeLabel(int idx)
|
||||||
|
|
||||||
std::string_view ruleFunction(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[] = {
|
static constexpr std::string_view ruleFunctions[] = {
|
||||||
"Reaction Low",
|
"Lowest Faction Reaction",
|
||||||
"Reaction High",
|
"Highest Faction Reaction",
|
||||||
"Rank Requirement",
|
"Rank Requirement",
|
||||||
"NPC? Reputation",
|
"NPC Reputation",
|
||||||
"Health Percent",
|
"Health Percent",
|
||||||
"Player Reputation",
|
"Player Reputation",
|
||||||
"NPC Level",
|
"NPC Level",
|
||||||
|
@ -648,6 +650,7 @@ std::string_view ruleFunction(int idx)
|
||||||
"Flee",
|
"Flee",
|
||||||
"Should Attack",
|
"Should Attack",
|
||||||
"Werewolf",
|
"Werewolf",
|
||||||
|
"Werewolf Kills",
|
||||||
};
|
};
|
||||||
return ruleFunctions[idx];
|
return ruleFunctions[idx];
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,112 +57,82 @@ namespace
|
||||||
std::cout << " Cell Name: " << p.mCellName << std::endl;
|
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)
|
switch (ss.mFunction)
|
||||||
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<int>(rule.substr(2, 2), 0);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case '1':
|
case ESM::DialogueCondition::Function_Global:
|
||||||
type_str = "Function";
|
type_str = "Global";
|
||||||
func_str = std::string(ruleFunction(func));
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '2':
|
case ESM::DialogueCondition::Function_Local:
|
||||||
if (indicator == 's')
|
type_str = "Local";
|
||||||
type_str = "Global short";
|
func_str = ss.mVariable;
|
||||||
else if (indicator == 'l')
|
|
||||||
type_str = "Global long";
|
|
||||||
else if (indicator == 'f')
|
|
||||||
type_str = "Global float";
|
|
||||||
break;
|
break;
|
||||||
case '3':
|
case ESM::DialogueCondition::Function_Journal:
|
||||||
if (indicator == 's')
|
type_str = "Journal";
|
||||||
type_str = "Local short";
|
func_str = ss.mVariable;
|
||||||
else if (indicator == 'l')
|
|
||||||
type_str = "Local long";
|
|
||||||
else if (indicator == 'f')
|
|
||||||
type_str = "Local float";
|
|
||||||
break;
|
break;
|
||||||
case '4':
|
case ESM::DialogueCondition::Function_Item:
|
||||||
if (indicator == 'J')
|
type_str = "Item count";
|
||||||
type_str = "Journal";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '5':
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
if (indicator == 'I')
|
type_str = "Dead";
|
||||||
type_str = "Item type";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '6':
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
if (indicator == 'D')
|
type_str = "Not ID";
|
||||||
type_str = "NPC Dead";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '7':
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
if (indicator == 'X')
|
type_str = "Not Faction";
|
||||||
type_str = "Not ID";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '8':
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
if (indicator == 'F')
|
type_str = "Not Class";
|
||||||
type_str = "Not Faction";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '9':
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
if (indicator == 'C')
|
type_str = "Not Race";
|
||||||
type_str = "Not Class";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case ESM::DialogueCondition::Function_NotCell:
|
||||||
if (indicator == 'R')
|
type_str = "Not Cell";
|
||||||
type_str = "Not Race";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case ESM::DialogueCondition::Function_NotLocal:
|
||||||
if (indicator == 'L')
|
type_str = "Not Local";
|
||||||
type_str = "Not Cell";
|
func_str = ss.mVariable;
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
if (indicator == 's')
|
|
||||||
type_str = "Not Local";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
type_str = "Function";
|
||||||
|
func_str = ruleFunction(ss.mFunction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the variable name to the function string if any.
|
std::string_view oper_str = "??";
|
||||||
if (type != '1')
|
switch (ss.mComparison)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
case '0':
|
case ESM::DialogueCondition::Comp_Eq:
|
||||||
oper_str = "==";
|
oper_str = "==";
|
||||||
break;
|
break;
|
||||||
case '1':
|
case ESM::DialogueCondition::Comp_Ne:
|
||||||
oper_str = "!=";
|
oper_str = "!=";
|
||||||
break;
|
break;
|
||||||
case '2':
|
case ESM::DialogueCondition::Comp_Gt:
|
||||||
oper_str = "> ";
|
oper_str = "> ";
|
||||||
break;
|
break;
|
||||||
case '3':
|
case ESM::DialogueCondition::Comp_Ge:
|
||||||
oper_str = ">=";
|
oper_str = ">=";
|
||||||
break;
|
break;
|
||||||
case '4':
|
case ESM::DialogueCondition::Comp_Ls:
|
||||||
oper_str = "< ";
|
oper_str = "< ";
|
||||||
break;
|
break;
|
||||||
case '5':
|
case ESM::DialogueCondition::Comp_Le:
|
||||||
oper_str = "<=";
|
oper_str = "<=";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -170,7 +140,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << ss.mValue;
|
std::visit([&](auto value) { stream << value; }, ss.mValue);
|
||||||
|
|
||||||
std::string result
|
std::string result
|
||||||
= Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
= Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
||||||
|
@ -842,7 +812,7 @@ namespace EsmTool
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << " Type: " << dialogTypeLabel(mData.mData.mType) << 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;
|
std::cout << " Select Rule: " << ruleString(rule) << std::endl;
|
||||||
|
|
||||||
if (!mData.mResultScript.empty())
|
if (!mData.mResultScript.empty())
|
||||||
|
|
|
@ -250,9 +250,9 @@ target_link_libraries(openmw-cs-lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if (QT_VERSION_MAJOR VERSION_EQUAL 6)
|
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()
|
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()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -81,7 +81,7 @@ int runApplication(int argc, char* argv[])
|
||||||
|
|
||||||
Application application(argc, argv);
|
Application application(argc, argv);
|
||||||
|
|
||||||
application.setWindowIcon(QIcon(":./openmw-cs.png"));
|
application.setWindowIcon(QIcon(":openmw-cs"));
|
||||||
|
|
||||||
CS::Editor editor(argc, argv);
|
CS::Editor editor(argc, argv);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
|
@ -171,10 +171,9 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
|
||||||
|
|
||||||
// Check info conditions
|
// Check info conditions
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator it = topicInfo.mSelects.begin();
|
for (const auto& select : topicInfo.mSelects)
|
||||||
it != topicInfo.mSelects.end(); ++it)
|
|
||||||
{
|
{
|
||||||
verifySelectStruct((*it), id, messages);
|
verifySelectStruct(select, id, messages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,49 +307,15 @@ bool CSMTools::TopicInfoCheckStage::verifyItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
|
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);
|
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);
|
messages.add(id, "Invalid condition '" + infoCondition.toString() + "'", "", CSMDoc::Message::Severity_Error);
|
||||||
return false;
|
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())
|
else if (infoCondition.conditionIsAlwaysTrue())
|
||||||
{
|
{
|
||||||
messages.add(
|
messages.add(
|
||||||
|
@ -365,48 +330,48 @@ bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Id checks
|
// Id checks
|
||||||
if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global
|
if (select.mFunction == ESM::DialogueCondition::Function_Global
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mGlobals, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mGlobals, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Journal
|
else if (select.mFunction == ESM::DialogueCondition::Function_Journal
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mJournals, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mJournals, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item
|
else if (select.mFunction == ESM::DialogueCondition::Function_Item
|
||||||
&& !verifyItem(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyItem(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead
|
else if (select.mFunction == ESM::DialogueCondition::Function_Dead
|
||||||
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotId
|
||||||
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotFaction
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotFaction
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mFactions, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mFactions, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotClass
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotClass
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mClasses, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mClasses, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotRace
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotRace
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mRaces, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mRaces, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotCell
|
||||||
&& !verifyCell(infoCondition.getVariableName(), id, messages))
|
&& !verifyCell(select.mVariable, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace CSMTools
|
||||||
const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
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 verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
bool verifySelectStruct(
|
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);
|
bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -7,133 +7,13 @@
|
||||||
|
|
||||||
#include <components/esm3/loadinfo.hpp>
|
#include <components/esm3/loadinfo.hpp>
|
||||||
|
|
||||||
namespace ESM
|
#include <QVariant>
|
||||||
{
|
|
||||||
class Variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CSMWorld
|
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
|
class ConstInfoSelectWrapper
|
||||||
{
|
{
|
||||||
public:
|
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
|
enum ComparisonType
|
||||||
{
|
{
|
||||||
Comparison_Boolean,
|
Comparison_Boolean,
|
||||||
|
@ -143,25 +23,13 @@ namespace CSMWorld
|
||||||
Comparison_None
|
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* FunctionEnumStrings[];
|
||||||
static const char* RelationEnumStrings[];
|
static const char* RelationEnumStrings[];
|
||||||
static const char* ComparisonEnumStrings[];
|
|
||||||
|
|
||||||
static std::string convertToString(FunctionName name);
|
ConstInfoSelectWrapper(const ESM::DialogueCondition& select);
|
||||||
static std::string convertToString(RelationType type);
|
|
||||||
static std::string convertToString(ComparisonType type);
|
|
||||||
|
|
||||||
ConstInfoSelectWrapper(const ESM::DialInfo::SelectStruct& select);
|
ESM::DialogueCondition::Function getFunctionName() const;
|
||||||
|
ESM::DialogueCondition::Comparison getRelationType() const;
|
||||||
FunctionName getFunctionName() const;
|
|
||||||
RelationType getRelationType() const;
|
|
||||||
ComparisonType getComparisonType() const;
|
ComparisonType getComparisonType() const;
|
||||||
|
|
||||||
bool hasVariable() const;
|
bool hasVariable() const;
|
||||||
|
@ -169,17 +37,12 @@ namespace CSMWorld
|
||||||
|
|
||||||
bool conditionIsAlwaysTrue() const;
|
bool conditionIsAlwaysTrue() const;
|
||||||
bool conditionIsNeverTrue() const;
|
bool conditionIsNeverTrue() const;
|
||||||
bool variantTypeIsValid() const;
|
|
||||||
|
|
||||||
const ESM::Variant& getVariant() const;
|
QVariant getValue() const;
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void readRule();
|
|
||||||
void readFunctionName();
|
|
||||||
void readRelationType();
|
|
||||||
void readVariableName();
|
|
||||||
void updateHasVariable();
|
void updateHasVariable();
|
||||||
void updateComparisonType();
|
void updateComparisonType();
|
||||||
|
|
||||||
|
@ -207,38 +70,29 @@ namespace CSMWorld
|
||||||
template <typename Type1, typename Type2>
|
template <typename Type1, typename Type2>
|
||||||
bool conditionIsNeverTrue(std::pair<Type1, Type1> conditionRange, std::pair<Type2, Type2> validRange) const;
|
bool conditionIsNeverTrue(std::pair<Type1, Type1> conditionRange, std::pair<Type2, Type2> validRange) const;
|
||||||
|
|
||||||
FunctionName mFunctionName;
|
|
||||||
RelationType mRelationType;
|
|
||||||
ComparisonType mComparisonType;
|
ComparisonType mComparisonType;
|
||||||
|
|
||||||
bool mHasVariable;
|
bool mHasVariable;
|
||||||
std::string mVariableName;
|
|
||||||
|
|
||||||
private:
|
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
|
class InfoSelectWrapper : public ConstInfoSelectWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InfoSelectWrapper(ESM::DialInfo::SelectStruct& select);
|
InfoSelectWrapper(ESM::DialogueCondition& select);
|
||||||
|
|
||||||
// Wrapped SelectStruct will not be modified until update() is called
|
// Wrapped SelectStruct will not be modified until update() is called
|
||||||
void setFunctionName(FunctionName name);
|
void setFunctionName(ESM::DialogueCondition::Function name);
|
||||||
void setRelationType(RelationType type);
|
void setRelationType(ESM::DialogueCondition::Comparison type);
|
||||||
void setVariableName(const std::string& name);
|
void setVariableName(const std::string& name);
|
||||||
|
void setValue(int value);
|
||||||
// Modified wrapped SelectStruct
|
void setValue(float value);
|
||||||
void update();
|
|
||||||
|
|
||||||
// This sets properties based on the function name to its defaults and updates the wrapped object
|
|
||||||
void setDefaults();
|
|
||||||
|
|
||||||
ESM::Variant& getVariant();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ESM::DialInfo::SelectStruct& mSelect;
|
ESM::DialogueCondition& mSelect;
|
||||||
|
|
||||||
void writeRule();
|
void writeRule();
|
||||||
};
|
};
|
||||||
|
|
|
@ -538,13 +538,11 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
// default row
|
// default row
|
||||||
ESM::DialInfo::SelectStruct condStruct;
|
ESM::DialogueCondition condStruct;
|
||||||
condStruct.mSelectRule = "01000";
|
condStruct.mIndex = conditions.size();
|
||||||
condStruct.mValue = ESM::Variant();
|
|
||||||
condStruct.mValue.setType(ESM::VT_Int);
|
|
||||||
|
|
||||||
conditions.insert(conditions.begin() + position, condStruct);
|
conditions.insert(conditions.begin() + position, condStruct);
|
||||||
|
|
||||||
|
@ -555,7 +553,7 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(conditions.size()))
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
@ -569,8 +567,8 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
info.mSelects = static_cast<const NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct>>&>(nestedTable)
|
info.mSelects
|
||||||
.mNestedTable;
|
= static_cast<const NestedTableWrapper<std::vector<ESM::DialogueCondition>>&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
record.setModified(info);
|
record.setModified(info);
|
||||||
}
|
}
|
||||||
|
@ -578,14 +576,14 @@ namespace CSMWorld
|
||||||
NestedTableWrapperBase* InfoConditionAdapter::table(const Record<Info>& record) const
|
NestedTableWrapperBase* InfoConditionAdapter::table(const Record<Info>& record) const
|
||||||
{
|
{
|
||||||
// deleted by dtor of NestedTableStoring
|
// deleted by dtor of NestedTableStoring
|
||||||
return new NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct>>(record.get().mSelects);
|
return new NestedTableWrapper<std::vector<ESM::DialogueCondition>>(record.get().mSelects);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant InfoConditionAdapter::getData(const Record<Info>& record, int subRowIndex, int subColIndex) const
|
QVariant InfoConditionAdapter::getData(const Record<Info>& record, int subRowIndex, int subColIndex) const
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
@ -607,23 +605,11 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
return infoSelectWrapper.getRelationType();
|
return infoSelectWrapper.getRelationType() - ESM::DialogueCondition::Comp_Eq;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
switch (infoSelectWrapper.getVariant().getType())
|
return infoSelectWrapper.getValue();
|
||||||
{
|
|
||||||
case ESM::VT_Int:
|
|
||||||
{
|
|
||||||
return infoSelectWrapper.getVariant().getInteger();
|
|
||||||
}
|
|
||||||
case ESM::VT_Float:
|
|
||||||
{
|
|
||||||
return infoSelectWrapper.getVariant().getFloat();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Info condition subcolumn index out of range");
|
throw std::runtime_error("Info condition subcolumn index out of range");
|
||||||
|
@ -635,7 +621,7 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
@ -647,27 +633,18 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
case 0: // Function
|
case 0: // Function
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setFunctionName(static_cast<ConstInfoSelectWrapper::FunctionName>(value.toInt()));
|
infoSelectWrapper.setFunctionName(static_cast<ESM::DialogueCondition::Function>(value.toInt()));
|
||||||
|
|
||||||
if (infoSelectWrapper.getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric
|
|
||||||
&& infoSelectWrapper.getVariant().getType() != ESM::VT_Int)
|
|
||||||
{
|
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
|
||||||
}
|
|
||||||
|
|
||||||
infoSelectWrapper.update();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Variable
|
case 1: // Variable
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setVariableName(value.toString().toUtf8().constData());
|
infoSelectWrapper.setVariableName(value.toString().toUtf8().constData());
|
||||||
infoSelectWrapper.update();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: // Relation
|
case 2: // Relation
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setRelationType(static_cast<ConstInfoSelectWrapper::RelationType>(value.toInt()));
|
infoSelectWrapper.setRelationType(
|
||||||
infoSelectWrapper.update();
|
static_cast<ESM::DialogueCondition::Comparison>(value.toInt() + ESM::DialogueCondition::Comp_Eq));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: // Value
|
case 3: // Value
|
||||||
|
@ -679,13 +656,11 @@ namespace CSMWorld
|
||||||
// QVariant seems to have issues converting 0
|
// QVariant seems to have issues converting 0
|
||||||
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
infoSelectWrapper.setValue(value.toInt());
|
||||||
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
||||||
}
|
}
|
||||||
else if (value.toFloat(&conversionResult) && conversionResult)
|
else if (value.toFloat(&conversionResult) && conversionResult)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Float);
|
infoSelectWrapper.setValue(value.toFloat());
|
||||||
infoSelectWrapper.getVariant().setFloat(value.toFloat());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -694,8 +669,7 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
infoSelectWrapper.setValue(value.toInt());
|
||||||
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
||||||
|
|
||||||
if (tmpIcon != id.getIcon())
|
if (tmpIcon != id.getIcon())
|
||||||
{
|
{
|
||||||
return ":/multitype.png"; // icon stolen from gnome TODO: get new icon
|
return ":multitype";
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIcon = id.getIcon();
|
tmpIcon = id.getIcon();
|
||||||
|
|
|
@ -23,158 +23,137 @@ namespace
|
||||||
constexpr TypeData sNoArg[] = {
|
constexpr TypeData sNoArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", ":placeholder" },
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", ":placeholder" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables",
|
||||||
":./global-variable.png" },
|
":global-variable" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":./gmst.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":gmst" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":./skill.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":skill" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":./class.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":class" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":./faction.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":faction" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":./race.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":race" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":./sound.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":sound" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":./script.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":script" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":./region.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":region" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", ":birthsign" },
|
||||||
":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":spell" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", ":dialogue-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics",
|
|
||||||
":./dialogue-topics.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals",
|
||||||
":./journal-topics.png" },
|
":journal-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos",
|
{ 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",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos",
|
||||||
":./journal-topic-infos.png" },
|
":journal-topic-infos" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments",
|
||||||
":./enchantment.png" },
|
":enchantment" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", ":body-part" },
|
||||||
":./body-part.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", ":object" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", ":instance" },
|
||||||
":./object.png" },
|
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", ":region-map" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":filter" },
|
||||||
":./instance.png" },
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", ":resources-mesh" },
|
||||||
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":resources-icon" },
|
||||||
":./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" },
|
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files",
|
||||||
":./resources-music" },
|
":resources-music" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files",
|
||||||
":resources-sound" },
|
":resources-sound" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures",
|
||||||
":./resources-texture" },
|
":resources-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", ":resources-video" },
|
||||||
":./resources-video" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles",
|
{ 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_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",
|
{ 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",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects",
|
||||||
":./magic-effect.png" },
|
":magic-effect" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", ":land-heightmap" },
|
||||||
":./land-heightmap.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures",
|
||||||
":./land-texture.png" },
|
":land-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", ":pathgrid" },
|
||||||
":./pathgrid.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts",
|
||||||
":./start-script.png" },
|
":start-script" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", ":metadata" },
|
||||||
":./metadata.png" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr TypeData sIdArg[] = {
|
constexpr TypeData sIdArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable",
|
||||||
":./global-variable.png" },
|
":global-variable" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./gmst.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":gmst" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":skill" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":class" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":faction" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":race" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":sound" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":script" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./region.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":region" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":birthsign" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":spell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":./dialogue-topics.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":dialogue-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", ":journal-topics" },
|
||||||
":./journal-topics.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo",
|
||||||
":./dialogue-topic-infos.png" },
|
":dialogue-info" },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo",
|
||||||
":./journal-topic-infos.png" },
|
":journal-topic-infos" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":./object.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":object" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":activator" },
|
||||||
":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":potion" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":apparatus" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":armor" },
|
||||||
":./apparatus.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":book" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":clothing" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":container" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":creature" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":door" },
|
||||||
":./container.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":ingredient" },
|
||||||
{ 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" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
{ 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",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, "Item Levelled List",
|
||||||
":./levelled-item.png" },
|
":levelled-item" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":light" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":lockpick" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, "Miscellaneous",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, "Miscellaneous",
|
||||||
":./miscellaneous.png" },
|
":miscellaneous" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":npc" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":probe" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":repair" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":static" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":weapon" },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", ":instance" },
|
||||||
":./instance.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":filter" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":scene" },
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":./scene.png" },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", ":edit-preview" },
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", ":enchantment" },
|
||||||
":./record-preview.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":body-part" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":resources-mesh" },
|
||||||
":./enchantment.png" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":resources-icon" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":./body-part.png" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":resources-music" },
|
||||||
{ 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",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File",
|
||||||
":./resources-sound" },
|
":resources-sound" },
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", ":resources-texture" },
|
||||||
":./resources-texture" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":resources-video" },
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":./resources-video" },
|
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile",
|
{ 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",
|
{ 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",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect",
|
||||||
":./magic-effect.png" },
|
":magic-effect" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":./land-heightmap.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":land-heightmap" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture",
|
||||||
":./land-texture.png" },
|
":land-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":./pathgrid.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":pathgrid" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script",
|
||||||
":./start-script.png" },
|
":start-script" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":./metadata.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":metadata" },
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr TypeData sIndexArg[] = {
|
constexpr TypeData sIndexArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults,
|
{ 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",
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log",
|
||||||
":./error-log.png" },
|
":error-log" },
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search",
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", ":menu-search" },
|
||||||
":./menu-search.png" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WriteToStream
|
struct WriteToStream
|
||||||
|
|
|
@ -71,30 +71,30 @@ void CSVDoc::View::setupFileMenu()
|
||||||
{
|
{
|
||||||
QMenu* file = menuBar()->addMenu(tr("File"));
|
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);
|
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);
|
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);
|
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);
|
connect(save, &QAction::triggered, this, &View::save);
|
||||||
mSave = save;
|
mSave = save;
|
||||||
|
|
||||||
file->addSeparator();
|
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);
|
connect(verify, &QAction::triggered, this, &View::verify);
|
||||||
mVerify = 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);
|
connect(merge, &QAction::triggered, this, &View::merge);
|
||||||
mMerge = 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);
|
connect(loadErrors, &QAction::triggered, this, &View::loadErrorLog);
|
||||||
|
|
||||||
QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata");
|
QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata");
|
||||||
|
@ -102,10 +102,10 @@ void CSVDoc::View::setupFileMenu()
|
||||||
|
|
||||||
file->addSeparator();
|
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);
|
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(exit, &QAction::triggered, this, &View::exit);
|
||||||
|
|
||||||
connect(this, &View::exitApplicationRequest, &mViewManager, &ViewManager::exitApplication);
|
connect(this, &View::exitApplicationRequest, &mViewManager, &ViewManager::exitApplication);
|
||||||
|
@ -140,17 +140,16 @@ void CSVDoc::View::setupEditMenu()
|
||||||
mUndo = mDocument->getUndoStack().createUndoAction(this, tr("Undo"));
|
mUndo = mDocument->getUndoStack().createUndoAction(this, tr("Undo"));
|
||||||
setupShortcut("document-edit-undo", mUndo);
|
setupShortcut("document-edit-undo", mUndo);
|
||||||
connect(mUndo, &QAction::changed, this, &View::undoActionChanged);
|
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);
|
edit->addAction(mUndo);
|
||||||
|
|
||||||
mRedo = mDocument->getUndoStack().createRedoAction(this, tr("Redo"));
|
mRedo = mDocument->getUndoStack().createRedoAction(this, tr("Redo"));
|
||||||
connect(mRedo, &QAction::changed, this, &View::redoActionChanged);
|
connect(mRedo, &QAction::changed, this, &View::redoActionChanged);
|
||||||
setupShortcut("document-edit-redo", mRedo);
|
setupShortcut("document-edit-redo", mRedo);
|
||||||
mRedo->setIcon(QIcon(QString::fromStdString(":./menu-redo.png")));
|
mRedo->setIcon(QIcon(QString::fromStdString(":menu-redo")));
|
||||||
edit->addAction(mRedo);
|
edit->addAction(mRedo);
|
||||||
|
|
||||||
QAction* userSettings
|
QAction* userSettings = createMenuEntry("Preferences", ":menu-preferences", edit, "document-edit-preferences");
|
||||||
= createMenuEntry("Preferences", ":./menu-preferences.png", edit, "document-edit-preferences");
|
|
||||||
connect(userSettings, &QAction::triggered, this, &View::editSettingsRequest);
|
connect(userSettings, &QAction::triggered, this, &View::editSettingsRequest);
|
||||||
|
|
||||||
QAction* search = createMenuEntry(CSMWorld::UniversalId::Type_Search, edit, "document-edit-search");
|
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"));
|
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);
|
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);
|
connect(mShowStatusBar, &QAction::toggled, this, &View::toggleShowStatusBar);
|
||||||
mShowStatusBar->setCheckable(true);
|
mShowStatusBar->setCheckable(true);
|
||||||
mShowStatusBar->setChecked(CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
|
mShowStatusBar->setChecked(CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
|
||||||
|
@ -289,7 +288,7 @@ void CSVDoc::View::setupAssetsMenu()
|
||||||
{
|
{
|
||||||
QMenu* assets = menuBar()->addMenu(tr("Assets"));
|
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);
|
connect(reload, &QAction::triggered, &mDocument->getData(), &CSMWorld::Data::assetsChanged);
|
||||||
|
|
||||||
assets->addSeparator();
|
assets->addSeparator();
|
||||||
|
@ -341,9 +340,9 @@ void CSVDoc::View::setupDebugMenu()
|
||||||
QAction* runDebug = debug->addMenu(mGlobalDebugProfileMenu);
|
QAction* runDebug = debug->addMenu(mGlobalDebugProfileMenu);
|
||||||
runDebug->setText(tr("Run OpenMW"));
|
runDebug->setText(tr("Run OpenMW"));
|
||||||
setupShortcut("document-debug-run", runDebug);
|
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);
|
connect(stopDebug, &QAction::triggered, this, &View::stop);
|
||||||
mStopDebug = stopDebug;
|
mStopDebug = stopDebug;
|
||||||
|
|
||||||
|
@ -355,16 +354,16 @@ void CSVDoc::View::setupHelpMenu()
|
||||||
{
|
{
|
||||||
QMenu* help = menuBar()->addMenu(tr("Help"));
|
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);
|
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);
|
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);
|
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);
|
connect(aboutQt, &QAction::triggered, this, &View::infoAboutQt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ CSVFilter::EditWidget::EditWidget(CSMWorld::Data& data, QWidget* parent)
|
||||||
|
|
||||||
mHelpAction = new QAction(tr("Help"), this);
|
mHelpAction = new QAction(tr("Help"), this);
|
||||||
connect(mHelpAction, &QAction::triggered, this, &EditWidget::openHelp);
|
connect(mHelpAction, &QAction::triggered, this, &EditWidget::openHelp);
|
||||||
mHelpAction->setIcon(QIcon(":/info.png"));
|
mHelpAction->setIcon(QIcon(":info"));
|
||||||
addAction(mHelpAction);
|
addAction(mHelpAction);
|
||||||
auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
||||||
openHelpShortcut->associateAction(mHelpAction);
|
openHelpShortcut->associateAction(mHelpAction);
|
||||||
|
|
|
@ -12,11 +12,10 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
// elements that are part of the actual scene
|
// elements that are part of the actual scene
|
||||||
Mask_Hidden = 0x0,
|
Mask_Hidden = 0x0,
|
||||||
Mask_Reference = 0x2,
|
Mask_Reference = 0x1,
|
||||||
Mask_Pathgrid = 0x4,
|
Mask_Pathgrid = 0x2,
|
||||||
Mask_Water = 0x8,
|
Mask_Water = 0x4,
|
||||||
Mask_Fog = 0x10,
|
Mask_Terrain = 0x8,
|
||||||
Mask_Terrain = 0x20,
|
|
||||||
|
|
||||||
// used within models
|
// used within models
|
||||||
Mask_ParticleSystem = 0x100,
|
Mask_ParticleSystem = 0x100,
|
||||||
|
|
|
@ -160,7 +160,6 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget::S
|
||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
||||||
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain");
|
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain");
|
||||||
tool->addButton(Button_Fog, Mask_Fog, "Fog", "", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool)
|
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool)
|
||||||
|
@ -170,9 +169,10 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::Sce
|
||||||
/// \todo replace EditMode with suitable subclasses
|
/// \todo replace EditMode with suitable subclasses
|
||||||
tool->addButton(new TerrainShapeMode(this, mRootNode, tool), "terrain-shape");
|
tool->addButton(new TerrainShapeMode(this, mRootNode, tool), "terrain-shape");
|
||||||
tool->addButton(new TerrainTextureMode(this, mRootNode, tool), "terrain-texture");
|
tool->addButton(new TerrainTextureMode(this, mRootNode, tool), "terrain-texture");
|
||||||
tool->addButton(
|
const QIcon vertexIcon = QIcon(":scenetoolbar/editing-terrain-vertex-paint");
|
||||||
new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain vertex paint editing"), "terrain-vertex");
|
const QIcon movementIcon = QIcon(":scenetoolbar/editing-terrain-movement");
|
||||||
tool->addButton(new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain movement"), "terrain-move");
|
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)
|
void CSVRender::PagedWorldspaceWidget::handleInteractionPress(const WorldspaceHitResult& hit, InteractionType type)
|
||||||
|
|
|
@ -36,8 +36,8 @@ class QWidget;
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
||||||
: EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(),
|
: EditMode(worldspaceWidget, QIcon(":scenetoolbar/editing-pathgrid"),
|
||||||
parent)
|
Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), parent)
|
||||||
, mDragMode(DragMode_None)
|
, mDragMode(DragMode_None)
|
||||||
, mFromNode(0)
|
, mFromNode(0)
|
||||||
, mSelectionMode(nullptr)
|
, mSelectionMode(nullptr)
|
||||||
|
|
|
@ -347,7 +347,6 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget:
|
||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
||||||
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
||||||
tool->addButton(Button_Fog, Mask_Fog, "Fog");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
||||||
|
|
|
@ -222,8 +222,7 @@ namespace CSVRender
|
||||||
Button_Reference = 0x1,
|
Button_Reference = 0x1,
|
||||||
Button_Pathgrid = 0x2,
|
Button_Pathgrid = 0x2,
|
||||||
Button_Water = 0x4,
|
Button_Water = 0x4,
|
||||||
Button_Fog = 0x8,
|
Button_Terrain = 0x8
|
||||||
Button_Terrain = 0x10
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool);
|
virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool);
|
||||||
|
|
|
@ -46,41 +46,41 @@ QWidget* CSVWorld::IdCompletionDelegate::createEditor(QWidget* parent, const QSt
|
||||||
|
|
||||||
switch (conditionFunction)
|
switch (conditionFunction)
|
||||||
{
|
{
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Global:
|
case ESM::DialogueCondition::Function_Global:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_GlobalVariable);
|
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);
|
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);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Dead:
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotId:
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
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);
|
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);
|
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);
|
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);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Cell);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Local:
|
case ESM::DialogueCondition::Function_Local:
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotLocal:
|
case ESM::DialogueCondition::Function_NotLocal:
|
||||||
{
|
{
|
||||||
return new CSVWidget::DropLineEdit(display, parent);
|
return new CSVWidget::DropLineEdit(display, parent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ CSVWorld::RecordButtonBar::RecordButtonBar(const CSMWorld::UniversalId& id, CSMW
|
||||||
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View)
|
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View)
|
||||||
{
|
{
|
||||||
QToolButton* viewButton = new QToolButton(this);
|
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");
|
viewButton->setToolTip("Open a scene view of the cell this record is located in");
|
||||||
buttonsLayout->addWidget(viewButton);
|
buttonsLayout->addWidget(viewButton);
|
||||||
connect(viewButton, &QToolButton::clicked, this, &RecordButtonBar::viewRecord);
|
connect(viewButton, &QToolButton::clicked, this, &RecordButtonBar::viewRecord);
|
||||||
|
|
|
@ -385,7 +385,7 @@ CSVWorld::Table::Table(const CSMWorld::UniversalId& id, bool createAndDelete, bo
|
||||||
|
|
||||||
mViewAction = new QAction(tr("View"), this);
|
mViewAction = new QAction(tr("View"), this);
|
||||||
connect(mViewAction, &QAction::triggered, this, &Table::viewRecord);
|
connect(mViewAction, &QAction::triggered, this, &Table::viewRecord);
|
||||||
mViewAction->setIcon(QIcon(":/cell.png"));
|
mViewAction->setIcon(QIcon(":cell"));
|
||||||
addAction(mViewAction);
|
addAction(mViewAction);
|
||||||
CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this);
|
CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this);
|
||||||
viewShortcut->associateAction(mViewAction);
|
viewShortcut->associateAction(mViewAction);
|
||||||
|
@ -417,7 +417,7 @@ CSVWorld::Table::Table(const CSMWorld::UniversalId& id, bool createAndDelete, bo
|
||||||
|
|
||||||
mHelpAction = new QAction(tr("Help"), this);
|
mHelpAction = new QAction(tr("Help"), this);
|
||||||
connect(mHelpAction, &QAction::triggered, this, &Table::openHelp);
|
connect(mHelpAction, &QAction::triggered, this, &Table::openHelp);
|
||||||
mHelpAction->setIcon(QIcon(":/info.png"));
|
mHelpAction->setIcon(QIcon(":info"));
|
||||||
addAction(mHelpAction);
|
addAction(mHelpAction);
|
||||||
CSMPrefs::Shortcut* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
CSMPrefs::Shortcut* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
||||||
openHelpShortcut->associateAction(mHelpAction);
|
openHelpShortcut->associateAction(mHelpAction);
|
||||||
|
|
|
@ -149,39 +149,36 @@ namespace CSMWorld
|
||||||
Params{ UniversalId(UniversalId::Type_None), UniversalId::Type_None, UniversalId::Class_None,
|
Params{ UniversalId(UniversalId::Type_None), UniversalId::Type_None, UniversalId::Class_None,
|
||||||
UniversalId::ArgumentType_None, "-", "-", ":placeholder" },
|
UniversalId::ArgumentType_None, "-", "-", ":placeholder" },
|
||||||
Params{ UniversalId(UniversalId::Type_RegionMap), UniversalId::Type_RegionMap, UniversalId::Class_NonRecord,
|
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,
|
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,
|
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,
|
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,
|
Params{ UniversalId(UniversalId::Type_Activator, "a"), UniversalId::Type_Activator,
|
||||||
UniversalId::Class_RefRecord, UniversalId::ArgumentType_Id, "Activator", "Activator: a",
|
UniversalId::Class_RefRecord, UniversalId::ArgumentType_Id, "Activator", "Activator: a", ":activator" },
|
||||||
":./activator.png" },
|
|
||||||
Params{ UniversalId(UniversalId::Type_Gmst, "b"), UniversalId::Type_Gmst, UniversalId::Class_Record,
|
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,
|
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,
|
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,
|
Params{ UniversalId(UniversalId::Type_Reference, "e"), UniversalId::Type_Reference,
|
||||||
UniversalId::Class_SubRecord, UniversalId::ArgumentType_Id, "Instance", "Instance: e",
|
UniversalId::Class_SubRecord, UniversalId::ArgumentType_Id, "Instance", "Instance: e", ":instance" },
|
||||||
":./instance.png" },
|
|
||||||
|
|
||||||
Params{ UniversalId(UniversalId::Type_Search, 42), UniversalId::Type_Search, UniversalId::Class_Transient,
|
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,
|
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,
|
Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::stringRefId("g")), UniversalId::Type_Reference,
|
||||||
UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", "Instance: g",
|
UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", "Instance: g", ":instance" },
|
||||||
":./instance.png" },
|
|
||||||
Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::index(ESM::REC_SKIL, 42)),
|
Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::index(ESM::REC_SKIL, 42)),
|
||||||
UniversalId::Type_Reference, UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance",
|
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));
|
INSTANTIATE_TEST_SUITE_P(ValidParams, CSMWorldUniversalIdValidPerTypeTest, ValuesIn(validParams));
|
||||||
|
|
|
@ -30,16 +30,16 @@ namespace
|
||||||
{
|
{
|
||||||
bool matchesStaticFilters(const MWDialogue::SelectWrapper& select, const MWWorld::Ptr& actor)
|
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)
|
if (select.getFunction() == ESM::DialogueCondition::Function_NotId)
|
||||||
return actor.getCellRef().getRefId() != selectId;
|
return actor.getCellRef().getRefId() != selectId;
|
||||||
if (actor.getClass().isNpc())
|
if (actor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotFaction)
|
if (select.getFunction() == ESM::DialogueCondition::Function_NotFaction)
|
||||||
return actor.getClass().getPrimaryFaction(actor) != selectId;
|
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<ESM::NPC>()->mBase->mClass != selectId;
|
return actor.get<ESM::NPC>()->mBase->mClass != selectId;
|
||||||
else if (select.getFunction() == MWDialogue::SelectWrapper::Function_NotRace)
|
else if (select.getFunction() == ESM::DialogueCondition::Function_NotRace)
|
||||||
return actor.get<ESM::NPC>()->mBase->mRace != selectId;
|
return actor.get<ESM::NPC>()->mBase->mRace != selectId;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -47,7 +47,7 @@ namespace
|
||||||
|
|
||||||
bool matchesStaticFilters(const ESM::DialInfo& info, const MWWorld::Ptr& actor)
|
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;
|
MWDialogue::SelectWrapper wrapper = select;
|
||||||
if (wrapper.getType() == MWDialogue::SelectWrapper::Type_Boolean)
|
if (wrapper.getType() == MWDialogue::SelectWrapper::Type_Boolean)
|
||||||
|
@ -62,7 +62,7 @@ namespace
|
||||||
}
|
}
|
||||||
else if (wrapper.getType() == MWDialogue::SelectWrapper::Type_Numeric)
|
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);
|
const ESM::RefId& scriptName = actor.getClass().getScript(actor);
|
||||||
if (scriptName.empty())
|
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
|
bool MWDialogue::Filter::testSelectStructs(const ESM::DialInfo& info) const
|
||||||
{
|
{
|
||||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter(info.mSelects.begin());
|
for (const auto& select : info.mSelects)
|
||||||
iter != info.mSelects.end(); ++iter)
|
if (!testSelectStruct(select))
|
||||||
if (!testSelectStruct(*iter))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
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.
|
// If the actor is a creature, we pass all conditions only applicable to NPCs.
|
||||||
return true;
|
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.
|
// If not currently in a choice, we reject all conditions that test against choices.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (select.getFunction() == SelectWrapper::Function_Weather
|
if (select.getFunction() == ESM::DialogueCondition::Function_Weather
|
||||||
&& !(MWBase::Environment::get().getWorld()->isCellExterior()
|
&& !(MWBase::Environment::get().getWorld()->isCellExterior()
|
||||||
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior()))
|
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior()))
|
||||||
// Reject weather conditions in interior cells
|
// Reject weather conditions in interior cells
|
||||||
|
@ -305,29 +304,31 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co
|
||||||
{
|
{
|
||||||
switch (select.getFunction())
|
switch (select.getFunction())
|
||||||
{
|
{
|
||||||
case SelectWrapper::Function_Global:
|
case ESM::DialogueCondition::Function_Global:
|
||||||
|
|
||||||
// internally all globals are float :(
|
// internally all globals are float :(
|
||||||
return select.selectCompare(MWBase::Environment::get().getWorld()->getGlobalFloat(select.getName()));
|
return select.selectCompare(MWBase::Environment::get().getWorld()->getGlobalFloat(select.getName()));
|
||||||
|
|
||||||
case SelectWrapper::Function_Local:
|
case ESM::DialogueCondition::Function_Local:
|
||||||
{
|
{
|
||||||
return testFunctionLocal(select);
|
return testFunctionLocal(select);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_NotLocal:
|
case ESM::DialogueCondition::Function_NotLocal:
|
||||||
{
|
{
|
||||||
return !testFunctionLocal(select);
|
return !testFunctionLocal(select);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcHealthPercent:
|
case ESM::DialogueCondition::Function_PcHealthPercent:
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
return select.selectCompare(
|
return select.selectCompare(
|
||||||
static_cast<int>(player.getClass().getCreatureStats(player).getHealth().getRatio() * 100));
|
static_cast<int>(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();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
|
||||||
|
@ -336,7 +337,7 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co
|
||||||
return select.selectCompare(value);
|
return select.selectCompare(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_HealthPercent:
|
case ESM::DialogueCondition::Function_Health_Percent:
|
||||||
{
|
{
|
||||||
return select.selectCompare(
|
return select.selectCompare(
|
||||||
static_cast<int>(mActor.getClass().getCreatureStats(mActor).getHealth().getRatio() * 100));
|
static_cast<int>(mActor.getClass().getCreatureStats(mActor).getHealth().getRatio() * 100));
|
||||||
|
@ -354,27 +355,29 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
|
|
||||||
switch (select.getFunction())
|
switch (select.getFunction())
|
||||||
{
|
{
|
||||||
case SelectWrapper::Function_Journal:
|
case ESM::DialogueCondition::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:
|
case ESM::DialogueCondition::Function_Item:
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||||
|
|
||||||
return store.count(ESM::RefId::stringRefId(select.getName()));
|
return store.count(select.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_Dead:
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->countDeaths(
|
return MWBase::Environment::get().getMechanicsManager()->countDeaths(select.getId());
|
||||||
ESM::RefId::stringRefId(select.getName()));
|
|
||||||
|
|
||||||
case SelectWrapper::Function_Choice:
|
case ESM::DialogueCondition::Function_Choice:
|
||||||
|
|
||||||
return mChoice;
|
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();
|
int argument = select.getArgument();
|
||||||
if (argument < 0 || argument > 3)
|
if (argument < 0 || argument > 3)
|
||||||
|
@ -387,32 +390,65 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
.getAiSetting(static_cast<MWMechanics::AiSetting>(argument))
|
.getAiSetting(static_cast<MWMechanics::AiSetting>(argument))
|
||||||
.getModified(false);
|
.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());
|
ESM::RefId attribute = ESM::Attribute::indexToRefId(select.getArgument());
|
||||||
return player.getClass().getCreatureStats(player).getAttribute(attribute).getModified();
|
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());
|
ESM::RefId skill = ESM::Skill::indexToRefId(select.getArgument());
|
||||||
return static_cast<int>(player.getClass().getNpcStats(player).getSkill(skill).getModified());
|
return static_cast<int>(player.getClass().getNpcStats(player).getSkill(skill).getModified());
|
||||||
}
|
}
|
||||||
case SelectWrapper::Function_FriendlyHit:
|
case ESM::DialogueCondition::Function_FriendHit:
|
||||||
{
|
{
|
||||||
int hits = mActor.getClass().getCreatureStats(mActor).getFriendlyHits();
|
int hits = mActor.getClass().getCreatureStats(mActor).getFriendlyHits();
|
||||||
|
|
||||||
return hits > 4 ? 4 : hits;
|
return hits > 4 ? 4 : hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcLevel:
|
case ESM::DialogueCondition::Function_PcLevel:
|
||||||
|
|
||||||
return player.getClass().getCreatureStats(player).getLevel();
|
return player.getClass().getCreatureStats(player).getLevel();
|
||||||
|
|
||||||
case SelectWrapper::Function_PcGender:
|
case ESM::DialogueCondition::Function_PcGender:
|
||||||
|
|
||||||
return player.get<ESM::NPC>()->mBase->isMale() ? 0 : 1;
|
return player.get<ESM::NPC>()->mBase->isMale() ? 0 : 1;
|
||||||
|
|
||||||
case SelectWrapper::Function_PcClothingModifier:
|
case ESM::DialogueCondition::Function_PcClothingModifier:
|
||||||
{
|
{
|
||||||
const MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
const MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
|
||||||
|
@ -429,11 +465,11 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcCrimeLevel:
|
case ESM::DialogueCondition::Function_PcCrimeLevel:
|
||||||
|
|
||||||
return player.getClass().getNpcStats(player).getBounty();
|
return player.getClass().getNpcStats(player).getBounty();
|
||||||
|
|
||||||
case SelectWrapper::Function_RankRequirement:
|
case ESM::DialogueCondition::Function_RankRequirement:
|
||||||
{
|
{
|
||||||
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||||
if (faction.empty())
|
if (faction.empty())
|
||||||
|
@ -455,23 +491,23 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_Level:
|
case ESM::DialogueCondition::Function_Level:
|
||||||
|
|
||||||
return mActor.getClass().getCreatureStats(mActor).getLevel();
|
return mActor.getClass().getCreatureStats(mActor).getLevel();
|
||||||
|
|
||||||
case SelectWrapper::Function_PCReputation:
|
case ESM::DialogueCondition::Function_PcReputation:
|
||||||
|
|
||||||
return player.getClass().getNpcStats(player).getReputation();
|
return player.getClass().getNpcStats(player).getReputation();
|
||||||
|
|
||||||
case SelectWrapper::Function_Weather:
|
case ESM::DialogueCondition::Function_Weather:
|
||||||
|
|
||||||
return MWBase::Environment::get().getWorld()->getCurrentWeather();
|
return MWBase::Environment::get().getWorld()->getCurrentWeather();
|
||||||
|
|
||||||
case SelectWrapper::Function_Reputation:
|
case ESM::DialogueCondition::Function_Reputation:
|
||||||
|
|
||||||
return mActor.getClass().getNpcStats(mActor).getReputation();
|
return mActor.getClass().getNpcStats(mActor).getReputation();
|
||||||
|
|
||||||
case SelectWrapper::Function_FactionRankDiff:
|
case ESM::DialogueCondition::Function_FactionRankDifference:
|
||||||
{
|
{
|
||||||
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||||
|
|
||||||
|
@ -483,14 +519,14 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
return rank - npcRank;
|
return rank - npcRank;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_WerewolfKills:
|
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
||||||
|
|
||||||
return player.getClass().getNpcStats(player).getWerewolfKills();
|
return player.getClass().getNpcStats(player).getWerewolfKills();
|
||||||
|
|
||||||
case SelectWrapper::Function_RankLow:
|
case ESM::DialogueCondition::Function_FacReactionLowest:
|
||||||
case SelectWrapper::Function_RankHigh:
|
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);
|
const ESM::RefId& factionId = mActor.getClass().getPrimaryFaction(mActor);
|
||||||
|
|
||||||
|
@ -513,7 +549,7 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_CreatureTargetted:
|
case ESM::DialogueCondition::Function_CreatureTarget:
|
||||||
|
|
||||||
{
|
{
|
||||||
MWWorld::Ptr target;
|
MWWorld::Ptr target;
|
||||||
|
@ -540,53 +576,49 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
|
|
||||||
switch (select.getFunction())
|
switch (select.getFunction())
|
||||||
{
|
{
|
||||||
case SelectWrapper::Function_False:
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
|
|
||||||
return false;
|
return mActor.getCellRef().getRefId() != select.getId();
|
||||||
|
|
||||||
case SelectWrapper::Function_NotId:
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
|
|
||||||
return !(mActor.getCellRef().getRefId() == ESM::RefId::stringRefId(select.getName()));
|
return mActor.getClass().getPrimaryFaction(mActor) != select.getId();
|
||||||
|
|
||||||
case SelectWrapper::Function_NotFaction:
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
|
|
||||||
return !(mActor.getClass().getPrimaryFaction(mActor) == ESM::RefId::stringRefId(select.getName()));
|
return mActor.get<ESM::NPC>()->mBase->mClass != select.getId();
|
||||||
|
|
||||||
case SelectWrapper::Function_NotClass:
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
|
|
||||||
return !(mActor.get<ESM::NPC>()->mBase->mClass == ESM::RefId::stringRefId(select.getName()));
|
return mActor.get<ESM::NPC>()->mBase->mRace != select.getId();
|
||||||
|
|
||||||
case SelectWrapper::Function_NotRace:
|
case ESM::DialogueCondition::Function_NotCell:
|
||||||
|
|
||||||
return !(mActor.get<ESM::NPC>()->mBase->mRace == ESM::RefId::stringRefId(select.getName()));
|
|
||||||
|
|
||||||
case SelectWrapper::Function_NotCell:
|
|
||||||
{
|
{
|
||||||
std::string_view actorCell = MWBase::Environment::get().getWorld()->getCellName(mActor.getCell());
|
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:
|
case ESM::DialogueCondition::Function_SameSex:
|
||||||
|
|
||||||
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)
|
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)
|
||||||
== (mActor.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female);
|
== (mActor.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female);
|
||||||
|
|
||||||
case SelectWrapper::Function_SameRace:
|
case ESM::DialogueCondition::Function_SameRace:
|
||||||
|
|
||||||
return mActor.get<ESM::NPC>()->mBase->mRace == player.get<ESM::NPC>()->mBase->mRace;
|
return mActor.get<ESM::NPC>()->mBase->mRace == player.get<ESM::NPC>()->mBase->mRace;
|
||||||
|
|
||||||
case SelectWrapper::Function_SameFaction:
|
case ESM::DialogueCondition::Function_SameFaction:
|
||||||
|
|
||||||
return player.getClass().getNpcStats(player).isInFaction(mActor.getClass().getPrimaryFaction(mActor));
|
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();
|
return player.getClass().getCreatureStats(player).hasCommonDisease();
|
||||||
|
|
||||||
case SelectWrapper::Function_PcBlightDisease:
|
case ESM::DialogueCondition::Function_PcBlightDisease:
|
||||||
|
|
||||||
return player.getClass().getCreatureStats(player).hasBlightDisease();
|
return player.getClass().getCreatureStats(player).hasBlightDisease();
|
||||||
|
|
||||||
case SelectWrapper::Function_PcCorprus:
|
case ESM::DialogueCondition::Function_PcCorprus:
|
||||||
|
|
||||||
return player.getClass()
|
return player.getClass()
|
||||||
.getCreatureStats(player)
|
.getCreatureStats(player)
|
||||||
|
@ -595,7 +627,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
!= 0;
|
!= 0;
|
||||||
|
|
||||||
case SelectWrapper::Function_PcExpelled:
|
case ESM::DialogueCondition::Function_PcExpelled:
|
||||||
{
|
{
|
||||||
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
const ESM::RefId& faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||||
|
|
||||||
|
@ -605,7 +637,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
return player.getClass().getNpcStats(player).getExpelled(faction);
|
return player.getClass().getNpcStats(player).getExpelled(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectWrapper::Function_PcVampire:
|
case ESM::DialogueCondition::Function_PcVampire:
|
||||||
|
|
||||||
return player.getClass()
|
return player.getClass()
|
||||||
.getCreatureStats(player)
|
.getCreatureStats(player)
|
||||||
|
@ -614,27 +646,27 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con
|
||||||
.getMagnitude()
|
.getMagnitude()
|
||||||
> 0;
|
> 0;
|
||||||
|
|
||||||
case SelectWrapper::Function_TalkedToPc:
|
case ESM::DialogueCondition::Function_TalkedToPc:
|
||||||
|
|
||||||
return mTalkedToPlayer;
|
return mTalkedToPlayer;
|
||||||
|
|
||||||
case SelectWrapper::Function_Alarmed:
|
case ESM::DialogueCondition::Function_Alarmed:
|
||||||
|
|
||||||
return mActor.getClass().getCreatureStats(mActor).isAlarmed();
|
return mActor.getClass().getCreatureStats(mActor).isAlarmed();
|
||||||
|
|
||||||
case SelectWrapper::Function_Detected:
|
case ESM::DialogueCondition::Function_Detected:
|
||||||
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, mActor);
|
return MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, mActor);
|
||||||
|
|
||||||
case SelectWrapper::Function_Attacked:
|
case ESM::DialogueCondition::Function_Attacked:
|
||||||
|
|
||||||
return mActor.getClass().getCreatureStats(mActor).getAttacked();
|
return mActor.getClass().getCreatureStats(mActor).getAttacked();
|
||||||
|
|
||||||
case SelectWrapper::Function_ShouldAttack:
|
case ESM::DialogueCondition::Function_ShouldAttack:
|
||||||
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor, MWMechanics::getPlayer());
|
return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor, MWMechanics::getPlayer());
|
||||||
|
|
||||||
case SelectWrapper::Function_Werewolf:
|
case ESM::DialogueCondition::Function_Werewolf:
|
||||||
|
|
||||||
return mActor.getClass().getNpcStats(mActor).isWerewolf();
|
return mActor.getClass().getNpcStats(mActor).isWerewolf();
|
||||||
|
|
||||||
|
|
|
@ -10,431 +10,264 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
bool selectCompareImp(char comp, T1 value1, T2 value2)
|
bool selectCompareImp(ESM::DialogueCondition::Comparison comp, T1 value1, T2 value2)
|
||||||
{
|
{
|
||||||
switch (comp)
|
switch (comp)
|
||||||
{
|
{
|
||||||
case '0':
|
case ESM::DialogueCondition::Comp_Eq:
|
||||||
return value1 == value2;
|
return value1 == value2;
|
||||||
case '1':
|
case ESM::DialogueCondition::Comp_Ne:
|
||||||
return value1 != value2;
|
return value1 != value2;
|
||||||
case '2':
|
case ESM::DialogueCondition::Comp_Gt:
|
||||||
return value1 > value2;
|
return value1 > value2;
|
||||||
case '3':
|
case ESM::DialogueCondition::Comp_Ge:
|
||||||
return value1 >= value2;
|
return value1 >= value2;
|
||||||
case '4':
|
case ESM::DialogueCondition::Comp_Ls:
|
||||||
return value1 < value2;
|
return value1 < value2;
|
||||||
case '5':
|
case ESM::DialogueCondition::Comp_Le:
|
||||||
return value1 <= value2;
|
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 <typename T>
|
template <typename T>
|
||||||
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 std::visit(
|
||||||
{
|
[&](auto value) { return selectCompareImp(select.mComparison, value1, value); }, select.mValue);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const
|
MWDialogue::SelectWrapper::SelectWrapper(const ESM::DialogueCondition& select)
|
||||||
{
|
|
||||||
const int index = Misc::StringUtils::toNumeric<int>(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)
|
|
||||||
: mSelect(select)
|
: mSelect(select)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() const
|
ESM::DialogueCondition::Function MWDialogue::SelectWrapper::getFunction() const
|
||||||
{
|
{
|
||||||
char type = mSelect.mSelectRule[1];
|
return mSelect.mFunction;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWDialogue::SelectWrapper::getArgument() const
|
int MWDialogue::SelectWrapper::getArgument() const
|
||||||
{
|
{
|
||||||
if (mSelect.mSelectRule[1] != '1')
|
switch (mSelect.mFunction)
|
||||||
return 0;
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
std::istringstream(mSelect.mSelectRule.substr(2, 2)) >> index;
|
|
||||||
|
|
||||||
switch (index)
|
|
||||||
{
|
{
|
||||||
// AI settings
|
// AI settings
|
||||||
case 67:
|
case ESM::DialogueCondition::Function_Fight:
|
||||||
return 1;
|
return 1;
|
||||||
case 68:
|
case ESM::DialogueCondition::Function_Hello:
|
||||||
return 0;
|
return 0;
|
||||||
case 69:
|
case ESM::DialogueCondition::Function_Alarm:
|
||||||
return 3;
|
return 3;
|
||||||
case 70:
|
case ESM::DialogueCondition::Function_Flee:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
case 10:
|
case ESM::DialogueCondition::Function_PcStrength:
|
||||||
return 0;
|
return 0;
|
||||||
case 51:
|
case ESM::DialogueCondition::Function_PcIntelligence:
|
||||||
return 1;
|
return 1;
|
||||||
case 52:
|
case ESM::DialogueCondition::Function_PcWillpower:
|
||||||
return 2;
|
return 2;
|
||||||
case 53:
|
case ESM::DialogueCondition::Function_PcAgility:
|
||||||
return 3;
|
return 3;
|
||||||
case 54:
|
case ESM::DialogueCondition::Function_PcSpeed:
|
||||||
return 4;
|
return 4;
|
||||||
case 55:
|
case ESM::DialogueCondition::Function_PcEndurance:
|
||||||
return 5;
|
return 5;
|
||||||
case 56:
|
case ESM::DialogueCondition::Function_PcPersonality:
|
||||||
return 6;
|
return 6;
|
||||||
case 57:
|
case ESM::DialogueCondition::Function_PcLuck:
|
||||||
return 7;
|
return 7;
|
||||||
|
|
||||||
// skills
|
// skills
|
||||||
case 11:
|
case ESM::DialogueCondition::Function_PcBlock:
|
||||||
return 0;
|
return 0;
|
||||||
case 12:
|
case ESM::DialogueCondition::Function_PcArmorer:
|
||||||
return 1;
|
return 1;
|
||||||
case 13:
|
case ESM::DialogueCondition::Function_PcMediumArmor:
|
||||||
return 2;
|
return 2;
|
||||||
case 14:
|
case ESM::DialogueCondition::Function_PcHeavyArmor:
|
||||||
return 3;
|
return 3;
|
||||||
case 15:
|
case ESM::DialogueCondition::Function_PcBluntWeapon:
|
||||||
return 4;
|
return 4;
|
||||||
case 16:
|
case ESM::DialogueCondition::Function_PcLongBlade:
|
||||||
return 5;
|
return 5;
|
||||||
case 17:
|
case ESM::DialogueCondition::Function_PcAxe:
|
||||||
return 6;
|
return 6;
|
||||||
case 18:
|
case ESM::DialogueCondition::Function_PcSpear:
|
||||||
return 7;
|
return 7;
|
||||||
case 19:
|
case ESM::DialogueCondition::Function_PcAthletics:
|
||||||
return 8;
|
return 8;
|
||||||
case 20:
|
case ESM::DialogueCondition::Function_PcEnchant:
|
||||||
return 9;
|
return 9;
|
||||||
case 21:
|
case ESM::DialogueCondition::Function_PcDestruction:
|
||||||
return 10;
|
return 10;
|
||||||
case 22:
|
case ESM::DialogueCondition::Function_PcAlteration:
|
||||||
return 11;
|
return 11;
|
||||||
case 23:
|
case ESM::DialogueCondition::Function_PcIllusion:
|
||||||
return 12;
|
return 12;
|
||||||
case 24:
|
case ESM::DialogueCondition::Function_PcConjuration:
|
||||||
return 13;
|
return 13;
|
||||||
case 25:
|
case ESM::DialogueCondition::Function_PcMysticism:
|
||||||
return 14;
|
return 14;
|
||||||
case 26:
|
case ESM::DialogueCondition::Function_PcRestoration:
|
||||||
return 15;
|
return 15;
|
||||||
case 27:
|
case ESM::DialogueCondition::Function_PcAlchemy:
|
||||||
return 16;
|
return 16;
|
||||||
case 28:
|
case ESM::DialogueCondition::Function_PcUnarmored:
|
||||||
return 17;
|
return 17;
|
||||||
case 29:
|
case ESM::DialogueCondition::Function_PcSecurity:
|
||||||
return 18;
|
return 18;
|
||||||
case 30:
|
case ESM::DialogueCondition::Function_PcSneak:
|
||||||
return 19;
|
return 19;
|
||||||
case 31:
|
case ESM::DialogueCondition::Function_PcAcrobatics:
|
||||||
return 20;
|
return 20;
|
||||||
case 32:
|
case ESM::DialogueCondition::Function_PcLightArmor:
|
||||||
return 21;
|
return 21;
|
||||||
case 33:
|
case ESM::DialogueCondition::Function_PcShortBlade:
|
||||||
return 22;
|
return 22;
|
||||||
case 34:
|
case ESM::DialogueCondition::Function_PcMarksman:
|
||||||
return 23;
|
return 23;
|
||||||
case 35:
|
case ESM::DialogueCondition::Function_PcMerchantile:
|
||||||
return 24;
|
return 24;
|
||||||
case 36:
|
case ESM::DialogueCondition::Function_PcSpeechcraft:
|
||||||
return 25;
|
return 25;
|
||||||
case 37:
|
case ESM::DialogueCondition::Function_PcHandToHand:
|
||||||
return 26;
|
return 26;
|
||||||
|
|
||||||
// dynamic stats
|
// dynamic stats
|
||||||
case 8:
|
case ESM::DialogueCondition::Function_PcMagicka:
|
||||||
return 1;
|
return 1;
|
||||||
case 9:
|
case ESM::DialogueCondition::Function_PcFatigue:
|
||||||
return 2;
|
return 2;
|
||||||
case 64:
|
case ESM::DialogueCondition::Function_PcHealth:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
|
MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
|
||||||
{
|
{
|
||||||
static const Function integerFunctions[] = {
|
switch (mSelect.mFunction)
|
||||||
Function_Journal,
|
{
|
||||||
Function_Item,
|
case ESM::DialogueCondition::Function_Journal:
|
||||||
Function_Dead,
|
case ESM::DialogueCondition::Function_Item:
|
||||||
Function_Choice,
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
Function_AiSetting,
|
case ESM::DialogueCondition::Function_Choice:
|
||||||
Function_PcAttribute,
|
case ESM::DialogueCondition::Function_Fight:
|
||||||
Function_PcSkill,
|
case ESM::DialogueCondition::Function_Hello:
|
||||||
Function_FriendlyHit,
|
case ESM::DialogueCondition::Function_Alarm:
|
||||||
Function_PcLevel,
|
case ESM::DialogueCondition::Function_Flee:
|
||||||
Function_PcGender,
|
case ESM::DialogueCondition::Function_PcStrength:
|
||||||
Function_PcClothingModifier,
|
case ESM::DialogueCondition::Function_PcIntelligence:
|
||||||
Function_PcCrimeLevel,
|
case ESM::DialogueCondition::Function_PcWillpower:
|
||||||
Function_RankRequirement,
|
case ESM::DialogueCondition::Function_PcAgility:
|
||||||
Function_Level,
|
case ESM::DialogueCondition::Function_PcSpeed:
|
||||||
Function_PCReputation,
|
case ESM::DialogueCondition::Function_PcEndurance:
|
||||||
Function_Weather,
|
case ESM::DialogueCondition::Function_PcPersonality:
|
||||||
Function_Reputation,
|
case ESM::DialogueCondition::Function_PcLuck:
|
||||||
Function_FactionRankDiff,
|
case ESM::DialogueCondition::Function_PcBlock:
|
||||||
Function_WerewolfKills,
|
case ESM::DialogueCondition::Function_PcArmorer:
|
||||||
Function_RankLow,
|
case ESM::DialogueCondition::Function_PcMediumArmor:
|
||||||
Function_RankHigh,
|
case ESM::DialogueCondition::Function_PcHeavyArmor:
|
||||||
Function_CreatureTargetted,
|
case ESM::DialogueCondition::Function_PcBluntWeapon:
|
||||||
// end marker
|
case ESM::DialogueCondition::Function_PcLongBlade:
|
||||||
Function_None,
|
case ESM::DialogueCondition::Function_PcAxe:
|
||||||
};
|
case ESM::DialogueCondition::Function_PcSpear:
|
||||||
|
case ESM::DialogueCondition::Function_PcAthletics:
|
||||||
static const Function numericFunctions[] = {
|
case ESM::DialogueCondition::Function_PcEnchant:
|
||||||
Function_Global,
|
case ESM::DialogueCondition::Function_PcDestruction:
|
||||||
Function_Local,
|
case ESM::DialogueCondition::Function_PcAlteration:
|
||||||
Function_NotLocal,
|
case ESM::DialogueCondition::Function_PcIllusion:
|
||||||
Function_PcDynamicStat,
|
case ESM::DialogueCondition::Function_PcConjuration:
|
||||||
Function_PcHealthPercent,
|
case ESM::DialogueCondition::Function_PcMysticism:
|
||||||
Function_HealthPercent,
|
case ESM::DialogueCondition::Function_PcRestoration:
|
||||||
// end marker
|
case ESM::DialogueCondition::Function_PcAlchemy:
|
||||||
Function_None,
|
case ESM::DialogueCondition::Function_PcUnarmored:
|
||||||
};
|
case ESM::DialogueCondition::Function_PcSecurity:
|
||||||
|
case ESM::DialogueCondition::Function_PcSneak:
|
||||||
static const Function booleanFunctions[] = {
|
case ESM::DialogueCondition::Function_PcAcrobatics:
|
||||||
Function_False,
|
case ESM::DialogueCondition::Function_PcLightArmor:
|
||||||
Function_SameGender,
|
case ESM::DialogueCondition::Function_PcShortBlade:
|
||||||
Function_SameRace,
|
case ESM::DialogueCondition::Function_PcMarksman:
|
||||||
Function_SameFaction,
|
case ESM::DialogueCondition::Function_PcMerchantile:
|
||||||
Function_PcCommonDisease,
|
case ESM::DialogueCondition::Function_PcSpeechcraft:
|
||||||
Function_PcBlightDisease,
|
case ESM::DialogueCondition::Function_PcHandToHand:
|
||||||
Function_PcCorprus,
|
case ESM::DialogueCondition::Function_FriendHit:
|
||||||
Function_PcExpelled,
|
case ESM::DialogueCondition::Function_PcLevel:
|
||||||
Function_PcVampire,
|
case ESM::DialogueCondition::Function_PcGender:
|
||||||
Function_TalkedToPc,
|
case ESM::DialogueCondition::Function_PcClothingModifier:
|
||||||
Function_Alarmed,
|
case ESM::DialogueCondition::Function_PcCrimeLevel:
|
||||||
Function_Detected,
|
case ESM::DialogueCondition::Function_RankRequirement:
|
||||||
Function_Attacked,
|
case ESM::DialogueCondition::Function_Level:
|
||||||
Function_ShouldAttack,
|
case ESM::DialogueCondition::Function_PcReputation:
|
||||||
Function_Werewolf,
|
case ESM::DialogueCondition::Function_Weather:
|
||||||
// end marker
|
case ESM::DialogueCondition::Function_Reputation:
|
||||||
Function_None,
|
case ESM::DialogueCondition::Function_FactionRankDifference:
|
||||||
};
|
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
||||||
|
case ESM::DialogueCondition::Function_FacReactionLowest:
|
||||||
static const Function invertedBooleanFunctions[] = {
|
case ESM::DialogueCondition::Function_FacReactionHighest:
|
||||||
Function_NotId,
|
case ESM::DialogueCondition::Function_CreatureTarget:
|
||||||
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)
|
|
||||||
return Type_Integer;
|
return Type_Integer;
|
||||||
|
case ESM::DialogueCondition::Function_Global:
|
||||||
for (int i = 0; numericFunctions[i] != Function_None; ++i)
|
case ESM::DialogueCondition::Function_Local:
|
||||||
if (numericFunctions[i] == function)
|
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;
|
return Type_Numeric;
|
||||||
|
case ESM::DialogueCondition::Function_SameSex:
|
||||||
for (int i = 0; booleanFunctions[i] != Function_None; ++i)
|
case ESM::DialogueCondition::Function_SameRace:
|
||||||
if (booleanFunctions[i] == function)
|
case ESM::DialogueCondition::Function_SameFaction:
|
||||||
|
case ESM::DialogueCondition::Function_PcCommonDisease:
|
||||||
|
case ESM::DialogueCondition::Function_PcBlightDisease:
|
||||||
|
case ESM::DialogueCondition::Function_PcCorprus:
|
||||||
|
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;
|
return Type_Boolean;
|
||||||
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
for (int i = 0; invertedBooleanFunctions[i] != Function_None; ++i)
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
if (invertedBooleanFunctions[i] == function)
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
|
case ESM::DialogueCondition::Function_NotCell:
|
||||||
return Type_Inverted;
|
return Type_Inverted;
|
||||||
|
default:
|
||||||
return Type_None;
|
return Type_None;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWDialogue::SelectWrapper::isNpcOnly() const
|
bool MWDialogue::SelectWrapper::isNpcOnly() const
|
||||||
{
|
{
|
||||||
static const Function functions[] = {
|
switch (mSelect.mFunction)
|
||||||
Function_NotFaction,
|
{
|
||||||
Function_NotClass,
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
Function_NotRace,
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
Function_SameGender,
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
Function_SameRace,
|
case ESM::DialogueCondition::Function_SameSex:
|
||||||
Function_SameFaction,
|
case ESM::DialogueCondition::Function_SameRace:
|
||||||
Function_RankRequirement,
|
case ESM::DialogueCondition::Function_SameFaction:
|
||||||
Function_Reputation,
|
case ESM::DialogueCondition::Function_RankRequirement:
|
||||||
Function_FactionRankDiff,
|
case ESM::DialogueCondition::Function_Reputation:
|
||||||
Function_Werewolf,
|
case ESM::DialogueCondition::Function_FactionRankDifference:
|
||||||
Function_WerewolfKills,
|
case ESM::DialogueCondition::Function_Werewolf:
|
||||||
Function_RankLow,
|
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
||||||
Function_RankHigh,
|
case ESM::DialogueCondition::Function_FacReactionLowest:
|
||||||
// end marker
|
case ESM::DialogueCondition::Function_FacReactionHighest:
|
||||||
Function_None,
|
|
||||||
};
|
|
||||||
|
|
||||||
Function function = getFunction();
|
|
||||||
|
|
||||||
for (int i = 0; functions[i] != Function_None; ++i)
|
|
||||||
if (functions[i] == function)
|
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MWDialogue::SelectWrapper::selectCompare(int value) const
|
bool MWDialogue::SelectWrapper::selectCompare(int value) const
|
||||||
|
@ -454,5 +287,15 @@ bool MWDialogue::SelectWrapper::selectCompare(bool value) const
|
||||||
|
|
||||||
std::string MWDialogue::SelectWrapper::getName() const
|
std::string MWDialogue::SelectWrapper::getName() const
|
||||||
{
|
{
|
||||||
return Misc::StringUtils::lowerCase(std::string_view(mSelect.mSelectRule).substr(5));
|
return Misc::StringUtils::lowerCase(mSelect.mVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view MWDialogue::SelectWrapper::getCellName() const
|
||||||
|
{
|
||||||
|
return mSelect.mVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::RefId MWDialogue::SelectWrapper::getId() const
|
||||||
|
{
|
||||||
|
return ESM::RefId::stringRefId(mSelect.mVariable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,62 +7,9 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
class SelectWrapper
|
class SelectWrapper
|
||||||
{
|
{
|
||||||
const ESM::DialInfo::SelectStruct& mSelect;
|
const ESM::DialogueCondition& mSelect;
|
||||||
|
|
||||||
public:
|
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
|
enum Type
|
||||||
{
|
{
|
||||||
Type_None,
|
Type_None,
|
||||||
|
@ -72,13 +19,10 @@ namespace MWDialogue
|
||||||
Type_Inverted
|
Type_Inverted
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
Function decodeFunction() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelectWrapper(const ESM::DialInfo::SelectStruct& select);
|
SelectWrapper(const ESM::DialogueCondition& select);
|
||||||
|
|
||||||
Function getFunction() const;
|
ESM::DialogueCondition::Function getFunction() const;
|
||||||
|
|
||||||
int getArgument() const;
|
int getArgument() const;
|
||||||
|
|
||||||
|
@ -95,6 +39,10 @@ namespace MWDialogue
|
||||||
|
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
///< Return case-smashed name.
|
///< Return case-smashed name.
|
||||||
|
|
||||||
|
std::string_view getCellName() const;
|
||||||
|
|
||||||
|
ESM::RefId getId() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,41 @@
|
||||||
#include "ffmpeg_decoder.hpp"
|
#include "ffmpeg_decoder.hpp"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
namespace MWSound
|
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)
|
int FFmpeg_Decoder::readPacket(void* user_data, uint8_t* buf, int buf_size)
|
||||||
{
|
{
|
||||||
|
@ -75,7 +101,7 @@ namespace MWSound
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::ptrdiff_t stream_idx = mStream - mFormatCtx->streams;
|
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 */
|
/* Check if the packet belongs to this stream */
|
||||||
if (stream_idx == mPacket.stream_index)
|
if (stream_idx == mPacket.stream_index)
|
||||||
|
@ -102,12 +128,12 @@ namespace MWSound
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Decode some data, and check for errors */
|
/* 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 (ret == AVERROR(EAGAIN))
|
||||||
{
|
{
|
||||||
if (mPacket.size == 0 && !getNextPacket())
|
if (mPacket.size == 0 && !getNextPacket())
|
||||||
return false;
|
return false;
|
||||||
ret = avcodec_send_packet(mCodecCtx, &mPacket);
|
ret = avcodec_send_packet(mCodecCtx.get(), &mPacket);
|
||||||
av_packet_unref(&mPacket);
|
av_packet_unref(&mPacket);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -187,137 +213,95 @@ namespace MWSound
|
||||||
close();
|
close();
|
||||||
mDataStream = mResourceMgr->get(fname);
|
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");
|
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 (formatCtxPtr->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||||
if (!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), nullptr, nullptr) != 0)
|
|
||||||
{
|
{
|
||||||
// "Note that a user-supplied AVFormatContext will be freed on failure".
|
stream = &formatCtxPtr->streams[j];
|
||||||
if (mFormatCtx)
|
break;
|
||||||
{
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (avformat_find_stream_info(mFormatCtx, nullptr) < 0)
|
if (stream == nullptr)
|
||||||
throw std::runtime_error("Failed to find stream info in " + fname);
|
throw std::runtime_error("No audio streams");
|
||||||
|
|
||||||
for (size_t j = 0; j < mFormatCtx->nb_streams; j++)
|
const AVCodec* codec = avcodec_find_decoder((*stream)->codecpar->codec_id);
|
||||||
{
|
if (codec == nullptr)
|
||||||
if (mFormatCtx->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
throw std::runtime_error("No codec found for id " + std::to_string((*stream)->codecpar->codec_id));
|
||||||
{
|
|
||||||
mStream = &mFormatCtx->streams[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!mStream)
|
|
||||||
throw std::runtime_error("No audio streams in " + fname);
|
|
||||||
|
|
||||||
const AVCodec* codec = avcodec_find_decoder((*mStream)->codecpar->codec_id);
|
AVCodecContext* codecCtx = avcodec_alloc_context3(codec);
|
||||||
if (!codec)
|
if (codecCtx == nullptr)
|
||||||
{
|
throw std::runtime_error("Failed to allocate codec context");
|
||||||
std::string ss = "No codec found for id " + std::to_string((*mStream)->codecpar->codec_id);
|
|
||||||
throw std::runtime_error(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
AVCodecContext* avctx = avcodec_alloc_context3(codec);
|
avcodec_parameters_to_context(codecCtx, (*stream)->codecpar);
|
||||||
avcodec_parameters_to_context(avctx, (*mStream)->codecpar);
|
|
||||||
|
|
||||||
// This is not needed anymore above FFMpeg version 4.0
|
// This is not needed anymore above FFMpeg version 4.0
|
||||||
#if LIBAVCODEC_VERSION_INT < 3805796
|
#if LIBAVCODEC_VERSION_INT < 3805796
|
||||||
av_codec_set_pkt_timebase(avctx, (*mStream)->time_base);
|
av_codec_set_pkt_timebase(avctx, (*stream)->time_base);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mCodecCtx = avctx;
|
AVCodecContextPtr codecCtxPtr(std::exchange(codecCtx, nullptr));
|
||||||
|
|
||||||
if (avcodec_open2(mCodecCtx, codec, nullptr) < 0)
|
if (avcodec_open2(codecCtxPtr.get(), codec, nullptr) < 0)
|
||||||
throw std::runtime_error(std::string("Failed to open audio codec ") + codec->long_name);
|
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)
|
if (codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_U8P)
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_U8;
|
mOutputSampleFormat = AV_SAMPLE_FMT_U8;
|
||||||
// FIXME: Check for AL_EXT_FLOAT32 support
|
// FIXME: Check for AL_EXT_FLOAT32 support
|
||||||
// else if (mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
// else if (codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_FLT || codecCtxPtr->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
||||||
// mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
// mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
else
|
else
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
|
|
||||||
mOutputChannelLayout = (*mStream)->codecpar->channel_layout;
|
mOutputChannelLayout = (*stream)->codecpar->channel_layout;
|
||||||
if (mOutputChannelLayout == 0)
|
if (mOutputChannelLayout == 0)
|
||||||
mOutputChannelLayout = av_get_default_channel_layout(mCodecCtx->channels);
|
mOutputChannelLayout = av_get_default_channel_layout(codecCtxPtr->channels);
|
||||||
|
|
||||||
mCodecCtx->channel_layout = mOutputChannelLayout;
|
codecCtxPtr->channel_layout = mOutputChannelLayout;
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
if (mStream)
|
|
||||||
avcodec_free_context(&mCodecCtx);
|
|
||||||
mStream = nullptr;
|
|
||||||
|
|
||||||
if (mFormatCtx != nullptr)
|
mIoCtx = std::move(ioCtx);
|
||||||
{
|
mFrame = std::move(frame);
|
||||||
if (mFormatCtx->pb->buffer != nullptr)
|
mFormatCtx = std::move(formatCtxPtr);
|
||||||
{
|
mCodecCtx = std::move(codecCtxPtr);
|
||||||
av_free(mFormatCtx->pb->buffer);
|
mStream = stream;
|
||||||
mFormatCtx->pb->buffer = nullptr;
|
|
||||||
}
|
|
||||||
av_free(mFormatCtx->pb);
|
|
||||||
mFormatCtx->pb = nullptr;
|
|
||||||
|
|
||||||
avformat_close_input(&mFormatCtx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpeg_Decoder::close()
|
void FFmpeg_Decoder::close()
|
||||||
{
|
{
|
||||||
if (mStream)
|
|
||||||
avcodec_free_context(&mCodecCtx);
|
|
||||||
mStream = nullptr;
|
mStream = nullptr;
|
||||||
|
mCodecCtx.reset();
|
||||||
|
|
||||||
av_packet_unref(&mPacket);
|
av_packet_unref(&mPacket);
|
||||||
av_freep(&mDataBuf);
|
av_freep(&mDataBuf);
|
||||||
av_frame_free(&mFrame);
|
mFrame.reset();
|
||||||
swr_free(&mSwr);
|
swr_free(&mSwr);
|
||||||
|
|
||||||
if (mFormatCtx)
|
mFormatCtx.reset();
|
||||||
{
|
mIoCtx.reset();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
mDataStream.reset();
|
mDataStream.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,10 +420,7 @@ namespace MWSound
|
||||||
|
|
||||||
FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs)
|
FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs)
|
||||||
: Sound_Decoder(vfs)
|
: Sound_Decoder(vfs)
|
||||||
, mFormatCtx(nullptr)
|
|
||||||
, mCodecCtx(nullptr)
|
|
||||||
, mStream(nullptr)
|
, mStream(nullptr)
|
||||||
, mFrame(nullptr)
|
|
||||||
, mFrameSize(0)
|
, mFrameSize(0)
|
||||||
, mFramePos(0)
|
, mFramePos(0)
|
||||||
, mNextPts(0.0)
|
, mNextPts(0.0)
|
||||||
|
@ -470,5 +451,4 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,43 @@ extern "C"
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
|
struct AVIOContextDeleter
|
||||||
|
{
|
||||||
|
void operator()(AVIOContext* ptr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AVIOContextPtr = std::unique_ptr<AVIOContext, AVIOContextDeleter>;
|
||||||
|
|
||||||
|
struct AVFormatContextDeleter
|
||||||
|
{
|
||||||
|
void operator()(AVFormatContext* ptr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AVFormatContextPtr = std::unique_ptr<AVFormatContext, AVFormatContextDeleter>;
|
||||||
|
|
||||||
|
struct AVCodecContextDeleter
|
||||||
|
{
|
||||||
|
void operator()(AVCodecContext* ptr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AVCodecContextPtr = std::unique_ptr<AVCodecContext, AVCodecContextDeleter>;
|
||||||
|
|
||||||
|
struct AVFrameDeleter
|
||||||
|
{
|
||||||
|
void operator()(AVFrame* ptr) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AVFramePtr = std::unique_ptr<AVFrame, AVFrameDeleter>;
|
||||||
|
|
||||||
class FFmpeg_Decoder final : public Sound_Decoder
|
class FFmpeg_Decoder final : public Sound_Decoder
|
||||||
{
|
{
|
||||||
AVFormatContext* mFormatCtx;
|
AVIOContextPtr mIoCtx;
|
||||||
AVCodecContext* mCodecCtx;
|
AVFormatContextPtr mFormatCtx;
|
||||||
|
AVCodecContextPtr mCodecCtx;
|
||||||
AVStream** mStream;
|
AVStream** mStream;
|
||||||
|
|
||||||
AVPacket mPacket;
|
AVPacket mPacket;
|
||||||
AVFrame* mFrame;
|
AVFramePtr mFrame;
|
||||||
|
|
||||||
std::size_t mFrameSize;
|
std::size_t mFrameSize;
|
||||||
std::size_t mFramePos;
|
std::size_t mFramePos;
|
||||||
|
|
|
@ -325,6 +325,7 @@ namespace MWWorld
|
||||||
player.mObject.mEnabled = true;
|
player.mObject.mEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorldModel()->deregisterLiveCellRef(mPlayer);
|
||||||
mPlayer.load(player.mObject);
|
mPlayer.load(player.mObject);
|
||||||
|
|
||||||
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
for (size_t i = 0; i < mSaveAttributes.size(); ++i)
|
||||||
|
|
|
@ -591,6 +591,12 @@ namespace MWWorld
|
||||||
// Must be cleared before mRendering is destroyed
|
// Must be cleared before mRendering is destroyed
|
||||||
if (mProjectileManager)
|
if (mProjectileManager)
|
||||||
mProjectileManager->clear();
|
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)
|
void World::setRandomSeed(uint32_t seed)
|
||||||
|
|
|
@ -267,7 +267,6 @@ namespace
|
||||||
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
updater.wait(WaitConditionType::allJobsDone, &mListener);
|
||||||
updater.stop();
|
updater.stop();
|
||||||
const std::set<TilePosition> present{
|
const std::set<TilePosition> present{
|
||||||
TilePosition(-2, 0),
|
|
||||||
TilePosition(-1, -1),
|
TilePosition(-1, -1),
|
||||||
TilePosition(-1, 0),
|
TilePosition(-1, 0),
|
||||||
TilePosition(-1, 1),
|
TilePosition(-1, 1),
|
||||||
|
@ -278,6 +277,7 @@ namespace
|
||||||
TilePosition(0, 2),
|
TilePosition(0, 2),
|
||||||
TilePosition(1, -1),
|
TilePosition(1, -1),
|
||||||
TilePosition(1, 0),
|
TilePosition(1, 0),
|
||||||
|
TilePosition(1, 1),
|
||||||
};
|
};
|
||||||
for (int x = -5; x <= 5; ++x)
|
for (int x = -5; x <= 5; ++x)
|
||||||
for (int y = -5; y <= 5; ++y)
|
for (int y = -5; y <= 5; ++y)
|
||||||
|
@ -336,4 +336,273 @@ namespace
|
||||||
EXPECT_EQ(tile->mTileId, 2);
|
EXPECT_EQ(tile->mTileId, 2);
|
||||||
EXPECT_EQ(tile->mVersion, navMeshFormatVersion);
|
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<GuardedNavMeshCacheItem>(1, mSettings);
|
||||||
|
|
||||||
|
std::map<TilePosition, ChangeType> 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<GuardedNavMeshCacheItem> mNavMeshCacheItemPtr;
|
||||||
|
const std::weak_ptr<GuardedNavMeshCacheItem> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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<Job> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<NavMeshDb>(":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
|
struct AddHeightfieldSurface
|
||||||
{
|
{
|
||||||
static constexpr std::size_t sSize = 65;
|
static constexpr std::size_t sSize = 65;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
#include <components/esm3/loadcont.hpp>
|
#include <components/esm3/loadcont.hpp>
|
||||||
#include <components/esm3/loaddial.hpp>
|
#include <components/esm3/loaddial.hpp>
|
||||||
|
#include <components/esm3/loadinfo.hpp>
|
||||||
#include <components/esm3/loadregn.hpp>
|
#include <components/esm3/loadregn.hpp>
|
||||||
#include <components/esm3/loadscpt.hpp>
|
#include <components/esm3/loadscpt.hpp>
|
||||||
#include <components/esm3/loadweap.hpp>
|
#include <components/esm3/loadweap.hpp>
|
||||||
|
@ -603,6 +604,83 @@ namespace ESM
|
||||||
EXPECT_EQ(result.mIcon, record.mIcon);
|
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()));
|
INSTANTIATE_TEST_SUITE_P(FormatVersions, Esm3SaveLoadRecordTest, ValuesIn(getFormats()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ add_component_dir (esm3
|
||||||
inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats
|
inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats
|
||||||
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||||
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
|
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
|
||||||
infoorder timestamp formatversion landrecorddata selectiongroup
|
infoorder timestamp formatversion landrecorddata selectiongroup dialoguecondition
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (esmterrain
|
add_component_dir (esmterrain
|
||||||
|
|
|
@ -61,6 +61,11 @@ namespace Debug
|
||||||
bool outRedirected = isRedirected(STD_OUTPUT_HANDLE);
|
bool outRedirected = isRedirected(STD_OUTPUT_HANDLE);
|
||||||
bool errRedirected = isRedirected(STD_ERROR_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))
|
if (AttachConsole(ATTACH_PARENT_PROCESS))
|
||||||
{
|
{
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -73,16 +78,19 @@ namespace Debug
|
||||||
{
|
{
|
||||||
_wfreopen(L"CON", L"r", stdin);
|
_wfreopen(L"CON", L"r", stdin);
|
||||||
freopen("CON", "r", stdin);
|
freopen("CON", "r", stdin);
|
||||||
|
std::cin.clear();
|
||||||
}
|
}
|
||||||
if (!outRedirected)
|
if (!outRedirected)
|
||||||
{
|
{
|
||||||
_wfreopen(L"CON", L"w", stdout);
|
_wfreopen(L"CON", L"w", stdout);
|
||||||
freopen("CON", "w", stdout);
|
freopen("CON", "w", stdout);
|
||||||
|
std::cout.clear();
|
||||||
}
|
}
|
||||||
if (!errRedirected)
|
if (!errRedirected)
|
||||||
{
|
{
|
||||||
_wfreopen(L"CON", L"w", stderr);
|
_wfreopen(L"CON", L"w", stderr);
|
||||||
freopen("CON", "w", stderr);
|
freopen("CON", "w", stderr);
|
||||||
|
std::cerr.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -256,9 +264,17 @@ namespace Debug
|
||||||
private:
|
private:
|
||||||
static bool useColoredOutput()
|
static bool useColoredOutput()
|
||||||
{
|
{
|
||||||
// Note: cmd.exe in Win10 should support ANSI colors, but in its own way.
|
|
||||||
#if defined(_WIN32)
|
#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
|
#else
|
||||||
char* term = getenv("TERM");
|
char* term = getenv("TERM");
|
||||||
bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr));
|
bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr));
|
||||||
|
|
|
@ -16,8 +16,9 @@
|
||||||
|
|
||||||
#include <osg/io_utils>
|
#include <osg/io_utils>
|
||||||
|
|
||||||
|
#include <boost/geometry.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -49,40 +50,6 @@ namespace DetourNavigator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getPriority(const Job& job) noexcept
|
|
||||||
{
|
|
||||||
return std::make_tuple(-static_cast<std::underlying_type_t<JobState>>(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<JobIt>& 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<std::underlying_type_t<JobState>>(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<JobIt>& queue)
|
|
||||||
{
|
|
||||||
const auto it = std::upper_bound(queue.begin(), queue.end(), job, LessByJobDbPriority{});
|
|
||||||
queue.insert(it, job);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getAgentAndTile(const Job& job) noexcept
|
auto getAgentAndTile(const Job& job) noexcept
|
||||||
{
|
{
|
||||||
return std::make_tuple(job.mAgentBounds, job.mChangedTile);
|
return std::make_tuple(job.mAgentBounds, job.mChangedTile);
|
||||||
|
@ -97,16 +64,6 @@ namespace DetourNavigator
|
||||||
settings.mRecast, settings.mWriteToNavMeshDb);
|
settings.mRecast, settings.mWriteToNavMeshDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateJobs(std::deque<JobIt>& 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()
|
std::size_t getNextJobId()
|
||||||
{
|
{
|
||||||
static std::atomic_size_t nextJobId{ 1 };
|
static std::atomic_size_t nextJobId{ 1 };
|
||||||
|
@ -134,7 +91,7 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
Job::Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> navMeshCacheItem,
|
Job::Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> 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)
|
std::chrono::steady_clock::time_point processTime)
|
||||||
: mId(getNextJobId())
|
: mId(getNextJobId())
|
||||||
, mAgentBounds(agentBounds)
|
, mAgentBounds(agentBounds)
|
||||||
|
@ -143,11 +100,148 @@ namespace DetourNavigator
|
||||||
, mChangedTile(changedTile)
|
, mChangedTile(changedTile)
|
||||||
, mProcessTime(processTime)
|
, mProcessTime(processTime)
|
||||||
, mChangeType(changeType)
|
, 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<JobIt>());
|
||||||
|
mIndex.insert(IndexValue(IndexPoint(job->mChangedTile.x(), job->mChangedTile.y()), it));
|
||||||
|
}
|
||||||
|
|
||||||
|
it->second.push_back(job);
|
||||||
|
|
||||||
|
++mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<JobIt> 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<JobIt>& 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<JobIt>& 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<JobIt> 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<JobIt> 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,
|
AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager,
|
||||||
OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr<NavMeshDb>&& db)
|
OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr<NavMeshDb>&& db)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
|
@ -180,48 +274,47 @@ namespace DetourNavigator
|
||||||
if (!playerTileChanged && changedTiles.empty())
|
if (!playerTileChanged && changedTiles.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int maxTiles
|
|
||||||
= std::min(mSettings.get().mMaxTilesNumber, navMeshCacheItem->lockConst()->getImpl().getParams()->maxTiles);
|
|
||||||
|
|
||||||
std::unique_lock lock(mMutex);
|
std::unique_lock lock(mMutex);
|
||||||
|
|
||||||
if (playerTileChanged)
|
if (playerTileChanged)
|
||||||
updateJobs(mWaiting, playerTile, maxTiles);
|
{
|
||||||
|
Log(Debug::Debug) << "Player tile has been changed to " << playerTile;
|
||||||
|
mWaiting.update(playerTile, mSettings.get().mMaxTilesNumber);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& [changedTile, changeType] : changedTiles)
|
for (const auto& [changedTile, changeType] : changedTiles)
|
||||||
{
|
{
|
||||||
if (mPushed.emplace(agentBounds, changedTile).second)
|
if (mPushed.emplace(agentBounds, changedTile).second)
|
||||||
{
|
{
|
||||||
const auto processTime = changeType == ChangeType::update
|
const auto processTime = [&, changedTile = changedTile, changeType = changeType] {
|
||||||
? mLastUpdates[std::tie(agentBounds, changedTile)] + mSettings.get().mMinUpdateInterval
|
if (changeType != ChangeType::update)
|
||||||
: std::chrono::steady_clock::time_point();
|
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,
|
const JobIt it = mJobs.emplace(
|
||||||
changeType, getManhattanDistance(changedTile, playerTile), processTime);
|
mJobs.end(), agentBounds, navMeshCacheItem, worldspace, changedTile, changeType, processTime);
|
||||||
|
|
||||||
Log(Debug::Debug) << "Post job " << it->mId << " for agent=(" << it->mAgentBounds << ")"
|
Log(Debug::Debug) << "Post job " << it->mId << " for agent=(" << it->mAgentBounds << ")"
|
||||||
<< " changedTile=(" << it->mChangedTile << ") "
|
<< " changedTile=(" << it->mChangedTile << ")"
|
||||||
<< " changeType=" << it->mChangeType;
|
<< " changeType=" << it->mChangeType;
|
||||||
|
|
||||||
if (playerTileChanged)
|
mWaiting.push(it);
|
||||||
mWaiting.push_back(it);
|
|
||||||
else
|
|
||||||
insertPrioritizedJob(it, mWaiting);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerTileChanged)
|
|
||||||
std::sort(mWaiting.begin(), mWaiting.end(), LessByJobPriority{});
|
|
||||||
|
|
||||||
Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs";
|
Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs";
|
||||||
|
|
||||||
if (!mWaiting.empty())
|
if (mWaiting.hasJob())
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
if (playerTileChanged && mDbWorker != nullptr)
|
if (playerTileChanged && mDbWorker != nullptr)
|
||||||
mDbWorker->updateJobs(playerTile, maxTiles);
|
mDbWorker->update(playerTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::wait(WaitConditionType waitConditionType, Loading::Listener* listener)
|
void AsyncNavMeshUpdater::wait(WaitConditionType waitConditionType, Loading::Listener* listener)
|
||||||
|
@ -313,7 +406,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::mutex> lock(mMutex);
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
result.mJobs = mJobs.size();
|
result.mJobs = mJobs.size();
|
||||||
result.mWaiting = mWaiting.size();
|
result.mWaiting = mWaiting.getStats();
|
||||||
result.mPushed = mPushed.size();
|
result.mPushed = mPushed.size();
|
||||||
}
|
}
|
||||||
result.mProcessing = mProcessingTiles.lockConst()->size();
|
result.mProcessing = mProcessingTiles.lockConst()->size();
|
||||||
|
@ -335,7 +428,8 @@ namespace DetourNavigator
|
||||||
if (JobIt job = getNextJob(); job != mJobs.end())
|
if (JobIt job = getNextJob(); job != mJobs.end())
|
||||||
{
|
{
|
||||||
const JobStatus status = processJob(*job);
|
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)
|
switch (status)
|
||||||
{
|
{
|
||||||
case JobStatus::Done:
|
case JobStatus::Done:
|
||||||
|
@ -346,7 +440,8 @@ namespace DetourNavigator
|
||||||
removeJob(job);
|
removeJob(job);
|
||||||
break;
|
break;
|
||||||
case JobStatus::Fail:
|
case JobStatus::Fail:
|
||||||
repost(job);
|
unlockTile(job->mId, job->mAgentBounds, job->mChangedTile);
|
||||||
|
removeJob(job);
|
||||||
break;
|
break;
|
||||||
case JobStatus::MemoryCacheMiss:
|
case JobStatus::MemoryCacheMiss:
|
||||||
{
|
{
|
||||||
|
@ -368,7 +463,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
JobStatus AsyncNavMeshUpdater::processJob(Job& job)
|
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();
|
const auto navMeshCacheItem = job.mNavMeshCacheItem.lock();
|
||||||
|
|
||||||
|
@ -376,12 +473,11 @@ namespace DetourNavigator
|
||||||
return JobStatus::Done;
|
return JobStatus::Done;
|
||||||
|
|
||||||
const auto playerTile = *mPlayerTile.lockConst();
|
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";
|
Log(Debug::Debug) << "Ignore add tile by job " << job.mId << ": too far from player";
|
||||||
|
job.mChangeType = ChangeType::remove;
|
||||||
navMeshCacheItem->lock()->removeTile(job.mChangedTile);
|
navMeshCacheItem->lock()->removeTile(job.mChangedTile);
|
||||||
return JobStatus::Done;
|
return JobStatus::Done;
|
||||||
}
|
}
|
||||||
|
@ -549,9 +645,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
bool shouldStop = false;
|
bool shouldStop = false;
|
||||||
const auto hasJob = [&] {
|
const auto hasJob = [&] {
|
||||||
shouldStop = mShouldStop;
|
shouldStop = mShouldStop.load();
|
||||||
return shouldStop
|
return shouldStop || mWaiting.hasJob();
|
||||||
|| (!mWaiting.empty() && mWaiting.front()->mProcessTime <= std::chrono::steady_clock::now());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob))
|
if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob))
|
||||||
|
@ -564,9 +659,15 @@ namespace DetourNavigator
|
||||||
if (shouldStop)
|
if (shouldStop)
|
||||||
return mJobs.end();
|
return mJobs.end();
|
||||||
|
|
||||||
const JobIt job = mWaiting.front();
|
const TilePosition playerTile = *mPlayerTile.lockConst();
|
||||||
|
|
||||||
mWaiting.pop_front();
|
JobIt job = mJobs.end();
|
||||||
|
|
||||||
|
if (const std::optional<JobIt> 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();
|
Log(Debug::Debug) << "Pop job " << job->mId << " by thread=" << std::this_thread::get_id();
|
||||||
|
|
||||||
|
@ -575,9 +676,9 @@ namespace DetourNavigator
|
||||||
|
|
||||||
if (!lockTile(job->mId, job->mAgentBounds, job->mChangedTile))
|
if (!lockTile(job->mId, job->mAgentBounds, job->mChangedTile))
|
||||||
{
|
{
|
||||||
Log(Debug::Debug) << "Failed to lock tile by job " << job->mId << " try=" << job->mTryNumber;
|
Log(Debug::Debug) << "Failed to lock tile by job " << job->mId;
|
||||||
++job->mTryNumber;
|
job->mProcessTime = std::chrono::steady_clock::now() + mSettings.get().mMinUpdateInterval;
|
||||||
insertPrioritizedJob(job, mWaiting);
|
mWaiting.push(job);
|
||||||
return mJobs.end();
|
return mJobs.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,26 +714,6 @@ namespace DetourNavigator
|
||||||
writeToFile(shared->lockConst()->getImpl(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
|
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<std::mutex> 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(
|
bool AsyncNavMeshUpdater::lockTile(
|
||||||
std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile)
|
std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile)
|
||||||
{
|
{
|
||||||
|
@ -677,7 +758,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
Log(Debug::Debug) << "Enqueueing job " << job->mId << " by thread=" << std::this_thread::get_id();
|
Log(Debug::Debug) << "Enqueueing job " << job->mId << " by thread=" << std::this_thread::get_id();
|
||||||
const std::lock_guard lock(mMutex);
|
const std::lock_guard lock(mMutex);
|
||||||
insertPrioritizedJob(job, mWaiting);
|
mWaiting.push(job);
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,40 +772,47 @@ namespace DetourNavigator
|
||||||
void DbJobQueue::push(JobIt job)
|
void DbJobQueue::push(JobIt job)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const std::lock_guard lock(mMutex);
|
||||||
insertPrioritizedDbJob(job, mJobs);
|
|
||||||
if (isWritingDbJob(*job))
|
if (isWritingDbJob(*job))
|
||||||
++mWritingJobs;
|
mWriting.push_back(job);
|
||||||
else
|
else
|
||||||
++mReadingJobs;
|
mReading.push(job);
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<JobIt> DbJobQueue::pop()
|
std::optional<JobIt> DbJobQueue::pop()
|
||||||
{
|
{
|
||||||
std::unique_lock lock(mMutex);
|
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;
|
return std::nullopt;
|
||||||
const JobIt job = mJobs.front();
|
|
||||||
mJobs.pop_front();
|
if (const std::optional<JobIt> job = mReading.pop(mPlayerTile))
|
||||||
if (isWritingDbJob(*job))
|
return job;
|
||||||
--mWritingJobs;
|
|
||||||
else
|
if (mWriting.empty())
|
||||||
--mReadingJobs;
|
return std::nullopt;
|
||||||
|
|
||||||
|
const JobIt job = mWriting.front();
|
||||||
|
mWriting.pop_front();
|
||||||
|
|
||||||
return job;
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbJobQueue::update(TilePosition playerTile, int maxTiles)
|
void DbJobQueue::update(TilePosition playerTile)
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const std::lock_guard lock(mMutex);
|
||||||
updateJobs(mJobs, playerTile, maxTiles);
|
mPlayerTile = playerTile;
|
||||||
std::sort(mJobs.begin(), mJobs.end(), LessByJobDbPriority{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbJobQueue::stop()
|
void DbJobQueue::stop()
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
const std::lock_guard lock(mMutex);
|
||||||
mJobs.clear();
|
mReading.clear();
|
||||||
|
mWriting.clear();
|
||||||
mShouldStop = true;
|
mShouldStop = true;
|
||||||
mHasJob.notify_all();
|
mHasJob.notify_all();
|
||||||
}
|
}
|
||||||
|
@ -732,7 +820,10 @@ namespace DetourNavigator
|
||||||
DbJobQueueStats DbJobQueue::getStats() const
|
DbJobQueueStats DbJobQueue::getStats() const
|
||||||
{
|
{
|
||||||
const std::lock_guard lock(mMutex);
|
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<NavMeshDb>&& db, TileVersion version,
|
DbWorker::DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db, TileVersion version,
|
||||||
|
@ -761,8 +852,10 @@ namespace DetourNavigator
|
||||||
|
|
||||||
DbWorkerStats DbWorker::getStats() const
|
DbWorkerStats DbWorker::getStats() const
|
||||||
{
|
{
|
||||||
return DbWorkerStats{ .mJobs = mQueue.getStats(),
|
return DbWorkerStats{
|
||||||
.mGetTileCount = mGetTileCount.load(std::memory_order_relaxed) };
|
.mJobs = mQueue.getStats(),
|
||||||
|
.mGetTileCount = mGetTileCount.load(std::memory_order_relaxed),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbWorker::stop()
|
void DbWorker::stop()
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "tileposition.hpp"
|
#include "tileposition.hpp"
|
||||||
#include "waitconditiontype.hpp"
|
#include "waitconditiontype.hpp"
|
||||||
|
|
||||||
|
#include <boost/geometry/geometries/point.hpp>
|
||||||
|
#include <boost/geometry/index/rtree.hpp>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
@ -49,11 +52,8 @@ namespace DetourNavigator
|
||||||
const std::weak_ptr<GuardedNavMeshCacheItem> mNavMeshCacheItem;
|
const std::weak_ptr<GuardedNavMeshCacheItem> mNavMeshCacheItem;
|
||||||
const std::string mWorldspace;
|
const std::string mWorldspace;
|
||||||
const TilePosition mChangedTile;
|
const TilePosition mChangedTile;
|
||||||
const std::chrono::steady_clock::time_point mProcessTime;
|
std::chrono::steady_clock::time_point mProcessTime;
|
||||||
unsigned mTryNumber = 0;
|
|
||||||
ChangeType mChangeType;
|
ChangeType mChangeType;
|
||||||
int mDistanceToPlayer;
|
|
||||||
const int mDistanceToOrigin;
|
|
||||||
JobState mState = JobState::Initial;
|
JobState mState = JobState::Initial;
|
||||||
std::vector<std::byte> mInput;
|
std::vector<std::byte> mInput;
|
||||||
std::shared_ptr<RecastMesh> mRecastMesh;
|
std::shared_ptr<RecastMesh> mRecastMesh;
|
||||||
|
@ -61,12 +61,65 @@ namespace DetourNavigator
|
||||||
std::unique_ptr<PreparedNavMeshData> mGeneratedNavMeshData;
|
std::unique_ptr<PreparedNavMeshData> mGeneratedNavMeshData;
|
||||||
|
|
||||||
Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> navMeshCacheItem,
|
Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> 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);
|
std::chrono::steady_clock::time_point processTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
using JobIt = std::list<Job>::iterator;
|
using JobIt = std::list<Job>::iterator;
|
||||||
|
|
||||||
|
class SpatialJobQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::size_t size() const { return mSize; }
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void push(JobIt job);
|
||||||
|
|
||||||
|
std::optional<JobIt> pop(TilePosition playerTile);
|
||||||
|
|
||||||
|
void update(TilePosition playerTile, int maxTiles, std::vector<JobIt>& removing);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using IndexPoint = boost::geometry::model::point<int, 2, boost::geometry::cs::cartesian>;
|
||||||
|
using UpdatingMap = std::map<TilePosition, std::deque<JobIt>>;
|
||||||
|
using IndexValue = std::pair<IndexPoint, UpdatingMap::iterator>;
|
||||||
|
|
||||||
|
std::size_t mSize = 0;
|
||||||
|
UpdatingMap mValues;
|
||||||
|
boost::geometry::index::rtree<IndexValue, boost::geometry::index::linear<4>> 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<JobIt> 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<JobIt> mRemoving;
|
||||||
|
SpatialJobQueue mUpdating;
|
||||||
|
std::deque<JobIt> mDelayed;
|
||||||
|
};
|
||||||
|
|
||||||
enum class JobStatus
|
enum class JobStatus
|
||||||
{
|
{
|
||||||
Done,
|
Done,
|
||||||
|
@ -83,7 +136,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::optional<JobIt> pop();
|
std::optional<JobIt> pop();
|
||||||
|
|
||||||
void update(TilePosition playerTile, int maxTiles);
|
void update(TilePosition playerTile);
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
@ -92,10 +145,10 @@ namespace DetourNavigator
|
||||||
private:
|
private:
|
||||||
mutable std::mutex mMutex;
|
mutable std::mutex mMutex;
|
||||||
std::condition_variable mHasJob;
|
std::condition_variable mHasJob;
|
||||||
std::deque<JobIt> mJobs;
|
SpatialJobQueue mReading;
|
||||||
|
std::deque<JobIt> mWriting;
|
||||||
|
TilePosition mPlayerTile;
|
||||||
bool mShouldStop = false;
|
bool mShouldStop = false;
|
||||||
std::size_t mWritingJobs = 0;
|
|
||||||
std::size_t mReadingJobs = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncNavMeshUpdater;
|
class AsyncNavMeshUpdater;
|
||||||
|
@ -112,7 +165,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void enqueueJob(JobIt job);
|
void enqueueJob(JobIt job);
|
||||||
|
|
||||||
void updateJobs(TilePosition playerTile, int maxTiles) { mQueue.update(playerTile, maxTiles); }
|
void update(TilePosition playerTile) { mQueue.update(playerTile); }
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
@ -169,7 +222,7 @@ namespace DetourNavigator
|
||||||
std::condition_variable mDone;
|
std::condition_variable mDone;
|
||||||
std::condition_variable mProcessed;
|
std::condition_variable mProcessed;
|
||||||
std::list<Job> mJobs;
|
std::list<Job> mJobs;
|
||||||
std::deque<JobIt> mWaiting;
|
JobQueue mWaiting;
|
||||||
std::set<std::tuple<AgentBounds, TilePosition>> mPushed;
|
std::set<std::tuple<AgentBounds, TilePosition>> mPushed;
|
||||||
Misc::ScopeGuarded<TilePosition> mPlayerTile;
|
Misc::ScopeGuarded<TilePosition> mPlayerTile;
|
||||||
NavMeshTilesCache mNavMeshTilesCache;
|
NavMeshTilesCache mNavMeshTilesCache;
|
||||||
|
@ -197,8 +250,6 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
|
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);
|
bool lockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
|
||||||
|
|
||||||
void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
|
void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
|
||||||
|
|
|
@ -6,15 +6,9 @@ namespace DetourNavigator
|
||||||
enum class ChangeType
|
enum class ChangeType
|
||||||
{
|
{
|
||||||
remove = 0,
|
remove = 0,
|
||||||
mixed = 1,
|
add = 1,
|
||||||
add = 2,
|
update = 2,
|
||||||
update = 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ChangeType addChangeType(const ChangeType current, const ChangeType add)
|
|
||||||
{
|
|
||||||
return current == add ? current : ChangeType::mixed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,13 +79,13 @@ namespace DetourNavigator
|
||||||
switch (v)
|
switch (v)
|
||||||
{
|
{
|
||||||
case CollisionShapeType::Aabb:
|
case CollisionShapeType::Aabb:
|
||||||
return s << "AgentShapeType::Aabb";
|
return s << "CollisionShapeType::Aabb";
|
||||||
case CollisionShapeType::RotatingBox:
|
case CollisionShapeType::RotatingBox:
|
||||||
return s << "AgentShapeType::RotatingBox";
|
return s << "CollisionShapeType::RotatingBox";
|
||||||
case CollisionShapeType::Cylinder:
|
case CollisionShapeType::Cylinder:
|
||||||
return s << "AgentShapeType::Cylinder";
|
return s << "CollisionShapeType::Cylinder";
|
||||||
}
|
}
|
||||||
return s << "AgentShapeType::" << static_cast<std::underlying_type_t<CollisionShapeType>>(v);
|
return s << "CollisionShapeType::" << static_cast<std::underlying_type_t<CollisionShapeType>>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& s, const AgentBounds& v)
|
std::ostream& operator<<(std::ostream& s, const AgentBounds& v)
|
||||||
|
@ -184,8 +184,6 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
case ChangeType::remove:
|
case ChangeType::remove:
|
||||||
return stream << "ChangeType::remove";
|
return stream << "ChangeType::remove";
|
||||||
case ChangeType::mixed:
|
|
||||||
return stream << "ChangeType::mixed";
|
|
||||||
case ChangeType::add:
|
case ChangeType::add:
|
||||||
return stream << "ChangeType::add";
|
return stream << "ChangeType::add";
|
||||||
case ChangeType::update:
|
case ChangeType::update:
|
||||||
|
|
|
@ -480,15 +480,6 @@ namespace DetourNavigator
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
unsigned long getMinValuableBitsNumber(const T value)
|
|
||||||
{
|
|
||||||
unsigned long power = 0;
|
|
||||||
while (power < sizeof(T) * 8 && (static_cast<T>(1) << power) < value)
|
|
||||||
++power;
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<float, float> getBoundsByZ(
|
std::pair<float, float> getBoundsByZ(
|
||||||
const RecastMesh& recastMesh, float agentHalfExtentsZ, const RecastSettings& settings)
|
const RecastMesh& recastMesh, float agentHalfExtentsZ, const RecastSettings& settings)
|
||||||
{
|
{
|
||||||
|
@ -528,10 +519,7 @@ namespace DetourNavigator
|
||||||
return { minZ, maxZ };
|
return { minZ, maxZ };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace DetourNavigator
|
|
||||||
|
|
||||||
namespace DetourNavigator
|
|
||||||
{
|
|
||||||
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh,
|
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh,
|
||||||
std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds,
|
std::string_view worldspace, const TilePosition& tilePosition, const AgentBounds& agentBounds,
|
||||||
const RecastSettings& settings)
|
const RecastSettings& settings)
|
||||||
|
@ -621,22 +609,12 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void initEmptyNavMesh(const Settings& settings, dtNavMesh& navMesh)
|
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;
|
dtNavMeshParams params;
|
||||||
std::fill_n(params.orig, 3, 0.0f);
|
std::fill_n(params.orig, 3, 0.0f);
|
||||||
params.tileWidth = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
params.tileWidth = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
||||||
params.tileHeight = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
params.tileHeight = settings.mRecast.mTileSize * settings.mRecast.mCellSize;
|
||||||
params.maxTiles = 1 << tilesBits;
|
params.maxTiles = settings.mMaxTilesNumber;
|
||||||
params.maxPolys = 1 << polysBits;
|
params.maxPolys = settings.mDetour.mMaxPolys;
|
||||||
|
|
||||||
const auto status = navMesh.init(¶ms);
|
const auto status = navMesh.init(¶ms);
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,15 @@ namespace DetourNavigator
|
||||||
function(position, tile.mVersion, *meshTile);
|
function(position, tile.mVersion, *meshTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Function>
|
||||||
|
void forEachTilePosition(Function&& function) const
|
||||||
|
{
|
||||||
|
for (const auto& [position, tile] : mUsedTiles)
|
||||||
|
function(position);
|
||||||
|
for (const TilePosition& position : mEmptyTiles)
|
||||||
|
function(position);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Tile
|
struct Tile
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
#include <DetourNavMesh.h>
|
#include <DetourNavMesh.h>
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/// Safely reset shared_ptr with definite underlying object destrutor call.
|
/// Safely reset shared_ptr with definite underlying object destrutor call.
|
||||||
|
@ -179,9 +177,9 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
std::map<osg::Vec2i, ChangeType> tilesToPost = changedTiles;
|
std::map<osg::Vec2i, ChangeType> tilesToPost = changedTiles;
|
||||||
{
|
{
|
||||||
|
const int maxTiles = mSettings.mMaxTilesNumber;
|
||||||
const auto locked = cached->lockConst();
|
const auto locked = cached->lockConst();
|
||||||
const auto& navMesh = locked->getImpl();
|
const auto& navMesh = locked->getImpl();
|
||||||
const auto maxTiles = std::min(mSettings.mMaxTilesNumber, navMesh.getParams()->maxTiles);
|
|
||||||
getTilesPositions(range, [&](const TilePosition& tile) {
|
getTilesPositions(range, [&](const TilePosition& tile) {
|
||||||
if (changedTiles.find(tile) != changedTiles.end())
|
if (changedTiles.find(tile) != changedTiles.end())
|
||||||
return;
|
return;
|
||||||
|
@ -190,7 +188,11 @@ namespace DetourNavigator
|
||||||
if (shouldAdd && !presentInNavMesh)
|
if (shouldAdd && !presentInNavMesh)
|
||||||
tilesToPost.emplace(tile, locked->isEmptyTile(tile) ? ChangeType::update : ChangeType::add);
|
tilesToPost.emplace(tile, locked->isEmptyTile(tile) ? ChangeType::update : ChangeType::add);
|
||||||
else if (!shouldAdd && presentInNavMesh)
|
else if (!shouldAdd && presentInNavMesh)
|
||||||
tilesToPost.emplace(tile, ChangeType::mixed);
|
tilesToPost.emplace(tile, ChangeType::remove);
|
||||||
|
});
|
||||||
|
locked->forEachTilePosition([&](const TilePosition& tile) {
|
||||||
|
if (!shouldAddTile(tile, playerTile, maxTiles))
|
||||||
|
tilesToPost.emplace(tile, ChangeType::remove);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
mAsyncNavMeshUpdater.post(agentBounds, cached, playerTile, mWorldspace, tilesToPost);
|
mAsyncNavMeshUpdater.post(agentBounds, cached, playerTile, mWorldspace, tilesToPost);
|
||||||
|
|
|
@ -3,41 +3,81 @@
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
#include <components/settings/values.hpp>
|
#include <components/settings/values.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastSettings makeRecastSettingsFromSettingsManager()
|
namespace
|
||||||
{
|
{
|
||||||
RecastSettings result;
|
struct NavMeshLimits
|
||||||
|
{
|
||||||
|
int mMaxTiles;
|
||||||
|
int mMaxPolys;
|
||||||
|
};
|
||||||
|
|
||||||
result.mBorderSize = ::Settings::navigator().mBorderSize;
|
template <class T>
|
||||||
result.mCellHeight = ::Settings::navigator().mCellHeight;
|
unsigned long getMinValuableBitsNumber(const T value)
|
||||||
result.mCellSize = ::Settings::navigator().mCellSize;
|
{
|
||||||
result.mDetailSampleDist = ::Settings::navigator().mDetailSampleDist;
|
unsigned long power = 0;
|
||||||
result.mDetailSampleMaxError = ::Settings::navigator().mDetailSampleMaxError;
|
while (power < sizeof(T) * 8 && (static_cast<T>(1) << power) < value)
|
||||||
result.mMaxClimb = Constants::sStepSizeUp;
|
++power;
|
||||||
result.mMaxSimplificationError = ::Settings::navigator().mMaxSimplificationError;
|
return power;
|
||||||
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;
|
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()
|
if (polysBits >= polysAndTilesBits)
|
||||||
{
|
throw std::invalid_argument("Too many polygons per tile: " + std::to_string(settings.mMaxPolys));
|
||||||
DetourSettings result;
|
|
||||||
|
|
||||||
result.mMaxNavMeshQueryNodes = ::Settings::navigator().mMaxNavMeshQueryNodes;
|
const unsigned long tilesBits = polysAndTilesBits - polysBits;
|
||||||
result.mMaxPolys = ::Settings::navigator().mMaxPolygonsPerTile;
|
|
||||||
result.mMaxPolygonPathSize = ::Settings::navigator().mMaxPolygonPathSize;
|
|
||||||
result.mMaxSmoothPathSize = ::Settings::navigator().mMaxSmoothPathSize;
|
|
||||||
|
|
||||||
return result;
|
return NavMeshLimits{
|
||||||
|
.mMaxTiles = static_cast<int>(1 << tilesBits),
|
||||||
|
.mMaxPolys = static_cast<int>(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()
|
Settings makeSettingsFromSettingsManager()
|
||||||
|
@ -46,7 +86,12 @@ namespace DetourNavigator
|
||||||
|
|
||||||
result.mRecast = makeRecastSettingsFromSettingsManager();
|
result.mRecast = makeRecastSettingsFromSettingsManager();
|
||||||
result.mDetour = makeDetourSettingsFromSettingsManager();
|
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.mWaitUntilMinDistanceToPlayer = ::Settings::navigator().mWaitUntilMinDistanceToPlayer;
|
||||||
result.mAsyncNavMeshUpdaterThreads = ::Settings::navigator().mAsyncNavMeshUpdaterThreads;
|
result.mAsyncNavMeshUpdaterThreads = ::Settings::navigator().mAsyncNavMeshUpdaterThreads;
|
||||||
result.mMaxNavMeshTilesCacheSize = ::Settings::navigator().mMaxNavMeshTilesCacheSize;
|
result.mMaxNavMeshTilesCacheSize = ::Settings::navigator().mMaxNavMeshTilesCacheSize;
|
||||||
|
|
|
@ -55,10 +55,6 @@ namespace DetourNavigator
|
||||||
|
|
||||||
inline constexpr std::int64_t navMeshFormatVersion = 2;
|
inline constexpr std::int64_t navMeshFormatVersion = 2;
|
||||||
|
|
||||||
RecastSettings makeRecastSettingsFromSettingsManager();
|
|
||||||
|
|
||||||
DetourSettings makeDetourSettingsFromSettingsManager();
|
|
||||||
|
|
||||||
Settings makeSettingsFromSettingsManager();
|
Settings makeSettingsFromSettingsManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,18 @@ namespace DetourNavigator
|
||||||
void reportStats(const AsyncNavMeshUpdaterStats& stats, unsigned int frameNumber, osg::Stats& out)
|
void reportStats(const AsyncNavMeshUpdaterStats& stats, unsigned int frameNumber, osg::Stats& out)
|
||||||
{
|
{
|
||||||
out.setAttribute(frameNumber, "NavMesh Jobs", static_cast<double>(stats.mJobs));
|
out.setAttribute(frameNumber, "NavMesh Jobs", static_cast<double>(stats.mJobs));
|
||||||
out.setAttribute(frameNumber, "NavMesh Waiting", static_cast<double>(stats.mWaiting));
|
out.setAttribute(frameNumber, "NavMesh Removing", static_cast<double>(stats.mWaiting.mRemoving));
|
||||||
|
out.setAttribute(frameNumber, "NavMesh Updating", static_cast<double>(stats.mWaiting.mUpdating));
|
||||||
|
out.setAttribute(frameNumber, "NavMesh Delayed", static_cast<double>(stats.mWaiting.mDelayed));
|
||||||
out.setAttribute(frameNumber, "NavMesh Pushed", static_cast<double>(stats.mPushed));
|
out.setAttribute(frameNumber, "NavMesh Pushed", static_cast<double>(stats.mPushed));
|
||||||
out.setAttribute(frameNumber, "NavMesh Processing", static_cast<double>(stats.mProcessing));
|
out.setAttribute(frameNumber, "NavMesh Processing", static_cast<double>(stats.mProcessing));
|
||||||
|
|
||||||
if (stats.mDb.has_value())
|
if (stats.mDb.has_value())
|
||||||
{
|
{
|
||||||
out.setAttribute(
|
|
||||||
frameNumber, "NavMesh DbJobs Write", static_cast<double>(stats.mDb->mJobs.mWritingJobs));
|
|
||||||
out.setAttribute(
|
out.setAttribute(
|
||||||
frameNumber, "NavMesh DbJobs Read", static_cast<double>(stats.mDb->mJobs.mReadingJobs));
|
frameNumber, "NavMesh DbJobs Read", static_cast<double>(stats.mDb->mJobs.mReadingJobs));
|
||||||
|
out.setAttribute(
|
||||||
|
frameNumber, "NavMesh DbJobs Write", static_cast<double>(stats.mDb->mJobs.mWritingJobs));
|
||||||
|
|
||||||
out.setAttribute(frameNumber, "NavMesh DbCache Get", static_cast<double>(stats.mDb->mGetTileCount));
|
out.setAttribute(frameNumber, "NavMesh DbCache Get", static_cast<double>(stats.mDb->mGetTileCount));
|
||||||
out.setAttribute(frameNumber, "NavMesh DbCache Hit", static_cast<double>(stats.mDbGetTileHits));
|
out.setAttribute(frameNumber, "NavMesh DbCache Hit", static_cast<double>(stats.mDbGetTileHits));
|
||||||
|
|
|
@ -11,10 +11,17 @@ namespace osg
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
|
struct JobQueueStats
|
||||||
|
{
|
||||||
|
std::size_t mRemoving = 0;
|
||||||
|
std::size_t mUpdating = 0;
|
||||||
|
std::size_t mDelayed = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct DbJobQueueStats
|
struct DbJobQueueStats
|
||||||
{
|
{
|
||||||
std::size_t mWritingJobs = 0;
|
|
||||||
std::size_t mReadingJobs = 0;
|
std::size_t mReadingJobs = 0;
|
||||||
|
std::size_t mWritingJobs = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DbWorkerStats
|
struct DbWorkerStats
|
||||||
|
@ -35,7 +42,7 @@ namespace DetourNavigator
|
||||||
struct AsyncNavMeshUpdaterStats
|
struct AsyncNavMeshUpdaterStats
|
||||||
{
|
{
|
||||||
std::size_t mJobs = 0;
|
std::size_t mJobs = 0;
|
||||||
std::size_t mWaiting = 0;
|
JobQueueStats mWaiting;
|
||||||
std::size_t mPushed = 0;
|
std::size_t mPushed = 0;
|
||||||
std::size_t mProcessing = 0;
|
std::size_t mProcessing = 0;
|
||||||
std::size_t mDbGetTileHits = 0;
|
std::size_t mDbGetTileHits = 0;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
#include <boost/geometry/geometry.hpp>
|
#include <boost/geometry/geometry.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -416,7 +415,7 @@ namespace DetourNavigator
|
||||||
if (tile == mChangedTiles.end())
|
if (tile == mChangedTiles.end())
|
||||||
mChangedTiles.emplace(tilePosition, changeType);
|
mChangedTiles.emplace(tilePosition, changeType);
|
||||||
else
|
else
|
||||||
tile->second = addChangeType(tile->second, changeType);
|
tile->second = changeType == ChangeType::remove ? changeType : tile->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<osg::Vec2i, ChangeType> TileCachedRecastMeshManager::takeChangedTiles(const UpdateGuard* guard)
|
std::map<osg::Vec2i, ChangeType> TileCachedRecastMeshManager::takeChangedTiles(const UpdateGuard* guard)
|
||||||
|
|
206
components/esm3/dialoguecondition.cpp
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
#include "dialoguecondition.hpp"
|
||||||
|
|
||||||
|
#include "esmreader.hpp"
|
||||||
|
#include "esmwriter.hpp"
|
||||||
|
#include "variant.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/misc/concepts.hpp>
|
||||||
|
#include <components/misc/strings/conversion.hpp>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
std::optional<DialogueCondition> 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<int>(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<int>(rule[0]) << " in INFO " << context;
|
||||||
|
condition.mIndex = 0;
|
||||||
|
}
|
||||||
|
if (rule[1] == '1')
|
||||||
|
{
|
||||||
|
int function = Misc::StringUtils::toNumeric<int>(std::string_view{ rule }.substr(2, 2), -1);
|
||||||
|
if (function >= Function_FacReactionLowest && function <= Function_PcWerewolfKills)
|
||||||
|
condition.mFunction = static_cast<Function>(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<int>(rule[1]) << " in INFO "
|
||||||
|
<< context;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
condition.mComparison = static_cast<Comparison>(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);
|
||||||
|
if (variant.getType() != VT_Float)
|
||||||
|
variant.setType(VT_Int);
|
||||||
|
std::string rule;
|
||||||
|
rule.reserve(5 + mVariable.size());
|
||||||
|
rule += static_cast<char>(mIndex + '0');
|
||||||
|
const auto appendVariableType = [&]() {
|
||||||
|
if (variant.getType() == VT_Float)
|
||||||
|
rule += "fX";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int32_t value = variant.getInteger();
|
||||||
|
if (static_cast<int16_t>(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, static_cast<int>(mFunction));
|
||||||
|
if (result.ec != std::errc())
|
||||||
|
{
|
||||||
|
Log(Debug::Error) << "Failed to save SCVR rule";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rule += static_cast<char>(mComparison);
|
||||||
|
rule += mVariable;
|
||||||
|
esm.writeHNString("SCVR", rule);
|
||||||
|
variant.write(esm, Variant::Format_Info);
|
||||||
|
}
|
||||||
|
}
|
134
components/esm3/dialoguecondition.hpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
#ifndef OPENMW_ESM3_DIALOGUECONDITION_H
|
||||||
|
#define OPENMW_ESM3_DIALOGUECONDITION_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include <components/esm/refid.hpp>
|
||||||
|
|
||||||
|
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_PcCorprus,
|
||||||
|
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<int32_t, float> mValue = 0;
|
||||||
|
std::uint8_t mIndex = 0;
|
||||||
|
Function mFunction = Function_None;
|
||||||
|
Comparison mComparison = Comp_None;
|
||||||
|
|
||||||
|
static std::optional<DialogueCondition> load(ESMReader& esm, ESM::RefId context);
|
||||||
|
|
||||||
|
void save(ESMWriter& esm) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -66,10 +66,9 @@ namespace ESM
|
||||||
break;
|
break;
|
||||||
case fourCC("SCVR"):
|
case fourCC("SCVR"):
|
||||||
{
|
{
|
||||||
SelectStruct ss;
|
auto filter = DialogueCondition::load(esm, mId);
|
||||||
ss.mSelectRule = esm.getHString();
|
if (filter)
|
||||||
ss.mValue.read(esm, Variant::Format_Info);
|
mSelects.emplace_back(std::move(*filter));
|
||||||
mSelects.push_back(ss);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case fourCC("BNAM"):
|
case fourCC("BNAM"):
|
||||||
|
@ -120,11 +119,8 @@ namespace ESM
|
||||||
esm.writeHNOCString("SNAM", mSound);
|
esm.writeHNOCString("SNAM", mSound);
|
||||||
esm.writeHNOString("NAME", mResponse);
|
esm.writeHNOString("NAME", mResponse);
|
||||||
|
|
||||||
for (std::vector<SelectStruct>::const_iterator it = mSelects.begin(); it != mSelects.end(); ++it)
|
for (const auto& rule : mSelects)
|
||||||
{
|
rule.save(esm);
|
||||||
esm.writeHNString("SCVR", it->mSelectRule);
|
|
||||||
it->mValue.write(esm, Variant::Format_Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
esm.writeHNOString("BNAM", mResultScript);
|
esm.writeHNOString("BNAM", mResultScript);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "components/esm/defs.hpp"
|
#include <components/esm/defs.hpp>
|
||||||
#include "components/esm/refid.hpp"
|
#include <components/esm/refid.hpp>
|
||||||
|
|
||||||
|
#include "dialoguecondition.hpp"
|
||||||
#include "variant.hpp"
|
#include "variant.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -47,13 +49,6 @@ namespace ESM
|
||||||
}; // 12 bytes
|
}; // 12 bytes
|
||||||
DATAstruct mData;
|
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)
|
// Journal quest indices (introduced with the quest system in Tribunal)
|
||||||
enum QuestStatus
|
enum QuestStatus
|
||||||
{
|
{
|
||||||
|
@ -65,7 +60,7 @@ namespace ESM
|
||||||
|
|
||||||
// Rules for when to include this item in the final list of options
|
// Rules for when to include this item in the final list of options
|
||||||
// visible to the player.
|
// visible to the player.
|
||||||
std::vector<SelectStruct> mSelects;
|
std::vector<DialogueCondition> mSelects;
|
||||||
|
|
||||||
// Id of this, previous and next INFO items
|
// Id of this, previous and next INFO items
|
||||||
RefId mId, mPrev, mNext;
|
RefId mId, mPrev, mNext;
|
||||||
|
|
|
@ -78,8 +78,7 @@ namespace Resource
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// not bothering with checks for other compression formats right now, we are unlikely to ever use those
|
// not bothering with checks for other compression formats right now
|
||||||
// anyway
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ namespace Resource
|
||||||
|
|
||||||
std::vector<std::string> generateAllStatNames()
|
std::vector<std::string> generateAllStatNames()
|
||||||
{
|
{
|
||||||
|
constexpr std::size_t itemsPerPage = 24;
|
||||||
|
|
||||||
constexpr std::string_view firstPage[] = {
|
constexpr std::string_view firstPage[] = {
|
||||||
"FrameNumber",
|
"FrameNumber",
|
||||||
"",
|
"",
|
||||||
|
@ -76,6 +78,8 @@ namespace Resource
|
||||||
"",
|
"",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(std::size(firstPage) == itemsPerPage);
|
||||||
|
|
||||||
constexpr std::string_view caches[] = {
|
constexpr std::string_view caches[] = {
|
||||||
"Node",
|
"Node",
|
||||||
"Shape",
|
"Shape",
|
||||||
|
@ -100,7 +104,9 @@ namespace Resource
|
||||||
|
|
||||||
constexpr std::string_view navMesh[] = {
|
constexpr std::string_view navMesh[] = {
|
||||||
"NavMesh Jobs",
|
"NavMesh Jobs",
|
||||||
"NavMesh Waiting",
|
"NavMesh Removing",
|
||||||
|
"NavMesh Updating",
|
||||||
|
"NavMesh Delayed",
|
||||||
"NavMesh Pushed",
|
"NavMesh Pushed",
|
||||||
"NavMesh Processing",
|
"NavMesh Processing",
|
||||||
"NavMesh DbJobs Write",
|
"NavMesh DbJobs Write",
|
||||||
|
@ -129,7 +135,8 @@ namespace Resource
|
||||||
for (std::string_view name : cellPreloader)
|
for (std::string_view name : cellPreloader)
|
||||||
statNames.emplace_back(name);
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
statNames.emplace_back();
|
while (statNames.size() % itemsPerPage != 0)
|
||||||
|
statNames.emplace_back();
|
||||||
|
|
||||||
for (std::string_view name : navMesh)
|
for (std::string_view name : navMesh)
|
||||||
statNames.emplace_back(name);
|
statNames.emplace_back(name);
|
||||||
|
|
|
@ -286,4 +286,125 @@ namespace SceneUtil
|
||||||
mOperationQueue->add(operation);
|
mOperationQueue->add(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum computeUnsizedPixelFormat(GLenum format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
// 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 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 osg::Image::computePixelFormat(format);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,10 @@ namespace SceneUtil
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osg::OperationQueue> mOperationQueue;
|
osg::ref_ptr<osg::OperationQueue> mOperationQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Compute the unsized format equivalent to the given pixel format
|
||||||
|
// Unlike osg::Image::computePixelFormat, this also covers compressed formats
|
||||||
|
GLenum computeUnsizedPixelFormat(GLenum format);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace Settings
|
||||||
SettingValue<bool> mEnableNavMeshDiskCache{ mIndex, "Navigator", "enable nav mesh disk cache" };
|
SettingValue<bool> mEnableNavMeshDiskCache{ mIndex, "Navigator", "enable nav mesh disk cache" };
|
||||||
SettingValue<bool> mWriteToNavmeshdb{ mIndex, "Navigator", "write to navmeshdb" };
|
SettingValue<bool> mWriteToNavmeshdb{ mIndex, "Navigator", "write to navmeshdb" };
|
||||||
SettingValue<std::uint64_t> mMaxNavmeshdbFileSize{ mIndex, "Navigator", "max navmeshdb file size" };
|
SettingValue<std::uint64_t> mMaxNavmeshdbFileSize{ mIndex, "Navigator", "max navmeshdb file size" };
|
||||||
|
SettingValue<bool> mWaitForAllJobsOnExit{ mIndex, "Navigator", "wait for all jobs on exit" };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <components/sceneutil/morphgeometry.hpp>
|
#include <components/sceneutil/morphgeometry.hpp>
|
||||||
#include <components/sceneutil/riggeometry.hpp>
|
#include <components/sceneutil/riggeometry.hpp>
|
||||||
#include <components/sceneutil/riggeometryosgaextension.hpp>
|
#include <components/sceneutil/riggeometryosgaextension.hpp>
|
||||||
|
#include <components/sceneutil/util.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/stereo/stereomanager.hpp>
|
#include <components/stereo/stereomanager.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
@ -184,6 +185,7 @@ namespace Shader
|
||||||
, mAdditiveBlending(false)
|
, mAdditiveBlending(false)
|
||||||
, mDiffuseHeight(false)
|
, mDiffuseHeight(false)
|
||||||
, mNormalHeight(false)
|
, mNormalHeight(false)
|
||||||
|
, mReconstructNormalZ(false)
|
||||||
, mTexStageRequiringTangents(-1)
|
, mTexStageRequiringTangents(-1)
|
||||||
, mSoftParticles(false)
|
, mSoftParticles(false)
|
||||||
, mNode(nullptr)
|
, mNode(nullptr)
|
||||||
|
@ -429,6 +431,7 @@ namespace Shader
|
||||||
normalMapTex->setFilter(osg::Texture::MAG_FILTER, diffuseMap->getFilter(osg::Texture::MAG_FILTER));
|
normalMapTex->setFilter(osg::Texture::MAG_FILTER, diffuseMap->getFilter(osg::Texture::MAG_FILTER));
|
||||||
normalMapTex->setMaxAnisotropy(diffuseMap->getMaxAnisotropy());
|
normalMapTex->setMaxAnisotropy(diffuseMap->getMaxAnisotropy());
|
||||||
normalMapTex->setName("normalMap");
|
normalMapTex->setName("normalMap");
|
||||||
|
normalMap = normalMapTex;
|
||||||
|
|
||||||
int unit = texAttributes.size();
|
int unit = texAttributes.size();
|
||||||
if (!writableStateSet)
|
if (!writableStateSet)
|
||||||
|
@ -440,6 +443,21 @@ namespace Shader
|
||||||
mRequirements.back().mNormalHeight = normalHeight;
|
mRequirements.back().mNormalHeight = normalHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (normalMap != nullptr && normalMap->getImage(0))
|
||||||
|
{
|
||||||
|
// Special handling for red-green normal maps (e.g. BC5 or R8G8)
|
||||||
|
switch (SceneUtil::computeUnsizedPixelFormat(normalMap->getImage(0)->getPixelFormat()))
|
||||||
|
{
|
||||||
|
case GL_RG:
|
||||||
|
case GL_RG_INTEGER:
|
||||||
|
{
|
||||||
|
mRequirements.back().mReconstructNormalZ = true;
|
||||||
|
mRequirements.back().mNormalHeight = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mAutoUseSpecularMaps && diffuseMap != nullptr && specularMap == nullptr && diffuseMap->getImage(0))
|
if (mAutoUseSpecularMaps && diffuseMap != nullptr && specularMap == nullptr && diffuseMap->getImage(0))
|
||||||
{
|
{
|
||||||
std::string specularMapFileName = diffuseMap->getImage(0)->getFileName();
|
std::string specularMapFileName = diffuseMap->getImage(0)->getFileName();
|
||||||
|
@ -629,6 +647,7 @@ namespace Shader
|
||||||
|
|
||||||
defineMap["diffuseParallax"] = reqs.mDiffuseHeight ? "1" : "0";
|
defineMap["diffuseParallax"] = reqs.mDiffuseHeight ? "1" : "0";
|
||||||
defineMap["parallax"] = reqs.mNormalHeight ? "1" : "0";
|
defineMap["parallax"] = reqs.mNormalHeight ? "1" : "0";
|
||||||
|
defineMap["reconstructNormalZ"] = reqs.mReconstructNormalZ ? "1" : "0";
|
||||||
|
|
||||||
writableStateSet->addUniform(new osg::Uniform("colorMode", reqs.mColorMode));
|
writableStateSet->addUniform(new osg::Uniform("colorMode", reqs.mColorMode));
|
||||||
addedState->addUniform("colorMode");
|
addedState->addUniform("colorMode");
|
||||||
|
|
|
@ -110,6 +110,7 @@ namespace Shader
|
||||||
|
|
||||||
bool mDiffuseHeight; // true if diffuse map has height info in alpha channel
|
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 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
|
// -1 == no tangents required
|
||||||
int mTexStageRequiringTangents;
|
int mTexStageRequiringTangents;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/sceneutil/depth.hpp>
|
#include <components/sceneutil/depth.hpp>
|
||||||
|
#include <components/sceneutil/util.hpp>
|
||||||
#include <components/shader/shadermanager.hpp>
|
#include <components/shader/shadermanager.hpp>
|
||||||
#include <components/stereo/stereomanager.hpp>
|
#include <components/stereo/stereomanager.hpp>
|
||||||
|
|
||||||
|
@ -271,18 +272,37 @@ namespace Terrain
|
||||||
stateset->addUniform(UniformCollection::value().mBlendMap);
|
stateset->addUniform(UniformCollection::value().mBlendMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parallax = it->mNormalMap && it->mParallax;
|
||||||
|
bool reconstructNormalZ = false;
|
||||||
|
|
||||||
if (it->mNormalMap)
|
if (it->mNormalMap)
|
||||||
{
|
{
|
||||||
stateset->setTextureAttributeAndModes(2, it->mNormalMap);
|
stateset->setTextureAttributeAndModes(2, it->mNormalMap);
|
||||||
stateset->addUniform(UniformCollection::value().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)
|
||||||
|
{
|
||||||
|
switch (SceneUtil::computeUnsizedPixelFormat(image->getPixelFormat()))
|
||||||
|
{
|
||||||
|
case GL_RG:
|
||||||
|
case GL_RG_INTEGER:
|
||||||
|
{
|
||||||
|
reconstructNormalZ = true;
|
||||||
|
parallax = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::ShaderManager::DefineMap defineMap;
|
Shader::ShaderManager::DefineMap defineMap;
|
||||||
defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0";
|
defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0";
|
||||||
defineMap["blendMap"] = (!blendmaps.empty()) ? "1" : "0";
|
defineMap["blendMap"] = (!blendmaps.empty()) ? "1" : "0";
|
||||||
defineMap["specularMap"] = it->mSpecular ? "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["writeNormals"] = (it == layers.end() - 1) ? "1" : "0";
|
||||||
|
defineMap["reconstructNormalZ"] = reconstructNormalZ ? "1" : "0";
|
||||||
Stereo::shaderStereoDefines(defineMap);
|
Stereo::shaderStereoDefines(defineMap);
|
||||||
|
|
||||||
stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));
|
stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));
|
||||||
|
|
|
@ -245,6 +245,16 @@ Absent pieces usually mean a bug in recast mesh tiles building.
|
||||||
Allows to do in-game debug.
|
Allows to do in-game debug.
|
||||||
Potentially decreases performance.
|
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
|
Expert settings
|
||||||
***************
|
***************
|
||||||
|
|
||||||
|
|
|
@ -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.
|
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
|
Specular Mapping
|
||||||
################
|
################
|
||||||
|
|
||||||
|
|
50
files/data/l10n/Calendar/sv.yaml
Normal file
|
@ -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"
|
Before Width: | Height: | Size: 562 B |
126
files/opencs/activator.svg
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2320"
|
||||||
|
x1="2.6458335"
|
||||||
|
y1="14.816667"
|
||||||
|
x2="5.8208332"
|
||||||
|
y2="14.816667"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
id="Main-5">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-8" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2322"
|
||||||
|
x1="3.1750002"
|
||||||
|
y1="14.816651"
|
||||||
|
x2="5.2916675"
|
||||||
|
y2="14.816651"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2324"
|
||||||
|
x1="5.6885424"
|
||||||
|
y1="14.816667"
|
||||||
|
x2="6.3500004"
|
||||||
|
y2="14.816667"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2326"
|
||||||
|
x1="4.17975"
|
||||||
|
y1="16.49861"
|
||||||
|
x2="5.3575182"
|
||||||
|
y2="16.49861"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2328"
|
||||||
|
x1="2.2552035"
|
||||||
|
y1="15.843752"
|
||||||
|
x2="3.3670816"
|
||||||
|
y2="15.843752"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2330"
|
||||||
|
x1="2.2552028"
|
||||||
|
y1="13.789582"
|
||||||
|
x2="3.3670833"
|
||||||
|
y2="13.789582"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-5"
|
||||||
|
id="linearGradient2332"
|
||||||
|
x1="4.17975"
|
||||||
|
y1="13.134723"
|
||||||
|
x2="5.3575163"
|
||||||
|
y2="13.134723"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="activator"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(3.7795278,0,0,3.7323517,-8.0000099,-47.301008)">
|
||||||
|
<rect
|
||||||
|
style="opacity:0;fill:#a51d2d;stroke-width:0.264583px;paint-order:fill markers stroke;stop-color:#000000"
|
||||||
|
id="rect1388"
|
||||||
|
width="4.2333331"
|
||||||
|
height="4.2333331"
|
||||||
|
x="2.1166692"
|
||||||
|
y="12.7"
|
||||||
|
rx="1.9824198e-15" />
|
||||||
|
<path
|
||||||
|
id="path1591"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2320);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 4.2333336,13.229167 a 1.5875001,1.5874996 0 0 0 -1.5875001,1.5875 1.5875001,1.5874996 0 0 0 1.5875001,1.5875 1.5875001,1.5874996 0 0 0 1.5874998,-1.5875 1.5875001,1.5874996 0 0 0 -1.5874998,-1.5875 z m 0,0.264583 A 1.3229167,1.3229167 0 0 1 5.5562504,14.816667 1.3229167,1.3229167 0 0 1 4.2333336,16.139583 1.3229167,1.3229167 0 0 1 2.9104169,14.816667 1.3229167,1.3229167 0 0 1 4.2333336,13.49375 Z" />
|
||||||
|
<path
|
||||||
|
id="path1598"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2322);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 4.2173138,13.758333 A 1.0583334,1.0583334 0 0 0 3.1750002,14.816667 1.0583334,1.0583334 0 0 0 4.2333336,15.875 1.0583334,1.0583334 0 0 0 5.2916674,14.816667 1.0583334,1.0583334 0 0 0 4.2333336,13.758333 a 1.0583334,1.0583334 0 0 0 -0.016021,0 z m 0.00259,0.264584 a 0.79374999,0.79374999 0 0 1 0.013427,0 0.79374999,0.79374999 0 0 1 0.7937496,0.79375 0.79374999,0.79374999 0 0 1 -0.7937496,0.79375 0.79374999,0.79374999 0 0 1 -0.7937501,-0.79375 0.79374999,0.79374999 0 0 1 0.7803143,-0.79375 z" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2324);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 5.6885424,14.2875 v 0.264584 h 0.396875 v 0.529166 h -0.396875 v 0.264584 c 0,0 0.264583,0 0.396875,0 0.264583,0 0.264583,0 0.264583,-0.264584 0,-0.176389 0,-0.529166 0,-0.529166 0,-0.264584 0,-0.264584 -0.264583,-0.264584 z"
|
||||||
|
id="path1605" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2326);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 5.1862854,16.037131 -0.251634,0.08176 0.122641,0.377451 -0.5032668,0.163521 -0.1226411,-0.377451 -0.2516344,0.08176 c 0,0 0.081761,0.251634 0.1226411,0.377451 0.081761,0.251633 0.081761,0.251633 0.333395,0.169872 0.1677562,-0.05451 0.5032672,-0.163521 0.5032672,-0.163521 0.251634,-0.08176 0.251634,-0.08176 0.169873,-0.333394 z"
|
||||||
|
id="path1607" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2328);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 3.3670817,16.100122 3.2115641,15.886069 2.890485,16.119347 2.5794493,15.691242 2.9005284,15.457965 2.7450107,15.243911 c 0,0 -0.2140526,0.155519 -0.321079,0.233278 -0.2140517,0.155518 -0.2140517,0.155518 -0.058533,0.369571 0.1036816,0.142701 0.3110358,0.428104 0.3110358,0.428104 0.1555176,0.214053 0.1555176,0.214053 0.3695702,0.05853 z"
|
||||||
|
id="path1609" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2330);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 2.7450088,14.389422 2.9005278,14.17537 2.5794483,13.942092 2.890485,13.513988 3.2115635,13.747266 3.3670834,13.533213 c 0,0 -0.2140533,-0.155518 -0.3210794,-0.233277 C 2.8319519,13.144419 2.8319519,13.144419 2.6764334,13.358476 2.572756,13.50118 2.3653976,13.78658 2.3653976,13.78658 c -0.1555189,0.214052 -0.1555189,0.214052 0.058538,0.369569 z"
|
||||||
|
id="path1611" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2332);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 4.1797501,13.26916 0.2516335,0.08176 0.1226416,-0.377452 0.5032662,0.163522 -0.122641,0.377451 0.251634,0.08176 c 0,0 0.08176,-0.251634 0.122641,-0.377451 0.08176,-0.251633 0.08176,-0.251633 -0.169878,-0.333393 -0.167758,-0.0545 -0.5032668,-0.163521 -0.5032668,-0.163521 -0.2516336,-0.08176 -0.2516336,-0.08176 -0.3333918,0.169876 z"
|
||||||
|
id="path1613" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 364 B |
58
files/opencs/apparatus.svg
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2316"
|
||||||
|
x1="7.4083333"
|
||||||
|
y1="15.610416"
|
||||||
|
x2="11.641667"
|
||||||
|
y2="15.610416"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
id="Main-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2318"
|
||||||
|
x1="7.4311438"
|
||||||
|
y1="13.585216"
|
||||||
|
x2="9.7828169"
|
||||||
|
y2="13.585216"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="apparatus"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(3.7795264,0,0,3.7795277,-27.999988,-48.000001)">
|
||||||
|
<path
|
||||||
|
id="path1548"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2316);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 7.4083332,14.2875 c 0,1.058334 10e-8,1.852084 0.7937501,2.116667 v 0.529166 h 2.6458337 v -0.529166 c 0.79375,-0.264583 0.79375,-1.058333 0.79375,-2.116667 z m 0.2645835,0.264583 h 3.7041663 c -0.0043,0.391937 -0.02302,0.776349 -0.08992,1.021643 -0.08422,0.308823 -0.201392,0.472102 -0.522965,0.579293 -0.108066,0.03605 -0.180927,0.0049 -0.180868,0.118856 V 16.66875 H 8.4666666 l 10e-8,-0.396875 c 5.96e-5,-0.113922 -0.072801,-0.0828 -0.1808676,-0.118856 C 7.9642258,16.045828 7.847058,15.882549 7.7628336,15.573726 7.6959349,15.328432 7.6772196,14.94402 7.6729167,14.552083 Z" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2318);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 8.0303333,14.440792 c 0,0 -0.2549422,-0.503321 -0.5872624,-1.214834 -0.051288,-0.109811 0.072913,-0.283564 0.1805731,-0.367422 0.1272316,-0.0991 0.335854,-0.186629 0.4261393,-0.102012 0.6564188,0.615209 1.7330335,1.691503 1.7330335,1.691503 l -0.443406,-0.08626 c 0,0 -0.8603506,-0.879948 -1.300715,-1.309642 -0.1226325,-0.119661 -0.3779304,0.08975 -0.3032537,0.272244 0.1220055,0.29815 0.5843882,1.043318 0.5843882,1.043318 z"
|
||||||
|
id="path1575" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 473 B |
58
files/opencs/armor.svg
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2334"
|
||||||
|
x1="12.7"
|
||||||
|
y1="14.834408"
|
||||||
|
x2="16.933334"
|
||||||
|
y2="14.834408"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2336"
|
||||||
|
x1="13.229167"
|
||||||
|
y1="14.816667"
|
||||||
|
x2="16.404167"
|
||||||
|
y2="14.816667"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="armor"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(3.7795254,0,0,3.7481122,-47.999972,-47.601024)">
|
||||||
|
<path
|
||||||
|
id="path1648"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2334);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 12.7,12.7 c -10e-7,2.645834 0.529166,3.307291 1.984375,4.233333 0.07443,0.04731 0.190154,0.04731 0.264584,0 1.455208,-0.926042 1.984375,-1.587499 1.984375,-4.233333 z m 0.264584,0.264583 h 3.704166 c 0,1.984375 -0.463021,2.869609 -1.736328,3.673161 -0.06513,0.04105 -0.16638,0.04105 -0.23151,0 -1.273308,-0.803552 -1.736328,-1.688786 -1.736328,-3.673161 z" />
|
||||||
|
<path
|
||||||
|
id="path1653"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2336);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 14.816667,16.404167 c 1.364557,-0.881951 1.49242,-1.658193 1.5875,-3.175 h -1.5875 -1.5875 c 0.09508,1.516807 0.222943,2.293049 1.5875,3.175 z m 0,-2.910417 h 1.30638 c -0.115736,1.322698 -0.265299,1.809261 -1.30638,2.588086 -1.041081,-0.778825 -1.190644,-1.265388 -1.30638,-2.588086 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 326 B |
46
files/opencs/attribute.svg
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2232"
|
||||||
|
x1="2.1166666"
|
||||||
|
y1="41.275002"
|
||||||
|
x2="6.3499999"
|
||||||
|
y2="41.275002"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="attribute"
|
||||||
|
transform="matrix(3.7795255,0,0,3.7795259,-7.9999953,-147.99994)"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="rect1081"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2232);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 3.9687499,39.158335 2.1166666,42.862502 2.453597,43.391668 H 6.0130694 L 6.3499999,42.862502 4.4979166,39.158335 Z m 0.1638143,0.264583 h 0.2015381 l 0.2645832,0.529167 H 3.8679809 Z m -0.396875,0.79375 h 0.995288 l 0.396875,0.79375 h -1.789038 z m -0.5291666,1.058334 h 2.0536213 l 0.396875,0.79375 H 2.8096476 Z m -0.5291667,1.058333 h 3.1119546 l 0.2361616,0.472323 -0.2046388,0.321427 h -3.175 L 2.4411946,42.805658 Z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 444 B |
94
files/opencs/birthsign.svg
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2222"
|
||||||
|
x1="8.2020836"
|
||||||
|
y1="40.481251"
|
||||||
|
x2="10.847917"
|
||||||
|
y2="40.481251"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2224"
|
||||||
|
x1="7.4083333"
|
||||||
|
y1="42.068752"
|
||||||
|
x2="8.4666662"
|
||||||
|
y2="42.068752"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2226"
|
||||||
|
x1="8.9958334"
|
||||||
|
y1="42.597919"
|
||||||
|
x2="10.054167"
|
||||||
|
y2="42.597919"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2228"
|
||||||
|
x1="10.583333"
|
||||||
|
y1="42.068752"
|
||||||
|
x2="11.641667"
|
||||||
|
y2="42.068752"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2230"
|
||||||
|
x1="7.4083333"
|
||||||
|
y1="40.613544"
|
||||||
|
x2="11.641667"
|
||||||
|
y2="40.613544"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="birthsign"
|
||||||
|
transform="matrix(3.7795264,0,0,3.7795278,-27.999988,-148.00001)"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="path10688"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2222);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 9.5249999,39.158335 a 1.3229166,1.3229166 0 0 0 -1.3229167,1.322916 1.3229166,1.3229166 0 0 0 1.3229167,1.322917 1.3229166,1.3229166 0 0 0 1.3229171,-1.322917 1.3229166,1.3229166 0 0 0 -1.3229171,-1.322916 z m -0.01602,0.264583 a 1.0583333,1.0583333 0 0 1 0.01602,0 1.0583333,1.0583333 0 0 1 1.0583331,1.058333 1.0583333,1.0583333 0 0 1 -1.0583331,1.058334 1.0583333,1.0583333 0 0 1 -1.0583333,-1.058334 1.0583333,1.0583333 0 0 1 1.0423133,-1.058333 z" />
|
||||||
|
<path
|
||||||
|
id="rect10697"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2224);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 7.6729166,41.539585 c -0.1465789,0 -0.2645834,0.118004 -0.2645834,0.264583 v 0.529167 c 0,0.146579 0.1180045,0.264583 0.2645834,0.264583 h 0.5291666 c 0.146579,0 0.2645834,-0.118004 0.2645834,-0.264583 v -0.529167 c 0,-0.146579 -0.1180044,-0.264583 -0.2645834,-0.264583 z m 0,0.264583 h 0.5291666 v 0.529167 H 7.6729166 Z" />
|
||||||
|
<path
|
||||||
|
id="path10718"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2226);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 9.2604166,42.068753 c -0.1465789,0 -0.2645833,0.118005 -0.2645833,0.264584 v 0.529166 c 0,0.14658 0.1180044,0.264584 0.2645833,0.264584 h 0.5291667 c 0.146579,0 0.2645837,-0.118004 0.2645837,-0.264584 v -0.529166 c 0,-0.146579 -0.1180047,-0.264584 -0.2645837,-0.264584 z m 0,0.264584 h 0.5291667 v 0.529166 H 9.2604166 Z" />
|
||||||
|
<path
|
||||||
|
id="path10720"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2228);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 10.847917,41.539587 c -0.146579,0 -0.264584,0.118005 -0.264584,0.264584 v 0.529166 c 0,0.14658 0.118005,0.264584 0.264584,0.264584 h 0.529166 c 0.146579,0 0.264584,-0.118004 0.264584,-0.264584 v -0.529166 c 0,-0.146579 -0.118005,-0.264584 -0.264584,-0.264584 z m 0,0.264584 h 0.529166 v 0.529166 h -0.529166 z" />
|
||||||
|
<path
|
||||||
|
id="path10722"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2230);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 7.9374999,40.216668 c -0.2922507,0 -0.5291667,0.177686 -0.5291667,0.396875 0,0.219189 0.236916,0.396875 0.5291667,0.396875 H 9.2604165 9.7895832 11.1125 c 0.292251,0 0.529167,-0.177686 0.529167,-0.396875 0,-0.219189 -0.236916,-0.396875 -0.529167,-0.396875 h -0.432015 v 0.264583 H 11.1125 c 0.0019,-2.4e-5 0.0038,-2.4e-5 0.0057,0 0.09451,0.0024 0.169547,0.06084 0.169499,0.132292 0,0.07309 -0.07845,0.132334 -0.175183,0.132292 h -0.0057 -1.3172328 -0.5291667 -1.3172322 -0.00568 c -0.096734,4.2e-5 -0.1751831,-0.0592 -0.1751831,-0.132292 -4.81e-5,-0.07145 0.074991,-0.130014 0.1694987,-0.132292 0.00189,-2.4e-5 0.00379,-2.4e-5 0.00568,0 h 0.432015 v -0.264583 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 418 B |
58
files/opencs/body-part.svg
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2234"
|
||||||
|
x1="12.700004"
|
||||||
|
y1="41.275002"
|
||||||
|
x2="16.662027"
|
||||||
|
y2="41.275002"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-1"
|
||||||
|
id="linearGradient2236"
|
||||||
|
x1="15.261501"
|
||||||
|
y1="42.025791"
|
||||||
|
x2="15.91278"
|
||||||
|
y2="42.025791"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="body-part"
|
||||||
|
transform="matrix(3.7795264,0,0,3.7795278,-47.999995,-148.00001)"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="path1689"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2234);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 14.305075,39.158335 c 0.660363,1.331254 0.764294,1.869768 0.764294,2.462382 0,0.424307 -0.988158,0.901957 -1.840199,0.987536 -0.18112,0.0063 -0.529166,0.09876 -0.529166,0.518832 0,0.229584 0.339402,0.264584 0.529166,0.264584 h 3.024106 c 0.686469,-0.431602 0.364641,-0.995913 0.07028,-1.802474 -0.223239,-0.779487 -0.183967,-1.148525 -0.183967,-2.43086 z m 0.432014,0.264584 h 1.137915 c 0.01315,1.138401 -0.05581,1.388856 0.167431,2.168342 0.294362,0.806564 0.370625,1.401879 0.09715,1.535824 h -2.910417 c -0.324061,0 -0.321976,-0.267568 0,-0.293523 0.859047,-0.06925 2.12235,-0.654593 2.12235,-1.212845 0.0016,-0.218358 0.106445,-0.895485 -0.614431,-2.197798 z" />
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2236);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 15.261501,42.27091 c 0.204639,0.05209 0.511182,-0.240606 0.55025,-0.599654 0.113481,0.139526 0.14858,0.519555 0.01464,0.635827 -0.133946,0.116272 -0.449543,0.08661 -0.564885,-0.03617 z"
|
||||||
|
id="path1693" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 323 B |
166
files/opencs/book.svg
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Red">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff664d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2533" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect3119">
|
||||||
|
<path
|
||||||
|
id="path3117"
|
||||||
|
style="opacity:1;fill:#000000;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 10.250537,66.995394 -0.0047,0.0047 c -0.02767,-0.0066 -0.211799,-0.04039 -0.4563028,0.204116 C 9.6572915,67.468749 9.6572915,67.468749 9.5249999,67.49562 9.3927082,67.468749 9.3927082,67.468749 9.2604165,67.204166 9.061979,67.005731 8.8982935,66.990872 8.8289184,66.99591 c -0.023124,0.0016 -0.035657,0.0057 -0.035657,0.0057 0,0 -0.062009,0.20257 0.2025716,0.467154 0.2645833,0.132291 0.2645841,0.132291 0.291455,0.264583 -0.026871,0.132292 -0.026872,0.132292 -0.291455,0.264583 -0.2445017,0.244505 -0.2107512,0.428639 -0.2041218,0.456304 l -0.00465,0.0047 c 0,0 0.00465,2.65e-4 0.00517,5.29e-4 1.736e-4,5.3e-4 0.00103,0.0057 0.00103,0.0057 l 0.00465,-0.0047 c 0.027721,0.0066 0.2118445,0.04033 0.4563028,-0.204123 0.1322919,-0.264584 0.1322919,-0.264584 0.2645833,-0.291455 0.1322919,0.02687 0.1322917,0.02687 0.2645833,0.291455 0.1984378,0.198435 0.3621234,0.213294 0.4314984,0.208256 0.02312,-0.0016 0.03566,-0.0057 0.03566,-0.0057 0,0 0.06201,-0.20257 -0.202572,-0.467156 -0.2645836,-0.132289 -0.2645839,-0.132291 -0.291455,-0.264583 0.026871,-0.132279 0.026873,-0.132292 0.291455,-0.264583 0.244502,-0.244505 0.210752,-0.428639 0.204122,-0.456304 l 0.0047,-0.0047 c 0,0 -0.0046,-7.94e-4 -0.0052,-0.0011 -1.47e-4,-5.29e-4 -10e-4,-0.0052 -10e-4,-0.0052 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2338"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="13.62678"
|
||||||
|
x2="20.108334"
|
||||||
|
y2="13.62678"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2340"
|
||||||
|
x1="19.84375"
|
||||||
|
y1="14.816667"
|
||||||
|
x2="20.372917"
|
||||||
|
y2="14.816667"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2342"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="14.948958"
|
||||||
|
x2="18.25625"
|
||||||
|
y2="14.948958"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2344"
|
||||||
|
x1="21.960417"
|
||||||
|
y1="14.948958"
|
||||||
|
x2="22.225"
|
||||||
|
y2="14.948958"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2346"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="15.478861"
|
||||||
|
x2="20.108334"
|
||||||
|
y2="15.478861"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2348"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="16.008026"
|
||||||
|
x2="20.108334"
|
||||||
|
y2="16.008026"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2350"
|
||||||
|
x1="20.108332"
|
||||||
|
y1="13.62678"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="13.62678"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2352"
|
||||||
|
x1="20.108332"
|
||||||
|
y1="16.008026"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="16.008026"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2354"
|
||||||
|
x1="20.108332"
|
||||||
|
y1="15.478861"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="15.478861"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="book"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(3.7795278,0,0,3.7795278,-67.999998,-48.000002)">
|
||||||
|
<path
|
||||||
|
id="path1701"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2338);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108334,13.493751 h -0.264583 c -0.631361,-0.523199 -1.676055,-0.176816 -1.852084,0.264583 l 0.04547,0.264583 c 0.176029,-0.441399 1.167806,-0.797084 1.806609,-0.264583 h 0.264583 z" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2340);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect1714"
|
||||||
|
width="0.5291667"
|
||||||
|
height="2.3812501"
|
||||||
|
x="19.84375"
|
||||||
|
y="13.626042" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2342);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect1716"
|
||||||
|
width="0.26458335"
|
||||||
|
height="2.3812501"
|
||||||
|
x="17.991667"
|
||||||
|
y="13.758333" />
|
||||||
|
<rect
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2344);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="rect1718"
|
||||||
|
width="0.26458335"
|
||||||
|
height="2.3812501"
|
||||||
|
x="21.960417"
|
||||||
|
y="13.758333" />
|
||||||
|
<path
|
||||||
|
id="path1736"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2346);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108334,15.345832 h -0.264583 c -0.631361,-0.523199 -1.676055,-0.176816 -1.852084,0.264583 l 0.04547,0.264583 c 0.176029,-0.441399 1.167806,-0.797084 1.806609,-0.264583 h 0.264583 z" />
|
||||||
|
<path
|
||||||
|
id="path1738"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2348);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108334,15.874998 h -0.264583 c -0.631361,-0.523199 -1.676055,-0.176816 -1.852084,0.264583 l 0.04547,0.264583 c 0.176029,-0.441399 1.167806,-0.797084 1.806609,-0.264583 h 0.264583 z" />
|
||||||
|
<path
|
||||||
|
id="path1740"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2350);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108331,13.493751 h 0.264583 c 0.631361,-0.523199 1.676055,-0.176816 1.852084,0.264583 l -0.04547,0.264583 c -0.176029,-0.441399 -1.167806,-0.797084 -1.806609,-0.264583 h -0.264583 z" />
|
||||||
|
<path
|
||||||
|
id="path1742"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2352);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108331,15.874998 h 0.264583 c 0.631361,-0.523199 1.676055,-0.176816 1.852084,0.264583 l -0.04547,0.264583 C 22.003499,15.962765 21.011722,15.60708 20.372919,16.139581 h -0.264583 z" />
|
||||||
|
<path
|
||||||
|
id="path1744"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2354);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108331,15.345832 h 0.264583 c 0.631361,-0.523199 1.676055,-0.176816 1.852084,0.264583 l -0.04547,0.264583 c -0.176029,-0.441399 -1.167806,-0.797084 -1.806609,-0.264583 h -0.264583 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
51
files/opencs/brush-circle.svg
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.01348304,5.4290978e-4,-5.4290978e-4,0.01348304,-8.3169871,11.902656)"
|
||||||
|
id="g3861"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:14.1112;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 1223.0877,970.60693 c 3.4659,1.1301 69.3268,-132.17231 0.01,1.65348 22.4324,7.9982 57.8129,20.83702 84.2736,35.72149 31.47,17.7026 95.0975,62.919 130.2191,93.4513 159.6062,-258.85749 217.7622,-402.8573 250.8816,-481.45696 1.4672,-3.6726 -10.6381,-224.03518 -7.9288,-242.38296 0.1439,-0.97479 -4.6307,-160.00282 -6.6178,-156.89403 -185.4652,290.15856 -351.8616,515.32983 -450.8377,749.90768 z m -18.5993,36.81547 c -10.343,-2.1435 -12.6893,2.7546 -14.3902,6.9154 -54.017,132.1446 -235.98278,450.7428 -258.39341,511.235 42.95377,6.6425 123.61141,56.0901 148.18501,89.6848 41.8408,-48.8743 238.2435,-354.2773 326.9039,-464.9703 3.3794,-4.2192 7.1429,-9.3124 11.2187,-15.1876 -31.8717,-28.1815 -90.6253,-67.9585 -118.9834,-84.5388 -27.4402,-16.0436 -52.8034,-27.3693 -75.3438,-35.4062 -5.3875,-1.921 -14.1678,-6.1689 -19.1968,-7.7323 z"
|
||||||
|
id="path3021"
|
||||||
|
transform="matrix(0.52516433,0,0,0.52516433,961.78994,-828.86591)" />
|
||||||
|
<g
|
||||||
|
id="g3795"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
id="path3793"
|
||||||
|
d="m 1432.3282,180.29088 c -0.3954,-0.0244 -0.6929,-0.0105 -1.091,-0.0361 -3.8526,-0.2484 -7.8422,-0.56196 -11.8738,-0.94553 -4.0316,-0.38357 -8.1046,-0.83644 -12.1828,-1.38194 -4.0783,-0.5455 -8.1539,-1.17502 -12.1465,-1.90928 -3.9927,-0.73421 -7.9173,-1.57768 -11.692,-2.52747 -3.7746,-0.94978 -7.3947,-2.0082 -10.8191,-3.20027 -1.7122,-0.59601 -3.3824,-1.22943 -4.9822,-1.89108 -1.5999,-0.66164 -3.1295,-1.36052 -4.6004,-2.09106 -1.4709,-0.73059 -2.8749,-1.48824 -4.2004,-2.29116 -1.3254,-0.80286 -2.5823,-1.64896 -3.7458,-2.52747 -1.1634,-0.8785 -2.2335,-1.78819 -3.2184,-2.74566 -0.9849,-0.95752 -1.8831,-1.96043 -2.673,-3.00029 -0.7898,-1.03985 -1.4765,-2.12929 -2.0547,-3.25479 -0.5782,-1.12557 -1.0501,-2.29484 -1.4001,-3.50943 -0.3501,-1.21459 -0.5856,-2.47515 -0.691,-3.78214 -0.1054,-1.307 -0.083,-2.65216 0.073,-4.05487 0.1559,-1.40277 0.2212,-2.7861 0.1819,-4.12766 -0.039,-1.34156 -0.1778,-2.64605 -0.4001,-3.92761 -0.2222,-1.28157 -0.5345,-2.5231 -0.9273,-3.74578 -0.3929,-1.22268 -0.8671,-2.41726 -1.4183,-3.58216 -0.5512,-1.16484 -1.1757,-2.31025 -1.8729,-3.41847 -0.6973,-1.10817 -1.4601,-2.18399 -2.2911,-3.23659 -0.8311,-1.05266 -1.7386,-2.07483 -2.6912,-3.07302 -0.9525,-0.9982 -1.9566,-1.98266 -3.0184,-2.92756 -1.0618,-0.94484 -2.1688,-1.85296 -3.3276,-2.74566 -1.1587,-0.8927 -2.375,-1.75864 -3.6185,-2.6002 -0.5162,-0.34947 -1.1071,-0.64116 -1.6365,-0.98196 -18.7596,41.685 -48.6658,67.50321 -110.1368,78.95234 -10.0671,1.87502 -6.7445,14.14668 0,14.14662 72.5797,0 156.074,-0.34097 218.4553,-19.58348 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path3849"
|
||||||
|
d="m 1430.619,-12.707633 c -45.8854,0 -84.0461,33.091677 -91.8989,76.715697 -4.2316,15.792726 -8.9665,30.004108 -14.7104,42.767336 0.5294,0.3408 1.1203,0.63249 1.6365,0.98196 1.2435,0.84156 2.4598,1.7075 3.6185,2.6002 1.1588,0.8927 2.2658,1.80082 3.3276,2.74566 1.0618,0.9449 2.0659,1.92936 3.0184,2.92756 0.9526,0.99819 1.8601,2.02036 2.6912,3.07302 0.831,1.0526 1.5938,2.12842 2.2911,3.23658 0.6972,1.10823 1.3217,2.25364 1.8729,3.41848 0.5512,1.1649 1.0254,2.35948 1.4183,3.58216 0.3928,1.22268 0.7051,2.46421 0.9273,3.74578 0.2223,1.28156 0.3607,2.58605 0.4001,3.92761 0.039,1.34156 -0.026,2.72489 -0.1819,4.12766 -0.1558,1.40271 -0.1781,2.74787 -0.073,4.05487 0.1054,1.30699 0.3409,2.56755 0.691,3.78214 0.35,1.21459 0.8219,2.38386 1.4001,3.50942 0.5782,1.12551 1.2649,2.21495 2.0547,3.2548 0.7899,1.03986 1.6881,2.04277 2.673,3.00029 0.9849,0.95747 2.055,1.86716 3.2184,2.74566 1.1635,0.87851 2.4204,1.7246 3.7458,2.52747 1.3255,0.80292 2.7295,1.56057 4.2004,2.29116 1.4709,0.73054 3.0005,1.42942 4.6004,2.09106 1.5998,0.66165 3.27,1.29507 4.9822,1.89108 3.4244,1.19207 7.0445,2.25049 10.8191,3.20027 3.7747,0.94979 7.6993,1.79326 11.692,2.52746 3.9926,0.73426 8.0682,1.36379 12.1465,1.90929 4.0782,0.5455 8.1512,0.99837 12.1828,1.38194 4.0316,0.38356 8.0212,0.69713 11.8738,0.94553 0.3981,0.0256 0.6956,0.0122 1.091,0.0361 35.9837,-11.09972 64.9673,-28.45453 80.7161,-55.73206 6.9768,-13.08128 10.9282,-28.03414 10.9282,-43.89477 0,-51.568563 -41.7849,-93.371684 -93.3535,-93.371684 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<circle
|
||||||
|
style="fill:none;fill-opacity:0.8;stroke:#920080;stroke-width:0.367521;stroke-opacity:1"
|
||||||
|
id="path1"
|
||||||
|
cx="6.0803809"
|
||||||
|
cy="6.6884193"
|
||||||
|
r="4.1580262"
|
||||||
|
transform="matrix(74.047192,-2.9815935,2.9815935,74.047192,580.36067,-906.15614)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
56
files/opencs/brush-custom.svg
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="brush-custom"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(-96.39494,-63.540021)">
|
||||||
|
<rect
|
||||||
|
style="opacity:0;fill:#ffbe6f;stroke:#eff0f1;stroke-width:0;paint-order:stroke fill markers;stop-color:#000000"
|
||||||
|
id="rect2449"
|
||||||
|
width="12.699994"
|
||||||
|
height="12.699999"
|
||||||
|
x="95.514572"
|
||||||
|
y="63.76458" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#920080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000"
|
||||||
|
d="m 101.20313,66.54271 c -1.678876,0 -3.042711,1.363835 -3.042711,3.042709 8.2e-5,0.61718 0.198856,1.213246 0.548288,1.720307 -0.178268,0.276987 -0.283678,0.594905 -0.283704,0.925526 0,0.948248 0.771543,1.719791 1.719787,1.719791 0.827,1.09e-4 1.52138,-0.595452 1.67639,-1.399397 0.27684,-0.05797 0.54302,-0.155514 0.79323,-0.287321 0.4243,0.549629 1.06517,0.89282 1.76372,0.892968 1.2405,0 2.24896,-1.008459 2.24896,-2.248958 0,-1.240499 -1.00846,-2.248958 -2.24896,-2.248958 -0.0962,-1.11e-4 -0.19147,0.01262 -0.28681,0.02479 -0.39574,-1.263941 -1.55476,-2.141357 -2.88819,-2.141457 z m 0,0.264584 c 1.25466,9.5e-5 2.35238,0.839655 2.68097,2.05052 l 0.0315,0.116271 0.11886,-0.02066 c 0.11342,-0.01979 0.22851,-0.02959 0.34365,-0.02946 1.09751,0 1.98437,0.886868 1.98437,1.984375 0,1.097508 -0.88686,1.984375 -1.98437,1.984375 -0.65001,-1.37e-4 -1.2585,-0.318322 -1.62936,-0.852143 l -0.0687,-0.09922 -0.10542,0.05943 c -0.27347,0.155496 -0.57095,0.263626 -0.88057,0.31936 l -0.0946,0.01707 -0.0134,0.09509 c -0.10037,0.720193 -0.71411,1.254281 -1.44126,1.254186 -0.805258,0 -1.455209,-0.649952 -1.455209,-1.455209 2.3e-5,-0.304604 0.09566,-0.601652 0.273367,-0.849042 l 0.05581,-0.07751 -0.05684,-0.07752 c -0.348953,-0.476242 -0.536839,-1.051359 -0.536919,-1.641761 0,-1.535882 1.242243,-2.778125 2.778121,-2.778125 z"
|
||||||
|
id="path2188" />
|
||||||
|
<g
|
||||||
|
id="g3795"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
transform="matrix(0.01348304,5.4290912e-4,-5.4290912e-4,0.01348304,88.077953,75.442677)">
|
||||||
|
<path
|
||||||
|
id="path3793"
|
||||||
|
d="m 1432.3282,180.29088 c -0.3954,-0.0244 -0.6929,-0.0105 -1.091,-0.0361 -3.8526,-0.2484 -7.8422,-0.56196 -11.8738,-0.94553 -4.0316,-0.38357 -8.1046,-0.83644 -12.1828,-1.38194 -4.0783,-0.5455 -8.1539,-1.17502 -12.1465,-1.90928 -3.9927,-0.73421 -7.9173,-1.57768 -11.692,-2.52747 -3.7746,-0.94978 -7.3947,-2.0082 -10.8191,-3.20027 -1.7122,-0.59601 -3.3824,-1.22943 -4.9822,-1.89108 -1.5999,-0.66164 -3.1295,-1.36052 -4.6004,-2.09106 -1.4709,-0.73059 -2.8749,-1.48824 -4.2004,-2.29116 -1.3254,-0.80286 -2.5823,-1.64896 -3.7458,-2.52747 -1.1634,-0.8785 -2.2335,-1.78819 -3.2184,-2.74566 -0.9849,-0.95752 -1.8831,-1.96043 -2.673,-3.00029 -0.7898,-1.03985 -1.4765,-2.12929 -2.0547,-3.25479 -0.5782,-1.12557 -1.0501,-2.29484 -1.4001,-3.50943 -0.3501,-1.21459 -0.5856,-2.47515 -0.691,-3.78214 -0.1054,-1.307 -0.083,-2.65216 0.073,-4.05487 0.1559,-1.40277 0.2212,-2.7861 0.1819,-4.12766 -0.039,-1.34156 -0.1778,-2.64605 -0.4001,-3.92761 -0.2222,-1.28157 -0.5345,-2.5231 -0.9273,-3.74578 -0.3929,-1.22268 -0.8671,-2.41726 -1.4183,-3.58216 -0.5512,-1.16484 -1.1757,-2.31025 -1.8729,-3.41847 -0.6973,-1.10817 -1.4601,-2.18399 -2.2911,-3.23659 -0.8311,-1.05266 -1.7386,-2.07483 -2.6912,-3.07302 -0.9525,-0.9982 -1.9566,-1.98266 -3.0184,-2.92756 -1.0618,-0.94484 -2.1688,-1.85296 -3.3276,-2.74566 -1.1587,-0.8927 -2.375,-1.75864 -3.6185,-2.6002 -0.5162,-0.34947 -1.1071,-0.64116 -1.6365,-0.98196 -18.7596,41.685 -48.6658,67.50321 -110.1368,78.95234 -10.0671,1.87502 -6.7445,14.14668 0,14.14662 72.5797,0 156.074,-0.34097 218.4553,-19.58348 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path3849"
|
||||||
|
d="m 1430.619,-12.707633 c -45.8854,0 -84.0461,33.091677 -91.8989,76.715697 -4.2316,15.792726 -8.9665,30.004108 -14.7104,42.767336 0.5294,0.3408 1.1203,0.63249 1.6365,0.98196 1.2435,0.84156 2.4598,1.7075 3.6185,2.6002 1.1588,0.8927 2.2658,1.80082 3.3276,2.74566 1.0618,0.9449 2.0659,1.92936 3.0184,2.92756 0.9526,0.99819 1.8601,2.02036 2.6912,3.07302 0.831,1.0526 1.5938,2.12842 2.2911,3.23658 0.6972,1.10823 1.3217,2.25364 1.8729,3.41848 0.5512,1.1649 1.0254,2.35948 1.4183,3.58216 0.3928,1.22268 0.7051,2.46421 0.9273,3.74578 0.2223,1.28156 0.3607,2.58605 0.4001,3.92761 0.039,1.34156 -0.026,2.72489 -0.1819,4.12766 -0.1558,1.40271 -0.1781,2.74787 -0.073,4.05487 0.1054,1.30699 0.3409,2.56755 0.691,3.78214 0.35,1.21459 0.8219,2.38386 1.4001,3.50942 0.5782,1.12551 1.2649,2.21495 2.0547,3.2548 0.7899,1.03986 1.6881,2.04277 2.673,3.00029 0.9849,0.95747 2.055,1.86716 3.2184,2.74566 1.1635,0.87851 2.4204,1.7246 3.7458,2.52747 1.3255,0.80292 2.7295,1.56057 4.2004,2.29116 1.4709,0.73054 3.0005,1.42942 4.6004,2.09106 1.5998,0.66165 3.27,1.29507 4.9822,1.89108 3.4244,1.19207 7.0445,2.25049 10.8191,3.20027 3.7747,0.94979 7.6993,1.79326 11.692,2.52746 3.9926,0.73426 8.0682,1.36379 12.1465,1.90929 4.0782,0.5455 8.1512,0.99837 12.1828,1.38194 4.0316,0.38356 8.0212,0.69713 11.8738,0.94553 0.3981,0.0256 0.6956,0.0122 1.091,0.0361 35.9837,-11.09972 64.9673,-28.45453 80.7161,-55.73206 6.9768,-13.08128 10.9282,-28.03414 10.9282,-43.89477 0,-51.568563 -41.7849,-93.371684 -93.3535,-93.371684 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:14.1112;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 1223.0877,970.60693 c 3.4659,1.1301 69.3268,-132.17231 0.01,1.65348 22.4324,7.9982 57.8129,20.83702 84.2736,35.72149 31.47,17.7026 95.0975,62.919 130.2191,93.4513 159.6062,-258.85749 217.7622,-402.8573 250.8816,-481.45696 1.4672,-3.6726 -10.6381,-224.03518 -7.9288,-242.38296 0.1439,-0.97479 -4.636,-160.00618 -6.6178,-156.89403 -183.2275,287.73306 -308.4059,492.56152 -450.8377,749.90768 z m -18.5993,36.81547 c -10.343,-2.1435 -12.6893,2.7546 -14.3902,6.9154 -54.017,132.1446 -235.98278,450.7428 -258.39341,511.235 42.95377,6.6425 123.61141,56.0901 148.18501,89.6848 41.8408,-48.8743 238.2435,-354.2773 326.9039,-464.9703 3.3794,-4.2192 7.1429,-9.3124 11.2187,-15.1876 -31.8717,-28.1815 -90.6253,-67.9585 -118.9834,-84.5388 -27.4402,-16.0436 -52.8034,-27.3693 -75.3438,-35.4062 -5.3875,-1.921 -14.1678,-6.1689 -19.1968,-7.7323 z"
|
||||||
|
id="path3021"
|
||||||
|
transform="matrix(0.52516428,8.6770679e-8,-8.6770679e-8,0.52516428,961.78997,-828.86587)" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 787 B |
65
files/opencs/brush-point.svg
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-2" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="brush-point"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(-74.612486,-65.352077)">
|
||||||
|
<path
|
||||||
|
id="path1998"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#920080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 76.975838,71.657408 c -0.144291,0 -0.792839,0.121337 -0.792839,0.265625 0,0.144291 0.648546,0.263672 0.792839,0.263672 h 1.853515 c 0.144291,0 0.263672,-0.119384 0.263672,-0.263672 0,-0.144291 -0.119379,-0.265625 -0.263672,-0.265625 z m 3.96875,-3.439453 c 0,-0.144291 -0.119384,-0.792839 -0.263672,-0.792839 -0.144291,0 -0.265625,0.648546 -0.265625,0.792839 v 1.853515 c 0,0.144291 0.121337,0.263672 0.265625,0.263672 0.144291,0 0.263672,-0.119379 0.263672,-0.263672 z m 0,5.55664 c 0,-0.14429 -0.119384,-0.263671 -0.263672,-0.263671 -0.144291,0 -0.265625,0.119378 -0.265625,0.263671 v 1.851563 c 0,0.144291 0.121337,0.794792 0.265625,0.794792 0.144291,0 0.263672,-0.650499 0.263672,-0.794792 z m 1.58789,-2.117187 c -0.14429,0 -0.263671,0.121337 -0.263671,0.265625 0,0.144291 0.119378,0.263672 0.263671,0.263672 h 1.851563 c 0.144291,0 0.794792,-0.119384 0.794792,-0.263672 0,-0.144291 -0.650499,-0.265625 -0.794792,-0.265625 z" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#920080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 80.151619,70.864439 c -0.290872,0 -0.529297,0.238426 -0.529297,0.529297 v 1.058594 c 0,0.290872 0.238426,0.529297 0.529297,0.529297 h 1.058594 c 0.290872,0 0.529297,-0.238425 0.529297,-0.529297 v -1.058594 c 0,-0.290871 -0.238425,-0.529297 -0.529297,-0.529297 z m 0,0.265625 h 1.058594 c 0.14887,0 0.263672,0.114803 0.263672,0.263672 v 1.058594 c 0,0.14887 -0.114802,0.263672 -0.263672,0.263672 h -1.058594 c -0.148869,0 -0.263672,-0.114802 -0.263672,-0.263672 v -1.058594 c 0,-0.148869 0.114804,-0.263672 0.263672,-0.263672 z"
|
||||||
|
id="path1983" />
|
||||||
|
<g
|
||||||
|
id="g3795"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
transform="matrix(0.01348304,5.4290911e-4,-5.4290911e-4,0.01348304,66.295499,77.254733)">
|
||||||
|
<path
|
||||||
|
id="path3793"
|
||||||
|
d="m 1432.3282,180.29088 c -0.3954,-0.0244 -0.6929,-0.0105 -1.091,-0.0361 -3.8526,-0.2484 -7.8422,-0.56196 -11.8738,-0.94553 -4.0316,-0.38357 -8.1046,-0.83644 -12.1828,-1.38194 -4.0783,-0.5455 -8.1539,-1.17502 -12.1465,-1.90928 -3.9927,-0.73421 -7.9173,-1.57768 -11.692,-2.52747 -3.7746,-0.94978 -7.3947,-2.0082 -10.8191,-3.20027 -1.7122,-0.59601 -3.3824,-1.22943 -4.9822,-1.89108 -1.5999,-0.66164 -3.1295,-1.36052 -4.6004,-2.09106 -1.4709,-0.73059 -2.8749,-1.48824 -4.2004,-2.29116 -1.3254,-0.80286 -2.5823,-1.64896 -3.7458,-2.52747 -1.1634,-0.8785 -2.2335,-1.78819 -3.2184,-2.74566 -0.9849,-0.95752 -1.8831,-1.96043 -2.673,-3.00029 -0.7898,-1.03985 -1.4765,-2.12929 -2.0547,-3.25479 -0.5782,-1.12557 -1.0501,-2.29484 -1.4001,-3.50943 -0.3501,-1.21459 -0.5856,-2.47515 -0.691,-3.78214 -0.1054,-1.307 -0.083,-2.65216 0.073,-4.05487 0.1559,-1.40277 0.2212,-2.7861 0.1819,-4.12766 -0.039,-1.34156 -0.1778,-2.64605 -0.4001,-3.92761 -0.2222,-1.28157 -0.5345,-2.5231 -0.9273,-3.74578 -0.3929,-1.22268 -0.8671,-2.41726 -1.4183,-3.58216 -0.5512,-1.16484 -1.1757,-2.31025 -1.8729,-3.41847 -0.6973,-1.10817 -1.4601,-2.18399 -2.2911,-3.23659 -0.8311,-1.05266 -1.7386,-2.07483 -2.6912,-3.07302 -0.9525,-0.9982 -1.9566,-1.98266 -3.0184,-2.92756 -1.0618,-0.94484 -2.1688,-1.85296 -3.3276,-2.74566 -1.1587,-0.8927 -2.375,-1.75864 -3.6185,-2.6002 -0.5162,-0.34947 -1.1071,-0.64116 -1.6365,-0.98196 -18.7596,41.685 -48.6658,67.50321 -110.1368,78.95234 -10.0671,1.87502 -6.7445,14.14668 0,14.14662 72.5797,0 156.074,-0.34097 218.4553,-19.58348 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path3849"
|
||||||
|
d="m 1430.619,-12.707633 c -45.8854,0 -84.0461,33.091677 -91.8989,76.715697 -4.2316,15.792726 -8.9665,30.004108 -14.7104,42.767336 0.5294,0.3408 1.1203,0.63249 1.6365,0.98196 1.2435,0.84156 2.4598,1.7075 3.6185,2.6002 1.1588,0.8927 2.2658,1.80082 3.3276,2.74566 1.0618,0.9449 2.0659,1.92936 3.0184,2.92756 0.9526,0.99819 1.8601,2.02036 2.6912,3.07302 0.831,1.0526 1.5938,2.12842 2.2911,3.23658 0.6972,1.10823 1.3217,2.25364 1.8729,3.41848 0.5512,1.1649 1.0254,2.35948 1.4183,3.58216 0.3928,1.22268 0.7051,2.46421 0.9273,3.74578 0.2223,1.28156 0.3607,2.58605 0.4001,3.92761 0.039,1.34156 -0.026,2.72489 -0.1819,4.12766 -0.1558,1.40271 -0.1781,2.74787 -0.073,4.05487 0.1054,1.30699 0.3409,2.56755 0.691,3.78214 0.35,1.21459 0.8219,2.38386 1.4001,3.50942 0.5782,1.12551 1.2649,2.21495 2.0547,3.2548 0.7899,1.03986 1.6881,2.04277 2.673,3.00029 0.9849,0.95747 2.055,1.86716 3.2184,2.74566 1.1635,0.87851 2.4204,1.7246 3.7458,2.52747 1.3255,0.80292 2.7295,1.56057 4.2004,2.29116 1.4709,0.73054 3.0005,1.42942 4.6004,2.09106 1.5998,0.66165 3.27,1.29507 4.9822,1.89108 3.4244,1.19207 7.0445,2.25049 10.8191,3.20027 3.7747,0.94979 7.6993,1.79326 11.692,2.52746 3.9926,0.73426 8.0682,1.36379 12.1465,1.90929 4.0782,0.5455 8.1512,0.99837 12.1828,1.38194 4.0316,0.38356 8.0212,0.69713 11.8738,0.94553 0.3981,0.0256 0.6956,0.0122 1.091,0.0361 35.9837,-11.09972 64.9673,-28.45453 80.7161,-55.73206 6.9768,-13.08128 10.9282,-28.03414 10.9282,-43.89477 0,-51.568563 -41.7849,-93.371684 -93.3535,-93.371684 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.01348304,5.4290911e-4,-5.4290911e-4,0.01348304,66.295499,77.254733)"
|
||||||
|
id="g3861"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:14.1112;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 1223.0877,970.60693 c 3.4659,1.1301 69.3268,-132.17231 0.01,1.65348 22.4324,7.9982 57.8129,20.83702 84.2736,35.72149 31.47,17.7026 95.0975,62.919 130.2191,93.4513 159.6062,-258.85749 217.7622,-402.8573 250.8816,-481.45696 1.4672,-3.6726 -10.6381,-224.03518 -7.9288,-242.38296 0.1439,-0.97479 -4.6307,-160.00282 -6.6178,-156.89403 -185.4652,290.15856 -351.8616,515.32983 -450.8377,749.90768 z m -18.5993,36.81547 c -10.343,-2.1435 -12.6893,2.7546 -14.3902,6.9154 -54.017,132.1446 -235.98278,450.7428 -258.39341,511.235 42.95377,6.6425 123.61141,56.0901 148.18501,89.6848 41.8408,-48.8743 238.2435,-354.2773 326.9039,-464.9703 3.3794,-4.2192 7.1429,-9.3124 11.2187,-15.1876 -31.8717,-28.1815 -90.6253,-67.9585 -118.9834,-84.5388 -27.4402,-16.0436 -52.8034,-27.3693 -75.3438,-35.4062 -5.3875,-1.921 -14.1678,-6.1689 -19.1968,-7.7323 z"
|
||||||
|
id="path3021"
|
||||||
|
transform="matrix(0.52516433,0,0,0.52516433,961.78994,-828.86591)" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 761 B |
52
files/opencs/brush-square.svg
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
transform="matrix(0.01348304,5.4290978e-4,-5.4290978e-4,0.01348304,-8.3169871,11.902656)"
|
||||||
|
id="g3861"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:14.1112;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 1223.0877,970.60693 c 3.4659,1.1301 69.3268,-132.17231 0.01,1.65348 22.4324,7.9982 57.8129,20.83702 84.2736,35.72149 31.47,17.7026 95.0975,62.919 130.2191,93.4513 159.6062,-258.85749 217.7622,-402.8573 250.8816,-481.45696 1.4672,-3.6726 -10.6381,-224.03518 -7.9288,-242.38296 0.1439,-0.97479 -4.636,-160.00618 -6.6178,-156.89403 -183.2275,287.73306 -308.4059,492.56152 -450.8377,749.90768 z m -18.5993,36.81547 c -10.343,-2.1435 -12.6893,2.7546 -14.3902,6.9154 -54.017,132.1446 -235.98278,450.7428 -258.39341,511.235 42.95377,6.6425 123.61141,56.0901 148.18501,89.6848 41.8408,-48.8743 238.2435,-354.2773 326.9039,-464.9703 3.3794,-4.2192 7.1429,-9.3124 11.2187,-15.1876 -31.8717,-28.1815 -90.6253,-67.9585 -118.9834,-84.5388 -27.4402,-16.0436 -52.8034,-27.3693 -75.3438,-35.4062 -5.3875,-1.921 -14.1678,-6.1689 -19.1968,-7.7323 z"
|
||||||
|
id="path3021"
|
||||||
|
transform="matrix(0.52516433,0,0,0.52516433,961.78994,-828.86591)" />
|
||||||
|
<g
|
||||||
|
id="g3795"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:7.41072;stroke-dasharray:none;stroke-opacity:1">
|
||||||
|
<path
|
||||||
|
id="path3793"
|
||||||
|
d="m 1432.3282,180.29088 c -0.3954,-0.0244 -0.6929,-0.0105 -1.091,-0.0361 -3.8526,-0.2484 -7.8422,-0.56196 -11.8738,-0.94553 -4.0316,-0.38357 -8.1046,-0.83644 -12.1828,-1.38194 -4.0783,-0.5455 -8.1539,-1.17502 -12.1465,-1.90928 -3.9927,-0.73421 -7.9173,-1.57768 -11.692,-2.52747 -3.7746,-0.94978 -7.3947,-2.0082 -10.8191,-3.20027 -1.7122,-0.59601 -3.3824,-1.22943 -4.9822,-1.89108 -1.5999,-0.66164 -3.1295,-1.36052 -4.6004,-2.09106 -1.4709,-0.73059 -2.8749,-1.48824 -4.2004,-2.29116 -1.3254,-0.80286 -2.5823,-1.64896 -3.7458,-2.52747 -1.1634,-0.8785 -2.2335,-1.78819 -3.2184,-2.74566 -0.9849,-0.95752 -1.8831,-1.96043 -2.673,-3.00029 -0.7898,-1.03985 -1.4765,-2.12929 -2.0547,-3.25479 -0.5782,-1.12557 -1.0501,-2.29484 -1.4001,-3.50943 -0.3501,-1.21459 -0.5856,-2.47515 -0.691,-3.78214 -0.1054,-1.307 -0.083,-2.65216 0.073,-4.05487 0.1559,-1.40277 0.2212,-2.7861 0.1819,-4.12766 -0.039,-1.34156 -0.1778,-2.64605 -0.4001,-3.92761 -0.2222,-1.28157 -0.5345,-2.5231 -0.9273,-3.74578 -0.3929,-1.22268 -0.8671,-2.41726 -1.4183,-3.58216 -0.5512,-1.16484 -1.1757,-2.31025 -1.8729,-3.41847 -0.6973,-1.10817 -1.4601,-2.18399 -2.2911,-3.23659 -0.8311,-1.05266 -1.7386,-2.07483 -2.6912,-3.07302 -0.9525,-0.9982 -1.9566,-1.98266 -3.0184,-2.92756 -1.0618,-0.94484 -2.1688,-1.85296 -3.3276,-2.74566 -1.1587,-0.8927 -2.375,-1.75864 -3.6185,-2.6002 -0.5162,-0.34947 -1.1071,-0.64116 -1.6365,-0.98196 -18.7596,41.685 -48.6658,67.50321 -110.1368,78.95234 -10.0671,1.87502 -6.7445,14.14668 0,14.14662 72.5797,0 156.074,-0.34097 218.4553,-19.58348 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path3849"
|
||||||
|
d="m 1430.619,-12.707633 c -45.8854,0 -84.0461,33.091677 -91.8989,76.715697 -4.2316,15.792726 -8.9665,30.004108 -14.7104,42.767336 0.5294,0.3408 1.1203,0.63249 1.6365,0.98196 1.2435,0.84156 2.4598,1.7075 3.6185,2.6002 1.1588,0.8927 2.2658,1.80082 3.3276,2.74566 1.0618,0.9449 2.0659,1.92936 3.0184,2.92756 0.9526,0.99819 1.8601,2.02036 2.6912,3.07302 0.831,1.0526 1.5938,2.12842 2.2911,3.23658 0.6972,1.10823 1.3217,2.25364 1.8729,3.41848 0.5512,1.1649 1.0254,2.35948 1.4183,3.58216 0.3928,1.22268 0.7051,2.46421 0.9273,3.74578 0.2223,1.28156 0.3607,2.58605 0.4001,3.92761 0.039,1.34156 -0.026,2.72489 -0.1819,4.12766 -0.1558,1.40271 -0.1781,2.74787 -0.073,4.05487 0.1054,1.30699 0.3409,2.56755 0.691,3.78214 0.35,1.21459 0.8219,2.38386 1.4001,3.50942 0.5782,1.12551 1.2649,2.21495 2.0547,3.2548 0.7899,1.03986 1.6881,2.04277 2.673,3.00029 0.9849,0.95747 2.055,1.86716 3.2184,2.74566 1.1635,0.87851 2.4204,1.7246 3.7458,2.52747 1.3255,0.80292 2.7295,1.56057 4.2004,2.29116 1.4709,0.73054 3.0005,1.42942 4.6004,2.09106 1.5998,0.66165 3.27,1.29507 4.9822,1.89108 3.4244,1.19207 7.0445,2.25049 10.8191,3.20027 3.7747,0.94979 7.6993,1.79326 11.692,2.52746 3.9926,0.73426 8.0682,1.36379 12.1465,1.90929 4.0782,0.5455 8.1512,0.99837 12.1828,1.38194 4.0316,0.38356 8.0212,0.69713 11.8738,0.94553 0.3981,0.0256 0.6956,0.0122 1.091,0.0361 35.9837,-11.09972 64.9673,-28.45453 80.7161,-55.73206 6.9768,-13.08128 10.9282,-28.03414 10.9282,-43.89477 0,-51.568563 -41.7849,-93.371684 -93.3535,-93.371684 z"
|
||||||
|
style="fill:#4d4d4d;fill-opacity:1;stroke:#808080;stroke-width:8.21086;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#920080;stroke-width:24.154;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect4"
|
||||||
|
width="551.00012"
|
||||||
|
height="551.00012"
|
||||||
|
x="759.14246"
|
||||||
|
y="-686.99188"
|
||||||
|
transform="rotate(-2.3058334)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 750 B |
63
files/opencs/camera-first-person.svg
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main"
|
||||||
|
gradientTransform="translate(63.499994)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Blue"
|
||||||
|
gradientTransform="matrix(0.26458333,0,0,0.26458333,-13.80713,103.48169)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#55c3ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2484" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Blue"
|
||||||
|
id="linearGradient2809"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="7.4083338"
|
||||||
|
y1="-3.7041662"
|
||||||
|
x2="11.641667"
|
||||||
|
y2="-3.7041662" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="camera-first-person"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(1.3333345,0,0,1.333334,-190.85285,-85.019482)">
|
||||||
|
<path
|
||||||
|
id="rect2331"
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:url(#linearGradient2809);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="M 558.40946,259.99589 557.5,270 h 3 l 0.91695,11.00345 A 1.0867995,1.0867995 42.618179 0 0 562.5,282 h 5 a 1.0867995,1.0867995 137.38182 0 0 1.08305,-0.99655 L 569.5,270 h 2.75 l -0.90946,-10.00411 A 1.0950328,1.0950328 42.402786 0 0 570.25,259 H 559.5 a 1.0950328,1.0950328 137.59721 0 0 -1.09054,0.99589 z"
|
||||||
|
transform="scale(0.26458333)" />
|
||||||
|
<ellipse
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="ellipse2327"
|
||||||
|
cx="149.48953"
|
||||||
|
cy="67.071899"
|
||||||
|
rx="1.5874941"
|
||||||
|
ry="1.5875033" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#241f31;fill-opacity:1;stroke:none;stroke-width:0.326641px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="circle2329"
|
||||||
|
cx="150.01872"
|
||||||
|
cy="67.204193"
|
||||||
|
r="0.52916664" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 783 B |
76
files/opencs/camera-free.svg
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main"
|
||||||
|
gradientTransform="translate(63.499994)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Blue"
|
||||||
|
gradientTransform="matrix(0.26458333,0,0,0.26458333,-13.80713,103.48169)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#55c3ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2484" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="camera-free"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(1.3333345,0,0,1.3333335,-169.68618,-85.01945)">
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="ellipse2315"
|
||||||
|
cx="133.08542"
|
||||||
|
cy="72.628128"
|
||||||
|
r="1.3229166" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="circle2319"
|
||||||
|
cx="131.36563"
|
||||||
|
cy="68.130211"
|
||||||
|
r="1.4552083" />
|
||||||
|
<ellipse
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#241f31;fill-opacity:1;stroke:none;stroke-width:0.237741px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="circle2317"
|
||||||
|
cx="123.01057"
|
||||||
|
cy="68.208794"
|
||||||
|
rx="0.48718452"
|
||||||
|
ry="0.46406204"
|
||||||
|
transform="matrix(1,0,0.12650781,0.99196561,0,0)" />
|
||||||
|
<ellipse
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#241f31;fill-opacity:1;stroke:none;stroke-width:0.205204px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="circle2321"
|
||||||
|
cx="132.5358"
|
||||||
|
cy="72.584305"
|
||||||
|
rx="0.3821989"
|
||||||
|
ry="0.440696" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="circle2323"
|
||||||
|
cx="135.99583"
|
||||||
|
cy="69.056252"
|
||||||
|
r="1.984375" />
|
||||||
|
<ellipse
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#241f31;fill-opacity:1;stroke:none;stroke-width:0.326641px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="ellipse2325"
|
||||||
|
cx="136.92188"
|
||||||
|
cy="69.171593"
|
||||||
|
rx="0.65753078"
|
||||||
|
ry="0.64905536" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.1 KiB |
62
files/opencs/camera-orbit.svg
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48pt"
|
||||||
|
height="48pt"
|
||||||
|
viewBox="0 0 16.933333 16.933333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="Main"
|
||||||
|
gradientTransform="translate(63.499994)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Blue"
|
||||||
|
gradientTransform="matrix(0.26458333,0,0,0.26458333,-13.80713,103.48169)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#55c3ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2484" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Blue"
|
||||||
|
id="linearGradient2502"
|
||||||
|
x1="7.4083338"
|
||||||
|
y1="-3.7041662"
|
||||||
|
x2="11.641667"
|
||||||
|
y2="-3.7041662"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="camera-orbit"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(1.3333345,0,0,1.333334,-148.51954,-85.019482)">
|
||||||
|
<path
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:url(#linearGradient2502);fill-opacity:1;stroke:none;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 114.81181,69.118264 c -3.49828,3.08633 1.51943,2.817376 3.58014,2.334121 2.06071,-0.483255 7.1306,-3.705601 -1.60983,-3.162598 7.34302,-2.156354 7.21991,2.475405 2.60397,3.889003 -4.95879,1.518595 -8.7571,-0.657262 -4.57428,-3.060526 z"
|
||||||
|
id="path2279" />
|
||||||
|
<ellipse
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path2257"
|
||||||
|
cx="115.8875"
|
||||||
|
cy="68.659378"
|
||||||
|
rx="1.5874941"
|
||||||
|
ry="1.5875033" />
|
||||||
|
<circle
|
||||||
|
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#241f31;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
id="path2261"
|
||||||
|
cx="116.41667"
|
||||||
|
cy="69.056252"
|
||||||
|
r="0.52916664" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.2 KiB |
83
files/opencs/cell.svg
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Red">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff664d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2533" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect3119">
|
||||||
|
<path
|
||||||
|
id="path3117"
|
||||||
|
style="opacity:1;fill:#000000;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 10.250537,66.995394 -0.0047,0.0047 c -0.02767,-0.0066 -0.211799,-0.04039 -0.4563028,0.204116 C 9.6572915,67.468749 9.6572915,67.468749 9.5249999,67.49562 9.3927082,67.468749 9.3927082,67.468749 9.2604165,67.204166 9.061979,67.005731 8.8982935,66.990872 8.8289184,66.99591 c -0.023124,0.0016 -0.035657,0.0057 -0.035657,0.0057 0,0 -0.062009,0.20257 0.2025716,0.467154 0.2645833,0.132291 0.2645841,0.132291 0.291455,0.264583 -0.026871,0.132292 -0.026872,0.132292 -0.291455,0.264583 -0.2445017,0.244505 -0.2107512,0.428639 -0.2041218,0.456304 l -0.00465,0.0047 c 0,0 0.00465,2.65e-4 0.00517,5.29e-4 1.736e-4,5.3e-4 0.00103,0.0057 0.00103,0.0057 l 0.00465,-0.0047 c 0.027721,0.0066 0.2118445,0.04033 0.4563028,-0.204123 0.1322919,-0.264584 0.1322919,-0.264584 0.2645833,-0.291455 0.1322919,0.02687 0.1322917,0.02687 0.2645833,0.291455 0.1984378,0.198435 0.3621234,0.213294 0.4314984,0.208256 0.02312,-0.0016 0.03566,-0.0057 0.03566,-0.0057 0,0 0.06201,-0.20257 -0.202572,-0.467156 -0.2645836,-0.132289 -0.2645839,-0.132291 -0.291455,-0.264583 0.026871,-0.132279 0.026873,-0.132292 0.291455,-0.264583 0.244502,-0.244505 0.210752,-0.428639 0.204122,-0.456304 l 0.0047,-0.0047 c 0,0 -0.0046,-7.94e-4 -0.0052,-0.0011 -1.47e-4,-5.29e-4 -10e-4,-0.0052 -10e-4,-0.0052 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Green"
|
||||||
|
gradientTransform="scale(3.7795276)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#66ff7a;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2506" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Green"
|
||||||
|
id="linearGradient4011"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="2.1166668"
|
||||||
|
y1="4.2333336"
|
||||||
|
x2="6.3500004"
|
||||||
|
y2="4.2333336"
|
||||||
|
gradientTransform="translate(21.166665,37.041663)" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient4013"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="2.1166666"
|
||||||
|
y1="4.2333336"
|
||||||
|
x2="6.3500004"
|
||||||
|
y2="4.2333336"
|
||||||
|
gradientTransform="matrix(0.26458333,0,0,0.26458333,21.166665,37.041663)" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="cell"
|
||||||
|
transform="matrix(3.7795278,0,0,3.7795278,-87.999996,-147.99999)"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="path887"
|
||||||
|
style="fill:url(#linearGradient4011);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 24.077082,39.95208 h 2.645833 v 2.645833 c 0,0 -2.645833,0 -2.645833,0 z m -0.264584,-0.79375 v 0.529166 h -0.529166 v 0.264584 h 0.529166 v 2.645833 h -0.529166 v 0.264583 h 0.529166 v 0.529167 h 0.264584 v -0.529167 h 2.645833 v 0.529167 h 0.264583 v -0.529167 h 0.529167 V 42.597913 H 26.987498 V 39.95208 h 0.529167 V 39.687496 H 26.987498 V 39.15833 h -0.264583 v 0.529166 H 24.077082 V 39.15833 Z" />
|
||||||
|
<path
|
||||||
|
id="rect890"
|
||||||
|
style="fill:url(#linearGradient4013);fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||||
|
d="m 24.341665,40.216663 v 2.116667 h 2.116667 v -2.116667 z m 0.264583,0.264583 h 1.5875 v 1.5875 h -1.5875 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 588 B |
186
files/opencs/class.svg
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Red">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff664d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2533" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect3119">
|
||||||
|
<path
|
||||||
|
id="path3117"
|
||||||
|
style="opacity:1;fill:#000000;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 10.250537,66.995394 -0.0047,0.0047 c -0.02767,-0.0066 -0.211799,-0.04039 -0.4563028,0.204116 C 9.6572915,67.468749 9.6572915,67.468749 9.5249999,67.49562 9.3927082,67.468749 9.3927082,67.468749 9.2604165,67.204166 9.061979,67.005731 8.8982935,66.990872 8.8289184,66.99591 c -0.023124,0.0016 -0.035657,0.0057 -0.035657,0.0057 0,0 -0.062009,0.20257 0.2025716,0.467154 0.2645833,0.132291 0.2645841,0.132291 0.291455,0.264583 -0.026871,0.132292 -0.026872,0.132292 -0.291455,0.264583 -0.2445017,0.244505 -0.2107512,0.428639 -0.2041218,0.456304 l -0.00465,0.0047 c 0,0 0.00465,2.65e-4 0.00517,5.29e-4 1.736e-4,5.3e-4 0.00103,0.0057 0.00103,0.0057 l 0.00465,-0.0047 c 0.027721,0.0066 0.2118445,0.04033 0.4563028,-0.204123 0.1322919,-0.264584 0.1322919,-0.264584 0.2645833,-0.291455 0.1322919,0.02687 0.1322917,0.02687 0.2645833,0.291455 0.1984378,0.198435 0.3621234,0.213294 0.4314984,0.208256 0.02312,-0.0016 0.03566,-0.0057 0.03566,-0.0057 0,0 0.06201,-0.20257 -0.202572,-0.467156 -0.2645836,-0.132289 -0.2645839,-0.132291 -0.291455,-0.264583 0.026871,-0.132279 0.026873,-0.132292 0.291455,-0.264583 0.244502,-0.244505 0.210752,-0.428639 0.204122,-0.456304 l 0.0047,-0.0047 c 0,0 -0.0046,-7.94e-4 -0.0052,-0.0011 -1.47e-4,-5.29e-4 -10e-4,-0.0052 -10e-4,-0.0052 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Green"
|
||||||
|
gradientTransform="scale(3.7795276)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#66ff7a;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2506" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect1741">
|
||||||
|
<path
|
||||||
|
id="path1739"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:0.992157;stroke:none;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.095414,60.589583 a 0.52916663,0.52916663 0 0 0 -0.516248,0.529166 0.52916663,0.52916663 0 0 0 0.529167,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529166 0.52916663,0.52916663 0 0 0 -0.01292,0 z m -1.058333,2.116666 A 0.52916663,0.52916663 0 0 0 18.520833,63.235416 0.52916663,0.52916663 0 0 0 19.05,63.764583 0.52916663,0.52916663 0 0 0 19.579166,63.235416 0.52916663,0.52916663 0 0 0 19.05,62.706249 a 0.52916663,0.52916663 0 0 0 -0.01292,0 z m 2.116666,0 a 0.52916663,0.52916663 0 0 0 -0.516247,0.529167 0.52916663,0.52916663 0 0 0 0.529166,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.01292,0 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2220"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="62.44165"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="62.44165"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect1741-0">
|
||||||
|
<path
|
||||||
|
id="mask-powermask-path-effect1741_box"
|
||||||
|
style="fill:#ffffff;fill-opacity:1"
|
||||||
|
d="m 16.991666,59.324974 h 6.233333 v 6.233352 h -6.233333 z" />
|
||||||
|
<path
|
||||||
|
id="path1739-0"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:0.992157;stroke:none;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.095414,60.589583 a 0.52916663,0.52916663 0 0 0 -0.516248,0.529166 0.52916663,0.52916663 0 0 0 0.529167,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529166 0.52916663,0.52916663 0 0 0 -0.01292,0 z m -1.058333,2.116666 A 0.52916663,0.52916663 0 0 0 18.520833,63.235416 0.52916663,0.52916663 0 0 0 19.05,63.764583 0.52916663,0.52916663 0 0 0 19.579166,63.235416 0.52916663,0.52916663 0 0 0 19.05,62.706249 a 0.52916663,0.52916663 0 0 0 -0.01292,0 z m 2.116666,0 a 0.52916663,0.52916663 0 0 0 -0.516247,0.529167 0.52916663,0.52916663 0 0 0 0.529166,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.01292,0 z" />
|
||||||
|
</mask>
|
||||||
|
<filter
|
||||||
|
id="mask-powermask-path-effect1741_inverse"
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
x="-50"
|
||||||
|
y="-50">
|
||||||
|
<feColorMatrix
|
||||||
|
id="mask-powermask-path-effect1741_primitive1"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="mask-powermask-path-effect1741_primitive2"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
|
||||||
|
in="fbSourceGraphic" />
|
||||||
|
</filter>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect1741-7">
|
||||||
|
<path
|
||||||
|
id="mask-powermask-path-effect1741-7_box"
|
||||||
|
style="fill:#ffffff;fill-opacity:1"
|
||||||
|
d="m 16.991666,59.324974 h 6.233333 v 6.233352 h -6.233333 z" />
|
||||||
|
<path
|
||||||
|
id="path1"
|
||||||
|
style="fill:#ffffff;fill-opacity:1"
|
||||||
|
d="m 16.991666,59.324974 h 6.233333 v 6.233352 h -6.233333 z" />
|
||||||
|
<path
|
||||||
|
id="path2"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:0.992157;stroke:none;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.095414,60.589583 a 0.52916663,0.52916663 0 0 0 -0.516248,0.529166 0.52916663,0.52916663 0 0 0 0.529167,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529166 0.52916663,0.52916663 0 0 0 -0.01292,0 z m -1.058333,2.116666 A 0.52916663,0.52916663 0 0 0 18.520833,63.235416 0.52916663,0.52916663 0 0 0 19.05,63.764583 0.52916663,0.52916663 0 0 0 19.579166,63.235416 0.52916663,0.52916663 0 0 0 19.05,62.706249 a 0.52916663,0.52916663 0 0 0 -0.01292,0 z m 2.116666,0 a 0.52916663,0.52916663 0 0 0 -0.516247,0.529167 0.52916663,0.52916663 0 0 0 0.529166,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.01292,0 z" />
|
||||||
|
</mask>
|
||||||
|
<filter
|
||||||
|
id="mask-powermask-path-effect1741-7_inverse"
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
x="-50"
|
||||||
|
y="-50">
|
||||||
|
<feColorMatrix
|
||||||
|
id="mask-powermask-path-effect1741-7_primitive1"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="mask-powermask-path-effect1741-7_primitive2"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
|
||||||
|
in="fbSourceGraphic" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="62.44165"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="62.44165" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient3"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="62.44165"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="62.44165" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient4"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="17.991667"
|
||||||
|
y1="62.44165"
|
||||||
|
x2="22.224998"
|
||||||
|
y2="62.44165" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="class"
|
||||||
|
transform="matrix(3.7795269,0,0,3.7795061,-67.999981,-147.99907)"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g1724"
|
||||||
|
mask="url(#mask-powermask-path-effect1741-7)"
|
||||||
|
transform="translate(0,-21.166665)"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2220);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">
|
||||||
|
<path
|
||||||
|
id="path843"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108333,60.324994 a 2.1166666,2.1166666 0 0 0 -2.116667,2.116667 2.1166666,2.1166666 0 0 0 2.116667,2.116665 2.1166666,2.1166666 0 0 0 2.116666,-2.116665 2.1166666,2.1166666 0 0 0 -2.116666,-2.116667 z m -0.02479,0.264583 a 1.8520806,1.8520806 0 0 1 0.02479,0 1.8520806,1.8520806 0 0 1 1.852082,1.852084 1.8520806,1.8520806 0 0 1 -1.852082,1.852083 1.8520806,1.8520806 0 0 1 -1.852084,-1.852083 1.8520806,1.8520806 0 0 1 1.827279,-1.852084 z" />
|
||||||
|
<path
|
||||||
|
id="path850"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#Main-6);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.108333,60.854161 a 1.5875,1.5875 0 0 0 -1.5875,1.5875 1.5875,1.5875 0 0 0 1.5875,1.587499 1.5875,1.5875 0 0 0 1.587499,-1.587499 1.5875,1.5875 0 0 0 -1.587499,-1.5875 z m 5.29e-4,0.264583 a 1.3235013,1.3229139 0 0 1 1.323435,1.322917 1.3235013,1.3229139 0 0 1 -1.323435,1.322916 1.3235013,1.3229139 0 0 1 -1.323433,-1.322916 1.3235013,1.3229139 0 0 1 1.323433,-1.322917 z" />
|
||||||
|
<path
|
||||||
|
id="path860"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient3);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.094895,60.325002 a 0.79375,0.79375 0 0 0 -0.780315,0.79375 0.79375,0.79375 0 0 0 0.79375,0.79375 0.79375,0.79375 0 0 0 0.793749,-0.79375 0.79375,0.79375 0 0 0 -0.793749,-0.79375 0.79375,0.79375 0 0 0 -0.01344,0 z m 5.29e-4,0.264584 a 0.52916664,0.52916664 0 0 1 0.01291,0 0.52916664,0.52916664 0 0 1 0.529166,0.529166 0.52916664,0.52916664 0 0 1 -0.529166,0.529167 0.52916664,0.52916664 0 0 1 -0.529167,-0.529167 0.52916664,0.52916664 0 0 1 0.516247,-0.529166 z"
|
||||||
|
mask="none" />
|
||||||
|
<path
|
||||||
|
id="path867"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#Main-6);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 19.036561,62.441668 a 0.79375,0.79375 0 0 0 -0.780315,0.793749 0.79375,0.79375 0 0 0 0.79375,0.79375 0.79375,0.79375 0 0 0 0.79375,-0.79375 0.79375,0.79375 0 0 0 -0.79375,-0.793749 0.79375,0.79375 0 0 0 -0.01344,0 z m 5.29e-4,0.264584 a 0.52916664,0.52916664 0 0 1 0.01291,0 0.52916664,0.52916664 0 0 1 0.529166,0.529165 A 0.52916664,0.52916664 0 0 1 19.05,63.764584 0.52916664,0.52916664 0 0 1 18.520833,63.235417 0.52916664,0.52916664 0 0 1 19.03708,62.706252 Z" />
|
||||||
|
<path
|
||||||
|
id="path869"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient4);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 21.153232,62.441668 a 0.79375,0.79375 0 0 0 -0.780314,0.793749 0.79375,0.79375 0 0 0 0.793749,0.79375 0.79375,0.79375 0 0 0 0.79375,-0.79375 0.79375,0.79375 0 0 0 -0.79375,-0.793749 0.79375,0.79375 0 0 0 -0.01344,0 z m 5.3e-4,0.264584 a 0.52916664,0.52916664 0 0 1 0.01291,0 0.52916664,0.52916664 0 0 1 0.529166,0.529165 0.52916664,0.52916664 0 0 1 -0.529166,0.529167 0.52916664,0.52916664 0 0 1 -0.529167,-0.529167 0.52916664,0.52916664 0 0 1 0.516247,-0.529165 z" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 369 B |
101
files/opencs/clothing.svg
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.0"
|
||||||
|
width="16.000000pt"
|
||||||
|
height="16.000000pt"
|
||||||
|
viewBox="0 0 16.000000 16.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
id="svg2"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
id="Main">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Red">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ff664d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2533" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect3119">
|
||||||
|
<path
|
||||||
|
id="path3117"
|
||||||
|
style="opacity:1;fill:#000000;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 10.250537,66.995394 -0.0047,0.0047 c -0.02767,-0.0066 -0.211799,-0.04039 -0.4563028,0.204116 C 9.6572915,67.468749 9.6572915,67.468749 9.5249999,67.49562 9.3927082,67.468749 9.3927082,67.468749 9.2604165,67.204166 9.061979,67.005731 8.8982935,66.990872 8.8289184,66.99591 c -0.023124,0.0016 -0.035657,0.0057 -0.035657,0.0057 0,0 -0.062009,0.20257 0.2025716,0.467154 0.2645833,0.132291 0.2645841,0.132291 0.291455,0.264583 -0.026871,0.132292 -0.026872,0.132292 -0.291455,0.264583 -0.2445017,0.244505 -0.2107512,0.428639 -0.2041218,0.456304 l -0.00465,0.0047 c 0,0 0.00465,2.65e-4 0.00517,5.29e-4 1.736e-4,5.3e-4 0.00103,0.0057 0.00103,0.0057 l 0.00465,-0.0047 c 0.027721,0.0066 0.2118445,0.04033 0.4563028,-0.204123 0.1322919,-0.264584 0.1322919,-0.264584 0.2645833,-0.291455 0.1322919,0.02687 0.1322917,0.02687 0.2645833,0.291455 0.1984378,0.198435 0.3621234,0.213294 0.4314984,0.208256 0.02312,-0.0016 0.03566,-0.0057 0.03566,-0.0057 0,0 0.06201,-0.20257 -0.202572,-0.467156 -0.2645836,-0.132289 -0.2645839,-0.132291 -0.291455,-0.264583 0.026871,-0.132279 0.026873,-0.132292 0.291455,-0.264583 0.244502,-0.244505 0.210752,-0.428639 0.204122,-0.456304 l 0.0047,-0.0047 c 0,0 -0.0046,-7.94e-4 -0.0052,-0.0011 -1.47e-4,-5.29e-4 -10e-4,-0.0052 -10e-4,-0.0052 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
id="Main-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2082-3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="Green"
|
||||||
|
gradientTransform="scale(3.7795276)">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#66ff7a;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop2506" />
|
||||||
|
</linearGradient>
|
||||||
|
<mask
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
id="mask-powermask-path-effect1741">
|
||||||
|
<path
|
||||||
|
id="path1739"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000000;fill-opacity:0.992157;stroke:none;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 20.095414,60.589583 a 0.52916663,0.52916663 0 0 0 -0.516248,0.529166 0.52916663,0.52916663 0 0 0 0.529167,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529166 0.52916663,0.52916663 0 0 0 -0.01292,0 z m -1.058333,2.116666 A 0.52916663,0.52916663 0 0 0 18.520833,63.235416 0.52916663,0.52916663 0 0 0 19.05,63.764583 0.52916663,0.52916663 0 0 0 19.579166,63.235416 0.52916663,0.52916663 0 0 0 19.05,62.706249 a 0.52916663,0.52916663 0 0 0 -0.01292,0 z m 2.116666,0 a 0.52916663,0.52916663 0 0 0 -0.516247,0.529167 0.52916663,0.52916663 0 0 0 0.529166,0.529167 0.52916663,0.52916663 0 0 0 0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.529167,-0.529167 0.52916663,0.52916663 0 0 0 -0.01292,0 z" />
|
||||||
|
</mask>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2356"
|
||||||
|
x1="24.077084"
|
||||||
|
y1="15.345833"
|
||||||
|
x2="26.722918"
|
||||||
|
y2="15.345833"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2358"
|
||||||
|
x1="23.283335"
|
||||||
|
y1="14.022916"
|
||||||
|
x2="27.516666"
|
||||||
|
y2="14.022916"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#Main-6"
|
||||||
|
id="linearGradient2360"
|
||||||
|
x1="24.606251"
|
||||||
|
y1="13.49375"
|
||||||
|
x2="26.19375"
|
||||||
|
y2="13.49375"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="clothing"
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(3.7795278,0,0,3.7795278,-88.000008,-48.000002)">
|
||||||
|
<path
|
||||||
|
id="rect923"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2356);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 24.077084,14.022917 v 2.645833 h 2.645833 V 14.022917 H 26.458334 V 15.875 h -2.116667 v -1.852083 z m 0.264583,2.116666 h 2.116667 v 0.264584 h -2.116667 z" />
|
||||||
|
<path
|
||||||
|
id="rect939"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2358);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 24.232113,12.964583 -0.948779,0.94878 V 14.2875 l 0.79375,0.79375 0.187068,-0.187069 -0.716235,-0.716235 v -0.155029 l 0.79375,-0.79375 h 2.116667 l 0.79375,0.79375 v 0.155029 l -0.716235,0.716235 0.187068,0.187069 0.79375,-0.79375 v -0.374137 l -0.948779,-0.94878 z" />
|
||||||
|
<path
|
||||||
|
id="rect941"
|
||||||
|
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient2360);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m 24.606251,13.229167 c 0,0.293158 0.236008,0.529166 0.529166,0.529166 h 0.529167 c 0.293159,0 0.529167,-0.236008 0.529167,-0.529166 -0.264584,0 -0.264584,0 -0.264584,0 0,0.14658 -0.118004,0.264583 -0.264583,0.264583 h -0.529167 c -0.146579,0 -0.264583,-0.118003 -0.264583,-0.264583 z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 421 B |