Merge branch 'master' of https://gitlab.com/OpenMW/openmw into fix7970-remove-removed-spells-on-rest

esm4-texture
trav5 8 months ago
commit 3f26a6c5a0

@ -173,6 +173,7 @@
Bug #7908: Key bindings names in the settings menu are layout-specific Bug #7908: Key bindings names in the settings menu are layout-specific
Bug #7943: Using "addSoulGem" and "dropSoulGem" commands to creatures works only with "Weapon & Shield" flagged ones Bug #7943: Using "addSoulGem" and "dropSoulGem" commands to creatures works only with "Weapon & Shield" flagged ones
Bug #7970: Difference of GetPCSleep (?) behavior between vanilla and OpenMW Bug #7970: Difference of GetPCSleep (?) behavior between vanilla and OpenMW
Bug #7980: Paralyzed NPCs' lips move
Feature #2566: Handle NAM9 records for manual cell references Feature #2566: Handle NAM9 records for manual cell references
Feature #3537: Shader-based water ripples Feature #3537: Shader-based water ripples
Feature #5173: Support for NiFogProperty Feature #5173: Support for NiFogProperty

@ -22,6 +22,11 @@
#include "importpage.hpp" #include "importpage.hpp"
#include "settingspage.hpp" #include "settingspage.hpp"
namespace
{
constexpr const char* toolBarStyle = "QToolBar { border: 0px; } QToolButton { min-width: 70px }";
}
using namespace Process; using namespace Process;
void cfgError(const QString& title, const QString& msg) void cfgError(const QString& title, const QString& msg)
@ -73,6 +78,7 @@ Launcher::MainDialog::MainDialog(const Files::ConfigurationManager& configuratio
QLabel* logo = new QLabel(this); QLabel* logo = new QLabel(this);
logo->setPixmap(QIcon(":/images/openmw-header.png").pixmap(QSize(294, 64))); logo->setPixmap(QIcon(":/images/openmw-header.png").pixmap(QSize(294, 64)));
toolBar->addWidget(logo); toolBar->addWidget(logo);
toolBar->setStyleSheet(toolBarStyle);
} }
Launcher::MainDialog::~MainDialog() Launcher::MainDialog::~MainDialog()
@ -81,6 +87,18 @@ Launcher::MainDialog::~MainDialog()
delete mWizardInvoker; delete mWizardInvoker;
} }
bool Launcher::MainDialog::event(QEvent* event)
{
// Apply style sheet again if style was changed
if (event->type() == QEvent::PaletteChange)
{
if (toolBar != nullptr)
toolBar->setStyleSheet(toolBarStyle);
}
return QMainWindow::event(event);
}
void Launcher::MainDialog::createIcons() void Launcher::MainDialog::createIcons()
{ {
if (!QIcon::hasThemeIcon("document-new")) if (!QIcon::hasThemeIcon("document-new"))

@ -60,6 +60,9 @@ namespace Launcher
void play(); void play();
void help(); void help();
protected:
bool event(QEvent* event) override;
private slots: private slots:
void wizardStarted(); void wizardStarted();
void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus); void wizardFinished(int exitCode, QProcess::ExitStatus exitStatus);

@ -75,16 +75,6 @@
<property name="layoutDirection"> <property name="layoutDirection">
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="styleSheet">
<string notr="true">QToolBar {
border: 0px;
}
QToolButton {
min-width: 70px;
}
</string>
</property>
<property name="movable"> <property name="movable">
<bool>false</bool> <bool>false</bool>
</property> </property>

@ -11,7 +11,7 @@ void LineEdit::setupClearButton()
mClearButton = new QToolButton(this); mClearButton = new QToolButton(this);
mClearButton->setIcon(QIcon::fromTheme("edit-clear")); mClearButton->setIcon(QIcon::fromTheme("edit-clear"));
mClearButton->setCursor(Qt::ArrowCursor); mClearButton->setCursor(Qt::ArrowCursor);
mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); mClearButton->setAutoRaise(true);
mClearButton->hide(); mClearButton->hide();
connect(mClearButton, &QToolButton::clicked, this, &LineEdit::clear); connect(mClearButton, &QToolButton::clicked, this, &LineEdit::clear);
connect(this, &LineEdit::textChanged, this, &LineEdit::updateClearButton); connect(this, &LineEdit::textChanged, this, &LineEdit::updateClearButton);

