Skip to content

Commit

Permalink
Modify sound API permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
akortunov committed Mar 15, 2024
1 parent 5d669f0 commit 009ccca
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 60 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 57)
set(OPENMW_LUA_API_REVISION 58)
set(OPENMW_POSTPROCESSING_API_REVISION 1)

set(OPENMW_VERSION_COMMITHASH "")
Expand Down
104 changes: 67 additions & 37 deletions apps/openmw/mwlua/soundbindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <components/vfs/pathutil.hpp>

#include "luamanagerimp.hpp"
#include "objectvariant.hpp"

namespace
{
Expand All @@ -28,6 +29,27 @@ namespace
float mFade = 1.f;
};

MWWorld::Ptr getMutablePtrOrThrow(const MWLua::ObjectVariant& variant)
{
if (variant.isLObject())
throw std::runtime_error("Local scripts can only modify object they are attached to.");

MWWorld::Ptr ptr = variant.ptr();
if (ptr.isEmpty())
throw std::runtime_error("Invalid object");

return ptr;
}

MWWorld::Ptr getPtrOrThrow(const MWLua::ObjectVariant& variant)
{
MWWorld::Ptr ptr = variant.ptr();
if (ptr.isEmpty())
throw std::runtime_error("Invalid object");

return ptr;
}

PlaySoundArgs getPlaySoundArgs(const sol::optional<sol::table>& options)
{
PlaySoundArgs args;
Expand Down Expand Up @@ -121,6 +143,17 @@ namespace MWLua
sndMgr->streamMusic(std::string(fileName), MWSound::MusicType::Scripted, args.mFade);
};

api["say"]
= [luaManager = context.mLuaManager](std::string_view fileName, sol::optional<std::string_view> text) {
MWBase::Environment::get().getSoundManager()->say(VFS::Path::Normalized(fileName));
if (text)
luaManager->addUIMessage(*text);
};

api["stopSay"] = []() { MWBase::Environment::get().getSoundManager()->stopSay(MWWorld::ConstPtr()); };
api["isSayActive"]
= []() { return MWBase::Environment::get().getSoundManager()->sayActive(MWWorld::ConstPtr()); };

api["isMusicPlaying"] = []() { return MWBase::Environment::get().getSoundManager()->isMusicPlaying(); };

api["stopMusic"] = []() { MWBase::Environment::get().getSoundManager()->stopMusic(); };
Expand All @@ -137,64 +170,61 @@ namespace MWLua
api["isEnabled"] = []() { return MWBase::Environment::get().getSoundManager()->isEnabled(); };

api["playSound3d"]
= [](std::string_view soundId, const Object& object, const sol::optional<sol::table>& options) {
= [](std::string_view soundId, const sol::object& object, const sol::optional<sol::table>& options) {
auto args = getPlaySoundArgs(options);
auto playMode = getPlayMode(args, true);

ESM::RefId sound = ESM::RefId::deserializeText(soundId);
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));

MWBase::Environment::get().getSoundManager()->playSound3D(
object.ptr(), sound, args.mVolume, args.mPitch, MWSound::Type::Sfx, playMode, args.mTimeOffset);
ptr, sound, args.mVolume, args.mPitch, MWSound::Type::Sfx, playMode, args.mTimeOffset);
};
api["playSoundFile3d"]
= [](std::string_view fileName, const Object& object, const sol::optional<sol::table>& options) {
= [](std::string_view fileName, const sol::object& object, const sol::optional<sol::table>& options) {
auto args = getPlaySoundArgs(options);
auto playMode = getPlayMode(args, true);
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));

MWBase::Environment::get().getSoundManager()->playSound3D(object.ptr(), fileName, args.mVolume,
args.mPitch, MWSound::Type::Sfx, playMode, args.mTimeOffset);
MWBase::Environment::get().getSoundManager()->playSound3D(
ptr, fileName, args.mVolume, args.mPitch, MWSound::Type::Sfx, playMode, args.mTimeOffset);
};

