2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined (INCLUDED_SCENELIB_H)
23 #define INCLUDED_SCENELIB_H
25 #include "iscenegraph.h"
26 #include "iselection.h"
32 #include "math/aabb.h"
33 #include "transformlib.h"
34 #include "generic/callback.h"
35 #include "generic/reference.h"
36 #include "container/stack.h"
37 #include "typesystem.h"
42 template<typename Element> class BasicVector3;
43 typedef BasicVector3<float> Vector3;
44 template<typename Element> class BasicVector4;
45 typedef BasicVector4<float> Vector4;
47 typedef Vector4 Quaternion;
50 class ComponentSelectionTestable
53 STRING_CONSTANT(Name, "ComponentSelectionTestable");
55 virtual bool isSelectedComponents() const = 0;
56 virtual void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) = 0;
57 virtual void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) = 0;
60 class ComponentEditable
63 STRING_CONSTANT(Name, "ComponentEditable");
65 virtual const AABB& getSelectedComponentsBounds() const = 0;
68 class ComponentSnappable
71 STRING_CONSTANT(Name, "ComponentSnappable");
73 virtual void snapComponents(float snap) = 0;
79 STRING_CONSTANT(Name, "Bounded");
81 virtual const AABB& localAABB() const = 0;
87 STRING_CONSTANT(Name, "BrushDoom3");
89 virtual void setDoom3GroupOrigin(const Vector3& origin) = 0;
95 typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;
97 template<typename Type>
98 class NodeType : public StaticTypeSystemInitialiser
102 typedef typename Type::Name Name;
103 NodeType() : m_typeId(NODETYPEID_NONE)
105 StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
109 m_typeId = GlobalSceneGraph().getNodeTypeId(Name());
111 typedef MemberCaller<NodeType<Type>, &NodeType<Type>::initialise> InitialiseCaller;
115 ASSERT_MESSAGE(m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted(Name()) << " used before being initialised");
121 template<typename Type>
125 enum unnamed0 { SIZE = NODETYPEID_MAX };
126 static TypeId getTypeId()
128 return Static< NodeType<Type> >::instance().getTypeId();
132 template<typename Type, typename Base>
133 class NodeStaticCast :
134 public CastInstaller<
135 StaticNodeType<Base>,
136 StaticCast<Type, Base>
141 template<typename Type, typename Contained>
142 class NodeContainedCast :
143 public CastInstaller<
144 StaticNodeType<Contained>,
145 ContainedCast<Type, Contained>
150 template<typename Type>
151 class NodeIdentityCast :
152 public CastInstaller<
153 StaticNodeType<Type>,
164 enum unnamed0 { eVisible = 0 };
165 enum unnamed1 { eHidden = 1 << 0 };
166 enum unnamed2 { eFiltered = 1 << 1 };
167 enum unnamed3 { eExcluded = 1 << 2 };
172 virtual void release() = 0;
176 unsigned int m_state;
177 std::size_t m_refcount;
180 NodeTypeCastTable& m_casts;
190 Node(Symbiot* symbiot, void* node, NodeTypeCastTable& casts) :
205 ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount");
210 ASSERT_MESSAGE(m_refcount < (1 << 24), "Node::decref: uninitialised refcount");
211 if(--m_refcount == 0)
213 m_symbiot->release();
216 std::size_t getReferenceCount() const
221 void* cast(TypeId typeId) const
223 return m_casts.cast(typeId, m_node);
226 void enable(unsigned int state)
230 void disable(unsigned int state)
236 return m_state == eVisible;
240 return (m_state & eExcluded) != 0;
244 class NullNode : public Node::Symbiot
246 NodeTypeCastTable m_casts;
249 NullNode() : m_node(this, 0, m_casts)
263 template<typename Type>
267 static Type* cast(scene::Node& node)
269 return static_cast<Type*>(node.cast(StaticNodeType<Type>::getTypeId()));
271 static const Type* cast(const scene::Node& node)
273 return static_cast<const Type*>(node.cast(StaticNodeType<Type>::getTypeId()));
278 inline scene::Instantiable* Node_getInstantiable(scene::Node& node)
280 return NodeTypeCast<scene::Instantiable>::cast(node);
283 inline scene::Traversable* Node_getTraversable(scene::Node& node)
285 return NodeTypeCast<scene::Traversable>::cast(node);
288 inline void Node_traverseSubgraph(scene::Node& node, const scene::Traversable::Walker& walker)
292 scene::Traversable* traversable = Node_getTraversable(node);
295 traversable->traverse(walker);
301 inline TransformNode* Node_getTransformNode(scene::Node& node)
303 return NodeTypeCast<TransformNode>::cast(node);
306 inline bool operator<(scene::Node& node, scene::Node& other)
308 return &node < &other;
310 inline bool operator==(scene::Node& node, scene::Node& other)
312 return &node == &other;
314 inline bool operator!=(scene::Node& node, scene::Node& other)
316 return !::operator==(node, other);
320 inline scene::Node& NewNullNode()
322 return (new scene::NullNode)->node();
325 inline void Path_deleteTop(const scene::Path& path)
327 Node_getTraversable(path.parent())->erase(path.top());
334 class delete_all : public scene::Traversable::Walker
336 scene::Node& m_parent;
338 delete_all(scene::Node& parent) : m_parent(parent)
341 bool pre(scene::Node& node) const
345 void post(scene::Node& node) const
347 Node_getTraversable(m_parent)->erase(node);
351 inline void DeleteSubgraph(scene::Node& subgraph)
353 Node_getTraversable(subgraph)->traverse(delete_all(subgraph));
357 class EntityUndefined
360 STRING_CONSTANT(Name, "Entity");
363 inline bool Node_isEntity(scene::Node& node)
365 return NodeTypeCast<EntityUndefined>::cast(node) != 0;
368 template<typename Functor>
369 class EntityWalker : public scene::Graph::Walker
371 const Functor& functor;
373 EntityWalker(const Functor& functor) : functor(functor)
376 bool pre(const scene::Path& path, scene::Instance& instance) const
378 if(Node_isEntity(path.top()))
387 template<typename Functor>
388 inline const Functor& Scene_forEachEntity(const Functor& functor)
390 GlobalSceneGraph().traverse(EntityWalker<Functor>(functor));
397 STRING_CONSTANT(Name, "Brush");
400 inline bool Node_isBrush(scene::Node& node)
402 return NodeTypeCast<BrushUndefined>::cast(node) != 0;
408 STRING_CONSTANT(Name, "Patch");
411 inline bool Node_isPatch(scene::Node& node)
413 return NodeTypeCast<PatchUndefined>::cast(node) != 0;
416 inline bool Node_isPrimitive(scene::Node& node)
419 return Node_isBrush(node) || Node_isPatch(node);
421 return !node.isRoot();
425 class ParentBrushes : public scene::Traversable::Walker
427 scene::Node& m_parent;
429 ParentBrushes(scene::Node& parent)
433 bool pre(scene::Node& node) const
437 void post(scene::Node& node) const
439 if(Node_isPrimitive(node))
441 Node_getTraversable(m_parent)->insert(node);
446 inline void parentBrushes(scene::Node& subgraph, scene::Node& parent)
448 Node_getTraversable(subgraph)->traverse(ParentBrushes(parent));
451 class HasBrushes : public scene::Traversable::Walker
455 HasBrushes(bool& hasBrushes)
456 : m_hasBrushes(hasBrushes)
460 bool pre(scene::Node& node) const
462 if(!Node_isPrimitive(node))
464 m_hasBrushes = false;
470 inline bool node_is_group(scene::Node& node)
472 scene::Traversable* traversable = Node_getTraversable(node);
475 bool hasBrushes = false;
476 traversable->traverse(HasBrushes(hasBrushes));
482 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
484 template<typename Type>
485 class InstanceType : public StaticTypeSystemInitialiser
489 typedef typename Type::Name Name;
490 InstanceType() : m_typeId(INSTANCETYPEID_NONE)
492 StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
496 m_typeId = GlobalSceneGraph().getInstanceTypeId(Name());
498 typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
502 ASSERT_MESSAGE(m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted(Name()) << " used before being initialised");
508 template<typename Type>
509 class StaticInstanceType
512 enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
513 static TypeId getTypeId()
515 return Static< InstanceType<Type> >::instance().getTypeId();
519 template<typename Type, typename Base>
520 class InstanceStaticCast :
521 public CastInstaller<
522 StaticInstanceType<Base>,
523 StaticCast<Type, Base>
528 template<typename Type, typename Contained>
529 class InstanceContainedCast :
530 public CastInstaller<
531 StaticInstanceType<Contained>,
532 ContainedCast<Type, Contained>
537 template<typename Type>
538 class InstanceIdentityCast :
539 public CastInstaller<
540 StaticInstanceType<Type>,
547 inline Selectable* Instance_getSelectable(scene::Instance& instance);
548 inline const Selectable* Instance_getSelectable(const scene::Instance& instance);
550 inline Bounded* Instance_getBounded(scene::Instance& instance);
551 inline const Bounded* Instance_getBounded(const scene::Instance& instance);
557 class AABBAccumulateWalker : public scene::Graph::Walker
560 mutable std::size_t m_depth;
562 AABBAccumulateWalker(AABB& aabb) : m_aabb(aabb), m_depth(0)
565 bool pre(const scene::Path& path, scene::Instance& instance) const
569 aabb_extend_by_aabb_safe(m_aabb, instance.worldAABB());
571 return ++m_depth != 2;
573 void post(const scene::Path& path, scene::Instance& instance) const
580 class TransformChangedWalker : public scene::Graph::Walker
583 bool pre(const scene::Path& path, scene::Instance& instance) const
585 instance.transformChangedLocal();
590 class ParentSelectedChangedWalker : public scene::Graph::Walker
593 bool pre(const scene::Path& path, scene::Instance& instance) const
595 instance.parentSelectedChanged();
600 class ChildSelectedWalker : public scene::Graph::Walker
602 bool& m_childSelected;
603 mutable std::size_t m_depth;
605 ChildSelectedWalker(bool& childSelected) : m_childSelected(childSelected), m_depth(0)
607 m_childSelected = false;
609 bool pre(const scene::Path& path, scene::Instance& instance) const
611 if(m_depth == 1 && !m_childSelected)
613 m_childSelected = instance.isSelected() || instance.childSelected();
615 return ++m_depth != 2;
617 void post(const scene::Path& path, scene::Instance& instance) const
626 InstanceTypeCastTable& m_casts;
628 mutable Matrix4 m_local2world;
629 mutable AABB m_bounds;
630 mutable AABB m_childBounds;
631 mutable bool m_transformChanged;
632 mutable bool m_transformMutex;
633 mutable bool m_boundsChanged;
634 mutable bool m_boundsMutex;
635 mutable bool m_childBoundsChanged;
636 mutable bool m_childBoundsMutex;
637 mutable bool m_isSelected;
638 mutable bool m_isSelectedChanged;
639 mutable bool m_childSelected;
640 mutable bool m_childSelectedChanged;
641 mutable bool m_parentSelected;
642 mutable bool m_parentSelectedChanged;
643 Callback m_childSelectedChangedCallback;
644 Callback m_transformChangedCallback;
647 void evaluateTransform() const
649 if(m_transformChanged)
651 ASSERT_MESSAGE(!m_transformMutex, "re-entering transform evaluation");
652 m_transformMutex = true;
654 m_local2world = (m_parent != 0) ? m_parent->localToWorld() : g_matrix4_identity;
655 TransformNode* transformNode = Node_getTransformNode(m_path.top());
656 if(transformNode != 0)
658 matrix4_multiply_by_matrix4(m_local2world, transformNode->localToParent());
661 m_transformMutex = false;
662 m_transformChanged = false;
665 void evaluateChildBounds() const
667 if(m_childBoundsChanged)
669 ASSERT_MESSAGE(!m_childBoundsMutex, "re-entering bounds evaluation");
670 m_childBoundsMutex = true;
672 m_childBounds = AABB();
674 GlobalSceneGraph().traverse_subgraph(AABBAccumulateWalker(m_childBounds), m_path);
676 m_childBoundsMutex = false;
677 m_childBoundsChanged = false;
680 void evaluateBounds() const
684 ASSERT_MESSAGE(!m_boundsMutex, "re-entering bounds evaluation");
685 m_boundsMutex = true;
687 m_bounds = childBounds();
689 const Bounded* bounded = Instance_getBounded(*this);
692 aabb_extend_by_aabb_safe(
694 aabb_for_oriented_aabb_safe(bounded->localAABB(), localToWorld())
698 m_boundsMutex = false;
699 m_boundsChanged = false;
703 Instance(const scene::Instance& other);
704 Instance& operator=(const scene::Instance& other);
707 Instance(const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts) :
710 m_instance(instance),
712 m_local2world(g_matrix4_identity),
713 m_transformChanged(true),
714 m_transformMutex(false),
715 m_boundsChanged(true),
716 m_boundsMutex(false),
717 m_childBoundsChanged(true),
718 m_childBoundsMutex(false),
719 m_isSelectedChanged(true),
720 m_childSelectedChanged(true),
721 m_parentSelectedChanged(true)
723 ASSERT_MESSAGE((parent == 0) == (path.size() == 1), "instance has invalid parent");
729 const scene::Path& path() const
734 void* cast(TypeId typeId) const
736 return m_casts.cast(typeId, m_instance);
739 const Matrix4& localToWorld() const
742 return m_local2world;
744 void transformChangedLocal()
746 ASSERT_NOTNULL(m_parent);
747 m_transformChanged = true;
748 m_boundsChanged = true;
749 m_childBoundsChanged = true;
750 m_transformChangedCallback();
752 void transformChanged()
754 GlobalSceneGraph().traverse_subgraph(TransformChangedWalker(), m_path);
757 void setTransformChangedCallback(const Callback& callback)
759 m_transformChangedCallback = callback;
763 const AABB& worldAABB() const
768 const AABB& childBounds() const
770 evaluateChildBounds();
771 return m_childBounds;
775 m_boundsChanged = true;
776 m_childBoundsChanged = true;
779 m_parent->boundsChanged();
781 GlobalSceneGraph().boundsChanged();
784 void childSelectedChanged()
786 m_childSelectedChanged = true;
787 m_childSelectedChangedCallback();
790 m_parent->childSelectedChanged();
793 bool childSelected() const
795 if(m_childSelectedChanged)
797 m_childSelectedChanged = false;
798 GlobalSceneGraph().traverse_subgraph(ChildSelectedWalker(m_childSelected), m_path);
800 return m_childSelected;
803 void setChildSelectedChangedCallback(const Callback& callback)
805 m_childSelectedChangedCallback = callback;
807 void selectedChanged()
809 m_isSelectedChanged = true;
812 m_parent->childSelectedChanged();
814 GlobalSceneGraph().traverse_subgraph(ParentSelectedChangedWalker(), m_path);
816 bool isSelected() const
818 if(m_isSelectedChanged)
820 m_isSelectedChanged = false;
821 const Selectable* selectable = Instance_getSelectable(*this);
822 m_isSelected = selectable != 0 && selectable->isSelected();
827 void parentSelectedChanged()
829 m_parentSelectedChanged = true;
831 bool parentSelected() const
833 if(m_parentSelectedChanged)
835 m_parentSelectedChanged = false;
836 m_parentSelected = m_parent != 0 && (m_parent->isSelected() || m_parent->parentSelected());
838 return m_parentSelected;
843 template<typename Type>
844 class InstanceTypeCast
847 static Type* cast(scene::Instance& instance)
849 return static_cast<Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
851 static const Type* cast(const scene::Instance& instance)
853 return static_cast<const Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
857 template<typename Functor>
858 class InstanceWalker : public scene::Graph::Walker
860 const Functor& m_functor;
862 InstanceWalker(const Functor& functor) : m_functor(functor)
865 bool pre(const scene::Path& path, scene::Instance& instance) const
872 template<typename Functor>
873 class ChildInstanceWalker : public scene::Graph::Walker
875 const Functor& m_functor;
876 mutable std::size_t m_depth;
878 ChildInstanceWalker(const Functor& functor) : m_functor(functor), m_depth(0)
881 bool pre(const scene::Path& path, scene::Instance& instance) const
887 return ++m_depth != 2;
889 void post(const scene::Path& path, scene::Instance& instance) const
895 template<typename Type, typename Functor>
896 class InstanceApply : public Functor
899 InstanceApply(const Functor& functor) : Functor(functor)
902 void operator()(scene::Instance& instance) const
904 Type* result = InstanceTypeCast<Type>::cast(instance);
907 Functor::operator()(*result);
912 inline Selectable* Instance_getSelectable(scene::Instance& instance)
914 return InstanceTypeCast<Selectable>::cast(instance);
916 inline const Selectable* Instance_getSelectable(const scene::Instance& instance)
918 return InstanceTypeCast<Selectable>::cast(instance);
921 template<typename Functor>
922 inline void Scene_forEachChildSelectable(const Functor& functor, const scene::Path& path)
924 GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Selectable, Functor> >(functor), path);
927 class SelectableSetSelected
931 SelectableSetSelected(bool selected) : m_selected(selected)
934 void operator()(Selectable& selectable) const
936 selectable.setSelected(m_selected);
940 inline Bounded* Instance_getBounded(scene::Instance& instance)
942 return InstanceTypeCast<Bounded>::cast(instance);
944 inline const Bounded* Instance_getBounded(const scene::Instance& instance)
946 return InstanceTypeCast<Bounded>::cast(instance);
949 inline Transformable* Instance_getTransformable(scene::Instance& instance)
951 return InstanceTypeCast<Transformable>::cast(instance);
953 inline const Transformable* Instance_getTransformable(const scene::Instance& instance)
955 return InstanceTypeCast<Transformable>::cast(instance);
959 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable(scene::Instance& instance)
961 return InstanceTypeCast<ComponentSelectionTestable>::cast(instance);
964 inline ComponentEditable* Instance_getComponentEditable(scene::Instance& instance)
966 return InstanceTypeCast<ComponentEditable>::cast(instance);
969 inline ComponentSnappable* Instance_getComponentSnappable(scene::Instance& instance)
971 return InstanceTypeCast<ComponentSnappable>::cast(instance);
975 inline void Instance_setSelected(scene::Instance& instance, bool selected)
977 Selectable* selectable = Instance_getSelectable(instance);
980 selectable->setSelected(selected);
984 inline bool Instance_isSelected(scene::Instance& instance)
986 Selectable* selectable = Instance_getSelectable(instance);
989 return selectable->isSelected();
994 inline scene::Instance& findInstance(const scene::Path& path)
996 scene::Instance* instance = GlobalSceneGraph().find(path);
997 ASSERT_MESSAGE(instance != 0, "findInstance: path not found in scene-graph");
1001 inline void selectPath(const scene::Path& path, bool selected)
1003 Instance_setSelected(findInstance(path), selected);
1006 class SelectChildren : public scene::Traversable::Walker
1008 mutable scene::Path m_path;
1010 SelectChildren(const scene::Path& root)
1014 bool pre(scene::Node& node) const
1016 m_path.push(makeReference(node));
1017 selectPath(m_path, true);
1020 void post(scene::Node& node) const
1026 inline void Entity_setSelected(scene::Instance& entity, bool selected)
1028 scene::Node& node = entity.path().top();
1029 if(node_is_group(node))
1031 Node_getTraversable(node)->traverse(SelectChildren(entity.path()));
1035 Instance_setSelected(entity, selected);
1039 inline bool Entity_isSelected(scene::Instance& entity)
1041 if(node_is_group(entity.path().top()))
1043 return entity.childSelected();
1045 return Instance_isSelected(entity);
1050 class InstanceCounter
1053 unsigned int m_count;
1054 InstanceCounter() : m_count(0)
1063 virtual void increment() = 0;
1064 virtual void decrement() = 0;
1067 #include "generic/callback.h"
1069 class SimpleCounter : public Counter
1071 Callback m_countChanged;
1072 std::size_t m_count;
1074 void setCountChangedCallback(const Callback& countChanged)
1076 m_countChanged = countChanged;
1088 std::size_t get() const
1095 template<typename Contained>
1096 class ConstReference;
1097 typedef ConstReference<scene::Path> PathConstReference;
1099 #include "generic/referencecounted.h"
1100 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;