rnr/Projects/Engine/Source/App/V8/Tree/Instance.cpp

240 lines
7.0 KiB
C++

#include <App/V8/Tree/Instance.hpp>
namespace RNR
{
World* Instance::world = 0;
Instance::Instance()
{
m_node = 0;
m_object = 0;
m_parent = 0;
setName("Instance");
}
Instance::~Instance()
{
setParent(NULL);
if(getNode())
{
getNode()->removeAndDestroyAllChildren();
delete getNode();
}
if(getObject())
{
if(getObject()->getParentNode() != 0)
getObject()->detachFromParent();
delete getObject();
}
}
std::vector<ReflectionProperty> Instance::getProperties()
{
ReflectionProperty properties[] = {
{ this, std::string("Name"), std::string("This is the name of this Instance."),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_STD_STRING,
REFLECTION_GETTER(Instance* instance = (Instance*)object; return &instance->m_name; ),
REFLECTION_SETTER(Instance* instance = (Instance*)object; instance->setName(*(std::string*)value); ) },
{ this, std::string("Parent"), std::string("This is the parent of this Instance."),
ACCESS_NONE, OPERATION_READ, PROPERTY_INSTANCE,
REFLECTION_GETTER(Instance* instance = (Instance*)object; return instance->m_parent; ),
REFLECTION_NO_SETTER() },
{ this, std::string("Archivable"), std::string("This determines whether this Instance may be saved or replicated."),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_BOOL,
REFLECTION_GETTER(Instance* instance = (Instance*)object; return &instance->m_archivable; ),
REFLECTION_SETTER(Instance* instance = (Instance*)object; instance->m_archivable = *(bool*)value; ) },
};
std::vector<ReflectionProperty> _properties(properties, properties+(sizeof(properties)/sizeof(ReflectionProperty)));
addProperties(_properties);
return _properties;
}
void Instance::deserializeXmlProperty(pugi::xml_node prop)
{
pugi::xml_attribute prop_name = prop.attribute("name");
if(prop_name.as_string() == std::string("Name"))
setName(prop.text().as_string());
else if(prop_name.as_string() == std::string("archivable"))
m_archivable = prop.text().as_bool();
else
deserializeProperty((char*)prop_name.as_string(), prop);
}
bool Instance::contains(Instance* child)
{
auto child_it = std::find(m_children.begin(), m_children.end(), child);
return child_it != m_children.end();
}
bool Instance::isAncestorOf(Instance* instance)
{
Instance* instance_parent = instance->m_parent;
while (instance_parent != 0)
{
instance_parent = instance_parent->m_parent;
if (instance_parent == this)
return true;
}
return false;
}
bool Instance::askSetParent(Instance* instance)
{
return true;
}
bool Instance::canSetParent(Instance* instance)
{
return !instance || instance->canAddChild(this);
}
bool Instance::askAddChild(Instance* instance)
{
return true;
}
bool Instance::canAddChild(Instance* instance)
{
if (instance->contains(this) || instance->m_parent == this)
return false;
if (askAddChild(instance))
return true;
return instance->askSetParent(this);
}
void Instance::setName(std::string name)
{
if (name != this->m_name)
{
this->m_name = name;
// raise property changed
}
}
void Instance::setParent(Instance* newParent)
{
if (newParent != m_parent)
{
char error_text[255];
if (this == newParent)
{
snprintf(error_text, 255, "Attempt to set %s as its own parent", m_name.c_str());
throw std::runtime_error(error_text);
}
if (newParent && isAncestorOf(newParent))
{
snprintf(error_text, 255, "Attempt to set parent of %s to %s results in circular reference", newParent->getName().c_str(), m_name.c_str());
throw std::runtime_error(error_text);
}
if (m_parent)
{
std::vector<Instance*>* children = m_parent->getChildren();
auto child_it = std::find(children->begin(), children->end(), this);
if (child_it != children->end())
{
children->erase(child_it);
m_parent->onChildRemoved(this);
m_parent->onDescendantRemoved(this);
for(auto& child : m_children)
descendantRemovedChildren(m_parent, child);
if (m_parent->numChildren() == 0)
{
// signal onlastchildremoved
}
}
}
onSetParent(newParent);
m_parent = newParent;
if(m_parent)
{
m_parent->m_children.push_back(this);
newParent->onChildAdded(this);
newParent->onDescendantAdded(this);
for(auto& child : m_children)
descendantAddedChildren(m_parent, child);
}
}
}
void Instance::descendantAddedChildren(Instance* p, Instance* c)
{
for(auto& child : *c->getChildren())
descendantAddedChildren(p, child);
p->onDescendantAdded(c);
}
void Instance::descendantRemovedChildren(Instance* p, Instance* c)
{
for(auto& child : *c->getChildren())
descendantRemovedChildren(p, child);
p->onDescendantRemoved(c);
}
void Instance::onChildAdded(Instance* childAdded)
{
//
}
void Instance::onDescendantAdded(Instance* descendantAdded)
{
if(m_parent)
m_parent->onDescendantAdded(descendantAdded);
}
void Instance::onChildRemoved(RNR::Instance* childRemoved)
{
}
void Instance::onDescendantRemoved(Instance* descendantRemoved)
{
if(m_parent)
m_parent->onDescendantRemoved(descendantRemoved);
}
void Instance::onSetParent(Instance* newParent)
{
}
bool Instance::isA(std::string type)
{
if (type == getClassName())
return true; // TODO: check if type is any of parent types
return false;
}
Instance* Instance::findFirstChild(std::string name)
{
for(auto& child : m_children)
{
if(child->getName() == name)
return child;
}
return NULL;
}
Instance* Instance::findFirstChildOfType(std::string type)
{
for(auto& child : m_children)
{
if(child->isA(type))
return child;
}
return NULL;
}
}