@ -205,13 +205,13 @@ namespace CSMPrefs
Settings::SettingValue<int> mErrorHeight{ mIndex, sName, "error-height", 100 }; Settings::SettingValue<int> mErrorHeight{ mIndex, sName, "error-height", 100 };
Settings::SettingValue<bool> mHighlightOccurrences{ mIndex, sName, "highlight-occurrences", true }; Settings::SettingValue<bool> mHighlightOccurrences{ mIndex, sName, "highlight-occurrences", true };
Settings::SettingValue<std::string> mColourHighlight{ mIndex, sName, "colour-highlight", "lightcyan" }; Settings::SettingValue<std::string> mColourHighlight{ mIndex, sName, "colour-highlight", "lightcyan" };
Settings::SettingValue<std::string> mColourInt{ mIndex, sName, "colour-int", "darkmagenta" }; Settings::SettingValue<std::string> mColourInt{ mIndex, sName, "colour-int", "#aa55ff" };
Settings::SettingValue<std::string> mColourFloat{ mIndex, sName, "colour-float", "magenta" }; Settings::SettingValue<std::string> mColourFloat{ mIndex, sName, "colour-float", "magenta" };
Settings::SettingValue<std::string> mColourName{ mIndex, sName, "colour-name", "grey" }; Settings::SettingValue<std::string> mColourName{ mIndex, sName, "colour-name", "grey" };
Settings::SettingValue<std::string> mColourKeyword{ mIndex, sName, "colour-keyword", "red" }; Settings::SettingValue<std::string> mColourKeyword{ mIndex, sName, "colour-keyword", "red" };
Settings::SettingValue<std::string> mColourSpecial{ mIndex, sName, "colour-special", "darkorange" }; Settings::SettingValue<std::string> mColourSpecial{ mIndex, sName, "colour-special", "darkorange" };
Settings::SettingValue<std::string> mColourComment{ mIndex, sName, "colour-comment", "green" }; Settings::SettingValue<std::string> mColourComment{ mIndex, sName, "colour-comment", "green" };
Settings::SettingValue<std::string> mColourId{ mIndex, sName, "colour-id", "blue" }; Settings::SettingValue<std::string> mColourId{ mIndex, sName, "colour-id", "#0055ff" };
}; };
struct GeneralInputCategory : Settings::WithIndex struct GeneralInputCategory : Settings::WithIndex

@ -177,6 +177,8 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString& name, bool)
mAdjusterWidget->setName("", true); mAdjusterWidget->setName("", true);
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled(success); ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled(success);
if (success)
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setFocus();
} }
QString CSVDoc::FileDialog::filename() const QString CSVDoc::FileDialog::filename() const

