diff --git a/source/game/BaseAnimating.cpp b/source/game/BaseAnimating.cpp index 664ce42d7b5100035a886a6628ff7935dd3df7dd..01dcb7257987f362ae7c65532081da9461d33817 100644 --- a/source/game/BaseAnimating.cpp +++ b/source/game/BaseAnimating.cpp @@ -309,6 +309,11 @@ void CBaseAnimating::setPos(const float3 & pos) if(m_pRigidBody) { m_pRigidBody->getWorldTransform().setOrigin(F3_BTVEC(pos)); + + if(m_pMgr->isEditorMode()) + { + SPhysics_GetDynWorld()->updateSingleAabb(m_pRigidBody); + } } } @@ -318,6 +323,11 @@ void CBaseAnimating::setOrient(const SMQuaternion & q) if(m_pRigidBody) { m_pRigidBody->getWorldTransform().setRotation(Q4_BTQUAT(q)); + + if(m_pMgr->isEditorMode()) + { + SPhysics_GetDynWorld()->updateSingleAabb(m_pRigidBody); + } } } @@ -487,3 +497,12 @@ void CBaseAnimating::setSkin(int iSkin) m_iSkin = iSkin; } +void CBaseAnimating::_initEditorBoxes() +{ + // do nothing +} + +void CBaseAnimating::_releaseEditorBoxes() +{ + // do nothing +} diff --git a/source/game/BaseAnimating.h b/source/game/BaseAnimating.h index 8ddfdf2ba1373212779487aea72738c270a29a33..ec0b0755bb9302fd19f821eae8243edf8d35c681 100644 --- a/source/game/BaseAnimating.h +++ b/source/game/BaseAnimating.h @@ -59,6 +59,8 @@ public: COLLISION_GROUP getCollisionGroup(); protected: + virtual void _initEditorBoxes(); + virtual void _releaseEditorBoxes(); void inputPlayAnim(inputdata_t * pInputdata); void inputPlayAnimNext(inputdata_t * pInputdata); diff --git a/source/game/BaseEntity.cpp b/source/game/BaseEntity.cpp index 54636e9ff0779d446af1f1e2daba115ebe5f6411..d55bf9f0ff8242ea300eb2578c97bace1122a4c4 100644 --- a/source/game/BaseEntity.cpp +++ b/source/game/BaseEntity.cpp @@ -92,6 +92,8 @@ CBaseEntity::CBaseEntity(CEntityManager * pWorld): CBaseEntity::~CBaseEntity() { + _releaseEditorBoxes(); + m_pMgr->unreg(m_iId); proptable_t * pt = getPropTable(); @@ -149,6 +151,12 @@ void CBaseEntity::getSphere(float3 * center, float * radius) void CBaseEntity::setPos(const float3 & pos) { m_vPosition = pos; + + if(m_pEditorRigidBody) + { + m_pEditorRigidBody->getWorldTransform().setOrigin(F3_BTVEC(m_vPosition)); + SPhysics_GetDynWorld()->updateSingleAabb(m_pEditorRigidBody); + } } float3 CBaseEntity::getPos() @@ -860,3 +868,42 @@ void CBaseEntity::_cleanup() void CBaseEntity::onUse(CBaseEntity *pUser) { } + +void CBaseEntity::_initEditorBoxes() +{ + if(m_pEditorRigidBody) + { + return; + } + + float3 vBoxHalfSize = m_vEditorBoxSize * 0.5f; + m_pEditorCollideShape = new btBoxShape(F3_BTVEC(vBoxHalfSize)); + + btDefaultMotionState * motionState = new btDefaultMotionState(btTransform(Q4_BTQUAT(SMQuaternion()), F3_BTVEC(m_vPosition))); + btRigidBody::btRigidBodyConstructionInfo rigidBodyCI( + 0, // mass + motionState, // initial position + m_pEditorCollideShape, // collision shape of body + btVector3(0,0,0) // local inertia + ); + m_pEditorRigidBody = new btRigidBody(rigidBodyCI); + m_pEditorRigidBody->getInvMass(); + m_pEditorRigidBody->setUserPointer(this); + + SPhysics_AddShapeEx(m_pEditorRigidBody, CG_DEFAULT, CG_BULLETFIRE); +} + +void CBaseEntity::_releaseEditorBoxes() +{ + if(m_pEditorRigidBody) + { + SPhysics_RemoveShape(m_pEditorRigidBody); + } + mem_delete(m_pEditorRigidBody); + mem_delete(m_pEditorCollideShape); +} + +float3 CBaseEntity::getEditorBoxSize() +{ + return(m_vEditorBoxSize); +} diff --git a/source/game/BaseEntity.h b/source/game/BaseEntity.h index 61aecf66c51dbd5df118a18ec34f6fcf7c7aa791..7d259fd3cd28f2fb2455e77de71e50cd52f19233 100644 --- a/source/game/BaseEntity.h +++ b/source/game/BaseEntity.h @@ -134,6 +134,9 @@ public: //! Обновляет действие флагов в режиме редактора уровня virtual void updateFlags(){} + + virtual float3 getEditorBoxSize(); + private: void setClassName(const char * name); void setDefaults(); @@ -145,6 +148,8 @@ private: protected: virtual void _cleanup(); + virtual void _initEditorBoxes(); + virtual void _releaseEditorBoxes(); CEntityManager * m_pMgr; @@ -209,6 +214,14 @@ protected: void takeHealth(float fVal, CBaseEntity *pAttacker, CBaseEntity *pInflictor=NULL); bool m_bSynced; + + + //! Для редактора + //@{ + float3_t m_vEditorBoxSize = float3_t(0.16f, 0.16f, 0.16f); + btCollisionShape * m_pEditorCollideShape = NULL; + btRigidBody * m_pEditorRigidBody = NULL; + //@} }; #pragma warning(pop) diff --git a/source/game/EntityFactory.cpp b/source/game/EntityFactory.cpp index c0310ad3bbde27bf34cda930f47ed9cb87c6a4b4..fc8e0ad2e76cff7b6a2dfa8f45afad838206d0d8 100644 --- a/source/game/EntityFactory.cpp +++ b/source/game/EntityFactory.cpp @@ -55,6 +55,10 @@ CBaseEntity * CEntityFactoryMap::create(const char * szName, CEntityManager * pW { pEnt->onPostLoad(); } + if(pWorld->isEditorMode()) + { + pEnt->_initEditorBoxes(); + } return(pEnt); } return(NULL); diff --git a/source/game/EntityManager.cpp b/source/game/EntityManager.cpp index d0aaa1eba18b7869f973232cf8c24aa7a6ffbca8..bc02ce99677a19bde0431c2a364d4ea53dcb0204 100644 --- a/source/game/EntityManager.cpp +++ b/source/game/EntityManager.cpp @@ -807,4 +807,40 @@ void CEntityManager::sheduleDestroy(CBaseEntity *pEnt) { pEnt->setFlags(pEnt->getFlags() | EF_REMOVED); m_vEntRemoveList.push_back(pEnt); + + if(m_isEditorMode) + { + pEnt->_releaseEditorBoxes(); + } +} + +void CEntityManager::setEditorMode(bool isEditor) +{ + if(m_isEditorMode == isEditor) + { + return; + } + m_isEditorMode = isEditor; + + for(int i = 0, l = m_vEntList.size(); i < l; ++i) + { + CBaseEntity * pEnt = m_vEntList[i]; + if(!pEnt) + { + continue; + } + if(isEditor) + { + pEnt->_initEditorBoxes(); + } + else + { + pEnt->_releaseEditorBoxes(); + } + } +} + +bool CEntityManager::isEditorMode() +{ + return(m_isEditorMode); } diff --git a/source/game/EntityManager.h b/source/game/EntityManager.h index bad361641e3301c2be86afdc077604c3ed51ce9f..22bc7bd8bf6e8228524d757b3556cbec8e9aa245 100644 --- a/source/game/EntityManager.h +++ b/source/game/EntityManager.h @@ -108,6 +108,9 @@ public: void sheduleDestroy(CBaseEntity *pEnt); + void setEditorMode(bool isEditor = true); + bool isEditorMode(); + protected: ID reg(CBaseEntity * pEnt); void unreg(ID ent); @@ -127,6 +130,8 @@ protected: //! @warning это нужно хранить в течение работы проги, т.к. таблицы дефолтов ссылаются напрямую на этот объект ISXConfig * m_pDefaultsConf; ISXConfig * m_pDynClassConf; + + bool m_isEditorMode = false; }; #endif diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp index c1908c7d2abe78852401863510062b4fc7435e00..dde7527aca13141d752099d08e1b1f0887bbf015 100644 --- a/source/game/GameData.cpp +++ b/source/game/GameData.cpp @@ -752,6 +752,10 @@ GameData::GameData(HWND hWnd, bool isGame): m_pPlayer->setActiveTool(pTool); } + else + { + m_pMgr->setEditorMode(true); + } } GameData::~GameData() { diff --git a/source/game/sxgame.h b/source/game/sxgame.h index f435bbbd4777a693a074172509615475f08f43b2..d09dc18aef07215d6e58f34c67843a9e90291bd8 100644 --- a/source/game/sxgame.h +++ b/source/game/sxgame.h @@ -266,6 +266,9 @@ SX_LIB_API void SGame_SetDebugText(const char *szText); */ SX_LIB_API ID SGame_EntClone(ID idSrc); +/*! Находит объект по пересечению с лучем, в режиме редактора так же находит точечные объекты, в режиме игры - нет +*/ +SX_LIB_API ID SGame_EntGetByRay(const float3 &vStart, const float3 &vDir, float3 *pHitPos = NULL); #endif diff --git a/source/game/sxgame_dll.cpp b/source/game/sxgame_dll.cpp index 9c0151683d53cce9e1c8c4f38fabb37a3ebe482c..66bc9109862cd0e8f68de6cf4cf3330e98f9861b 100644 --- a/source/game/sxgame_dll.cpp +++ b/source/game/sxgame_dll.cpp @@ -10,6 +10,7 @@ See the license in LICENSE #include "sxgame.h" #include <core/sxcore.h> #include <gcore/sxgcore.h> +#include <BulletCollision/NarrowPhaseCollision/btRaycastCallback.h> #include "EntityManager.h" @@ -200,8 +201,8 @@ SX_LIB_API void SGame_EditorRender(ID id, ID id_sel_tex, const float3 *pvRenderP { SG_PRECOND(_VOID); - CBaseEntity* bEnt = SGame_EntGet(id); - if (!bEnt) + CBaseEntity* pEnt = SGame_EntGet(id); + if (!pEnt) return; SMMATRIX mView, mProj; @@ -211,9 +212,11 @@ SX_LIB_API void SGame_EditorRender(ID id, ID id_sel_tex, const float3 *pvRenderP SGCore_GetDXDevice()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&mView); SGCore_GetDXDevice()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&mProj); - if(strcmp(bEnt->getClassName(), "path_corner") == 0) + float3 vBoxSize = pEnt->getEditorBoxSize(); + + if(strcmp(pEnt->getClassName(), "path_corner") == 0) { - CPathCorner * pStartPoint = (CPathCorner*)bEnt; + CPathCorner * pStartPoint = (CPathCorner*)pEnt; if (!pStartPoint) return; @@ -230,7 +233,7 @@ SX_LIB_API void SGame_EditorRender(ID id, ID id_sel_tex, const float3 *pvRenderP { len += pCur->GetLength(); ++count; - SGCore_GetDXDevice()->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&SMMatrixTranslation(pCur->getPos())); + SGCore_GetDXDevice()->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&SMMatrixTranslation(SMMatrixScaling(vBoxSize) * pCur->getPos())); if (id == pCur->getId()) SGCore_GetDXDevice()->SetTexture(0, SGCore_LoadTexGetTex(id_sel_tex)); @@ -279,7 +282,7 @@ SX_LIB_API void SGame_EditorRender(ID id, ID id_sel_tex, const float3 *pvRenderP SGCore_GetDXDevice()->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&mView); SGCore_GetDXDevice()->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)&mProj); - SGCore_GetDXDevice()->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&(bEnt->getOrient().GetMatrix() * SMMatrixTranslation(pvRenderPos ? *pvRenderPos : bEnt->getPos()))/*bEnt->getWorldTM()*/); + SGCore_GetDXDevice()->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&(SMMatrixScaling(vBoxSize) * pEnt->getOrient().GetMatrix() * SMMatrixTranslation(pvRenderPos ? *pvRenderPos : pEnt->getPos()))/*bEnt->getWorldTM()*/); SGCore_GetDXDevice()->SetTexture(0, SGCore_LoadTexGetTex(id_sel_tex)); g_pFigureBox->DrawSubset(0); @@ -408,7 +411,7 @@ SX_LIB_API void SGame_SetDebugText(const char *szText) SX_LIB_API ID SGame_EntClone(ID idSrc) { - SG_PRECOND(NULL); + SG_PRECOND(-1); CBaseEntity *pEnt = GameData::m_pMgr->cloneEntity(GameData::m_pMgr->getById(idSrc)); if(!pEnt) @@ -418,3 +421,28 @@ SX_LIB_API ID SGame_EntClone(ID idSrc) return(pEnt->getId()); } + +SX_LIB_API ID SGame_EntGetByRay(const float3 &vStart, const float3 &vDir, float3 *pHitPos) +{ + SG_PRECOND(-1); + float3 vEnd = vStart + vDir * 10000.0f; + btCollisionWorld::ClosestRayResultCallback cb(F3_BTVEC(vStart), F3_BTVEC(vEnd)); + cb.m_collisionFilterGroup = CG_BULLETFIRE; + cb.m_collisionFilterMask = CG_ALL; + cb.m_flags |= btTriangleRaycastCallback::kF_FilterBackfaces; + SPhysics_GetDynWorld()->rayTest(F3_BTVEC(vStart), F3_BTVEC(vEnd), cb); + + if(cb.hasHit()) + { + CBaseEntity *pEnt = (CBaseEntity*)cb.m_collisionObject->getUserPointer(); + if(pEnt) + { + if(pHitPos) + { + *pHitPos = BTVEC_F3(cb.m_hitPointWorld); + } + return(pEnt->getId()); + } + } + return(-1); +} diff --git a/source/sxleveleditor/common_callback.cpp b/source/sxleveleditor/common_callback.cpp index 5c957aa887efeff5665bd64df036fb343e582a33..6bb7cbd2446fcef7e777b9328046815ff6f17178 100644 --- a/source/sxleveleditor/common_callback.cpp +++ b/source/sxleveleditor/common_callback.cpp @@ -257,7 +257,7 @@ LRESULT SXLevelEditor_RenderWindow_LClick(HWND hWnd, UINT uiMsg, WPARAM wParam, level_editor::GreenTraceSelect(); else if (level_editor::iActiveGroupType == EDITORS_LEVEL_GROUPTYPE_GAME && level_editor::idActiveElement >= 0) { - + level_editor::GameTraceSelect(); } else if (level_editor::iActiveGroupType == EDITORS_LEVEL_GROUPTYPE_AIGRID) level_editor::AIGridTraceSelect(); diff --git a/source/sxleveleditor/game_callback.cpp b/source/sxleveleditor/game_callback.cpp index 1710f4872755d8ea9512c892badb64ac14c3d66d..9167a5e602a29bc5a1506c1cb80abb8e58e76c2a 100644 --- a/source/sxleveleditor/game_callback.cpp +++ b/source/sxleveleditor/game_callback.cpp @@ -249,6 +249,29 @@ void level_editor::GameSel(int iSelected) //level_editor::pAxesHelper->setScale(float3(1, 1, 1)); } +void level_editor::GameTraceSelect() +{ + float3 vResult; + ID idEnt = -1; + ID idMtrl = -1; + + idEnt = SGame_EntGetByRay(vRayOrigin, vRayDir, &vResult); + + if(ID_VALID(idEnt)) + { + for(int i = 0, l = pListBoxList->getItemCount(); i < l; ++i) + { + if(pListBoxList->getItemData(i) == idEnt) + { + pListBoxList->setSel(i); + GameSel(i); + idMtl = idMtrl; + return; + } + } + } +} + void level_editor::GameTraceSetPos() { if (level_editor::iActiveGroupType != EDITORS_LEVEL_GROUPTYPE_GAME || level_editor::idActiveElement < 0) diff --git a/source/sxleveleditor/level_editor.h b/source/sxleveleditor/level_editor.h index dc8abcac587b07e5624f08e847e51015d5f91ca5..fbd8355567889f90b0afe93d136ac448a3aac5dd 100644 --- a/source/sxleveleditor/level_editor.h +++ b/source/sxleveleditor/level_editor.h @@ -372,6 +372,8 @@ namespace level_editor //! ��������� �������� ������� �� ������ �� ������ listbox void GameSel(int iSelect); + void GameTraceSelect(); + //! ����������� ���� � ��������� ������� � ����� ����������� void GameTraceSetPos();