diff --git a/CMakeLists.txt b/CMakeLists.txt index e153fce677..0dd4f0ac27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 "") diff --git a/apps/openmw/mwlua/types/light.cpp b/apps/openmw/mwlua/types/light.cpp index 41a0bf8d4a..171db177a4 100644 --- a/apps/openmw/mwlua/types/light.cpp +++ b/apps/openmw/mwlua/types/light.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -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()) + light.mData.mColor = color.as().toRGBA(); + else + light.mData.mColor = color.as(); + } 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( diff --git a/components/misc/color.cpp b/components/misc/color.cpp index b6e7be1fa3..0652e6dbb7 100644 --- a/components/misc/color.cpp +++ b/components/misc/color.cpp @@ -6,13 +6,12 @@ #include #include +#include + 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 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 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(rgb[i] * 255.0f); + int b = static_cast(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; } } diff --git a/components/misc/color.hpp b/components/misc/color.hpp index f23448c98f..20a24a73ad 100644 --- a/components/misc/color.hpp +++ b/components/misc/color.hpp @@ -3,31 +3,38 @@ #include +#include + 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; }; } diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 0012a51c41..5aef5fac94 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -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.