//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #include "BsIReflectable.h" #include "BsRTTIType.h" #include "BsException.h" namespace BansheeEngine { void IReflectable::_registerDerivedClass(RTTITypeBase* derivedClass) { if(_isTypeIdDuplicate(derivedClass->getRTTIId())) { BS_EXCEPT(InternalErrorException, "RTTI type \"" + derivedClass->getRTTIName() + "\" has a duplicate ID: " + toString(derivedClass->getRTTIId())); } getDerivedClasses().push_back(derivedClass); } std::shared_ptr IReflectable::createInstanceFromTypeId(UINT32 rttiTypeId) { RTTITypeBase* type = _getRTTIfromTypeId(rttiTypeId); if(type != nullptr) return type->newRTTIObject(); return nullptr; } RTTITypeBase* IReflectable::_getRTTIfromTypeId(UINT32 rttiTypeId) { Stack todo; Vector& rootClasses = getDerivedClasses(); for(auto iter = rootClasses.begin(); iter != rootClasses.end(); ++iter) todo.push(*iter); while(!todo.empty()) { RTTITypeBase* curType = todo.top(); todo.pop(); if(curType->getRTTIId() == rttiTypeId) return curType; Vector& derivedClasses = curType->getDerivedClasses(); for(auto iter = derivedClasses.begin(); iter != derivedClasses.end(); ++iter) todo.push(*iter); } return nullptr; } bool IReflectable::_isTypeIdDuplicate(UINT32 typeId) { if(typeId == TID_Abstract) return false; return IReflectable::_getRTTIfromTypeId(typeId) != nullptr; } bool IReflectable::isDerivedFrom(RTTITypeBase* base) { return getRTTI()->isDerivedFrom(base); } void IReflectable::_checkForCircularReferences() { Stack todo; Vector rootTypes = getDerivedClasses(); for (auto& entry : rootTypes) todo.push(entry); while(!todo.empty()) { RTTITypeBase* myType = todo.top(); todo.pop(); UINT32 myNumFields = myType->getNumFields(); for (UINT32 i = 0; i < myNumFields; i++) { RTTIField* myField = myType->getField(i); if (!myField->isReflectablePtrType()) continue; RTTIReflectablePtrFieldBase* myReflectablePtrField = static_cast(myField); RTTITypeBase* otherType = myReflectablePtrField->getType(); UINT32 otherNumFields = otherType->getNumFields(); for (UINT32 j = 0; j < otherNumFields; j++) { RTTIField* otherField = otherType->getField(j); if (!otherField->isReflectablePtrType()) continue; RTTIReflectablePtrFieldBase* otherReflectablePtrField = static_cast(otherField); RTTITypeBase* a = myReflectablePtrField->getType(); RTTITypeBase* b = otherReflectablePtrField->getType(); if (myType->getRTTIId() == otherReflectablePtrField->getType()->getRTTIId() && (myReflectablePtrField->getFlags() & RTTI_Flag_WeakRef) == 0 && (otherReflectablePtrField->getFlags() & RTTI_Flag_WeakRef) == 0) { BS_EXCEPT(InternalErrorException, "Found circular reference on RTTI type: " + myType->getRTTIName() + " to type: " + otherType->getRTTIName() + ". Either remove one of the references or mark it" + " as a weak reference when defining the RTTI field."); } } } } } UINT32 IReflectable::getTypeId() const { return getRTTI()->getRTTIId(); } const String& IReflectable::getTypeName() const { return getRTTI()->getRTTIName(); } }