Merge branch 'master' of gitlab.com:openmw/openmw into doc_has_more_probls
@ -81,7 +81,7 @@ message(STATUS "Configuring OpenMW...")
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 49)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
set(OPENMW_LUA_API_REVISION 60)
|
||||
set(OPENMW_LUA_API_REVISION 61)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 1)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
@ -2,7 +2,8 @@
|
||||
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm/vector3.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<width>775</width>
|
||||
<height>635</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>750</width>
|
||||
<width>775</width>
|
||||
<height>635</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
@ -424,6 +425,7 @@ void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent* event)
|
||||
painter.setBackgroundMode(Qt::OpaqueMode);
|
||||
QFont font = painter.font();
|
||||
QBrush background = painter.background();
|
||||
QColor textColor = QApplication::palette().text().color();
|
||||
|
||||
while (block.isValid() && top <= event->rect().bottom())
|
||||
{
|
||||
@ -440,7 +442,7 @@ void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent* event)
|
||||
else
|
||||
{
|
||||
painter.setBackground(background);
|
||||
painter.setPen(Qt::black);
|
||||
painter.setPen(textColor);
|
||||
}
|
||||
painter.setFont(newFont);
|
||||
painter.drawText(0, top, mLineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, number);
|
||||
|
@ -343,7 +343,12 @@ namespace MWGui
|
||||
|
||||
MWBase::Environment::get().getInputManager()->update(0, true, true);
|
||||
|
||||
mResourceSystem->reportStats(mViewer->getFrameStamp()->getFrameNumber(), mViewer->getViewerStats());
|
||||
osg::Stats* const stats = mViewer->getViewerStats();
|
||||
const unsigned frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||
|
||||
stats->setAttribute(frameNumber, "Loading", 1);
|
||||
|
||||
mResourceSystem->reportStats(frameNumber, stats);
|
||||
if (osgUtil::IncrementalCompileOperation* ico = mViewer->getIncrementalCompileOperation())
|
||||
{
|
||||
ico->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(1.f / getTargetFrameRate());
|
||||
|
@ -104,7 +104,27 @@ namespace MWLua
|
||||
});
|
||||
aiPackage["sideWithTarget"] = sol::readonly_property([](const AiPackage& p) { return p.sideWithTarget(); });
|
||||
aiPackage["destPosition"] = sol::readonly_property([](const AiPackage& p) { return p.getDestination(); });
|
||||
aiPackage["distance"] = sol::readonly_property([](const AiPackage& p) { return p.getDistance(); });
|
||||
aiPackage["duration"] = sol::readonly_property([](const AiPackage& p) { return p.getDuration(); });
|
||||
aiPackage["idle"] = sol::readonly_property([context](const AiPackage& p) -> sol::optional<sol::table> {
|
||||
if (p.getTypeId() == MWMechanics::AiPackageTypeId::Wander)
|
||||
{
|
||||
sol::table idles(context.mLua->sol(), sol::create);
|
||||
const std::vector<unsigned char>& idle = static_cast<const MWMechanics::AiWander&>(p).getIdle();
|
||||
if (!idle.empty())
|
||||
{
|
||||
for (size_t i = 0; i < idle.size(); ++i)
|
||||
{
|
||||
std::string_view groupName = MWMechanics::AiWander::getIdleGroupName(i);
|
||||
idles[groupName] = idle[i];
|
||||
}
|
||||
return idles;
|
||||
}
|
||||
}
|
||||
return sol::nullopt;
|
||||
});
|
||||
|
||||
aiPackage["isRepeat"] = sol::readonly_property([](const AiPackage& p) { return p.getRepeat(); });
|
||||
selfAPI["_getActiveAiPackage"] = [](SelfObject& self) -> sol::optional<std::shared_ptr<AiPackage>> {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
@ -132,13 +152,25 @@ namespace MWLua
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
ai.stack(MWMechanics::AiPursue(target.ptr()), ptr, cancelOther);
|
||||
};
|
||||
selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target, bool cancelOther) {
|
||||
selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target, sol::optional<LCell> cell,
|
||||
float duration, const osg::Vec3f& dest, bool repeat, bool cancelOther) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
ai.stack(MWMechanics::AiFollow(target.ptr()), ptr, cancelOther);
|
||||
if (cell)
|
||||
{
|
||||
ai.stack(MWMechanics::AiFollow(target.ptr().getCellRef().getRefId(),
|
||||
cell->mStore->getCell()->getNameId(), duration, dest.x(), dest.y(), dest.z(), repeat),
|
||||
ptr, cancelOther);
|
||||
}
|
||||
else
|
||||
{
|
||||
ai.stack(MWMechanics::AiFollow(
|
||||
target.ptr().getCellRef().getRefId(), duration, dest.x(), dest.y(), dest.z(), repeat),
|
||||
ptr, cancelOther);
|
||||
}
|
||||
};
|
||||
selfAPI["_startAiEscort"] = [](SelfObject& self, const LObject& target, LCell cell, float duration,
|
||||
const osg::Vec3f& dest, bool cancelOther) {
|
||||
const osg::Vec3f& dest, bool repeat, bool cancelOther) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
// TODO: change AiEscort implementation to accept ptr instead of a non-unique refId.
|
||||
@ -146,23 +178,27 @@ namespace MWLua
|
||||
int gameHoursDuration = static_cast<int>(std::ceil(duration / 3600.0));
|
||||
auto* esmCell = cell.mStore->getCell();
|
||||
if (esmCell->isExterior())
|
||||
ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), false), ptr,
|
||||
ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), repeat), ptr,
|
||||
cancelOther);
|
||||
else
|
||||
ai.stack(MWMechanics::AiEscort(
|
||||
refId, esmCell->getNameId(), gameHoursDuration, dest.x(), dest.y(), dest.z(), false),
|
||||
refId, esmCell->getNameId(), gameHoursDuration, dest.x(), dest.y(), dest.z(), repeat),
|
||||
ptr, cancelOther);
|
||||
};
|
||||
selfAPI["_startAiWander"] = [](SelfObject& self, int distance, float duration, bool cancelOther) {
|
||||
selfAPI["_startAiWander"]
|
||||
= [](SelfObject& self, int distance, int duration, sol::table luaIdle, bool repeat, bool cancelOther) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
std::vector<unsigned char> idle;
|
||||
// Lua index starts at 1
|
||||
for (size_t i = 1; i <= luaIdle.size(); i++)
|
||||
idle.emplace_back(luaIdle.get<unsigned char>(i));
|
||||
ai.stack(MWMechanics::AiWander(distance, duration, 0, idle, repeat), ptr, cancelOther);
|
||||
};
|
||||
selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target, bool repeat, bool cancelOther) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
int gameHoursDuration = static_cast<int>(std::ceil(duration / 3600.0));
|
||||
ai.stack(MWMechanics::AiWander(distance, gameHoursDuration, 0, {}, false), ptr, cancelOther);
|
||||
};
|
||||
selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target, bool cancelOther) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
|
||||
ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), false), ptr, cancelOther);
|
||||
ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), repeat), ptr, cancelOther);
|
||||
};
|
||||
selfAPI["_enableLuaAnimations"] = [](SelfObject& self, bool enable) {
|
||||
const MWWorld::Ptr& ptr = self.ptr();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "aiescort.hpp"
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm3/aisequence.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
|
@ -51,6 +51,8 @@ namespace MWMechanics
|
||||
|
||||
osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); }
|
||||
|
||||
std::optional<float> getDuration() const override { return mDuration; }
|
||||
|
||||
private:
|
||||
const std::string mCellId;
|
||||
const float mX;
|
||||
|
@ -110,6 +110,10 @@ namespace MWMechanics
|
||||
|
||||
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
|
||||
|
||||
virtual std::optional<int> getDistance() const { return std::nullopt; }
|
||||
|
||||
virtual std::optional<float> getDuration() const { return std::nullopt; }
|
||||
|
||||
/// Return true if any loaded actor with this AI package must be active.
|
||||
bool alwaysActive() const { return mOptions.mAlwaysActive; }
|
||||
|
||||
|
@ -113,6 +113,14 @@ namespace MWMechanics
|
||||
|
||||
bool isStationary() const { return mDistance == 0; }
|
||||
|
||||
std::optional<int> getDistance() const override { return mDistance; }
|
||||
|
||||
std::optional<float> getDuration() const override { return static_cast<float>(mDuration); }
|
||||
|
||||
const std::vector<unsigned char>& getIdle() const { return mIdle; }
|
||||
|
||||
static std::string_view getIdleGroupName(size_t index) { return sIdleSelectToGroupName[index]; }
|
||||
|
||||
private:
|
||||
void stopWalking(const MWWorld::Ptr& actor);
|
||||
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
@ -16,8 +15,6 @@
|
||||
#include <osg/Timer>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include "collisiontype.hpp"
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <osg/Object>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/esmterrain/storage.hpp>
|
||||
#include <components/resource/resourcemanager.hpp>
|
||||
|
||||
|
@ -555,11 +555,19 @@ namespace MWRender
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (activeGrid)
|
||||
if (activeGrid && !refs.empty())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mRefTrackerMutex);
|
||||
for (auto ref : getRefTracker().mBlacklist)
|
||||
refs.erase(ref);
|
||||
const std::set<ESM::RefNum>& blacklist = getRefTracker().mBlacklist;
|
||||
if (blacklist.size() < refs.size())
|
||||
{
|
||||
for (ESM::RefNum ref : blacklist)
|
||||
refs.erase(ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::erase_if(refs, [&](const auto& ref) { return blacklist.contains(ref.first); });
|
||||
}
|
||||
}
|
||||
|
||||
osg::Vec2f minBound = (center - osg::Vec2f(size / 2.f, size / 2.f));
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
@ -123,7 +125,7 @@ namespace MWScript
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr playerPtr = world->getPlayerPtr();
|
||||
|
||||
osg::Vec2 posFromIndex
|
||||
const osg::Vec2f posFromIndex
|
||||
= ESM::indexToPosition(ESM::ExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId), true);
|
||||
pos.pos[0] = posFromIndex.x();
|
||||
pos.pos[1] = posFromIndex.y();
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
#include <components/compiler/opcodes.hpp>
|
||||
|
||||
#include <components/interpreter/interpreter.hpp>
|
||||
|
@ -624,7 +624,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
|
||||
Log(Debug::Warning) << "Player character's cell no longer exists, changing to the default cell";
|
||||
ESM::ExteriorCellLocation cellIndex(0, 0, ESM::Cell::sDefaultWorldspaceId);
|
||||
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex);
|
||||
osg::Vec2 posFromIndex = ESM::indexToPosition(cellIndex, false);
|
||||
const osg::Vec2f posFromIndex = ESM::indexToPosition(cellIndex, false);
|
||||
ESM::Position pos;
|
||||
pos.pos[0] = posFromIndex.x();
|
||||
pos.pos[1] = posFromIndex.y();
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <osg/Vec2i>
|
||||
|
||||
#include <components/esm/esmbridge.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <components/esm3/loadrace.hpp>
|
||||
#include <components/esm3/projectilestate.hpp>
|
||||
|
||||
#include <components/esm/quaternion.hpp>
|
||||
#include <components/esm/vector3.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/convert.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
@ -542,7 +542,7 @@ namespace MWWorld
|
||||
= mCurrentCell ? mCurrentCell->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId;
|
||||
if (currentGridCenter)
|
||||
{
|
||||
osg::Vec2 center = ESM::indexToPosition(
|
||||
const osg::Vec2f center = ESM::indexToPosition(
|
||||
ESM::ExteriorCellLocation(currentGridCenter->x(), currentGridCenter->y(), worldspace), true);
|
||||
float distance = std::max(std::abs(center.x() - pos.x()), std::abs(center.y() - pos.y()));
|
||||
float cellSize = ESM::getCellSize(worldspace);
|
||||
@ -1171,7 +1171,7 @@ namespace MWWorld
|
||||
&& dx != -halfGridSizePlusOne)
|
||||
continue; // only care about the outer (not yet loaded) part of the grid
|
||||
ESM::ExteriorCellLocation cellIndex(cellX + dx, cellY + dy, extWorldspace);
|
||||
osg::Vec2 thisCellCenter = ESM::indexToPosition(cellIndex, true);
|
||||
const osg::Vec2f thisCellCenter = ESM::indexToPosition(cellIndex, true);
|
||||
|
||||
float dist = std::max(
|
||||
std::abs(thisCellCenter.x() - playerPos.x()), std::abs(thisCellCenter.y() - playerPos.y()));
|
||||
|
@ -10,10 +10,9 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
namespace osg
|
||||
|
@ -2784,7 +2784,7 @@ namespace MWWorld
|
||||
|
||||
int x = ext->getGridX();
|
||||
int y = ext->getGridY();
|
||||
osg::Vec2 posFromIndex = indexToPosition(ESM::ExteriorCellLocation(x, y, ext->getWorldSpace()), true);
|
||||
const osg::Vec2f posFromIndex = indexToPosition(ESM::ExteriorCellLocation(x, y, ext->getWorldSpace()), true);
|
||||
pos.pos[0] = posFromIndex.x();
|
||||
pos.pos[1] = posFromIndex.y();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/misc/algorithm.hpp>
|
||||
|
||||
#include "cellstore.hpp"
|
||||
|
@ -169,6 +169,9 @@ add_component_dir(esm attr common defs esmcommon records util luascripts format
|
||||
indexrefid
|
||||
serializerefid
|
||||
esm3exteriorcellrefid
|
||||
quaternion
|
||||
vector3
|
||||
exteriorcelllocation
|
||||
)
|
||||
|
||||
add_component_dir(fx pass technique lexer lexer_types parse_constants widgets stateupdater)
|
||||
@ -186,6 +189,7 @@ add_component_dir (esm3
|
||||
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
|
||||
infoorder timestamp formatversion landrecorddata selectiongroup dialoguecondition
|
||||
refnum
|
||||
)
|
||||
|
||||
add_component_dir (esmterrain
|
||||
|
@ -602,7 +602,8 @@ void ContentSelectorModel::ContentModel::sortFiles()
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
int firstModifiable = 0;
|
||||
while (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile())
|
||||
while (firstModifiable < mFiles.size()
|
||||
&& (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile()))
|
||||
++firstModifiable;
|
||||
|
||||
// Dependency sort
|
||||
|
53
components/esm/exteriorcelllocation.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESM_EXTERIORCELLLOCATION_H
|
||||
#define OPENMW_COMPONENTS_ESM_EXTERIORCELLLOCATION_H
|
||||
|
||||
#include "refid.hpp"
|
||||
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ExteriorCellLocation
|
||||
{
|
||||
int mX = 0;
|
||||
int mY = 0;
|
||||
ESM::RefId mWorldspace = ESM::Cell::sDefaultWorldspaceId;
|
||||
|
||||
ExteriorCellLocation() = default;
|
||||
|
||||
ExteriorCellLocation(int x, int y, ESM::RefId worldspace)
|
||||
: mX(x)
|
||||
, mY(y)
|
||||
, mWorldspace(worldspace)
|
||||
{
|
||||
}
|
||||
|
||||
friend bool operator==(const ExteriorCellLocation& lhs, const ExteriorCellLocation& rhs) = default;
|
||||
|
||||
friend inline bool operator<(const ExteriorCellLocation& lhs, const ExteriorCellLocation& rhs)
|
||||
{
|
||||
return std::make_tuple(lhs.mX, lhs.mY, lhs.mWorldspace) < std::make_tuple(rhs.mX, rhs.mY, rhs.mWorldspace);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<ESM::ExteriorCellLocation>
|
||||
{
|
||||
std::size_t operator()(const ESM::ExteriorCellLocation& toHash) const
|
||||
{
|
||||
// Compute individual hash values for first,
|
||||
// second and third and combine them using XOR
|
||||
// and bit shifting:
|
||||
|
||||
return ((hash<int>()(toHash.mX) ^ (hash<int>()(toHash.mY) << 1)) >> 1)
|
||||
^ (hash<ESM::RefId>()(toHash.mWorldspace) << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
29
components/esm/quaternion.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESM_QUATERNION_H
|
||||
#define OPENMW_COMPONENTS_ESM_QUATERNION_H
|
||||
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
// format 0, savegames only
|
||||
struct Quaternion
|
||||
{
|
||||
float mValues[4];
|
||||
|
||||
Quaternion() = default;
|
||||
|
||||
Quaternion(const osg::Quat& q)
|
||||
: mValues{
|
||||
static_cast<float>(q.w()),
|
||||
static_cast<float>(q.x()),
|
||||
static_cast<float>(q.y()),
|
||||
static_cast<float>(q.z()),
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
operator osg::Quat() const { return osg::Quat(mValues[1], mValues[2], mValues[3], mValues[0]); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,8 +1,9 @@
|
||||
#include "util.hpp"
|
||||
|
||||
#include <components/esm3/loadland.hpp>
|
||||
#include <components/esm4/loadland.hpp>
|
||||
|
||||
osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre)
|
||||
osg::Vec2f ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre)
|
||||
{
|
||||
const int cellSize = ESM::getCellSize(cellIndex.mWorldspace);
|
||||
|
||||
@ -14,7 +15,8 @@ osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool
|
||||
x += cellSize / 2;
|
||||
y += cellSize / 2;
|
||||
}
|
||||
return osg::Vec2(x, y);
|
||||
|
||||
return osg::Vec2f(x, y);
|
||||
}
|
||||
|
||||
int ESM::getLandSize(ESM::RefId worldspaceId)
|
||||
|
@ -1,79 +1,18 @@
|
||||
#ifndef OPENMW_ESM_UTIL_H
|
||||
#define OPENMW_ESM_UTIL_H
|
||||
#ifndef OPENMW_COMPONENTS_ESM_UTIL_H
|
||||
#define OPENMW_COMPONENTS_ESM_UTIL_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec2>
|
||||
#include <osg/Vec2i>
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec2f>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
#include "components/esm3/loadcell.hpp"
|
||||
#include "components/misc/constants.hpp"
|
||||
|
||||
#include "exteriorcelllocation.hpp"
|
||||
#include "refid.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
||||
// format 0, savegames only
|
||||
|
||||
struct Quaternion
|
||||
{
|
||||
float mValues[4];
|
||||
|
||||
Quaternion() = default;
|
||||
|
||||
Quaternion(const osg::Quat& q)
|
||||
{
|
||||
mValues[0] = q.w();
|
||||
mValues[1] = q.x();
|
||||
mValues[2] = q.y();
|
||||
mValues[3] = q.z();
|
||||
}
|
||||
|
||||
operator osg::Quat() const { return osg::Quat(mValues[1], mValues[2], mValues[3], mValues[0]); }
|
||||
};
|
||||
|
||||
struct Vector3
|
||||
{
|
||||
float mValues[3];
|
||||
|
||||
Vector3() = default;
|
||||
|
||||
Vector3(const osg::Vec3f& v)
|
||||
{
|
||||
mValues[0] = v.x();
|
||||
mValues[1] = v.y();
|
||||
mValues[2] = v.z();
|
||||
}
|
||||
|
||||
operator osg::Vec3f() const { return osg::Vec3f(mValues[0], mValues[1], mValues[2]); }
|
||||
};
|
||||
|
||||
struct ExteriorCellLocation
|
||||
{
|
||||
int mX = 0;
|
||||
int mY = 0;
|
||||
ESM::RefId mWorldspace = ESM::Cell::sDefaultWorldspaceId;
|
||||
ExteriorCellLocation() = default;
|
||||
|
||||
ExteriorCellLocation(int x, int y, ESM::RefId worldspace)
|
||||
: mX(x)
|
||||
, mY(y)
|
||||
, mWorldspace(worldspace)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const ExteriorCellLocation& other) const
|
||||
{
|
||||
return mX == other.mX && mY == other.mY && mWorldspace == other.mWorldspace;
|
||||
}
|
||||
|
||||
bool operator<(const ExteriorCellLocation& other) const
|
||||
{
|
||||
return std::make_tuple(mX, mY, mWorldspace) < std::make_tuple(other.mX, other.mY, other.mWorldspace);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool isEsm4Ext(ESM::RefId worldspaceId)
|
||||
{
|
||||
return worldspaceId != ESM::Cell::sDefaultWorldspaceId;
|
||||
@ -81,7 +20,6 @@ namespace ESM
|
||||
|
||||
inline int getCellSize(ESM::RefId worldspaceId)
|
||||
{
|
||||
|
||||
return isEsm4Ext(worldspaceId) ? Constants::ESM4CellSizeInUnits : Constants::CellSizeInUnits;
|
||||
}
|
||||
|
||||
@ -95,25 +33,8 @@ namespace ESM
|
||||
return { static_cast<int>(std::floor(x / cellSize)), static_cast<int>(std::floor(y / cellSize)), worldspaceId };
|
||||
}
|
||||
|
||||
osg::Vec2 indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre = false);
|
||||
///< Convert cell numbers to position.
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<ESM::ExteriorCellLocation>
|
||||
{
|
||||
std::size_t operator()(const ESM::ExteriorCellLocation& toHash) const
|
||||
{
|
||||
// Compute individual hash values for first,
|
||||
// second and third and combine them using XOR
|
||||
// and bit shifting:
|
||||
|
||||
return ((hash<int>()(toHash.mX) ^ (hash<int>()(toHash.mY) << 1)) >> 1)
|
||||
^ (hash<ESM::RefId>()(toHash.mWorldspace) << 1);
|
||||
}
|
||||
};
|
||||
// Convert exterior cell location to position.
|
||||
osg::Vec2f indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre = false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
24
components/esm/vector3.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESM_VECTOR3_H
|
||||
#define OPENMW_COMPONENTS_ESM_VECTOR3_H
|
||||
|
||||
#include <osg/Vec3f>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
// format 0, savegames only
|
||||
struct Vector3
|
||||
{
|
||||
float mValues[3];
|
||||
|
||||
Vector3() = default;
|
||||
|
||||
Vector3(const osg::Vec3f& v)
|
||||
: mValues{ v.x(), v.y(), v.z() }
|
||||
{
|
||||
}
|
||||
|
||||
operator osg::Vec3f() const { return osg::Vec3f(mValues[0], mValues[1], mValues[2]); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -6,8 +6,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "components/esm/refid.hpp"
|
||||
#include "components/esm/util.hpp"
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/vector3.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -8,13 +8,13 @@
|
||||
#include <components/esm/position.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
|
||||
#include "refnum.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMWriter;
|
||||
class ESMReader;
|
||||
|
||||
using RefNum = ESM::FormId;
|
||||
|
||||
/* Cell reference. This represents ONE object (of many) inside the
|
||||
cell. The cell references are not loaded as part of the normal
|
||||
loading process, but are rather loaded later on demand when we are
|
||||
|
@ -1,18 +1,19 @@
|
||||
#ifndef OPENMW_ESM_PROJECTILESTATE_H
|
||||
#define OPENMW_ESM_PROJECTILESTATE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include "effectlist.hpp"
|
||||
|
||||
#include "components/esm/quaternion.hpp"
|
||||
#include "components/esm/refid.hpp"
|
||||
#include "components/esm/util.hpp"
|
||||
#include "components/esm/vector3.hpp"
|
||||
|
||||
#include "refnum.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
// format 0, savegames only
|
||||
|
||||
|
11
components/esm3/refnum.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESM3_REFNUM_H
|
||||
#define OPENMW_COMPONENTS_ESM3_REFNUM_H
|
||||
|
||||
#include <components/esm/formid.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
using RefNum = ESM::FormId;
|
||||
}
|
||||
|
||||
#endif
|
@ -32,8 +32,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm4/reader.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm/esmterrain.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm3/loadland.hpp>
|
||||
#include <components/esm4/loadland.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <components/terrain/storage.hpp>
|
||||
|
||||
#include <components/esm/esmterrain.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/esm3/loadltex.hpp>
|
||||
|
||||
namespace ESM4
|
||||
|
@ -54,6 +54,7 @@ namespace Resource
|
||||
constexpr std::string_view firstPage[] = {
|
||||
"FrameNumber",
|
||||
"",
|
||||
"Loading",
|
||||
"Compiling",
|
||||
"WorkQueue",
|
||||
"WorkThread",
|
||||
@ -75,7 +76,6 @@ namespace Resource
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
};
|
||||
|
||||
static_assert(std::size(firstPage) == itemsPerPage);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/loadinglistener/reporter.hpp>
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/mathutil.hpp>
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <components/esm/exteriorcelllocation.hpp>
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
|
||||
#include "defs.hpp"
|
||||
|
||||
|
@ -99,6 +99,18 @@ Follow another actor.
|
||||
* - target
|
||||
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
|
||||
- the actor to follow
|
||||
* - destCell
|
||||
- Cell [optional]
|
||||
- the destination cell
|
||||
* - duration
|
||||
- number [optional]
|
||||
- duration in game time (will be rounded up to the next hour)
|
||||
* - destPosition
|
||||
- `3d vector <openmw_util.html##(Vector3)>`_ [optional]
|
||||
- the destination point
|
||||
* - isRepeat
|
||||
- boolean [optional]
|
||||
- Will the package repeat (true or false)
|
||||
|
||||
Escort
|
||||
------
|
||||
@ -126,6 +138,9 @@ Escort another actor to the given location.
|
||||
* - duration
|
||||
- number [optional]
|
||||
- duration in game time (will be rounded up to the next hour)
|
||||
* - isRepeat
|
||||
- boolean [optional]
|
||||
- Will the package repeat (true or false)
|
||||
|
||||
**Example**
|
||||
|
||||
@ -136,6 +151,7 @@ Escort another actor to the given location.
|
||||
target = object.self,
|
||||
destPosition = util.vector3(x, y, z),
|
||||
duration = 3 * time.hour,
|
||||
isRepeat = true
|
||||
})
|
||||
|
||||
Wander
|
||||
@ -158,6 +174,34 @@ Wander nearby current position.
|
||||
* - duration
|
||||
- number [optional]
|
||||
- duration in game time (will be rounded up to the next hour)
|
||||
* - idle
|
||||
- table [optional]
|
||||
- Idle chance values, up to 8
|
||||
* - isRepeat
|
||||
- boolean [optional]
|
||||
- Will the package repeat (true or false)
|
||||
|
||||
**Example**
|
||||
|
||||
.. code-block:: Lua
|
||||
|
||||
local idleTable = {
|
||||
idle2 = 60,
|
||||
idle3 = 50,
|
||||
idle4 = 40,
|
||||
idle5 = 30,
|
||||
idle6 = 20,
|
||||
idle7 = 10,
|
||||
idle8 = 0,
|
||||
idle9 = 25
|
||||
}
|
||||
actor:sendEvent('StartAIPackage', {
|
||||
type = 'Wander',
|
||||
distance = 5000,
|
||||
duration = 5 * time.hour,
|
||||
idle = idleTable,
|
||||
isRepeat = true
|
||||
})
|
||||
|
||||
Travel
|
||||
------
|
||||
@ -176,4 +220,6 @@ Go to given location.
|
||||
* - destPosition
|
||||
- `3d vector <openmw_util.html##(Vector3)>`_ [required]
|
||||
- the point to travel to
|
||||
|
||||
* - isRepeat
|
||||
- boolean [optional]
|
||||
- Will the package repeat (true or false)
|
||||
|
@ -1,5 +1,6 @@
|
||||
local self = require('openmw.self')
|
||||
local interfaces = require('openmw.interfaces')
|
||||
local util = require('openmw.util')
|
||||
|
||||
local function startPackage(args)
|
||||
local cancelOther = args.cancelOther
|
||||
@ -12,16 +13,36 @@ local function startPackage(args)
|
||||
self:_startAiPursue(args.target, cancelOther)
|
||||
elseif args.type == 'Follow' then
|
||||
if not args.target then error("target required") end
|
||||
self:_startAiFollow(args.target, cancelOther)
|
||||
self:_startAiFollow(args.target, args.cellId, args.duration or 0, args.destPosition or util.vector3(0, 0, 0), args.isRepeat or false, cancelOther)
|
||||
elseif args.type == 'Escort' then
|
||||
if not args.target then error("target required") end
|
||||
if not args.destPosition then error("destPosition required") end
|
||||
self:_startAiEscort(args.target, args.destCell or self.cell, args.duration or 0, args.destPosition, cancelOther)
|
||||
elseif args.type == 'Wander' then
|
||||
self:_startAiWander(args.distance or 0, args.duration or 0, cancelOther)
|
||||
local key = "idle"
|
||||
local idle = {}
|
||||
local duration = 0
|
||||
if args.idle then
|
||||
for i = 2, 9 do
|
||||
local val = args.idle[key .. i]
|
||||
if val == nil then
|
||||
idle[i-1] = 0
|
||||
else
|
||||
local v = tonumber(val) or 0
|
||||
if v < 0 or v > 100 then
|
||||
error("idle values cannot exceed 100")
|
||||
end
|
||||
idle[i-1] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
if args.duration then
|
||||
duration = args.duration / 3600
|
||||
end
|
||||
self:_startAiWander(args.distance or 0, duration, idle, args.isRepeat or false, cancelOther)
|
||||
elseif args.type == 'Travel' then
|
||||
if not args.destPosition then error("destPosition required") end
|
||||
self:_startAiTravel(args.destPosition, cancelOther)
|
||||
self:_startAiTravel(args.destPosition, args.isRepeat or false, cancelOther)
|
||||
else
|
||||
error('Unsupported AI Package: ' .. args.type)
|
||||
end
|
||||
@ -47,6 +68,10 @@ return {
|
||||
-- @field openmw.core#GameObject target Target (usually an actor) of the AI package (can be nil).
|
||||
-- @field #boolean sideWithTarget Whether to help the target in combat (true or false).
|
||||
-- @field openmw.util#Vector3 destPosition Destination point of the AI package.
|
||||
-- @field #number distance Distance value (can be nil).
|
||||
-- @field #number duration Duration value (can be nil).
|
||||
-- @field #table idle Idle value (can be nil).
|
||||
-- @field #boolean isRepeat Should this package be repeated (true or false).
|
||||
|
||||
--- Return the currently active AI package (or `nil` if there are no AI packages).
|
||||
-- @function [parent=#AI] getActivePackage
|
||||
|
93
files/lang/components_en.ts
Normal file
@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en">
|
||||
<context>
|
||||
<name>ContentSelector</name>
|
||||
<message>
|
||||
<source>Select language used by ESM/ESP content files to allow OpenMW to detect their encoding. </source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ContentSelectorModel::ContentModel</name>
|
||||
<message>
|
||||
<source>Unable to find dependent file: %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Dependent file needs to be active: %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This file needs to load after %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ContentSelectorModel::EsmFile</name>
|
||||
<message>
|
||||
<source><br/><b>This content file cannot be disabled because it is part of OpenMW.</b><br/></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><b>Author:</b> %1<br/><b>Format version:</b> %2<br/><b>Modified:</b> %3<br/><b>Path:</b><br/>%4<br/><br/><b>Description:</b><br/>%5<br/><br/><b>Dependencies: </b>%6<br/></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ContentSelectorView::ContentSelector</name>
|
||||
<message>
|
||||
<source><No game file></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Check Selected</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Uncheck Selected</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Copy Path(s) to Clipboard</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Process::ProcessInvoker</name>
|
||||
<message>
|
||||
<source>Error starting executable</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not find %1</b></p><p>The application is not found.</p><p>Please make sure OpenMW is installed correctly and try again.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not start %1</b></p><p>The application is not executable.</p><p>Please make sure you have the right permissions and try again.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not start %1</b></p><p>An error occurred while starting %1.</p><p>Press "Show Details..." for more information.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error running executable</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Executable %1 returned an error</b></p><p>An error occurred while running %1.</p><p>Press "Show Details..." for more information.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>
|
||||
Arguments:
|
||||
</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
1475
files/lang/launcher_en.ts
Normal file
@ -1226,11 +1226,11 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>If enabled, a magical ammunition is required to bypass normal weapon resistance or weakness. If disabled, a magical ranged weapon or a magical ammunition is required.</p></body></html></source>
|
||||
<translation><html><head/><body><p>Если настройка включена, требуются магические метательные снаряды, чтобы обойти сопротивление обычному оружию или уязвимость к нему. Если отключена, то требуются магические снаряды или магическое оружие дальнего боя.</p></body></html></translation>
|
||||
<translation><html><head/><body><p>Если настройка включена, для обхода сопротивления или уязвимости к обычному оружию необходимо, чтобы снаряд был магическим. Если выключена, то магическим для этого может быть как снаряд, так и оружие дальнего боя.</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Only Magical Ammo Bypass Resistance</source>
|
||||
<translation>Только снаряды обходят сопротивление</translation>
|
||||
<translation>Обычные снаряды не обходят сопротивление</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Graphic Herbalism</source>
|
||||
|
656
files/lang/wizard_en.ts
Normal file
@ -0,0 +1,656 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en_EN">
|
||||
<context>
|
||||
<name>ComponentSelectionPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Components</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Which components should be installed?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>Select which official Morrowind expansions should be installed. For best results, it is recommended to have both expansions installed.</p><p><span style=" font-weight:bold;">Note:</span> It is possible to install expansions later by re-running this Wizard.<br/></p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Selected components:</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ConclusionPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Completing the OpenMW Wizard</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Placeholder</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ExistingInstallationPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Existing Installation</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select an existing installation for OpenMW to use or modify.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Detected installations:</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Browse...</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ImportPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import Settings</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import settings from the Morrowind installation.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>OpenMW needs to import settings from the Morrowind configuration file in order to function properly.</p><p><span style=" font-weight:bold;">Note:</span> It is possible to import settings later by re-running this Wizard.</p><p/></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import Settings From Morrowind.ini</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import Add-on and Plugin Selection</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import Bitmap Fonts Setup From Morrowind.ini</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fonts shipped with the original engine are blurry with UI scaling and support only a small amount of characters,
|
||||
so OpenMW provides another set of fonts to avoid these issues. These fonts use TrueType technology and are quite similar
|
||||
to default Morrowind fonts. Check this box if you still prefer original fonts over OpenMW ones or if you use custom bitmap fonts.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InstallationPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please wait while Morrowind is installed on your computer.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>InstallationTargetPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Installation Destination</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Where should Morrowind be installed?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind will be installed to the following location. </source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Browse...</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IntroPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Welcome to the OpenMW Wizard</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>This Wizard will help you install Morrowind and its add-ons for OpenMW to use.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LanguageSelectionPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Morrowind Language</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>What is the language of the Morrowind installation?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select the language of the Morrowind installation.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MethodSelectionPage</name>
|
||||
<message>
|
||||
<source>WizardPage</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Installation Method</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>Select how you would like to install <i>The Elder Scrolls III: Morrowind</i>.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Retail CD/DVD</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Install from a retail disc to a new location.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Existing Installation</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select an existing installation.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Don't have a copy?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Buy the game</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<source><br><b>Could not find Morrowind.ini</b><br><br>The Wizard needs to update settings in this file.<br><br>Press "Browse..." to specify the location manually.<br></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>B&rowse...</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select configuration file</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><b>Morrowind.bsa</b> is missing!<br>Make sure your Morrowind installation is complete.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Most recent Morrowind not detected</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><br><b>There may be a more recent version of Morrowind available.</b><br><br>Do you wish to continue anyway?<br></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select a valid %1 installation media.<br><b>Hint</b>: make sure that it contains at least one <b>.cab</b> file.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>There may be a more recent version of Morrowind available.<br><br>Do you wish to continue anyway?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::ComponentSelectionPage</name>
|
||||
<message>
|
||||
<source>&Install</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Skip</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind (installed)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tribunal (installed)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tribunal</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bloodmoon (installed)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bloodmoon</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>About to install Tribunal after Bloodmoon</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>You are about to install Tribunal</b></p><p>Bloodmoon is already installed on your computer.</p><p>However, it is recommended that you install Tribunal before Bloodmoon.</p><p>Would you like to re-install Bloodmoon?</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Re-install &Bloodmoon</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::ConclusionPage</name>
|
||||
<message>
|
||||
<source><html><head/><body><p>The OpenMW Wizard successfully installed Morrowind on your computer.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>The OpenMW Wizard successfully modified your existing Morrowind installation.</body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p>The OpenMW Wizard failed to install Morrowind on your computer.</p><p>Please report any bugs you might have encountered to our <a href="https://gitlab.com/OpenMW/openmw/issues">bug tracker</a>.<br/>Make sure to include the installation log.</p><br/></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::ExistingInstallationPage</name>
|
||||
<message>
|
||||
<source>No existing installations detected</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error detecting Morrowind configuration</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind configuration file (*.ini)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Morrowind.esm (located in Data Files)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind master file (Morrowind.esm)</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error detecting Morrowind files</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::InstallationPage</name>
|
||||
<message>
|
||||
<source><p>Attempting to install component %1.</p></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Attempting to install component %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 Installation</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select %1 installation media</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><p><br/><span style="color:red;"><b>Error: The installation was aborted by the user</b></span></p></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><p>Detected old version of component Morrowind.</p></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Detected old version of component Morrowind.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Morrowind Installation</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installation finished</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installation completed successfully!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installation failed!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><p><br/><span style="color:red;"><b>Error: %1</b></p></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><p><span style="color:red;"><b>%1</b></p></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error occurred</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>The Wizard has encountered an error</b></p><p>The error reported was:</p><p>%1</p><p>Press &quot;Show Details...&quot; for more information.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::InstallationTargetPage</name>
|
||||
<message>
|
||||
<source>Error creating destination</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not create the destination directory</b></p><p>Please make sure you have the right permissions and try again, or specify a different location.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Insufficient permissions</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not write to the destination directory</b></p><p>Please make sure you have the right permissions and try again, or specify a different location.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Destination not empty</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>The destination directory is not empty</b></p><p>An existing Morrowind installation is present in the specified location.</p><p>Please specify a different location, or go back and select the location as an existing installation.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select where to install Morrowind</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::LanguageSelectionPage</name>
|
||||
<message>
|
||||
<source>English</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>French</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>German</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Italian</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Polish</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Russian</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Spanish</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::MainWizard</name>
|
||||
<message>
|
||||
<source>OpenMW Wizard</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not open %1 for writing</b></p><p>Please make sure you have the right permissions and try again.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error opening Wizard log file</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not open %1 for reading</b></p><p>Please make sure you have the right permissions and try again.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error opening OpenMW configuration file</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quit Wizard</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Are you sure you want to exit the Wizard?</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error creating OpenMW configuration directory</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><html><head/><body><p><b>Could not create %1</b></p><p>Please make sure you have the right permissions and try again.</p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error writing OpenMW configuration file</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wizard::UnshieldWorker</name>
|
||||
<message>
|
||||
<source>Failed to open Morrowind configuration file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Opening %1 failed: %2.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to write Morrowind configuration file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Writing to %1 failed: %2.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing: %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing: %1 directory</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installation finished!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Component parameter is invalid!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An invalid component parameter was supplied.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to find a valid archive containing %1.bsa! Retrying.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installation media path not set!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The source path for %1 was not set.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot create temporary directory!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to create %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot move into temporary directory!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to move into %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Moving installation files</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not install directory!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing %1 to %2 failed.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not install translation file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to install *%1 files.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not install Morrowind data file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to install %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not install Morrowind configuration file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Installing: Sound directory</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not find Tribunal data file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to find %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not find Tribunal patch file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not find Bloodmoon data file!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Updating Morrowind configuration file</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 installation finished!</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Extracting: %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to open InstallShield Cabinet File.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Opening %1 failed.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to extract %1.</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Complete path: %1</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
@ -117,7 +117,7 @@
|
||||
xlink:href="#Main-3"
|
||||
id="linearGradient6786"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(3.7795276,0,0,3.7795276,-5.9999999,-6.9999999)"
|
||||
gradientTransform="matrix(0.95388135,0,0,1.0509393,2.6074109,-0.47696551)"
|
||||
x1="2.116667"
|
||||
y1="-3.7041662"
|
||||
x2="6.3499999"
|
||||
@ -137,8 +137,7 @@
|
||||
rx="2.8318619e-14" />
|
||||
<path
|
||||
id="path6782"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6786);fill-opacity:1;stroke:none;stroke-width:0.999999px;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 186.2207,24.220703 C 186.09149,24.184168 186,24.274642 186,24.46875 v 8.931641 c 0,0.331351 0.20639,0.426988 0.46094,0.214843 l 5.17968,-4.314453 c 0.19881,-0.165685 0.19881,-0.435875 0,-0.601562 l -5.28124,-4.398438 c -0.0497,-0.04142 -0.0956,-0.0679 -0.13868,-0.08008 z m 0.78321,1.916016 3.43164,2.865234 -3.43164,2.855469 z"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,1.8520833,1.8520833)" />
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6786);fill-opacity:1;stroke:none;stroke-width:0.26491px;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 51.120283,8.2042949 c -0.03261,-0.010163 -0.0557,0.014998 -0.0557,0.068972 v 2.4835411 c 0,0.09214 0.05209,0.118729 0.116333,0.05973 l 1.433536,-1.1996808 c 0.05017,-0.04607 0.05017,-0.1211999 0,-0.1672709 L 51.155284,8.2265564 c -0.01254,-0.011517 -0.02412,-0.01888 -0.035,-0.022267 z m 0.197668,0.5327694 0.992382,0.7967099 -0.992382,0.7939938 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
@ -117,7 +117,7 @@
|
||||
xlink:href="#Main-3"
|
||||
id="linearGradient6770"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.39687235)"
|
||||
gradientTransform="matrix(0.95393695,0,0,1.0509392,2.7307818,-0.47696343)"
|
||||
x1="2.116667"
|
||||
y1="-3.7041662"
|
||||
x2="6.3499999"
|
||||
@ -137,7 +137,7 @@
|
||||
rx="2.8318619e-14" />
|
||||
<path
|
||||
id="path6766"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6770);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"
|
||||
d="m 51.255265,8.2604776 c -0.03419,-0.00967 -0.05839,0.014271 -0.05839,0.065629 V 10.68927 c 0,0.08767 0.05461,0.112974 0.121957,0.05684 l 1.370457,-1.1415325 c 0.0526,-0.043838 0.0526,-0.1153253 0,-0.1591633 L 51.291958,8.2816649 c -0.01315,-0.010959 -0.02529,-0.017965 -0.03669,-0.021188 z m 0.207225,0.5069458 0.907954,0.7580932 -0.907954,0.7555094 z" />
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6770);fill-opacity:1;stroke:none;stroke-width:0.264917px;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 51.120363,8.204296 c -0.03261,-0.010162 -0.05578,0.014998 -0.05578,0.068972 v 2.483541 c 0,0.09214 0.05211,0.118729 0.116355,0.05973 L 52.61445,9.6168633 c 0.05018,-0.046071 0.05018,-0.1211999 0,-0.167271 L 51.15519,8.2265626 c -0.01254,-0.011517 -0.02395,-0.01888 -0.03483,-0.022267 z m 0.197626,0.5327692 0.992304,0.7967099 -0.983218,0.7939939 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
@ -117,7 +117,7 @@
|
||||
xlink:href="#Main-3"
|
||||
id="linearGradient6778"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.39694445)"
|
||||
gradientTransform="matrix(0.95389396,0,0,1.0509392,2.7330252,-0.47696299)"
|
||||
x1="2.116667"
|
||||
y1="-3.7041662"
|
||||
x2="6.3499999"
|
||||
@ -137,7 +137,7 @@
|
||||
rx="2.8318619e-14" />
|
||||
<path
|
||||
id="path6774"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6778);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"
|
||||
d="m 51.255337,8.2604776 c -0.03419,-0.00967 -0.05839,0.014271 -0.05839,0.065629 V 10.68927 c 0,0.08767 0.05461,0.112974 0.121957,0.05684 l 1.370457,-1.1415325 c 0.0526,-0.043838 0.0526,-0.1153253 0,-0.1591633 L 51.29203,8.2816649 c -0.01315,-0.010959 -0.02529,-0.017965 -0.03669,-0.021188 z m 0.207225,0.5069458 0.907954,0.7580932 -0.907954,0.7555094 z" />
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6778);fill-opacity:1;stroke:none;stroke-width:0.264912px;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 51.120353,8.2042965 c -0.03261,-0.010163 -0.05577,0.014998 -0.05577,0.068972 V 10.75681 c 0,0.09214 0.05211,0.118729 0.116349,0.05973 l 1.43352,-1.1996813 c 0.05017,-0.046071 0.05017,-0.1211999 0,-0.167271 L 51.155435,8.2265631 c -0.01254,-0.011517 -0.02421,-0.01888 -0.03509,-0.022267 z M 51.31696,8.7370657 52.310301,9.5337756 51.31696,10.32777 Z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
@ -117,7 +117,7 @@
|
||||
xlink:href="#Main-3"
|
||||
id="linearGradient6788"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(3.7795276,0,0,3.7795276,-5.9999999,-6.9999999)"
|
||||
gradientTransform="matrix(0.95388135,0,0,1.0509393,2.6074049,-0.4769654)"
|
||||
x1="2.116667"
|
||||
y1="-3.7041662"
|
||||
x2="6.3499999"
|
||||
@ -137,8 +137,7 @@
|
||||
rx="2.8318619e-14" />
|
||||
<path
|
||||
id="path6695"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6788);fill-opacity:1;stroke:none;stroke-width:0.999999px;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 186.2207,24.220703 C 186.09149,24.184168 186,24.274642 186,24.46875 v 8.931641 c 0,0.331351 0.20639,0.426988 0.46094,0.214843 l 5.17968,-4.314453 c 0.19881,-0.165685 0.19881,-0.435875 0,-0.601562 l -5.28124,-4.398438 c -0.0497,-0.04142 -0.0956,-0.0679 -0.13868,-0.08008 z m 0.78321,1.916016 3.43164,2.865234 -3.43164,2.855469 z"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,1.8520833,1.8520833)" />
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6788);fill-opacity:1;stroke:none;stroke-width:0.26491px;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 51.120277,8.2042951 c -0.03261,-0.010162 -0.0557,0.014998 -0.0557,0.068972 v 2.4835409 c 0,0.09214 0.05209,0.118729 0.116333,0.05974 l 1.433536,-1.1996855 c 0.05018,-0.04607 0.05018,-0.1211998 0,-0.167271 L 51.155278,8.2265617 c -0.01254,-0.011517 -0.02412,-0.01888 -0.035,-0.022267 z m 0.197668,0.5327694 0.992382,0.7967099 -0.992382,0.7939946 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
@ -59,6 +59,39 @@ uniform int PointLightCount;
|
||||
|
||||
#endif
|
||||
|
||||
float lcalcConstantAttenuation(int lightIndex)
|
||||
{
|
||||
#if @lightingMethodPerObjectUniform
|
||||
return @getLight[lightIndex][0].w;
|
||||
#elif @lightingMethodUBO
|
||||
return @getLight[lightIndex].attenuation.x;
|
||||
#else
|
||||
return @getLight[lightIndex].constantAttenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
float lcalcLinearAttenuation(int lightIndex)
|
||||
{
|
||||
#if @lightingMethodPerObjectUniform
|
||||
return @getLight[lightIndex][1].w;
|
||||
#elif @lightingMethodUBO
|
||||
return @getLight[lightIndex].attenuation.y;
|
||||
#else
|
||||
return @getLight[lightIndex].linearAttenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
float lcalcQuadraticAttenuation(int lightIndex)
|
||||
{
|
||||
#if @lightingMethodPerObjectUniform
|
||||
return @getLight[lightIndex][2].w;
|
||||
#elif @lightingMethodUBO
|
||||
return @getLight[lightIndex].attenuation.z;
|
||||
#else
|
||||
return @getLight[lightIndex].quadraticAttenuation;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !@lightingMethodFFP
|
||||
float lcalcRadius(int lightIndex)
|
||||
{
|
||||
@ -70,17 +103,16 @@ float lcalcRadius(int lightIndex)
|
||||
}
|
||||
#endif
|
||||
|
||||
float lcalcIllumination(int lightIndex, float lightDistance)
|
||||
float lcalcIllumination(int lightIndex, float dist)
|
||||
{
|
||||
#if @lightingMethodPerObjectUniform
|
||||
float illumination = clamp(1.0 / (@getLight[lightIndex][0].w + @getLight[lightIndex][1].w * lightDistance + @getLight[lightIndex][2].w * lightDistance * lightDistance), 0.0, 1.0);
|
||||
return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0)));
|
||||
#elif @lightingMethodUBO
|
||||
float illumination = clamp(1.0 / (@getLight[lightIndex].attenuation.x + @getLight[lightIndex].attenuation.y * lightDistance + @getLight[lightIndex].attenuation.z * lightDistance * lightDistance), 0.0, 1.0);
|
||||
return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0)));
|
||||
#else
|
||||
return clamp(1.0 / (@getLight[lightIndex].constantAttenuation + @getLight[lightIndex].linearAttenuation * lightDistance + @getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0);
|
||||
float illumination = 1.0 / (lcalcConstantAttenuation(lightIndex) + lcalcLinearAttenuation(lightIndex) * dist + lcalcQuadraticAttenuation(lightIndex) * dist * dist);
|
||||
// FIXME: FFP doesn't do this
|
||||
illumination = clamp(illumination, 0.0, 1.0);
|
||||
#if @lightingMethodPerObjectUniform || @lightingMethodUBO
|
||||
// Fade illumination between the radius and the radius doubled to diminish pop-in
|
||||
illumination *= 1.0 - quickstep((dist / lcalcRadius(lightIndex)) - 1.0);
|
||||
#endif
|
||||
return illumination;
|
||||
}
|
||||
|
||||
vec3 lcalcPosition(int lightIndex)
|
||||
|