@ -15,6 +15,11 @@
#include "creator.hpp" #include "creator.hpp"
#include "infocreator.hpp" #include "infocreator.hpp"
namespace
{
constexpr const char* statusBarStyle = "QStatusBar::item { border: 0px }";
}
void CSVWorld::TableBottomBox::updateSize() void CSVWorld::TableBottomBox::updateSize()
{ {
// Make sure that the size of the bottom box is determined by the currently visible widget // Make sure that the size of the bottom box is determined by the currently visible widget
@ -104,6 +109,7 @@ CSVWorld::TableBottomBox::TableBottomBox(const CreatorFactoryBase& creatorFactor
mStatusBar = new QStatusBar(this); mStatusBar = new QStatusBar(this);
mStatusBar->addWidget(mStatus); mStatusBar->addWidget(mStatus);
mStatusBar->setStyleSheet(statusBarStyle);
mLayout->addWidget(mStatusBar); mLayout->addWidget(mStatusBar);
@ -129,6 +135,18 @@ CSVWorld::TableBottomBox::TableBottomBox(const CreatorFactoryBase& creatorFactor
updateSize(); updateSize();
} }
bool CSVWorld::TableBottomBox::event(QEvent* event)
{
// Apply style sheet again if style was changed
if (event->type() == QEvent::PaletteChange)
{
if (mStatusBar != nullptr)
mStatusBar->setStyleSheet(statusBarStyle);
}
return QWidget::event(event);
}
void CSVWorld::TableBottomBox::setEditLock(bool locked) void CSVWorld::TableBottomBox::setEditLock(bool locked)
{ {
if (mCreator) if (mCreator)

@ -61,6 +61,9 @@ namespace CSVWorld
void extendedConfigRequest(ExtendedCommandConfigurator::Mode mode, const std::vector<std::string>& selectedIds); void extendedConfigRequest(ExtendedCommandConfigurator::Mode mode, const std::vector<std::string>& selectedIds);
protected:
bool event(QEvent* event) override;
public: public:
TableBottomBox(const CreatorFactoryBase& creatorFactory, CSMDoc::Document& document, TableBottomBox(const CreatorFactoryBase& creatorFactory, CSMDoc::Document& document,
const CSMWorld::UniversalId& id, QWidget* parent = nullptr); const CSMWorld::UniversalId& id, QWidget* parent = nullptr);

@ -259,7 +259,8 @@ namespace MWInput
void MouseManager::warpMouse() void MouseManager::warpMouse()
{ {
float uiScale = MWBase::Environment::get().getWindowManager()->getScalingFactor(); float guiUiScale = Settings::gui().mScalingFactor;
mInputWrapper->warpMouse(static_cast<int>(mGuiCursorX * uiScale), static_cast<int>(mGuiCursorY * uiScale)); mInputWrapper->warpMouse(
static_cast<int>(mGuiCursorX * guiUiScale), static_cast<int>(mGuiCursorY * guiUiScale));
} }
} }

@ -155,6 +155,9 @@ namespace MWRender
if (!mEnabled) if (!mEnabled)
return; return;
if (dt == 0.f)
return;
if (!MWBase::Environment::get().getSoundManager()->sayActive(mReference)) if (!MWBase::Environment::get().getSoundManager()->sayActive(mReference))
{ {
mBlinkTimer += dt; mBlinkTimer += dt;

@ -23,6 +23,11 @@ Wizard::MethodSelectionPage::MethodSelectionPage(QWidget* parent)
buyLinkButton->released(); buyLinkButton->released();
#endif #endif
QFont font = existingLocationRadioButton->font();
font.setBold(true);
existingLocationRadioButton->setFont(font);
retailDiscRadioButton->setFont(font);
registerField(QLatin1String("installation.retailDisc"), retailDiscRadioButton); registerField(QLatin1String("installation.retailDisc"), retailDiscRadioButton);
connect(buyLinkButton, &QPushButton::released, this, &MethodSelectionPage::handleBuyButton); connect(buyLinkButton, &QPushButton::released, this, &MethodSelectionPage::handleBuyButton);

@ -22,9 +22,6 @@
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QRadioButton" name="retailDiscRadioButton"> <widget class="QRadioButton" name="retailDiscRadioButton">
<property name="styleSheet">
<string notr="true">font-weight:bold;</string>
</property>
<property name="text"> <property name="text">
<string>Retail CD/DVD</string> <string>Retail CD/DVD</string>
</property> </property>
@ -81,9 +78,6 @@
</item> </item>
<item> <item>
<widget class="QRadioButton" name="existingLocationRadioButton"> <widget class="QRadioButton" name="existingLocationRadioButton">
<property name="styleSheet">
<string notr="true">font-weight:bold</string>
</property>
<property name="text"> <property name="text">
<string>Existing Installation</string> <string>Existing Installation</string>
</property> </property>

@ -221,51 +221,40 @@ namespace Debug
}; };
#else #else
class Tee : public DebugOutputBase namespace
{ {
public: struct Record
Tee(std::ostream& stream, std::ostream& stream2)
: out(stream)
, out2(stream2)
{ {
// TODO: check which stream is stderr? std::string mValue;
mUseColor = useColoredOutput(); Level mLevel;
};
mColors[Error] = Red;
mColors[Warning] = Yellow;
mColors[Info] = Reset;
mColors[Verbose] = DarkGray;
mColors[Debug] = DarkGray;
mColors[NoLevel] = Reset;
}
std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) override std::vector<Record> globalBuffer;
{
out.write(str, size);
out.flush();
if (mUseColor) Color getColor(Level level)
{ {
out2 << "\033[0;" << mColors[debugLevel] << "m"; switch (level)
out2.write(str, size);
out2 << "\033[0;" << Reset << "m";
}
else
{ {
out2.write(str, size); case Error:
return Red;
case Warning:
return Yellow;
case Info:
return Reset;
case Verbose:
return DarkGray;
case Debug:
return DarkGray;
case NoLevel:
return Reset;
} }
out2.flush(); return Reset;
return size;
} }
virtual ~Tee() = default; bool useColoredOutput()
private:
static bool useColoredOutput()
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (getenv("NO_COLOR")) if (std::getenv("NO_COLOR") != nullptr)
return false; return false;
DWORD mode; DWORD mode;
@ -273,22 +262,94 @@ namespace Debug
return true; return true;
// some console emulators may not use the Win32 API, so try the Unixy approach // some console emulators may not use the Win32 API, so try the Unixy approach
char* term = getenv("TERM"); return std::getenv("TERM") != nullptr && GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_CHAR;
return term && GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_CHAR;
#else #else
char* term = getenv("TERM"); return std::getenv("TERM") != nullptr && std::getenv("NO_COLOR") == nullptr && isatty(fileno(stderr));
bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr));
return useColor;
#endif #endif
} }
std::ostream& out; class Identity
std::ostream& out2; {
bool mUseColor; public:
explicit Identity(std::ostream& stream)
: mStream(stream)
{
}
std::map<Level, int> mColors; void write(const char* str, std::streamsize size, Level /*level*/)
}; {
mStream.write(str, size);
mStream.flush();
}
private:
std::ostream& mStream;
};
class Coloured
{
public:
explicit Coloured(std::ostream& stream)
: mStream(stream)
// TODO: check which stream is stderr?
, mUseColor(useColoredOutput())
{
}
void write(const char* str, std::streamsize size, Level level)
{
if (mUseColor)
mStream << "\033[0;" << getColor(level) << 'm';
mStream.write(str, size);
if (mUseColor)
mStream << "\033[0;" << Reset << 'm';
mStream.flush();
}
private:
std::ostream& mStream;
bool mUseColor;
};
class Buffer
{
public:
explicit Buffer(std::vector<Record>& buffer)
: mBuffer(buffer)
{
}
void write(const char* str, std::streamsize size, Level debugLevel)
{
mBuffer.push_back(Record{ std::string(str, size), debugLevel });
}
private:
std::vector<Record>& mBuffer;
};
template <class First, class Second>
class Tee : public DebugOutputBase
{
public:
explicit Tee(First first, Second second)
: mFirst(first)
, mSecond(second)
{
}
std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) override
{
mFirst.write(str, size, debugLevel);
mSecond.write(str, size, debugLevel);
return size;
}
private:
First mFirst;
Second mSecond;
};
}
#endif #endif
} }
@ -301,8 +362,10 @@ static std::ofstream logfile;
#if defined(_WIN32) && defined(_DEBUG) #if defined(_WIN32) && defined(_DEBUG)
static boost::iostreams::stream_buffer<Debug::DebugOutput> sb; static boost::iostreams::stream_buffer<Debug::DebugOutput> sb;
#else #else
static boost::iostreams::stream_buffer<Debug::Tee> coutsb; static boost::iostreams::stream_buffer<Debug::Tee<Debug::Identity, Debug::Coloured>> standardOut;
static boost::iostreams::stream_buffer<Debug::Tee> cerrsb; static boost::iostreams::stream_buffer<Debug::Tee<Debug::Identity, Debug::Coloured>> standardErr;
static boost::iostreams::stream_buffer<Debug::Tee<Debug::Buffer, Debug::Coloured>> bufferedOut;
static boost::iostreams::stream_buffer<Debug::Tee<Debug::Buffer, Debug::Coloured>> bufferedErr;
#endif #endif
std::ostream& getRawStdout() std::ostream& getRawStdout()
@ -323,20 +386,22 @@ Misc::Locked<std::ostream&> getLockedRawStderr()
// Redirect cout and cerr to the log file // Redirect cout and cerr to the log file
void setupLogging(const std::filesystem::path& logDir, std::string_view appName, std::ios_base::openmode mode) void setupLogging(const std::filesystem::path& logDir, std::string_view appName, std::ios_base::openmode mode)
{ {
#if defined(_WIN32) && defined(_DEBUG) #if !(defined(_WIN32) && defined(_DEBUG))
// Redirect cout and cerr to VS debug output when running in debug mode
sb.open(Debug::DebugOutput());
std::cout.rdbuf(&sb);
std::cerr.rdbuf(&sb);
#else
const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log"; const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log";
logfile.open(logDir / logName, mode); logfile.open(logDir / logName, mode);
coutsb.open(Debug::Tee(logfile, *rawStdout)); Debug::Identity log(logfile);
cerrsb.open(Debug::Tee(logfile, *rawStderr));
for (const Debug::Record& v : Debug::globalBuffer)
log.write(v.mValue.data(), v.mValue.size(), v.mLevel);
std::cout.rdbuf(&coutsb); Debug::globalBuffer.clear();
std::cerr.rdbuf(&cerrsb);
standardOut.open(Debug::Tee(log, Debug::Coloured(*rawStdout)));
standardErr.open(Debug::Tee(log, Debug::Coloured(*rawStderr)));
std::cout.rdbuf(&standardOut);
std::cerr.rdbuf(&standardErr);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -356,6 +421,19 @@ int wrapApplication(int (*innerApplication)(int argc, char* argv[]), int argc, c
rawStderr = std::make_unique<std::ostream>(std::cerr.rdbuf()); rawStderr = std::make_unique<std::ostream>(std::cerr.rdbuf());
rawStderrMutex = std::make_unique<std::mutex>(); rawStderrMutex = std::make_unique<std::mutex>();
#if defined(_WIN32) && defined(_DEBUG)
// Redirect cout and cerr to VS debug output when running in debug mode
sb.open(Debug::DebugOutput());
std::cout.rdbuf(&sb);
std::cerr.rdbuf(&sb);
#else
bufferedOut.open(Debug::Tee(Debug::Buffer(Debug::globalBuffer), Debug::Coloured(*rawStdout)));
bufferedErr.open(Debug::Tee(Debug::Buffer(Debug::globalBuffer), Debug::Coloured(*rawStderr)));
std::cout.rdbuf(&bufferedOut);
std::cerr.rdbuf(&bufferedErr);
#endif
int ret = 0; int ret = 0;
try try
{ {

@ -122,11 +122,13 @@ namespace Nif
mStringPalette.read(nif); mStringPalette.read(nif);
else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24) else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24)
{ {
uint16_t numAnimNotes = 1;
if (nif->getBethVersion() >= 29) if (nif->getBethVersion() >= 29)
nif->read(numAnimNotes); mAnimNotesList.resize(nif->get<uint16_t>());
else
mAnimNotesList.resize(1);
nif->skip(4 * numAnimNotes); // BSAnimNotes links for (auto& notes : mAnimNotesList)
notes.read(nif);
} }
} }
@ -793,4 +795,92 @@ namespace Nif
mInterpolator.post(nif); mInterpolator.post(nif);
} }
void NiBSplineInterpolator::read(NIFStream* nif)
{
nif->read(mStartTime);
nif->read(mStopTime);
mSplineData.read(nif);
mBasisData.read(nif);
}
void NiBSplineInterpolator::post(Reader& nif)
{
mSplineData.post(nif);
mBasisData.post(nif);
}
void NiBSplineFloatInterpolator::read(NIFStream* nif)
{
NiBSplineInterpolator::read(nif);
nif->read(mValue);
nif->read(mHandle);
}
void NiBSplineCompFloatInterpolator::read(NIFStream* nif)
{
NiBSplineFloatInterpolator::read(nif);
nif->read(mOffset);
nif->read(mHalfRange);
}
void NiBSplinePoint3Interpolator::read(NIFStream* nif)
{
NiBSplineInterpolator::read(nif);
nif->read(mValue);
nif->read(mHandle);
}
void NiBSplineCompPoint3Interpolator::read(NIFStream* nif)
{
NiBSplinePoint3Interpolator::read(nif);
nif->read(mOffset);
nif->read(mHalfRange);
}
void NiBSplineTransformInterpolator::read(NIFStream* nif)
{
NiBSplineInterpolator::read(nif);
nif->read(mValue);
nif->read(mTranslationHandle);
nif->read(mRotationHandle);
nif->read(mScaleHandle);
}
void NiBSplineCompTransformInterpolator::read(NIFStream* nif)
{
NiBSplineTransformInterpolator::read(nif);
nif->read(mTranslationOffset);
nif->read(mTranslationHalfRange);
nif->read(mRotationOffset);
nif->read(mRotationHalfRange);
nif->read(mScaleOffset);
nif->read(mScaleHalfRange);
}
void BSTreadTransform::read(NIFStream* nif)
{
nif->read(mName);
nif->read(mTransform1);
nif->read(mTransform2);
}
void BSTreadTransfInterpolator::read(NIFStream* nif)
{
mTransforms.resize(nif->get<uint32_t>());
for (BSTreadTransform& transform : mTransforms)
transform.read(nif);
mData.read(nif);
}
void BSTreadTransfInterpolator::post(Reader& nif)
{
mData.post(nif);
}
} }