api["stopSound3d"] = [](std::string_view soundId, const Object& object) {
api["stopSound3d"] = [](std::string_view soundId, const sol::object& object) {
ESM::RefId sound = ESM::RefId::deserializeText(soundId);
MWBase::Environment::get().getSoundManager()->stopSound3D(object.ptr(), sound);
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));
MWBase::Environment::get().getSoundManager()->stopSound3D(ptr, sound);
};
api["stopSoundFile3d"] = [](std::string_view fileName, const Object& object) {
MWBase::Environment::get().getSoundManager()->stopSound3D(object.ptr(), fileName);
api["stopSoundFile3d"] = [](std::string_view fileName, const sol::object& object) {
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));
MWBase::Environment::get().getSoundManager()->stopSound3D(ptr, fileName);
};

api["isSoundPlaying"] = [](std::string_view soundId, const Object& object) {
api["isSoundPlaying"] = [](std::string_view soundId, const sol::object& object) {
ESM::RefId sound = ESM::RefId::deserializeText(soundId);
return MWBase::Environment::get().getSoundManager()->getSoundPlaying(object.ptr(), sound);
const MWWorld::Ptr& ptr = getPtrOrThrow(ObjectVariant(object));
return MWBase::Environment::get().getSoundManager()->getSoundPlaying(ptr, sound);
};
api["isSoundFilePlaying"] = [](std::string_view fileName, const Object& object) {
return MWBase::Environment::get().getSoundManager()->getSoundPlaying(object.ptr(), fileName);
api["isSoundFilePlaying"] = [](std::string_view fileName, const sol::object& object) {
const MWWorld::Ptr& ptr = getPtrOrThrow(ObjectVariant(object));
return MWBase::Environment::get().getSoundManager()->getSoundPlaying(ptr, fileName);
};

api["say"] = sol::overload(
[luaManager = context.mLuaManager](
std::string_view fileName, const Object& object, sol::optional<std::string_view> text) {
MWBase::Environment::get().getSoundManager()->say(object.ptr(), VFS::Path::Normalized(fileName));
if (text)
luaManager->addUIMessage(*text);
},
[luaManager = context.mLuaManager](std::string_view fileName, sol::optional<std::string_view> text) {
MWBase::Environment::get().getSoundManager()->say(VFS::Path::Normalized(fileName));
if (text)
luaManager->addUIMessage(*text);
});
api["stopSay"] = sol::overload(
[](const Object& object) {
const MWWorld::Ptr& objPtr = object.ptr();
MWBase::Environment::get().getSoundManager()->stopSay(objPtr);
},
[]() { MWBase::Environment::get().getSoundManager()->stopSay(MWWorld::ConstPtr()); });
api["isSayActive"] = sol::overload(
[](const Object& object) {
const MWWorld::Ptr& objPtr = object.ptr();
return MWBase::Environment::get().getSoundManager()->sayActive(objPtr);
},
[]() { return MWBase::Environment::get().getSoundManager()->sayActive(MWWorld::ConstPtr()); });
api["say"] = [luaManager = context.mLuaManager](
std::string_view fileName, const sol::object& object, sol::optional<std::string_view> text) {
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));
MWBase::Environment::get().getSoundManager()->say(ptr, VFS::Path::Normalized(fileName));
if (text)
luaManager->addUIMessage(*text);
};
api["stopSay"] = [](const sol::object& object) {
MWWorld::Ptr ptr = getMutablePtrOrThrow(ObjectVariant(object));
MWBase::Environment::get().getSoundManager()->stopSay(ptr);
};
api["isSayActive"] = [](const sol::object& object) {
const MWWorld::Ptr& ptr = getPtrOrThrow(ObjectVariant(object));
return MWBase::Environment::get().getSoundManager()->sayActive(ptr);
};

using SoundStore = MWWorld::Store<ESM::Sound>;
sol::usertype<SoundStore> soundStoreT = lua.new_usertype<SoundStore>("ESM3_SoundStore");
Expand Down
22 changes: 22 additions & 0 deletions files/lua_api/openmw/ambient.lua
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,26 @@
-- @return #boolean
-- @usage local isPlaying = ambient.isMusicPlaying();

