Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145#include "scriptcontext.hpp"
#include <algorithm>#include <sstream>#include <type_traits>
#include <apps/opencs/model/world/columns.hpp>#include <apps/opencs/model/world/idcollection.hpp>#include <apps/opencs/model/world/record.hpp>#include <apps/opencs/model/world/refidcollection.hpp>
#include <components/compiler/nullerrorhandler.hpp>#include <components/compiler/quickfileparser.hpp>#include <components/compiler/scanner.hpp>#include <components/esm3/loadglob.hpp>#include <components/esm3/loadscpt.hpp>#include <components/esm3/variant.hpp>#include <components/misc/strings/lower.hpp>
#include "data.hpp"
CSMWorld::ScriptContext::ScriptContext(const Data& data) : mData(data) , mIdsUpdated(false){}
bool CSMWorld::ScriptContext::canDeclareLocals() const{ return true;}
char CSMWorld::ScriptContext::getGlobalType(const std::string& name) const{ const int index = mData.getGlobals().searchId(ESM::RefId::stringRefId(name));
if (index != -1) { switch (mData.getGlobals().getRecord(index).get().mValue.getType()) { case ESM::VT_Short: return 's'; case ESM::VT_Long: return 'l'; case ESM::VT_Float: return 'f';
default: return ' '; } }
return ' ';}
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string& name, const ESM::RefId& id) const{ ESM::RefId id2 = id;
int index = mData.getScripts().searchId(id2); bool reference = false;
if (index == -1) { // ID is not a script ID. Search for a matching referenceable instead. index = mData.getReferenceables().searchId(id2);
if (index != -1) { // Referenceable found. int columnIndex = mData.getReferenceables().findColumnIndex(Columns::ColumnId_Script);
id2 = ESM::RefId::stringRefId( mData.getReferenceables().getData(index, columnIndex).toString().toUtf8().constData());
if (!id2.empty()) { // Referenceable has a script -> use it. index = mData.getScripts().searchId(id2); reference = true; } } }
if (index == -1) return std::make_pair(' ', false);
auto iter = mLocals.find(id2);
if (iter == mLocals.end()) { Compiler::Locals locals;
Compiler::NullErrorHandler errorHandler; std::istringstream stream(mData.getScripts().getRecord(index).get().mScriptText); Compiler::QuickFileParser parser(errorHandler, *this, locals); Compiler::Scanner scanner(errorHandler, stream, getExtensions()); scanner.scan(parser);
iter = mLocals.emplace(id2, std::move(locals)).first; }
return std::make_pair(iter->second.getType(Misc::StringUtils::lowerCase(name)), reference);}
bool CSMWorld::ScriptContext::isId(const ESM::RefId& name) const{ if (!mIdsUpdated) { mIds = mData.getIds();
std::sort(mIds.begin(), mIds.end());
mIdsUpdated = true; }
return std::binary_search(mIds.begin(), mIds.end(), name);}
void CSMWorld::ScriptContext::invalidateIds(){ mIdsUpdated = false;}
void CSMWorld::ScriptContext::clear(){ mIds.clear(); mIdsUpdated = false; mLocals.clear();}
bool CSMWorld::ScriptContext::clearLocals(const std::string& script){ const auto iter = mLocals.find(script);
if (iter != mLocals.end()) { mLocals.erase(iter); mIdsUpdated = false; return true; }
return false;}