@ -56,6 +56,7 @@ namespace Nif
bool mPlayBackwards{ false }; bool mPlayBackwards{ false };
NiControllerManagerPtr mManager; NiControllerManagerPtr mManager;
NiStringPalettePtr mStringPalette; NiStringPalettePtr mStringPalette;
BSAnimNotesList mAnimNotesList;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;
@ -548,5 +549,91 @@ namespace Nif
using NiBlendPoint3Interpolator = TypedNiBlendInterpolator<osg::Vec3f>; using NiBlendPoint3Interpolator = TypedNiBlendInterpolator<osg::Vec3f>;
using NiBlendTransformInterpolator = TypedNiBlendInterpolator<NiQuatTransform>; using NiBlendTransformInterpolator = TypedNiBlendInterpolator<NiQuatTransform>;
// Abstract
struct NiBSplineInterpolator : public NiInterpolator
{
float mStartTime;
float mStopTime;
NiBSplineDataPtr mSplineData;
NiBSplineBasisDataPtr mBasisData;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
// Abstract
struct NiBSplineFloatInterpolator : public NiBSplineInterpolator
{
float mValue;
uint32_t mHandle;
void read(NIFStream* nif) override;
};
struct NiBSplineCompFloatInterpolator : public NiBSplineFloatInterpolator
{
float mOffset;
float mHalfRange;
void read(NIFStream* nif) override;
};
// Abstract
struct NiBSplinePoint3Interpolator : public NiBSplineInterpolator
{
osg::Vec3f mValue;
uint32_t mHandle;
void read(NIFStream* nif) override;
};
struct NiBSplineCompPoint3Interpolator : public NiBSplinePoint3Interpolator
{
float mOffset;
float mHalfRange;
void read(NIFStream* nif) override;
};
struct NiBSplineTransformInterpolator : public NiBSplineInterpolator
{
NiQuatTransform mValue;
uint32_t mTranslationHandle;
uint32_t mRotationHandle;
uint32_t mScaleHandle;
void read(NIFStream* nif) override;
};
struct NiBSplineCompTransformInterpolator : public NiBSplineTransformInterpolator
{
float mTranslationOffset;
float mTranslationHalfRange;
float mRotationOffset;
float mRotationHalfRange;
float mScaleOffset;
float mScaleHalfRange;
void read(NIFStream* nif) override;
};
struct BSTreadTransform
{
std::string mName;
NiQuatTransform mTransform1;
NiQuatTransform mTransform2;
void read(NIFStream* nif);
};
struct BSTreadTransfInterpolator : public NiInterpolator
{
std::vector<BSTreadTransform> mTransforms;
NiFloatDataPtr mData;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
} }
#endif #endif

