@@ -31,10 +31,16 @@ ProjectLoader::ProjectLoader(QObject *parent) :
3131
3232ProjectLoader::~ProjectLoader ()
3333{
34+ if (m_loadThread.isRunning ())
35+ m_loadThread.waitForFinished ();
36+
3437 if (m_engine) {
3538 m_engine->stopEventLoop ();
3639 m_eventLoop.waitForFinished ();
3740 }
41+
42+ for (SpriteModel *sprite : m_sprites)
43+ sprite->deleteLater ();
3844}
3945
4046const QString &ProjectLoader::fileName () const
@@ -44,6 +50,9 @@ const QString &ProjectLoader::fileName() const
4450
4551void ProjectLoader::setFileName (const QString &newFileName)
4652{
53+ if (m_loadThread.isRunning ())
54+ m_loadThread.waitForFinished ();
55+
4756 if (m_fileName == newFileName)
4857 return ;
4958
@@ -56,89 +65,72 @@ void ProjectLoader::setFileName(const QString &newFileName)
5665
5766 m_project.setScratchVersion (ScratchVersion::Scratch3);
5867 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 ();
10370 emit fileNameChanged ();
104- emit loadedChanged ();
105- emit engineChanged ();
106- emit stageChanged ();
107- emit spritesChanged ();
71+
72+ m_loadThread = QtConcurrent::run (&callLoad, this );
10873}
10974
110- bool ProjectLoader::loaded () const
75+ bool ProjectLoader::loadStatus () const
11176{
112- return m_loaded;
77+ if (m_loadThread.isRunning ())
78+ return false ;
79+
80+ return m_loadStatus;
11381}
11482
11583IEngine *ProjectLoader::engine () const
11684{
85+ if (m_loadThread.isRunning ())
86+ return nullptr ;
87+
11788 return m_engine;
11889}
11990
12091StageModel *ProjectLoader::stage ()
12192{
93+ if (m_loadThread.isRunning ())
94+ m_loadThread.waitForFinished ();
95+
12296 return &m_stage;
12397}
12498
12599QQmlListProperty<SpriteModel> ProjectLoader::sprites ()
126100{
101+ if (m_loadThread.isRunning ())
102+ m_loadThread.waitForFinished ();
103+
127104 return QQmlListProperty<SpriteModel>(this , &m_sprites);
128105}
129106
130107void ProjectLoader::start ()
131108{
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+ }
133116}
134117
135118void ProjectLoader::stop ()
136119{
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+ }
138127}
139128
140129void ProjectLoader::timerEvent (QTimerEvent *event)
141130{
131+ if (m_loadThread.isRunning ())
132+ return ;
133+
142134 auto stageRenderedTarget = m_stage.renderedTarget ();
143135
144136 if (stageRenderedTarget)
@@ -154,6 +146,68 @@ void ProjectLoader::timerEvent(QTimerEvent *event)
154146 event->accept ();
155147}
156148
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+
157211void ProjectLoader::initTimer ()
158212{
159213 QScreen *screen = qApp->primaryScreen ();
@@ -164,6 +218,9 @@ void ProjectLoader::initTimer()
164218
165219void ProjectLoader::emitTick ()
166220{
221+ if (m_loadThread.isRunning ())
222+ m_loadThread.waitForFinished ();
223+
167224 auto stageRenderedTarget = m_stage.renderedTarget ();
168225
169226 if (stageRenderedTarget)
@@ -188,10 +245,12 @@ void ProjectLoader::setFps(double newFps)
188245 return ;
189246
190247 m_fps = newFps;
248+ m_engineMutex.lock ();
191249
192250 if (m_engine)
193251 m_engine->setFps (m_fps);
194252
253+ m_engineMutex.unlock ();
195254 emit fpsChanged ();
196255}
197256
@@ -206,10 +265,12 @@ void ProjectLoader::setTurboMode(bool newTurboMode)
206265 return ;
207266
208267 m_turboMode = newTurboMode;
268+ m_engineMutex.lock ();
209269
210270 if (m_engine)
211271 m_engine->setTurboModeEnabled (m_turboMode);
212272
273+ m_engineMutex.unlock ();
213274 emit turboModeChanged ();
214275}
215276
@@ -224,10 +285,12 @@ void ProjectLoader::setStageWidth(unsigned int newStageWidth)
224285 return ;
225286
226287 m_stageWidth = newStageWidth;
288+ m_engineMutex.lock ();
227289
228290 if (m_engine)
229291 m_engine->setStageWidth (m_stageWidth);
230292
293+ m_engineMutex.unlock ();
231294 emit stageWidthChanged ();
232295}
233296
@@ -242,10 +305,12 @@ void ProjectLoader::setStageHeight(unsigned int newStageHeight)
242305 return ;
243306
244307 m_stageHeight = newStageHeight;
308+ m_engineMutex.lock ();
245309
246310 if (m_engine)
247311 m_engine->setStageHeight (m_stageHeight);
248312
313+ m_engineMutex.unlock ();
249314 emit stageHeightChanged ();
250315}
251316
@@ -260,10 +325,12 @@ void ProjectLoader::setCloneLimit(int newCloneLimit)
260325 return ;
261326
262327 m_cloneLimit = newCloneLimit;
328+ m_engineMutex.lock ();
263329
264330 if (m_engine)
265331 m_engine->setCloneLimit (m_cloneLimit);
266332
333+ m_engineMutex.unlock ();
267334 emit cloneLimitChanged ();
268335}
269336
@@ -278,9 +345,11 @@ void ProjectLoader::setSpriteFencing(bool newSpriteFencing)
278345 return ;
279346
280347 m_spriteFencing = newSpriteFencing;
348+ m_engineMutex.lock ();
281349
282350 if (m_engine)
283351 m_engine->setSpriteFencingEnabled (m_spriteFencing);
284352
353+ m_engineMutex.unlock ();
285354 emit spriteFencingChanged ();
286355}
0 commit comments