1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
---|---|
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "Reflection/BsIReflectable.h" |
4 | #include "Reflection/BsRTTIType.h" |
5 | #include "Error/BsException.h" |
6 | #include "Private/RTTI/BsIReflectableRTTI.h" |
7 | |
8 | namespace bs |
9 | { |
10 | void IReflectable::_registerRTTIType(RTTITypeBase* rttiType) |
11 | { |
12 | if(_isTypeIdDuplicate(rttiType->getRTTIId())) |
13 | { |
14 | BS_EXCEPT(InternalErrorException, "RTTI type \""+ rttiType->getRTTIName() + |
15 | "\" has a duplicate ID: "+ toString(rttiType->getRTTIId())); |
16 | } |
17 | |
18 | getAllRTTITypes()[rttiType->getRTTIId()] = rttiType; |
19 | } |
20 | |
21 | SPtr<IReflectable> IReflectable::createInstanceFromTypeId(UINT32 rttiTypeId) |
22 | { |
23 | RTTITypeBase* type = _getRTTIfromTypeId(rttiTypeId); |
24 | |
25 | SPtr<IReflectable> output; |
26 | if(type != nullptr) |
27 | output = type->newRTTIObject(); |
28 | |
29 | return output; |
30 | } |
31 | |
32 | RTTITypeBase* IReflectable::_getRTTIfromTypeId(UINT32 rttiTypeId) |
33 | { |
34 | const auto iterFind = getAllRTTITypes().find(rttiTypeId); |
35 | if(iterFind != getAllRTTITypes().end()) |
36 | return iterFind->second; |
37 | |
38 | return nullptr; |
39 | } |
40 | |
41 | bool IReflectable::_isTypeIdDuplicate(UINT32 typeId) |
42 | { |
43 | if(typeId == TID_Abstract) |
44 | return false; |
45 | |
46 | return IReflectable::_getRTTIfromTypeId(typeId) != nullptr; |
47 | } |
48 | |
49 | bool IReflectable::isDerivedFrom(RTTITypeBase* base) |
50 | { |
51 | return getRTTI()->isDerivedFrom(base); |
52 | } |
53 | |
54 | void IReflectable::_checkForCircularReferences() |
55 | { |
56 | Stack<RTTITypeBase*> todo; |
57 | |
58 | const UnorderedMap<UINT32, RTTITypeBase*>& allTypes = getAllRTTITypes(); |
59 | for(auto& entry : allTypes) |
60 | { |
61 | RTTITypeBase* myType = entry.second; |
62 | |
63 | UINT32 myNumFields = myType->getNumFields(); |
64 | for (UINT32 i = 0; i < myNumFields; i++) |
65 | { |
66 | RTTIField* myField = myType->getField(i); |
67 | |
68 | if (!myField->isReflectablePtrType()) |
69 | continue; |
70 | |
71 | RTTIReflectablePtrFieldBase* myReflectablePtrField = static_cast<RTTIReflectablePtrFieldBase*>(myField); |
72 | |
73 | RTTITypeBase* otherType = myReflectablePtrField->getType(); |
74 | UINT32 otherNumFields = otherType->getNumFields(); |
75 | for (UINT32 j = 0; j < otherNumFields; j++) |
76 | { |
77 | RTTIField* otherField = otherType->getField(j); |
78 | |
79 | if (!otherField->isReflectablePtrType()) |
80 | continue; |
81 | |
82 | RTTIReflectablePtrFieldBase* otherReflectablePtrField = static_cast<RTTIReflectablePtrFieldBase*>(otherField); |
83 | |
84 | if (myType->getRTTIId() == otherReflectablePtrField->getType()->getRTTIId() && |
85 | (!myReflectablePtrField->getInfo().flags.isSet(RTTIFieldFlag::WeakRef) && |
86 | !otherReflectablePtrField->getInfo().flags.isSet(RTTIFieldFlag::WeakRef))) |
87 | { |
88 | BS_EXCEPT(InternalErrorException, "Found circular reference on RTTI type: "+ myType->getRTTIName() |
89 | + " to type: "+ otherType->getRTTIName() + ". Either remove one of the references or mark it" |
90 | + " as a weak reference when defining the RTTI field."); |
91 | } |
92 | } |
93 | } |
94 | } |
95 | } |
96 | |
97 | UINT32 IReflectable::getTypeId() const |
98 | { |
99 | return getRTTI()->getRTTIId(); |
100 | } |
101 | |
102 | const String& IReflectable::getTypeName() const |
103 | { |
104 | return getRTTI()->getRTTIName(); |
105 | } |
106 | |
107 | RTTITypeBase* IReflectable::getRTTIStatic() |
108 | { |
109 | return IReflectableRTTI::instance(); |
110 | } |
111 | } |
112 |