mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
Merge branch 'add_loop_and_vfx_id_to_world_vfx_spawn' into 'master'
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled
add loop + vfxId params to world.vfx.spawn and add world.vfx.remove See merge request OpenMW/openmw!4503
This commit is contained in:
commit
a5b8c4b736
10 changed files with 113 additions and 35 deletions
|
@ -516,9 +516,12 @@ namespace MWBase
|
|||
virtual void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
|
||||
|
||||
virtual void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
|
||||
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = true)
|
||||
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = true,
|
||||
std::string_view effectId = {}, bool loop = false)
|
||||
= 0;
|
||||
|
||||
virtual void removeEffect(std::string_view effectId) = 0;
|
||||
|
||||
/// @see MWWorld::WeatherManager::isInStorm
|
||||
virtual bool isInStorm() const = 0;
|
||||
|
||||
|
|
|
@ -312,28 +312,34 @@ namespace MWLua
|
|||
sol::table api(context.mLua->unsafeState(), sol::create);
|
||||
auto world = MWBase::Environment::get().getWorld();
|
||||
|
||||
api["spawn"]
|
||||
= [world, context](std::string_view model, const osg::Vec3f& worldPos, sol::optional<sol::table> options) {
|
||||
if (options)
|
||||
{
|
||||
bool magicVfx = options->get_or("mwMagicVfx", true);
|
||||
std::string texture = options->get_or<std::string>("particleTextureOverride", "");
|
||||
float scale = options->get_or("scale", 1.f);
|
||||
bool useAmbientLight = options->get_or("useAmbientLight", true);
|
||||
context.mLuaManager->addAction(
|
||||
[world, model = VFS::Path::Normalized(model), texture = std::move(texture), worldPos, scale,
|
||||
magicVfx, useAmbientLight]() {
|
||||
world->spawnEffect(model, texture, worldPos, scale, magicVfx, useAmbientLight);
|
||||
},
|
||||
"openmw.vfx.spawn");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.mLuaManager->addAction([world, model = VFS::Path::Normalized(model),
|
||||
worldPos]() { world->spawnEffect(model, "", worldPos, 1.f); },
|
||||
"openmw.vfx.spawn");
|
||||
}
|
||||
};
|
||||
api["remove"] = [world, context](std::string_view vfxId) {
|
||||
context.mLuaManager->addAction([world, vfxId = vfxId] { world->removeEffect(vfxId); }, "openmw.vfx.remove");
|
||||
};
|
||||
|
||||
api["spawn"] = [world, context](
|
||||
std::string_view model, const osg::Vec3f& worldPos, sol::optional<sol::table> options) {
|
||||
if (options)
|
||||
{
|
||||
bool magicVfx = options->get_or("mwMagicVfx", true);
|
||||
std::string texture = options->get_or<std::string>("particleTextureOverride", "");
|
||||
float scale = options->get_or("scale", 1.f);
|
||||
std::string_view vfxId = options->get_or<std::string_view>("vfxId", "");
|
||||
bool loop = options->get_or("loop", false);
|
||||
bool useAmbientLight = options->get_or("useAmbientLight", true);
|
||||
context.mLuaManager->addAction(
|
||||
[world, model = VFS::Path::Normalized(model), texture = std::move(texture), worldPos, scale,
|
||||
magicVfx, useAmbientLight, vfxId, loop]() {
|
||||
world->spawnEffect(model, texture, worldPos, scale, magicVfx, useAmbientLight, vfxId, loop);
|
||||
},
|
||||
"openmw.vfx.spawn");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.mLuaManager->addAction([world, model = VFS::Path::Normalized(model),
|
||||
worldPos]() { world->spawnEffect(model, "", worldPos, 1.f); },
|
||||
"openmw.vfx.spawn");
|
||||
}
|
||||
};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ namespace MWRender
|
|||
}
|
||||
|
||||
void EffectManager::addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride,
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight)
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight, std::string_view effectId,
|
||||
bool loop)
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(model);
|
||||
|
||||
|
@ -36,6 +37,8 @@ namespace MWRender
|
|||
|
||||
Effect effect;
|
||||
effect.mAnimTime = std::make_shared<EffectAnimationTime>();
|
||||
effect.loop = loop;
|
||||
effect.effectId = std::string(effectId);
|
||||
|
||||
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
||||
node->accept(findMaxLengthVisitor);
|
||||
|
@ -67,17 +70,47 @@ namespace MWRender
|
|||
|
||||
mResourceSystem->getSceneManager()->setUpNormalsRTForStateSet(node->getOrCreateStateSet(), false);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mEffectsMutex);
|
||||
mEffects.push_back(std::move(effect));
|
||||
}
|
||||
|
||||
void EffectManager::removeEffect(std::string_view effectId)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mEffectsMutex);
|
||||
mEffects.erase(std::remove_if(mEffects.begin(), mEffects.end(),
|
||||
[effectId, this](Effect& effect) {
|
||||
if (effectId.compare(effect.effectId) == 0)
|
||||
{
|
||||
mParentNode->removeChild(effect.mTransform);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}),
|
||||
mEffects.end());
|
||||
}
|
||||
|
||||
void EffectManager::update(float dt)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mEffectsMutex);
|
||||
mEffects.erase(std::remove_if(mEffects.begin(), mEffects.end(),
|
||||
[dt, this](Effect& effect) {
|
||||
bool remove = false;
|
||||
effect.mAnimTime->addTime(dt);
|
||||
const auto remove = effect.mAnimTime->getTime() >= effect.mMaxControllerLength;
|
||||
if (remove)
|
||||
mParentNode->removeChild(effect.mTransform);
|
||||
if (effect.mAnimTime->getTime() >= effect.mMaxControllerLength)
|
||||
{
|
||||
if (effect.loop)
|
||||
{
|
||||
float remainder = effect.mAnimTime->getTime() - effect.mMaxControllerLength;
|
||||
effect.mAnimTime->resetTime(remainder);
|
||||
}
|
||||
else
|
||||
{
|
||||
mParentNode->removeChild(effect.mTransform);
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
return remove;
|
||||
}),
|
||||
mEffects.end());
|
||||
|
@ -85,6 +118,7 @@ namespace MWRender
|
|||
|
||||
void EffectManager::clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mEffectsMutex);
|
||||
for (const auto& effect : mEffects)
|
||||
{
|
||||
mParentNode->removeChild(effect.mTransform);
|
||||
|
|
|
@ -35,7 +35,10 @@ namespace MWRender
|
|||
|
||||
/// Add an effect. When it's finished playing, it will be removed automatically.
|
||||
void addEffect(VFS::Path::NormalizedView model, std::string_view textureOverride,
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true, bool useAmbientLight = true);
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX = true, bool useAmbientLight = true,
|
||||
std::string_view effectId = {}, bool loop = false);
|
||||
|
||||
void removeEffect(std::string_view effectId);
|
||||
|
||||
void update(float dt);
|
||||
|
||||
|
@ -45,11 +48,14 @@ namespace MWRender
|
|||
private:
|
||||
struct Effect
|
||||
{
|
||||
std::string effectId;
|
||||
float mMaxControllerLength;
|
||||
bool loop;
|
||||
std::shared_ptr<EffectAnimationTime> mAnimTime;
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> mTransform;
|
||||
};
|
||||
|
||||
std::mutex mEffectsMutex;
|
||||
std::vector<Effect> mEffects;
|
||||
|
||||
osg::ref_ptr<osg::Group> mParentNode;
|
||||
|
|
|
@ -1253,9 +1253,15 @@ namespace MWRender
|
|||
}
|
||||
|
||||
void RenderingManager::spawnEffect(VFS::Path::NormalizedView model, std::string_view texture,
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight)
|
||||
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX, bool useAmbientLight, std::string_view effectId,
|
||||
bool loop)
|
||||
{
|
||||
mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX, useAmbientLight);
|
||||
mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX, useAmbientLight, effectId, loop);
|
||||
}
|
||||
|
||||
void RenderingManager::removeEffect(std::string_view effectId)
|
||||
{
|
||||
mEffectManager->removeEffect(effectId);
|
||||
}
|
||||
|
||||
void RenderingManager::notifyWorldSpaceChanged()
|
||||
|
|
|
@ -195,7 +195,10 @@ namespace MWRender
|
|||
SkyManager* getSkyManager();
|
||||
|
||||
void spawnEffect(VFS::Path::NormalizedView model, std::string_view texture, const osg::Vec3f& worldPosition,
|
||||
float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = true);
|
||||
float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = true, std::string_view effectId = {},
|
||||
bool loop = false);
|
||||
|
||||
void removeEffect(std::string_view effectId);
|
||||
|
||||
/// Clear all savegame-specific data
|
||||
void clear();
|
||||
|
|
|
@ -3689,9 +3689,15 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
void World::spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
|
||||
const osg::Vec3f& worldPos, float scale, bool isMagicVFX, bool useAmbientLight)
|
||||
const osg::Vec3f& worldPos, float scale, bool isMagicVFX, bool useAmbientLight, std::string_view effectId,
|
||||
bool loop)
|
||||
{
|
||||
mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX, useAmbientLight);
|
||||
mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX, useAmbientLight, effectId, loop);
|
||||
}
|
||||
|
||||
void World::removeEffect(std::string_view effectId)
|
||||
{
|
||||
mRendering->removeEffect(effectId);
|
||||
}
|
||||
|
||||
struct ResetActorsVisitor
|
||||
|
|
|
@ -604,8 +604,10 @@ namespace MWWorld
|
|||
void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) override;
|
||||
|
||||
void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride,
|
||||
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true,
|
||||
bool useAmbientLight = true) override;
|
||||
const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true, bool useAmbientLight = true,
|
||||
std::string_view effectId = {}, bool loop = false) override;
|
||||
|
||||
void removeEffect(std::string_view effectId) override;
|
||||
|
||||
/// @see MWWorld::WeatherManager::isInStorm
|
||||
bool isInStorm() const override;
|
||||
|
|
|
@ -7,5 +7,6 @@ return {
|
|||
SetGameTimeScale = function(scale) world.setGameTimeScale(scale) end,
|
||||
SetSimulationTimeScale = function(scale) world.setSimulationTimeScale(scale) end,
|
||||
SpawnVfx = function(data) world.vfx.spawn(data.model, data.position, data.options) end,
|
||||
RemoveVfx = function(vfxId) world.vfx.remove(vfxId) end,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -196,6 +196,8 @@
|
|||
-- * `particleTextureOverride` - Name of a particle texture that should override this effect's default texture. (default: "")
|
||||
-- * `scale` - A number that scales the size of the vfx (Default: 1)
|
||||
-- * `useAmbientLighting` - boolean, vfx get a white ambient light attached in Morrowind. If false don't attach this. (default: 1)
|
||||
-- * `loop` - boolean, if true the effect will loop until removed (default: 0).
|
||||
-- * `vfxId` - a string ID that can be used to remove the effect later, using #remove. (Default: "").
|
||||
--
|
||||
-- @usage -- Spawn a sanctuary effect near the player
|
||||
-- local effect = core.magic.effects.records[core.magic.EFFECT_TYPE.Sanctuary]
|
||||
|
@ -204,4 +206,13 @@
|
|||
-- core.sendGlobalEvent('SpawnVfx', {model = model, position = pos})
|
||||
--
|
||||
|
||||
---
|
||||
-- Remove a VFX with the given vfxId. Best invoked through the RemoveVfx global event
|
||||
-- @function [parent=#VFX] remove
|
||||
-- @param #string vfxId the vfxId of the vfx to remove.
|
||||
--
|
||||
-- @usage -- Remove the vfx with vfxId "myvfx"
|
||||
-- core.sendGlobalEvent('RemoveVfx', "myvfx")
|
||||
--
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue