Loading...
Searching...
No Matches
ScriptEditCommand.hpp
1#pragma once
2#include <Process/Dataflow/Port.hpp>
3#include <Process/Process.hpp>
4#include <Process/Script/ScriptEditor.hpp>
5#include <Process/Script/ScriptProcess.hpp>
6
7#include <Scenario/Document/ScenarioDocument/ScenarioDocumentModel.hpp>
8
9#include <Dataflow/Commands/CableHelpers.hpp>
10
11#include <ossia/detail/algorithms.hpp>
12namespace Scenario
13{
14using SavedPort = Dataflow::SavedPort;
15
16template <typename Process_T, typename Property_T>
18{
19public:
20 using param_type = typename Property_T::param_type;
21 using score::Command::Command;
23 const Process_T& model, param_type newScript, const score::DocumentContext& ctx)
24 : m_path{model}
25 , m_newScript{std::move(newScript)}
26 , m_oldScript{(model.*Property_T::get)()}
27 {
28 m_oldCables = Dataflow::saveCables({const_cast<Process_T*>(&model)}, ctx);
29
30 for(auto& port : model.inlets())
31 m_oldInlets.emplace_back(SavedPort{port->name(), port->type(), port->saveData()});
32 for(auto& port : model.outlets())
33 m_oldOutlets.emplace_back(SavedPort{port->name(), port->type(), port->saveData()});
34 }
35
36private:
37 void undo(const score::DocumentContext& ctx) const override
38 {
39 auto& cmt = m_path.find(ctx);
40 // Remove all the cables that could have been added during
41 // the creation
42 Dataflow::removeCables(m_oldCables, ctx);
43
44 // Set the old script
45 Process::ScriptChangeResult res = (cmt.*Property_T::set)(m_oldScript);
46 cmt.programChanged();
47
48 // We expect the inputs / outputs to revert back to the
49 // exact same state
50 SCORE_ASSERT(m_oldInlets.size() == cmt.inlets().size());
51 SCORE_ASSERT(m_oldOutlets.size() == cmt.outlets().size());
52
53 // So we can reload their data identically
54 for(std::size_t i = 0; i < m_oldInlets.size(); i++)
55 {
56 cmt.inlets()[i]->loadData(m_oldInlets[i].data);
57 }
58 for(std::size_t i = 0; i < m_oldOutlets.size(); i++)
59 {
60 cmt.outlets()[i]->loadData(m_oldOutlets[i].data);
61 }
62
63 // Recreate the old cables
64 Dataflow::restoreCables(m_oldCables, ctx);
65 cmt.inletsChanged();
66 cmt.outletsChanged();
67 if constexpr(requires { cmt.isGpu(); })
68 if(cmt.isGpu())
69 cmt.programChanged();
70 }
71
72 void redo(const score::DocumentContext& ctx) const override
73 {
74 Dataflow::removeCables(m_oldCables, ctx);
75
76 auto& cmt = m_path.find(ctx);
77 Process::ScriptChangeResult res = (cmt.*Property_T::set)(m_newScript);
78 cmt.programChanged();
79
80 Dataflow::reloadPortsInNewProcess(m_oldInlets, m_oldOutlets, m_oldCables, cmt, ctx);
81
82 cmt.inletsChanged();
83 cmt.outletsChanged();
84 if constexpr(requires { cmt.isGpu(); })
85 if(cmt.isGpu())
86 cmt.programChanged();
87 // FIXME if we have it only here, then changing cables fails for the exec nodes
88 // as in the cable loading, in SetupContext::connectCable(Process::Cable& cable)
89 // auto it = outlets.find(port_src); fails because the new outlet hasn't yet been created by the component
90 // but if we have it only above, the JS GPU node fails
91 }
92
93 void serializeImpl(DataStreamInput& s) const override
94 {
95 s << m_path << m_newScript << m_oldScript << m_oldInlets << m_oldOutlets
96 << m_oldCables;
97 }
98
99 void deserializeImpl(DataStreamOutput& s) override
100 {
101 s >> m_path >> m_newScript >> m_oldScript >> m_oldInlets >> m_oldOutlets
102 >> m_oldCables;
103 }
104
105 Path<Process_T> m_path;
106 param_type m_newScript;
107 param_type m_oldScript;
108
109 std::vector<SavedPort> m_oldInlets, m_oldOutlets;
110
111 Dataflow::SerializedCables m_oldCables;
112};
113}
114
115template <>
116struct is_custom_serialized<Scenario::SavedPort> : std::true_type
117{
118};
119
120template <>
121struct TSerializer<DataStream, Scenario::SavedPort>
122{
123 static void readFrom(DataStream::Serializer& s, const Scenario::SavedPort& tv)
124 {
125 s.stream() << tv.name << tv.type << tv.data;
126 }
127
128 static void writeTo(DataStream::Deserializer& s, Scenario::SavedPort& tv)
129 {
130 s.stream() >> tv.name >> tv.type >> tv.data;
131 }
132};
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
Definition DataStreamVisitor.hpp:202
The Path class is a typesafe wrapper around ObjectPath.
Definition Path.hpp:52
Definition ScriptEditCommand.hpp:18
The Command class.
Definition Command.hpp:34
Main plug-in of score.
Definition score-plugin-dataflow/Dataflow/PortItem.hpp:13
Definition DataStreamHelpers.hpp:99
Definition DataStreamHelpers.hpp:103
Definition CableHelpers.hpp:66
Definition ScriptProcess.hpp:14
Definition VisitorInterface.hpp:13
Definition DocumentContext.hpp:18