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 <Dataflow/Commands/CableHelpers.hpp>
8
9#include <ossia/detail/algorithms.hpp>
10namespace Scenario
11{
12using SavedPort = Dataflow::SavedPort;
13
14template <typename Process_T, typename Property_T>
16{
17public:
18 using param_type = typename Property_T::param_type;
19 using score::Command::Command;
21 const Process_T& model, param_type newScript, const score::DocumentContext& ctx)
22 : m_path{model}
23 , m_newScript{std::move(newScript)}
24 , m_oldScript{(model.*Property_T::get)()}
25 {
26 m_oldCables = Dataflow::saveCables({const_cast<Process_T*>(&model)}, ctx);
27
28 for(auto& port : model.inlets())
29 m_oldInlets.emplace_back(
30 Dataflow::SavedPort{port->name(), port->type(), port->saveData()});
31 for(auto& port : model.outlets())
32 m_oldOutlets.emplace_back(
33 Dataflow::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; the ports at the other end lost them too
64 auto cables = Dataflow::restoreCablesWithoutTouchingPorts(m_oldCables, ctx);
65 Dataflow::reattachCablesToPorts(cables, ctx);
66 cmt.inletsChanged();
67 cmt.outletsChanged();
68 cmt.programChanged();
69
70 Dataflow::notifyAddedCables(cables, ctx);
71 }
72
73 void redo(const score::DocumentContext& ctx) const override
74 {
75 Dataflow::removeCables(m_oldCables, ctx);
76
77 auto& cmt = m_path.find(ctx);
78 Process::ScriptChangeResult res = (cmt.*Property_T::set)(m_newScript);
79 cmt.programChanged();
80
81 auto cables = Dataflow::reloadPortsInNewProcess(
82 m_oldInlets, m_oldOutlets, m_oldCables, cmt, Process::PortLoadDataFlags{}, ctx,
83 {}, {});
84
85 cmt.inletsChanged();
86 cmt.outletsChanged();
87 cmt.programChanged();
88
89 Dataflow::notifyAddedCables(cables, ctx);
90 }
91
92 void serializeImpl(DataStreamInput& s) const override
93 {
94 s << m_path << m_newScript << m_oldScript << m_oldInlets << m_oldOutlets
95 << m_oldCables;
96 }
97
98 void deserializeImpl(DataStreamOutput& s) override
99 {
100 s >> m_path >> m_newScript >> m_oldScript >> m_oldInlets >> m_oldOutlets
101 >> m_oldCables;
102 }
103
104 Path<Process_T> m_path;
105 param_type m_newScript;
106 param_type m_oldScript;
107
108 std::vector<SavedPort> m_oldInlets, m_oldOutlets;
109
110 Dataflow::SerializedCables m_oldCables;
111};
112}
The Path class is a typesafe wrapper around ObjectPath.
Definition Path.hpp:52
Definition ScriptEditCommand.hpp:16
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:88
Definition ScriptProcess.hpp:14
Definition DocumentContext.hpp:18