| 1 | /**************************************************************************************** |
| 2 | |
| 3 | Copyright (C) 2015 Autodesk, Inc. |
| 4 | All rights reserved. |
| 5 | |
| 6 | Use of this software is subject to the terms of the Autodesk license agreement |
| 7 | provided at the time of installation or download, or which otherwise accompanies |
| 8 | this software in either electronic or hard copy form. |
| 9 | |
| 10 | ****************************************************************************************/ |
| 11 | |
| 12 | //! \file fbxevent.h |
| 13 | #ifndef _FBXSDK_CORE_EVENT_H_ |
| 14 | #define _FBXSDK_CORE_EVENT_H_ |
| 15 | |
| 16 | #include <fbxsdk/fbxsdk_def.h> |
| 17 | |
| 18 | #include <fbxsdk/core/fbxpropertytypes.h> |
| 19 | |
| 20 | #include <fbxsdk/fbxsdk_nsbegin.h> |
| 21 | |
| 22 | /** FBX SDK event base class. |
| 23 | * An event is something that is emitted by an emitter, with the goal of being filled by the listener that listen to it. |
| 24 | * You can see that like a form that you send to some people. If those people know how to fill the form, they fill it and return |
| 25 | * it to you with the right information in it. FBX object could be used as emitter, since FbxObject is derived from FbxEmitter. |
| 26 | * Meanwhile, plug-in could be used as listener, since FbxPlugin is derived from FbxListener. |
| 27 | * The derived class of FbxEventBase contains a type ID to distinguish different types of events. |
| 28 | * FBX object can emit different types of FBX events at different conditions. |
| 29 | * \par The whole process of event is: |
| 30 | * \li 1. Create an emitter and a listener, then bind them together via the same event handler. |
| 31 | * \li 2. Emitter can emit an event at certain conditions. The event could be handled by event handler. |
| 32 | * \li 3. Once an event is emitted, the listener to this event will receive a signal. |
| 33 | * \li 4. And then the listener could process the event data according to the types of event, by calling event handler. |
| 34 | * \note The event data is process by the callback function of event handler. |
| 35 | * For example, if a certain property of a FBX object is changed, the FBX object(emitter) can emit an event which type is FbxObjectPropertyChanged. |
| 36 | * The plug-in(listener) who are listening to FbxObjectPropertyChanged, will receive a signal and take action to process the event data. |
| 37 | * \nosubgrouping |
| 38 | * \see FbxEvent FbxEventHandler FbxListener FbxEmitter |
| 39 | */ |
| 40 | class FBXSDK_DLL FbxEventBase |
| 41 | { |
| 42 | public: |
| 43 | /** |
| 44 | * \name Constructor and Destructor |
| 45 | */ |
| 46 | //@{ |
| 47 | //!Destructor |
| 48 | virtual ~FbxEventBase(); |
| 49 | //@} |
| 50 | |
| 51 | /** Retrieve the event type ID |
| 52 | * \return type id |
| 53 | */ |
| 54 | virtual int GetTypeId() const = 0; |
| 55 | |
| 56 | /** Force events to give us a name |
| 57 | * \return event name |
| 58 | */ |
| 59 | virtual const char* GetEventName() const = 0; |
| 60 | |
| 61 | protected: |
| 62 | static int GetStaticTypeId(const char*); |
| 63 | }; |
| 64 | |
| 65 | // Force events to declare a name by using an abstract method, and force them to use |
| 66 | // the proper name by making the call from FbxEvent<> go through the private static |
| 67 | // method. |
| 68 | #define FBXSDK_EVENT_DECLARE(Class) \ |
| 69 | public: virtual const char* GetEventName() const { return FbxEventName(); } \ |
| 70 | private: static const char* FbxEventName() { return #Class; } \ |
| 71 | friend class FbxEvent<Class>; \ |
| 72 | |
| 73 | // |
| 74 | // Similar to above, but to be used when you've got an event template, and the |
| 75 | // type is something know to FBX |
| 76 | // |
| 77 | #define FBXSDK_EVENT_TYPE_DECLARE(Class, FBXType) \ |
| 78 | public: virtual const char* GetEventName() const { return FbxEventName(); } \ |
| 79 | private: \ |
| 80 | static const char* FbxEventName() { \ |
| 81 | static FbxString lEventName = FbxString(#Class) + FbxString("<") + \ |
| 82 | FbxGetDataTypeFromEnum(FbxTypeOf(*((const FBXType *)0))).GetName() + ">"; \ |
| 83 | \ |
| 84 | return lEventName.Buffer(); \ |
| 85 | } \ |
| 86 | friend class FbxEvent< Class<FBXType> >; |
| 87 | |
| 88 | |
| 89 | |
| 90 | //This is for templates classes that will uses non fbxtypes in their templates |
| 91 | //We force the the creation of an UNIQUE string for each types so that we can |
| 92 | //retrieve the event within multiple DLLs |
| 93 | |
| 94 | //to be able to use this, the char EventName[] = "uniqueEventName"; must be declared |
| 95 | //globally. |
| 96 | |
| 97 | #define (ClassName, TemplateName)\ |
| 98 | template < class TemplateName, const char* T > \ |
| 99 | class ClassName: public FbxEvent< ClassName <TemplateName,T> >\ |
| 100 | {\ |
| 101 | public: virtual const char* GetEventName() const {return FbxEventName();}\ |
| 102 | private: static const char* FbxEventName() {\ |
| 103 | static FbxString lEventName = (FbxString(#ClassName) +"<"+ FbxString(T) +">");\ |
| 104 | return lEventName.Buffer();\ |
| 105 | }\ |
| 106 | friend class FbxEvent< ClassName<TemplateName, T> >; |
| 107 | |
| 108 | |
| 109 | //This is the footer macro, to put at the end to close the template class |
| 110 | //created by FBXSDK_EVENT_TEMPLATE_HEADER |
| 111 | #define ()\ |
| 112 | }; |
| 113 | |
| 114 | /** FBX event class, derived from FbxEventBase, and it contains a type ID for event. |
| 115 | * It's a template class. You can derive your own types of even. Such as: |
| 116 | * \code class FbxEventCustom : public FbxEvent<FbxEventCustom> \endcode |
| 117 | * \see FbxObjectPropertyChanged FbxEventReferencedDocument FbxEventPostExport |
| 118 | * \see FbxEventPostImport FbxEventPreExport FbxEventPreImport FbxEventPopulateSystemLibrary |
| 119 | * \nosubgrouping |
| 120 | * \remarks A FBX event is something that is emitted by an emitter, with the goal of being filled by the listener that listen to it. |
| 121 | * An object(emitter) can emit a certain type of event, the plug-in(listener) who are listening to that type of event, |
| 122 | * will receive a signal and take action to process the event data. |
| 123 | * \par The whole process of event is: |
| 124 | * \li 1. Create an emitter and a listener, then bind them together via the same event handler. |
| 125 | * \li 2. Emitter can emit an event at certain conditions. The event could be handled by event handler. |
| 126 | * \li 3. Once an event is emitted, the listener to this event will receive a signal. |
| 127 | * \li 4. And then the listener could process the event data according to the types of event, by calling event handler. |
| 128 | * \note The event data is process by the callback function of event handler. |
| 129 | * \see FbxEventBase FbxEventHandler FbxListener FbxEmitter |
| 130 | */ |
| 131 | //--------------------------------------------------- |
| 132 | // T : We use the curiously recurring template pattern |
| 133 | // to initialize the typeId of each event type |
| 134 | template<typename T> class FbxEvent : public FbxEventBase |
| 135 | { |
| 136 | public: |
| 137 | //!Destructor |
| 138 | virtual ~FbxEvent(){} |
| 139 | |
| 140 | /** Update the type ID of current event with the given type ID. |
| 141 | * \param pTypeId the new type ID. |
| 142 | */ |
| 143 | static void ForceTypeId(int pTypeId) |
| 144 | { |
| 145 | // This is to handle specific cases where the type ID must be hard coded |
| 146 | // It is useful for shared event across DLL. We can then guarantee that |
| 147 | // The ID of a certain type will always have the same ID |
| 148 | smTypeId = pTypeId; |
| 149 | } |
| 150 | |
| 151 | /** Retrieve the event type ID |
| 152 | * \note This may be called from multiple threads. |
| 153 | * \return type id |
| 154 | */ |
| 155 | virtual int GetTypeId() const |
| 156 | { |
| 157 | return GetStaticTypeId(); |
| 158 | } |
| 159 | |
| 160 | /** Retrieve the event type ID |
| 161 | * \return type id |
| 162 | */ |
| 163 | static int GetStaticTypeId() |
| 164 | { |
| 165 | if( !smTypeId ) |
| 166 | { |
| 167 | if( !smTypeId ) |
| 168 | { |
| 169 | // If this does not compile, you need to add |
| 170 | // FBXSDK_EVENT_DECLARE(YourEventClassName) to your class declaration |
| 171 | smTypeId = FbxEventBase::GetStaticTypeId(T::FbxEventName()); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | return smTypeId; |
| 176 | } |
| 177 | |
| 178 | private: |
| 179 | //! The type ID of event |
| 180 | static int smTypeId; |
| 181 | }; |
| 182 | |
| 183 | // Static members implementation |
| 184 | template<typename T> int FbxEvent<T>::smTypeId = 0; |
| 185 | |
| 186 | #include <fbxsdk/fbxsdk_nsend.h> |
| 187 | |
| 188 | #endif /* _FBXSDK_CORE_EVENT_H_ */ |
| 189 | |