---
-- Play an ambient voiceover.
-- @function [parent=#ambient] say
-- @param #string fileName Path to sound file in VFS
-- @param #string text Subtitle text (optional)
-- @usage -- play voiceover and print messagebox
-- ambient.say("Sound\\Vo\\Misc\\voice.mp3", "Subtitle text")
-- @usage -- play voiceover, without messagebox
-- ambient.say("Sound\\Vo\\Misc\\voice.mp3")

---
-- Stop an ambient voiceover
-- @function [parent=#ambient] stopSay
-- @param #string fileName Path to sound file in VFS
-- @usage ambient.stopSay();

---
-- Check if an ambient voiceover is playing
-- @function [parent=#Sound] isSayActive
-- @return #boolean
-- @usage local isActive = isSayActive();

return nil
42 changes: 20 additions & 22 deletions files/lua_api/openmw/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,8 @@

---
-- Play a 3D sound, attached to object
--
-- In local scripts can be used only on self.
-- @function [parent=#Sound] playSound3d
-- @param #string soundId ID of Sound record to play
-- @param #GameObject object Object to which we attach the sound
Expand All @@ -733,6 +735,8 @@

---
-- Play a 3D sound file, attached to object
--
-- In local scripts can be used only on self.
-- @function [parent=#Sound] playSoundFile3d
-- @param #string fileName Path to sound file in VFS
-- @param #GameObject object Object to which we attach the sound
Expand All @@ -752,13 +756,17 @@

---
-- Stop a 3D sound, attached to object
--
-- In local scripts can be used only on self.
-- @function [parent=#Sound] stopSound3d
-- @param #string soundId ID of Sound record to stop
-- @param #GameObject object Object on which we want to stop sound
-- @usage core.sound.stopSound("shock bolt", object);

---
-- Stop a 3D sound file, attached to object
--
-- In local scripts can be used only on self.
-- @function [parent=#Sound] stopSoundFile3d
-- @param #string fileName Path to sound file in VFS
-- @param #GameObject object Object on which we want to stop sound
Expand All @@ -781,42 +789,32 @@
-- @usage local isPlaying = core.sound.isSoundFilePlaying("Sound\\test.mp3", object);

---
-- Play an animated voiceover. Has two overloads:
--
-- * With an "object" argument: play sound for given object, with speaking animation if possible
-- * Without an "object" argument: play sound globally, without object
-- Play an animated voiceover.
-- In local scripts can be used only on self.
-- @function [parent=#Sound] say
-- @param #string fileName Path to sound file in VFS
-- @param #GameObject object Object on which we want to play an animated voiceover (optional)
-- @param #GameObject object Object on which we want to play an animated voiceover
-- @param #string text Subtitle text (optional)
-- @usage -- play voiceover for object and print messagebox
-- core.sound.say("Sound\\Vo\\Misc\\voice.mp3", object, "Subtitle text")
-- @usage -- play voiceover globally and print messagebox
-- core.sound.say("Sound\\Vo\\Misc\\voice.mp3", "Subtitle text")
-- @usage -- play voiceover for object without messagebox
-- @usage -- play voiceover for object, without messagebox
-- core.sound.say("Sound\\Vo\\Misc\\voice.mp3", object)
-- @usage -- play voiceover globally without messagebox
-- core.sound.say("Sound\\Vo\\Misc\\voice.mp3")

---
-- Stop animated voiceover
-- Stop an animated voiceover
--
-- In local scripts can be used only on self.
-- @function [parent=#Sound] stopSay
-- @param #string fileName Path to sound file in VFS
-- @param #GameObject object Object on which we want to stop an animated voiceover (optional)
-- @usage -- stop voice for given object
-- core.sound.stopSay(object);
-- @usage -- stop global voice
-- core.sound.stopSay();
-- @param #GameObject object Object on which we want to stop an animated voiceover
-- @usage core.sound.stopSay(object);

---
-- Check if animated voiceover is playing
-- Check if an animated voiceover is playing
-- @function [parent=#Sound] isSayActive
-- @param #GameObject object Object on which we want to check an animated voiceover (optional)
-- @param #GameObject object Object on which we want to check an animated voiceover
-- @return #boolean
-- @usage -- check voice for given object
-- local isActive = isSayActive(object);
-- @usage -- check global voice
-- local isActive = isSayActive();
-- @usage local isActive = isSayActive(object);

---
-- @type SoundRecord
Expand Down

0 comments on commit 009ccca

Please sign in to comment.