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;
371 STRING_CONSTANT(Name, "Brush");
374 inline bool Node_isBrush(scene::Node& node)
376 return NodeTypeCast<BrushUndefined>::cast(node) != 0;
382 STRING_CONSTANT(Name, "Patch");
385 inline bool Node_isPatch(scene::Node& node)
387 return NodeTypeCast<PatchUndefined>::cast(node) != 0;
390 inline bool Node_isPrimitive(scene::Node& node)
393 return Node_isBrush(node) || Node_isPatch(node);
395 return !node.isRoot();
399 class ParentBrushes : public scene::Traversable::Walker
401 scene::Node& m_parent;
403 ParentBrushes(scene::Node& parent)
407 bool pre(scene::Node& node) const
411 void post(scene::Node& node) const
413 if(Node_isPrimitive(node))
415 Node_getTraversable(m_parent)->insert(node);
420 inline void parentBrushes(scene::Node& subgraph, scene::Node& parent)
422 Node_getTraversable(subgraph)->traverse(ParentBrushes(parent));
425 class HasBrushes : public scene::Traversable::Walker
429 HasBrushes(bool& hasBrushes)
430 : m_hasBrushes(hasBrushes)
434 bool pre(scene::Node& node) const
436 if(!Node_isPrimitive(node))
438 m_hasBrushes = false;
444 inline bool node_is_group(scene::Node& node)
446 scene::Traversable* traversable = Node_getTraversable(node);
449 bool hasBrushes = false;
450 traversable->traverse(HasBrushes(hasBrushes));
456 typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;
458 template<typename Type>
459 class InstanceType : public StaticTypeSystemInitialiser
463 typedef typename Type::Name Name;
464 InstanceType() : m_typeId(INSTANCETYPEID_NONE)
466 StaticTypeSystemInitialiser::instance().addInitialiser(InitialiseCaller(*this));
470 m_typeId = GlobalSceneGraph().getInstanceTypeId(Name());
472 typedef MemberCaller<InstanceType<Type>, &InstanceType<Type>::initialise> InitialiseCaller;
476 ASSERT_MESSAGE(m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted(Name()) << " used before being initialised");
482 template<typename Type>
483 class StaticInstanceType
486 enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
487 static TypeId getTypeId()
489 return Static< InstanceType<Type> >::instance().getTypeId();
493 template<typename Type, typename Base>
494 class InstanceStaticCast :
495 public CastInstaller<
496 StaticInstanceType<Base>,
497 StaticCast<Type, Base>
502 template<typename Type, typename Contained>
503 class InstanceContainedCast :
504 public CastInstaller<
505 StaticInstanceType<Contained>,
506 ContainedCast<Type, Contained>
511 template<typename Type>
512 class InstanceIdentityCast :
513 public CastInstaller<
514 StaticInstanceType<Type>,
521 inline Selectable* Instance_getSelectable(scene::Instance& instance);
522 inline const Selectable* Instance_getSelectable(const scene::Instance& instance);
524 inline Bounded* Instance_getBounded(scene::Instance& instance);
525 inline const Bounded* Instance_getBounded(const scene::Instance& instance);
531 class AABBAccumulateWalker : public scene::Graph::Walker
534 mutable std::size_t m_depth;
536 AABBAccumulateWalker(AABB& aabb) : m_aabb(aabb), m_depth(0)
539 bool pre(const scene::Path& path, scene::Instance& instance) const
543 aabb_extend_by_aabb_safe(m_aabb, instance.worldAABB());
545 return ++m_depth != 2;
547 void post(const scene::Path& path, scene::Instance& instance) const
554 class TransformChangedWalker : public scene::Graph::Walker
557 bool pre(const scene::Path& path, scene::Instance& instance) const
559 instance.transformChangedLocal();
564 class ParentSelectedChangedWalker : public scene::Graph::Walker
567 bool pre(const scene::Path& path, scene::Instance& instance) const
569 instance.parentSelectedChanged();
574 class ChildSelectedWalker : public scene::Graph::Walker
576 bool& m_childSelected;
577 mutable std::size_t m_depth;
579 ChildSelectedWalker(bool& childSelected) : m_childSelected(childSelected), m_depth(0)
581 m_childSelected = false;
583 bool pre(const scene::Path& path, scene::Instance& instance) const
585 if(m_depth == 1 && !m_childSelected)
587 m_childSelected = instance.isSelected() || instance.childSelected();
589 return ++m_depth != 2;
591 void post(const scene::Path& path, scene::Instance& instance) const
600 InstanceTypeCastTable& m_casts;
602 mutable Matrix4 m_local2world;
603 mutable AABB m_bounds;
604 mutable AABB m_childBounds;
605 mutable bool m_transformChanged;
606 mutable bool m_transformMutex;
607 mutable bool m_boundsChanged;
608 mutable bool m_boundsMutex;
609 mutable bool m_childBoundsChanged;
610 mutable bool m_childBoundsMutex;
611 mutable bool m_isSelected;
612 mutable bool m_isSelectedChanged;
613 mutable bool m_childSelected;
614 mutable bool m_childSelectedChanged;
615 mutable bool m_parentSelected;
616 mutable bool m_parentSelectedChanged;
617 Callback m_childSelectedChangedCallback;
618 Callback m_transformChangedCallback;
621 void evaluateTransform() const
623 if(m_transformChanged)
625 ASSERT_MESSAGE(!m_transformMutex, "re-entering transform evaluation");
626 m_transformMutex = true;
628 m_local2world = (m_parent != 0) ? m_parent->localToWorld() : g_matrix4_identity;
629 TransformNode* transformNode = Node_getTransformNode(m_path.top());
630 if(transformNode != 0)
632 matrix4_multiply_by_matrix4(m_local2world, transformNode->localToParent());
635 m_transformMutex = false;
636 m_transformChanged = false;
639 void evaluateChildBounds() const
641 if(m_childBoundsChanged)
643 ASSERT_MESSAGE(!m_childBoundsMutex, "re-entering bounds evaluation");
644 m_childBoundsMutex = true;
646 m_childBounds = AABB();
648 GlobalSceneGraph().traverse_subgraph(AABBAccumulateWalker(m_childBounds), m_path);
650 m_childBoundsMutex = false;
651 m_childBoundsChanged = false;
654 void evaluateBounds() const
658 ASSERT_MESSAGE(!m_boundsMutex, "re-entering bounds evaluation");
659 m_boundsMutex = true;
661 m_bounds = childBounds();
663 const Bounded* bounded = Instance_getBounded(*this);
666 aabb_extend_by_aabb_safe(
668 aabb_for_oriented_aabb_safe(bounded->localAABB(), localToWorld())
672 m_boundsMutex = false;
673 m_boundsChanged = false;
677 Instance(const scene::Instance& other);
678 Instance& operator=(const scene::Instance& other);
681 Instance(const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts) :
684 m_instance(instance),
686 m_local2world(g_matrix4_identity),
687 m_transformChanged(true),
688 m_transformMutex(false),
689 m_boundsChanged(true),
690 m_boundsMutex(false),
691 m_childBoundsChanged(true),
692 m_childBoundsMutex(false),
693 m_isSelectedChanged(true),
694 m_childSelectedChanged(true),
695 m_parentSelectedChanged(true)
697 ASSERT_MESSAGE((parent == 0) == (path.size() == 1), "instance has invalid parent");
703 const scene::Path& path() const
708 void* cast(TypeId typeId) const
710 return m_casts.cast(typeId, m_instance);
713 const Matrix4& localToWorld() const
716 return m_local2world;
718 void transformChangedLocal()
720 ASSERT_NOTNULL(m_parent);
721 m_transformChanged = true;
722 m_boundsChanged = true;
723 m_childBoundsChanged = true;
724 m_transformChangedCallback();
726 void transformChanged()
728 GlobalSceneGraph().traverse_subgraph(TransformChangedWalker(), m_path);
731 void setTransformChangedCallback(const Callback& callback)
733 m_transformChangedCallback = callback;
737 const AABB& worldAABB() const
742 const AABB& childBounds() const
744 evaluateChildBounds();
745 return m_childBounds;
749 m_boundsChanged = true;
750 m_childBoundsChanged = true;
753 m_parent->boundsChanged();
755 GlobalSceneGraph().boundsChanged();
758 void childSelectedChanged()
760 m_childSelectedChanged = true;
761 m_childSelectedChangedCallback();
764 m_parent->childSelectedChanged();
767 bool childSelected() const
769 if(m_childSelectedChanged)
771 m_childSelectedChanged = false;
772 GlobalSceneGraph().traverse_subgraph(ChildSelectedWalker(m_childSelected), m_path);
774 return m_childSelected;
777 void setChildSelectedChangedCallback(const Callback& callback)
779 m_childSelectedChangedCallback = callback;
781 void selectedChanged()
783 m_isSelectedChanged = true;
786 m_parent->childSelectedChanged();
788 GlobalSceneGraph().traverse_subgraph(ParentSelectedChangedWalker(), m_path);
790 bool isSelected() const
792 if(m_isSelectedChanged)
794 m_isSelectedChanged = false;
795 const Selectable* selectable = Instance_getSelectable(*this);
796 m_isSelected = selectable != 0 && selectable->isSelected();
801 void parentSelectedChanged()
803 m_parentSelectedChanged = true;
805 bool parentSelected() const
807 if(m_parentSelectedChanged)
809 m_parentSelectedChanged = false;
810 m_parentSelected = m_parent != 0 && (m_parent->isSelected() || m_parent->parentSelected());
812 return m_parentSelected;
817 template<typename Type>
818 class InstanceTypeCast
821 static Type* cast(scene::Instance& instance)
823 return static_cast<Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
825 static const Type* cast(const scene::Instance& instance)
827 return static_cast<const Type*>(instance.cast(StaticInstanceType<Type>::getTypeId()));
831 template<typename Functor>
832 class InstanceWalker : public scene::Graph::Walker
834 const Functor& m_functor;
836 InstanceWalker(const Functor& functor) : m_functor(functor)
839 bool pre(const scene::Path& path, scene::Instance& instance) const
846 template<typename Functor>
847 class ChildInstanceWalker : public scene::Graph::Walker
849 const Functor& m_functor;
850 mutable std::size_t m_depth;
852 ChildInstanceWalker(const Functor& functor) : m_functor(functor), m_depth(0)
855 bool pre(const scene::Path& path, scene::Instance& instance) const
861 return ++m_depth != 2;
863 void post(const scene::Path& path, scene::Instance& instance) const
869 template<typename Type, typename Functor>
870 class InstanceApply : public Functor
873 InstanceApply(const Functor& functor) : Functor(functor)
876 void operator()(scene::Instance& instance) const
878 Type* result = InstanceTypeCast<Type>::cast(instance);
881 Functor::operator()(*result);
886 inline Selectable* Instance_getSelectable(scene::Instance& instance)
888 return InstanceTypeCast<Selectable>::cast(instance);
890 inline const Selectable* Instance_getSelectable(const scene::Instance& instance)
892 return InstanceTypeCast<Selectable>::cast(instance);
895 template<typename Functor>
896 inline void Scene_forEachChildSelectable(const Functor& functor, const scene::Path& path)
898 GlobalSceneGraph().traverse_subgraph(ChildInstanceWalker< InstanceApply<Selectable, Functor> >(functor), path);
901 class SelectableSetSelected
905 SelectableSetSelected(bool selected) : m_selected(selected)
908 void operator()(Selectable& selectable) const
910 selectable.setSelected(m_selected);
914 inline Bounded* Instance_getBounded(scene::Instance& instance)
916 return InstanceTypeCast<Bounded>::cast(instance);
918 inline const Bounded* Instance_getBounded(const scene::Instance& instance)
920 return InstanceTypeCast<Bounded>::cast(instance);
923 inline Transformable* Instance_getTransformable(scene::Instance& instance)
925 return InstanceTypeCast<Transformable>::cast(instance);
927 inline const Transformable* Instance_getTransformable(const scene::Instance& instance)
929 return InstanceTypeCast<Transformable>::cast(instance);
933 inline ComponentSelectionTestable* Instance_getComponentSelectionTestable(scene::Instance& instance)
935 return InstanceTypeCast<ComponentSelectionTestable>::cast(instance);
938 inline ComponentEditable* Instance_getComponentEditable(scene::Instance& instance)
940 return InstanceTypeCast<ComponentEditable>::cast(instance);
943 inline ComponentSnappable* Instance_getComponentSnappable(scene::Instance& instance)
945 return InstanceTypeCast<ComponentSnappable>::cast(instance);
949 inline void Instance_setSelected(scene::Instance& instance, bool selected)
951 Selectable* selectable = Instance_getSelectable(instance);
954 selectable->setSelected(selected);
958 inline bool Instance_isSelected(scene::Instance& instance)
960 Selectable* selectable = Instance_getSelectable(instance);
963 return selectable->isSelected();
968 inline scene::Instance& findInstance(const scene::Path& path)
970 scene::Instance* instance = GlobalSceneGraph().find(path);
971 ASSERT_MESSAGE(instance != 0, "findInstance: path not found in scene-graph");
975 inline void selectPath(const scene::Path& path, bool selected)
977 Instance_setSelected(findInstance(path), selected);
980 class SelectChildren : public scene::Traversable::Walker
982 mutable scene::Path m_path;
984 SelectChildren(const scene::Path& root)
988 bool pre(scene::Node& node) const
990 m_path.push(makeReference(node));
991 selectPath(m_path, true);
994 void post(scene::Node& node) const
1000 inline void Entity_setSelected(scene::Instance& entity, bool selected)
1002 scene::Node& node = entity.path().top();
1003 if(node_is_group(node))
1005 Node_getTraversable(node)->traverse(SelectChildren(entity.path()));
1009 Instance_setSelected(entity, selected);
1013 inline bool Entity_isSelected(scene::Instance& entity)
1015 if(node_is_group(entity.path().top()))
1017 return entity.childSelected();
1019 return Instance_isSelected(entity);
1024 class InstanceCounter
1027 unsigned int m_count;
1028 InstanceCounter() : m_count(0)
1037 virtual void increment() = 0;
1038 virtual void decrement() = 0;
1041 #include "generic/callback.h"
1043 class SimpleCounter : public Counter
1045 Callback m_countChanged;
1046 std::size_t m_count;
1048 void setCountChangedCallback(const Callback& countChanged)
1050 m_countChanged = countChanged;
1062 std::size_t get() const
1069 template<typename Contained>
1070 class ConstReference;
1071 typedef ConstReference<scene::Path> PathConstReference;
1073 #include "generic/referencecounted.h"
1074 typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;