diff --git a/proj/sxgame/vs2013/sxgame.vcxproj b/proj/sxgame/vs2013/sxgame.vcxproj index c6d0cbd4b2f4bce1c8356195b9170b70b6a95fbd..2e16dab93c6757bd80479bc292c96d3455221b3c 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj +++ b/proj/sxgame/vs2013/sxgame.vcxproj @@ -196,7 +196,6 @@ <ClCompile Include="..\..\..\source\game\EditorOutputsTab.cpp" /> <ClCompile Include="..\..\..\source\game\EntityFactory.cpp" /> <ClCompile Include="..\..\..\source\game\EntityManager.cpp" /> - <ClCompile Include="..\..\..\source\game\EntityPointer.cpp" /> <ClCompile Include="..\..\..\source\game\EnvSkybox.cpp" /> <ClCompile Include="..\..\..\source\game\FuncRotating.cpp" /> <ClCompile Include="..\..\..\source\game\FuncTrain.cpp" /> diff --git a/proj/sxgame/vs2013/sxgame.vcxproj.filters b/proj/sxgame/vs2013/sxgame.vcxproj.filters index d826392c715d3701fdb4c19f13d52066ae3513c7..57e82a2c547b2b30e821154fe9649143bff55863 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj.filters +++ b/proj/sxgame/vs2013/sxgame.vcxproj.filters @@ -312,9 +312,6 @@ <ClCompile Include="..\..\..\source\common\guid.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="..\..\..\source\game\EntityPointer.cpp"> - <Filter>Source Files</Filter> - </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\source\game\sxgame.h"> diff --git a/source/game/BaseAnimating.cpp b/source/game/BaseAnimating.cpp index 4a19bb739dc4a782fc1a69020555729ee25b9eaf..ee58f156ad3c0e9809ab7654ddfe57699f6e52e1 100644 --- a/source/game/BaseAnimating.cpp +++ b/source/game/BaseAnimating.cpp @@ -22,7 +22,7 @@ BEGIN_PROPTABLE(CBaseAnimating) DEFINE_FIELD_FLOATFN(m_fBaseScale, 0, "scale", "Scale", setScale, EDITOR_TEXTFIELD) //! Объект референса для цвета свечения - DEFINE_FIELD_ENTITY(m_pEntColorRef, 0, "glow_color_ref", "Glow color reference", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CBaseEntity, m_pEntColorRef, 0, "glow_color_ref", "Glow color reference", EDITOR_TEXTFIELD) //! Цвет свечения DEFINE_FIELD_VECTOR(m_vGlowColor, 0, "glow_color", "Glow color", EDITOR_TEXTFIELD) diff --git a/source/game/BaseAnimating.h b/source/game/BaseAnimating.h index bd0b17552b36160cbcb93bce68ecde43697b9132..d8d7d9ac88745073cb4d2a639ed3f24eab0fbf11 100644 --- a/source/game/BaseAnimating.h +++ b/source/game/BaseAnimating.h @@ -113,7 +113,7 @@ protected: bool m_isStatic = false; bool m_useAutoPhysbox = true; - CBaseEntity *m_pEntColorRef = NULL; + CEntityPointer<CBaseEntity> m_pEntColorRef; float3_t m_vGlowColor; virtual void initPhysics(); diff --git a/source/game/BaseEntity.cpp b/source/game/BaseEntity.cpp index 662e96671799a1c8a3d82d51b5b7392b38e6796b..6f7ff03ccb874d6eeac8470c6a458ce8a8a113c3 100644 --- a/source/game/BaseEntity.cpp +++ b/source/game/BaseEntity.cpp @@ -24,11 +24,11 @@ BEGIN_PROPTABLE_NOBASE(CBaseEntity) //! Ориентация в мире, углы эйлера или кватернион DEFINE_FIELD_ANGLESFN(m_qOrientation, 0, "rotation", "Rotation", setOrient, EDITOR_TEXTFIELD) //! Родительский объект в иерархии движения - DEFINE_FIELD_PARENT(m_pParent, 0, "parent", "Parent entity", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CBaseEntity, m_pParent, 0, "parent", "Parent entity", EDITOR_TEXTFIELD) //! Флаги объекта DEFINE_FIELD_FLAGS(m_iFlags, 0, "flags", "Flags", EDITOR_FLAGS) //! Объект-владелец - DEFINE_FIELD_ENTITY(m_pOwner, PDFF_NOEXPORT | PDFF_NOEDIT, "owner", "", EDITOR_NONE) + DEFINE_FIELD_ENTITY(CBaseEntity, m_pOwner, PDFF_NOEXPORT | PDFF_NOEDIT, "owner", "", EDITOR_NONE) //! Здоровье DEFINE_FIELD_FLOAT(m_fHealth, PDFF_NOEXPORT | PDFF_NOEDIT, "health", "", EDITOR_NONE) @@ -55,9 +55,9 @@ void CBaseEntity::setDefaults() { this->*((const char* ThisClass::*)pt->pData[i].pField) = estr; } - else if(pt->pData[i].type == PDF_PARENT) + else if(pt->pData[i].type == PDF_ENTITY) { - (this->*((CEntityPointer ThisClass::*)pt->pData[i].pField)).init(m_pMgr, this); + (this->*((CEntityPointer<CBaseEntity> ThisClass::*)pt->pData[i].pField)).init(m_pMgr, this); } } } @@ -385,37 +385,9 @@ bool CBaseEntity::setKV(const char * name, const char * value) return(true); } return(false); - case PDF_PARENT: - (this->*((CEntityPointer ThisClass::*)field->pField)).setEntityName(value); - break; case PDF_ENTITY: - pEnt = m_pMgr->findEntityByName(value); - if(pEnt || !value[0]) - { - if(field->type == PDF_PARENT) - { - setParent(pEnt); - } - else - { - // check type of pEnt - if(field->pfnCheckType && !field->pfnCheckType(pEnt)) - { - LibReport(REPORT_MSG_LEVEL_ERROR, "Unable to set entity field '%s' to entity '%s'. Invalid class. Ent: %s", name, value, m_szName); - return(false); - } - if(field->fnSet.e) - { - (this->*(field->fnSet.e))(pEnt); - } - else - { - this->*((CBaseEntity* ThisClass::*)field->pField) = pEnt; - } - } - return(true); - } - return(false); + (this->*((CEntityPointer<CBaseEntity> ThisClass::*)field->pField)).setEntityName(value); + return(true); case PDF_FLAGS: if(1 == sscanf(value, "%d", &d)) { @@ -544,19 +516,8 @@ bool CBaseEntity::getKV(const char * name, char * out, int bufsize) //f3 = SMMatrixToEuler(q.GetMatrix()); sprintf_s(out, bufsize, "%f %f %f %f", q.x, q.y, q.z, q.w); break; - case PDF_PARENT: - (this->*((CEntityPointer ThisClass::*)field->pField)).getEntityName(out, bufsize); - break; case PDF_ENTITY: - pEnt = this->*((CBaseEntity* ThisClass::*)field->pField); - if(!pEnt) - { - sprintf_s(out, bufsize, ""); - } - else - { - sprintf_s(out, bufsize, "%s", pEnt->getName()); - } + (this->*((CEntityPointer<CBaseEntity> ThisClass::*)field->pField)).getEntityName(out, bufsize); break; case PDF_OUTPUT: { @@ -1027,13 +988,13 @@ void CBaseEntity::renderEditor(bool is3D) } -void CBaseEntity::registerPointer(CEntityPointer *pPtr) +void CBaseEntity::registerPointer(IEntityPointer *pPtr) { ScopedSpinLock lock(m_slPointers); m_aPointers.push_back(pPtr); } -void CBaseEntity::unregisterPointer(CEntityPointer *pPtr) +void CBaseEntity::unregisterPointer(IEntityPointer *pPtr) { ScopedSpinLock lock(m_slPointers); int idx = m_aPointers.indexOf(pPtr); diff --git a/source/game/BaseEntity.h b/source/game/BaseEntity.h index ff40b13494654a48598c57171533bea63969354f..ad35a5c17fa515d1560c67e8b2bc7b89d5410e00 100644 --- a/source/game/BaseEntity.h +++ b/source/game/BaseEntity.h @@ -45,6 +45,8 @@ class SXGAME_EXPORT CBaseEntity DECLARE_PROPTABLE(); friend class CEntityManager; + + template<typename T> friend class CEntityPointer; public: @@ -170,9 +172,9 @@ private: const XGUID *m_pGUID = NULL; SpinLock m_slPointers; - Array<CEntityPointer*> m_aPointers; - void registerPointer(CEntityPointer *pPtr); - void unregisterPointer(CEntityPointer *pPtr); + Array<IEntityPointer*> m_aPointers; + void registerPointer(IEntityPointer *pPtr); + void unregisterPointer(IEntityPointer *pPtr); void notifyPointers(); void onParentSet(CBaseEntity *pNewParent); @@ -215,12 +217,12 @@ protected: //! Родитель // CBaseEntity *m_pParent = NULL; - CEntityPointer m_pParent; + CEntityPointer<CBaseEntity> m_pParent; //! Индекс кости родителя int m_iParentAttachment = -1; //! Владелец - CBaseEntity *m_pOwner = NULL; + CEntityPointer<CBaseEntity> m_pOwner; //! Вызывается на стадии синхронизации virtual void onSync() diff --git a/source/game/BaseTool.cpp b/source/game/BaseTool.cpp index e7d1be26f0c896f6c1c0c0ec6ffd0c6e65f1cbae..bbf92e0e6520a533b46bf68874e07e8a5b14ced1 100644 --- a/source/game/BaseTool.cpp +++ b/source/game/BaseTool.cpp @@ -179,7 +179,7 @@ void CBaseTool::secondaryAction(BOOL st) m_bInSecondaryAction = st != FALSE; if(m_iZoomable) { - ((CPlayer*)m_pOwner)->getCrosshair()->enable(!st); + ((CPlayer*)m_pOwner.getEntity())->getCrosshair()->enable(!st); } } @@ -238,7 +238,7 @@ void CBaseTool::onSync() { if(m_pOwner) { - float3_t ang = ((CPlayer*)m_pOwner)->getWeaponDeltaAngles(); + float3_t ang = ((CPlayer*)m_pOwner.getEntity())->getWeaponDeltaAngles(); m_qOffsetOrient = m_qSlotRotResult * SMQuaternion(ang.x, 'x') * SMQuaternion(ang.y, 'y') * SMQuaternion(ang.z, 'z'); } else @@ -265,7 +265,7 @@ void CBaseTool::_update(float dt) float3 start = m_pParent->getPos(); float3 dir = m_pParent->getOrient() * float3(0.0f, 0.0f, 1.0f); float3 end = start + dir * m_fCenterLength; - btKinematicClosestNotMeRayResultCallback cb(((CBaseCharacter*)m_pOwner)->getBtCollisionObject(), F3_BTVEC(start), F3_BTVEC(end)); + btKinematicClosestNotMeRayResultCallback cb(((CBaseCharacter*)m_pOwner.getEntity())->getBtCollisionObject(), F3_BTVEC(start), F3_BTVEC(end)); SPhysics_GetDynWorld()->rayTest(F3_BTVEC(start), F3_BTVEC(end), cb); m_isClose = cb.hasHit(); @@ -344,7 +344,7 @@ void CBaseTool::_rezoom() m_qSlotRotResult = SMquaternionSlerp(SMquaternionSlerp(m_qSlotRot, m_qSlotRotClose, m_fCloseProgress), m_qSlotRotAim, m_fZoomProgress); if(m_pOwner && m_pOwner->getClassName() && !fstrcmp(m_pOwner->getClassName(), "player")) { - ((CPlayer*)m_pOwner)->getCamera()->getCamera()->setFOV(SMToRadian(vlerp(*r_default_fov, *r_default_fov - 10.0f, m_fZoomProgress))); + ((CPlayer*)m_pOwner.getEntity())->getCamera()->getCamera()->setFOV(SMToRadian(vlerp(*r_default_fov, *r_default_fov - 10.0f, m_fZoomProgress))); } } diff --git a/source/game/BaseWeapon.cpp b/source/game/BaseWeapon.cpp index fda77236f49b26bb1e018df98b1b522958ea1f7f..67f5c8803f5bbcb3e3cf75a34eee39b56ff4cc73 100644 --- a/source/game/BaseWeapon.cpp +++ b/source/game/BaseWeapon.cpp @@ -230,7 +230,7 @@ void CBaseWeapon::secondaryAction(BOOL st) m_bInSecondaryAction = st != FALSE; if(m_iZoomable) { - ((CPlayer*)m_pOwner)->getCrosshair()->enable(!st); + ((CPlayer*)m_pOwner.getEntity())->getCrosshair()->enable(!st); } } @@ -254,7 +254,7 @@ void CBaseWeapon::reload() printf(COLOR_MAGENTA "Mag full!\n" COLOR_RESET); return; } - int count = ((CBaseCharacter*)m_pOwner)->getInventory()->consumeItems(m_szLoadedAmmo, iWantLoad); + int count = ((CBaseCharacter*)m_pOwner.getEntity())->getInventory()->consumeItems(m_szLoadedAmmo, iWantLoad); if(count) { bool isFast = m_iCapacity == m_iCurrentLoad; @@ -283,7 +283,7 @@ void CBaseWeapon::reload() if(pHUD) { pHUD->setWeaponCurrentLoad((m_pMag ? m_pMag->getLoad() : 0) + m_iCurrentLoad); - pHUD->setWeaponMaxAmmo(((CBaseCharacter*)m_pOwner)->getInventory()->getItemCount(m_szLoadedAmmo)); + pHUD->setWeaponMaxAmmo(((CBaseCharacter*)m_pOwner.getEntity())->getInventory()->getItemCount(m_szLoadedAmmo)); } } else @@ -505,12 +505,12 @@ void CBaseWeapon::updateHUDinfo() { if(m_pOwner) { - CHUDcontroller * pHUD = ((CBaseCharacter*)m_pOwner)->getHUDcontroller(); + CHUDcontroller *pHUD = ((CBaseCharacter*)m_pOwner.getEntity())->getHUDcontroller(); if(pHUD) { pHUD->setWeaponMaxLoad((m_pMag ? m_pMag->getCapacity() : 0)/* + m_iCapacity*/); pHUD->setWeaponCurrentLoad((m_pMag ? m_pMag->getLoad() : 0) + m_iCurrentLoad); - pHUD->setWeaponMaxAmmo(((CBaseCharacter*)m_pOwner)->getInventory()->getItemCount(m_szLoadedAmmo)); + pHUD->setWeaponMaxAmmo(((CBaseCharacter*)m_pOwner.getEntity())->getInventory()->getItemCount(m_szLoadedAmmo)); } } } diff --git a/source/game/EditorObject.cpp b/source/game/EditorObject.cpp index f30dcc9bfd0bcf962d57df10691813f903173e60..11af1e264f46b7b7d47f0209a4a20f45149e92c2 100644 --- a/source/game/EditorObject.cpp +++ b/source/game/EditorObject.cpp @@ -40,13 +40,22 @@ void CEditorObject::_iniFieldList() { proptable_t *pTable = CEntityFactoryMap::GetInstance()->getPropTable(m_szClassName); propdata_t *pField = NULL; - X_PROP_FIELD xField; + X_PROP_FIELD xField = {}; for(UINT i = 0; i < 16; ++i) { m_aszFlags[i] = NULL; } + { + xField.editorType = XPET_TEXT; + xField.szHelp = ""; + xField.szKey = "guid"; + xField.szName = "GUID"; + + m_aFields.push_back(xField); + } + while(pTable) { for(int i = 0; i < pTable->numFields; ++i) @@ -322,7 +331,14 @@ const char* XMETHODCALLTYPE CEditorObject::getKV(const char *szKey) char tmp[4096]; - m_pEntity->getKV(szKey, tmp, sizeof(tmp)); + if(!fstrcmp(szKey, "guid")) + { + XGUIDToSting(*m_pEntity->getGUID(), tmp, sizeof(tmp)); + } + else + { + m_pEntity->getKV(szKey, tmp, sizeof(tmp)); + } m_msPropCache[szKey] = tmp; return(m_msPropCache[szKey].c_str()); diff --git a/source/game/EntityManager.cpp b/source/game/EntityManager.cpp index 92107cac1841c1a07654d8eeee5697d6f28a80cc..0317024cd2de051a5a0880ec26c6f1ab9619c49e 100644 --- a/source/game/EntityManager.cpp +++ b/source/game/EntityManager.cpp @@ -1301,18 +1301,18 @@ CBaseline *CEntityManager::deserializeBaseline(ID id, INETbuff *pBuf) } #endif -void CEntityManager::registerWaitForGUID(const XGUID &guid, CEntityPointer *pPtr) +void CEntityManager::registerWaitForGUID(const XGUID &guid, IEntityPointer *pPtr) { ScopedSpinLock lock(m_slWaitingPointers); m_maWaitingPointers[guid].push_back(pPtr); } -void CEntityManager::unregisterWaitForGUID(const XGUID &guid, CEntityPointer *pPtr) +void CEntityManager::unregisterWaitForGUID(const XGUID &guid, IEntityPointer *pPtr) { ScopedSpinLock lock(m_slWaitingPointers); - Array<CEntityPointer*> &list = m_maWaitingPointers[guid]; + Array<IEntityPointer*> &list = m_maWaitingPointers[guid]; int idx = list.indexOf(pPtr); assert(idx >= 0); @@ -1330,10 +1330,10 @@ void CEntityManager::notifyWaitForGUID(const XGUID &guid, CBaseEntity *pEnt) { ScopedSpinLock lock(m_slWaitingPointers); - const Map<XGUID, Array<CEntityPointer*>>::Node *pNode; + const Map<XGUID, Array<IEntityPointer*>>::Node *pNode; if(m_maWaitingPointers.KeyExists(guid, &pNode)) { - Array<CEntityPointer*> &list = m_maWaitingPointers[guid]; + Array<IEntityPointer*> &list = m_maWaitingPointers[guid]; for(UINT i = 0, l = list.size(); i < l; ++i) { list[i]->onWaitDone(pEnt); diff --git a/source/game/EntityManager.h b/source/game/EntityManager.h index a411a015b157d6ac1be1b093b48c19cd9cc4f9e9..7355d911ade294ab59460ab7a1b78634278163df 100644 --- a/source/game/EntityManager.h +++ b/source/game/EntityManager.h @@ -89,6 +89,7 @@ class CEntityManager friend class CBaseEntity; friend class CEntityFactoryMap; + template<typename T> friend class CEntityPointer; public: CEntityManager(); @@ -183,10 +184,10 @@ protected: private: void finalRemove(); - Map<XGUID, Array<CEntityPointer*>> m_maWaitingPointers; + Map<XGUID, Array<IEntityPointer*>> m_maWaitingPointers; SpinLock m_slWaitingPointers; - void registerWaitForGUID(const XGUID &guid, CEntityPointer *pPtr); - void unregisterWaitForGUID(const XGUID &guid, CEntityPointer *pPtr); + void registerWaitForGUID(const XGUID &guid, IEntityPointer *pPtr); + void unregisterWaitForGUID(const XGUID &guid, IEntityPointer *pPtr); void notifyWaitForGUID(const XGUID &guid, CBaseEntity *pEnt); bool m_isOldImported = false; diff --git a/source/game/EntityPointer.cpp b/source/game/EntityPointer.cpp deleted file mode 100644 index 64764639e83db911e3f7dd916efe8baf0bd3c263..0000000000000000000000000000000000000000 --- a/source/game/EntityPointer.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "EntityPointer.h" -#include "BaseEntity.h" - -CEntityPointer::~CEntityPointer() -{ - if(m_pEntity) - { - m_pEntity->unregisterPointer(this); - } - - unregisterWait(); -} - -void CEntityPointer::setEntityName(const char *szName) -{ - if(szName[0] == '{') - { - XGUID guid; - if(XGUIDFromString(&guid, szName)) - { - setEntityGUID(guid); - return; - } - } - - setEntity(m_pMgr->findEntityByName(szName)); -} - -void CEntityPointer::setEntityGUID(const XGUID &guid) -{ - CBaseEntity *pEnt = m_pMgr->getByGUID(guid); - setEntity(pEnt); - if(!pEnt) - { - m_guid = guid; - registerWait(); - } -} - -void CEntityPointer::setEntity(CBaseEntity *pEnt) -{ - if(m_pEntity != pEnt) - { - unregisterWait(); - - if(m_pEntity) - { - onLinkBroken(m_pEntity); - } - m_pEntity = pEnt; - if(pEnt) - { - m_guid = *pEnt->getGUID(); - } - else - { - m_guid = XGUID(); - } - if(m_pEntity) - { - onLinkEstablished(m_pEntity); - } - } -} - -CBaseEntity* CEntityPointer::getEntity() -{ - return(m_pEntity); -} - -CBaseEntity* CEntityPointer::operator->() -{ - return(getEntity()); -} -CEntityPointer::operator CBaseEntity*() -{ - return(getEntity()); -} - -CEntityPointer& CEntityPointer::operator=(CBaseEntity *pEnt) -{ - setEntity(pEnt); - return(*this); -} - -void CEntityPointer::getEntityName(char *szOutput, int iBufSize) -{ - if(m_pEntity && m_pEntity->getName()[0]) - { - if(m_pMgr->countEntityByName(m_pEntity->getName()) == 1) - { - strncpy(szOutput, m_pEntity->getName(), iBufSize); - szOutput[iBufSize - 1] = 0; - return; - } - } - - if(m_guid == XGUID()) - { - if(iBufSize) - { - szOutput[0] = 0; - } - return; - } - - char tmp[64]; - XGUIDToSting(m_guid, tmp, sizeof(tmp)); - strncpy(szOutput, tmp, iBufSize); - szOutput[iBufSize - 1] = 0; -} -const XGUID& CEntityPointer::getGUID() -{ - return(m_guid); -} - -void CEntityPointer::init(CEntityManager *pWorld, CBaseEntity *pThisEntity) -{ - m_pMgr = pWorld; - m_pThisEntity = pThisEntity; -} - -void CEntityPointer::onLinkBroken(CBaseEntity *pOldEnt) -{ - if(m_pfnOnLinkBroken) - { - (m_pThisEntity->*m_pfnOnLinkBroken)(pOldEnt); - } -} - -void CEntityPointer::onLinkEstablished(CBaseEntity *pNewEnt) -{ - pNewEnt->registerPointer(this); - - if(m_pfnOnLinkEstablished) - { - (m_pThisEntity->*m_pfnOnLinkEstablished)(pNewEnt); - } -} - -void CEntityPointer::onTargetRemoved() -{ - onLinkBroken(NULL); - m_pEntity = NULL; - registerWait(); -} - -void CEntityPointer::registerWait() -{ - if(!m_isWaiting) - { - m_pMgr->registerWaitForGUID(m_guid, this); - m_isWaiting = true; - } -} - -void CEntityPointer::unregisterWait() -{ - if(m_isWaiting) - { - m_pMgr->unregisterWaitForGUID(m_guid, this); - m_isWaiting = false; - } -} - -void CEntityPointer::onWaitDone(CBaseEntity *pEnt) -{ - assert(m_isWaiting); - - m_isWaiting = false; - - m_pEntity = pEnt; - - onLinkEstablished(pEnt); -} diff --git a/source/game/EntityPointer.h b/source/game/EntityPointer.h index 647f3c682942b42ab8594fce79348bfc9da24b09..da7a94bbce3658bb71ad7a6751405b709c88773f 100644 --- a/source/game/EntityPointer.h +++ b/source/game/EntityPointer.h @@ -3,74 +3,267 @@ #include <gdefines.h> +class IEntityPointer +{ + friend class CBaseEntity; + friend class CEntityManager; + +private: + virtual void onTargetRemoved() = 0; + virtual void onWaitDone(CBaseEntity *pEnt) = 0; +}; + class CBaseEntity; class CEntityManager; -class CEntityPointer +template<typename T> +class CEntityPointer: public IEntityPointer { DECLARE_CLASS_NOBASE(CEntityPointer); friend class CBaseEntity; - friend class CEntityManager; public: - ~CEntityPointer(); + CEntityPointer(): + m_pfnCheckEntityType(&CEntityFactoryMap::IsEntityOfClass<T>) + { + } + + ~CEntityPointer() + { + SAFE_CALL(m_pEntity, unregisterPointer, this); + + unregisterWait(); + } //! Установка имени или GUID связанного объекта - void setEntityName(const char *szName); + void setEntityName(const char *szName) + { + if(szName[0] == '{') + { + XGUID guid; + if(XGUIDFromString(&guid, szName)) + { + setEntityGUID(guid); + return; + } + } + + CBaseEntity *pEnt = m_pMgr->findEntityByName(szName); + + if(pEnt) + { + if(m_pfnCheckEntityType(pEnt)) + { + setEntity(pEnt); + } + else + { + char tmp1[64], tmp2[64]; + XGUIDToSting(m_guid, tmp1, sizeof(tmp1)); + XGUIDToSting(*m_pThisEntity->getGUID(), tmp2, sizeof(tmp2)); + LibReport(REPORT_MSG_LEVEL_ERROR, "Unable to link entity '%s' to entity '%s'. Invalid class %s\n", tmp1, tmp2, pEnt->getClassName()); + } + } + } //! Установка GUID - void setEntityGUID(const XGUID &guid); + void setEntityGUID(const XGUID &guid) + { + CBaseEntity *pEnt = m_pMgr->getByGUID(guid); + + if(pEnt) + { + if(m_pfnCheckEntityType(pEnt)) + { + setEntity(pEnt); + } + else + { + char tmp1[64], tmp2[64]; + XGUIDToSting(m_guid, tmp1, sizeof(tmp1)); + XGUIDToSting(*m_pThisEntity->getGUID(), tmp2, sizeof(tmp2)); + LibReport(REPORT_MSG_LEVEL_ERROR, "Unable to link entity '%s' to entity '%s'. Invalid class %s\n", tmp1, tmp2, pEnt->getClassName()); + } + } + else + { + m_guid = guid; + registerWait(); + } + } //! Установка - void setEntity(CBaseEntity *pEnt); + void setEntity(T *pEnt) + { + if(m_pEntity != pEnt) + { + unregisterWait(); + + if(m_pEntity) + { + onLinkBroken(m_pEntity); + } + m_pEntity = pEnt; + if(pEnt) + { + m_guid = *pEnt->getGUID(); + } + else + { + m_guid = XGUID(); + } + if(m_pEntity) + { + onLinkEstablished(m_pEntity); + } + } + } //! Получение указателя на объект - CBaseEntity* getEntity(); + T* getEntity() + { + return(m_pEntity); + } - void getEntityName(char *szOutput, int iBufSize); - const XGUID& getGUID(); + void getEntityName(char *szOutput, int iBufSize) + { + if(m_pEntity && m_pEntity->getName()[0]) + { + if(m_pMgr->countEntityByName(m_pEntity->getName()) == 1) + { + strncpy(szOutput, m_pEntity->getName(), iBufSize); + szOutput[iBufSize - 1] = 0; + return; + } + } - CBaseEntity* operator->(); - operator CBaseEntity*(); + if(m_guid == XGUID()) + { + if(iBufSize) + { + szOutput[0] = 0; + } + return; + } - CEntityPointer& operator=(CBaseEntity *pEnt); + char tmp[64]; + XGUIDToSting(m_guid, tmp, sizeof(tmp)); + strncpy(szOutput, tmp, iBufSize); + szOutput[iBufSize - 1] = 0; + } + const XGUID& getGUID() + { + return(m_guid); + } + + T* operator->() + { + return(getEntity()); + } + operator T*() + { + return(getEntity()); + } + + CEntityPointer& operator=(T *pEnt) + { + setEntity(pEnt); + return(*this); + } //! Вызывается при разрушении связи (pEnt -- указатель на объект, если причиной разрыва связи стало не удаление объекта) template<typename F> - void setLinkBrokenListener(void(F::*func)(CBaseEntity*)) + void setLinkBrokenListener(void(F::*func)(T*)) { static_assert(std::is_base_of<CBaseEntity, F>::value, "F must be subclass of CBaseEntity"); - m_pfnOnLinkBroken = func; + m_pfnOnLinkBroken = (void(CBaseEntity::*)(T*))func; } //! Вызывается при установке связи template<typename F> - void setLinkEstablishedListener(void(F::*func)(CBaseEntity*)) + void setLinkEstablishedListener(void(F::*func)(T*)) { static_assert(std::is_base_of<CBaseEntity, F>::value, "F must be subclass of CBaseEntity"); - m_pfnOnLinkEstablished = func; + m_pfnOnLinkEstablished = (void(CBaseEntity::*)(T*))func; } private: XGUID m_guid; - CBaseEntity *m_pEntity = NULL; + T *m_pEntity = NULL; CEntityManager *m_pMgr = NULL; CBaseEntity *m_pThisEntity = NULL; + bool(*m_pfnCheckEntityType)(CBaseEntity*) = NULL; - void(CBaseEntity::*m_pfnOnLinkBroken)(CBaseEntity*) = NULL; - void(CBaseEntity::*m_pfnOnLinkEstablished)(CBaseEntity*) = NULL; + void(CBaseEntity::*m_pfnOnLinkBroken)(T*) = NULL; + void(CBaseEntity::*m_pfnOnLinkEstablished)(T*) = NULL; - void init(CEntityManager *pWorld, CBaseEntity *pThisEntity); + void init(CEntityManager *pWorld, CBaseEntity *pThisEntity) + { + m_pMgr = pWorld; + m_pThisEntity = pThisEntity; + } - void onLinkBroken(CBaseEntity *pOldEnt); - void onLinkEstablished(CBaseEntity *pNewEnt); - void onTargetRemoved(); + void onLinkBroken(T *pOldEnt) + { + if(m_pfnOnLinkBroken) + { + (m_pThisEntity->*m_pfnOnLinkBroken)(pOldEnt); + } + } + void onLinkEstablished(T *pNewEnt) + { + pNewEnt->registerPointer(this); + + if(m_pfnOnLinkEstablished) + { + (m_pThisEntity->*m_pfnOnLinkEstablished)(pNewEnt); + } + } + void onTargetRemoved() override + { + onLinkBroken(NULL); + m_pEntity = NULL; + registerWait(); + } bool m_isWaiting = false; - void registerWait(); - void unregisterWait(); - void onWaitDone(CBaseEntity *pEnt); + void registerWait() + { + if(!m_isWaiting) + { + m_pMgr->registerWaitForGUID(m_guid, this); + m_isWaiting = true; + } + } + void unregisterWait() + { + if(m_isWaiting) + { + m_pMgr->unregisterWaitForGUID(m_guid, this); + m_isWaiting = false; + } + } + void onWaitDone(CBaseEntity *pEnt) override + { + assert(m_isWaiting); + + m_isWaiting = false; + + if(m_pfnCheckEntityType(pEnt)) + { + m_pEntity = (T*)pEnt; + + onLinkEstablished((T*)pEnt); + } + else + { + char tmp1[64], tmp2[64]; + XGUIDToSting(m_guid, tmp1, sizeof(tmp1)); + XGUIDToSting(*m_pThisEntity->getGUID(), tmp2, sizeof(tmp2)); + LibReport(REPORT_MSG_LEVEL_ERROR, "Unable to link entity '%s' to entity '%s'. Invalid class %s\n", tmp1, tmp2, pEnt->getClassName()); + } + } }; #endif diff --git a/source/game/FuncTrain.cpp b/source/game/FuncTrain.cpp index 466178eb6943f88ef1285a1784121b54f6a26039..550adde21b3ef0d56f6aae4c3b13c06a5e518e18 100644 --- a/source/game/FuncTrain.cpp +++ b/source/game/FuncTrain.cpp @@ -16,7 +16,7 @@ BEGIN_PROPTABLE(CFuncTrain) DEFINE_FIELD_FLOAT(m_fSpeed, 0, "speed", "Move speed", EDITOR_TEXTFIELD) //! path_corner, с которого начнется движение - DEFINE_FIELD_ENTITY2(CPathCorner, m_pStartStop, 0, "start", "Start point", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CPathCorner, m_pStartStop, 0, "start", "Start point", EDITOR_TEXTFIELD) END_PROPTABLE() REGISTER_ENTITY(CFuncTrain, func_train); diff --git a/source/game/FuncTrain.h b/source/game/FuncTrain.h index d03ad5bc8f1c019e474d665df23609b3adb8a050..cc1630befc7d50117e8a94d1e57a27f1cd0d5299 100644 --- a/source/game/FuncTrain.h +++ b/source/game/FuncTrain.h @@ -12,8 +12,7 @@ See the license in LICENSE #define __FUNC_TRAIN_H #include "PointEntity.h" - -class CPathCorner; +#include "PathCorner.h" /*! Поезда класс \ingroup cpointentity @@ -35,7 +34,7 @@ protected: void moveFunc(float dt); //! Начальная точка движения - CPathCorner *m_pStartStop = NULL; + CEntityPointer<CPathCorner> m_pStartStop; //! Текущая точка CPathCorner *m_pCurStop = NULL; diff --git a/source/game/PathCorner.cpp b/source/game/PathCorner.cpp index 0bfe9cca48b328e1910d47261e4f92628d9dc265..a421a920c563f029f206284a56998d97e687eff8 100644 --- a/source/game/PathCorner.cpp +++ b/source/game/PathCorner.cpp @@ -21,12 +21,19 @@ BEGIN_PROPTABLE(CPathCorner) DEFINE_FIELD_FLOAT(m_fNewSpeed, 0, "speed", "New speed", EDITOR_TEXTFIELD) //! Следующая точка пути - DEFINE_FIELD_ENTITY2FN(CPathCorner, m_pNextStop, 0, "next", "Next stop", setNextPoint, EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CPathCorner, m_pNextStop, 0, "next", "Next stop", EDITOR_TEXTFIELD) + + DEFINE_FIELD_ENTITY(CPathCorner, m_pPrevStop, PDFF_NOEDIT | PDFF_NOEXPORT, "prev", "Prev stop", EDITOR_NONE) END_PROPTABLE() REGISTER_ENTITY(CPathCorner, path_corner); +CPathCorner::CPathCorner() +{ + m_pNextStop.setLinkEstablishedListener(&CPathCorner::setNextPoint); +} + CPathCorner::~CPathCorner() { setNextPoint(NULL); diff --git a/source/game/PathCorner.h b/source/game/PathCorner.h index c15064c6abead767ef84e09d3a4cc9750a68760c..2e67c98e19964cea56e672c6ae4c5d6973af0e9c 100644 --- a/source/game/PathCorner.h +++ b/source/game/PathCorner.h @@ -31,7 +31,7 @@ class CPathCorner: public CPointEntity DECLARE_CLASS(CPathCorner, CPointEntity); DECLARE_PROPTABLE(); public: - DECLARE_TRIVIAL_CONSTRUCTOR(); + DECLARE_CONSTRUCTOR(); ~CPathCorner(); //! получает координаты точки на пути на расстоянии dist от начала @@ -78,9 +78,9 @@ protected: //! @} //! Следующая точка - CPathCorner *m_pNextStop = NULL; + CEntityPointer<CPathCorner> m_pNextStop; //! Предыдущая точка - CPathCorner *m_pPrevStop = NULL; + CEntityPointer<CPathCorner> m_pPrevStop; }; #endif diff --git a/source/game/TriggerTeleport.cpp b/source/game/TriggerTeleport.cpp index 15ce00a12360a549bc8d64926d6c540cbdd32195..d96649db9b2372c0926545162c218be4254abd91 100644 --- a/source/game/TriggerTeleport.cpp +++ b/source/game/TriggerTeleport.cpp @@ -14,9 +14,9 @@ See the license in LICENSE BEGIN_PROPTABLE(CTriggerTeleport) //! Локальный маркер для относительных координат - DEFINE_FIELD_ENTITY(m_pLandmark, PDFF_NONE, "landmark", "Landmark object", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CBaseEntity, m_pLandmark, PDFF_NONE, "landmark", "Landmark object", EDITOR_TEXTFIELD) //! Цель - DEFINE_FIELD_ENTITY(m_pDestination, PDFF_NONE, "destination", "Destination landmark object", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY(CBaseEntity, m_pDestination, PDFF_NONE, "destination", "Destination landmark object", EDITOR_TEXTFIELD) END_PROPTABLE() REGISTER_ENTITY(CTriggerTeleport, trigger_teleport); diff --git a/source/game/TriggerTeleport.h b/source/game/TriggerTeleport.h index 721011d6654895ddca79351af5c59eacb673f8c0..61042aa7568c90513d6f8d444b3497c4efc64f67 100644 --- a/source/game/TriggerTeleport.h +++ b/source/game/TriggerTeleport.h @@ -31,8 +31,8 @@ protected: virtual void onTouchStart(CBaseEntity *pActivator) override; private: - CBaseEntity *m_pLandmark = NULL; - CBaseEntity *m_pDestination = NULL; + CEntityPointer<CBaseEntity> m_pLandmark; + CEntityPointer<CBaseEntity> m_pDestination; }; #endif diff --git a/source/game/proptable.h b/source/game/proptable.h index 7a72d969b3ddd35d9aa0d0151d912f69e0781289..40b0e428974c671ca970595fc7ac9c3f05c39585 100644 --- a/source/game/proptable.h +++ b/source/game/proptable.h @@ -51,7 +51,6 @@ enum PDF_TYPE PDF_STRING, PDF_ANGLES, PDF_ENTITY, - PDF_PARENT, PDF_FLAGS, PDF_FLAG, @@ -193,7 +192,6 @@ struct inputdata_t }; typedef void(CBaseEntity::*input_func)(inputdata_t *pInputData); -typedef bool(*PFNCHECKENTTYPE)(CBaseEntity*); struct propdata_t { @@ -205,7 +203,7 @@ struct propdata_t szEdName(NULL), editor({}) {} - propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNCHECKENTTYPE pfnCheckType, prop_editor_t ed): + propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, prop_editor_t ed): pField(f), type(t), flags(fl), @@ -213,7 +211,7 @@ struct propdata_t szEdName(edname), editor(ed) {} - propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNFIELDSET _fnSet, PFNCHECKENTTYPE pfnCheckType, prop_editor_t ed): + propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNFIELDSET _fnSet, prop_editor_t ed): pField(f), type(t), flags(fl), @@ -242,8 +240,6 @@ struct propdata_t prop_editor_t editor; PFNFIELDSET fnSet; - PFNCHECKENTTYPE pfnCheckType = NULL; - template<typename T> static fieldtype ToFieldType(T arg) { @@ -421,36 +417,31 @@ const char * GetEmptyString(); #define EDITOR_SOUND EDITOR_FILEFIELD FILE_OPTION("Select sound", "ogg") EDITOR_FILE_END() #define EDITOR_TEXTURE EDITOR_FILEFIELD FILE_OPTION("Select texture", "dds") EDITOR_FILE_END() -#define DEFINE_FIELD_STRING(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_VECTOR(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_VECTOR4(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_ANGLES(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_INT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_ENUM(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_FLOAT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_BOOL(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_ENTITY(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<CBaseEntity* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_ENTITY2(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<type* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, CEntityFactoryMap::IsEntityOfClass<type>, editor -#define DEFINE_FIELD_PARENT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<CEntityPointer DataClass::*>(&DataClass::field), PDF_PARENT, flags, keyname, edname, NULL, editor -#define DEFINE_FIELD_FLAGS(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<UINT DataClass::*>(&DataClass::field), PDF_FLAGS, flags, keyname, edname, NULL, editor - -#define DEFINE_FIELD_STRINGFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const char*>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_VECTORFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float3&>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_VECTOR4FN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float4&>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_ANGLESFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const SMQuaternion&>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_INTFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_ENUMFN(type, field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_FLOATFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, float>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_BOOLFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, bool>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_ENTITYFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<CBaseEntity* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, CBaseEntity*>(&DataClass::fn), NULL, editor -#define DEFINE_FIELD_ENTITY2FN(type, field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<type* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, type*>(&DataClass::fn), CEntityFactoryMap::IsEntityOfClass<type>, editor -//#define DEFINE_FIELD_PARENTFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_PARENT, flags, keyname, edname, fn, editor +#define DEFINE_FIELD_STRING(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, editor +#define DEFINE_FIELD_VECTOR(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, editor +#define DEFINE_FIELD_VECTOR4(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, editor +#define DEFINE_FIELD_ANGLES(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, editor +#define DEFINE_FIELD_INT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, editor +#define DEFINE_FIELD_ENUM(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, editor +#define DEFINE_FIELD_FLOAT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, editor +#define DEFINE_FIELD_BOOL(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, editor +#define DEFINE_FIELD_ENTITY(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<CEntityPointer<type> DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, editor +#define DEFINE_FIELD_FLAGS(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<UINT DataClass::*>(&DataClass::field), PDF_FLAGS, flags, keyname, edname, editor + +#define DEFINE_FIELD_STRINGFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const char*>(&DataClass::fn), editor +#define DEFINE_FIELD_VECTORFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float3&>(&DataClass::fn), editor +#define DEFINE_FIELD_VECTOR4FN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float4&>(&DataClass::fn), editor +#define DEFINE_FIELD_ANGLESFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const SMQuaternion&>(&DataClass::fn), editor +#define DEFINE_FIELD_INTFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), editor +#define DEFINE_FIELD_ENUMFN(type, field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), editor +#define DEFINE_FIELD_FLOATFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, float>(&DataClass::fn), editor +#define DEFINE_FIELD_BOOLFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, bool>(&DataClass::fn), editor //#define DEFINE_FIELD_FLAGSFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_FLAGS, flags, keyname, edname, fn, editor #define DEFINE_INPUT(method, keyname, edname, argtype) , {propdata_t::ToInputFunc<void(DataClass::*)(inputdata_t*)>(&DataClass::method), argtype, PDFF_NOEDIT | PDFF_INPUT, keyname, edname, EDITOR_NONE -#define DEFINE_OUTPUT(field, keyname, edname) , {propdata_t::ToFieldType<output_t DataClass::*>(&DataClass::field), PDF_OUTPUT, PDFF_NOEDIT | PDFF_OUTPUT, keyname, edname, NULL, EDITOR_NONE +#define DEFINE_OUTPUT(field, keyname, edname) , {propdata_t::ToFieldType<output_t DataClass::*>(&DataClass::field), PDF_OUTPUT, PDFF_NOEDIT | PDFF_OUTPUT, keyname, edname, EDITOR_NONE #define DEFINE_MESSAGE(method, keyname, edname, argtype) , {propdata_t::ToInputFunc<void(DataClass::*)(inputdata_t*)>(&DataClass::method), argtype, PDFF_NOEDIT | PDFF_MESSAGE, keyname, edname, EDITOR_NONE -#define DEFINE_FLAG(value, edname) , {(fieldtype)NULL, PDF_FLAG, value, NULL, edname, NULL, EDITOR_FLAGS +#define DEFINE_FLAG(value, edname) , {(fieldtype)NULL, PDF_FLAG, value, NULL, edname, EDITOR_FLAGS #endif