-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathScriptEngine.cpp
146 lines (130 loc) · 4.47 KB
/
ScriptEngine.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "ScriptEngine.h"
ScriptEngine::ScriptEngine()
{
m_snd_object = m_engine.newObject();
m_arg_object = m_engine.newObject();
m_engine.globalObject().setProperty(ScriptKeyword::Snd, m_snd_object);
m_engine.globalObject().setProperty(ScriptKeyword::Arg, m_arg_object);
}
void ScriptEngine::init(const LibraryModelPtr& a_model)
{
Q_ASSERT( m_model.isNull());
Q_ASSERT(!a_model.isNull());
m_model = a_model;
}
SynthMode ScriptEngine::run(const PatternItem* a_item, int a_frame)
{
// Prepare self
Q_ASSERT(m_selfs.count(a_item) == 1);
const QJSValue& self = m_selfs[a_item];
m_engine.globalObject().setProperty(ScriptKeyword::Self, self);
m_arg_object.setProperty(ScriptKeyword::AgrFrame , a_frame);
m_arg_object.setProperty(ScriptKeyword::AgrFrames, a_item->size());
// Reset sound properties
m_snd_object.deleteProperty(ScriptKeyword::SndType);
m_snd_object.deleteProperty(ScriptKeyword::SndVolumeFrom);
m_snd_object.deleteProperty(ScriptKeyword::SndVolumeTo);
m_snd_object.deleteProperty(ScriptKeyword::SndPitch);
m_snd_object.deleteProperty(ScriptKeyword::SndDuty);
// Prepare constants
m_snd_object.setProperty(ScriptKeyword::SndSin , SynthType::Sin);
m_snd_object.setProperty(ScriptKeyword::SndSquare , SynthType::Square);
m_snd_object.setProperty(ScriptKeyword::SndTriangle, SynthType::Triangle);
m_snd_object.setProperty(ScriptKeyword::SndSaw , SynthType::Saw);
// Run script
auto library_item = a_item->libraryItem().get();
Q_ASSERT(m_script_objects.count(library_item) == 1);
QJSValue& script = m_script_objects[library_item];
SynthMode mode;
if (script.isCallable())
{
auto result = script.call();
if (!result.isError())
{
if (m_snd_object.hasProperty(ScriptKeyword::SndType))
{
SynthType type = m_snd_object.property(ScriptKeyword::SndType).toInt();
mode.setType(type);
}
if (m_snd_object.hasProperty(ScriptKeyword::SndVolumeFrom))
{
float volume = m_snd_object.property(ScriptKeyword::SndVolumeFrom).toVariant().value<float>();
mode.setVolumeFrom(volume);
}
if (m_snd_object.hasProperty(ScriptKeyword::SndVolumeTo))
{
float volume = m_snd_object.property(ScriptKeyword::SndVolumeTo).toVariant().value<float>();
mode.setVolumeTo(volume);
}
if (m_snd_object.hasProperty(ScriptKeyword::SndPitch))
{
float pitch = m_snd_object.property(ScriptKeyword::SndPitch).toVariant().value<float>();
mode.setPitch(pitch);
}
if (m_snd_object.hasProperty(ScriptKeyword::SndDuty))
{
float duty = m_snd_object.property(ScriptKeyword::SndDuty).toVariant().value<float>();
mode.setDuty(duty);
}
}
}
return mode;
}
void ScriptEngine::onLibraryItemAdded(const QModelIndex& a_parent, int a_start, int a_end)
{
Q_ASSERT(!a_parent.isValid());
for (int index = a_start; index <= a_end; index++)
{
auto item = m_model->item(index).get();
Q_ASSERT(m_script_objects.count(item) == 0);
updateScriptObject(index, item);
}
}
void ScriptEngine::onLibraryItemChanged(const QModelIndex& a_top_left, const QModelIndex& a_bottom_right)
{
if (a_top_left.column() > LibraryModel::Column::Script ||
a_bottom_right.column() < LibraryModel::Column::Script )
return;
for (int index = a_top_left.row(); index <= a_bottom_right.row(); index++)
{
auto item = m_model->item(index).get();
Q_ASSERT(m_script_objects.count(item) == 1);
updateScriptObject(index, item);
}
}
void ScriptEngine::onLibraryItemDeleted(const QModelIndex& a_parent, int a_start, int a_end)
{
Q_ASSERT(!a_parent.isValid());
for (int index = a_start; index <= a_end; index++)
{
auto item = m_model->item(index).get();
Q_ASSERT(m_script_objects.count(item) == 1);
m_script_objects.remove(item);
}
}
void ScriptEngine::onPatternItemAdded(QGraphicsItem* a_item)
{
PatternItem* item = dynamic_cast<PatternItem*>(a_item);
if (item == nullptr)
return;
Q_ASSERT(m_selfs.count(item) == 0);
m_selfs[item] = m_engine.newObject();
}
void ScriptEngine::onPatternItemDeleted(QGraphicsItem* a_item)
{
PatternItem* item = dynamic_cast<PatternItem*>(a_item);
if (item == nullptr)
return;
Q_ASSERT(m_selfs.count(item) == 1);
m_selfs.remove(item);
}
void ScriptEngine::updateScriptObject(int a_index, const LibraryItem* a_item)
{
QString script = QString("(function() { %1 })").arg( a_item->script() );
QJSValue script_object = m_engine.evaluate(script);
if (script_object.isError())
emit scriptError(a_index, script_object.toString());
if (!script_object.isCallable())
script_object = QJSValue();
m_script_objects[a_item] = script_object;
}