diff --git a/3rdparty/avendish b/3rdparty/avendish index c616916c46..b6f124eba1 160000 --- a/3rdparty/avendish +++ b/3rdparty/avendish @@ -1 +1 @@ -Subproject commit c616916c46d3713084c91f536163048544ca7258 +Subproject commit b6f124eba1f8a537a8b0e31941fb8b400aa6df9b diff --git a/src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp b/src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp index 1f3228a268..fd05352278 100644 --- a/src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/CpuAnalysisNode.hpp @@ -15,6 +15,7 @@ struct GfxRenderer final : score::gfx::OutputNodeRenderer using texture_inputs = avnd::texture_input_introspection; const GfxNode& parent; Node_T state; + score::gfx::Message m_last_message{}; ossia::small_flat_map m_rts; @@ -76,10 +77,11 @@ struct GfxRenderer final : score::gfx::OutputNodeRenderer void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override { - if constexpr(requires { state.init(); }) + if constexpr(requires { state.prepare(); }) { - parent.processControlIn(state, this->parent.last_message); - state.init(); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); + state.prepare(); } // Init input render targets @@ -193,7 +195,8 @@ struct GfxRenderer final : score::gfx::OutputNodeRenderer }); } - parent.processControlIn(state, this->parent.last_message); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); // Run the processor state(); @@ -204,16 +207,18 @@ struct GfxRenderer final : score::gfx::OutputNodeRenderer }; template - requires( - avnd::texture_input_introspection::size > 0 - && avnd::texture_output_introspection::size == 0) -struct GfxNode final : CustomGpuOutputNodeBase + requires(avnd::texture_input_introspection::size > 0 + && avnd::texture_output_introspection::size == 0) +struct GfxNode final + : CustomGpuOutputNodeBase + , GpuNodeElements { oscr::ProcessModel& processModel; GfxNode( oscr::ProcessModel& element, - std::weak_ptr q, Gfx::exec_controls ctls, int id) - : CustomGpuOutputNodeBase{std::move(q), std::move(ctls)} + std::weak_ptr q, Gfx::exec_controls ctls, int id, + const score::DocumentContext& ctx) + : CustomGpuOutputNodeBase{std::move(q), std::move(ctls), ctx} , processModel{element} { this->instance = id; diff --git a/src/plugins/score-plugin-avnd/Crousti/CpuFilterNode.hpp b/src/plugins/score-plugin-avnd/Crousti/CpuFilterNode.hpp index 624345f888..7d7dd702a0 100644 --- a/src/plugins/score-plugin-avnd/Crousti/CpuFilterNode.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/CpuFilterNode.hpp @@ -16,6 +16,7 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer using texture_outputs = avnd::texture_output_introspection; const GfxNode& parent; Node_T state; + score::gfx::Message m_last_message{}; ossia::small_flat_map m_rts; @@ -154,9 +155,11 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override { - if constexpr(requires { state.init(); }) + if constexpr(requires { state.prepare(); }) { - state.init(); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); + state.prepare(); } const auto& mesh = renderer.defaultTriangle(); @@ -267,7 +270,8 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer }); } - parent.processControlIn(state, this->parent.last_message); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); // Run the processor state(); @@ -298,12 +302,15 @@ struct GfxNode final , GpuWorker , GpuControlIns , GpuControlOuts + , GpuNodeElements { oscr::ProcessModel& processModel; GfxNode( oscr::ProcessModel& element, - std::weak_ptr q, Gfx::exec_controls ctls, int id) - : GpuControlOuts{std::move(q), std::move(ctls)} + std::weak_ptr q, Gfx::exec_controls ctls, int id, + const score::DocumentContext& ctx) + : CustomGfxNodeBase{ctx} + , GpuControlOuts{std::move(q), std::move(ctls)} , processModel{element} { this->instance = id; diff --git a/src/plugins/score-plugin-avnd/Crousti/CpuGeneratorNode.hpp b/src/plugins/score-plugin-avnd/Crousti/CpuGeneratorNode.hpp index 2387ff2c6c..ac556faf23 100644 --- a/src/plugins/score-plugin-avnd/Crousti/CpuGeneratorNode.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/CpuGeneratorNode.hpp @@ -15,6 +15,7 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer using texture_outputs = avnd::texture_output_introspection; const GfxNode& parent; Node_T state; + score::gfx::Message m_last_message{}; ossia::time_value m_last_time{-1}; GfxRenderer(const GfxNode& p) @@ -118,9 +119,11 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override { - if constexpr(requires { state.init(); }) + if constexpr(requires { state.prepare(); }) { - state.init(); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); + state.prepare(); } const auto& mesh = renderer.defaultTriangle(); @@ -168,7 +171,8 @@ struct GfxRenderer final : score::gfx::GenericNodeRenderer } m_last_time = parent.last_message.token.date; - parent.processControlIn(state, this->parent.last_message); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, parent.m_ctx); // Run the processor state(); @@ -197,12 +201,15 @@ struct GfxNode final , GpuWorker , GpuControlIns , GpuControlOuts + , GpuNodeElements { oscr::ProcessModel& processModel; GfxNode( oscr::ProcessModel& element, - std::weak_ptr q, Gfx::exec_controls ctls, int id) - : GpuControlOuts{std::move(q), std::move(ctls)} + std::weak_ptr q, Gfx::exec_controls ctls, int id, + const score::DocumentContext& ctx) + : CustomGfxNodeBase{ctx} + , GpuControlOuts{std::move(q), std::move(ctls)} , processModel{element} { this->instance = id; diff --git a/src/plugins/score-plugin-avnd/Crousti/Executor.hpp b/src/plugins/score-plugin-avnd/Crousti/Executor.hpp index 4748ad8356..964a8cb68d 100644 --- a/src/plugins/score-plugin-avnd/Crousti/Executor.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/Executor.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -29,8 +30,6 @@ #include #endif -#include - #include #include @@ -45,104 +44,9 @@ #include #include #include -#include namespace oscr { -namespace -{ -[[nodiscard]] static QString -filenameFromPort(const ossia::value& value, const score::DocumentContext& ctx) -{ - if(auto str = value.target()) - return score::locateFilePath(QString::fromStdString(*str).trimmed(), ctx); - return {}; -} - -// TODO refactor this into a generic explicit soundfile loaded mechanism -[[nodiscard]] static auto -loadSoundfile(const ossia::value& value, const score::DocumentContext& ctx, double rate) -{ - // Initialize the control with the current soundfile - if(auto str = filenameFromPort(value, ctx); !str.isEmpty()) - { - auto dec = Media::AudioDecoder::decode_synchronous(str, rate); - - if(dec.has_value()) - { - auto hdl = std::make_shared(); - hdl->data = std::move(dec->second); - hdl->path = str.toStdString(); - hdl->rate = rate; - return hdl; - } - } - return ossia::audio_handle{}; -} - -using midifile_handle = std::shared_ptr; -[[nodiscard]] inline midifile_handle -loadMidifile(const ossia::value& value, const score::DocumentContext& ctx) -{ - // Initialize the control with the current soundfile - if(auto str = filenameFromPort(value, ctx); !str.isEmpty()) - { - QFile f(str); - if(!f.open(QIODevice::ReadOnly)) - return {}; - auto ptr = f.map(0, f.size()); - - auto hdl = std::make_shared(); - if(auto ret = hdl->reader.parse((uint8_t*)ptr, f.size()); - ret == libremidi::reader::invalid) - return {}; - - hdl->filename = str.toStdString(); - return hdl; - } - return {}; -} - -using raw_file_handle = std::shared_ptr; -[[nodiscard]] inline raw_file_handle loadRawfile( - const ossia::value& value, const score::DocumentContext& ctx, bool text, bool mmap) -{ - // Initialize the control with the current soundfile - if(auto filename = filenameFromPort(value, ctx); !filename.isEmpty()) - { - if(!QFile::exists(filename)) - return {}; - - auto hdl = std::make_shared(); - hdl->file.setFileName(filename); - if(!hdl->file.open(QIODevice::ReadOnly)) - return {}; - - if(mmap) - { - auto map = (char*)hdl->file.map(0, hdl->file.size()); - hdl->data = QByteArray::fromRawData(map, hdl->file.size()); - } - else - { - if(text) - hdl->file.setTextModeEnabled(true); - - hdl->data = hdl->file.readAll(); - } - hdl->filename = filename.toStdString(); - return hdl; - } - return {}; -} -[[nodiscard]] inline auto loadSoundfile( - const ossia::value& value, const score::DocumentContext& ctx, - const std::shared_ptr& st) -{ - const double rate = ossia::exec_state_facade{st.get()}.sampleRate(); - return loadSoundfile(value, ctx, rate); -} -} template struct control_updater @@ -378,16 +282,6 @@ struct setup_Impl0 } } - template - static auto executePortPreprocess(auto& file) - { - using field_file_type = decltype(Field::file); - field_file_type ffile; - ffile.bytes = decltype(ffile.bytes)(file.data.constData(), file.file.size()); - ffile.filename = file.filename; - return Field::process(ffile); - } - template void operator()(Field& param, avnd::predicate_index, avnd::field_index) { @@ -396,11 +290,8 @@ struct setup_Impl0 if(auto inlet = qobject_cast(p)) { // FIXME handle dynamic ports correctly - - using file_ports = avnd::raw_file_input_introspection; - using elt = typename file_ports::template nth_element; - static constexpr bool has_text = requires { decltype(elt::file)::text; }; - static constexpr bool has_mmap = requires { decltype(elt::file)::mmap; }; + static constexpr bool has_text = requires { decltype(Field::file)::text; }; + static constexpr bool has_mmap = requires { decltype(Field::file)::mmap; }; // First we can load it directly since execution hasn't started yet if(auto hdl = loadRawfile(inlet->value(), ctx.doc, has_text, has_mmap)) @@ -715,17 +606,20 @@ class Executor final std::unique_ptr ptr; if constexpr(GpuGraphicsNode2) { - auto gpu_node = new CustomGpuNode(qex_ptr, node->control_outs, id); + auto gpu_node + = new CustomGpuNode(qex_ptr, node->control_outs, id, ctx.doc); ptr.reset(gpu_node); } else if constexpr(GpuComputeNode2) { - auto gpu_node = new GpuComputeNode(qex_ptr, node->control_outs, id); + auto gpu_node + = new GpuComputeNode(qex_ptr, node->control_outs, id, ctx.doc); ptr.reset(gpu_node); } else if constexpr(GpuNode) { - auto gpu_node = new GfxNode(element, qex_ptr, node->control_outs, id); + auto gpu_node + = new GfxNode(element, qex_ptr, node->control_outs, id, ctx.doc); ptr.reset(gpu_node); } node->id = gfx_exec.ui->register_node(std::move(ptr)); diff --git a/src/plugins/score-plugin-avnd/Crousti/File.hpp b/src/plugins/score-plugin-avnd/Crousti/File.hpp new file mode 100644 index 0000000000..ca42f59dfc --- /dev/null +++ b/src/plugins/score-plugin-avnd/Crousti/File.hpp @@ -0,0 +1,126 @@ +#pragma once +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +namespace oscr +{ + +namespace +{ +[[nodiscard]] static QString +filenameFromPort(const ossia::value& value, const score::DocumentContext& ctx) +{ + if(auto str = value.target()) + return score::locateFilePath(QString::fromStdString(*str).trimmed(), ctx); + return {}; +} + +// TODO refactor this into a generic explicit soundfile loaded mechanism +[[nodiscard]] static auto +loadSoundfile(const ossia::value& value, const score::DocumentContext& ctx, double rate) +{ + // Initialize the control with the current soundfile + if(auto str = filenameFromPort(value, ctx); !str.isEmpty()) + { + auto dec = Media::AudioDecoder::decode_synchronous(str, rate); + + if(dec.has_value()) + { + auto hdl = std::make_shared(); + hdl->data = std::move(dec->second); + hdl->path = str.toStdString(); + hdl->rate = rate; + return hdl; + } + } + return ossia::audio_handle{}; +} + +using midifile_handle = std::shared_ptr; +[[nodiscard]] inline midifile_handle +loadMidifile(const ossia::value& value, const score::DocumentContext& ctx) +{ + // Initialize the control with the current soundfile + if(auto str = filenameFromPort(value, ctx); !str.isEmpty()) + { + QFile f(str); + if(!f.open(QIODevice::ReadOnly)) + return {}; + auto ptr = f.map(0, f.size()); + + auto hdl = std::make_shared(); + if(auto ret = hdl->reader.parse((uint8_t*)ptr, f.size()); + ret == libremidi::reader::invalid) + return {}; + + hdl->filename = str.toStdString(); + return hdl; + } + return {}; +} + +using raw_file_handle = std::shared_ptr; +[[nodiscard]] inline raw_file_handle loadRawfile( + const ossia::value& value, const score::DocumentContext& ctx, bool text, bool mmap) +{ + // Initialize the control with the current soundfile + if(auto filename = filenameFromPort(value, ctx); !filename.isEmpty()) + { + if(!QFile::exists(filename)) + return {}; + + auto hdl = std::make_shared(); + hdl->file.setFileName(filename); + if(!hdl->file.open(QIODevice::ReadOnly)) + return {}; + + if(mmap) + { + auto map = (char*)hdl->file.map(0, hdl->file.size()); + hdl->data = QByteArray::fromRawData(map, hdl->file.size()); + } + else + { + if(text) + hdl->file.setTextModeEnabled(true); + + hdl->data = hdl->file.readAll(); + } + hdl->filename = filename.toStdString(); + return hdl; + } + return {}; +} + +[[nodiscard]] inline auto loadSoundfile( + const ossia::value& value, const score::DocumentContext& ctx, + const std::shared_ptr& st) +{ + const double rate = ossia::exec_state_facade{st.get()}.sampleRate(); + return loadSoundfile(value, ctx, rate); +} + +template +static auto executePortPreprocess(auto& file) +{ + using field_file_type = decltype(Field::file); + field_file_type ffile; + ffile.bytes = decltype(ffile.bytes)(file.data.constData(), file.file.size()); + ffile.filename = file.filename; + return Field::process(ffile); +} + +} + +} diff --git a/src/plugins/score-plugin-avnd/Crousti/GpuComputeNode.hpp b/src/plugins/score-plugin-avnd/Crousti/GpuComputeNode.hpp index 8699b6f6b9..b5d6a67e35 100644 --- a/src/plugins/score-plugin-avnd/Crousti/GpuComputeNode.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/GpuComputeNode.hpp @@ -28,8 +28,9 @@ template struct GpuComputeNode final : ComputeNodeBaseType { GpuComputeNode( - std::weak_ptr q, Gfx::exec_controls ctls, int id) - : ComputeNodeBaseType{std::move(q), std::move(ctls)} + std::weak_ptr q, Gfx::exec_controls ctls, int id, + const score::DocumentContext& ctx) + : ComputeNodeBaseType{std::move(q), std::move(ctls), ctx} { this->instance = id; @@ -66,6 +67,7 @@ struct GpuComputeRenderer final : ComputeRendererBaseType using texture_outputs = avnd::gpu_image_output_introspection; const GpuComputeNode& parent; Node_T state; + score::gfx::Message m_last_message{}; ossia::small_flat_map m_rts; @@ -233,9 +235,11 @@ struct GpuComputeRenderer final : ComputeRendererBaseType void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override { - if constexpr(requires { state.init(); }) + if constexpr(requires { state.prepare(); }) { - state.init(); + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); + state.prepare(); } // Create the global shared inputs @@ -385,7 +389,9 @@ struct GpuComputeRenderer final : ComputeRendererBaseType // m_last_time = parent.last_message.token.date; // Apply the controls - parent.processControlIn(this->state, this->parent.last_message); + parent.processControlIn( + *this, this->state, m_last_message, this->parent.last_message, + this->parent.m_ctx); // Run the compute shader { diff --git a/src/plugins/score-plugin-avnd/Crousti/GpuNode.hpp b/src/plugins/score-plugin-avnd/Crousti/GpuNode.hpp index 5fc72db99d..751dc7443b 100644 --- a/src/plugins/score-plugin-avnd/Crousti/GpuNode.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/GpuNode.hpp @@ -20,6 +20,7 @@ struct CustomGpuRenderer final : score::gfx::NodeRenderer using texture_outputs = avnd::texture_output_introspection; const CustomGpuNodeBase& parent; std::vector states; + score::gfx::Message m_last_message{}; ossia::small_flat_map m_rts; @@ -189,10 +190,14 @@ struct CustomGpuRenderer final : score::gfx::NodeRenderer void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res) override { - if constexpr(requires { states[0].init(); }) + if constexpr(requires { states[0].prepare(); }) { for(auto& state : states) - state.init(); + { + parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); + state.prepare(); + } } if(!m_meshBuffer) @@ -368,7 +373,8 @@ struct CustomGpuRenderer final : score::gfx::NodeRenderer // Apply the controls for(auto& state : states) { - this->parent.processControlIn(state, this->parent.last_message); + this->parent.processControlIn( + *this, state, m_last_message, this->parent.last_message, this->parent.m_ctx); } } @@ -386,13 +392,15 @@ struct CustomGpuRenderer final : score::gfx::NodeRenderer } }; - template -struct CustomGpuNode final : CustomGpuNodeBase +struct CustomGpuNode final + : CustomGpuNodeBase + , GpuNodeElements { CustomGpuNode( - std::weak_ptr q, Gfx::exec_controls ctls, int id) - : CustomGpuNodeBase{std::move(q), std::move(ctls)} + std::weak_ptr q, Gfx::exec_controls ctls, int id, + const score::DocumentContext& ctx) + : CustomGpuNodeBase{std::move(q), std::move(ctls), ctx} { this->instance = id; diff --git a/src/plugins/score-plugin-avnd/Crousti/GpuUtils.cpp b/src/plugins/score-plugin-avnd/Crousti/GpuUtils.cpp index 2844f7812b..0c3c728783 100644 --- a/src/plugins/score-plugin-avnd/Crousti/GpuUtils.cpp +++ b/src/plugins/score-plugin-avnd/Crousti/GpuUtils.cpp @@ -37,8 +37,10 @@ CustomGfxNodeBase::~CustomGfxNodeBase() = default; CustomGfxOutputNodeBase::~CustomGfxOutputNodeBase() = default; CustomGpuOutputNodeBase::CustomGpuOutputNodeBase( - std::weak_ptr q, Gfx::exec_controls&& ctls) + std::weak_ptr q, Gfx::exec_controls&& ctls, + const score::DocumentContext& ctx) : GpuControlOuts{std::move(q), std::move(ctls)} + , m_ctx{ctx} { m_renderState = std::make_shared(); diff --git a/src/plugins/score-plugin-avnd/Crousti/GpuUtils.hpp b/src/plugins/score-plugin-avnd/Crousti/GpuUtils.hpp index 11a34e4abd..3e9e9b18de 100644 --- a/src/plugins/score-plugin-avnd/Crousti/GpuUtils.hpp +++ b/src/plugins/score-plugin-avnd/Crousti/GpuUtils.hpp @@ -3,6 +3,7 @@ #if SCORE_PLUGIN_GFX #include +#include #include #include #include @@ -10,10 +11,14 @@ #include #include +#include #include #include +#include #include +#include +#include #include #include @@ -847,24 +852,106 @@ struct GpuWorker } } }; -struct GpuControlIns + +template +struct GpuProcessIns { - template - static void processControlIn(Node_T& state, const score::gfx::Message& mess) noexcept + GpuNodeRenderer& gpu; + Node& state; + const score::gfx::Message& prev_mess; + const score::gfx::Message& mess; + const score::DocumentContext& ctx; + + bool can_process_message(std::size_t N) { - // Apply the controls - avnd::parameter_input_introspection::for_all_n2( - avnd::get_inputs(state), - [&](avnd::parameter auto& t, auto pred_index, auto field_index) { - if(mess.input.size() > field_index) + if(mess.input.size() <= N) + return false; + + if(prev_mess.input.size() == mess.input.size()) + { + auto& prev = prev_mess.input[N]; + auto& next = mess.input[N]; + if(prev.index() == 1 && next.index() == 1) { - if(auto val = ossia::get_if(&mess.input[field_index])) + if(ossia::get(prev) == ossia::get(next)) { - oscr::from_ossia_value(t, *val, t.value); - if_possible(t.update(state)); + return false; } } - }); + } + return true; + } + + void operator()(avnd::parameter auto& t, auto field_index) + { + if(!can_process_message(field_index)) + return; + + if(auto val = ossia::get_if(&mess.input[field_index])) + { + oscr::from_ossia_value(t, *val, t.value); + if_possible(t.update(state)); + } + } + +#if OSCR_HAS_MMAP_FILE_STORAGE + template + void operator()(Field& t, avnd::field_index field_index) + { + // FIXME we should be loading a file there + using node_type = std::remove_cvref_t; + using file_ports = avnd::raw_file_input_introspection; + + if(!can_process_message(field_index)) + return; + + auto val = ossia::get_if(&mess.input[field_index]); + if(!val) + return; + + static constexpr bool has_text = requires { decltype(Field::file)::text; }; + static constexpr bool has_mmap = requires { decltype(Field::file)::mmap; }; + + // First we can load it directly since execution hasn't started yet + if(auto hdl = loadRawfile(*val, ctx, has_text, has_mmap)) + { + static constexpr auto N = file_ports::field_index_to_index(NField); + if constexpr(avnd::port_can_process) + { + // FIXME also do it when we get a run-time message from the exec engine, + // OSC, etc + auto func = executePortPreprocess(*hdl); + const_cast(gpu.parent) + .file_loaded( + state, hdl, avnd::predicate_index{}, avnd::field_index{}); + if(func) + func(state); + } + else + { + const_cast(gpu.parent) + .file_loaded( + state, hdl, avnd::predicate_index{}, avnd::field_index{}); + } + } + } +#endif + + void operator()(auto& t, auto field_index) { } +}; + +struct GpuControlIns +{ + template + static void processControlIn( + Self& self, Node_T& state, score::gfx::Message& renderer_mess, + const score::gfx::Message& mess, const score::DocumentContext& ctx) noexcept + { + // Apply the controls + avnd::input_introspection::for_all_n( + avnd::get_inputs(state), + GpuProcessIns{self, state, renderer_mess, mess, ctx}); + renderer_mess = mess; } }; @@ -899,10 +986,36 @@ struct GpuControlOuts } }; +template +struct SCORE_PLUGIN_AVND_EXPORT GpuNodeElements +{ + [[no_unique_address]] oscr::soundfile_storage soundfiles; + + [[no_unique_address]] oscr::midifile_storage midifiles; + +#if defined(OSCR_HAS_MMAP_FILE_STORAGE) + [[no_unique_address]] oscr::raw_file_storage rawfiles; +#endif + + template + void file_loaded( + auto& state, const std::shared_ptr& hdl, + avnd::predicate_index, avnd::field_index) + { + this->rawfiles.load( + state, hdl, avnd::predicate_index{}, avnd::field_index{}); + } +}; + struct SCORE_PLUGIN_AVND_EXPORT CustomGfxNodeBase : score::gfx::NodeModel { + explicit CustomGfxNodeBase(const score::DocumentContext& ctx) + : score::gfx::NodeModel{} + , m_ctx{ctx} + { + } virtual ~CustomGfxNodeBase(); - + const score::DocumentContext& m_ctx; score::gfx::Message last_message; void process(score::gfx::Message&& msg) override; }; @@ -920,13 +1033,16 @@ struct CustomGpuNodeBase , GpuControlOuts { CustomGpuNodeBase( - std::weak_ptr&& q, Gfx::exec_controls&& ctls) + std::weak_ptr&& q, Gfx::exec_controls&& ctls, + const score::DocumentContext& ctx) : GpuControlOuts{std::move(q), std::move(ctls)} + , m_ctx{ctx} { } virtual ~CustomGpuNodeBase() = default; + const score::DocumentContext& m_ctx; QString vertex, fragment, compute; score::gfx::Message last_message; void process(score::gfx::Message&& msg) override; @@ -939,9 +1055,11 @@ struct SCORE_PLUGIN_AVND_EXPORT CustomGpuOutputNodeBase , GpuControlOuts { CustomGpuOutputNodeBase( - std::weak_ptr q, Gfx::exec_controls&& ctls); + std::weak_ptr q, Gfx::exec_controls&& ctls, + const score::DocumentContext& ctx); virtual ~CustomGpuOutputNodeBase(); + const score::DocumentContext& m_ctx; std::weak_ptr m_renderer{}; std::shared_ptr m_renderState{}; std::function m_update;