@ -537,6 +537,17 @@ namespace Nif
mKeyList->read(nif); mKeyList->read(nif);
} }
void NiBSplineData::read(NIFStream* nif)
{
nif->readVector(mFloatControlPoints, nif->get<uint32_t>());
nif->readVector(mCompactControlPoints, nif->get<uint32_t>());
}
void NiBSplineBasisData::read(NIFStream* nif)
{
nif->read(mNumControlPoints);
}
void NiAdditionalGeometryData::read(NIFStream* nif) void NiAdditionalGeometryData::read(NIFStream* nif)
{ {
nif->read(mNumVertices); nif->read(mNumVertices);
@ -603,4 +614,31 @@ namespace Nif
nif->read(mSphere); nif->read(mSphere);
} }
void BSAnimNote::read(NIFStream* nif)
{
mType = static_cast<Type>(nif->get<uint32_t>());
nif->read(mTime);
if (mType == Type::GrabIK)
{
nif->read(mArm);
}
else if (mType == Type::LookIK)
{
nif->read(mGain);
nif->read(mState);
}
}
void BSAnimNotes::read(NIFStream* nif)
{
mList.resize(nif->get<uint16_t>());
for (auto& note : mList)
note.read(nif);
}
void BSAnimNotes::post(Reader& nif)
{
postRecordList(nif, mList);
}
} // Namespace } // Namespace

