docs: add plugin setup guide
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BGSCreatedObjectManager.h"
|
||||
|
||||
#include "RE/A/AlchemyItem.h"
|
||||
#include "RE/T/TESForm.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<AlchemyItem>;
|
||||
static_assert(std::is_empty_v<BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<AlchemyItem>>);
|
||||
|
||||
template class BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<TESForm>;
|
||||
static_assert(std::is_empty_v<BGSCreatedObjectManager::BSTCreatedObjectSmartPointerPolicy<TESForm>>);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BGSInventoryItem.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
std::uint32_t BGSInventoryItem::GetCount() const noexcept
|
||||
{
|
||||
std::uint32_t count = 0;
|
||||
for (auto iter = stackData.get(); iter; iter = iter->nextStack.get()) {
|
||||
count += iter->GetCount();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "RE/B/BGSKeyword.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
BGSKeyword* BGSKeywordGetTypedKeywordByIndex(KeywordType a_type, std::uint16_t a_index)
|
||||
{
|
||||
return BGSKeyword::GetTypedKeywordByIndex(a_type, a_index);
|
||||
}
|
||||
|
||||
std::uint16_t BGSKeywordGetIndexForTypedKeyword(BGSKeyword* a_keyword, KeywordType a_type)
|
||||
{
|
||||
return BGSKeyword::GetIndexForTypedKeyword(a_keyword, a_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "RE/B/BGSKeywordForm.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void BGSKeywordForm::CopyKeywords(const std::vector<BGSKeyword*>& a_copiedData)
|
||||
{
|
||||
const auto oldData = keywords;
|
||||
|
||||
const auto newSize = a_copiedData.size();
|
||||
const auto newData = calloc<BGSKeyword*>(newSize);
|
||||
std::ranges::copy(a_copiedData, newData);
|
||||
|
||||
numKeywords = static_cast<std::uint32_t>(newSize);
|
||||
keywords = newData;
|
||||
|
||||
free(oldData);
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::AddKeywords(const std::vector<BGSKeyword*>& a_keywords)
|
||||
{
|
||||
std::vector<BGSKeyword*> copiedData{ keywords, keywords + numKeywords };
|
||||
std::ranges::remove_copy_if(a_keywords, std::back_inserter(copiedData), [&](auto& keyword) {
|
||||
return std::ranges::find(copiedData, keyword) != copiedData.end();
|
||||
});
|
||||
CopyKeywords(copiedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::ContainsKeywordString(std::string_view a_editorID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->formEditorID.contains(a_editorID)) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::HasKeywordID(TESFormID a_formID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->GetFormID() == a_formID) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::HasKeywordString(std::string_view a_editorID) const
|
||||
{
|
||||
bool result = false;
|
||||
ForEachKeyword([&](const BGSKeyword* a_keyword) {
|
||||
if (a_keyword->formEditorID == a_editorID) {
|
||||
result = true;
|
||||
return BSContainer::ForEachResult::kStop;
|
||||
}
|
||||
return BSContainer::ForEachResult::kContinue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BGSKeywordForm::RemoveKeywords(const std::vector<BGSKeyword*>& a_keywords)
|
||||
{
|
||||
std::vector<BGSKeyword*> copiedData{ keywords, keywords + numKeywords };
|
||||
if (std::erase_if(copiedData, [&](auto& keyword) { return std::ranges::find(a_keywords, keyword) != a_keywords.end(); }) > 0) {
|
||||
CopyKeywords(copiedData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "RE/B/BGSLocation.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
bool BGSLocation::IsChild(const BGSLocation* a_possibleChild) const
|
||||
{
|
||||
if (a_possibleChild) {
|
||||
for (auto it = a_possibleChild->parentLoc; it; it = it->parentLoc) {
|
||||
if (this == it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BGSLocation::IsParent(const BGSLocation* a_possibleParent) const
|
||||
{
|
||||
if (a_possibleParent) {
|
||||
for (auto it = parentLoc; it; it = it->parentLoc) {
|
||||
if (a_possibleParent == it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "RE/B/BGSObjectInstanceExtra.h"
|
||||
|
||||
#include "RE/B/BGSMod.h"
|
||||
#include "RE/T/TESBoundObject.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
void BGSObjectInstanceExtra::CreateBaseInstanceData(const TESBoundObject& a_object, BSTSmartPointer<TBO_InstanceData>& a_instanceData) const
|
||||
{
|
||||
if (values && itemIndex != static_cast<std::uint16_t>(-1)) {
|
||||
a_object.ApplyMods(a_instanceData, this);
|
||||
}
|
||||
}
|
||||
|
||||
std::span<BGSMod::ObjectIndexData> BGSObjectInstanceExtra::GetIndexData() const noexcept
|
||||
{
|
||||
return values->GetBuffer<BGSMod::ObjectIndexData>(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "RE/B/BSCRC32.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template struct BSCRC32<std::int8_t>;
|
||||
template struct BSCRC32<std::uint8_t>;
|
||||
template struct BSCRC32<std::int16_t>;
|
||||
template struct BSCRC32<std::uint16_t>;
|
||||
template struct BSCRC32<std::int32_t>;
|
||||
template struct BSCRC32<std::uint32_t>;
|
||||
template struct BSCRC32<std::int64_t>;
|
||||
template struct BSCRC32<std::uint64_t>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "RE/B/BSFixedString.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template class BSFixedString<char, false>;
|
||||
static_assert(sizeof(BSFixedString<char, false>) == 0x8);
|
||||
|
||||
template class BSFixedString<char, true>;
|
||||
static_assert(sizeof(BSFixedString<char, true>) == 0x8);
|
||||
|
||||
template class BSFixedString<wchar_t, false>;
|
||||
static_assert(sizeof(BSFixedString<wchar_t, false>) == 0x8);
|
||||
|
||||
template class BSFixedString<wchar_t, true>;
|
||||
static_assert(sizeof(BSFixedString<wchar_t, true>) == 0x8);
|
||||
}
|
||||
|
||||
template struct BSCRC32<BSFixedString>;
|
||||
template struct BSCRC32<BSFixedStringCS>;
|
||||
template struct BSCRC32<BSFixedStringW>;
|
||||
template struct BSCRC32<BSFixedStringWCS>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "RE/B/BSPointerHandle.h"
|
||||
|
||||
#include "RE/A/Actor.h"
|
||||
#include "RE/P/Projectile.h"
|
||||
#include "RE/T/TESObjectREFR.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSPointerHandle<Actor>;
|
||||
static_assert(sizeof(BSPointerHandle<Actor>) == 0x4);
|
||||
|
||||
template class BSPointerHandle<Projectile>;
|
||||
static_assert(sizeof(BSPointerHandle<Projectile>) == 0x4);
|
||||
|
||||
template class BSPointerHandle<TESObjectREFR>;
|
||||
static_assert(sizeof(BSPointerHandle<TESObjectREFR>) == 0x4);
|
||||
|
||||
template class BSUntypedPointerHandle<>;
|
||||
static_assert(sizeof(BSUntypedPointerHandle<>) == 0x4);
|
||||
|
||||
template class BSPointerHandleManagerInterface<Actor>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<Actor>>);
|
||||
|
||||
template class BSPointerHandleManagerInterface<Projectile>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<Projectile>>);
|
||||
|
||||
template class BSPointerHandleManagerInterface<TESObjectREFR>;
|
||||
static_assert(std::is_empty_v<BSPointerHandleManagerInterface<TESObjectREFR>>);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "RE/B/BSResource.h"
|
||||
|
||||
namespace RE::BSResource
|
||||
{
|
||||
ErrorCode GetOrCreateStream(const char* a_fileName, BSTSmartPointer<Stream>& a_result, bool a_writable, Location* a_optionalStart)
|
||||
{
|
||||
using func_t = decltype(&GetOrCreateStream);
|
||||
static REL::Relocation<func_t> func{ ID::BSResource::GetOrCreateStream };
|
||||
return func(a_fileName, a_result, a_writable, a_optionalStart);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "RE/B/BSResourceNiBinaryStream.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
BSResourceNiBinaryStream::BSResourceNiBinaryStream() :
|
||||
NiBinaryStream()
|
||||
{}
|
||||
|
||||
BSResourceNiBinaryStream::BSResourceNiBinaryStream(const char* a_file, bool a_writeable, BSResource::Location* a_optionalStart, bool a_fullReadHint) :
|
||||
NiBinaryStream()
|
||||
{
|
||||
using func_t = void (*)(BSResourceNiBinaryStream*, const char*, bool, BSResource::Location*, bool);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Ctor };
|
||||
func(this, a_file, a_writeable, a_optionalStart, a_fullReadHint);
|
||||
}
|
||||
|
||||
BSResourceNiBinaryStream::~BSResourceNiBinaryStream()
|
||||
{
|
||||
using func_t = void (*)(BSResourceNiBinaryStream*);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Dtor };
|
||||
func(this);
|
||||
}
|
||||
|
||||
void BSResourceNiBinaryStream::Seek(std::ptrdiff_t a_numBytes)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::Seek);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::Seek };
|
||||
return func(this, a_numBytes);
|
||||
}
|
||||
|
||||
void BSResourceNiBinaryStream::GetBufferInfo(BufferInfo& a_buf)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::GetBufferInfo);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::GetBufferInfo };
|
||||
return func(this, a_buf);
|
||||
}
|
||||
|
||||
std::size_t BSResourceNiBinaryStream::DoRead(void* a_buf, std::size_t a_toRead)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::DoRead);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::DoRead };
|
||||
return func(this, a_buf, a_toRead);
|
||||
}
|
||||
|
||||
std::size_t BSResourceNiBinaryStream::DoWrite(const void* a_buf, std::size_t a_toWrite)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::DoWrite);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::DoWrite };
|
||||
return func(this, a_buf, a_toWrite);
|
||||
}
|
||||
|
||||
[[nodiscard]] BSResourceNiBinaryStream* BSResourceNiBinaryStream::BinaryStreamWithRescan(const char* a_fileName)
|
||||
{
|
||||
using func_t = decltype(&BSResourceNiBinaryStream::BinaryStreamWithRescan);
|
||||
static REL::Relocation<func_t> func{ ID::BSResourceNiBinaryStream::BinaryStreamWithRescan };
|
||||
return func(a_fileName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "RE/B/BSResource_Stream.h"
|
||||
|
||||
namespace RE::BSResource
|
||||
{
|
||||
Stream::Stream() :
|
||||
Stream(0, false)
|
||||
{}
|
||||
|
||||
Stream::Stream(std::uint32_t a_totalSize, bool writable) :
|
||||
StreamBase(a_totalSize, writable)
|
||||
{}
|
||||
|
||||
Stream::Stream(const Stream& a_rhs) :
|
||||
StreamBase(a_rhs)
|
||||
{}
|
||||
|
||||
Stream::Stream(Stream&& a_rhs) :
|
||||
StreamBase(std::move(a_rhs))
|
||||
{}
|
||||
|
||||
ErrorCode Stream::DoSetEndOfStream()
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoPrefetchAt([[maybe_unused]] std::uint64_t a_v, [[maybe_unused]] std::uint64_t b_v, [[maybe_unused]] std::uint32_t c_v) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoPrefetchAll([[maybe_unused]] std::uint32_t a_v) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoStartTaggedPrioritizedRead([[maybe_unused]] void* a_buf,
|
||||
[[maybe_unused]] std::uint64_t a_v,
|
||||
[[maybe_unused]] std::uint64_t b_v,
|
||||
[[maybe_unused]] std::uint32_t c_v,
|
||||
[[maybe_unused]] std::uint32_t volatile* d_v,
|
||||
[[maybe_unused]] std::uint32_t& e_v,
|
||||
[[maybe_unused]] BSEventFlag* event_flag) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoGetName(BSFixedString& a_dst) const
|
||||
{
|
||||
a_dst = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoCreateAsync(BSTSmartPointer<BSResource::AsyncStream>&) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoGetIsFromArchive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ErrorCode Stream::DoWaitTags([[maybe_unused]] volatile std::uint32_t* a_completionTag,
|
||||
[[maybe_unused]] std::uint32_t a_completionTagWaitValue,
|
||||
[[maybe_unused]] BSEventFlag* a_eventFlag) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
bool Stream::DoQTaggedPrioritizedReadSupported() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoCreateOp([[maybe_unused]] BSTSmartPointer<ICacheDriveOp>& p_op, [[maybe_unused]] char const* name) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::DoReadAt([[maybe_unused]] void* a_buffer,
|
||||
[[maybe_unused]] std::uint64_t a_offset,
|
||||
[[maybe_unused]] std::uint64_t a_toRead,
|
||||
[[maybe_unused]] std::uint64_t& a_read) const
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
// interface functions
|
||||
ErrorCode Stream::Read(void* a_buffer, std::uint64_t a_toRead, std::uint64_t& a_read) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoRead(a_buffer, a_toRead, a_read);
|
||||
}
|
||||
|
||||
ErrorCode Stream::ReadAt(void* a_buffer, std::uint64_t a_offset, std::uint64_t a_toRead, std::uint64_t& a_read) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoReadAt(a_buffer, a_offset, a_toRead, a_read);
|
||||
}
|
||||
|
||||
bool Stream::GetName(BSFixedString& a_dst) const
|
||||
{
|
||||
return DoGetName(a_dst);
|
||||
}
|
||||
|
||||
ErrorCode Stream::Open(bool buffered, bool readFullHint)
|
||||
{
|
||||
uint32_t _flags = kUnk3;
|
||||
if (buffered) {
|
||||
_flags |= kBuffered;
|
||||
}
|
||||
if (readFullHint) {
|
||||
_flags |= kBuffered | kFullReadHint;
|
||||
}
|
||||
static std::atomic_ref myflags{ flags };
|
||||
uint32_t old_flags = flags;
|
||||
while (!myflags.compare_exchange_strong(old_flags, (old_flags | _flags))) {
|
||||
old_flags = flags;
|
||||
}
|
||||
return DoOpen();
|
||||
}
|
||||
|
||||
ErrorCode Stream::Seek(std::uint64_t a_toSeek, SeekMode a_mode, std::uint64_t& a_sought) const
|
||||
{
|
||||
return DoSeek(a_toSeek, a_mode, a_sought);
|
||||
}
|
||||
|
||||
ErrorCode Stream::Write(const void* a_buffer, std::uint64_t a_toWrite, std::uint64_t& a_written) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return DoWrite(a_buffer, a_toWrite, a_written);
|
||||
}
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
ErrorCode Stream::CreateOp(BSTSmartPointer<ICacheDriveOp>& a_opOut, const char* name) const
|
||||
{
|
||||
return DoCreateOp(a_opOut, name);
|
||||
}
|
||||
|
||||
ErrorCode Stream::CreateAsync(BSTSmartPointer<AsyncStream>& a_streamOut) const
|
||||
{
|
||||
return DoCreateAsync(a_streamOut);
|
||||
}
|
||||
|
||||
ErrorCode Stream::PrefetchAll(std::uint32_t a_v) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoPrefetchAll(a_v);
|
||||
}
|
||||
|
||||
ErrorCode Stream::PrefetchAt(std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_v) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoPrefetchAt(a_v, b_v, c_v);
|
||||
}
|
||||
|
||||
std::uint32_t Stream::QFullReadHint() const
|
||||
{
|
||||
return flags & kFullReadHint;
|
||||
}
|
||||
|
||||
bool Stream::QTaggedPrioritizedReadSupported() const
|
||||
{
|
||||
return DoQTaggedPrioritizedReadSupported();
|
||||
}
|
||||
|
||||
ErrorCode Stream::StartTaggedPrioritizedRead(void* buf, std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_V, std::uint32_t volatile* d_v, std::uint32_t& e_v, BSEventFlag* event_flag) const
|
||||
{
|
||||
if ((flags & kWritable) != 0) {
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
return DoStartTaggedPrioritizedRead(buf, a_v, b_v, c_V, d_v, e_v, event_flag);
|
||||
}
|
||||
|
||||
ErrorCode Stream::WaitTags(std::uint32_t volatile* a_v, std::uint32_t b_v, BSEventFlag* event_flag) const
|
||||
{
|
||||
return DoWaitTags(a_v, b_v, event_flag);
|
||||
}
|
||||
|
||||
std::uint32_t Stream::QBuffered() const
|
||||
{
|
||||
return flags & kBuffered;
|
||||
}
|
||||
|
||||
ErrorCode Stream::SetEndOfStream()
|
||||
{
|
||||
return DoSetEndOfStream();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "RE/B/BSResource_StreamBase.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSResource
|
||||
{
|
||||
StreamBase::StreamBase() :
|
||||
totalSize(0),
|
||||
flags(0)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(const StreamBase& a_rhs) :
|
||||
totalSize(a_rhs.totalSize),
|
||||
flags(a_rhs.flags & ~kRefCountMask)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(StreamBase&& a_rhs) :
|
||||
totalSize(a_rhs.totalSize),
|
||||
flags(a_rhs.flags & ~kRefCountMask)
|
||||
{}
|
||||
|
||||
StreamBase::StreamBase(std::uint32_t a_totalSize, bool writable) :
|
||||
totalSize(a_totalSize),
|
||||
flags(writable ? 1 : 0)
|
||||
{}
|
||||
|
||||
std::uint64_t StreamBase::DoGetKey() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ErrorCode StreamBase::DoGetInfo(Info&)
|
||||
{
|
||||
return ErrorCode::kUnsupported;
|
||||
}
|
||||
|
||||
std::uint32_t StreamBase::DecRef()
|
||||
{
|
||||
REX::TAtomicRef myFlags{ flags };
|
||||
std::uint32_t expected;
|
||||
do {
|
||||
expected = myFlags;
|
||||
} while (!myFlags.compare_exchange_weak(expected, expected - kRefCountBeg));
|
||||
return (expected - kRefCountBeg) & kRefCountMask;
|
||||
}
|
||||
|
||||
std::uint32_t StreamBase::IncRef()
|
||||
{
|
||||
REX::TAtomicRef myFlags{ flags };
|
||||
std::uint32_t expected;
|
||||
do {
|
||||
expected = myFlags;
|
||||
} while (!myFlags.compare_exchange_weak(expected, expected + kRefCountBeg));
|
||||
return (expected - kRefCountBeg) & kRefCountMask;
|
||||
}
|
||||
|
||||
bool StreamBase::IsWritable() const
|
||||
{
|
||||
return static_cast<bool>(flags & kWritable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "RE/B/BSScaleformManager.h"
|
||||
|
||||
#include "RE/B/BSSystemFileStreamer.h"
|
||||
#include "RE/I/IMenu.h"
|
||||
#include "RE/S/Setting.h"
|
||||
#include "Scaleform/G/GFx_Loader.h"
|
||||
#include "Scaleform/G/GFx_MovieDef.h"
|
||||
#include "Scaleform/P/Ptr.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
bool BSScaleformManager::LoadMovieEx(
|
||||
IMenu& a_menu,
|
||||
std::string_view a_filePath,
|
||||
std::string_view a_menuObjPath,
|
||||
ScaleModeType a_scaleMode,
|
||||
float a_backgroundAlpha)
|
||||
{
|
||||
static REL::Relocation<SettingT<INISettingCollection>*> fileUncacheOnMenuOpen{ ID::BSScaleformManager::FileUncacheOnMenuOpen };
|
||||
if (fileUncacheOnMenuOpen && fileUncacheOnMenuOpen->GetBinary()) {
|
||||
BSSystemFileStreamer::UncacheAll(true);
|
||||
}
|
||||
|
||||
REX::TEnumSet loadConstants{
|
||||
Scaleform::GFx::Loader::LoadConstants::kKeepBindData,
|
||||
Scaleform::GFx::Loader::LoadConstants::kWaitFrame1
|
||||
};
|
||||
|
||||
const auto movieDef = Scaleform::Ptr{ loader->CreateMovie(a_filePath.data(), loadConstants.get()) };
|
||||
if (!movieDef) {
|
||||
return false;
|
||||
}
|
||||
movieDef->Release();
|
||||
|
||||
auto& movie = a_menu.uiMovie;
|
||||
movie.reset(movieDef->CreateInstance(true));
|
||||
if (!movie) {
|
||||
return false;
|
||||
}
|
||||
movie->Release();
|
||||
|
||||
movie->SetViewScaleMode(a_scaleMode);
|
||||
movie->SetBackgroundAlpha(a_backgroundAlpha);
|
||||
a_menu.DoAdvanceMovie(0.0);
|
||||
if (!a_menuObjPath.empty()) {
|
||||
a_menu.SetMenuCodeObject(*movie, a_menuObjPath);
|
||||
}
|
||||
a_menu.RefreshPlatform();
|
||||
InitMovieViewport(*movie, 1.0F, 1.0F);
|
||||
a_menu.OnSetSafeRect();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
#include "RE/B/BSScript_Array.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
Array::~Array()
|
||||
{
|
||||
}
|
||||
|
||||
// Array* Array::ctor(const TypeInfo *type_info, std::uint32_t initial_size)
|
||||
// {
|
||||
// using func_t = decltype(&Array::ctor);
|
||||
// REL::Relocation<func_t> func{ ID::BSScript_Array::ctor };
|
||||
// return func(this, type_info, initial_size);
|
||||
// }
|
||||
|
||||
[[nodiscard]] auto Array::operator[](size_type a_pos)
|
||||
-> reference
|
||||
{
|
||||
assert(a_pos < size());
|
||||
return elements[a_pos];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::operator[](size_type a_pos) const
|
||||
-> const_reference
|
||||
{
|
||||
assert(a_pos < size());
|
||||
return elements[a_pos];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::front()
|
||||
-> reference
|
||||
{
|
||||
return operator[](0);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::front() const
|
||||
-> const_reference
|
||||
{
|
||||
return operator[](0);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::back()
|
||||
-> reference
|
||||
{
|
||||
return operator[](size() - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::back() const
|
||||
-> const_reference
|
||||
{
|
||||
return operator[](size() - 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::data() noexcept
|
||||
-> pointer
|
||||
{
|
||||
return size() > 0 ? elements.data() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::data() const noexcept
|
||||
-> const_pointer
|
||||
{
|
||||
return size() > 0 ? elements.data() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::begin() noexcept
|
||||
-> iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::begin() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::cbegin() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::end() noexcept
|
||||
-> iterator
|
||||
{
|
||||
return size() > 0 ? elements.end() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::end() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return size() > 0 ? elements.end() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::cend() const noexcept
|
||||
-> const_iterator
|
||||
{
|
||||
return elements.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rbegin() noexcept
|
||||
-> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rbegin() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::crbegin() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rend() noexcept
|
||||
-> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::rend() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::crend() const noexcept
|
||||
-> const_reverse_iterator
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Array::empty() const noexcept
|
||||
{
|
||||
return size() > 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::size() const noexcept
|
||||
-> size_type
|
||||
{
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Array::max_size() const noexcept
|
||||
-> size_type
|
||||
{
|
||||
return elements.max_size();
|
||||
}
|
||||
|
||||
[[nodiscard]] TypeInfo& Array::type_info()
|
||||
{
|
||||
return elementType;
|
||||
}
|
||||
|
||||
[[nodiscard]] const TypeInfo& Array::type_info() const
|
||||
{
|
||||
return elementType;
|
||||
}
|
||||
|
||||
[[nodiscard]] TypeInfo::RawType Array::type() const
|
||||
{
|
||||
const REX::TEnumSet typeID = elementType.GetRawType();
|
||||
switch (*typeID) {
|
||||
case TypeInfo::RawType::kNone:
|
||||
case TypeInfo::RawType::kObject:
|
||||
case TypeInfo::RawType::kString:
|
||||
case TypeInfo::RawType::kInt:
|
||||
case TypeInfo::RawType::kFloat:
|
||||
case TypeInfo::RawType::kBool:
|
||||
return *(typeID + TypeInfo::RawType::kArrayStart);
|
||||
default:
|
||||
return *(typeID + TypeInfo::RawType::kObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "RE/B/BSScript_Internal_VirtualMachine.h"
|
||||
|
||||
#include "RE/G/GameScript.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
VirtualMachine* VirtualMachine::GetSingleton()
|
||||
{
|
||||
auto vm = GameVM::GetSingleton();
|
||||
return vm ? static_cast<VirtualMachine*>(vm->impl.get()) : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "RE/B/BSScript_Object.h"
|
||||
|
||||
#include "RE/B/BSScript_IObjectHandlePolicy.h"
|
||||
#include "RE/B/BSScript_Internal_VirtualMachine.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Object::~Object()
|
||||
{
|
||||
if (IsConstructed()) {
|
||||
const std::uint32_t size = type ? type->GetVariableCount() : 0;
|
||||
for (std::uint32_t i = 0; i < size; ++i) {
|
||||
variables[i].reset();
|
||||
}
|
||||
|
||||
constructed = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
auto lock = reinterpret_cast<std::uintptr_t>(lockStructure) & ~static_cast<std::uintptr_t>(1);
|
||||
if (lock) {
|
||||
REX::TAtomicRef l{ lock };
|
||||
--l;
|
||||
}
|
||||
}
|
||||
ObjectTypeInfo* Object::GetTypeInfo()
|
||||
{
|
||||
return type.get();
|
||||
}
|
||||
|
||||
const ObjectTypeInfo* Object::GetTypeInfo() const
|
||||
{
|
||||
return type.get();
|
||||
}
|
||||
|
||||
void* Object::Resolve(std::uint32_t a_typeID) const
|
||||
{
|
||||
auto vm = Internal::VirtualMachine::GetSingleton();
|
||||
if (!vm) {
|
||||
return nullptr;
|
||||
}
|
||||
IObjectHandlePolicy& policy = vm->GetObjectHandlePolicy();
|
||||
auto myHandle = GetHandle();
|
||||
if (policy.HandleIsType(a_typeID, myHandle) && policy.IsHandleObjectAvailable(myHandle)) {
|
||||
return policy.GetObjectForHandle(a_typeID, myHandle);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Variable* Object::GetProperty(const BSFixedString& a_name)
|
||||
{
|
||||
return const_cast<Variable*>(
|
||||
const_cast<const Object*>(this)->GetProperty(a_name));
|
||||
}
|
||||
|
||||
const Variable* Object::GetProperty(const BSFixedString& a_name) const
|
||||
{
|
||||
constexpr auto INVALID = static_cast<std::uint32_t>(-1);
|
||||
|
||||
auto idx = INVALID;
|
||||
for (auto cls = type.get(); cls && idx == INVALID; cls = cls->GetParent()) {
|
||||
idx = cls->GetPropertyIndex(a_name);
|
||||
}
|
||||
|
||||
return idx != INVALID ? std::addressof(variables[idx]) : nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "RE/B/BSScript_ObjectTypeInfo.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
BSFixedString ObjectTypeInfo::UserFlagInfo::GetUserFlag() const
|
||||
{
|
||||
auto sanitizedType = data & ~kSetOnObject;
|
||||
return *reinterpret_cast<BSFixedString*>(&sanitizedType);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::NamedStateInfo::GetFuncIter()
|
||||
-> Func*
|
||||
{
|
||||
return reinterpret_cast<Func*>((std::uintptr_t)this + memberFunctionOffset);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::NamedStateInfo::GetFuncIter() const
|
||||
-> const Func*
|
||||
{
|
||||
return reinterpret_cast<const Func*>((std::uintptr_t)this + memberFunctionOffset);
|
||||
}
|
||||
|
||||
ObjectTypeInfo::~ObjectTypeInfo()
|
||||
{
|
||||
dtor();
|
||||
}
|
||||
|
||||
const char* ObjectTypeInfo::GetName() const
|
||||
{
|
||||
return name.c_str();
|
||||
}
|
||||
|
||||
ObjectTypeInfo* ObjectTypeInfo::GetParent()
|
||||
{
|
||||
return parentTypeInfo.get();
|
||||
}
|
||||
|
||||
const ObjectTypeInfo* ObjectTypeInfo::GetParent() const
|
||||
{
|
||||
return parentTypeInfo.get();
|
||||
}
|
||||
|
||||
TypeInfo::RawType ObjectTypeInfo::GetRawType() const
|
||||
{
|
||||
return TypeInfo::RawType::kObject;
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUnlinkedFunctionIter()
|
||||
-> UnlinkedNativeFunction*
|
||||
{
|
||||
return reinterpret_cast<UnlinkedNativeFunction*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUnlinkedFunctionIter() const
|
||||
-> const UnlinkedNativeFunction*
|
||||
{
|
||||
return reinterpret_cast<const UnlinkedNativeFunction*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUserFlagIter()
|
||||
-> UserFlagInfo*
|
||||
{
|
||||
return reinterpret_cast<UserFlagInfo*>(data);
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetUserFlagIter() const
|
||||
-> const UserFlagInfo*
|
||||
{
|
||||
return reinterpret_cast<const UserFlagInfo*>(data);
|
||||
}
|
||||
|
||||
std::uint32_t ObjectTypeInfo::GetTotalNumVariables() const
|
||||
{
|
||||
auto numVars = GetNumVariables();
|
||||
for (auto iter = GetParent(); iter; iter = iter->GetParent()) {
|
||||
numVars += iter->GetNumVariables();
|
||||
}
|
||||
return numVars;
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetVariableIter()
|
||||
-> VariableInfo*
|
||||
{
|
||||
return reinterpret_cast<VariableInfo*>(GetUserFlagIter() + GetNumUserFlags());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetVariableIter() const
|
||||
-> const VariableInfo*
|
||||
{
|
||||
return reinterpret_cast<const VariableInfo*>(GetUserFlagIter() + GetNumUserFlags());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialValueIter()
|
||||
-> InitialValueInfo*
|
||||
{
|
||||
return reinterpret_cast<InitialValueInfo*>(GetVariableIter() + GetNumVariables());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialValueIter() const
|
||||
-> const InitialValueInfo*
|
||||
{
|
||||
return reinterpret_cast<const InitialValueInfo*>(GetVariableIter() + GetNumVariables());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetPropertyIter()
|
||||
-> PropertyInfo*
|
||||
{
|
||||
return reinterpret_cast<PropertyInfo*>(GetInitialValueIter() + GetNumInitalValues());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetPropertyIter() const
|
||||
-> const PropertyInfo*
|
||||
{
|
||||
return reinterpret_cast<const PropertyInfo*>(GetInitialValueIter() + GetNumInitalValues());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetGlobalFuncIter()
|
||||
-> GlobalFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<GlobalFuncInfo*>(GetPropertyIter() + GetNumProperties());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetGlobalFuncIter() const
|
||||
-> const GlobalFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<const GlobalFuncInfo*>(GetPropertyIter() + GetNumProperties());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetMemberFuncIter()
|
||||
-> MemberFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<MemberFuncInfo*>(GetGlobalFuncIter() + GetNumGlobalFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetMemberFuncIter() const
|
||||
-> const MemberFuncInfo*
|
||||
{
|
||||
return reinterpret_cast<const MemberFuncInfo*>(GetGlobalFuncIter() + GetNumGlobalFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetNamedStateIter()
|
||||
-> NamedStateInfo*
|
||||
{
|
||||
return reinterpret_cast<NamedStateInfo*>(GetMemberFuncIter() + GetNumMemberFuncs());
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetNamedStateIter() const
|
||||
-> const NamedStateInfo*
|
||||
{
|
||||
return reinterpret_cast<const NamedStateInfo*>(GetMemberFuncIter() + GetNumMemberFuncs());
|
||||
}
|
||||
|
||||
std::uint32_t ObjectTypeInfo::GetPropertyIndex(const BSFixedString& a_name) const
|
||||
{
|
||||
const auto props = GetPropertyIter();
|
||||
if (props) {
|
||||
for (std::uint32_t i = 0; i < GetNumProperties(); ++i) {
|
||||
const auto& prop = props[i];
|
||||
if (prop.name == a_name) {
|
||||
return prop.info.autoVarIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return static_cast<std::uint32_t>(-1);
|
||||
}
|
||||
|
||||
constexpr bool ObjectTypeInfo::HasPropertyGroups() const
|
||||
{
|
||||
return propertyGroups.size();
|
||||
}
|
||||
|
||||
auto ObjectTypeInfo::GetInitialState() const -> const BSFixedString*
|
||||
{
|
||||
BSFixedString thing = "hello";
|
||||
return reinterpret_cast<const BSFixedString*>(GetNamedStateIter() + GetNumNamedStates());
|
||||
}
|
||||
|
||||
void ObjectTypeInfo::dtor()
|
||||
{
|
||||
using func_t = decltype(&ObjectTypeInfo::dtor);
|
||||
REL::Relocation<func_t> func{ ID::BSScript_ObjectTypeInfo::dtor };
|
||||
return func(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "RE/B/BSScript_PackedInstructionStream.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
namespace ByteCode
|
||||
{
|
||||
PackedInstructionStream::PackedInstructionStream() :
|
||||
numInstructionBits(0),
|
||||
jumpTargetBitCount(0),
|
||||
localVariableBitCount(0),
|
||||
memberVariableBitCount(0),
|
||||
instructions(nullptr)
|
||||
{}
|
||||
|
||||
PackedInstructionStream::PackedInstructionStream(
|
||||
void* a_instructions,
|
||||
std::uint32_t a_numInstrBits,
|
||||
std::uint16_t a_jumpTargetBitCount,
|
||||
std::int8_t a_localVariableBitCount,
|
||||
std::int8_t a_memberVariableBitCount) :
|
||||
numInstructionBits(a_numInstrBits),
|
||||
jumpTargetBitCount(a_jumpTargetBitCount),
|
||||
localVariableBitCount(a_localVariableBitCount),
|
||||
memberVariableBitCount(a_memberVariableBitCount),
|
||||
instructions(a_instructions)
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "RE/B/BSScript_StackFrame.h"
|
||||
|
||||
#include "RE/B/BSScript_Internal_Stack.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
std::uint32_t StackFrame::GetPageForFrame() const
|
||||
{
|
||||
return parent->GetPageForFrame(this);
|
||||
}
|
||||
|
||||
Variable& StackFrame::GetStackFrameVariable(std::uint32_t a_index, std::uint32_t a_pageHint) const
|
||||
{
|
||||
return parent->GetStackFrameVariable(this, a_index, a_pageHint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSScript_Struct.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Struct::~Struct()
|
||||
{
|
||||
if (constructed) {
|
||||
const std::uint32_t size = type ? type->variables.size() : 0;
|
||||
for (std::uint32_t i = 0; i < size; ++i) {
|
||||
variables[i].reset();
|
||||
}
|
||||
|
||||
constructed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "RE/B/BSScript_StructTypeInfo.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSScript
|
||||
{
|
||||
TypeInfo::RawType StructTypeInfo::GetRawType() const
|
||||
{
|
||||
return TypeInfo::RawType::kStruct;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "RE/B/BSScript_TypeInfo.h"
|
||||
|
||||
#include "RE/B/BSScript_IComplexType.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
auto TypeInfo::GetRawType() const
|
||||
-> RawType
|
||||
{
|
||||
if (IsComplex()) {
|
||||
const auto complex =
|
||||
reinterpret_cast<IComplexType*>(
|
||||
reinterpret_cast<std::uintptr_t>(data.complexTypeInfo) &
|
||||
~static_cast<std::uintptr_t>(1));
|
||||
uint32_t rtype = (uint32_t)complex->GetRawType();
|
||||
if (IsArray()) {
|
||||
rtype += 10;
|
||||
}
|
||||
return (RawType)rtype;
|
||||
} else {
|
||||
return *data.rawType;
|
||||
}
|
||||
}
|
||||
|
||||
IComplexType* TypeInfo::GetComplexType() const
|
||||
{
|
||||
return IsComplex() ? reinterpret_cast<IComplexType*>(
|
||||
reinterpret_cast<std::uintptr_t>(data.complexTypeInfo) &
|
||||
~static_cast<std::uintptr_t>(1)) :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
ObjectTypeInfo* TypeInfo::GetObjectTypeInfo() const
|
||||
{
|
||||
return IsObject() || IsObjectArray() ? reinterpret_cast<ObjectTypeInfo*>(GetComplexType()) : nullptr;
|
||||
}
|
||||
|
||||
StructTypeInfo* TypeInfo::GetStructTypeInfo() const
|
||||
{
|
||||
return IsStruct() || IsStructArray() ? reinterpret_cast<StructTypeInfo*>(GetComplexType()) : nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "RE/B/BSScript_Variable.h"
|
||||
|
||||
#include "RE/B/BSScript_Array.h"
|
||||
#include "RE/B/BSScript_Object.h"
|
||||
#include "RE/B/BSScript_Struct.h"
|
||||
|
||||
namespace RE::BSScript
|
||||
{
|
||||
Variable& Variable::operator=(BSTSmartPointer<Object> a_object)
|
||||
{
|
||||
reset();
|
||||
if (a_object) {
|
||||
value.o = std::move(a_object);
|
||||
varType = value.o->type.get();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Object>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variable& Variable::operator=(BSTSmartPointer<Struct> a_struct)
|
||||
{
|
||||
reset();
|
||||
if (a_struct) {
|
||||
value.t = std::move(a_struct);
|
||||
varType = value.t->type.get();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Struct>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variable& Variable::operator=(BSTSmartPointer<Array> a_array)
|
||||
{
|
||||
reset();
|
||||
if (a_array) {
|
||||
value.a = std::move(a_array);
|
||||
varType = value.a->elementType;
|
||||
varType.SetArray(true);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(is<Array>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Variable::reset()
|
||||
{
|
||||
switch (varType.GetRawType()) {
|
||||
case RawType::kObject:
|
||||
value.o.reset();
|
||||
break;
|
||||
case RawType::kString:
|
||||
value.s.~BSFixedString();
|
||||
break;
|
||||
case RawType::kVar:
|
||||
delete value.v;
|
||||
break;
|
||||
case RawType::kStruct:
|
||||
value.t.reset();
|
||||
break;
|
||||
case RawType::kArrayObject:
|
||||
case RawType::kArrayString:
|
||||
case RawType::kArrayInt:
|
||||
case RawType::kArrayFloat:
|
||||
case RawType::kArrayBool:
|
||||
case RawType::kArrayVar:
|
||||
case RawType::kArrayStruct:
|
||||
value.a.reset();
|
||||
break;
|
||||
case RawType::kNone:
|
||||
case RawType::kInt:
|
||||
case RawType::kFloat:
|
||||
case RawType::kBool:
|
||||
break;
|
||||
default:
|
||||
assert(false); // unhandled type
|
||||
break;
|
||||
}
|
||||
|
||||
varType = RawType::kNone;
|
||||
value.v = nullptr;
|
||||
assert(is<std::nullptr_t>());
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(misc-no-recursion)
|
||||
void Variable::copy(const Variable& a_rhs)
|
||||
{
|
||||
assert(varType.GetRawType() == RawType::kNone);
|
||||
assert(value.v == nullptr);
|
||||
|
||||
switch (a_rhs.varType.GetRawType()) {
|
||||
case RawType::kObject:
|
||||
value.o = a_rhs.value.o;
|
||||
break;
|
||||
case RawType::kString:
|
||||
value.s = a_rhs.value.s;
|
||||
break;
|
||||
case RawType::kVar:
|
||||
if (a_rhs.value.v) {
|
||||
value.v = new Variable(*a_rhs.value.v);
|
||||
}
|
||||
break;
|
||||
case RawType::kStruct:
|
||||
value.t = a_rhs.value.t;
|
||||
break;
|
||||
case RawType::kArrayObject:
|
||||
case RawType::kArrayString:
|
||||
case RawType::kArrayInt:
|
||||
case RawType::kArrayFloat:
|
||||
case RawType::kArrayBool:
|
||||
case RawType::kArrayVar:
|
||||
case RawType::kArrayStruct:
|
||||
value.a = a_rhs.value.a;
|
||||
break;
|
||||
case RawType::kNone:
|
||||
break;
|
||||
case RawType::kInt:
|
||||
value.u = a_rhs.value.u;
|
||||
break;
|
||||
case RawType::kFloat:
|
||||
value.f = a_rhs.value.f;
|
||||
break;
|
||||
case RawType::kBool:
|
||||
value.b = a_rhs.value.b;
|
||||
break;
|
||||
default:
|
||||
assert(false); // unhandled type
|
||||
break;
|
||||
}
|
||||
|
||||
varType = a_rhs.varType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "RE/B/BSSpinLock.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSAutoLockReadLockPolicy<BSReadWriteLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockReadLockPolicy<BSReadWriteLock>>);
|
||||
|
||||
template class BSAutoLockWriteLockPolicy<BSReadWriteLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockWriteLockPolicy<BSReadWriteLock>>);
|
||||
|
||||
template class BSAutoLockDefaultPolicy<BSSpinLock>;
|
||||
static_assert(std::is_empty_v<BSAutoLockDefaultPolicy<BSSpinLock>>);
|
||||
|
||||
template class BSAutoLock<BSReadWriteLock, BSAutoLockReadLockPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSReadWriteLock, BSAutoLockReadLockPolicy>) == 0x8);
|
||||
|
||||
template class BSAutoLock<BSReadWriteLock, BSAutoLockWriteLockPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSReadWriteLock, BSAutoLockWriteLockPolicy>) == 0x8);
|
||||
|
||||
template class BSAutoLock<BSSpinLock, BSAutoLockDefaultPolicy>;
|
||||
static_assert(sizeof(BSAutoLock<BSSpinLock, BSAutoLockDefaultPolicy>) == 0x8);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSSpring_SpringState.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
namespace BSSpring
|
||||
{
|
||||
template class SpringState<float>;
|
||||
static_assert(sizeof(SpringState<float>) == 0xC);
|
||||
|
||||
template class SpringState<NiPoint2>;
|
||||
static_assert(sizeof(SpringState<NiPoint2>) == 0x14);
|
||||
|
||||
template class SpringState<NiPoint3>;
|
||||
static_assert(sizeof(SpringState<NiPoint3>) == 0x1C);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/BSTArray.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTAlignedHeapArrayAllocator<0x10>::Allocator;
|
||||
static_assert(sizeof(BSTAlignedHeapArrayAllocator<0x10>::Allocator) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RE/B/BSTAtomicValue.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTAtomicValue<std::int32_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::int32_t>) == 0x4);
|
||||
|
||||
template class BSTAtomicValue<std::uint32_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::uint32_t>) == 0x4);
|
||||
|
||||
template class BSTAtomicValue<std::int64_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::int64_t>) == 0x8);
|
||||
|
||||
template class BSTAtomicValue<std::uint64_t>;
|
||||
static_assert(sizeof(BSTAtomicValue<std::uint64_t>) == 0x8);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "RE/B/BSTDataBuffer.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTDataBuffer<1>;
|
||||
static_assert(sizeof(BSTDataBuffer<1>) == 0x10);
|
||||
|
||||
template class BSTDataBuffer<2>;
|
||||
static_assert(sizeof(BSTDataBuffer<2>) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/BSTInterpolator.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor>;
|
||||
static_assert(sizeof(BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor>) == 0x18);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "RE/B/BSTPoint.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template class BSTPoint2<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::int32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint2<std::uint32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2<float>;
|
||||
static_assert(sizeof(BSTPoint2<float>) == 0x8);
|
||||
|
||||
template class BSTPoint2<double>;
|
||||
static_assert(sizeof(BSTPoint2<double>) == 0x10);
|
||||
|
||||
template class BSTPoint2Base<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2Base<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint8_t>) == 0x2);
|
||||
|
||||
template class BSTPoint2Base<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2Base<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint16_t>) == 0x4);
|
||||
|
||||
template class BSTPoint2Base<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::int32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint2Base<std::uint32_t>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<float>;
|
||||
static_assert(sizeof(BSTPoint2Base<float>) == 0x8);
|
||||
|
||||
template class BSTPoint2Base<double>;
|
||||
static_assert(sizeof(BSTPoint2Base<double>) == 0x10);
|
||||
|
||||
template class BSTPoint3<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::int32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint3<std::uint32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3<float>;
|
||||
static_assert(sizeof(BSTPoint3<float>) == 0xC);
|
||||
|
||||
template class BSTPoint3<double>;
|
||||
static_assert(sizeof(BSTPoint3<double>) == 0x18);
|
||||
|
||||
template class BSTPoint3Base<std::int8_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3Base<std::uint8_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint8_t>) == 0x3);
|
||||
|
||||
template class BSTPoint3Base<std::int16_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3Base<std::uint16_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint16_t>) == 0x6);
|
||||
|
||||
template class BSTPoint3Base<std::int32_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::int32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<std::uint32_t>;
|
||||
static_assert(sizeof(BSTPoint3Base<std::uint32_t>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<float>;
|
||||
static_assert(sizeof(BSTPoint3Base<float>) == 0xC);
|
||||
|
||||
template class BSTPoint3Base<double>;
|
||||
static_assert(sizeof(BSTPoint3Base<double>) == 0x18);
|
||||
|
||||
template class BSTPointDefaultOps<std::int8_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int8_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint8_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint8_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::int16_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int16_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint16_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint16_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::int32_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::int32_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<std::uint32_t>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<std::uint32_t>>);
|
||||
|
||||
template class BSTPointDefaultOps<float>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<float>>);
|
||||
|
||||
template class BSTPointDefaultOps<double>;
|
||||
static_assert(std::is_empty_v<BSTPointDefaultOps<double>>);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "RE/B/BSVisit.h"
|
||||
|
||||
#include "RE/N/NiAVObject.h"
|
||||
#include "RE/N/NiNode.h"
|
||||
|
||||
namespace RE::BSVisit
|
||||
{
|
||||
BSVisitControl TraverseScenegraphGeometries(NiAVObject* a_object, std::function<BSVisitControl(BSGeometry*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (auto geom = a_object->IsGeometry())
|
||||
return a_func(geom);
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphGeometries(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
|
||||
BSVisitControl TraverseScenegraphObjects(NiAVObject* a_object, std::function<BSVisitControl(NiAVObject*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (a_func(a_object) == BSVisitControl::kStop)
|
||||
return BSVisitControl::kStop;
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphObjects(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
|
||||
BSVisitControl TraverseScenegraphCollision(const NiAVObject* a_object, std::function<BSVisitControl(bhkNPCollisionObject*)> a_func)
|
||||
{
|
||||
if (a_object) {
|
||||
if (const auto collision = a_object->GetCollisionObject()) {
|
||||
if (const auto collisionNP = collision->IsbhkNPCollisionObject()) {
|
||||
if (a_func(collisionNP) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto node = a_object->IsNode()) {
|
||||
for (const auto& child : node->children) {
|
||||
if (TraverseScenegraphCollision(child.get(), a_func) == BSVisitControl::kStop) {
|
||||
return BSVisitControl::kStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BSVisitControl::kContinue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "RE/B/ButtonEvent.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template ButtonEvent* InputEvent::As() noexcept;
|
||||
template const ButtonEvent* InputEvent::As() const noexcept;
|
||||
}
|
||||
Reference in New Issue
Block a user