-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSceneNode.cpp
147 lines (116 loc) · 3.53 KB
/
SceneNode.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
147
#include "SceneNode.hpp"
#include <SFML/Graphics.hpp>
SceneNode::SceneNode(Category::Type category)
: mChildren()
, mParent()
, mDefaultCategory(category)
{}
void SceneNode::attachChild(SceneNode::Ptr child)
{
child->mParent = this;
mChildren.push_back(std::move(child));
}
SceneNode::Ptr SceneNode::detachChild(const SceneNode &node)
{
auto found = std::find_if(mChildren.begin(), mChildren.end(),
[&] (Ptr &p) -> bool {return p.get() == &node;});
assert(found != mChildren.end());
Ptr result = std::move(*found);
result->mParent = nullptr;
mChildren.erase(found);
return result;
}
void SceneNode::update(sf::Time dt, CommandQueue &commands)
{
updateCurrent(dt, commands);
updateChildren(dt, commands);
}
sf::Vector2f SceneNode::getWorldPosition() const
{
return getWorldTransform() * sf::Vector2f();
}
void SceneNode::onCommand(const Command &command, sf::Time dt)
{
if(command.category & getCategory())
command.action(*this, dt);
for(Ptr &child : mChildren)
child->onCommand(command, dt);
}
void SceneNode::checkNodeCollision(SceneNode &node, std::set<Pair> &collisionPairs)
{
if(this != &node && collision(*this, node) && !isDestroyed() && !node.isDestroyed())
collisionPairs.insert(std::minmax(this, &node));
for(Ptr &child : mChildren)
child->checkNodeCollision(node, collisionPairs);
}
void SceneNode::checkSceneCollision(SceneNode &sceneGraph, std::set<Pair> &collisionPairs)
{
checkNodeCollision(sceneGraph, collisionPairs);
for(Ptr &child : sceneGraph.mChildren)
checkSceneCollision(*child, collisionPairs);
}
// virtual, and should not be override by subclass, final function
void SceneNode::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
states.transform *= getTransform();
drawCurrent(target, states);
for(auto itr = mChildren.begin(); itr != mChildren.end(); ++itr)
(*itr)->draw(target, states);
// drawBoundingRect(target, states);
}
// virtual, should be override
void SceneNode::drawCurrent(sf::RenderTarget &target, sf::RenderStates states) const
{}
// virtual
void SceneNode::updateCurrent(sf::Time dt, CommandQueue &commands)
{
// do nothing
}
void SceneNode::updateChildren(sf::Time dt, CommandQueue &commands)
{
for(Ptr &child : mChildren)
child->update(dt, commands);
}
sf::Transform SceneNode::getWorldTransform() const
{
sf::Transform transform = sf::Transform::Identity;
for(const SceneNode *node=this; node != nullptr; node = node->mParent)
transform = node->getTransform() * transform;
return transform;
}
//virtual
unsigned int SceneNode::getCategory() const
{
return mDefaultCategory;
}
void SceneNode::removeWrecks()
{
// Remove all children which request so
auto wreckfieldBegin = std::remove_if(mChildren.begin(), mChildren.end(), std::mem_fn(&SceneNode::isMarkedForRemoval));
mChildren.erase(wreckfieldBegin, mChildren.end());
// Call function recursively for all remaining children
std::for_each(mChildren.begin(), mChildren.end(), std::mem_fn(&SceneNode::removeWrecks));
}
sf::FloatRect SceneNode::getBoundingRect() const
{
return sf::FloatRect();
}
bool SceneNode::isDestroyed() const
{
return false;
}
bool SceneNode::isMarkedForRemoval() const
{
return isDestroyed();
}
void SceneNode::drawBoundingRect(sf::RenderTarget &target, sf::RenderStates) const
{
sf::FloatRect rect = getBoundingRect();
sf::RectangleShape shape;
shape.setPosition(sf::Vector2f(rect.left, rect.top));
shape.setSize(sf::Vector2f(rect.width, rect.height));
shape.setFillColor(sf::Color::Transparent);
shape.setOutlineColor(sf::Color::Red);
shape.setOutlineThickness(1.f);
target.draw(shape);
}