1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "Layer.h" 21 22 #include "Model/Brush.h" 23 #include "Model/Group.h" 24 #include "Model/Entity.h" 25 #include "Model/IssueGenerator.h" 26 #include "Model/NodeVisitor.h" 27 28 namespace TrenchBroom { 29 namespace Model { Layer(const String & name,const BBox3 & worldBounds)30 Layer::Layer(const String& name, const BBox3& worldBounds) : 31 m_name(name), 32 m_octree(worldBounds, static_cast<FloatType>(64.0f)) {} 33 setName(const String & name)34 void Layer::setName(const String& name) { 35 m_name = name; 36 } 37 doGetName() const38 const String& Layer::doGetName() const { 39 return m_name; 40 } 41 doGetBounds() const42 const BBox3& Layer::doGetBounds() const { 43 return m_octree.bounds(); 44 } 45 doClone(const BBox3 & worldBounds) const46 Node* Layer::doClone(const BBox3& worldBounds) const { 47 Layer* layer = new Layer(m_name, worldBounds); 48 cloneAttributes(layer); 49 layer->addChildren(clone(worldBounds, children())); 50 return layer; 51 } 52 53 class CanAddChildToLayer : public ConstNodeVisitor, public NodeQuery<bool> { 54 private: doVisit(const World * world)55 void doVisit(const World* world) { setResult(false); } doVisit(const Layer * layer)56 void doVisit(const Layer* layer) { setResult(false); } doVisit(const Group * group)57 void doVisit(const Group* group) { setResult(true); } doVisit(const Entity * entity)58 void doVisit(const Entity* entity) { setResult(true); } doVisit(const Brush * brush)59 void doVisit(const Brush* brush) { setResult(true); } 60 }; 61 doCanAddChild(const Node * child) const62 bool Layer::doCanAddChild(const Node* child) const { 63 CanAddChildToLayer visitor; 64 child->accept(visitor); 65 return visitor.result(); 66 } 67 doCanRemoveChild(const Node * child) const68 bool Layer::doCanRemoveChild(const Node* child) const { 69 return true; 70 } 71 doRemoveIfEmpty() const72 bool Layer::doRemoveIfEmpty() const { 73 return false; 74 } 75 76 class Layer::AddNodeToOctree : public NodeVisitor { 77 private: 78 NodeTree& m_octree; 79 public: AddNodeToOctree(NodeTree & octree)80 AddNodeToOctree(NodeTree& octree) : 81 m_octree(octree) {} 82 private: doVisit(World * world)83 void doVisit(World* world) {} doVisit(Layer * layer)84 void doVisit(Layer* layer) {} doVisit(Group * group)85 void doVisit(Group* group) { m_octree.addObject(group->bounds(), group); } doVisit(Entity * entity)86 void doVisit(Entity* entity) { m_octree.addObject(entity->bounds(), entity); } doVisit(Brush * brush)87 void doVisit(Brush* brush) { m_octree.addObject(brush->bounds(), brush); } 88 }; 89 90 class Layer::RemoveNodeFromOctree : public NodeVisitor { 91 private: 92 NodeTree& m_octree; 93 public: RemoveNodeFromOctree(NodeTree & octree)94 RemoveNodeFromOctree(NodeTree& octree) : 95 m_octree(octree) {} 96 private: doVisit(World * world)97 void doVisit(World* world) {} doVisit(Layer * layer)98 void doVisit(Layer* layer) {} doVisit(Group * group)99 void doVisit(Group* group) { m_octree.removeObject(group); } doVisit(Entity * entity)100 void doVisit(Entity* entity) { m_octree.removeObject(entity); } doVisit(Brush * brush)101 void doVisit(Brush* brush) { m_octree.removeObject(brush); } 102 }; 103 104 class Layer::UpdateNodeInOctree : public NodeVisitor { 105 private: 106 NodeTree& m_octree; 107 public: UpdateNodeInOctree(NodeTree & octree)108 UpdateNodeInOctree(NodeTree& octree) : 109 m_octree(octree) {} 110 private: doVisit(World * world)111 void doVisit(World* world) {} doVisit(Layer * layer)112 void doVisit(Layer* layer) {} doVisit(Group * group)113 void doVisit(Group* group) { m_octree.updateObject(group->bounds(), group); } doVisit(Entity * entity)114 void doVisit(Entity* entity) { m_octree.updateObject(entity->bounds(), entity); } doVisit(Brush * brush)115 void doVisit(Brush* brush) { m_octree.updateObject(brush->bounds(), brush); } 116 }; 117 doChildWasAdded(Node * node)118 void Layer::doChildWasAdded(Node* node) { 119 AddNodeToOctree visitor(m_octree); 120 node->accept(visitor); 121 } 122 doChildWillBeRemoved(Node * node)123 void Layer::doChildWillBeRemoved(Node* node) { 124 RemoveNodeFromOctree visitor(m_octree); 125 node->accept(visitor); 126 } 127 doChildBoundsDidChange(Node * node)128 void Layer::doChildBoundsDidChange(Node* node) { 129 UpdateNodeInOctree visitor(m_octree); 130 node->accept(visitor); 131 } 132 doSelectable() const133 bool Layer::doSelectable() const { 134 return false; 135 } 136 doGenerateIssues(const IssueGenerator * generator,IssueList & issues)137 void Layer::doGenerateIssues(const IssueGenerator* generator, IssueList& issues) { 138 generator->generate(this, issues); 139 } 140 doAccept(NodeVisitor & visitor)141 void Layer::doAccept(NodeVisitor& visitor) { 142 visitor.visit(this); 143 } 144 doAccept(ConstNodeVisitor & visitor) const145 void Layer::doAccept(ConstNodeVisitor& visitor) const { 146 visitor.visit(this); 147 } 148 doPick(const Ray3 & ray,PickResult & pickResult) const149 void Layer::doPick(const Ray3& ray, PickResult& pickResult) const { 150 const Model::NodeList candidates = m_octree.findObjects(ray); 151 NodeList::const_iterator it, end; 152 for (it = candidates.begin(), end = candidates.end(); it != end; ++it) { 153 const Node* node = *it; 154 node->pick(ray, pickResult); 155 } 156 } 157 doFindNodesContaining(const Vec3 & point,NodeList & result)158 void Layer::doFindNodesContaining(const Vec3& point, NodeList& result) { 159 const Model::NodeList candidates = m_octree.findObjects(point); 160 NodeList::const_iterator it, end; 161 for (it = candidates.begin(), end = candidates.end(); it != end; ++it) { 162 Node* node = *it; 163 node->findNodesContaining(point, result); 164 } 165 } 166 doIntersectWithRay(const Ray3 & ray) const167 FloatType Layer::doIntersectWithRay(const Ray3& ray) const { 168 return Math::nan<FloatType>(); 169 } 170 } 171 } 172