@@ -31,10 +31,16 @@ ProjectLoader::ProjectLoader(QObject *parent) :
31
31
32
32
ProjectLoader::~ProjectLoader ()
33
33
{
34
+ if (m_loadThread.isRunning ())
35
+ m_loadThread.waitForFinished ();
36
+
34
37
if (m_engine) {
35
38
m_engine->stopEventLoop ();
36
39
m_eventLoop.waitForFinished ();
37
40
}
41
+
42
+ for (SpriteModel *sprite : m_sprites)
43
+ sprite->deleteLater ();
38
44
}
39
45
40
46
const QString &ProjectLoader::fileName () const
@@ -44,6 +50,9 @@ const QString &ProjectLoader::fileName() const
44
50
45
51
void ProjectLoader::setFileName (const QString &newFileName)
46
52
{
53
+ if (m_loadThread.isRunning ())
54
+ m_loadThread.waitForFinished ();
55
+
47
56
if (m_fileName == newFileName)
48
57
return ;
49
58
@@ -56,89 +65,72 @@ void ProjectLoader::setFileName(const QString &newFileName)
56
65
57
66
m_project.setScratchVersion (ScratchVersion::Scratch3);
58
67
m_project.setFileName (m_fileName.toStdString ());
59
- m_loaded = m_project.load ();
60
- m_engine = m_project.engine ().get ();
61
-
62
- // Delete old sprites
63
- for (SpriteModel *sprite : m_sprites)
64
- sprite->deleteLater ();
65
-
66
- m_sprites.clear ();
67
-
68
- if (!m_engine) {
69
- emit fileNameChanged ();
70
- emit loadedChanged ();
71
- emit engineChanged ();
72
- emit spritesChanged ();
73
- return ;
74
- }
75
-
76
- m_engine->setFps (m_fps);
77
- m_engine->setTurboModeEnabled (m_turboMode);
78
- m_engine->setStageWidth (m_stageWidth);
79
- m_engine->setStageHeight (m_stageHeight);
80
- m_engine->setCloneLimit (m_cloneLimit);
81
- m_engine->setSpriteFencingEnabled (m_spriteFencing);
82
-
83
- auto handler = std::bind (&ProjectLoader::emitTick, this );
84
- m_engine->setRedrawHandler (std::function<void ()>(handler));
85
-
86
- // Load targets
87
- const auto &targets = m_engine->targets ();
88
-
89
- for (auto target : targets) {
90
- if (target->isStage ())
91
- dynamic_cast <Stage *>(target.get ())->setInterface (&m_stage);
92
- else {
93
- SpriteModel *sprite = new SpriteModel (this );
94
- dynamic_cast <Sprite *>(target.get ())->setInterface (sprite);
95
- m_sprites.push_back (sprite);
96
- }
97
- }
98
-
99
- // Run event loop
100
- m_engine->setSpriteFencingEnabled (false );
101
- m_eventLoop = QtConcurrent::run (&runEventLoop, m_engine);
102
-
68
+ m_loadStatus = false ;
69
+ emit loadStatusChanged ();
103
70
emit fileNameChanged ();
104
- emit loadedChanged ();
105
- emit engineChanged ();
106
- emit stageChanged ();
107
- emit spritesChanged ();
71
+
72
+ m_loadThread = QtConcurrent::run (&callLoad, this );
108
73
}
109
74
110
- bool ProjectLoader::loaded () const
75
+ bool ProjectLoader::loadStatus () const
111
76
{
112
- return m_loaded;
77
+ if (m_loadThread.isRunning ())
78
+ return false ;
79
+
80
+ return m_loadStatus;
113
81
}
114
82
115
83
IEngine *ProjectLoader::engine () const
116
84
{
85
+ if (m_loadThread.isRunning ())
86
+ return nullptr ;
87
+
117
88
return m_engine;
118
89
}
119
90
120
91
StageModel *ProjectLoader::stage ()
121
92
{
93
+ if (m_loadThread.isRunning ())
94
+ m_loadThread.waitForFinished ();
95
+
122
96
return &m_stage;
123
97
}
124
98
125
99
QQmlListProperty<SpriteModel> ProjectLoader::sprites ()
126
100
{
101
+ if (m_loadThread.isRunning ())
102
+ m_loadThread.waitForFinished ();
103
+
127
104
return QQmlListProperty<SpriteModel>(this , &m_sprites);
128
105
}
129
106
130
107
void ProjectLoader::start ()
131
108
{
132
- m_engine->start ();
109
+ if (m_loadThread.isRunning ())
110
+ m_loadThread.waitForFinished ();
111
+
112
+ if (m_loadStatus) {
113
+ Q_ASSERT (m_engine);
114
+ m_engine->start ();
115
+ }
133
116
}
134
117
135
118
void ProjectLoader::stop ()
136
119
{
137
- m_engine->stop ();
120
+ if (m_loadThread.isRunning ())
121
+ m_loadThread.waitForFinished ();
122
+
123
+ if (m_loadStatus) {
124
+ Q_ASSERT (m_engine);
125
+ m_engine->stop ();
126
+ }
138
127
}
139
128
140
129
void ProjectLoader::timerEvent (QTimerEvent *event)
141
130
{
131
+ if (m_loadThread.isRunning ())
132
+ return ;
133
+
142
134
auto stageRenderedTarget = m_stage.renderedTarget ();
143
135
144
136
if (stageRenderedTarget)
@@ -154,6 +146,68 @@ void ProjectLoader::timerEvent(QTimerEvent *event)
154
146
event->accept ();
155
147
}
156
148
149
+ void ProjectLoader::callLoad (ProjectLoader *loader)
150
+ {
151
+ loader->load ();
152
+ }
153
+
154
+ void ProjectLoader::load ()
155
+ {
156
+ m_loadStatus = m_project.load ();
157
+ m_engineMutex.lock ();
158
+ m_engine = m_project.engine ().get ();
159
+
160
+ // Delete old sprites
161
+ for (SpriteModel *sprite : m_sprites)
162
+ sprite->deleteLater ();
163
+
164
+ m_sprites.clear ();
165
+
166
+ if (!m_engine) {
167
+ emit fileNameChanged ();
168
+ emit loadStatusChanged ();
169
+ emit loadingFinished ();
170
+ emit engineChanged ();
171
+ emit spritesChanged ();
172
+ return ;
173
+ }
174
+
175
+ m_engine->setFps (m_fps);
176
+ m_engine->setTurboModeEnabled (m_turboMode);
177
+ m_engine->setStageWidth (m_stageWidth);
178
+ m_engine->setStageHeight (m_stageHeight);
179
+ m_engine->setCloneLimit (m_cloneLimit);
180
+ m_engine->setSpriteFencingEnabled (m_spriteFencing);
181
+
182
+ auto handler = std::bind (&ProjectLoader::emitTick, this );
183
+ m_engine->setRedrawHandler (std::function<void ()>(handler));
184
+
185
+ // Load targets
186
+ const auto &targets = m_engine->targets ();
187
+
188
+ for (auto target : targets) {
189
+ if (target->isStage ())
190
+ dynamic_cast <Stage *>(target.get ())->setInterface (&m_stage);
191
+ else {
192
+ SpriteModel *sprite = new SpriteModel;
193
+ sprite->moveToThread (qApp->thread ());
194
+ dynamic_cast <Sprite *>(target.get ())->setInterface (sprite);
195
+ m_sprites.push_back (sprite);
196
+ }
197
+ }
198
+
199
+ // Run event loop
200
+ m_engine->setSpriteFencingEnabled (false );
201
+ m_eventLoop = QtConcurrent::run (&runEventLoop, m_engine);
202
+ m_engineMutex.unlock ();
203
+
204
+ emit loadStatusChanged ();
205
+ emit loadingFinished ();
206
+ emit engineChanged ();
207
+ emit stageChanged ();
208
+ emit spritesChanged ();
209
+ }
210
+
157
211
void ProjectLoader::initTimer ()
158
212
{
159
213
QScreen *screen = qApp->primaryScreen ();
@@ -164,6 +218,9 @@ void ProjectLoader::initTimer()
164
218
165
219
void ProjectLoader::emitTick ()
166
220
{
221
+ if (m_loadThread.isRunning ())
222
+ m_loadThread.waitForFinished ();
223
+
167
224
auto stageRenderedTarget = m_stage.renderedTarget ();
168
225
169
226
if (stageRenderedTarget)
@@ -188,10 +245,12 @@ void ProjectLoader::setFps(double newFps)
188
245
return ;
189
246
190
247
m_fps = newFps;
248
+ m_engineMutex.lock ();
191
249
192
250
if (m_engine)
193
251
m_engine->setFps (m_fps);
194
252
253
+ m_engineMutex.unlock ();
195
254
emit fpsChanged ();
196
255
}
197
256
@@ -206,10 +265,12 @@ void ProjectLoader::setTurboMode(bool newTurboMode)
206
265
return ;
207
266
208
267
m_turboMode = newTurboMode;
268
+ m_engineMutex.lock ();
209
269
210
270
if (m_engine)
211
271
m_engine->setTurboModeEnabled (m_turboMode);
212
272
273
+ m_engineMutex.unlock ();
213
274
emit turboModeChanged ();
214
275
}
215
276
@@ -224,10 +285,12 @@ void ProjectLoader::setStageWidth(unsigned int newStageWidth)
224
285
return ;
225
286
226
287
m_stageWidth = newStageWidth;
288
+ m_engineMutex.lock ();
227
289
228
290
if (m_engine)
229
291
m_engine->setStageWidth (m_stageWidth);
230
292
293
+ m_engineMutex.unlock ();
231
294
emit stageWidthChanged ();
232
295
}
233
296
@@ -242,10 +305,12 @@ void ProjectLoader::setStageHeight(unsigned int newStageHeight)
242
305
return ;
243
306
244
307
m_stageHeight = newStageHeight;
308
+ m_engineMutex.lock ();
245
309
246
310
if (m_engine)
247
311
m_engine->setStageHeight (m_stageHeight);
248
312
313
+ m_engineMutex.unlock ();
249
314
emit stageHeightChanged ();
250
315
}
251
316
@@ -260,10 +325,12 @@ void ProjectLoader::setCloneLimit(int newCloneLimit)
260
325
return ;
261
326
262
327
m_cloneLimit = newCloneLimit;
328
+ m_engineMutex.lock ();
263
329
264
330
if (m_engine)
265
331
m_engine->setCloneLimit (m_cloneLimit);
266
332
333
+ m_engineMutex.unlock ();
267
334
emit cloneLimitChanged ();
268
335
}
269
336
@@ -278,9 +345,11 @@ void ProjectLoader::setSpriteFencing(bool newSpriteFencing)
278
345
return ;
279
346
280
347
m_spriteFencing = newSpriteFencing;
348
+ m_engineMutex.lock ();
281
349
282
350
if (m_engine)
283
351
m_engine->setSpriteFencingEnabled (m_spriteFencing);
284
352
353
+ m_engineMutex.unlock ();
285
354
emit spriteFencingChanged ();
286
355
}
0 commit comments