198 lines
4.8 KiB
C++
198 lines
4.8 KiB
C++
|
|
#include "std.hpp"
|
|
#include "entity.hpp"
|
|
|
|
//#include "stats.hpp"
|
|
|
|
Entity *Entity::_orphans, *Entity::_last_orphan;
|
|
|
|
enum {
|
|
INVALID_LOCALTFORM = 1,
|
|
INVALID_WORLDTFORM = 2
|
|
};
|
|
|
|
void Entity::RemoveParent() {
|
|
if (m_parent) {
|
|
if (m_parent->m_children == this) m_parent->m_children = m_listNext;
|
|
if (m_parent->m_last_child == this) m_parent->m_last_child = m_listPrev;
|
|
} else {
|
|
if (_orphans == this) _orphans = m_listNext;
|
|
if (_last_orphan == this) _last_orphan = m_listPrev;
|
|
}
|
|
if (m_listNext) m_listNext->m_listPrev = m_listPrev;
|
|
if (m_listPrev) m_listPrev->m_listNext = m_listNext;
|
|
}
|
|
|
|
void Entity::InsertChildToParent() {
|
|
m_listNext = 0;
|
|
if (m_parent) {
|
|
if (m_listPrev = m_parent->m_last_child) m_listPrev->m_listNext = this;
|
|
else m_parent->m_children = this;
|
|
m_parent->m_last_child = this;
|
|
} else {
|
|
if (m_listPrev = _last_orphan) m_listPrev->m_listNext = this;
|
|
else _orphans = this;
|
|
_last_orphan = this;
|
|
}
|
|
}
|
|
|
|
Entity::Entity() :
|
|
m_listNext(0), m_listPrev(0), m_parent(0), m_children(0), m_last_child(0),
|
|
m_isVisible(true), m_isEnabled(true),
|
|
m_localScale(1, 1, 1),
|
|
invalid(0) {
|
|
InsertChildToParent();
|
|
}
|
|
|
|
Entity::Entity(const Entity &e) :
|
|
m_listNext(0), m_listPrev(0), m_parent(0), m_children(0), m_last_child(0),
|
|
m_name(e.m_name), m_isVisible(e.m_isVisible), m_isEnabled(e.m_isEnabled),
|
|
m_localPosition(e.m_localPosition),
|
|
m_localScale(e.m_localScale),
|
|
m_localRotation(e.m_localRotation),
|
|
invalid(INVALID_LOCALTFORM | INVALID_WORLDTFORM) {
|
|
InsertChildToParent();
|
|
}
|
|
|
|
Entity::~Entity() {
|
|
while (GetChildren()) delete GetChildren();
|
|
RemoveParent();
|
|
}
|
|
|
|
void Entity::InvalidateWorldTransform() {
|
|
if (invalid & INVALID_WORLDTFORM) return;
|
|
invalid |= INVALID_WORLDTFORM;
|
|
for (Entity *e = m_children; e; e = e->m_listNext) {
|
|
e->InvalidateWorldTransform();
|
|
}
|
|
}
|
|
|
|
void Entity::invalidateLocal() {
|
|
invalid |= INVALID_LOCALTFORM;
|
|
InvalidateWorldTransform();
|
|
}
|
|
|
|
const Transform &Entity::GetLocalTransform()const {
|
|
if (invalid&INVALID_LOCALTFORM) {
|
|
m_localTransform.m = Matrix(m_localRotation);
|
|
m_localTransform.m.i *= m_localScale.x;
|
|
m_localTransform.m.j *= m_localScale.y;
|
|
m_localTransform.m.k *= m_localScale.z;
|
|
m_localTransform.v = m_localPosition;
|
|
invalid &= ~INVALID_LOCALTFORM;
|
|
}
|
|
return m_localTransform;
|
|
}
|
|
|
|
const Transform &Entity::GetWorldTransform()const {
|
|
if (invalid&INVALID_WORLDTFORM) {
|
|
m_worldTransform = m_parent ? m_parent->GetWorldTransform() * GetLocalTransform() : GetLocalTransform();
|
|
invalid &= ~INVALID_WORLDTFORM;
|
|
}
|
|
return m_worldTransform;
|
|
}
|
|
|
|
void Entity::SetParent(Entity *p) {
|
|
if (m_parent == p) return;
|
|
|
|
RemoveParent();
|
|
|
|
m_parent = p;
|
|
|
|
InsertChildToParent();
|
|
|
|
InvalidateWorldTransform();
|
|
}
|
|
|
|
void Entity::SetName(const string &t) {
|
|
m_name = t;
|
|
}
|
|
|
|
void Entity::SetVisible(bool visible) {
|
|
m_isVisible = visible;
|
|
}
|
|
|
|
void Entity::SetEnabled(bool enabled) {
|
|
m_isEnabled = enabled;
|
|
}
|
|
|
|
void Entity::EnumerateVisible(std::list<Object*> &out) {
|
|
if (!m_isVisible) return;
|
|
if (Object *o = getObject()) out.push_back(o);
|
|
for (Entity *e = m_children; e; e = e->m_listNext) {
|
|
e->EnumerateVisible(out);
|
|
}
|
|
}
|
|
|
|
void Entity::EnumerateEnabled(std::list<Object*> &out) {
|
|
if (!m_isEnabled) return;
|
|
if (Object *o = getObject()) out.push_back(o);
|
|
for (Entity *e = m_children; e; e = e->m_listNext) {
|
|
e->EnumerateEnabled(out);
|
|
}
|
|
}
|
|
|
|
void Entity::SetLocalPosition(const Vector &v) {
|
|
m_localPosition = v;
|
|
invalidateLocal();
|
|
}
|
|
|
|
void Entity::SetLocalScale(const Vector &v) {
|
|
m_localScale = v;
|
|
invalidateLocal();
|
|
}
|
|
|
|
void Entity::SetLocalRotation(const Quat &q) {
|
|
m_localRotation = q.normalized();
|
|
invalidateLocal();
|
|
}
|
|
|
|
void Entity::SetLocalTransform(const Transform &t) {
|
|
m_localPosition = t.v;
|
|
m_localScale = Vector(t.m.i.length(), t.m.j.length(), t.m.k.length());
|
|
m_localRotation = matrixQuat(t.m);
|
|
invalidateLocal();
|
|
}
|
|
|
|
void Entity::SetWorldPosition(const Vector &v) {
|
|
SetLocalPosition(m_parent ? -m_parent->GetWorldTransform() * v : v);
|
|
}
|
|
|
|
void Entity::SetWorldScale(const Vector &v) {
|
|
SetLocalScale(m_parent ? v / m_parent->GetWorldScale() : v);
|
|
}
|
|
|
|
void Entity::SetWorldRotation(const Quat &q) {
|
|
SetLocalRotation(m_parent ? -m_parent->GetWorldRotation() * q : q);
|
|
}
|
|
|
|
void Entity::SetWorldTransform(const Transform &t) {
|
|
SetLocalTransform(m_parent ? -m_parent->GetWorldTransform() * t : t);
|
|
}
|
|
|
|
const Vector &Entity::GetLocalPosition()const {
|
|
return m_localPosition;
|
|
}
|
|
|
|
const Vector &Entity::GetLocalScale()const {
|
|
return m_localScale;
|
|
}
|
|
|
|
const Quat &Entity::GetLocalRotation()const {
|
|
return m_localRotation;
|
|
}
|
|
|
|
const Vector &Entity::GetWorldPosition()const {
|
|
return GetWorldTransform().v;
|
|
}
|
|
|
|
const Vector &Entity::GetWorldScale()const {
|
|
m_worldScale = m_parent ? m_parent->GetWorldScale() * m_localScale : m_localScale;
|
|
return m_worldScale;
|
|
}
|
|
|
|
const Quat &Entity::GetWorldRotation()const {
|
|
m_worldRotation = m_parent ? m_parent->GetWorldRotation() * m_localRotation : m_localRotation;
|
|
return m_worldRotation;
|
|
}
|