CUGL 1.1
Cornell University Game Library
CUNode.h
1 //
2 // CUNode.h
3 // Cornell University Game Library (CUGL)
4 //
5 // This module provides support for a (2d) scene graph node. It uses an anchor
6 // based approach, much like Cocos2d. However, it is much more streamlined
7 // and removes a lot of the Cocos2d nonsense when it comes to transforms.
8 //
9 // This class uses our standard shared-pointer architecture.
10 //
11 // 1. The constructor does not perform any initialization; it just sets all
12 // attributes to their defaults.
13 //
14 // 2. All initialization takes place via init methods, which can fail if an
15 // object is initialized more than once.
16 //
17 // 3. All allocation takes place via static constructors which return a shared
18 // pointer.
19 //
20 // CUGL zlib License:
21 // This software is provided 'as-is', without any express or implied
22 // warranty. In no event will the authors be held liable for any damages
23 // arising from the use of this software.
24 //
25 // Permission is granted to anyone to use this software for any purpose,
26 // including commercial applications, and to alter it and redistribute it
27 // freely, subject to the following restrictions:
28 //
29 // 1. The origin of this software must not be misrepresented; you must not
30 // claim that you wrote the original software. If you use this software
31 // in a product, an acknowledgment in the product documentation would be
32 // appreciated but is not required.
33 //
34 // 2. Altered source versions must be plainly marked as such, and must not
35 // be misrepresented as being the original software.
36 //
37 // 3. This notice may not be removed or altered from any source distribution.
38 //
39 // Author: Walker White
40 // Version: 6/27/16
41 
42 #ifndef __CU_NODE_H__
43 #define __CU_NODE_H__
44 
45 #include <cugl/math/cu_math.h>
46 #include <cugl/renderer/CUSpriteBatch.h>
47 #include <cugl/util/CUDebug.h>
48 #include <cugl/assets/CUJsonValue.h>
49 #include <vector>
50 #include <string>
51 
52 namespace cugl {
53 
55 class Scene;
56 class SceneLoader;
57 class Layout;
58 
92 class Node {
93 #pragma mark Values
94 protected:
102 
110 
113 
120 
128 
137  float _angle;
138 
148 
151 
160 
162  std::vector<std::shared_ptr<Node>> _children;
163 
169  std::shared_ptr<Layout> _layout;
170 
173 
181  unsigned int _tag;
182 
189  std::string _name;
190 
196  size_t _hashOfName;
197 
199  int _zOrder;
201  bool _zDirty;
202 
203 #pragma mark -
204 #pragma mark Constructors
205 public:
214  Node();
215 
219  ~Node() { dispose(); }
220 
230  virtual void dispose();
231 
239  virtual bool init() {
240  return initWithPosition(0, 0);
241  }
242 
243 
254  virtual bool initWithPosition(const Vec2& pos);
255 
267  bool initWithPosition(float x, float y) {
268  return initWithPosition(Vec2(x,y));
269  }
270 
283  virtual bool initWithBounds(const Size& size);
284 
298  bool initWithBounds(float width, float height) {
299  return initWithBounds(Size(width,height));
300  }
301 
317  virtual bool initWithBounds(const Rect& rect);
318 
337  bool initWithBounds(float x, float y, float width, float height) {
338  return initWithBounds(Rect(x,y,width,height));
339  }
340 
368  virtual bool initWithData(const SceneLoader* loader, const std::shared_ptr<JsonValue> data);
369 
381  virtual Node* copy(Node* dst);
382 
383 
384 #pragma mark -
385 #pragma mark Static Constructors
386 
394  static std::shared_ptr<Node> alloc() {
395  std::shared_ptr<Node> result = std::make_shared<Node>();
396  return (result->init() ? result : nullptr);
397  }
398 
409  static std::shared_ptr<Node> allocWithPosition(const Vec2& pos) {
410  std::shared_ptr<Node> result = std::make_shared<Node>();
411  return (result->initWithPosition(pos) ? result : nullptr);
412  }
413 
425  static std::shared_ptr<Node> allocWithPosition(float x, float y) {
426  std::shared_ptr<Node> result = std::make_shared<Node>();
427  return (result->initWithPosition(x,y) ? result : nullptr);
428  }
429 
442  static std::shared_ptr<Node> allocWithBounds(const Size& size) {
443  std::shared_ptr<Node> result = std::make_shared<Node>();
444  return (result->initWithBounds(size) ? result : nullptr);
445  }
446 
460  static std::shared_ptr<Node> allocWithBounds(float width, float height) {
461  std::shared_ptr<Node> result = std::make_shared<Node>();
462  return (result->initWithBounds(width,height) ? result : nullptr);
463  }
464 
480  static std::shared_ptr<Node> allocWithBounds(const Rect& rect) {
481  std::shared_ptr<Node> result = std::make_shared<Node>();
482  return (result->initWithBounds(rect) ? result : nullptr);
483  }
484 
503  static std::shared_ptr<Node> allocWithBounds(float x, float y, float width, float height) {
504  std::shared_ptr<Node> result = std::make_shared<Node>();
505  return (result->initWithBounds(x,y,width,height) ? result : nullptr);
506  }
507 
535  static std::shared_ptr<Node> allocWithData(const SceneLoader* loader,
536  const std::shared_ptr<JsonValue> data) {
537  std::shared_ptr<Node> result = std::make_shared<Node>();
538  return (result->initWithData(loader,data) ? result : nullptr);
539  }
540 
541 #pragma mark -
542 #pragma mark Identifiers
543 
552  unsigned int getTag() const { return _tag; }
553 
563  void setTag(unsigned int tag) { _tag = tag; }
564 
574  const std::string& getName() const { return _name; }
575 
585  void setName(const std::string& name) {
586  _name = name;
587  _hashOfName = std::hash<std::string>()(_name);
588  }
589 
600  virtual std::string toString(bool verbose = false) const;
601 
603  operator std::string() const { return toString(); }
604 
605 
606 #pragma mark -
607 #pragma mark Position
608 
618  const Vec2& getPosition() const { return _position; }
619 
630  void setPosition(const Vec2 &position) { setPosition(position.x,position.y); }
631 
643  void setPosition(float x, float y);
644 
655  float getPositionX(void) const { return getPosition().x; }
656 
667  void setPositionX(float x) { setPosition(x,getPositionY()); }
668 
679  float getPositionY(void) const { return getPosition().y; }
680 
691  void setPositionY(float y) { setPosition(getPositionX(),y); }
692 
702  return nodeToWorldCoords(_anchor*getContentSize());
703  }
704 
705 
706 #pragma mark -
707 #pragma mark Size
708 
716  const Size& getContentSize() const { return _contentSize; }
717 
731  virtual void setContentSize(const Size& size);
732 
747  virtual void setContentSize(float width, float height) {
748  setContentSize(Size(width, height));
749  }
750 
759  float getContentWidth() const { return getContentSize().width; }
760 
774  void setContentWidth(float width) { setContentSize(width,getContentHeight()); }
775 
784  float getContentHeight() const { return getContentSize().height; }
785 
799  void setContentHeight(float height) { setContentSize(getContentWidth(),height); }
800 
811  Size getSize() const;
812 
823  float getWidth() const { return getSize().width; }
824 
835  float getHeight() const { return getSize().height; }
836 
848  }
849 
850 #pragma mark -
851 #pragma mark Anchors
852 
871  virtual void setAnchor(const Vec2& anchor);
872 
893  void setAnchor(float x, float y) { setAnchor(Vec2(x,y)); }
894 
914  const Vec2& getAnchor() const { return _anchor; }
915 
930  Vec2 getAnchorInPixels() { return _anchor * _contentSize; }
931 
932 
933 #pragma mark -
934 #pragma mark Visibility
935 
946  Color4 getColor() const { return _tintColor; }
947 
959  virtual void setColor(Color4 color) { _tintColor = color; }
960 
971 
981  bool isVisible() const { return _isVisible; }
982 
992  void setVisible(bool visible) { _isVisible = visible; }
993 
1004 
1014  void setRelativeColor(bool flag) { _hasParentColor = flag; }
1015 
1016 
1017 #pragma mark -
1018 #pragma mark Transforms
1019 
1029  const Vec2& getScale() const { return _scale; }
1030 
1041  float getScaleX() const { return _scale.x; }
1042 
1053  float getScaleY() const { return _scale.y; }
1054 
1065  void setScale(float scale) {
1066  _scale.set(scale,scale);
1067  if (!_useTransform) updateTransform();
1068  }
1069 
1080  void setScale(const Vec2& vec) {
1081  _scale = vec;
1082  if (!_useTransform) updateTransform();
1083  }
1084 
1096  void setScale(float sx, float sy) {
1097  _scale.set(sx,sy);
1098  if (!_useTransform) updateTransform();
1099  }
1100 
1110  float getAngle() { return _angle; }
1111 
1121  void setAngle(float angle) {
1122  _angle = angle;
1123  if (!_useTransform) updateTransform();
1124  }
1125 
1141 
1156  void setAlternateTransform(const Mat4& transform) {
1157  _transform = transform;
1158  updateTransform();
1159  }
1160 
1176 
1191  void chooseAlternateTransform(bool active) {
1192  _useTransform = active; updateTransform();
1193  }
1194 
1204  const Mat4& getNodeToParentTransform() const { return _combined; }
1205 
1215  Mat4 getParentToNodeTransform() const { return _combined.getInverse(); }
1216 
1226  Mat4 getNodeToWorldTransform() const;
1227 
1240  }
1241 
1259  Vec2 screenToNodeCoords(const Vec2& screenPoint) const;
1260 
1261 
1273  Vec2 worldToNodeCoords(const Vec2& worldPoint) const {
1274  return getWorldToNodeTransform().transform(worldPoint);
1275  }
1276 
1294  Vec2 nodeToScreenCoords(const Vec2& nodePoint) const;
1295 
1307  Vec2 nodeToWorldCoords(const Vec2& nodePoint) const {
1308  return getNodeToWorldTransform().transform(nodePoint);
1309  }
1310 
1322  Vec2 parentToNodeCoords(const Vec2& parentPoint) const {
1323  return getParentToNodeTransform().transform(parentPoint);
1324  }
1325 
1337  Vec2 nodeToParentCoords(const Vec2& nodePoint) const {
1338  return getNodeToParentTransform().transform(nodePoint);
1339  }
1340 
1341 #pragma mark -
1342 #pragma mark Z-order
1343 
1360  void setZOrder(int z);
1361 
1379  int getZOrder() const { return _zOrder; }
1380 
1398  bool isZDirty() const { return _zDirty; }
1399 
1417  void sortZOrder();
1418 
1419 
1420 #pragma mark -
1421 #pragma mark Scene Graph
1422 
1427  size_t getChildCount() const { return _children.size(); }
1428 
1440  std::shared_ptr<Node> getChild(unsigned int pos);
1441 
1453  const std::shared_ptr<Node>& getChild(unsigned int pos) const;
1454 
1471  template <typename T>
1472  inline std::shared_ptr<T> getChild(unsigned int pos) const {
1473  return std::dynamic_pointer_cast<T>(getChild(pos));
1474  }
1475 
1489  std::shared_ptr<Node> getChildByTag(unsigned int tag) const;
1490 
1509  template <typename T>
1510  inline std::shared_ptr<T> getChildByTag(unsigned int tag) const {
1511  return std::dynamic_pointer_cast<T>(getChildByTag(tag));
1512  }
1513 
1527  std::shared_ptr<Node> getChildByName(const std::string& name) const;
1528 
1547  template <typename T>
1548  inline std::shared_ptr<T> getChildByName(const std::string& name) const {
1549  return std::dynamic_pointer_cast<T>(getChildByName(name));
1550  }
1551 
1557  std::vector<std::shared_ptr<Node>> getChildren() { return _children; }
1558 
1564  const std::vector<std::shared_ptr<Node>>& getChildren() const { return _children; }
1565 
1575  void addChild(std::shared_ptr<Node> child) {
1576  addChild(child,child->_zOrder);
1577  }
1578 
1591  virtual void addChild(const std::shared_ptr<Node>& child, int zval);
1592 
1603  void addChildWithTag(const std::shared_ptr<Node>& child, unsigned int tag) {
1604  addChild(child);
1605  child->setTag(tag);
1606  }
1607 
1621  void addChildWithTag(const std::shared_ptr<Node>& child, unsigned int tag, int zval) {
1622  addChild(child,zval);
1623  child->setTag(tag);
1624  }
1625 
1636  void addChildWithName(const std::shared_ptr<Node>& child, const std::string &name) {
1637  addChild(child);
1638  child->setName(name);
1639  }
1640 
1654  void addChildWithName(const std::shared_ptr<Node>& child, const std::string &name, int zval) {
1655  addChild(child,zval);
1656  child->setName(name);
1657  }
1658 
1672  void swapChild(const std::shared_ptr<Node>& child1, const std::shared_ptr<Node>& child2, bool inherit=false);
1673 
1682  Node* getParent() { return _parent; }
1683 
1692  const Node* getParent() const { return _parent; }
1693 
1702  Scene* getScene() { return _graph; }
1703 
1712  const Scene* getScene() const { return _graph; }
1713 
1719  void removeFromParent() { if (_parent) { _parent->removeChild(_childOffset); } }
1720 
1729  virtual void removeChild(unsigned int pos);
1730 
1741  void removeChild(const std::shared_ptr<Node>& child);
1742 
1754  void removeChildByTag(unsigned int tag);
1755 
1767  void removeChildByName(const std::string &name);
1768 
1772  virtual void removeAllChildren();
1773 
1774 
1775 #pragma mark -
1776 #pragma mark Rendering
1777 
1788  virtual void render(const std::shared_ptr<SpriteBatch>& batch, const Mat4& transform, Color4 tint);
1789 
1799  virtual void render(const std::shared_ptr<SpriteBatch>& batch) {
1801  }
1802 
1826  virtual void draw(const std::shared_ptr<SpriteBatch>& batch, const Mat4& transform, Color4 tint) {}
1827 
1828 
1829 #pragma mark -
1830 #pragma mark Layout Automation
1831 
1842  const std::shared_ptr<Layout>& getLayout() const { return _layout; }
1843 
1858  void setLayout(const std::shared_ptr<Layout>& layout) { _layout = layout; }
1859 
1867  virtual void doLayout();
1868 
1869 private:
1870 #pragma mark -
1871 #pragma mark Internal Helpers
1872 
1889  void setZDirty(bool value);
1890 
1899  void setParent(Node* parent) { _parent = parent; }
1900 
1909  void setScene(Scene* scene) { _graph = scene; }
1910 
1919  void pushScene(Scene* scene);
1920 
1931  static bool compareNodeSibs(const std::shared_ptr<Node>& a, const std::shared_ptr<Node>& b);
1932 
1939  virtual void updateTransform();
1940 
1941  // Copying is only allowed via shared pointer.
1942  CU_DISALLOW_COPY_AND_ASSIGN(Node);
1943 
1944  friend class Scene;
1945 };
1946 
1947 
1948 }
1949 #endif /* __CU_NODE_H__ */
Definition: CUSize.h:57
Vec2 _position
Definition: CUNode.h:101
bool initWithPosition(float x, float y)
Definition: CUNode.h:267
std::vector< std::shared_ptr< Node > > _children
Definition: CUNode.h:162
void setRelativeColor(bool flag)
Definition: CUNode.h:1014
Color4 _tintColor
Definition: CUNode.h:115
Vec2 nodeToScreenCoords(const Vec2 &nodePoint) const
unsigned int getTag() const
Definition: CUNode.h:552
const Mat4 & getNodeToParentTransform() const
Definition: CUNode.h:1204
float x
Definition: CUVec2.h:66
float getHeight() const
Definition: CUNode.h:835
Vec2 screenToNodeCoords(const Vec2 &screenPoint) const
static std::shared_ptr< Node > allocWithPosition(const Vec2 &pos)
Definition: CUNode.h:409
float y
Definition: CUVec2.h:68
static Vec2 * transform(const Mat4 &mat, const Vec2 &point, Vec2 *dst)
const Node * getParent() const
Definition: CUNode.h:1692
void addChildWithName(const std::shared_ptr< Node > &child, const std::string &name)
Definition: CUNode.h:1636
void setPosition(const Vec2 &position)
Definition: CUNode.h:630
Definition: CUVec2.h:61
Vec2 nodeToParentCoords(const Vec2 &nodePoint) const
Definition: CUNode.h:1337
size_t getChildCount() const
Definition: CUNode.h:1427
float _angle
Definition: CUNode.h:137
float getAngle()
Definition: CUNode.h:1110
float getPositionY(void) const
Definition: CUNode.h:679
bool _hasParentColor
Definition: CUNode.h:117
Node * _parent
Definition: CUNode.h:165
Vec2 _scale
Definition: CUNode.h:127
virtual bool initWithBounds(const Size &size)
Definition: CUNode.h:92
virtual void render(const std::shared_ptr< SpriteBatch > &batch, const Mat4 &transform, Color4 tint)
std::shared_ptr< Node > getChildByTag(unsigned int tag) const
virtual void setContentSize(const Size &size)
Size getSize() const
virtual void draw(const std::shared_ptr< SpriteBatch > &batch, const Mat4 &transform, Color4 tint)
Definition: CUNode.h:1826
void removeChildByTag(unsigned int tag)
Mat4 getNodeToWorldTransform() const
static std::shared_ptr< Node > allocWithBounds(const Rect &rect)
Definition: CUNode.h:480
std::shared_ptr< Node > getChildByName(const std::string &name) const
void setPositionY(float y)
Definition: CUNode.h:691
int _zOrder
Definition: CUNode.h:199
virtual bool initWithData(const SceneLoader *loader, const std::shared_ptr< JsonValue > data)
Mat4 _combined
Definition: CUNode.h:159
virtual void removeChild(unsigned int pos)
Vec2 getWorldPosition() const
Definition: CUNode.h:701
bool hasRelativeColor()
Definition: CUNode.h:1003
void setZOrder(int z)
void setScale(const Vec2 &vec)
Definition: CUNode.h:1080
virtual std::string toString(bool verbose=false) const
void setPositionX(float x)
Definition: CUNode.h:667
void addChildWithTag(const std::shared_ptr< Node > &child, unsigned int tag, int zval)
Definition: CUNode.h:1621
float getScaleX() const
Definition: CUNode.h:1041
bool _zDirty
Definition: CUNode.h:201
Vec2 worldToNodeCoords(const Vec2 &worldPoint) const
Definition: CUNode.h:1273
bool initWithBounds(float x, float y, float width, float height)
Definition: CUNode.h:337
Vec2 getAnchorInPixels()
Definition: CUNode.h:930
virtual void setAnchor(const Vec2 &anchor)
bool isVisible() const
Definition: CUNode.h:981
void sortZOrder()
static const Color4 WHITE
Definition: CUColor4.h:1106
unsigned int _tag
Definition: CUNode.h:181
const Vec2 & getPosition() const
Definition: CUNode.h:618
void setContentHeight(float height)
Definition: CUNode.h:799
void setAnchor(float x, float y)
Definition: CUNode.h:893
void setContentWidth(float width)
Definition: CUNode.h:774
float width
Definition: CUSize.h:61
bool isZDirty() const
Definition: CUNode.h:1398
Vec2 nodeToWorldCoords(const Vec2 &nodePoint) const
Definition: CUNode.h:1307
void setTag(unsigned int tag)
Definition: CUNode.h:563
~Node()
Definition: CUNode.h:219
static std::shared_ptr< Node > allocWithBounds(float x, float y, float width, float height)
Definition: CUNode.h:503
const Size & getContentSize() const
Definition: CUNode.h:716
Mat4 getInverse() const
Definition: CUMat4.h:1056
void addChild(std::shared_ptr< Node > child)
Definition: CUNode.h:1575
void setLayout(const std::shared_ptr< Layout > &layout)
Definition: CUNode.h:1858
Mat4 getWorldToNodeTransform() const
Definition: CUNode.h:1238
Scene * _graph
Definition: CUNode.h:167
void setAngle(float angle)
Definition: CUNode.h:1121
float getWidth() const
Definition: CUNode.h:823
const std::string & getName() const
Definition: CUNode.h:574
Color4 getAbsoluteColor()
void setAlternateTransform(const Mat4 &transform)
Definition: CUNode.h:1156
void addChildWithName(const std::shared_ptr< Node > &child, const std::string &name, int zval)
Definition: CUNode.h:1654
float height
Definition: CUSize.h:63
const std::shared_ptr< Layout > & getLayout() const
Definition: CUNode.h:1842
Vec2 _anchor
Definition: CUNode.h:109
void chooseAlternateTransform(bool active)
Definition: CUNode.h:1191
static std::shared_ptr< Node > allocWithPosition(float x, float y)
Definition: CUNode.h:425
void addChildWithTag(const std::shared_ptr< Node > &child, unsigned int tag)
Definition: CUNode.h:1603
std::vector< std::shared_ptr< Node > > getChildren()
Definition: CUNode.h:1557
const Vec2 & getAnchor() const
Definition: CUNode.h:914
int _childOffset
Definition: CUNode.h:172
virtual void setColor(Color4 color)
Definition: CUNode.h:959
float getScaleY() const
Definition: CUNode.h:1053
std::shared_ptr< Node > getChild(unsigned int pos)
void setName(const std::string &name)
Definition: CUNode.h:585
Mat4 _transform
Definition: CUNode.h:147
Definition: CURect.h:45
static const Mat4 IDENTITY
Definition: CUMat4.h:114
Vec2 parentToNodeCoords(const Vec2 &parentPoint) const
Definition: CUNode.h:1322
static std::shared_ptr< Node > alloc()
Definition: CUNode.h:394
void removeFromParent()
Definition: CUNode.h:1719
const Vec2 & getScale() const
Definition: CUNode.h:1029
Definition: CUSceneLoader.h:77
Mat4 getParentToNodeTransform() const
Definition: CUNode.h:1215
const Mat4 & getAlternateTransform()
Definition: CUNode.h:1140
float getContentHeight() const
Definition: CUNode.h:784
void setScale(float scale)
Definition: CUNode.h:1065
void removeChildByName(const std::string &name)
virtual void dispose()
static std::shared_ptr< Node > allocWithBounds(const Size &size)
Definition: CUNode.h:442
Scene * getScene()
Definition: CUNode.h:1702
virtual Node * copy(Node *dst)
void swapChild(const std::shared_ptr< Node > &child1, const std::shared_ptr< Node > &child2, bool inherit=false)
std::shared_ptr< T > getChildByName(const std::string &name) const
Definition: CUNode.h:1548
static std::shared_ptr< Node > allocWithData(const SceneLoader *loader, const std::shared_ptr< JsonValue > data)
Definition: CUNode.h:535
float getContentWidth() const
Definition: CUNode.h:759
std::string _name
Definition: CUNode.h:189
float getPositionX(void) const
Definition: CUNode.h:655
virtual void removeAllChildren()
Node * getParent()
Definition: CUNode.h:1682
const Scene * getScene() const
Definition: CUNode.h:1712
virtual void doLayout()
bool _useTransform
Definition: CUNode.h:150
virtual void setContentSize(float width, float height)
Definition: CUNode.h:747
Definition: CUColor4.h:1084
Size _contentSize
Definition: CUNode.h:112
Rect getBoundingBox() const
Definition: CUNode.h:846
static std::shared_ptr< Node > allocWithBounds(float width, float height)
Definition: CUNode.h:460
Color4 getColor() const
Definition: CUNode.h:946
std::shared_ptr< T > getChild(unsigned int pos) const
Definition: CUNode.h:1472
bool initWithBounds(float width, float height)
Definition: CUNode.h:298
Vec2 & set(float x, float y)
Definition: CUVec2.h:153
Definition: CUAction.h:51
bool withAlternateTransform()
Definition: CUNode.h:1175
virtual bool initWithPosition(const Vec2 &pos)
virtual void render(const std::shared_ptr< SpriteBatch > &batch)
Definition: CUNode.h:1799
static const Vec2 ZERO
Definition: CUVec2.h:71
Definition: CUScene.h:65
void setScale(float sx, float sy)
Definition: CUNode.h:1096
Definition: CUMat4.h:92
virtual bool init()
Definition: CUNode.h:239
void setVisible(bool visible)
Definition: CUNode.h:992
const std::vector< std::shared_ptr< Node > > & getChildren() const
Definition: CUNode.h:1564
std::shared_ptr< T > getChildByTag(unsigned int tag) const
Definition: CUNode.h:1510
int getZOrder() const
Definition: CUNode.h:1379
bool _isVisible
Definition: CUNode.h:119
size_t _hashOfName
Definition: CUNode.h:196
std::shared_ptr< Layout > _layout
Definition: CUNode.h:169