Skip to content

Commit 8792b25

Browse files
committed
Add a way to get variable and list owner target
1 parent 1db403e commit 8792b25

File tree

5 files changed

+101
-1
lines changed

5 files changed

+101
-1
lines changed

include/scratchcpp/iengine.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class Broadcast;
1616
class Block;
1717
class Target;
1818
class Sprite;
19+
class Variable;
20+
class List;
1921
class Script;
2022

2123
/*!
@@ -176,6 +178,12 @@ class LIBSCRATCHCPP_EXPORT IEngine
176178
/*! Returns the index of the target with the given name. */
177179
virtual int findTarget(const std::string &targetName) const = 0;
178180

181+
/*! Returns the target which owns the given variable. If it is the stage, the variable is global. */
182+
virtual Target *variableOwner(Variable *variable) const = 0;
183+
184+
/*! Returns the target which owns the given list. If it is the stage, the list is global. */
185+
virtual Target *listOwner(List *list) const = 0;
186+
179187
/*! Returns the list of extension names. */
180188
virtual const std::vector<std::string> &extensions() const = 0;
181189

src/engine/internal/engine.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,15 +509,31 @@ const std::vector<std::shared_ptr<Target>> &Engine::targets() const
509509
void Engine::setTargets(const std::vector<std::shared_ptr<Target>> &newTargets)
510510
{
511511
m_targets = newTargets;
512+
m_variableOwners.clear();
513+
m_listOwners.clear();
512514

513-
// Set engine in targets and engine and target in all blocks
514515
for (auto target : m_targets) {
516+
// Set engine in the target
515517
target->setEngine(this);
516518
auto blocks = target->blocks();
519+
517520
for (auto block : blocks) {
521+
// Set engine and target in the block
518522
block->setEngine(this);
519523
block->setTarget(target.get());
520524
}
525+
526+
// Add variables to owner map
527+
const auto &variables = target->variables();
528+
529+
for (auto variable : variables)
530+
m_variableOwners[variable.get()] = target.get();
531+
532+
// Add lists to owner map
533+
const auto &lists = target->lists();
534+
535+
for (auto list : lists)
536+
m_listOwners[list.get()] = target.get();
521537
}
522538
}
523539

@@ -540,6 +556,26 @@ int Engine::findTarget(const std::string &targetName) const
540556
return -1;
541557
}
542558

559+
Target *Engine::variableOwner(Variable *variable) const
560+
{
561+
auto it = m_variableOwners.find(variable);
562+
563+
if (it == m_variableOwners.cend())
564+
return nullptr;
565+
566+
return it->second;
567+
}
568+
569+
Target *Engine::listOwner(List *list) const
570+
{
571+
auto it = m_listOwners.find(list);
572+
573+
if (it == m_listOwners.cend())
574+
return nullptr;
575+
576+
return it->second;
577+
}
578+
543579
const std::vector<std::string> &Engine::extensions() const
544580
{
545581
return m_extensions;

src/engine/internal/engine.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ class Engine : public IEngine
6868
Target *targetAt(int index) const override;
6969
int findTarget(const std::string &targetName) const override;
7070

71+
Target *variableOwner(Variable *variable) const override;
72+
Target *listOwner(List *list) const override;
73+
7174
const std::vector<std::string> &extensions() const override;
7275
void setExtensions(const std::vector<std::string> &newExtensions) override;
7376

@@ -95,6 +98,8 @@ class Engine : public IEngine
9598
std::vector<VirtualMachine *> m_scriptsToRemove;
9699
std::unordered_map<std::shared_ptr<Block>, std::shared_ptr<Script>> m_scripts;
97100
std::vector<BlockFunc> m_functions;
101+
std::unordered_map<Variable *, Target *> m_variableOwners;
102+
std::unordered_map<List *, Target *> m_listOwners;
98103

99104
bool m_breakFrame = false;
100105
bool m_skipFrame = false;

test/engine/engine_test.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <scratchcpp/broadcast.h>
22
#include <scratchcpp/block.h>
3+
#include <scratchcpp/variable.h>
4+
#include <scratchcpp/list.h>
35

46
#include "../common.h"
57
#include "testsection.h"
@@ -283,3 +285,49 @@ TEST(EngineTest, Targets)
283285
ASSERT_EQ(block1->engine(), &engine);
284286
ASSERT_EQ(block2->engine(), &engine);
285287
}
288+
289+
TEST(EngineTest, VariableOwner)
290+
{
291+
Engine engine;
292+
auto t1 = std::make_shared<Target>();
293+
auto t2 = std::make_shared<Target>();
294+
auto t3 = std::make_shared<Target>();
295+
296+
auto var1 = std::make_shared<Variable>("", "", Value());
297+
auto var2 = std::make_shared<Variable>("", "", Value());
298+
auto var3 = std::make_shared<Variable>("", "", Value());
299+
auto var4 = std::make_shared<Variable>("", "", Value());
300+
t1->addVariable(var1);
301+
t1->addVariable(var4);
302+
t3->addVariable(var3);
303+
304+
engine.setTargets({ t1, t2, t3 });
305+
306+
ASSERT_EQ(engine.variableOwner(var1.get()), t1.get());
307+
ASSERT_EQ(engine.variableOwner(var2.get()), nullptr);
308+
ASSERT_EQ(engine.variableOwner(var3.get()), t3.get());
309+
ASSERT_EQ(engine.variableOwner(var4.get()), t1.get());
310+
}
311+
312+
TEST(EngineTest, ListOwner)
313+
{
314+
Engine engine;
315+
auto t1 = std::make_shared<Target>();
316+
auto t2 = std::make_shared<Target>();
317+
auto t3 = std::make_shared<Target>();
318+
319+
auto list1 = std::make_shared<List>("", "");
320+
auto list2 = std::make_shared<List>("", "");
321+
auto list3 = std::make_shared<List>("", "");
322+
auto list4 = std::make_shared<List>("", "");
323+
t1->addList(list1);
324+
t1->addList(list4);
325+
t3->addList(list3);
326+
327+
engine.setTargets({ t1, t2, t3 });
328+
329+
ASSERT_EQ(engine.listOwner(list1.get()), t1.get());
330+
ASSERT_EQ(engine.listOwner(list2.get()), nullptr);
331+
ASSERT_EQ(engine.listOwner(list3.get()), t3.get());
332+
ASSERT_EQ(engine.listOwner(list4.get()), t1.get());
333+
}

test/mocks/enginemock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class EngineMock : public IEngine
5656
MOCK_METHOD(Target *, targetAt, (int), (const, override));
5757
MOCK_METHOD(int, findTarget, (const std::string &), (const, override));
5858

59+
MOCK_METHOD(Target *, variableOwner, (Variable *), (const, override));
60+
MOCK_METHOD(Target *, listOwner, (List *), (const, override));
61+
5962
MOCK_METHOD(std::vector<std::string> &, extensions, (), (const, override));
6063
MOCK_METHOD(void, setExtensions, (const std::vector<std::string> &), (override));
6164

0 commit comments

Comments
 (0)