@ -362,6 +362,21 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
struct NiBSplineData : public Record
{
std::vector<float> mFloatControlPoints;
std::vector<int16_t> mCompactControlPoints;
void read(NIFStream* nif) override;
};
struct NiBSplineBasisData : public Record
{
uint32_t mNumControlPoints;
void read(NIFStream* nif) override;
};
struct NiAdditionalGeometryData : public Record struct NiAdditionalGeometryData : public Record
{ {
struct DataStream struct DataStream
@ -434,5 +449,31 @@ namespace Nif
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
struct BSAnimNote : public Record
{
enum class Type : uint32_t
{
Invalid = 0,
GrabIK = 1,
LookIK = 2,
};
Type mType;
float mTime;
uint32_t mArm;
float mGain;
uint32_t mState;
void read(NIFStream* nif) override;
};
struct BSAnimNotes : public Record
{
BSAnimNoteList mList;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
} }
#endif #endif

@ -164,6 +164,14 @@ namespace Nif
{ "NiLightRadiusController", &construct<NiFloatInterpController, RC_NiLightRadiusController> }, { "NiLightRadiusController", &construct<NiFloatInterpController, RC_NiLightRadiusController> },
// Interpolators, Gamebryo // Interpolators, Gamebryo
{ "NiBSplineCompFloatInterpolator",
&construct<NiBSplineCompFloatInterpolator, RC_NiBSplineCompFloatInterpolator> },
{ "NiBSplineCompPoint3Interpolator",
&construct<NiBSplineCompPoint3Interpolator, RC_NiBSplineCompPoint3Interpolator> },
{ "NiBSplineCompTransformInterpolator",
&construct<NiBSplineCompTransformInterpolator, RC_NiBSplineCompTransformInterpolator> },
{ "NiBSplineTransformInterpolator",
&construct<NiBSplineTransformInterpolator, RC_NiBSplineTransformInterpolator> },
{ "NiBlendBoolInterpolator", &construct<NiBlendBoolInterpolator, RC_NiBlendBoolInterpolator> }, { "NiBlendBoolInterpolator", &construct<NiBlendBoolInterpolator, RC_NiBlendBoolInterpolator> },
{ "NiBlendFloatInterpolator", &construct<NiBlendFloatInterpolator, RC_NiBlendFloatInterpolator> }, { "NiBlendFloatInterpolator", &construct<NiBlendFloatInterpolator, RC_NiBlendFloatInterpolator> },
{ "NiBlendPoint3Interpolator", &construct<NiBlendPoint3Interpolator, RC_NiBlendPoint3Interpolator> }, { "NiBlendPoint3Interpolator", &construct<NiBlendPoint3Interpolator, RC_NiBlendPoint3Interpolator> },
@ -178,6 +186,10 @@ namespace Nif
{ "NiPoint3Interpolator", &construct<NiPoint3Interpolator, RC_NiPoint3Interpolator> }, { "NiPoint3Interpolator", &construct<NiPoint3Interpolator, RC_NiPoint3Interpolator> },
{ "NiTransformInterpolator", &construct<NiTransformInterpolator, RC_NiTransformInterpolator> }, { "NiTransformInterpolator", &construct<NiTransformInterpolator, RC_NiTransformInterpolator> },
// Interpolators, Bethesda
{ "BSRotAccumTransfInterpolator", &construct<NiTransformInterpolator, RC_BSRotAccumTransfInterpolator> },
{ "BSTreadTransfInterpolator", &construct<BSTreadTransfInterpolator, RC_BSTreadTransfInterpolator> },
// DATA // DATA
// 4.0.0.2 // 4.0.0.2
@ -195,10 +207,14 @@ namespace Nif
// Gamebryo // Gamebryo
{ "NiAdditionalGeometryData", &construct<NiAdditionalGeometryData, RC_NiAdditionalGeometryData> }, { "NiAdditionalGeometryData", &construct<NiAdditionalGeometryData, RC_NiAdditionalGeometryData> },
{ "NiBoolData", &construct<NiBoolData, RC_NiBoolData> }, { "NiBoolData", &construct<NiBoolData, RC_NiBoolData> },
{ "NiBSplineData", &construct<NiBSplineData, RC_NiBSplineData> },
{ "NiBSplineBasisData", &construct<NiBSplineBasisData, RC_NiBSplineBasisData> },
{ "NiDefaultAVObjectPalette", &construct<NiDefaultAVObjectPalette, RC_NiDefaultAVObjectPalette> }, { "NiDefaultAVObjectPalette", &construct<NiDefaultAVObjectPalette, RC_NiDefaultAVObjectPalette> },
{ "NiTransformData", &construct<NiKeyframeData, RC_NiKeyframeData> }, { "NiTransformData", &construct<NiKeyframeData, RC_NiKeyframeData> },
// Bethesda // Bethesda
{ "BSAnimNote", &construct<BSAnimNote, RC_BSAnimNote> },
{ "BSAnimNotes", &construct<BSAnimNotes, RC_BSAnimNotes> },
{ "BSPackedAdditionalGeometryData", { "BSPackedAdditionalGeometryData",
&construct<NiAdditionalGeometryData, RC_BSPackedAdditionalGeometryData> }, &construct<NiAdditionalGeometryData, RC_BSPackedAdditionalGeometryData> },
{ "BSShaderTextureSet", &construct<BSShaderTextureSet, RC_BSShaderTextureSet> }, { "BSShaderTextureSet", &construct<BSShaderTextureSet, RC_BSShaderTextureSet> },

@ -73,6 +73,8 @@ namespace Nif
RC_bhkSimpleShapePhantom, RC_bhkSimpleShapePhantom,
RC_bhkSphereShape, RC_bhkSphereShape,
RC_bhkStiffSpringConstraint, RC_bhkStiffSpringConstraint,
RC_BSAnimNote,
RC_BSAnimNotes,
RC_BSBehaviorGraphExtraData, RC_BSBehaviorGraphExtraData,
RC_BSBound, RC_BSBound,
RC_BSBoneLODExtraData, RC_BSBoneLODExtraData,
@ -127,6 +129,7 @@ namespace Nif
RC_BSStripPSysData, RC_BSStripPSysData,
RC_BSRefractionFirePeriodController, RC_BSRefractionFirePeriodController,
RC_BSRefractionStrengthController, RC_BSRefractionStrengthController,
RC_BSRotAccumTransfInterpolator,
RC_BSSegmentedTriShape, RC_BSSegmentedTriShape,
RC_BSShaderNoLightingProperty, RC_BSShaderNoLightingProperty,
RC_BSShaderPPLightingProperty, RC_BSShaderPPLightingProperty,
@ -136,6 +139,7 @@ namespace Nif
RC_BSSkinInstance, RC_BSSkinInstance,
RC_BSSkyShaderProperty, RC_BSSkyShaderProperty,
RC_BSSubIndexTriShape, RC_BSSubIndexTriShape,
RC_BSTreadTransfInterpolator,
RC_BSTriShape, RC_BSTriShape,
RC_BSWArray, RC_BSWArray,
RC_BSWaterShaderProperty, RC_BSWaterShaderProperty,
@ -162,6 +166,12 @@ namespace Nif
RC_NiBSAnimationNode, RC_NiBSAnimationNode,
RC_NiBSPArrayController, RC_NiBSPArrayController,
RC_NiBSParticleNode, RC_NiBSParticleNode,
RC_NiBSplineData,
RC_NiBSplineBasisData,
RC_NiBSplineCompFloatInterpolator,
RC_NiBSplineCompPoint3Interpolator,
RC_NiBSplineCompTransformInterpolator,
RC_NiBSplineTransformInterpolator,
RC_NiCamera, RC_NiCamera,
RC_NiClusterAccumulator, RC_NiClusterAccumulator,
RC_NiCollisionObject, RC_NiCollisionObject,

@ -137,6 +137,8 @@ namespace Nif
struct NiPSysModifier; struct NiPSysModifier;
struct NiPSysSpawnModifier; struct NiPSysSpawnModifier;
struct NiBoolData; struct NiBoolData;
struct NiBSplineData;
struct NiBSplineBasisData;
struct NiSkinPartition; struct NiSkinPartition;
struct BSShaderTextureSet; struct BSShaderTextureSet;
struct NiTriBasedGeom; struct NiTriBasedGeom;
@ -163,6 +165,8 @@ namespace Nif
struct BSMultiBound; struct BSMultiBound;
struct BSMultiBoundData; struct BSMultiBoundData;
struct BSSkinBoneData; struct BSSkinBoneData;
struct BSAnimNote;
struct BSAnimNotes;
using NiAVObjectPtr = RecordPtrT<NiAVObject>; using NiAVObjectPtr = RecordPtrT<NiAVObject>;
using ExtraPtr = RecordPtrT<Extra>; using ExtraPtr = RecordPtrT<Extra>;
@ -189,6 +193,8 @@ namespace Nif
using NiPSysModifierPtr = RecordPtrT<NiPSysModifier>; using NiPSysModifierPtr = RecordPtrT<NiPSysModifier>;
using NiPSysSpawnModifierPtr = RecordPtrT<NiPSysSpawnModifier>; using NiPSysSpawnModifierPtr = RecordPtrT<NiPSysSpawnModifier>;
using NiBoolDataPtr = RecordPtrT<NiBoolData>; using NiBoolDataPtr = RecordPtrT<NiBoolData>;
using NiBSplineDataPtr = RecordPtrT<NiBSplineData>;
using NiBSplineBasisDataPtr = RecordPtrT<NiBSplineBasisData>;
using NiSkinPartitionPtr = RecordPtrT<NiSkinPartition>; using NiSkinPartitionPtr = RecordPtrT<NiSkinPartition>;
using BSShaderTextureSetPtr = RecordPtrT<BSShaderTextureSet>; using BSShaderTextureSetPtr = RecordPtrT<BSShaderTextureSet>;
using NiTriBasedGeomPtr = RecordPtrT<NiTriBasedGeom>; using NiTriBasedGeomPtr = RecordPtrT<NiTriBasedGeom>;
@ -227,6 +233,8 @@ namespace Nif
using NiControllerSequenceList = RecordListT<NiControllerSequence>; using NiControllerSequenceList = RecordListT<NiControllerSequence>;
using NiPSysModifierList = RecordListT<NiPSysModifier>; using NiPSysModifierList = RecordListT<NiPSysModifier>;
using NiTriBasedGeomList = RecordListT<NiTriBasedGeom>; using NiTriBasedGeomList = RecordListT<NiTriBasedGeom>;
using BSAnimNoteList = RecordListT<BSAnimNote>;
using BSAnimNotesList = RecordListT<BSAnimNotes>;
} // Namespace } // Namespace
#endif #endif

Loading…
Cancel
Save