240 lines
7.0 KiB
C++
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;
|
|
}
|
|
} |