/*
   Copyright (C) 2001-2006, William Joseph.
   All Rights Reserved.

   This file is part of GtkRadiant.

   GtkRadiant is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   GtkRadiant is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GtkRadiant; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#if !defined ( INCLUDED_SCENELIB_H )
#define INCLUDED_SCENELIB_H

#include "globaldefs.h"
#include "iscenegraph.h"
#include "iselection.h"

#include "warnings.h"
#include <cstddef>
#include <string.h>

#include "math/aabb.h"
#include "transformlib.h"
#include "generic/callback.h"
#include "generic/reference.h"
#include "container/stack.h"
#include "typesystem.h"

class Selector;
class SelectionTest;
class VolumeTest;
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
template<typename Element> class BasicVector4;
typedef BasicVector4<float> Vector4;
class Matrix4;
typedef Vector4 Quaternion;
class AABB;

class ComponentSelectionTestable
{
public:
STRING_CONSTANT( Name, "ComponentSelectionTestable" );

virtual bool isSelectedComponents() const = 0;
virtual void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ) = 0;
virtual void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ) = 0;
};

class ComponentEditable
{
public:
STRING_CONSTANT( Name, "ComponentEditable" );

virtual const AABB& getSelectedComponentsBounds() const = 0;
};

class ComponentSnappable
{
public:
STRING_CONSTANT( Name, "ComponentSnappable" );

virtual void snapComponents( float snap ) = 0;
};

class Bounded
{
public:
STRING_CONSTANT( Name, "Bounded" );

virtual const AABB& localAABB() const = 0;
};

class BrushDoom3
{
public:
STRING_CONSTANT( Name, "BrushDoom3" );

virtual void setDoom3GroupOrigin( const Vector3& origin ) = 0;
};




typedef TypeCastTable<NODETYPEID_MAX> NodeTypeCastTable;

template<typename Type>
class NodeType : public StaticTypeSystemInitialiser
{
TypeId m_typeId;
public:
typedef typename Type::Name Name;
NodeType() : m_typeId( NODETYPEID_NONE ){
	StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
}
void initialise(){
	m_typeId = GlobalSceneGraph().getNodeTypeId( Name() );
}
typedef MemberCaller<NodeType<Type>, void(), &NodeType<Type>::initialise> InitialiseCaller;
TypeId getTypeId(){
#if GDEF_DEBUG
	ASSERT_MESSAGE( m_typeId != NODETYPEID_NONE, "node-type " << makeQuoted( Name() ) << " used before being initialised" );
#endif
	return m_typeId;
}
};

template<typename Type>
class StaticNodeType
{
public:
enum unnamed0 { SIZE = NODETYPEID_MAX };
static TypeId getTypeId(){
	return Static< NodeType<Type> >::instance().getTypeId();
}
};

template<typename Type, typename Base>
class NodeStaticCast :
	public CastInstaller<
		StaticNodeType<Base>,
		StaticCast<Type, Base>
		>
{
};

template<typename Type, typename Contained>
class NodeContainedCast :
	public CastInstaller<
		StaticNodeType<Contained>,
		ContainedCast<Type, Contained>
		>
{
};

template<typename Type>
class NodeIdentityCast :
	public CastInstaller<
		StaticNodeType<Type>,
		IdentityCast<Type>
		>
{
};

namespace scene
{
class Node
{
public:
enum unnamed0 { eVisible = 0 };
enum unnamed1 { eHidden = 1 << 0 };
enum unnamed2 { eFiltered = 1 << 1 };
enum unnamed3 { eExcluded = 1 << 2 };

class Symbiot
{
public:
virtual void release() = 0;
virtual ~Symbiot(){
}
};

private:
unsigned int m_state;
std::size_t m_refcount;
Symbiot* m_symbiot;
void* m_node;
NodeTypeCastTable& m_casts;

public:
bool m_isRoot;

bool isRoot(){
	return m_isRoot;
}

Node( Symbiot* symbiot, void* node, NodeTypeCastTable& casts ) :
	m_state( eVisible ),
	m_refcount( 0 ),
	m_symbiot( symbiot ),
	m_node( node ),
	m_casts( casts ),
	m_isRoot( false ){
}
~Node(){
}

void IncRef(){
	ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
	++m_refcount;
}
void DecRef(){
	ASSERT_MESSAGE( m_refcount < ( 1 << 24 ), "Node::decref: uninitialised refcount" );
	if ( --m_refcount == 0 ) {
		m_symbiot->release();
	}
}
std::size_t getReferenceCount() const {
	return m_refcount;
}

void* cast( TypeId typeId ) const {
	return m_casts.cast( typeId, m_node );
}

void enable( unsigned int state ){
	m_state |= state;
}
void disable( unsigned int state ){
	m_state &= ~state;
}
bool visible(){
	return m_state == eVisible;
}
bool excluded(){
	return ( m_state & eExcluded ) != 0;
}
bool operator<( const scene::Node& other ){
	return this < &other;
}
bool operator==( const scene::Node& other ){
	return this == &other;
}
bool operator!=( const scene::Node& other ){
	return this != &other;
}
};


class NullNode : public Node::Symbiot
{
NodeTypeCastTable m_casts;
Node m_node;
public:
NullNode() : m_node( this, 0, m_casts ){
}
void release(){
	delete this;
}
scene::Node& node(){
	return m_node;
}
};
}

template<typename Type>
class NodeTypeCast
{
public:
static Type* cast( scene::Node& node ){
	return static_cast<Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
}
static const Type* cast( const scene::Node& node ){
	return static_cast<const Type*>( node.cast( StaticNodeType<Type>::getTypeId() ) );
}
};


inline scene::Instantiable* Node_getInstantiable( scene::Node& node ){
	return NodeTypeCast<scene::Instantiable>::cast( node );
}

inline scene::Traversable* Node_getTraversable( scene::Node& node ){
	return NodeTypeCast<scene::Traversable>::cast( node );
}

inline void Node_traverseSubgraph( scene::Node& node, const scene::Traversable::Walker& walker ){
	if ( walker.pre( node ) ) {
		scene::Traversable* traversable = Node_getTraversable( node );
		if ( traversable != 0 ) {
			traversable->traverse( walker );
		}
	}
	walker.post( node );
}

inline TransformNode* Node_getTransformNode( scene::Node& node ){
	return NodeTypeCast<TransformNode>::cast( node );
}


inline scene::Node& NewNullNode(){
	return ( new scene::NullNode )->node();
}

inline void Path_deleteTop( const scene::Path& path ){
	Node_getTraversable( path.parent() )->erase( path.top() );
}





class delete_all : public scene::Traversable::Walker
{
scene::Node& m_parent;
public:
delete_all( scene::Node& parent ) : m_parent( parent ){
}
bool pre( scene::Node& node ) const {
	return false;
}
void post( scene::Node& node ) const {
	Node_getTraversable( m_parent )->erase( node );
}
};

inline void DeleteSubgraph( scene::Node& subgraph ){
	Node_getTraversable( subgraph )->traverse( delete_all( subgraph ) );
}


class EntityUndefined
{
public:
STRING_CONSTANT( Name, "Entity" );
};

inline bool Node_isEntity( scene::Node& node ){
	return NodeTypeCast<EntityUndefined>::cast( node ) != 0;
}

template<typename Functor>
class EntityWalker : public scene::Graph::Walker
{
const Functor& functor;
public:
EntityWalker( const Functor& functor ) : functor( functor ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	if ( Node_isEntity( path.top() ) ) {
		functor( instance );
		return false;
	}
	return true;
}
};

template<typename Functor>
inline const Functor& Scene_forEachEntity( const Functor& functor ){
	GlobalSceneGraph().traverse( EntityWalker<Functor>( functor ) );
	return functor;
}

class BrushUndefined
{
public:
STRING_CONSTANT( Name, "Brush" );
};

inline bool Node_isBrush( scene::Node& node ){
	return NodeTypeCast<BrushUndefined>::cast( node ) != 0;
}

class PatchUndefined
{
public:
STRING_CONSTANT( Name, "Patch" );
};

inline bool Node_isPatch( scene::Node& node ){
	return NodeTypeCast<PatchUndefined>::cast( node ) != 0;
}

inline bool Node_isPrimitive( scene::Node& node ){
#if 1
	return Node_isBrush( node ) || Node_isPatch( node );
#else
	return !node.isRoot();
#endif
}

class ParentBrushes : public scene::Traversable::Walker
{
scene::Node& m_parent;
public:
ParentBrushes( scene::Node& parent )
	: m_parent( parent ){
}
bool pre( scene::Node& node ) const {
	return false;
}
void post( scene::Node& node ) const {
	if ( Node_isPrimitive( node ) ) {
		Node_getTraversable( m_parent )->insert( node );
	}
}
};

inline void parentBrushes( scene::Node& subgraph, scene::Node& parent ){
	Node_getTraversable( subgraph )->traverse( ParentBrushes( parent ) );
}

class HasBrushes : public scene::Traversable::Walker
{
bool& m_hasBrushes;
public:
HasBrushes( bool& hasBrushes )
	: m_hasBrushes( hasBrushes ){
	m_hasBrushes = true;
}
bool pre( scene::Node& node ) const {
	if ( !Node_isPrimitive( node ) ) {
		m_hasBrushes = false;
	}
	return false;
}
};

inline bool node_is_group( scene::Node& node ){
	scene::Traversable* traversable = Node_getTraversable( node );
	if ( traversable != 0 ) {
		bool hasBrushes = false;
		traversable->traverse( HasBrushes( hasBrushes ) );
		return hasBrushes;
	}
	return false;
}

typedef TypeCastTable<INSTANCETYPEID_MAX> InstanceTypeCastTable;

template<typename Type>
class InstanceType : public StaticTypeSystemInitialiser
{
TypeId m_typeId;
public:
typedef typename Type::Name Name;
InstanceType() : m_typeId( INSTANCETYPEID_NONE ){
	StaticTypeSystemInitialiser::instance().addInitialiser( InitialiseCaller( *this ) );
}
void initialise(){
	m_typeId = GlobalSceneGraph().getInstanceTypeId( Name() );
}
typedef MemberCaller<InstanceType<Type>, void(), &InstanceType<Type>::initialise> InitialiseCaller;
TypeId getTypeId(){
#if GDEF_DEBUG
	ASSERT_MESSAGE( m_typeId != INSTANCETYPEID_NONE, "instance-type " << makeQuoted( Name() ) << " used before being initialised" );
#endif
	return m_typeId;
}
};

template<typename Type>
class StaticInstanceType
{
public:
enum unnamed0 { SIZE = INSTANCETYPEID_MAX };
static TypeId getTypeId(){
	return Static< InstanceType<Type> >::instance().getTypeId();
}
};

template<typename Type, typename Base>
class InstanceStaticCast :
	public CastInstaller<
		StaticInstanceType<Base>,
		StaticCast<Type, Base>
		>
{
};

template<typename Type, typename Contained>
class InstanceContainedCast :
	public CastInstaller<
		StaticInstanceType<Contained>,
		ContainedCast<Type, Contained>
		>
{
};

template<typename Type>
class InstanceIdentityCast :
	public CastInstaller<
		StaticInstanceType<Type>,
		IdentityCast<Type>
		>
{
};


inline Selectable* Instance_getSelectable( scene::Instance& instance );
inline const Selectable* Instance_getSelectable( const scene::Instance& instance );

inline Bounded* Instance_getBounded( scene::Instance& instance );
inline const Bounded* Instance_getBounded( const scene::Instance& instance );

namespace scene
{
class Instance
{
class AABBAccumulateWalker : public scene::Graph::Walker
{
AABB& m_aabb;
mutable std::size_t m_depth;
public:
AABBAccumulateWalker( AABB& aabb ) : m_aabb( aabb ), m_depth( 0 ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	if ( m_depth == 1 ) {
		aabb_extend_by_aabb_safe( m_aabb, instance.worldAABB() );
	}
	return ++m_depth != 2;
}
void post( const scene::Path& path, scene::Instance& instance ) const {
	--m_depth;
}
};


class TransformChangedWalker : public scene::Graph::Walker
{
public:
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	instance.transformChangedLocal();
	return true;
}
};

class ParentSelectedChangedWalker : public scene::Graph::Walker
{
public:
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	instance.parentSelectedChanged();
	return true;
}
};

class ChildSelectedWalker : public scene::Graph::Walker
{
bool& m_childSelected;
mutable std::size_t m_depth;
public:
ChildSelectedWalker( bool& childSelected ) : m_childSelected( childSelected ), m_depth( 0 ){
	m_childSelected = false;
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	if ( m_depth == 1 && !m_childSelected ) {
		m_childSelected = instance.isSelected() || instance.childSelected();
	}
	return ++m_depth != 2;
}
void post( const scene::Path& path, scene::Instance& instance ) const {
	--m_depth;
}
};

Path m_path;
Instance* m_parent;
void* m_instance;
InstanceTypeCastTable& m_casts;

mutable Matrix4 m_local2world;
mutable AABB m_bounds;
mutable AABB m_childBounds;
mutable bool m_transformChanged;
mutable bool m_transformMutex;
mutable bool m_boundsChanged;
mutable bool m_boundsMutex;
mutable bool m_childBoundsChanged;
mutable bool m_childBoundsMutex;
mutable bool m_isSelected;
mutable bool m_isSelectedChanged;
mutable bool m_childSelected;
mutable bool m_childSelectedChanged;
mutable bool m_parentSelected;
mutable bool m_parentSelectedChanged;
Callback<void()> m_childSelectedChangedCallback;
Callback<void()> m_transformChangedCallback;


void evaluateTransform() const {
	if ( m_transformChanged ) {
		ASSERT_MESSAGE( !m_transformMutex, "re-entering transform evaluation" );
		m_transformMutex = true;

		m_local2world = ( m_parent != 0 ) ? m_parent->localToWorld() : g_matrix4_identity;
		TransformNode* transformNode = Node_getTransformNode( m_path.top() );
		if ( transformNode != 0 ) {
			matrix4_multiply_by_matrix4( m_local2world, transformNode->localToParent() );
		}

		m_transformMutex = false;
		m_transformChanged = false;
	}
}
void evaluateChildBounds() const {
	if ( m_childBoundsChanged ) {
		ASSERT_MESSAGE( !m_childBoundsMutex, "re-entering bounds evaluation" );
		m_childBoundsMutex = true;

		m_childBounds = AABB();

		GlobalSceneGraph().traverse_subgraph( AABBAccumulateWalker( m_childBounds ), m_path );

		m_childBoundsMutex = false;
		m_childBoundsChanged = false;
	}
}
void evaluateBounds() const {
	if ( m_boundsChanged ) {
		ASSERT_MESSAGE( !m_boundsMutex, "re-entering bounds evaluation" );
		m_boundsMutex = true;

		m_bounds = childBounds();

		const Bounded* bounded = Instance_getBounded( *this );
		if ( bounded != 0 ) {
			aabb_extend_by_aabb_safe(
				m_bounds,
				aabb_for_oriented_aabb_safe( bounded->localAABB(), localToWorld() )
				);
		}

		m_boundsMutex = false;
		m_boundsChanged = false;
	}
}

Instance( const scene::Instance& other );
Instance& operator=( const scene::Instance& other );
public:

Instance( const scene::Path& path, Instance* parent, void* instance, InstanceTypeCastTable& casts ) :
	m_path( path ),
	m_parent( parent ),
	m_instance( instance ),
	m_casts( casts ),
	m_local2world( g_matrix4_identity ),
	m_transformChanged( true ),
	m_transformMutex( false ),
	m_boundsChanged( true ),
	m_boundsMutex( false ),
	m_childBoundsChanged( true ),
	m_childBoundsMutex( false ),
	m_isSelectedChanged( true ),
	m_childSelectedChanged( true ),
	m_parentSelectedChanged( true ){
	ASSERT_MESSAGE( ( parent == 0 ) == ( path.size() == 1 ), "instance has invalid parent" );
}
virtual ~Instance(){
}

const scene::Path& path() const {
	return m_path;
}

void* cast( TypeId typeId ) const {
	return m_casts.cast( typeId, m_instance );
}

const Matrix4& localToWorld() const {
	evaluateTransform();
	return m_local2world;
}
void transformChangedLocal(){
	ASSERT_NOTNULL( m_parent );
	m_transformChanged = true;
	m_boundsChanged = true;
	m_childBoundsChanged = true;
	m_transformChangedCallback();
}
void transformChanged(){
	GlobalSceneGraph().traverse_subgraph( TransformChangedWalker(), m_path );
	boundsChanged();
}
void setTransformChangedCallback( const Callback<void()>& callback ){
	m_transformChangedCallback = callback;
}


const AABB& worldAABB() const {
	evaluateBounds();
	return m_bounds;
}
const AABB& childBounds() const {
	evaluateChildBounds();
	return m_childBounds;
}
void boundsChanged(){
	m_boundsChanged = true;
	m_childBoundsChanged = true;
	if ( m_parent != 0 ) {
		m_parent->boundsChanged();
	}
	GlobalSceneGraph().boundsChanged();
}

void childSelectedChanged(){
	m_childSelectedChanged = true;
	m_childSelectedChangedCallback();
	if ( m_parent != 0 ) {
		m_parent->childSelectedChanged();
	}
}
bool childSelected() const {
	if ( m_childSelectedChanged ) {
		m_childSelectedChanged = false;
		GlobalSceneGraph().traverse_subgraph( ChildSelectedWalker( m_childSelected ), m_path );
	}
	return m_childSelected;
}

void setChildSelectedChangedCallback( const Callback<void()>& callback ){
	m_childSelectedChangedCallback = callback;
}
void selectedChanged(){
	m_isSelectedChanged = true;
	if ( m_parent != 0 ) {
		m_parent->childSelectedChanged();
	}
	GlobalSceneGraph().traverse_subgraph( ParentSelectedChangedWalker(), m_path );
}
bool isSelected() const {
	if ( m_isSelectedChanged ) {
		m_isSelectedChanged = false;
		const Selectable* selectable = Instance_getSelectable( *this );
		m_isSelected = selectable != 0 && selectable->isSelected();
	}
	return m_isSelected;
}

void parentSelectedChanged(){
	m_parentSelectedChanged = true;
}
bool parentSelected() const {
	if ( m_parentSelectedChanged ) {
		m_parentSelectedChanged = false;
		m_parentSelected = m_parent != 0 && ( m_parent->isSelected() || m_parent->parentSelected() );
	}
	return m_parentSelected;
}
Instance* parent() const
{
	return m_parent;
}
};
}

template<typename Type>
class InstanceTypeCast
{
public:
static Type* cast( scene::Instance& instance ){
	return static_cast<Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
}
static const Type* cast( const scene::Instance& instance ){
	return static_cast<const Type*>( instance.cast( StaticInstanceType<Type>::getTypeId() ) );
}
};

template<typename Functor>
class InstanceWalker : public scene::Graph::Walker
{
const Functor& m_functor;
public:
InstanceWalker( const Functor& functor ) : m_functor( functor ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	//m_functor( instance );
	//return true;
	if ( path.top().get().visible() ) {
		m_functor( instance );
	}
	else{
		return false;
	}
	return true;
}
};

template<typename Functor>
class ChildInstanceWalker : public scene::Graph::Walker
{
const Functor& m_functor;
mutable std::size_t m_depth;
public:
ChildInstanceWalker( const Functor& functor ) : m_functor( functor ), m_depth( 0 ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
	if ( m_depth == 1 ) {
		m_functor( instance );
	}
	return ++m_depth != 2;
}
void post( const scene::Path& path, scene::Instance& instance ) const {
	--m_depth;
}
};

template<typename Type, typename Functor>
class InstanceApply : public Functor
{
public:
InstanceApply( const Functor& functor ) : Functor( functor ){
}
void operator()( scene::Instance& instance ) const {
	Type* result = InstanceTypeCast<Type>::cast( instance );
	if ( result != 0 ) {
		Functor::operator()( *result );
	}
}
};

inline Selectable* Instance_getSelectable( scene::Instance& instance ){
	return InstanceTypeCast<Selectable>::cast( instance );
}
inline const Selectable* Instance_getSelectable( const scene::Instance& instance ){
	return InstanceTypeCast<Selectable>::cast( instance );
}

template<typename Functor>
inline void Scene_forEachChildSelectable( const Functor& functor, const scene::Path& path ){
	GlobalSceneGraph().traverse_subgraph( ChildInstanceWalker< InstanceApply<Selectable, Functor> >( functor ), path );
}

class SelectableSetSelected
{
bool m_selected;
public:
SelectableSetSelected( bool selected ) : m_selected( selected ){
}
void operator()( Selectable& selectable ) const {
	selectable.setSelected( m_selected );
}
};

inline Bounded* Instance_getBounded( scene::Instance& instance ){
	return InstanceTypeCast<Bounded>::cast( instance );
}
inline const Bounded* Instance_getBounded( const scene::Instance& instance ){
	return InstanceTypeCast<Bounded>::cast( instance );
}

inline Transformable* Instance_getTransformable( scene::Instance& instance ){
	return InstanceTypeCast<Transformable>::cast( instance );
}
inline const Transformable* Instance_getTransformable( const scene::Instance& instance ){
	return InstanceTypeCast<Transformable>::cast( instance );
}


inline ComponentSelectionTestable* Instance_getComponentSelectionTestable( scene::Instance& instance ){
	return InstanceTypeCast<ComponentSelectionTestable>::cast( instance );
}

inline ComponentEditable* Instance_getComponentEditable( scene::Instance& instance ){
	return InstanceTypeCast<ComponentEditable>::cast( instance );
}

inline ComponentSnappable* Instance_getComponentSnappable( scene::Instance& instance ){
	return InstanceTypeCast<ComponentSnappable>::cast( instance );
}


inline void Instance_setSelected( scene::Instance& instance, bool selected ){
	Selectable* selectable = Instance_getSelectable( instance );
	if ( selectable != 0 ) {
		selectable->setSelected( selected );
	}
}

inline bool Instance_isSelected( scene::Instance& instance ){
	Selectable* selectable = Instance_getSelectable( instance );
	if ( selectable != 0 ) {
		return selectable->isSelected();
	}
	return false;
}

inline scene::Instance& findInstance( const scene::Path& path ){
	scene::Instance* instance = GlobalSceneGraph().find( path );
	ASSERT_MESSAGE( instance != 0, "findInstance: path not found in scene-graph" );
	return *instance;
}

inline void selectPath( const scene::Path& path, bool selected ){
	Instance_setSelected( findInstance( path ), selected );
}

class SelectChildren : public scene::Traversable::Walker
{
mutable scene::Path m_path;
public:
SelectChildren( const scene::Path& root )
	: m_path( root ){
}
bool pre( scene::Node& node ) const {
	m_path.push( makeReference( node ) );
	selectPath( m_path, true );
	return false;
}
void post( scene::Node& node ) const {
	m_path.pop();
}
};

inline void Entity_setSelected( scene::Instance& entity, bool selected ){
	scene::Node& node = entity.path().top();
	if ( node_is_group( node ) ) {
		Node_getTraversable( node )->traverse( SelectChildren( entity.path() ) );
	}
	else
	{
		Instance_setSelected( entity, selected );
	}
}

inline bool Entity_isSelected( scene::Instance& entity ){
	if ( node_is_group( entity.path().top() ) ) {
		return entity.childSelected();
	}
	return Instance_isSelected( entity );
}



class InstanceCounter
{
public:
unsigned int m_count;
InstanceCounter() : m_count( 0 ){
}
};


class Counter
{
public:
virtual void increment() = 0;
virtual void decrement() = 0;
};

#include "generic/callback.h"

class SimpleCounter : public Counter
{
Callback<void()> m_countChanged;
std::size_t m_count;
public:
void setCountChangedCallback( const Callback<void()>& countChanged ){
	m_countChanged = countChanged;
}
void increment(){
	++m_count;
	m_countChanged();
}
void decrement(){
	--m_count;
	m_countChanged();
}
std::size_t get() const {
	return m_count;
}
};


template<typename Contained>
class ConstReference;
typedef ConstReference<scene::Path> PathConstReference;

#include "generic/referencecounted.h"
typedef SmartReference<scene::Node, IncRefDecRefCounter<scene::Node> > NodeSmartReference;


#endif
