Commit adcdd3f1 authored by D-AIRY's avatar D-AIRY

Terrax: load/save levels; Models: scale support (render)

parent 7bb667f9
......@@ -194,9 +194,11 @@
<ClCompile Include="..\..\..\source\terrax\CommandScale.cpp" />
<ClCompile Include="..\..\..\source\terrax\CommandSelect.cpp" />
<ClCompile Include="..\..\..\source\terrax\Grid.cpp" />
<ClCompile Include="..\..\..\source\terrax\LevelOpenDialog.cpp" />
<ClCompile Include="..\..\..\source\terrax\mainWindow.cpp" />
<ClCompile Include="..\..\..\source\terrax\PropertyWindow.cpp" />
<ClCompile Include="..\..\..\source\terrax\terrax.cpp" />
<ClCompile Include="..\..\..\source\terrax\Tools.cpp" />
<ClCompile Include="..\..\..\source\terrax\UndoManager.cpp" />
</ItemGroup>
<ItemGroup>
......@@ -217,7 +219,9 @@
<ClInclude Include="..\..\..\source\terrax\CommandRotate.h" />
<ClInclude Include="..\..\..\source\terrax\CommandScale.h" />
<ClInclude Include="..\..\..\source\terrax\CommandSelect.h" />
<ClInclude Include="..\..\..\source\terrax\LevelOpenDialog.h" />
<ClInclude Include="..\..\..\source\terrax\PropertyWindow.h" />
<ClInclude Include="..\..\..\source\terrax\Tools.h" />
<ClInclude Include="..\..\..\source\terrax\UndoManager.h" />
<ClInclude Include="..\..\..\source\terrax\Grid.h" />
<ClInclude Include="..\..\..\source\terrax\resource.h" />
......
......@@ -84,6 +84,12 @@
<ClCompile Include="..\..\..\source\terrax\CommandProperties.cpp">
<Filter>Source Files\cmd</Filter>
</ClCompile>
<ClCompile Include="..\..\..\source\terrax\LevelOpenDialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\source\terrax\Tools.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\source\terrax\terrax.rc">
......@@ -154,6 +160,12 @@
<ClInclude Include="..\..\..\source\terrax\CommandProperties.h">
<Filter>Header Files\cmd</Filter>
</ClInclude>
<ClInclude Include="..\..\..\source\terrax\LevelOpenDialog.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\source\terrax\Tools.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="..\..\..\source\terrax\resource\new.bmp">
......
......@@ -80,7 +80,26 @@ SMQuaternion XMETHODCALLTYPE CAnimatedModel::getOrientation() const
}
void XMETHODCALLTYPE CAnimatedModel::setOrientation(const SMQuaternion &qRot)
{
if(m_qRotation == qRot)
{
return;
}
m_qRotation = qRot;
m_isLocalAABBvalid = false;
}
float XMETHODCALLTYPE CAnimatedModel::getScale() const
{
return(m_fScale);
}
void XMETHODCALLTYPE CAnimatedModel::setScale(float fScale)
{
if(m_fScale == fScale)
{
return;
}
m_fScale = fScale;
m_isLocalAABBvalid = false;
}
UINT XMETHODCALLTYPE CAnimatedModel::getSkin() const
......@@ -94,11 +113,48 @@ void XMETHODCALLTYPE CAnimatedModel::setSkin(UINT uSkin)
float3 XMETHODCALLTYPE CAnimatedModel::getLocalBoundMin() const
{
return(m_pShared->getLocalBoundMin());
_updateAABB();
return(m_vLocalMin);
}
float3 XMETHODCALLTYPE CAnimatedModel::getLocalBoundMax() const
{
return(m_pShared->getLocalBoundMax());
_updateAABB();
return(m_vLocalMax);
}
void CAnimatedModel::_updateAABB() const
{
if(m_isLocalAABBvalid)
{
return;
}
float3 vMin = m_pShared->getLocalBoundMin() * m_fScale;
float3 vMax = m_pShared->getLocalBoundMax() * m_fScale;
float3 vCurrent[] = {
m_qRotation * float3(vMin.x, vMin.y, vMin.z),
m_qRotation * float3(vMin.x, vMin.y, vMax.z),
m_qRotation * float3(vMin.x, vMax.y, vMin.z),
m_qRotation * float3(vMin.x, vMax.y, vMax.z),
m_qRotation * float3(vMax.x, vMin.y, vMin.z),
m_qRotation * float3(vMax.x, vMin.y, vMax.z),
m_qRotation * float3(vMax.x, vMax.y, vMin.z),
m_qRotation * float3(vMax.x, vMax.y, vMax.z)
};
m_vLocalMin = (float3)SMVectorMin(
SMVectorMin(SMVectorMin(vCurrent[0], vCurrent[1]), SMVectorMin(vCurrent[2], vCurrent[3])),
SMVectorMin(SMVectorMin(vCurrent[4], vCurrent[5]), SMVectorMin(vCurrent[6], vCurrent[7]))
);
m_vLocalMax = (float3)SMVectorMax(
SMVectorMax(SMVectorMax(vCurrent[0], vCurrent[1]), SMVectorMax(vCurrent[2], vCurrent[3])),
SMVectorMax(SMVectorMax(vCurrent[4], vCurrent[5]), SMVectorMax(vCurrent[6], vCurrent[7]))
);
m_isLocalAABBvalid = true;
}
float4 XMETHODCALLTYPE CAnimatedModel::getColor() const
......@@ -662,7 +718,7 @@ void CAnimatedModel::render(UINT uLod)
m_pDevice->setVertexShaderConstant(m_pBoneConstantBuffer, 10);
m_pShared->render(m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition), m_uSkin, uLod, m_vColor);
m_pShared->render(SMMatrixScaling(m_fScale) * m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition), m_uSkin, uLod, m_vColor);
}
void CAnimatedModel::sync()
......
......@@ -24,6 +24,9 @@ public:
SMQuaternion XMETHODCALLTYPE getOrientation() const override;
void XMETHODCALLTYPE setOrientation(const SMQuaternion &qRot) override;
float XMETHODCALLTYPE getScale() const override;
void XMETHODCALLTYPE setScale(float fScale) override;
UINT XMETHODCALLTYPE getSkin() const override;
void XMETHODCALLTYPE setSkin(UINT uSkin) override;
......@@ -91,6 +94,7 @@ protected:
UINT m_uSkin = 0;
float4_t m_vColor{1.0f, 1.0f, 1.0f, 1.0f};
bool m_isEnabled = true;
float m_fScale = 1.0f;
IGXConstantBuffer *m_pBoneConstantBuffer = NULL;
......@@ -141,6 +145,12 @@ protected:
void playActivityNext(UINT uLayer);
bool validateLayer(UINT uLayer);
void fillBoneMatrix();
mutable bool m_isLocalAABBvalid = false;
mutable float3_t m_vLocalMin;
mutable float3_t m_vLocalMax;
void _updateAABB() const;
};
#endif
......@@ -53,7 +53,26 @@ SMQuaternion XMETHODCALLTYPE CDynamicModel::getOrientation() const
}
void XMETHODCALLTYPE CDynamicModel::setOrientation(const SMQuaternion &qRot)
{
if(m_qRotation == qRot)
{
return;
}
m_qRotation = qRot;
m_isLocalAABBvalid = false;
}
float XMETHODCALLTYPE CDynamicModel::getScale() const
{
return(m_fScale);
}
void XMETHODCALLTYPE CDynamicModel::setScale(float fScale)
{
if(m_fScale == fScale)
{
return;
}
m_fScale = fScale;
m_isLocalAABBvalid = false;
}
UINT XMETHODCALLTYPE CDynamicModel::getSkin() const
......@@ -67,11 +86,48 @@ void XMETHODCALLTYPE CDynamicModel::setSkin(UINT uSkin)
float3 XMETHODCALLTYPE CDynamicModel::getLocalBoundMin() const
{
return(m_pShared->getLocalBoundMin());
_updateAABB();
return(m_vLocalMin);
}
float3 XMETHODCALLTYPE CDynamicModel::getLocalBoundMax() const
{
return(m_pShared->getLocalBoundMax());
_updateAABB();
return(m_vLocalMax);
}
void CDynamicModel::_updateAABB() const
{
if(m_isLocalAABBvalid)
{
return;
}
float3 vMin = m_pShared->getLocalBoundMin() * m_fScale;
float3 vMax = m_pShared->getLocalBoundMax() * m_fScale;
float3 vCurrent[] = {
m_qRotation * float3(vMin.x, vMin.y, vMin.z),
m_qRotation * float3(vMin.x, vMin.y, vMax.z),
m_qRotation * float3(vMin.x, vMax.y, vMin.z),
m_qRotation * float3(vMin.x, vMax.y, vMax.z),
m_qRotation * float3(vMax.x, vMin.y, vMin.z),
m_qRotation * float3(vMax.x, vMin.y, vMax.z),
m_qRotation * float3(vMax.x, vMax.y, vMin.z),
m_qRotation * float3(vMax.x, vMax.y, vMax.z)
};
m_vLocalMin = (float3)SMVectorMin(
SMVectorMin(SMVectorMin(vCurrent[0], vCurrent[1]), SMVectorMin(vCurrent[2], vCurrent[3])),
SMVectorMin(SMVectorMin(vCurrent[4], vCurrent[5]), SMVectorMin(vCurrent[6], vCurrent[7]))
);
m_vLocalMax = (float3)SMVectorMax(
SMVectorMax(SMVectorMax(vCurrent[0], vCurrent[1]), SMVectorMax(vCurrent[2], vCurrent[3])),
SMVectorMax(SMVectorMax(vCurrent[4], vCurrent[5]), SMVectorMax(vCurrent[6], vCurrent[7]))
);
m_isLocalAABBvalid = true;
}
float4 XMETHODCALLTYPE CDynamicModel::getColor() const
......@@ -109,5 +165,5 @@ void CDynamicModel::render(UINT uLod)
return;
}
m_pShared->render(m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition), m_uSkin, uLod, m_vColor);
m_pShared->render(SMMatrixScaling(m_fScale) * m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition), m_uSkin, uLod, m_vColor);
}
......@@ -24,6 +24,9 @@ public:
SMQuaternion XMETHODCALLTYPE getOrientation() const override;
void XMETHODCALLTYPE setOrientation(const SMQuaternion &qRot) override;
float XMETHODCALLTYPE getScale() const override;
void XMETHODCALLTYPE setScale(float fScale) override;
UINT XMETHODCALLTYPE getSkin() const override;
void XMETHODCALLTYPE setSkin(UINT uSkin) override;
......@@ -49,7 +52,13 @@ protected:
UINT m_uSkin = 0;
float4_t m_vColor{1.0f, 1.0f, 1.0f, 1.0f};
bool m_isEnabled = true;
float m_fScale = 1.0f;
mutable bool m_isLocalAABBvalid = false;
mutable float3_t m_vLocalMin;
mutable float3_t m_vLocalMax;
void _updateAABB() const;
};
#endif
......@@ -805,6 +805,10 @@ void CEntityManager::setOutputTimeout(named_output_t * pOutput, inputdata_t * pD
void CEntityManager::sheduleDestroy(CBaseEntity *pEnt)
{
if(pEnt->getFlags() & EF_REMOVED)
{
return;
}
pEnt->setFlags(pEnt->getFlags() | EF_REMOVED);
m_vEntRemoveList.push_back(pEnt);
......
......@@ -202,6 +202,92 @@ BOOL EnumLevels(CLevelInfo *pInfo)
//##########################################################################
class CLevelLoadProgressListener: public IEventListener<XEventLevelProgress>
{
public:
void onEvent(const XEventLevelProgress *pData)
{
if(m_isDonning)
{
return;
}
switch(pData->type)
{
case XEventLevelProgress::TYPE_PROGRESS_BEGIN:
++m_iLoadingCount;
break;
case XEventLevelProgress::TYPE_PROGRESS_END:
--m_iLoadingCount;
break;
}
testDone();
}
void onSendBegin()
{
XEventLevelProgress ev;
ev.fProgress = 0.0f;
ev.idPlugin = -1;
ev.type = XEventLevelProgress::TYPE_PROGRESS_BEGIN;
Core_GetIXCore()->getEventChannel<XEventLevelProgress>(EVENT_LEVEL_PROGRESS_GUID)->broadcastEvent(&ev);
m_isSending = true;
m_iLoadingCount = 0;
}
void onSendDone()
{
m_isSending = false;
testDone();
}
void testDone()
{
assert(m_iLoadingCount >= 0);
if(m_isSending)
{
return;
}
if(m_iLoadingCount == 0)
{
XEventLevelProgress ev;
ev.fProgress = 0.0f;
ev.idPlugin = -1;
ev.type = XEventLevelProgress::TYPE_PROGRESS_END;
m_isDonning = true;
Core_GetIXCore()->getEventChannel<XEventLevelProgress>(EVENT_LEVEL_PROGRESS_GUID)->broadcastEvent(&ev);
m_isDonning = false;
LibReport(REPORT_MSG_LEVEL_NOTICE, COLOR_LGREEN "Level is loaded!" COLOR_RESET "\n");
}
}
protected:
bool m_isSending = false;
bool m_isDonning = false;
int m_iLoadingCount = 0;
};
CLevelLoadProgressListener g_levelProgressListener;
void EndMap()
{
if(!GameData::m_pMgr->isEditorMode())
{
GameData::m_pGameStateManager->activate("main_menu");
GameData::m_pPlayer->observe();
}
XEventLevel evLevel;
evLevel.type = XEventLevel::TYPE_UNLOAD;
evLevel.szLevelName = NULL;
g_pLevelChannel->broadcastEvent(&evLevel);
};
//##########################################################################
GameData::GameData(HWND hWnd, bool isGame):
m_hWnd(hWnd)
{
......@@ -238,6 +324,35 @@ GameData::GameData(HWND hWnd, bool isGame):
m_pMgr = new CEntityManager();
g_pLevelChannel = Core_GetIXCore()->getEventChannel<XEventLevel>(EVENT_LEVEL_GUID);
Core_GetIXCore()->getEventChannel<XEventLevelProgress>(EVENT_LEVEL_PROGRESS_GUID)->addListener(&g_levelProgressListener);
g_pLevelChannel->addListener([](const XEventLevel *pData)
{
switch(pData->type)
{
case XEventLevel::TYPE_LOAD:
{
char szPath[256];
sprintf(szPath, "levels/%s/%s.ent", pData->szLevelName, pData->szLevelName);
LibReport(REPORT_MSG_LEVEL_NOTICE, "loading entities\n");
SGame_LoadEnts(szPath);
SGame_OnLevelLoad(pData->szLevelName);
}
break;
case XEventLevel::TYPE_UNLOAD:
SGame_UnloadObjLevel();
break;
case XEventLevel::TYPE_SAVE:
{
char szPath[256];
sprintf(szPath, "levels/%s/%s.ent", pData->szLevelName, pData->szLevelName);
SGame_SaveEnts(szPath);
}
break;
}
});
m_pLightSystem = (IXLightSystem*)Core_GetIXCore()->getPluginManager()->getInterface(IXLIGHTSYSTEM_GUID);
......@@ -321,20 +436,7 @@ GameData::GameData(HWND hWnd, bool isGame):
{
UpdateSettingsDesktop();
});
Core_0RegisterConcmdArg("ent_load_level", [](int argc, const char ** argv){
if(argc != 3)
{
printf("Usage: ent_load_file <entfile> <levelname>");
return;
}
LibReport(REPORT_MSG_LEVEL_NOTICE, "load entity\n");
SGame_LoadEnts(argv[1]);
SGame_OnLevelLoad(argv[2]);
});
Core_0RegisterConcmd("ent_unload_level", [](){
SGame_UnloadObjLevel();
});
Core_0RegisterConcmdArg("ent_save_level", [](int argc, const char ** argv){
if(argc != 2)
{
......@@ -366,10 +468,19 @@ GameData::GameData(HWND hWnd, bool isGame):
printf("Usage: map <levelname>");
return;
}
EndMap();
LibReport(REPORT_MSG_LEVEL_NOTICE, "Loading level '" COLOR_LGREEN "%s" COLOR_RESET "'\n", argv[1]);
g_levelProgressListener.onSendBegin();
XEventLevel evLevel;
evLevel.type = XEventLevel::TYPE_LOAD;
evLevel.szLevelName = argv[1];
g_pLevelChannel->broadcastEvent(&evLevel);
g_levelProgressListener.onSendDone();
//SLevel_Load(argv[1], true);
......@@ -388,6 +499,7 @@ GameData::GameData(HWND hWnd, bool isGame):
bEnt->setKV("origin", "0 1 0");
}
});
Core_0RegisterConcmd("endmap", EndMap);
Core_0RegisterConcmdArg("gmode", [](int argc, const char ** argv)
{
......@@ -553,15 +665,7 @@ GameData::GameData(HWND hWnd, bool isGame):
}
});
m_pGUI->registerCallback("to_mainmenu", [](gui::IEvent * ev){
GameData::m_pGameStateManager->activate("main_menu");
//Core_0ConsoleExecCmd("observe");
GameData::m_pPlayer->observe();
XEventLevel evLevel;
evLevel.type = XEventLevel::TYPE_UNLOAD;
g_pLevelChannel->broadcastEvent(&evLevel);
//SLevel_Clear();
Core_0ConsoleExecCmd("endmap");
});
m_pGUI->registerCallback("dial_settings", [](gui::IEvent * ev){
static gui::IDesktop * pSettingsDesktop = GameData::m_pGUI->createDesktopA("menu_settings", "menu/settings.html");
......
......@@ -11,7 +11,8 @@ See the license in LICENSE
*/
BEGIN_PROPTABLE(CPropStatic)
//empty
//! Масштаб модели
DEFINE_FIELD_FLOATFN(m_fScale, 0, "scale", "Scale", onSetScale, EDITOR_TEXTFIELD)
END_PROPTABLE()
REGISTER_ENTITY(CPropStatic, prop_static);
......@@ -51,3 +52,13 @@ void CPropStatic::removePhysBody()
SPhysics_RemoveShape(m_pRigidBody);
mem_delete(m_pRigidBody);
}
void CPropStatic::onSetScale(float fScale)
{
m_fScale = fScale;
if(m_pModel)
{
m_pModel->setScale(fScale);
}
}
......@@ -28,6 +28,8 @@ public:
void createPhysBody() override;
void removePhysBody() override;
protected:
void onSetScale(float fScale);
float m_fScale = 1.0f;
};
#endif
......@@ -61,7 +61,7 @@ void CLevel::clear()
#endif
//SGame_UnloadObjLevel();
Core_0ConsoleExecCmd("ent_unload_level");
// Core_0ConsoleExecCmd("ent_unload_level");
// SPhysics_UnloadGeom();
SAIG_Clear();
if(!m_isServerMode)
......@@ -117,7 +117,7 @@ void CLevel::load(const char *szName, bool isGame)
}
}
if (pConfig->keyExists("level", "entity"))
/*if (pConfig->keyExists("level", "entity"))
{
//LibReport(REPORT_MSG_LEVEL_NOTICE, " load entity\n");
sprintf(szFullPathEntity, "%s%s/%s", Core_RStringGet(G_RI_STRING_PATH_GS_LEVELS), szName, pConfig->getKey("level", "entity"));
......@@ -130,7 +130,7 @@ void CLevel::load(const char *szName, bool isGame)
{
LibReport(REPORT_MSG_LEVEL_WARNING, "not found file of entity '%s'", szFullPathEntity);
}
}
}*/
/*if (pConfig->keyExists("level", "physic"))
{
......@@ -250,13 +250,13 @@ void CLevel::load(const char *szName, bool isGame)
}
}
Core_0ConsoleExecCmd("ent_load_level \"%s\" \"%s\"", szFullPathEntity, szName);
// Core_0ConsoleExecCmd("ent_load_level \"%s\" \"%s\"", szFullPathEntity, szName);
//SGame_OnLevelLoad(szName);
mem_release(pConfig);
LibReport(REPORT_MSG_LEVEL_NOTICE, "level '%s' loaded!\n", szName);
//LibReport(REPORT_MSG_LEVEL_NOTICE, "level '%s' loaded!\n", szName);
}
void CLevel::save(const char *szName)
......
......@@ -756,11 +756,11 @@ void SkyXEngine_InitViewports()
GetClientRect(g_hBottomRightWnd, &rc);
g_pBottomRightSwapChain = pContext->createSwapChain(rc.right - rc.left, rc.bottom - rc.top, g_hBottomRightWnd);
g_BottomRightDepthStencilSurface = pContext->createDepthStencilSurface(rc.right - rc.left, rc.bottom - rc.top, GXFMT_D24S8, GXMULTISAMPLE_NONE);
/*
GetClientRect(g_pGuiWnd, &rc);
g_pGuiSwapChain = pContext->createSwapChain(rc.right - rc.left, rc.bottom - rc.top, g_pGuiWnd);
g_pGuiDepthStencilSurface = pContext->createDepthStencilSurface(rc.right - rc.left, rc.bottom - rc.top, GXFMT_D24S8, GXMULTISAMPLE_NONE);
*/
g_pCameraConstantBuffer = pContext->createConstantBuffer(sizeof(SMMATRIX));
}
......@@ -1017,7 +1017,7 @@ void SkyXEngine_Frame(DWORD timeDelta)
g_pTopRightSwapChain->swapBuffers();
g_pBottomLeftSwapChain->swapBuffers();
g_pBottomRightSwapChain->swapBuffers();
g_pGuiSwapChain->swapBuffers();
// g_pGuiSwapChain->swapBuffers();
#endif
Core_PEndSection(PERF_SECTION_RENDER_PRESENT);
......@@ -1089,14 +1089,14 @@ void SkyXEngine_Frame(DWORD timeDelta)
XRender2D(views[i], fScales[i], false);
mem_release(pBackBuffer);
}
/*
IGXSurface *pBackBuffer = g_pGuiSwapChain->getColorTarget();
pDXDevice->setColorTarget(pBackBuffer);
pDXDevice->setDepthStencilSurface(g_pGuiDepthStencilSurface);
pDXDevice->clear(GXCLEAR_COLOR | GXCLEAR_DEPTH | GXCLEAR_STENCIL);
XGuiRender();
mem_release(pBackBuffer);
*/
//#############################################################################
SRender_SetCamera(p3DCamera);
pDXDevice->setColorTarget(NULL);
......@@ -2003,6 +2003,10 @@ bool SkyXEngine_CycleMainIteration()
Core_PStartSection(PERF_SECTION_WMSG_PROC);
while(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
return(false);
}
if(g_hAccelTable && TranslateAccelerator(GetParent((HWND)SGCore_GetHWND()), g_hAccelTable, &msg))
{
continue;
......
......@@ -34,6 +34,7 @@ bool CCommandCreate::exec()
m_pObject->create();
g_pLevelObjects.push_back(m_pObject);
m_pObject->AddRef();
XUpdatePropWindow();
return(true);
......
#include "LevelOpenDialog.h"
#include "resource.h"
#include <windowsx.h>
#include <commctrl.h>
struct CLevelInfo
{
char m_szName[MAX_LEVEL_STRING]; //!< имя папки уровня
char m_szLocalName[MAX_LEVEL_STRING]; //!< Отображаемое имя уровня
char m_szLastEdit[64];
//bool m_bHasPreview;
bool m_isIndoor;
HANDLE m_hFind = NULL; //!< для внутреннего использования
};
BOOL GetLastWriteTime(const char *szFile, LPTSTR lpszString)
{
FILETIME ftCreate, ftAccess, ftWrite;
SYSTEMTIME stUTC, stLocal;
DWORD dwRet;
HANDLE hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
return(FALSE);
}
// Retrieve the file times for the file.
if(!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
{
return(FALSE);
}
CloseHandle(hFile);
// Convert the last-write time to local time.
FileTimeToSystemTime(&ftWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
// Build a string showing the date and time.
sprintf(lpszString,
TEXT("%02d.%02d.%d %02d:%02d"),
stLocal.wDay, stLocal.wMonth, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
return(TRUE);
}
BOOL EnumLevels(CLevelInfo *pInfo)
{
pInfo->m_szName[0] = 0;
pInfo->m_szLocalName[0] = 0;
pInfo->m_szLastEdit[0] = 0;
WIN32_FIND_DATA fd;
bool bFound = false;
if(!pInfo->m_hFind)
{
if((pInfo->m_hFind = ::FindFirstFile((String(Core_RStringGet(G_RI_STRING_PATH_GS_LEVELS)) + "*").c_str(), &fd)) != INVALID_HANDLE_VALUE)
{
bFound = true;
}
}
else
{
if(::FindNextFile(pInfo->m_hFind, &fd))
{
bFound = true;
}
}
if(bFound)
{
while(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")))
{
bFound = false;
if(::FindNextFile(pInfo->m_hFind, &fd))
{
if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, ".."))
{
bFound = true;
break;
}
}
else
{
break;
}
}
}
if(!bFound)
{
if(INVALID_HANDLE_VALUE != pInfo->m_hFind)
{
::FindClose(pInfo->m_hFind);
}
return(FALSE);
}
strncpy(pInfo->m_szName, fd.cFileName, MAX_LEVEL_STRING - 1);
{
char szFullPath[1024];
sprintf(szFullPath, "%s%s/%s.lvl", Core_RStringGet(G_RI_STRING_PATH_GS_LEVELS), pInfo->m_szName, pInfo->m_szName);
GetLastWriteTime(szFullPath, pInfo->m_szLastEdit);
ISXConfig *pConfig = Core_OpConfig(szFullPath);
if(pConfig->keyExists("level", "local_name"))
{
strncpy(pInfo->m_szLocalName, pConfig->getKey("level", "local_name"), MAX_LEVEL_STRING - 1);
}
else
{
strncpy(pInfo->m_szLocalName, fd.cFileName, MAX_LEVEL_STRING - 1);