/src/assimp/code/AssetLib/FBX/FBXProperties.h
Line | Count | Source |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2026, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution. |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /** @file FBXProperties.h |
43 | | * @brief FBX dynamic properties |
44 | | */ |
45 | | #ifndef INCLUDED_AI_FBX_PROPERTIES_H |
46 | | #define INCLUDED_AI_FBX_PROPERTIES_H |
47 | | |
48 | | #include "FBXCompileConfig.h" |
49 | | #include <memory> |
50 | | #include <string> |
51 | | |
52 | | namespace Assimp { |
53 | | namespace FBX { |
54 | | |
55 | | // Forward declarations |
56 | | class Element; |
57 | | |
58 | | /** |
59 | | * Represents a dynamic property. Type info added by deriving classes, |
60 | | * see #TypedProperty. |
61 | | * Example: |
62 | | * |
63 | | * @verbatim |
64 | | * P: "ShininessExponent", "double", "Number", "",0.5 |
65 | | * @endvebatim |
66 | | */ |
67 | | class Property { |
68 | | |
69 | | public: |
70 | 31.4k | virtual ~Property() = default; |
71 | | |
72 | | template <typename T> |
73 | 120k | const T* As() const { |
74 | 120k | return dynamic_cast<const T*>(this); |
75 | 120k | } Assimp::FBX::TypedProperty<aiVector3t<float> > const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<aiVector3t<float> > >() const Line | Count | Source | 73 | 81.7k | const T* As() const { | 74 | 81.7k | return dynamic_cast<const T*>(this); | 75 | 81.7k | } |
Assimp::FBX::TypedProperty<float> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<float> >() const Line | Count | Source | 73 | 4.96k | const T* As() const { | 74 | 4.96k | return dynamic_cast<const T*>(this); | 75 | 4.96k | } |
Assimp::FBX::TypedProperty<int> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<int> >() const Line | Count | Source | 73 | 17.9k | const T* As() const { | 74 | 17.9k | return dynamic_cast<const T*>(this); | 75 | 17.9k | } |
Assimp::FBX::TypedProperty<bool> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<bool> >() const Line | Count | Source | 73 | 10.3k | const T* As() const { | 74 | 10.3k | return dynamic_cast<const T*>(this); | 75 | 10.3k | } |
Assimp::FBX::TypedProperty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >() const Line | Count | Source | 73 | 264 | const T* As() const { | 74 | 264 | return dynamic_cast<const T*>(this); | 75 | 264 | } |
Assimp::FBX::TypedProperty<long> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<long> >() const Line | Count | Source | 73 | 1.84k | const T* As() const { | 74 | 1.84k | return dynamic_cast<const T*>(this); | 75 | 1.84k | } |
Assimp::FBX::TypedProperty<unsigned long> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<unsigned long> >() const Line | Count | Source | 73 | 1.77k | const T* As() const { | 74 | 1.77k | return dynamic_cast<const T*>(this); | 75 | 1.77k | } |
Assimp::FBX::TypedProperty<unsigned int> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<unsigned int> >() const Line | Count | Source | 73 | 1.36k | const T* As() const { | 74 | 1.36k | return dynamic_cast<const T*>(this); | 75 | 1.36k | } |
Assimp::FBX::TypedProperty<aiColor3D> const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<aiColor3D> >() const Line | Count | Source | 73 | 106 | const T* As() const { | 74 | 106 | return dynamic_cast<const T*>(this); | 75 | 106 | } |
Assimp::FBX::TypedProperty<aiColor4t<float> > const* Assimp::FBX::Property::As<Assimp::FBX::TypedProperty<aiColor4t<float> > >() const Line | Count | Source | 73 | 106 | const T* As() const { | 74 | 106 | return dynamic_cast<const T*>(this); | 75 | 106 | } |
|
76 | | |
77 | | protected: |
78 | 31.4k | Property() = default; |
79 | | }; |
80 | | |
81 | | template<typename T> |
82 | | class TypedProperty : public Property { |
83 | | public: |
84 | 31.4k | explicit TypedProperty(const T& value) : value(value) {}Assimp::FBX::TypedProperty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::TypedProperty(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 84 | 21 | explicit TypedProperty(const T& value) : value(value) {} |
Assimp::FBX::TypedProperty<aiVector3t<float> >::TypedProperty(aiVector3t<float> const&) Line | Count | Source | 84 | 14.8k | explicit TypedProperty(const T& value) : value(value) {} |
Unexecuted instantiation: Assimp::FBX::TypedProperty<aiColor4t<float> >::TypedProperty(aiColor4t<float> const&) Assimp::FBX::TypedProperty<bool>::TypedProperty(bool const&) Line | Count | Source | 84 | 1.40k | explicit TypedProperty(const T& value) : value(value) {} |
Assimp::FBX::TypedProperty<int>::TypedProperty(int const&) Line | Count | Source | 84 | 10.1k | explicit TypedProperty(const T& value) : value(value) {} |
Unexecuted instantiation: Assimp::FBX::TypedProperty<unsigned long>::TypedProperty(unsigned long const&) Assimp::FBX::TypedProperty<long>::TypedProperty(long const&) Line | Count | Source | 84 | 892 | explicit TypedProperty(const T& value) : value(value) {} |
Assimp::FBX::TypedProperty<float>::TypedProperty(float const&) Line | Count | Source | 84 | 4.22k | explicit TypedProperty(const T& value) : value(value) {} |
|
85 | | |
86 | 104k | const T& Value() const { |
87 | 104k | return value; |
88 | 104k | } Assimp::FBX::TypedProperty<aiVector3t<float> >::Value() const Line | Count | Source | 86 | 81.6k | const T& Value() const { | 87 | 81.6k | return value; | 88 | 81.6k | } |
Assimp::FBX::TypedProperty<float>::Value() const Line | Count | Source | 86 | 4.70k | const T& Value() const { | 87 | 4.70k | return value; | 88 | 4.70k | } |
Assimp::FBX::TypedProperty<int>::Value() const Line | Count | Source | 86 | 16.4k | const T& Value() const { | 87 | 16.4k | return value; | 88 | 16.4k | } |
Assimp::FBX::TypedProperty<bool>::Value() const Line | Count | Source | 86 | 1.38k | const T& Value() const { | 87 | 1.38k | return value; | 88 | 1.38k | } |
Assimp::FBX::TypedProperty<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::Value() const Line | Count | Source | 86 | 24 | const T& Value() const { | 87 | 24 | return value; | 88 | 24 | } |
Assimp::FBX::TypedProperty<long>::Value() const Line | Count | Source | 86 | 478 | const T& Value() const { | 87 | 478 | return value; | 88 | 478 | } |
Unexecuted instantiation: Assimp::FBX::TypedProperty<unsigned long>::Value() const Unexecuted instantiation: Assimp::FBX::TypedProperty<unsigned int>::Value() const Unexecuted instantiation: Assimp::FBX::TypedProperty<aiColor3D>::Value() const Unexecuted instantiation: Assimp::FBX::TypedProperty<aiColor4t<float> >::Value() const |
89 | | |
90 | | private: |
91 | | T value; |
92 | | }; |
93 | | |
94 | | using DirectPropertyMap = std::fbx_unordered_map<std::string,std::shared_ptr<Property> >; |
95 | | using PropertyMap = std::fbx_unordered_map<std::string,const Property*>; |
96 | | using LazyPropertyMap = std::fbx_unordered_map<std::string,const Element*>; |
97 | | |
98 | | /** |
99 | | * Represents a property table as can be found in the newer FBX files (Properties60, Properties70) |
100 | | */ |
101 | | class PropertyTable { |
102 | | public: |
103 | | // in-memory property table with no source element |
104 | 3.27k | PropertyTable() : element() {} |
105 | | PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps); |
106 | | ~PropertyTable(); |
107 | | |
108 | | const Property* Get(const std::string& name) const; |
109 | | |
110 | | // PropertyTable's need not be coupled with FBX elements so this can be nullptr |
111 | 0 | const Element* GetElement() const { |
112 | 0 | return element; |
113 | 0 | } |
114 | | |
115 | 107 | const PropertyTable* TemplateProps() const { |
116 | 107 | return templateProps.get(); |
117 | 107 | } |
118 | | |
119 | | DirectPropertyMap GetUnparsedProperties() const; |
120 | | |
121 | | private: |
122 | | LazyPropertyMap lazyProps; |
123 | | mutable PropertyMap props; |
124 | | const std::shared_ptr<const PropertyTable> templateProps; |
125 | | const Element* const element; |
126 | | }; |
127 | | |
128 | | // ------------------------------------------------------------------------------------------------ |
129 | | template <typename T> |
130 | 25.3k | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { |
131 | 25.3k | const Property* const prop = in.Get(name); |
132 | 25.3k | if( nullptr == prop) { |
133 | 4.38k | return defaultValue; |
134 | 4.38k | } |
135 | | |
136 | | // strong typing, no need to be lenient |
137 | 20.9k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); |
138 | 20.9k | if( nullptr == tprop) { |
139 | 466 | return defaultValue; |
140 | 466 | } |
141 | | |
142 | 20.5k | return tprop->Value(); |
143 | 20.9k | } aiVector3t<float> Assimp::FBX::PropertyGet<aiVector3t<float> >(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, aiVector3t<float> const&) Line | Count | Source | 130 | 8.58k | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 8.58k | const Property* const prop = in.Get(name); | 132 | 8.58k | if( nullptr == prop) { | 133 | 67 | return defaultValue; | 134 | 67 | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 8.51k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 8.51k | if( nullptr == tprop) { | 139 | 0 | return defaultValue; | 140 | 0 | } | 141 | | | 142 | 8.51k | return tprop->Value(); | 143 | 8.51k | } |
float Assimp::FBX::PropertyGet<float>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, float const&) Line | Count | Source | 130 | 2.72k | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 2.72k | const Property* const prop = in.Get(name); | 132 | 2.72k | if( nullptr == prop) { | 133 | 145 | return defaultValue; | 134 | 145 | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 2.57k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 2.57k | if( nullptr == tprop) { | 139 | 0 | return defaultValue; | 140 | 0 | } | 141 | | | 142 | 2.57k | return tprop->Value(); | 143 | 2.57k | } |
int Assimp::FBX::PropertyGet<int>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int const&) Line | Count | Source | 130 | 9.54k | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 9.54k | const Property* const prop = in.Get(name); | 132 | 9.54k | if( nullptr == prop) { | 133 | 555 | return defaultValue; | 134 | 555 | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 8.99k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 8.99k | if( nullptr == tprop) { | 139 | 54 | return defaultValue; | 140 | 54 | } | 141 | | | 142 | 8.93k | return tprop->Value(); | 143 | 8.99k | } |
Unexecuted instantiation: bool Assimp::FBX::PropertyGet<bool>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool const&) std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Assimp::FBX::PropertyGet<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Line | Count | Source | 130 | 3.56k | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 3.56k | const Property* const prop = in.Get(name); | 132 | 3.56k | if( nullptr == prop) { | 133 | 3.56k | return defaultValue; | 134 | 3.56k | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 0 | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 0 | if( nullptr == tprop) { | 139 | 0 | return defaultValue; | 140 | 0 | } | 141 | | | 142 | 0 | return tprop->Value(); | 143 | 0 | } |
long Assimp::FBX::PropertyGet<long>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, long const&) Line | Count | Source | 130 | 490 | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 490 | const Property* const prop = in.Get(name); | 132 | 490 | if( nullptr == prop) { | 133 | 12 | return defaultValue; | 134 | 12 | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 478 | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 478 | if( nullptr == tprop) { | 139 | 0 | return defaultValue; | 140 | 0 | } | 141 | | | 142 | 478 | return tprop->Value(); | 143 | 478 | } |
unsigned long Assimp::FBX::PropertyGet<unsigned long>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long const&) Line | Count | Source | 130 | 454 | inline T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { | 131 | 454 | const Property* const prop = in.Get(name); | 132 | 454 | if( nullptr == prop) { | 133 | 42 | return defaultValue; | 134 | 42 | } | 135 | | | 136 | | // strong typing, no need to be lenient | 137 | 412 | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 138 | 412 | if( nullptr == tprop) { | 139 | 412 | return defaultValue; | 140 | 412 | } | 141 | | | 142 | 0 | return tprop->Value(); | 143 | 412 | } |
|
144 | | |
145 | | // ------------------------------------------------------------------------------------------------ |
146 | | template <typename T> |
147 | 94.0k | inline T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) { |
148 | 94.0k | const Property* prop = in.Get(name); |
149 | 94.0k | if( nullptr == prop) { |
150 | 20.2k | if ( ! useTemplate ) { |
151 | 20.1k | result = false; |
152 | 20.1k | return T(); |
153 | 20.1k | } |
154 | 107 | const PropertyTable* templ = in.TemplateProps(); |
155 | 107 | if ( nullptr == templ ) { |
156 | 29 | result = false; |
157 | 29 | return T(); |
158 | 29 | } |
159 | 78 | prop = templ->Get(name); |
160 | 78 | if ( nullptr == prop ) { |
161 | 78 | result = false; |
162 | 78 | return T(); |
163 | 78 | } |
164 | 78 | } |
165 | | |
166 | | // strong typing, no need to be lenient |
167 | 73.7k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); |
168 | 73.7k | if( nullptr == tprop) { |
169 | 1 | result = false; |
170 | 1 | return T(); |
171 | 1 | } |
172 | | |
173 | 73.7k | result = true; |
174 | 73.7k | return tprop->Value(); |
175 | 73.7k | } aiVector3t<float> Assimp::FBX::PropertyGet<aiVector3t<float> >(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool&, bool) Line | Count | Source | 147 | 92.3k | inline T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) { | 148 | 92.3k | const Property* prop = in.Get(name); | 149 | 92.3k | if( nullptr == prop) { | 150 | 19.5k | if ( ! useTemplate ) { | 151 | 19.4k | result = false; | 152 | 19.4k | return T(); | 153 | 19.4k | } | 154 | 100 | const PropertyTable* templ = in.TemplateProps(); | 155 | 100 | if ( nullptr == templ ) { | 156 | 23 | result = false; | 157 | 23 | return T(); | 158 | 23 | } | 159 | 77 | prop = templ->Get(name); | 160 | 77 | if ( nullptr == prop ) { | 161 | 77 | result = false; | 162 | 77 | return T(); | 163 | 77 | } | 164 | 77 | } | 165 | | | 166 | | // strong typing, no need to be lenient | 167 | 72.8k | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 168 | 72.8k | if( nullptr == tprop) { | 169 | 1 | result = false; | 170 | 1 | return T(); | 171 | 1 | } | 172 | | | 173 | 72.8k | result = true; | 174 | 72.8k | return tprop->Value(); | 175 | 72.8k | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > Assimp::FBX::PropertyGet<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool&, bool) Line | Count | Source | 147 | 6 | inline T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) { | 148 | 6 | const Property* prop = in.Get(name); | 149 | 6 | if( nullptr == prop) { | 150 | 0 | if ( ! useTemplate ) { | 151 | 0 | result = false; | 152 | 0 | return T(); | 153 | 0 | } | 154 | 0 | const PropertyTable* templ = in.TemplateProps(); | 155 | 0 | if ( nullptr == templ ) { | 156 | 0 | result = false; | 157 | 0 | return T(); | 158 | 0 | } | 159 | 0 | prop = templ->Get(name); | 160 | 0 | if ( nullptr == prop ) { | 161 | 0 | result = false; | 162 | 0 | return T(); | 163 | 0 | } | 164 | 0 | } | 165 | | | 166 | | // strong typing, no need to be lenient | 167 | 6 | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 168 | 6 | if( nullptr == tprop) { | 169 | 0 | result = false; | 170 | 0 | return T(); | 171 | 0 | } | 172 | | | 173 | 6 | result = true; | 174 | 6 | return tprop->Value(); | 175 | 6 | } |
float Assimp::FBX::PropertyGet<float>(Assimp::FBX::PropertyTable const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool&, bool) Line | Count | Source | 147 | 1.62k | inline T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) { | 148 | 1.62k | const Property* prop = in.Get(name); | 149 | 1.62k | if( nullptr == prop) { | 150 | 707 | if ( ! useTemplate ) { | 151 | 700 | result = false; | 152 | 700 | return T(); | 153 | 700 | } | 154 | 7 | const PropertyTable* templ = in.TemplateProps(); | 155 | 7 | if ( nullptr == templ ) { | 156 | 6 | result = false; | 157 | 6 | return T(); | 158 | 6 | } | 159 | 1 | prop = templ->Get(name); | 160 | 1 | if ( nullptr == prop ) { | 161 | 1 | result = false; | 162 | 1 | return T(); | 163 | 1 | } | 164 | 1 | } | 165 | | | 166 | | // strong typing, no need to be lenient | 167 | 919 | const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); | 168 | 919 | if( nullptr == tprop) { | 169 | 0 | result = false; | 170 | 0 | return T(); | 171 | 0 | } | 172 | | | 173 | 919 | result = true; | 174 | 919 | return tprop->Value(); | 175 | 919 | } |
|
176 | | |
177 | | } //! FBX |
178 | | } //! Assimp |
179 | | |
180 | | #endif // INCLUDED_AI_FBX_PROPERTIES_H |