mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 06:45:34 +00:00
Merge branch 'save_me_not' into 'master'
[Postprocessing] Fix a couple awkward issues with Lua API See merge request OpenMW/openmw!1946
This commit is contained in:
commit
7bc0d46896
9 changed files with 74 additions and 29 deletions
|
@ -30,7 +30,7 @@ namespace
|
|||
{
|
||||
auto technique = processor->getTechniques()[i];
|
||||
|
||||
if (!technique)
|
||||
if (!technique || technique->getDynamic())
|
||||
continue;
|
||||
|
||||
chain << technique->getName();
|
||||
|
@ -140,10 +140,15 @@ namespace MWGui
|
|||
{
|
||||
auto* processor = MWBase::Environment::get().getWorld()->getPostProcessor();
|
||||
mOverrideHint = list->getItemNameAt(selected);
|
||||
|
||||
auto technique = *list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected);
|
||||
if (technique->getDynamic())
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
processor->enableTechnique(*list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected));
|
||||
processor->enableTechnique(technique);
|
||||
else
|
||||
processor->disableTechnique(*list->getItemDataAt<std::shared_ptr<fx::Technique>>(selected));
|
||||
processor->disableTechnique(technique);
|
||||
saveChain();
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +177,11 @@ namespace MWGui
|
|||
|
||||
if (static_cast<size_t>(index) != selected)
|
||||
{
|
||||
if (processor->enableTechnique(*mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected), index))
|
||||
auto technique = *mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected);
|
||||
if (technique->getDynamic())
|
||||
return;
|
||||
|
||||
if (processor->enableTechnique(technique, index) != MWRender::PostProcessor::Status_Error)
|
||||
saveChain();
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +339,9 @@ namespace MWGui
|
|||
{
|
||||
case fx::Technique::Status::Success:
|
||||
case fx::Technique::Status::Uncompiled:
|
||||
{
|
||||
if (technique->getDynamic())
|
||||
ss << "#{fontcolourhtml=header}Locked: #{fontcolourhtml=normal} Cannot be toggled or moved, controlled by external Lua script" << endl << endl;
|
||||
ss << "#{fontcolourhtml=header}Author: #{fontcolourhtml=normal} " << author << endl << endl
|
||||
<< "#{fontcolourhtml=header}Version: #{fontcolourhtml=normal} " << version << endl << endl
|
||||
<< "#{fontcolourhtml=header}Description: #{fontcolourhtml=normal} " << description << endl << endl
|
||||
|
@ -338,6 +350,7 @@ namespace MWGui
|
|||
<< "#{fontcolourhtml=header} Underwater: #{fontcolourhtml=normal} " << flag_underwater
|
||||
<< "#{fontcolourhtml=header} Abovewater: #{fontcolourhtml=normal} " << flag_abovewater;
|
||||
break;
|
||||
}
|
||||
case fx::Technique::Status::Parse_Error:
|
||||
ss << "#{fontcolourhtml=negative}Shader Compile Error: #{fontcolourhtml=normal} <" << std::string(technique->getName()) << "> failed to compile." << endl << endl
|
||||
<< technique->getLastError();
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwrender/postprocessor.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
@ -271,6 +273,7 @@ namespace MWLua
|
|||
LuaUi::clearUserInterface();
|
||||
mUiResourceManager.clear();
|
||||
MWBase::Environment::get().getWindowManager()->setConsoleMode("");
|
||||
MWBase::Environment::get().getWorld()->getPostProcessor()->disableDynamicShaders();
|
||||
mActiveLocalScripts.clear();
|
||||
mLocalEvents.clear();
|
||||
mGlobalEvents.clear();
|
||||
|
|
|
@ -117,10 +117,9 @@ namespace MWLua
|
|||
[=, &shader] {
|
||||
shader.mQueuedAction = Shader::Action_None;
|
||||
|
||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos))
|
||||
if (MWBase::Environment::get().getWorld()->getPostProcessor()->enableTechnique(shader.mShader, pos) == MWRender::PostProcessor::Status_Error)
|
||||
throw std::runtime_error("Failed enabling shader '" + shader.mShader->getName() + "'");
|
||||
},
|
||||
"Enable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -132,10 +131,9 @@ namespace MWLua
|
|||
[&] {
|
||||
shader.mQueuedAction = Shader::Action_None;
|
||||
|
||||
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader))
|
||||
if (MWBase::Environment::get().getWorld()->getPostProcessor()->disableTechnique(shader.mShader) == MWRender::PostProcessor::Status_Error)
|
||||
throw std::runtime_error("Failed disabling shader '" + shader.mShader->getName() + "'");
|
||||
},
|
||||
"Disable shader " + (shader.mShader ? shader.mShader->getName() : "nil")
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -168,6 +166,9 @@ namespace MWLua
|
|||
if (!shader.mShader || !shader.mShader->isValid())
|
||||
throw std::runtime_error(Misc::StringUtils::format("Failed loading shader '%s'", name));
|
||||
|
||||
if (!shader.mShader->getDynamic())
|
||||
throw std::runtime_error(Misc::StringUtils::format("Shader '%s' is not marked as dynamic", name));
|
||||
|
||||
return shader;
|
||||
};
|
||||
|
||||
|
|
|
@ -182,7 +182,6 @@ namespace MWRender
|
|||
if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt)
|
||||
{
|
||||
auto absolutePath = std::filesystem::path(mVFS->getAbsoluteFileName(name));
|
||||
|
||||
mTechniqueFileMap[absolutePath.stem().string()] = absolutePath;
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +209,6 @@ namespace MWRender
|
|||
if (mUsePostProcessing && mTechniqueFileMap.empty())
|
||||
{
|
||||
populateTechniqueFiles();
|
||||
|
||||
}
|
||||
|
||||
mMainTemplate->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||
|
@ -648,16 +646,16 @@ namespace MWRender
|
|||
mRendering.getSkyManager()->setSunglare(sunglare);
|
||||
}
|
||||
|
||||
bool PostProcessor::enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location)
|
||||
PostProcessor::Status PostProcessor::enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
Log(Debug::Warning) << "PostProcessing disabled, cannot load technique '" << technique->getName() << "'";
|
||||
return false;
|
||||
return Status_Error;
|
||||
}
|
||||
|
||||
if (!technique || Misc::StringUtils::ciEqual(technique->getName(), "main") || (location.has_value() && location.value() <= 0))
|
||||
return false;
|
||||
return Status_Error;
|
||||
|
||||
disableTechnique(technique, false);
|
||||
|
||||
|
@ -666,23 +664,23 @@ namespace MWRender
|
|||
mTechniques.insert(mTechniques.begin() + pos, technique);
|
||||
dirtyTechniques();
|
||||
|
||||
return true;
|
||||
return Status_Toggled;
|
||||
}
|
||||
|
||||
bool PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty)
|
||||
PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(technique->getName(), "main"))
|
||||
return false;
|
||||
return Status_Error;
|
||||
|
||||
auto it = std::find(mTechniques.begin(), mTechniques.end(), technique);
|
||||
if (it == std::end(mTechniques))
|
||||
return false;
|
||||
return Status_Unchanged;
|
||||
|
||||
mTechniques.erase(it);
|
||||
if (dirty)
|
||||
dirtyTechniques();
|
||||
|
||||
return true;
|
||||
return Status_Toggled;
|
||||
}
|
||||
|
||||
bool PostProcessor::isTechniqueEnabled(const std::shared_ptr<fx::Technique>& technique) const
|
||||
|
@ -792,7 +790,7 @@ namespace MWRender
|
|||
if (technique->getStatus() != fx::Technique::Status::File_Not_exists)
|
||||
technique->setLastModificationTime(std::filesystem::last_write_time(mTechniqueFileMap[technique->getName()]));
|
||||
|
||||
if (!loadNextFrame)
|
||||
if (loadNextFrame)
|
||||
{
|
||||
mQueuedTemplates.push_back(technique);
|
||||
return technique;
|
||||
|
@ -853,5 +851,12 @@ namespace MWRender
|
|||
|
||||
dirtyTechniques();
|
||||
}
|
||||
|
||||
void PostProcessor::disableDynamicShaders()
|
||||
{
|
||||
for (auto& technique : mTechniques)
|
||||
if (technique->getDynamic())
|
||||
disableTechnique(technique);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,9 +110,16 @@ namespace MWRender
|
|||
|
||||
void resize();
|
||||
|
||||
bool enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location = std::nullopt);
|
||||
enum Status
|
||||
{
|
||||
Status_Error,
|
||||
Status_Toggled,
|
||||
Status_Unchanged
|
||||
};
|
||||
|
||||
bool disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty = true);
|
||||
Status enableTechnique(std::shared_ptr<fx::Technique> technique, std::optional<int> location = std::nullopt);
|
||||
|
||||
Status disableTechnique(std::shared_ptr<fx::Technique> technique, bool dirty = true);
|
||||
|
||||
bool getSupportsNormalsRT() const { return mNormalsSupported; }
|
||||
|
||||
|
@ -154,7 +161,7 @@ namespace MWRender
|
|||
|
||||
void toggleMode();
|
||||
|
||||
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=true);
|
||||
std::shared_ptr<fx::Technique> loadTechnique(const std::string& name, bool loadNextFrame=false);
|
||||
|
||||
bool isEnabled() const { return mUsePostProcessing && mEnabled; }
|
||||
|
||||
|
@ -168,6 +175,8 @@ namespace MWRender
|
|||
|
||||
void setRenderTargetSize(int width, int height) { mWidth = width; mHeight = height; }
|
||||
|
||||
void disableDynamicShaders();
|
||||
|
||||
private:
|
||||
|
||||
void populateTechniqueFiles();
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace fx
|
|||
mGLSLExtensions.clear();
|
||||
mGLSLVersion = mUBO ? 330 : 120;
|
||||
mGLSLProfile.clear();
|
||||
mDynamic = false;
|
||||
}
|
||||
|
||||
std::string Technique::getBlockWithLineDirective()
|
||||
|
@ -249,11 +250,13 @@ namespace fx
|
|||
for (const auto& ext : parseLiteralList<Lexer::Comma>())
|
||||
mGLSLExtensions.emplace(ext);
|
||||
}
|
||||
else if (key == "dynamic")
|
||||
mDynamic = parseBool();
|
||||
else
|
||||
error(Misc::StringUtils::format("unexpected key '%s'", std::string{key}));
|
||||
|
||||
expect<Lexer::SemiColon>();
|
||||
}
|
||||
}
|
||||
|
||||
if (mPassKeys.empty())
|
||||
error("pass list in 'technique' block cannot be empty.");
|
||||
|
|
|
@ -159,6 +159,8 @@ namespace fx
|
|||
|
||||
UniformMap::iterator findUniform(const std::string& name);
|
||||
|
||||
bool getDynamic() const { return mDynamic; }
|
||||
|
||||
private:
|
||||
[[noreturn]] void error(const std::string& msg);
|
||||
|
||||
|
@ -275,6 +277,8 @@ namespace fx
|
|||
std::string mBuffer;
|
||||
|
||||
std::string mLastError;
|
||||
|
||||
bool mDynamic = false;
|
||||
};
|
||||
|
||||
template<> void Technique::parseBlockImp<Lexer::Shared>();
|
||||
|
|
|
@ -5,8 +5,8 @@ Connecting With Lua
|
|||
Overview
|
||||
########
|
||||
|
||||
Every shader can be controlled through the Lua scripting system. While shaders can be disabled and enabled,
|
||||
shader uniforms can also be controlled. For details reference the API documentation, found :doc:`here<../lua-scripting/openmw_postprocessing>`.
|
||||
Every shader that is marked as ``dynamic`` can be controlled through the Lua scripting system. Shaders can be disabled and enabled,
|
||||
and their uniforms can be controlled via scripts. For details, reference the API documentation :doc:`here<../lua-scripting/openmw_postprocessing>`.
|
||||
|
||||
Toggling Shaders With a Keybind
|
||||
###############################
|
||||
|
@ -42,12 +42,14 @@ It is assumed the shader has the filename ``desaturate.omwfx`` in this example.
|
|||
|
||||
technique {
|
||||
description = "Desaturates scene";
|
||||
passes = desaturate;
|
||||
version = "1.0";
|
||||
author = "Fargoth";
|
||||
passes = desaturate;
|
||||
dynamic = true;
|
||||
}
|
||||
|
||||
.. note::
|
||||
The ``dynamic`` flag here is very important, otherwise Lua will not be able to interact with this shader.
|
||||
|
||||
Next, a script that is attached to the player is needed. The shader is loaded first, then toggled on and off in response to key presses.
|
||||
Below is a working example to illustrate this.
|
||||
|
@ -83,11 +85,11 @@ hidden in this HUD, this can done by adding the ``hidden`` flag to the main tech
|
|||
|
||||
technique {
|
||||
description = "Desaturates scene";
|
||||
passes = desaturate;
|
||||
version = "1.0";
|
||||
author = "Fargoth";
|
||||
passes = desaturate;
|
||||
flags = hidden;
|
||||
dynamic = true;
|
||||
}
|
||||
|
||||
This flag is usually used when the shader is associated with something special, like special weather, spell, or alcohol effects.
|
||||
|
|
|
@ -314,6 +314,11 @@ Exactly one ``technique`` block is required for every shader file. In this we de
|
|||
+------------------+--------------------+---------------------------------------------------+
|
||||
| flags | `SHADER_FLAG`_ | ``,`` separated list of shader flags |
|
||||
+------------------+--------------------+---------------------------------------------------+
|
||||
| dynamic | boolean | Whether shader is exposed to Lua |
|
||||
+------------------+--------------------+---------------------------------------------------+
|
||||
|
||||
When ``dynamic`` is set to ``true``, the shaders order cannot be manually moved, enabled, or disabled. The shaders state
|
||||
can only be controlled via a Lua script.
|
||||
|
||||
In the code snippet below, a shader is defined that requires GLSL `330`, HDR capatiblities, and is only enabled underwater in exteriors.
|
||||
|
||||
|
|
Loading…
Reference in a new issue