#include 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 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 _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* 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; } }