|
7 | 7 |
|
8 | 8 | #include "nbl/asset/interchange/IAssetLoader.h" |
9 | 9 |
|
10 | | -//#include "nbl/ext/MitsubaLoader/CElementFactory.h" |
| 10 | +#include "nbl/ext/MitsubaLoader/PropertyElement.h" |
| 11 | +#include "nbl/ext/MitsubaLoader/CElementShape.h" |
11 | 12 | #include "nbl/ext/MitsubaLoader/CMitsubaMetadata.h" |
12 | 13 |
|
13 | 14 | #include "expat/lib/expat.h" |
@@ -36,89 +37,112 @@ class ElementPool // similar to : public std::tuple<core::vector<types>...> |
36 | 37 | }; |
37 | 38 |
|
38 | 39 | //struct, which will be passed to expat handlers as user data (first argument) see: XML_StartElementHandler or XML_EndElementHandler in expat.h |
39 | | -class ParserManager |
| 40 | +class ParserManager final |
40 | 41 | { |
41 | | - protected: |
42 | | - // TODO: need per-file/per-parse contexts and per-load (one shapegroup, one metadata, one stack, etc. - basically the members of `ParserManager` now) |
43 | | - struct Context |
| 42 | + public: |
| 43 | + //! Constructor |
| 44 | + ParserManager(); |
| 45 | + |
| 46 | + // |
| 47 | + static void elementHandlerStart(void* _data, const char* _el, const char** _atts); |
| 48 | + static void elementHandlerEnd(void* _data, const char* _el); |
| 49 | + |
| 50 | + struct Params |
| 51 | + { |
| 52 | + system::logger_opt_ptr logger; |
| 53 | + // for opening included XML files |
| 54 | + system::ISystem* system; |
| 55 | + asset::IAssetLoader::IAssetLoaderOverride* _override; |
| 56 | + }; |
| 57 | + struct Result |
| 58 | + { |
| 59 | + explicit inline operator bool() const {return bool(metadata);} |
| 60 | + |
| 61 | + // note that its shared between per-file contexts |
| 62 | + core::smart_refctd_ptr<CMitsubaMetadata> metadata = nullptr; |
| 63 | + // |
| 64 | + core::vector<std::pair<CElementShape*,std::string> > shapegroups = {}; |
| 65 | + }; |
| 66 | + Result parse(system::IFile* _file, const Params& _params) const; |
| 67 | + |
| 68 | + // Properties are simple XML nodes which are not `IElement` and neither children of an` IElement` |
| 69 | + // If we match any `<name` we call the `processProperty` method instead of element creation method |
| 70 | + const core::unordered_set<std::string,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> propertyElements; |
| 71 | + const CPropertyElementManager propertyElementManager; |
| 72 | + |
| 73 | + private: |
| 74 | + struct SNamedElement |
44 | 75 | { |
45 | | - /*prints this message: |
46 | | - Mitsuba loader error: |
47 | | - Invalid .xml file structure: message */ |
48 | | - void invalidXMLFileStructure(const std::string& errorMessage) const; |
| 76 | + IElement* element = nullptr; |
| 77 | + core::string name = {}; |
| 78 | + }; |
| 79 | + // the XMLs can include each other, so this stores the stuff across files |
| 80 | + struct SessionContext |
| 81 | + { |
| 82 | + // prints this message: |
| 83 | + // Mitsuba loader error: |
| 84 | + // Invalid .xml file structure: message |
| 85 | + inline void invalidXMLFileStructure(const std::string& errorMessage) const |
| 86 | + { |
| 87 | + ::nbl::ext::MitsubaLoader::invalidXMLFileStructure(params->logger,errorMessage); |
| 88 | + } |
| 89 | + // meant for parsing one file in an include chain |
| 90 | + bool parse(system::IFile* _file); |
49 | 91 |
|
| 92 | + Result* const result; |
| 93 | + const Params* const params; |
| 94 | + const ParserManager* const manager; |
| 95 | + // |
| 96 | + uint32_t sceneDeclCount = 0; |
| 97 | + // TODO: This leaks memory all over the place because destructors are not ran! |
| 98 | + ElementPool</* |
| 99 | + CElementIntegrator, |
| 100 | + CElementSensor, |
| 101 | + CElementFilm, |
| 102 | + CElementRFilter, |
| 103 | + CElementSampler, |
| 104 | + CElementShape, |
| 105 | + CElementBSDF, |
| 106 | + CElementTexture, |
| 107 | + CElementEmitter*/ |
| 108 | + > objects = {}; |
| 109 | + // aliases and names (in Mitsbua XML you can give nodes names and `ref` them) |
| 110 | + core::unordered_map<core::string,IElement*,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> handles = {}; |
| 111 | + // stack of currently processed elements, each element of index N is parent of the element of index N+1 |
| 112 | + // the scene element is a parent of all elements of index 0 |
| 113 | + core::stack<SNamedElement> elements = {}; |
| 114 | + }; |
| 115 | + // This is for a single XML File |
| 116 | + struct XMLContext |
| 117 | + { |
50 | 118 | // |
51 | 119 | inline void killParseWithError(const std::string& message) const |
52 | 120 | { |
53 | | - invalidXMLFileStructure(message); |
| 121 | + session->invalidXMLFileStructure(message); |
54 | 122 | XML_StopParser(parser,false); |
55 | 123 | } |
| 124 | + void parseElement(const char* _el, const char** _atts); |
| 125 | + void onEnd(const char* _el); |
56 | 126 |
|
57 | | - system::path currentXMLDir; |
| 127 | + SessionContext* const session; |
58 | 128 | // |
59 | | - ParserManager* manager; |
60 | | - system::logger_opt_ptr logger; |
| 129 | + const system::path currentXMLDir; |
61 | 130 | // |
62 | 131 | XML_Parser parser; |
63 | 132 | }; |
64 | | - |
65 | | - public: |
66 | | - //! Constructor |
67 | | - inline ParserManager(system::ISystem* _system, asset::IAssetLoader::IAssetLoaderOverride* _override) : |
68 | | - propertyElements({ |
69 | | - "float", "string", "boolean", "integer", |
70 | | - "rgb", "srgb", "spectrum", "blackbody", |
71 | | - "point", "vector", |
72 | | - "matrix", "rotate", "translate", "scale", "lookat" |
73 | | - }), m_system(_system), m_override(_override), m_metadata(core::make_smart_refctd_ptr<CMitsubaMetadata>()) {} |
74 | | - |
75 | | - // |
76 | | - static void elementHandlerStart(void* _data, const char* _el, const char** _atts); |
77 | | - static void elementHandlerEnd(void* _data, const char* _el); |
78 | | - |
79 | | - bool parse(system::IFile* _file, const system::logger_opt_ptr& _logger); |
80 | | - |
81 | | - void parseElement(const Context& ctx, const char* _el, const char** _atts); |
82 | | - |
83 | | - void onEnd(const Context& ctx, const char* _el); |
84 | | - |
85 | | -#if 0 |
86 | | - // |
87 | | - core::vector<std::pair<CElementShape*,std::string> > shapegroups; |
88 | | -#endif |
89 | | - // note that its shared between per-file contexts |
90 | | - core::smart_refctd_ptr<CMitsubaMetadata> m_metadata; |
91 | | - |
92 | | - private: |
93 | | - // |
94 | | - void processProperty(const Context& ctx, const char* _el, const char** _atts); |
95 | | - |
96 | | - const core::unordered_set<std::string,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> propertyElements; |
97 | | - // TODO: re-architect this and move into context so the PArserManager can be persistent |
98 | | - system::ISystem* m_system; |
99 | | - asset::IAssetLoader::IAssetLoaderOverride* m_override; |
| 133 | + |
| 134 | + struct SElementCreator |
| 135 | + { |
| 136 | + // we still push nullptr (failed creation) onto the stack, we only stop parse on catastrphic failure later on if a use of the element pops up |
| 137 | + // this is why we don't need XMLCOntext for `killParseWithError` |
| 138 | + using func_t = SNamedElement(*)(const char**/*attributes*/,SessionContext*); |
| 139 | + func_t create; |
| 140 | + bool retvalGoesOnStack; |
| 141 | + }; |
| 142 | + const core::unordered_map<std::string/*elementName*/,SElementCreator,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> createElementTable; |
100 | 143 | // |
101 | | - uint32_t m_sceneDeclCount = 0; |
102 | | - // TODO: This leaks memory all over the place because destructors are not ran! |
103 | | - ElementPool</* |
104 | | - CElementIntegrator, |
105 | | - CElementSensor, |
106 | | - CElementFilm, |
107 | | - CElementRFilter, |
108 | | - CElementSampler, |
109 | | - CElementShape, |
110 | | - CElementBSDF, |
111 | | - CElementTexture, |
112 | | - CElementEmitter*/ |
113 | | - > objects; |
114 | | - // aliases and names |
115 | | - core::unordered_map<std::string,IElement*,core::CaseInsensitiveHash,core::CaseInsensitiveEquals> handles; |
116 | | - /*stack of currently processed elements |
117 | | - each element of index N is parent of the element of index N+1 |
118 | | - the scene element is a parent of all elements of index 0 */ |
119 | | - core::stack<std::pair<IElement*,std::string> > elements; |
120 | | - |
121 | | - friend class CElementFactory; |
| 144 | + static SNamedElement processAlias(const char** _atts, SessionContext* ctx); |
| 145 | + static SNamedElement processRef(const char** _atts, SessionContext* ctx); |
122 | 146 | }; |
123 | 147 |
|
124 | 148 | } |
|
0 commit comments