From db13c50ec5be0d4f75b65233e35b43c5e7b576d2 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 28 Sep 2018 11:55:55 +0200 Subject: [PATCH] gfx-effect-source: Add initial code for texture support --- data/locale/en-US.ini | 4 + source/gfx-effect-source.cpp | 312 ++++++++++++++++++++++++----------- source/gfx-effect-source.h | 119 ++++++------- 3 files changed, 280 insertions(+), 155 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index caf8431b..b3c5496b 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -10,6 +10,10 @@ CustomShader.Input.Text="Shader Content" CustomShader.Input.Text.Description="Text to load as a shader." CustomShader.Input.File="Shader File" CustomShader.Input.File.Description="File to load as a shader." +CustomShader.Texture.Type="Type" +CustomShader.Texture.Type.Description="What type of texture do you want to use?" +CustomShader.Texture.Type.File="File" +CustomShader.Texture.Type.Source="Source" # Filter - Blur Filter.Blur="Blur" diff --git a/source/gfx-effect-source.cpp b/source/gfx-effect-source.cpp index 9122ef05..9bfa5ffb 100644 --- a/source/gfx-effect-source.cpp +++ b/source/gfx-effect-source.cpp @@ -16,46 +16,84 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include "gfx-effect-source.h" -#include "strings.h" -#include #include +#include +#include "strings.h" -bool gfx::effect_source::property_type_modified(void*, obs_properties_t* props, obs_property_t*, obs_data_t* sett) { +bool gfx::effect_source::property_type_modified(void*, obs_properties_t* props, obs_property_t*, obs_data_t* sett) +{ switch ((InputTypes)obs_data_get_int(sett, D_TYPE)) { - default: - case InputTypes::Text: - obs_property_set_visible(obs_properties_get(props, D_INPUT_TEXT), true); - obs_property_set_visible(obs_properties_get(props, D_INPUT_FILE), false); - break; - case InputTypes::File: - obs_property_set_visible(obs_properties_get(props, D_INPUT_TEXT), false); - obs_property_set_visible(obs_properties_get(props, D_INPUT_FILE), true); - break; + default: + case InputTypes::Text: + obs_property_set_visible(obs_properties_get(props, D_INPUT_TEXT), true); + obs_property_set_visible(obs_properties_get(props, D_INPUT_FILE), false); + break; + case InputTypes::File: + obs_property_set_visible(obs_properties_get(props, D_INPUT_TEXT), false); + obs_property_set_visible(obs_properties_get(props, D_INPUT_FILE), true); + break; } return true; } -bool gfx::effect_source::property_input_modified(void* obj, obs_properties_t*, obs_property_t*, obs_data_t* sett) { +bool gfx::effect_source::property_input_modified(void* obj, obs_properties_t*, obs_property_t*, obs_data_t* sett) +{ const char* text = nullptr; const char* file = nullptr; switch ((InputTypes)obs_data_get_int(sett, D_TYPE)) { - default: - case InputTypes::Text: - text = obs_data_get_string(sett, D_INPUT_TEXT); - break; - case InputTypes::File: - file = obs_data_get_string(sett, D_INPUT_FILE); - break; + default: + case InputTypes::Text: + text = obs_data_get_string(sett, D_INPUT_TEXT); + break; + case InputTypes::File: + file = obs_data_get_string(sett, D_INPUT_FILE); + break; } return reinterpret_cast(obj)->test_for_updates(text, file); } -gfx::effect_source::effect_source(obs_data_t* data, obs_source_t* owner) { - m_source = owner; +void gfx::effect_source::fill_source_list(obs_property_t* prop) +{ + obs_enum_sources( + [](void* ptr, obs_source_t* src) { + obs_property_t* prop = (obs_property_t*)ptr; + const char* sname = obs_source_get_name(src); + obs_property_list_add_string(prop, sname, sname); + return true; + }, + prop); +} + +bool gfx::effect_source::property_texture_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop, + obs_data_t* sett) +{ + texture_parameter* tpm = reinterpret_cast(priv); + + int64_t v = obs_data_get_int(sett, obs_property_name(prop)); + if (v == 0) { // File + obs_property_set_visible(obs_properties_get(props, tpm->ui.names[1]), true); + obs_property_set_visible(obs_properties_get(props, tpm->ui.names[2]), false); + } else { // Source + obs_property_set_visible(obs_properties_get(props, tpm->ui.names[1]), false); + obs_property_set_visible(obs_properties_get(props, tpm->ui.names[2]), true); + } + + return true; +} + +bool gfx::effect_source::property_texture_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, + obs_data_t* sett) +{ + return false; +} + +gfx::effect_source::effect_source(obs_data_t* data, obs_source_t* owner) +{ + m_source = owner; m_timeExisting = 0; - m_timeActive = 0; + m_timeActive = 0; m_quadBuffer = std::make_shared(4); m_quadBuffer->set_uv_layers(1); @@ -74,11 +112,13 @@ gfx::effect_source::effect_source(obs_data_t* data, obs_source_t* owner) { m_quadBuffer->update(true); } -gfx::effect_source::~effect_source() { +gfx::effect_source::~effect_source() +{ m_quadBuffer = nullptr; } -void gfx::effect_source::get_properties(obs_properties_t* properties) { +void gfx::effect_source::get_properties(obs_properties_t* properties) +{ obs_property_t* p = nullptr; p = obs_properties_add_list(properties, D_TYPE, P_TRANSLATE(T_TYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); @@ -93,8 +133,9 @@ void gfx::effect_source::get_properties(obs_properties_t* properties) { { char* tmp_path = obs_module_file(m_defaultShaderPath.c_str()); - p = obs_properties_add_path(properties, D_INPUT_FILE, P_TRANSLATE(T_INPUT_FILE), OBS_PATH_FILE, - "Any (*.effect *.shader *.hlsl);;Effect (*.effect);;Shader (*.shader);;DirectX (*.hlsl)", tmp_path); + p = obs_properties_add_path( + properties, D_INPUT_FILE, P_TRANSLATE(T_INPUT_FILE), OBS_PATH_FILE, + "Any (*.effect *.shader *.hlsl);;Effect (*.effect);;Shader (*.shader);;DirectX (*.hlsl)", tmp_path); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(T_INPUT_FILE))); obs_property_set_modified_callback2(p, property_input_modified, this); bfree(tmp_path); @@ -104,29 +145,57 @@ void gfx::effect_source::get_properties(obs_properties_t* properties) { for (auto prm : m_parameters) { if (prm.first.second == gs::effect_parameter::type::Boolean) { obs_properties_add_bool(properties, prm.second->ui.names[0], prm.second->ui.descs[0]); - } else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) { + } else if (prm.first.second >= gs::effect_parameter::type::Integer + && prm.first.second <= gs::effect_parameter::type::Integer4) { size_t cnt = (size_t)prm.first.second - (size_t)gs::effect_parameter::type::Integer; for (size_t idx = 0; idx <= cnt; idx++) { - obs_properties_add_int(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], INT_MIN, INT_MAX, 1); + obs_properties_add_int(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], INT_MIN, + INT_MAX, 1); } - } else if (prm.first.second >= gs::effect_parameter::type::Float && prm.first.second <= gs::effect_parameter::type::Float4) { + } else if (prm.first.second >= gs::effect_parameter::type::Float + && prm.first.second <= gs::effect_parameter::type::Float4) { size_t cnt = (size_t)prm.first.second - (size_t)gs::effect_parameter::type::Float; for (size_t idx = 0; idx <= cnt; idx++) { - obs_properties_add_float(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], FLT_MIN, FLT_MAX, 0.01); + obs_properties_add_float(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], -FLT_MAX, + FLT_MAX, 0.01); } + } else if (prm.first.second == gs::effect_parameter::type::Texture) { + // Switch between File and Source Input + p = obs_properties_add_list(properties, prm.second->ui.names[0], prm.second->ui.descs[0], + obs_combo_type::OBS_COMBO_TYPE_LIST, obs_combo_format::OBS_COMBO_FORMAT_INT); + obs_property_set_long_description(p, P_TRANSLATE(P_DESC(T_TEXTURE_TYPE))); + obs_property_set_modified_callback2(p, property_texture_type_modified, prm.second.get()); + obs_property_list_add_int(p, P_TRANSLATE(T_TEXTURE_TYPE_FILE), 0); + obs_property_list_add_int(p, P_TRANSLATE(T_TEXTURE_TYPE_SOURCE), 1); + + // Texture Path + char* defaultPath = obs_module_file(""); + p = obs_properties_add_path(properties, prm.second->ui.names[1], prm.second->ui.descs[1], + obs_path_type::OBS_PATH_FILE, "Images (*.bmp *.jpeg *.jpg *.png *.tga *.tiff)", + defaultPath); + obs_property_set_modified_callback2(p, property_texture_input_modified, prm.second.get()); + bfree(defaultPath); + + // Source Name + p = obs_properties_add_list(properties, prm.second->ui.names[2], prm.second->ui.descs[2], + obs_combo_type::OBS_COMBO_TYPE_LIST, obs_combo_format::OBS_COMBO_FORMAT_STRING); + obs_property_set_modified_callback2(p, property_texture_input_modified, prm.second.get()); + fill_source_list(p); } } } -void gfx::effect_source::get_defaults(obs_data_t* data) { +void gfx::effect_source::get_defaults(obs_data_t* data) +{ obs_data_set_default_int(data, D_TYPE, (long long)InputTypes::Text); obs_data_set_default_string(data, D_INPUT_TEXT, ""); obs_data_set_default_string(data, D_INPUT_FILE, ""); } -void gfx::effect_source::update(obs_data_t* data) { +void gfx::effect_source::update(obs_data_t* data) +{ obs_data_addref(data); // Update Shader @@ -144,11 +213,12 @@ void gfx::effect_source::update(obs_data_t* data) { obs_data_release(data); } -bool gfx::effect_source::test_for_updates(const char* text, const char* path) { +bool gfx::effect_source::test_for_updates(const char* text, const char* path) +{ bool is_shader_different = false; if (text != nullptr) { if (text != m_shader.text) { - m_shader.text = text; + m_shader.text = text; is_shader_different = true; } @@ -161,12 +231,12 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { } } else if (path != nullptr) { if (path != this->m_shader.path) { - this->m_shader.path = path; - this->m_shader.file_info.time_updated = 0; - this->m_shader.file_info.time_create = 0; + this->m_shader.path = path; + this->m_shader.file_info.time_updated = 0; + this->m_shader.file_info.time_create = 0; this->m_shader.file_info.time_modified = 0; - this->m_shader.file_info.file_size = 0; - is_shader_different = true; + this->m_shader.file_info.file_size = 0; + is_shader_different = true; } // If the update timer is 0 or less, grab new file information. @@ -174,18 +244,16 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { struct stat stats; if (os_stat(m_shader.path.c_str(), &stats) == 0) { m_shader.file_info.modified = (m_shader.file_info.time_create != stats.st_ctime) - | (m_shader.file_info.time_modified != stats.st_mtime) - | (m_shader.file_info.file_size != stats.st_size); + | (m_shader.file_info.time_modified != stats.st_mtime) + | (m_shader.file_info.file_size != stats.st_size); // Mark shader as different if the file was changed. - is_shader_different = - is_shader_different - | m_shader.file_info.modified; + is_shader_different = is_shader_different | m_shader.file_info.modified; // Update own information - m_shader.file_info.time_create = stats.st_ctime; + m_shader.file_info.time_create = stats.st_ctime; m_shader.file_info.time_modified = stats.st_mtime; - m_shader.file_info.file_size = stats.st_size; + m_shader.file_info.file_size = stats.st_size; } // Increment timer so that the next check is a reasonable timespan away. @@ -195,7 +263,7 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { if (is_shader_different || m_shader.file_info.modified) { // gs_effect_create_from_file caches results, which is bad for us. std::vector content; - std::ifstream fs(m_shader.path.c_str(), std::ios::binary); + std::ifstream fs(m_shader.path.c_str(), std::ios::binary); if (fs.good()) { size_t beg = fs.tellg(); @@ -222,10 +290,10 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { // ToDo: Figure out if a recycling approach would work. // Might improve stability in low memory situations. std::map> new_params; - auto effect_param_list = m_shader.effect->get_parameters(); + auto effect_param_list = m_shader.effect->get_parameters(); for (auto effect_param : effect_param_list) { paramident_t ident; - ident.first = effect_param.get_name(); + ident.first = effect_param.get_name(); ident.second = effect_param.get_type(); if (is_special_parameter(ident.first, ident.second)) @@ -258,13 +326,14 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { nparam->ui.descs[0] = nparam->ui.buffer.data() + ui_name.size() + 1; param = std::dynamic_pointer_cast(nparam); - } else if (ident.second >= gs::effect_parameter::type::Integer && ident.second <= gs::effect_parameter::type::Integer4) { + } else if (ident.second >= gs::effect_parameter::type::Integer + && ident.second <= gs::effect_parameter::type::Integer4) { std::shared_ptr nparam = std::make_shared(); size_t cnt = (size_t)ident.second - (size_t)gs::effect_parameter::type::Integer; std::string ui_name[4], ui_desc[4]; - size_t bufsize = 0; + size_t bufsize = 0; if (cnt > 0) { for (size_t idx = 0; idx <= cnt; idx++) { ui_name[idx] = ident.first + (char)(48 + idx); @@ -297,13 +366,14 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { } param = std::dynamic_pointer_cast(nparam); - } else if (ident.second >= gs::effect_parameter::type::Float && ident.second <= gs::effect_parameter::type::Float4) { + } else if (ident.second >= gs::effect_parameter::type::Float + && ident.second <= gs::effect_parameter::type::Float4) { std::shared_ptr nparam = std::make_shared(); size_t cnt = (size_t)ident.second - (size_t)gs::effect_parameter::type::Float; std::string ui_name[4], ui_desc[4]; - size_t bufsize = 0; + size_t bufsize = 0; if (cnt > 0) { for (size_t idx = 0; idx <= cnt; idx++) { ui_name[idx] = ident.first + (char)(48 + idx); @@ -336,12 +406,44 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { } param = std::dynamic_pointer_cast(nparam); - } else { + } else if (ident.second == gs::effect_parameter::type::Texture) { + std::shared_ptr nparam = std::make_shared(); + std::string ui_name[3], ui_desc[3]; + size_t bufsize = 0; + + ui_name[0] = ident.first + "_type"; + ui_desc[0] = ident.first + " Type"; + ui_name[1] = ident.first + "_file"; + ui_desc[1] = ident.first + " File"; + ui_desc[2] = ident.first + "_source"; + ui_desc[2] = ident.first + " Source"; + + for (size_t i = 0; i <= 2; i++) { + bufsize += ui_name[i].size() + ui_desc[i].size() + 2; + } + + nparam->ui.names.resize(3); + nparam->ui.descs.resize(3); + + nparam->ui.buffer.resize(bufsize); + memset(nparam->ui.buffer.data(), 0, bufsize); + size_t off = 0; + for (size_t idx = 0; idx <= 2; idx++) { + memcpy(nparam->ui.buffer.data() + off, ui_name[idx].c_str(), ui_name[idx].size()); + nparam->ui.names[idx] = nparam->ui.buffer.data() + off; + off += ui_name[idx].size() + 1; + + memcpy(nparam->ui.buffer.data() + off, ui_desc[idx].c_str(), ui_desc[idx].size()); + nparam->ui.descs[idx] = nparam->ui.buffer.data() + off; + off += ui_desc[idx].size() + 1; + } + + param = std::dynamic_pointer_cast(nparam); } if (param) { - param->name = ident.first; + param->name = ident.first; param->param = std::make_shared(effect_param); new_params.insert_or_assign(ident, param); } @@ -356,17 +458,20 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) { return is_shader_different; } -void gfx::effect_source::update_parameters(obs_data_t* data) { +void gfx::effect_source::update_parameters(obs_data_t* data) +{ for (auto prm : m_parameters) { if (prm.first.second == gs::effect_parameter::type::Boolean) { - auto param = std::static_pointer_cast(prm.second); + auto param = std::static_pointer_cast(prm.second); param->value = obs_data_get_bool(data, prm.second->ui.names[0]); - } else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) { + } else if (prm.first.second >= gs::effect_parameter::type::Integer + && prm.first.second <= gs::effect_parameter::type::Integer4) { auto param = std::static_pointer_cast(prm.second); for (size_t idx = 0; idx < prm.second->ui.names.size(); idx++) { param->value[idx] = obs_data_get_int(data, prm.second->ui.names[idx]); } - } else if (prm.first.second >= gs::effect_parameter::type::Float && prm.first.second <= gs::effect_parameter::type::Float4) { + } else if (prm.first.second >= gs::effect_parameter::type::Float + && prm.first.second <= gs::effect_parameter::type::Float4) { auto param = std::static_pointer_cast(prm.second); for (size_t idx = 0; idx < prm.second->ui.names.size(); idx++) { param->value[idx] = obs_data_get_double(data, prm.second->ui.names[idx]); @@ -375,68 +480,77 @@ void gfx::effect_source::update_parameters(obs_data_t* data) { } } -void gfx::effect_source::apply_parameters() { +void gfx::effect_source::apply_parameters() +{ for (auto prm : m_parameters) { if (prm.first.second == gs::effect_parameter::type::Boolean) { auto param = std::static_pointer_cast(prm.second); param->param->set_bool(param->value); - } else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) { + } else if (prm.first.second >= gs::effect_parameter::type::Integer + && prm.first.second <= gs::effect_parameter::type::Integer4) { auto param = std::static_pointer_cast(prm.second); switch (prm.first.second) { - case gs::effect_parameter::type::Integer: - param->param->set_int(param->value[0]); - break; - case gs::effect_parameter::type::Integer2: - param->param->set_int2(param->value[0], param->value[1]); - break; - case gs::effect_parameter::type::Integer3: - param->param->set_int3(param->value[0], param->value[1], param->value[2]); - break; - case gs::effect_parameter::type::Integer4: - param->param->set_int4(param->value[0], param->value[1], param->value[2], param->value[3]); - break; + case gs::effect_parameter::type::Integer: + param->param->set_int(param->value[0]); + break; + case gs::effect_parameter::type::Integer2: + param->param->set_int2(param->value[0], param->value[1]); + break; + case gs::effect_parameter::type::Integer3: + param->param->set_int3(param->value[0], param->value[1], param->value[2]); + break; + case gs::effect_parameter::type::Integer4: + param->param->set_int4(param->value[0], param->value[1], param->value[2], param->value[3]); + break; } - } else if (prm.first.second >= gs::effect_parameter::type::Float && prm.first.second <= gs::effect_parameter::type::Float4) { + } else if (prm.first.second >= gs::effect_parameter::type::Float + && prm.first.second <= gs::effect_parameter::type::Float4) { auto param = std::static_pointer_cast(prm.second); switch (prm.first.second) { - case gs::effect_parameter::type::Float: - param->param->set_float(param->value[0]); - break; - case gs::effect_parameter::type::Float2: - param->param->set_float2(param->value[0], param->value[1]); - break; - case gs::effect_parameter::type::Float3: - param->param->set_float3(param->value[0], param->value[1], param->value[2]); - break; - case gs::effect_parameter::type::Float4: - param->param->set_float4(param->value[0], param->value[1], param->value[2], param->value[3]); - break; + case gs::effect_parameter::type::Float: + param->param->set_float(param->value[0]); + break; + case gs::effect_parameter::type::Float2: + param->param->set_float2(param->value[0], param->value[1]); + break; + case gs::effect_parameter::type::Float3: + param->param->set_float3(param->value[0], param->value[1], param->value[2]); + break; + case gs::effect_parameter::type::Float4: + param->param->set_float4(param->value[0], param->value[1], param->value[2], param->value[3]); + break; } } } } -void gfx::effect_source::activate() { +void gfx::effect_source::activate() +{ m_timeActive = 0; } -void gfx::effect_source::deactivate() { +void gfx::effect_source::deactivate() +{ m_timeActive = 0; } -std::string gfx::effect_source::get_shader_file() { +std::string gfx::effect_source::get_shader_file() +{ return m_shader.path; } -uint32_t gfx::effect_source::get_width() { +uint32_t gfx::effect_source::get_width() +{ return 0; } -uint32_t gfx::effect_source::get_height() { +uint32_t gfx::effect_source::get_height() +{ return 0; } -void gfx::effect_source::video_tick(float time) { +void gfx::effect_source::video_tick(float time) +{ // Shader Timers m_timeExisting += time; m_timeActive += time; @@ -447,21 +561,21 @@ void gfx::effect_source::video_tick(float time) { video_tick_impl(time); } -void gfx::effect_source::video_render(gs_effect_t* parent_effect) { +void gfx::effect_source::video_render(gs_effect_t* parent_effect) +{ if (!m_source) { obs_source_skip_video_filter(m_source); return; } - obs_source_t *parent = obs_filter_get_parent(m_source); - obs_source_t *target = obs_filter_get_target(m_source); + obs_source_t* parent = obs_filter_get_parent(m_source); + obs_source_t* target = obs_filter_get_target(m_source); if (!parent || !target || !m_shader.effect) { obs_source_skip_video_filter(m_source); return; } - uint32_t viewW = obs_source_get_base_width(target), - viewH = obs_source_get_base_height(target); + uint32_t viewW = obs_source_get_base_width(target), viewH = obs_source_get_base_height(target); if (!viewW || !viewH) { obs_source_skip_video_filter(m_source); return; @@ -475,7 +589,7 @@ void gfx::effect_source::video_render(gs_effect_t* parent_effect) { if (m_shader.effect->has_parameter("ViewSize", gs::effect_parameter::type::Float2)) { m_shader.effect->get_parameter("ViewSize").set_float2(float_t(viewW), float_t(viewH)); } - if (m_shader.effect->has_parameter("ViewSizeI"/*, gs::effect_parameter::type::Integer2*/)) { + if (m_shader.effect->has_parameter("ViewSizeI" /*, gs::effect_parameter::type::Integer2*/)) { m_shader.effect->get_parameter("ViewSizeI").set_int2(int32_t(viewW), int32_t(viewH)); } if (m_shader.effect->has_parameter("Time", gs::effect_parameter::type::Float)) { diff --git a/source/gfx-effect-source.h b/source/gfx-effect-source.h index efcc123d..20b56d52 100644 --- a/source/gfx-effect-source.h +++ b/source/gfx-effect-source.h @@ -16,39 +16,46 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #pragma once -#include -#include +#include #include +#include +#include +#include +#include "gfx-source-texture.h" #include "gs-effect.h" +#include "gs-mipmapper.h" #include "gs-rendertarget.h" #include "gs-texture.h" #include "gs-vertexbuffer.h" -#include "gfx-source-texture.h" -#include -#include -#include + +extern "C" { +#include +} // Data Defines -#define D_TYPE "CustomShader.Type" -#define D_INPUT_TEXT "CustomShader.Input.Text" -#define D_INPUT_FILE "CustomShader.Input.File" +#define D_TYPE "CustomShader.Type" +#define D_INPUT_TEXT "CustomShader.Input.Text" +#define D_INPUT_FILE "CustomShader.Input.File" // Translation Defines -#define T_TYPE "CustomShader.Type" -#define T_TYPE_TEXT "CustomShader.Type.Text" -#define T_TYPE_FILE "CustomShader.Type.File" -#define T_INPUT_TEXT "CustomShader.Input.Text" -#define T_INPUT_FILE "CustomShader.Input.File" +#define T_TYPE "CustomShader.Type" +#define T_TYPE_TEXT "CustomShader.Type.Text" +#define T_TYPE_FILE "CustomShader.Type.File" +#define T_INPUT_TEXT "CustomShader.Input.Text" +#define T_INPUT_FILE "CustomShader.Input.File" +#define T_TEXTURE_TYPE "CustomShader.Texture.Type" +#define T_TEXTURE_TYPE_FILE "CustomShader.Texture.Type.File" +#define T_TEXTURE_TYPE_SOURCE "CustomShader.Texture.Type.Source" namespace gfx { class effect_source { public: struct parameter { - std::string name = ""; + std::string name = ""; std::shared_ptr param; struct { - std::vector buffer; + std::vector buffer; std::vector names; std::vector descs; } ui; @@ -57,59 +64,57 @@ namespace gfx { bool value = false; }; struct int_parameter : parameter { - int32_t value[4] = { 0,0,0,0 }; + int32_t value[4] = {0, 0, 0, 0}; }; struct float_parameter : parameter { - float_t value[4] = { 0,0,0,0 }; + float_t value[4] = {0, 0, 0, 0}; }; struct texture_parameter : parameter { bool isSource = false; struct { - std::string path = ""; + std::string path = ""; std::shared_ptr tex; struct { - float_t time_updated = 0; - time_t time_create = 0; - time_t time_modified = 0; - size_t file_size = 0; - bool modified = true; + float_t time_updated = 0; + time_t time_create = 0; + time_t time_modified = 0; + size_t file_size = 0; + bool modified = true; } info; } file; struct { - std::string name = ""; + std::string name = ""; std::shared_ptr tex; + std::shared_ptr final_tex; + gs::mipmapper mipmapper; } source; struct { - bool doResample = false; - std::pair resolution = { 10, 10 }; + bool doResample = false; + std::pair resolution = {10, 10}; std::shared_ptr rt; } resample; }; - struct matrix_parameter : parameter { - - }; + struct matrix_parameter : parameter {}; typedef std::pair paramident_t; private: - - protected: - obs_source_t* m_source; + obs_source_t* m_source; std::shared_ptr m_quadBuffer; // Effect Information struct { std::shared_ptr effect; - std::string text; - std::string path; + std::string text; + std::string path; struct { float_t time_updated; - time_t time_create; - time_t time_modified; - size_t file_size; - bool modified; + time_t time_create; + time_t time_modified; + size_t file_size; + bool modified; } file_info; } m_shader; std::map> m_parameters; @@ -121,39 +126,41 @@ namespace gfx { std::string m_defaultShaderPath = "shaders/"; static bool property_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett); - static bool property_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett); - + static bool property_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, + obs_data_t* sett); + static void fill_source_list(obs_property_t* prop); + static bool property_texture_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop, + obs_data_t* sett); + static bool property_texture_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, + obs_data_t* sett); + virtual bool is_special_parameter(std::string name, gs::effect_parameter::type type) = 0; - virtual bool video_tick_impl(float_t time) = 0; + virtual bool video_tick_impl(float_t time) = 0; virtual bool video_render_impl(gs_effect_t* parent_effect, uint32_t viewW, uint32_t viewH) = 0; public: effect_source(obs_data_t* data, obs_source_t* owner); ~effect_source(); - void get_properties(obs_properties_t* properties); + void get_properties(obs_properties_t* properties); static void get_defaults(obs_data_t* data); - void update(obs_data_t* data); - bool test_for_updates(const char* text, const char* path); - void update_parameters(obs_data_t* data); - void apply_parameters(); + void update(obs_data_t* data); + bool test_for_updates(const char* text, const char* path); + void update_parameters(obs_data_t* data); + void apply_parameters(); void activate(); void deactivate(); - + std::string get_shader_file(); uint32_t get_width(); uint32_t get_height(); - void video_tick(float time); - void video_render(gs_effect_t* parent_effect); - + void video_tick(float time); + void video_render(gs_effect_t* parent_effect); public: - enum class InputTypes { - Text, - File - }; + enum class InputTypes { Text, File }; }; -} +} // namespace gfx