#include "std.h" #include "entity.h" #include "stats.h" Entity *Entity::_orphans,*Entity::_last_orphan; enum{ INVALID_LOCALTFORM=1, INVALID_WORLDTFORM=2 }; void Entity::remove(){ if( _parent ){ if( _parent->_children==this ) _parent->_children=_succ; if( _parent->_last_child==this ) _parent->_last_child=_pred; }else{ if( _orphans==this ) _orphans=_succ; if( _last_orphan==this ) _last_orphan=_pred; } if( _succ ) _succ->_pred=_pred; if( _pred ) _pred->_succ=_succ; } void Entity::insert(){ _succ=0; if( _parent ){ if( _pred=_parent->_last_child ) _pred->_succ=this; else _parent->_children=this; _parent->_last_child=this; }else{ if( _pred=_last_orphan ) _pred->_succ=this; else _orphans=this; _last_orphan=this; } } Entity::Entity(): _succ(0),_pred(0),_parent(0),_children(0),_last_child(0), _visible(true),_enabled(true), local_scl(1,1,1), invalid(0){ insert(); } Entity::Entity( const Entity &e ): _succ(0),_pred(0),_parent(0),_children(0),_last_child(0), _name(e._name),_visible(e._visible),_enabled(e._enabled), local_pos(e.local_pos), local_scl(e.local_scl), local_rot(e.local_rot), invalid( INVALID_LOCALTFORM|INVALID_WORLDTFORM ){ insert(); } Entity::~Entity(){ while( children() ) delete children(); remove(); } void Entity::invalidateWorld(){ if( invalid & INVALID_WORLDTFORM ) return; invalid|=INVALID_WORLDTFORM; for( Entity *e=_children;e;e=e->_succ ){ e->invalidateWorld(); } } void Entity::invalidateLocal(){ invalid|=INVALID_LOCALTFORM; invalidateWorld(); } const Transform &Entity::getLocalTform()const{ if( invalid&INVALID_LOCALTFORM ){ local_tform.m=Matrix( local_rot ); local_tform.m.i*=local_scl.x; local_tform.m.j*=local_scl.y; local_tform.m.k*=local_scl.z; local_tform.v=local_pos; invalid&=~INVALID_LOCALTFORM; } return local_tform; } const Transform &Entity::getWorldTform()const{ if( invalid&INVALID_WORLDTFORM ){ world_tform=_parent ? _parent->getWorldTform() * getLocalTform() : getLocalTform(); invalid&=~INVALID_WORLDTFORM; } return world_tform; } void Entity::setParent( Entity *p ){ if( _parent==p ) return; remove(); _parent=p; insert(); invalidateWorld(); } void Entity::setName( const string &t ){ _name=t; } void Entity::setVisible( bool visible ){ _visible=visible; } void Entity::setEnabled( bool enabled ){ _enabled=enabled; } void Entity::enumVisible( vector &out ){ if( !_visible ) return; if( Object *o=getObject() ) out.push_back(o); for( Entity *e=_children;e;e=e->_succ ){ e->enumVisible( out ); } } void Entity::enumEnabled( vector &out ){ if( !_enabled ) return; if( Object *o=getObject() ) out.push_back(o); for( Entity *e=_children;e;e=e->_succ ){ e->enumEnabled( out ); } } void Entity::setLocalPosition( const Vector &v ){ local_pos=v; invalidateLocal(); } void Entity::setLocalScale( const Vector &v ){ local_scl=v; invalidateLocal(); } void Entity::setLocalRotation( const Quat &q ){ local_rot=q.normalized(); invalidateLocal(); } void Entity::setLocalTform( const Transform &t ){ local_pos=t.v; local_scl=Vector( t.m.i.length(),t.m.j.length(),t.m.k.length() ); local_rot=matrixQuat( t.m ); invalidateLocal(); } void Entity::setWorldPosition( const Vector &v ){ setLocalPosition( _parent ? -_parent->getWorldTform() * v : v ); } void Entity::setWorldScale( const Vector &v ){ setLocalScale( _parent ? v/_parent->getWorldScale() : v ); } void Entity::setWorldRotation( const Quat &q ){ setLocalRotation( _parent ? -_parent->getWorldRotation() * q : q ); } void Entity::setWorldTform( const Transform &t ){ setLocalTform( _parent ? -_parent->getWorldTform() * t : t ); } const Vector &Entity::getLocalPosition()const{ return local_pos; } const Vector &Entity::getLocalScale()const{ return local_scl; } const Quat &Entity::getLocalRotation()const{ return local_rot; } const Vector &Entity::getWorldPosition()const{ return getWorldTform().v; } const Vector &Entity::getWorldScale()const{ world_scl=_parent ? _parent->getWorldScale() * local_scl : local_scl; return world_scl; } const Quat &Entity::getWorldRotation()const{ world_rot=_parent ? _parent->getWorldRotation() * local_rot : local_rot; return world_rot; }