mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-10 22:05:06 +00:00
gfx-shader-param: Vastly improve parameter functionality
Allow for overriding type and size of an element, opening the path for `int#[]`, `float#[]`, `int#x#`, `float#x#`, `bool#x#`, `vector<type, #>` and `matrix<type, #, #>`. Also allows for specifying the exact type of texture instead of hoping the user gets it right, as well as samplers. Parameters are also now created if they are invisible, which means that the properties() function must not be called, but they must still be used like any other. This is due to a problem with default values not being applied all the time, and sometimes just vanishing. The code also now throws exceptions with reasonable text, which should be caught by the gfx::shader implementation and refuse a load of the effect. No other state should be modified at that point, so care must be taken that up until the moment the complete initialization is done no other state is modified.
This commit is contained in:
parent
eab3ae4fbc
commit
777556f4f6
2 changed files with 210 additions and 35 deletions
|
@ -16,9 +16,98 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
#include "gfx-shader-param.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include "gfx-shader-param-basic.hpp"
|
||||
|
||||
#define ANNO_ORDER "order"
|
||||
#define ANNO_VISIBILITY "visible"
|
||||
#define ANNO_NAME "name"
|
||||
#define ANNO_DESCRIPTION "description"
|
||||
#define ANNO_TYPE "type"
|
||||
#define ANNO_SIZE "size"
|
||||
|
||||
typedef gs::effect_parameter::type eptype;
|
||||
|
||||
gfx::shader::parameter_type gfx::shader::get_type_from_effect_type(gs::effect_parameter::type type)
|
||||
{
|
||||
switch (type) {
|
||||
case eptype::Boolean:
|
||||
return parameter_type::Boolean;
|
||||
case eptype::Integer:
|
||||
case eptype::Integer2:
|
||||
case eptype::Integer3:
|
||||
case eptype::Integer4:
|
||||
return parameter_type::Integer;
|
||||
case eptype::Float:
|
||||
case eptype::Float2:
|
||||
case eptype::Float3:
|
||||
case eptype::Float4:
|
||||
case eptype::Matrix:
|
||||
return parameter_type::Float;
|
||||
case eptype::String:
|
||||
return parameter_type::String;
|
||||
case eptype::Texture:
|
||||
return parameter_type::Texture;
|
||||
default:
|
||||
return parameter_type::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
size_t gfx::shader::get_length_from_effect_type(gs::effect_parameter::type type)
|
||||
{
|
||||
switch (type) {
|
||||
case eptype::Unknown:
|
||||
case eptype::Invalid:
|
||||
case eptype::String:
|
||||
return 0;
|
||||
case eptype::Boolean:
|
||||
case eptype::Float:
|
||||
case eptype::Integer:
|
||||
case eptype::Texture:
|
||||
return 1;
|
||||
case eptype::Float2:
|
||||
case eptype::Integer2:
|
||||
return 2;
|
||||
case eptype::Float3:
|
||||
case eptype::Integer3:
|
||||
return 3;
|
||||
case eptype::Float4:
|
||||
case eptype::Integer4:
|
||||
return 4;
|
||||
case eptype::Matrix:
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::shader::parameter_type gfx::shader::get_type_from_string(std::string v)
|
||||
{
|
||||
if ((v == "bool") || (v == "boolean")) {
|
||||
return parameter_type::Boolean;
|
||||
}
|
||||
if ((v == "float") || (v == "single")) {
|
||||
return parameter_type::Float;
|
||||
}
|
||||
if ((v == "int") || (v == "integer")) {
|
||||
return parameter_type::Integer;
|
||||
}
|
||||
if ((v == "text") || (v == "string")) {
|
||||
return parameter_type::String;
|
||||
}
|
||||
if ((v == "tex") || (v == "texture")) {
|
||||
return parameter_type::Texture;
|
||||
}
|
||||
if ((v == "sampler")) {
|
||||
return parameter_type::Sampler;
|
||||
}
|
||||
/* To decide on in the future:
|
||||
* - Double support?
|
||||
* - Half Support?
|
||||
* - Texture Arrays? (Likely not supported in libobs)
|
||||
*/
|
||||
throw std::invalid_argument("Invalid parameter type string.");
|
||||
}
|
||||
|
||||
gfx::shader::parameter::parameter(gs::effect_parameter param, std::string key_prefix)
|
||||
: _param(param), _order(0), _key(_param.get_name()), _name(_key), _description()
|
||||
{
|
||||
|
@ -28,17 +117,44 @@ gfx::shader::parameter::parameter(gs::effect_parameter param, std::string key_pr
|
|||
_name = (_key);
|
||||
}
|
||||
|
||||
if (auto anno = _param.get_annotation("order"); anno) {
|
||||
// Read Order
|
||||
if (auto anno = _param.get_annotation(ANNO_ORDER); anno) {
|
||||
_order = anno.get_default_int();
|
||||
}
|
||||
if (auto anno = _param.get_annotation("name"); anno) {
|
||||
if (std::string v = anno.get_default_string(); v.length() > 0)
|
||||
|
||||
// Read Name
|
||||
if (auto anno = _param.get_annotation(ANNO_NAME); anno) {
|
||||
if (std::string v = anno.get_default_string(); v.length() > 0) {
|
||||
_name = v;
|
||||
} else {
|
||||
throw std::out_of_range("'" ANNO_NAME "' annotation has zero length.");
|
||||
}
|
||||
}
|
||||
if (auto anno = _param.get_annotation("description"); anno) {
|
||||
if (std::string v = anno.get_default_string(); v.length() > 0)
|
||||
|
||||
// Read Description
|
||||
if (auto anno = _param.get_annotation(ANNO_DESCRIPTION); anno) {
|
||||
if (std::string v = anno.get_default_string(); v.length() > 0) {
|
||||
_description = v;
|
||||
} else {
|
||||
throw std::out_of_range("'" ANNO_DESCRIPTION "' annotation has zero length.");
|
||||
}
|
||||
}
|
||||
|
||||
// Read Type override.
|
||||
_type = get_type_from_effect_type(_param.get_type());
|
||||
if (auto anno = _param.get_annotation(ANNO_TYPE); anno) {
|
||||
// We have a type override.
|
||||
_type = get_type_from_string(anno.get_default_string());
|
||||
}
|
||||
|
||||
// Read Size override.
|
||||
_size = get_length_from_effect_type(_param.get_type());
|
||||
if (auto anno = _param.get_annotation(ANNO_SIZE); anno) {
|
||||
size_t ov = anno.get_default_int();
|
||||
if (ov > 0)
|
||||
_size = ov;
|
||||
}
|
||||
_size = std::clamp(_size, 1ull, 32ull);
|
||||
}
|
||||
|
||||
void gfx::shader::parameter::defaults(obs_data_t* settings) {}
|
||||
|
@ -49,11 +165,36 @@ void gfx::shader::parameter::update(obs_data_t* settings) {}
|
|||
|
||||
void gfx::shader::parameter::assign() {}
|
||||
|
||||
gs::effect_parameter gfx::shader::parameter::get_parameter()
|
||||
{
|
||||
return gs::effect_parameter();
|
||||
}
|
||||
|
||||
gfx::shader::parameter_type gfx::shader::parameter::get_type()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
size_t gfx::shader::parameter::get_size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
int32_t gfx::shader::parameter::get_order()
|
||||
{
|
||||
return _order;
|
||||
}
|
||||
|
||||
const std::string& gfx::shader::parameter::get_key()
|
||||
{
|
||||
return _key;
|
||||
}
|
||||
|
||||
bool gfx::shader::parameter::has_name()
|
||||
{
|
||||
return _name.length() > 0;
|
||||
}
|
||||
|
||||
const std::string& gfx::shader::parameter::get_name()
|
||||
{
|
||||
return _name;
|
||||
|
@ -72,36 +213,23 @@ const std::string& gfx::shader::parameter::get_description()
|
|||
std::shared_ptr<gfx::shader::parameter> gfx::shader::parameter::make_parameter(gs::effect_parameter param,
|
||||
std::string prefix)
|
||||
{
|
||||
if (!param)
|
||||
return nullptr;
|
||||
|
||||
// ToDo: Allow other parameters to specify hidden properties, as well as the shader itself, and the source/filter/transition.
|
||||
if (auto anno = param.get_annotation("visible"); anno != nullptr) {
|
||||
if (!anno.get_default_bool()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!param) {
|
||||
throw std::runtime_error("Bad call to make_parameter. This is a bug in the plugin.");
|
||||
}
|
||||
|
||||
typedef gs::effect_parameter::type eptype;
|
||||
switch (param.get_type()) {
|
||||
case eptype::Boolean: {
|
||||
auto el = std::make_shared<gfx::shader::bool_parameter>(param, prefix);
|
||||
return el;
|
||||
}
|
||||
case eptype::Integer:
|
||||
case eptype::Integer2:
|
||||
case eptype::Integer3:
|
||||
case eptype::Integer4: {
|
||||
auto el = std::make_shared<gfx::shader::int_parameter>(param, prefix);
|
||||
return el;
|
||||
}
|
||||
case eptype::Float:
|
||||
case eptype::Float2:
|
||||
case eptype::Float3:
|
||||
case eptype::Float4: {
|
||||
auto el = std::make_shared<gfx::shader::float_parameter>(param, prefix);
|
||||
return el;
|
||||
parameter_type real_type = get_type_from_effect_type(param.get_type());
|
||||
if (auto anno = param.get_annotation(ANNO_TYPE); anno) {
|
||||
// We have a type override.
|
||||
parameter_type real_type = get_type_from_string(param.get_default_string());
|
||||
}
|
||||
|
||||
switch (real_type) {
|
||||
case parameter_type::Boolean:
|
||||
return std::make_shared<gfx::shader::bool_parameter>(param, prefix);
|
||||
case parameter_type::Integer:
|
||||
return std::make_shared<gfx::shader::int_parameter>(param, prefix);
|
||||
case parameter_type::Float:
|
||||
return std::make_shared<gfx::shader::float_parameter>(param, prefix);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -34,19 +34,54 @@ extern "C" {
|
|||
|
||||
namespace gfx {
|
||||
namespace shader {
|
||||
enum class parameter_type {
|
||||
// Unknown type, could be anything.
|
||||
Unknown,
|
||||
// Boolean, either false or true.
|
||||
Boolean,
|
||||
// Single Floating Point
|
||||
Float,
|
||||
// 32-Bit Integer
|
||||
Integer,
|
||||
// UTF-8 Character based String.
|
||||
String,
|
||||
// Texture with dimensions stored in size (1 = Texture1D, 2 = Texture2D, 3 = Texture3D, 6 = TextureCube).
|
||||
Texture,
|
||||
// Sampler for Textures.
|
||||
Sampler
|
||||
};
|
||||
|
||||
parameter_type get_type_from_effect_type(gs::effect_parameter::type type);
|
||||
|
||||
size_t get_length_from_effect_type(gs::effect_parameter::type type);
|
||||
|
||||
parameter_type get_type_from_string(std::string v);
|
||||
|
||||
class parameter {
|
||||
protected:
|
||||
// Parameter used for all functionality.
|
||||
gs::effect_parameter _param;
|
||||
|
||||
int32_t _order;
|
||||
// Real type of the parameter (libobs gets it wrong often).
|
||||
parameter_type _type;
|
||||
|
||||
// Real size of the parameter (libobs gets it wrong often).
|
||||
size_t _size;
|
||||
|
||||
// Order of the parameter in a list/map.
|
||||
int32_t _order;
|
||||
|
||||
// Key for the parameter (group) in a list/map.
|
||||
std::string _key;
|
||||
|
||||
// Visibility, name and description.
|
||||
bool _visible;
|
||||
std::string _name;
|
||||
std::string _description;
|
||||
|
||||
protected:
|
||||
parameter(gs::effect_parameter param, std::string key_prefix);
|
||||
virtual ~parameter(){};
|
||||
|
||||
public:
|
||||
virtual void defaults(obs_data_t* settings);
|
||||
|
||||
virtual void properties(obs_properties_t* props, obs_data_t* settings);
|
||||
|
@ -56,8 +91,20 @@ namespace gfx {
|
|||
virtual void assign();
|
||||
|
||||
public:
|
||||
gs::effect_parameter get_parameter();
|
||||
|
||||
parameter_type get_type();
|
||||
|
||||
size_t get_size();
|
||||
|
||||
int32_t get_order();
|
||||
|
||||
const std::string& get_key();
|
||||
|
||||
bool is_visible();
|
||||
|
||||
bool has_name();
|
||||
|
||||
const std::string& get_name();
|
||||
|
||||
bool has_description();
|
||||
|
|
Loading…
Reference in a new issue