mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-12 17:13:07 +00:00
Merge branch 'master' of https://gitlab.com/enoznal/openmw
This commit is contained in:
commit
9380233ab7
14 changed files with 68 additions and 38 deletions
|
|
@ -11,8 +11,7 @@ brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd
|
|||
|
||||
command -v ccache >/dev/null 2>&1 || brew install ccache
|
||||
command -v cmake >/dev/null 2>&1 || brew install cmake
|
||||
command -v qmake >/dev/null 2>&1 || brew install qt@5
|
||||
export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"
|
||||
command -v qmake >/dev/null 2>&1 || brew install qt@6
|
||||
|
||||
# Install deps
|
||||
brew install openal-soft icu4c yaml-cpp sqlite
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ cd build
|
|||
|
||||
DEPENDENCIES_ROOT="/tmp/openmw-deps"
|
||||
|
||||
QT_PATH=$(brew --prefix qt@5)
|
||||
QT_PATH=$(brew --prefix qt@6)
|
||||
ICU_PATH=$(brew --prefix icu4c)
|
||||
OPENAL_PATH=$(brew --prefix openal-soft)
|
||||
CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache
|
||||
|
|
|
|||
|
|
@ -82,7 +82,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 75)
|
||||
set(OPENMW_LUA_API_REVISION 76)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 2)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <components/esm3/loadligh.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/util.hpp>
|
||||
#include <components/misc/color.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
|
|
@ -62,7 +63,13 @@ namespace
|
|||
if (rec["radius"] != sol::nil)
|
||||
light.mData.mRadius = rec["radius"];
|
||||
if (rec["color"] != sol::nil)
|
||||
light.mData.mColor = rec["color"];
|
||||
{
|
||||
sol::object color = rec["color"];
|
||||
if (color.is<Misc::Color>())
|
||||
light.mData.mColor = color.as<Misc::Color>().toRGBA();
|
||||
else
|
||||
light.mData.mColor = color.as<uint32_t>();
|
||||
}
|
||||
setRecordFlag(rec, "isCarriable", ESM::Light::Carry, light);
|
||||
setRecordFlag(rec, "isDynamic", ESM::Light::Dynamic, light);
|
||||
setRecordFlag(rec, "isFire", ESM::Light::Fire, light);
|
||||
|
|
@ -104,7 +111,8 @@ namespace MWLua
|
|||
record["value"] = sol::readonly_property([](const ESM::Light& rec) -> int { return rec.mData.mValue; });
|
||||
record["duration"] = sol::readonly_property([](const ESM::Light& rec) -> int { return rec.mData.mTime; });
|
||||
record["radius"] = sol::readonly_property([](const ESM::Light& rec) -> int { return rec.mData.mRadius; });
|
||||
record["color"] = sol::readonly_property([](const ESM::Light& rec) -> int { return rec.mData.mColor; });
|
||||
record["color"] = sol::readonly_property(
|
||||
[](const ESM::Light& rec) -> Misc::Color { return Misc::Color::fromRGB(rec.mData.mColor); });
|
||||
record["isCarriable"] = sol::readonly_property(
|
||||
[](const ESM::Light& rec) -> bool { return rec.mData.mFlags & ESM::Light::Carry; });
|
||||
record["isDynamic"] = sol::readonly_property(
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex& index
|
|||
{
|
||||
if (depFile->isGameFile() && file->gameFiles().contains(depFile->fileName(), Qt::CaseInsensitive))
|
||||
{
|
||||
if (!depFile->builtIn() && !depFile->fromAnotherConfigFile() && !mCheckedFiles.contains(depFile))
|
||||
if (!isChecked(depFile))
|
||||
break;
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled;
|
||||
|
|
@ -215,8 +215,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
|
|||
if (file == mGameFile)
|
||||
return QVariant();
|
||||
|
||||
return (file->builtIn() || file->fromAnotherConfigFile() || mCheckedFiles.contains(file)) ? Qt::Checked
|
||||
: Qt::Unchecked;
|
||||
return isChecked(file) ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
|
||||
case Qt::UserRole:
|
||||
|
|
@ -230,7 +229,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
|
|||
}
|
||||
|
||||
case Qt::UserRole + 1:
|
||||
return mCheckedFiles.contains(file);
|
||||
return isChecked(file);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -264,9 +263,9 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const
|
|||
{
|
||||
int checkValue = value.toInt();
|
||||
if (checkValue == Qt::Checked)
|
||||
return mCheckedFiles.contains(file) || setCheckState(file, true);
|
||||
return isChecked(file) || setCheckState(file, true);
|
||||
if (checkValue == Qt::Unchecked)
|
||||
return !mCheckedFiles.contains(file) || setCheckState(file, false);
|
||||
return !isChecked(file) || setCheckState(file, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -606,6 +605,14 @@ void ContentSelectorModel::ContentModel::sortFiles()
|
|||
emit layoutChanged();
|
||||
}
|
||||
|
||||
bool ContentSelectorModel::ContentModel::isChecked(const EsmFile* file) const
|
||||
{
|
||||
if (file == nullptr)
|
||||
return false;
|
||||
|
||||
return file->builtIn() || file->fromAnotherConfigFile() || mCheckedFiles.contains(file);
|
||||
}
|
||||
|
||||
bool ContentSelectorModel::ContentModel::isEnabled(const QModelIndex& index) const
|
||||
{
|
||||
return (flags(index) & Qt::ItemIsEnabled);
|
||||
|
|
@ -691,7 +698,7 @@ QList<ContentSelectorModel::LoadOrderError> ContentSelectorModel::ContentModel::
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!mCheckedFiles.contains(dependentFile))
|
||||
if (!isChecked(dependentFile))
|
||||
{
|
||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_InactiveDependency, dependentfileName));
|
||||
}
|
||||
|
|
@ -706,7 +713,7 @@ QList<ContentSelectorModel::LoadOrderError> ContentSelectorModel::ContentModel::
|
|||
{
|
||||
// Warn the user if Bloodmoon is loaded before Tribunal (Tribunal is not a hard dependency)
|
||||
const EsmFile* tribunalFile = item("Tribunal.esm");
|
||||
if (tribunalFile != nullptr && mCheckedFiles.contains(tribunalFile) && row < indexFromItem(tribunalFile).row())
|
||||
if (isChecked(tribunalFile) && row < indexFromItem(tribunalFile).row())
|
||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_LoadOrder, "Tribunal.esm"));
|
||||
}
|
||||
|
||||
|
|
@ -770,8 +777,9 @@ bool ContentSelectorModel::ContentModel::setCheckState(const EsmFile* file, bool
|
|||
for (const QString& upstreamName : file->gameFiles())
|
||||
{
|
||||
const EsmFile* upstreamFile = item(upstreamName);
|
||||
if (upstreamFile == nullptr || !mCheckedFiles.insert(upstreamFile).second)
|
||||
if (upstreamFile == nullptr || isChecked(upstreamFile))
|
||||
continue;
|
||||
mCheckedFiles.insert(upstreamFile);
|
||||
QModelIndex upstreamIndex = indexFromItem(upstreamFile);
|
||||
emit dataChanged(upstreamIndex, upstreamIndex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ namespace ContentSelectorModel
|
|||
QStringList gameFiles() const;
|
||||
void setCurrentGameFile(const EsmFile* file);
|
||||
|
||||
bool isChecked(const EsmFile* file) const;
|
||||
bool isEnabled(const QModelIndex& index) const;
|
||||
bool setCheckState(const EsmFile* file, bool isChecked);
|
||||
bool isNew(const QString& filepath) const;
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ void ContentSelectorView::ContentSelector::setGameFile(const QString& filename)
|
|||
index = ui->gameFileView->findText(file->fileName());
|
||||
|
||||
// verify that the current index is also checked in the model
|
||||
if (!mContentModel->setCheckState(file, true))
|
||||
if (!mContentModel->isChecked(file) && !mContentModel->setCheckState(file, true))
|
||||
{
|
||||
// throw error in case file not found?
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ namespace LuaUtil
|
|||
colorType["asRgba"] = [](const Misc::Color& c) { return Vec4(c.r(), c.g(), c.b(), c.a()); };
|
||||
colorType["asRgb"] = [](const Misc::Color& c) { return Vec3(c.r(), c.g(), c.b()); };
|
||||
colorType["asHex"] = [](const Misc::Color& c) { return c.toHex(); };
|
||||
colorType[sol::meta_function::equal_to] = [](const Misc::Color& a, const Misc::Color& b) { return a == b; };
|
||||
|
||||
sol::table color(lua, sol::create);
|
||||
color["rgba"] = [](float r, float g, float b, float a) { return Misc::Color(r, g, b, a); };
|
||||
|
|
|
|||
|
|
@ -6,13 +6,12 @@
|
|||
#include <sstream>
|
||||
#include <system_error>
|
||||
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
Color::Color(float r, float g, float b, float a)
|
||||
: mR(std::clamp(r, 0.f, 1.f))
|
||||
, mG(std::clamp(g, 0.f, 1.f))
|
||||
, mB(std::clamp(b, 0.f, 1.f))
|
||||
, mA(std::clamp(a, 0.f, 1.f))
|
||||
: mValue(std::clamp(r, 0.f, 1.f), std::clamp(g, 0.f, 1.f), std::clamp(b, 0.f, 1.f), std::clamp(a, 0.f, 1.f))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -27,26 +26,31 @@ namespace Misc
|
|||
{
|
||||
if (hex.size() != 6)
|
||||
throw std::logic_error(std::string("Invalid hex color: ") += hex);
|
||||
std::array<float, 3> rgb;
|
||||
for (size_t i = 0; i < rgb.size(); i++)
|
||||
Color col;
|
||||
col.mValue.a() = 1;
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
auto sub = hex.substr(i * 2, 2);
|
||||
int v = 0;
|
||||
auto [_, ec] = std::from_chars(sub.data(), sub.data() + sub.size(), v, 16);
|
||||
if (ec != std::errc())
|
||||
throw std::logic_error(std::string("Invalid hex color: ") += hex);
|
||||
rgb[i] = v / 255.0f;
|
||||
col.mValue[i] = v / 255.0f;
|
||||
}
|
||||
return Color(rgb[0], rgb[1], rgb[2], 1);
|
||||
return col;
|
||||
}
|
||||
|
||||
Color Color::fromRGB(unsigned int value)
|
||||
{
|
||||
return Color(SceneUtil::colourFromRGB(value));
|
||||
}
|
||||
|
||||
std::string Color::toHex() const
|
||||
{
|
||||
std::string result(6, '0');
|
||||
std::array<float, 3> rgb = { mR, mG, mB };
|
||||
for (size_t i = 0; i < rgb.size(); i++)
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
int b = static_cast<int>(rgb[i] * 255.0f);
|
||||
int b = static_cast<int>(mValue[i] * 255.0f);
|
||||
char* start = result.data() + i * 2;
|
||||
if (b < 16)
|
||||
start++;
|
||||
|
|
@ -59,6 +63,6 @@ namespace Misc
|
|||
|
||||
bool operator==(const Color& l, const Color& r)
|
||||
{
|
||||
return l.mR == r.mR && l.mG == r.mG && l.mB == r.mB && l.mA == r.mA;
|
||||
return l.mValue == r.mValue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,38 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <osg/Vec4>
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
class Color
|
||||
{
|
||||
explicit Color(osg::Vec4&& value)
|
||||
: mValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Color() = default;
|
||||
Color(float r, float g, float b, float a);
|
||||
|
||||
float r() const { return mR; }
|
||||
float g() const { return mG; }
|
||||
float b() const { return mB; }
|
||||
float a() const { return mA; }
|
||||
float r() const { return mValue.r(); }
|
||||
float g() const { return mValue.g(); }
|
||||
float b() const { return mValue.b(); }
|
||||
float a() const { return mValue.a(); }
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
static Color fromHex(std::string_view hex);
|
||||
static Color fromRGB(unsigned int value);
|
||||
|
||||
std::string toHex() const;
|
||||
unsigned int toRGBA() const { return mValue.asRGBA(); }
|
||||
|
||||
friend bool operator==(const Color& l, const Color& r);
|
||||
|
||||
private:
|
||||
float mR;
|
||||
float mG;
|
||||
float mB;
|
||||
float mA;
|
||||
osg::Vec4 mValue;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1673,7 +1673,7 @@
|
|||
-- @field #number value
|
||||
-- @field #number duration
|
||||
-- @field #number radius
|
||||
-- @field #number color
|
||||
-- @field openmw.util#Color color
|
||||
-- @field #boolean isCarriable True if the light can be carried by actors and appears up in their inventory.
|
||||
-- @field #boolean isDynamic If true, the light will apply to actors and other moving objects
|
||||
-- @field #boolean isFire True if the light acts like a fire.
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ TryExec=openmw-cs
|
|||
Exec=openmw-cs
|
||||
Icon=openmw-cs
|
||||
Categories=Game;RolePlaying;
|
||||
StartupWMClass=openmw-cs
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ TryExec=openmw-launcher
|
|||
Exec=openmw-launcher
|
||||
Icon=openmw
|
||||
Categories=Game;RolePlaying;
|
||||
StartupWMClass=openmw-launcher
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ testing.registerGlobalTest('record creation', function()
|
|||
value = 10,
|
||||
duration = 12,
|
||||
radius = 30,
|
||||
color = 5,
|
||||
color = util.color.hex('123456'),
|
||||
name = "TestLight",
|
||||
model = "meshes/marker_door.dae"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue