port(2V0-b): EterPythonLib 窗口树实现 + EterLib 资源层
- port: PythonWindow/PythonSlotWindow/PythonGridSlotWindow/PythonWindowManager(布局/命中/事件/插槽渲染) - port: EterLib ReferenceObject/Resource/ResourceManager(资源引用与查找) - platform: EterLib Util、EterPythonLib PythonGraphic - tests: port.window_tree(需要解释器,不需要 40250 Client/pack) - 顺带补上 4 个缺失的 Godot .uid Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// 40250 EterLib/Util.cpp 的“默认代码页”那一小块。
|
||||
//
|
||||
// Util.cpp 本身是逻辑单元(LoadTextData / base64 / TokenTo*),但代码页这几个函数和它们旁边的
|
||||
// GetFontFaceFromCodePage 是连在一起的,后者靠 GDI 的 EnumFontFamiliesEx 枚举字体,win32 shim 里没有,
|
||||
// 真正的实现要等 2V0-f 的文字渲染。所以整份 Util.cpp 的移植留到那时,这里只放现在真正被调用到的
|
||||
// GetDefaultCodePage:EterPythonLib/PythonWindow.cpp 的 CTextLine::OnChangePosition 用它判断 CP_ARABIC。
|
||||
//
|
||||
// 默认值和 40250 一致:gs_codePage = 0,也就是“还没有 SetDefaultCodePage”。40250 在
|
||||
// PythonApplication 里根据 locale 调 SetDefaultCodePage(),那条路径同样等 2V0-d。
|
||||
#include "EterLib/StdAfx.h"
|
||||
#include "EterLib/Util.h"
|
||||
|
||||
static DWORD gs_codePage = 0;
|
||||
|
||||
DWORD GetDefaultCodePage()
|
||||
{
|
||||
return gs_codePage;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// CPythonGraphic(40250 EterPythonLib/PythonGraphic.cpp)的平台骨架 —— 目前只有窗口树链接时真正需要
|
||||
// 的那一个函数。
|
||||
//
|
||||
// CPythonGraphic 是 UI 的 2D 绘制层(D3D8 的正交投影、按钮的立体边框、冷却圈、截图),整份实现属于
|
||||
// 2V0-f;platform_stub.py 不认 EterPythonLib(port_map 把它划成 python 层),所以这里按手写平台桩的
|
||||
// 惯例来:先只放被引用到的符号,链接器会告诉我们下一个是谁。
|
||||
//
|
||||
// RenderCoolTimeBox:CSlotWindow::OnRender 画技能冷却扇形用的,没有渲染设备时什么都不做。
|
||||
#include "EterPythonLib/StdAfx.h"
|
||||
#include "EterPythonLib/PythonGraphic.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
|
||||
void CPythonGraphic::RenderCoolTimeBox(float fxCenter, float fyCenter, float fRadius, float fTime)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
@@ -171,5 +171,14 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
||||
add_test(NAME port.python_launcher
|
||||
COMMAND $<TARGET_FILE:port_python_launcher_test> ${MT_40250_CLIENT} ${MT_PYTHON_STDLIB_ZIP})
|
||||
set_tests_properties(port.python_launcher PROPERTIES SKIP_RETURN_CODE 77)
|
||||
|
||||
# EterPythonLib 的窗口树(批次 2V0-b)。需要解释器(CWindowManager 的构造函数就调 Python),
|
||||
# 但不需要 40250 的 Client/pack —— 布局/命中/事件都不读资源。
|
||||
add_executable(port_window_tree_test ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/port_window_tree_test.cpp)
|
||||
target_link_libraries(port_window_tree_test PRIVATE port_platform)
|
||||
add_dependencies(port_window_tree_test mtpython_stdlib)
|
||||
add_test(NAME port.window_tree
|
||||
COMMAND $<TARGET_FILE:port_window_tree_test> ${MT_PYTHON_STDLIB_ZIP})
|
||||
set_tests_properties(port.window_tree PROPERTIES SKIP_RETURN_CODE 77)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "StdAfx.h"
|
||||
#include "ReferenceObject.h"
|
||||
|
||||
CReferenceObject::CReferenceObject() : m_refCount(0), m_destructed(false)
|
||||
{
|
||||
}
|
||||
|
||||
CReferenceObject::~CReferenceObject()
|
||||
{
|
||||
}
|
||||
|
||||
void CReferenceObject::AddReference()
|
||||
{
|
||||
if (m_refCount == 0)
|
||||
OnConstruct();
|
||||
|
||||
++m_refCount;
|
||||
}
|
||||
|
||||
int CReferenceObject::GetReferenceCount()
|
||||
{
|
||||
return m_refCount;
|
||||
}
|
||||
|
||||
void CReferenceObject::AddReferenceOnly()
|
||||
{
|
||||
++m_refCount;
|
||||
}
|
||||
|
||||
void CReferenceObject::Release()
|
||||
{
|
||||
if (m_refCount > 1)
|
||||
{
|
||||
--m_refCount;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_destructed == false);
|
||||
assert(m_refCount >= 0);
|
||||
m_refCount = 0;
|
||||
OnSelfDestruct();
|
||||
}
|
||||
|
||||
void CReferenceObject::OnConstruct()
|
||||
{
|
||||
m_destructed = false;
|
||||
}
|
||||
|
||||
void CReferenceObject::OnSelfDestruct()
|
||||
{
|
||||
m_destructed = true;
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool CReferenceObject::canDestroy()
|
||||
{
|
||||
if (m_refCount > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../EterPack/EterPackManager.h"
|
||||
#include "../EterBase/CRC32.h"
|
||||
#include "../EterBase/Timer.h"
|
||||
|
||||
#include "Resource.h"
|
||||
#include "ResourceManager.h"
|
||||
|
||||
bool CResource::ms_bDeleteImmediately = false;
|
||||
|
||||
CResource::CResource(const char* c_szFileName) : me_state(STATE_EMPTY)
|
||||
{
|
||||
SetFileName(c_szFileName);
|
||||
}
|
||||
|
||||
CResource::~CResource()
|
||||
{
|
||||
}
|
||||
|
||||
void CResource::SetDeleteImmediately(bool isSet)
|
||||
{
|
||||
ms_bDeleteImmediately = isSet;
|
||||
}
|
||||
|
||||
void CResource::OnConstruct()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
void CResource::OnSelfDestruct()
|
||||
{
|
||||
if (ms_bDeleteImmediately)
|
||||
Clear();
|
||||
else
|
||||
CResourceManager::Instance().ReserveDeletingResource(this);
|
||||
}
|
||||
|
||||
void CResource::Load()
|
||||
{
|
||||
if (me_state != STATE_EMPTY)
|
||||
return;
|
||||
|
||||
const char * c_szFileName = GetFileName();
|
||||
|
||||
DWORD dwStart = ELTimer_GetMSec();
|
||||
CMappedFile file;
|
||||
LPCVOID fileData;
|
||||
|
||||
//Tracenf("Load %s", c_szFileName);
|
||||
|
||||
if (CEterPackManager::Instance().Get(file, c_szFileName, &fileData))
|
||||
{
|
||||
m_dwLoadCostMiliiSecond = ELTimer_GetMSec() - dwStart;
|
||||
//Tracef("CResource::Load %s (%d bytes) in %d ms\n", c_szFileName, file.Size(), m_dwLoadCostMiliiSecond);
|
||||
|
||||
if (OnLoad(file.Size(), fileData))
|
||||
{
|
||||
me_state = STATE_EXIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tracef("CResource::Load Error %s\n", c_szFileName);
|
||||
me_state = STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OnLoad(0, NULL))
|
||||
me_state = STATE_EXIST;
|
||||
else
|
||||
{
|
||||
Tracef("CResource::Load file not exist %s\n", c_szFileName);
|
||||
me_state = STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CResource::Reload()
|
||||
{
|
||||
Clear();
|
||||
Tracef("CResource::Reload %s\n", GetFileName());
|
||||
|
||||
CMappedFile file;
|
||||
LPCVOID fileData;
|
||||
|
||||
if (CEterPackManager::Instance().Get(file, GetFileName(), &fileData))
|
||||
{
|
||||
if (OnLoad(file.Size(), fileData))
|
||||
{
|
||||
me_state = STATE_EXIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
me_state = STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OnLoad(0, NULL))
|
||||
me_state = STATE_EXIST;
|
||||
else
|
||||
{
|
||||
me_state = STATE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CResource::TType CResource::StringToType(const char* c_szType)
|
||||
{
|
||||
return GetCRC32(c_szType, strlen(c_szType));
|
||||
}
|
||||
|
||||
int CResource::ConvertPathName(const char * c_szPathName, char * pszRetPathName, int retLen)
|
||||
{
|
||||
const char * pc;
|
||||
int len = 0;
|
||||
|
||||
for (pc = c_szPathName; *pc && len < retLen; ++pc, ++len)
|
||||
{
|
||||
if (*pc == '/')
|
||||
*(pszRetPathName++) = '\\';
|
||||
else
|
||||
*(pszRetPathName++) = (char) korean_tolower(*pc);
|
||||
}
|
||||
|
||||
*pszRetPathName = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
void CResource::SetFileName(const char* c_szFileName)
|
||||
{
|
||||
// 2004. 2. 1. myevan. 쓰레드가 사용되는 상황에서 static 변수는 사용하지 않는것이 좋다.
|
||||
// 2004. 2. 1. myevan. 파일 이름 처리를 std::string 사용
|
||||
m_stFileName=c_szFileName;
|
||||
}
|
||||
|
||||
void CResource::Clear()
|
||||
{
|
||||
OnClear();
|
||||
me_state = STATE_EMPTY;
|
||||
}
|
||||
|
||||
bool CResource::IsType(TType type)
|
||||
{
|
||||
return OnIsType(type);
|
||||
}
|
||||
|
||||
CResource::TType CResource::Type()
|
||||
{
|
||||
static TType s_type = StringToType("CResource");
|
||||
return s_type;
|
||||
}
|
||||
|
||||
bool CResource::OnIsType(TType type)
|
||||
{
|
||||
if (CResource::Type() == type)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CResource::IsData() const
|
||||
{
|
||||
return me_state != STATE_EMPTY;
|
||||
}
|
||||
|
||||
bool CResource::IsEmpty() const
|
||||
{
|
||||
return OnIsEmpty();
|
||||
}
|
||||
|
||||
bool CResource::CreateDeviceObjects()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CResource::DestroyDeviceObjects()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,525 @@
|
||||
#include "StdAfx.h"
|
||||
#include <io.h>
|
||||
#include "../EterBase/CRC32.h"
|
||||
#include "../EterBase/Timer.h"
|
||||
#include "../EterBase/Stl.h"
|
||||
#include "../EterPack/EterPackManager.h"
|
||||
|
||||
#include "ResourceManager.h"
|
||||
#include "GrpImage.h"
|
||||
|
||||
int g_iLoadingDelayTime = 20;
|
||||
|
||||
const long c_Deleting_Wait_Time = 30000; // 삭제 대기 시간 (30초)
|
||||
const long c_DeletingCountPerFrame = 30; // 프레임당 체크 리소스 갯수
|
||||
const long c_Reference_Decrease_Wait_Time = 30000; // 선로딩 리소스의 해제 대기 시간 (30초)
|
||||
|
||||
CFileLoaderThread CResourceManager::ms_loadingThread;
|
||||
|
||||
void CResourceManager::LoadStaticCache(const char* c_szFileName)
|
||||
{
|
||||
CResource* pkRes=GetResourcePointer(c_szFileName);
|
||||
if (!pkRes)
|
||||
{
|
||||
Lognf(1, "CResourceManager::LoadStaticCache %s - FAILED", c_szFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwCacheKey=GetCRC32(c_szFileName, strlen(c_szFileName));
|
||||
TResourcePointerMap::iterator f=m_pCacheMap.find(dwCacheKey);
|
||||
if (m_pCacheMap.end()!=f)
|
||||
return;
|
||||
|
||||
pkRes->AddReference();
|
||||
m_pCacheMap.insert(TResourcePointerMap::value_type(dwCacheKey, pkRes));
|
||||
|
||||
}
|
||||
|
||||
void CResourceManager::ProcessBackgroundLoading()
|
||||
{
|
||||
TResourceRequestMap::iterator itor = m_RequestMap.begin();
|
||||
|
||||
while (itor != m_RequestMap.end())
|
||||
{
|
||||
DWORD dwFileCRC = itor->first;
|
||||
std::string & stFileName = itor->second;
|
||||
|
||||
if (isResourcePointerData(dwFileCRC) ||
|
||||
(m_WaitingMap.end() != m_WaitingMap.find(dwFileCRC)))
|
||||
{
|
||||
//printf("SKP %s\n", stFileName.c_str());
|
||||
itor = m_RequestMap.erase(itor);
|
||||
continue;
|
||||
}
|
||||
|
||||
//printf("REQ %s\n", stFileName.c_str());
|
||||
ms_loadingThread.Request(stFileName);
|
||||
m_WaitingMap.insert(TResourceRequestMap::value_type(dwFileCRC, stFileName));
|
||||
itor = m_RequestMap.erase(itor);
|
||||
//break; // NOTE: 여기서 break 하면 천천히 로딩 된다.
|
||||
}
|
||||
|
||||
DWORD dwCurrentTime = ELTimer_GetMSec();
|
||||
|
||||
CFileLoaderThread::TData * pData;
|
||||
while (ms_loadingThread.Fetch(&pData))
|
||||
{
|
||||
//printf("LOD %s\n", pData->stFileName.c_str());
|
||||
CResource * pResource = GetResourcePointer(pData->stFileName.c_str());
|
||||
|
||||
if (pResource)
|
||||
{
|
||||
if (pResource->IsEmpty())
|
||||
{
|
||||
pResource->OnLoad(pData->dwSize, pData->pvBuf);
|
||||
pResource->AddReferenceOnly();
|
||||
|
||||
// 여기서 올라간 레퍼런스 카운트를 일정 시간이 지난 뒤에 풀어주기 위하여
|
||||
m_pResRefDecreaseWaitingMap.insert(TResourceRefDecreaseWaitingMap::value_type(dwCurrentTime, pResource));
|
||||
}
|
||||
}
|
||||
|
||||
m_WaitingMap.erase(GetCRC32(pData->stFileName.c_str(), pData->stFileName.size()));
|
||||
|
||||
delete [] ((char *) pData->pvBuf);
|
||||
delete pData;
|
||||
}
|
||||
|
||||
// DO : 일정 시간이 지나고 난뒤 미리 로딩해 두었던 리소스의 레퍼런스 카운트를 감소 시킨다 - [levites]
|
||||
long lCurrentTime = ELTimer_GetMSec();
|
||||
|
||||
TResourceRefDecreaseWaitingMap::iterator itorRef = m_pResRefDecreaseWaitingMap.begin();
|
||||
|
||||
while (itorRef != m_pResRefDecreaseWaitingMap.end())
|
||||
{
|
||||
const long & rCreatingTime = itorRef->first;
|
||||
|
||||
if (lCurrentTime - rCreatingTime > c_Reference_Decrease_Wait_Time)
|
||||
{
|
||||
CResource * pResource = itorRef->second;
|
||||
|
||||
// Decrease Reference Count
|
||||
pResource->Release();
|
||||
itorRef = m_pResRefDecreaseWaitingMap.erase(itorRef);
|
||||
//Tracef("Decrease Pre Loading Resource\n", rCreatingTime);
|
||||
}
|
||||
else
|
||||
++itorRef;
|
||||
}
|
||||
}
|
||||
|
||||
void CResourceManager::PushBackgroundLoadingSet(std::set<std::string> & LoadingSet)
|
||||
{
|
||||
std::set<std::string>::iterator itor = LoadingSet.begin();
|
||||
|
||||
while (itor != LoadingSet.end())
|
||||
{
|
||||
DWORD dwFileCRC = __GetFileCRC(itor->c_str());
|
||||
|
||||
if (NULL != isResourcePointerData(dwFileCRC))
|
||||
{
|
||||
++itor;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_RequestMap.insert(TResourceRequestMap::value_type(dwFileCRC, itor->c_str()));
|
||||
++itor;
|
||||
}
|
||||
}
|
||||
|
||||
void CResourceManager::__DestroyCacheMap()
|
||||
{
|
||||
TResourcePointerMap::iterator i;
|
||||
for (i = m_pCacheMap.begin(); i != m_pCacheMap.end(); ++i)
|
||||
{
|
||||
CResource* pResource = i->second;
|
||||
pResource->Release();
|
||||
}
|
||||
|
||||
m_pCacheMap.clear();
|
||||
}
|
||||
|
||||
void CResourceManager::__DestroyDeletingResourceMap()
|
||||
{
|
||||
Tracenf("CResourceManager::__DestroyDeletingResourceMap %d", m_ResourceDeletingMap.size());
|
||||
for (TResourceDeletingMap::iterator i = m_ResourceDeletingMap.begin(); i != m_ResourceDeletingMap.end(); ++i)
|
||||
(i->first)->Clear();
|
||||
|
||||
m_ResourceDeletingMap.clear();
|
||||
}
|
||||
|
||||
void CResourceManager::__DestroyResourceMap()
|
||||
{
|
||||
Tracenf("CResourceManager::__DestroyResourceMap %d", m_pResMap.size());
|
||||
|
||||
TResourcePointerMap::iterator i;
|
||||
for (i = m_pResMap.begin(); i != m_pResMap.end(); ++i)
|
||||
{
|
||||
CResource* pResource = i->second;
|
||||
pResource->Clear();
|
||||
}
|
||||
|
||||
stl_wipe_second(m_pResMap);
|
||||
}
|
||||
|
||||
void CResourceManager::DestroyDeletingList()
|
||||
{
|
||||
CResource::SetDeleteImmediately(true);
|
||||
|
||||
__DestroyCacheMap();
|
||||
__DestroyDeletingResourceMap();
|
||||
}
|
||||
|
||||
void CResourceManager::Destroy()
|
||||
{
|
||||
assert(m_ResourceDeletingMap.empty() && "CResourceManager::Destroy - YOU MUST CALL DestroyDeletingList");
|
||||
__DestroyResourceMap();
|
||||
}
|
||||
|
||||
void CResourceManager::RegisterResourceNewFunctionPointer(const char* c_szFileExt, CResource* (*pNewFunc)(const char* c_szFileName))
|
||||
{
|
||||
m_pResNewFuncMap[c_szFileExt] = pNewFunc;
|
||||
}
|
||||
|
||||
void CResourceManager::RegisterResourceNewFunctionByTypePointer(int iType, CResource* (*pNewFunc) (const char* c_szFileName))
|
||||
{
|
||||
assert(iType >= 0);
|
||||
m_pResNewFuncByTypeMap[iType] = pNewFunc;
|
||||
}
|
||||
|
||||
CResource * CResourceManager::InsertResourcePointer(DWORD dwFileCRC, CResource* pResource)
|
||||
{
|
||||
TResourcePointerMap::iterator itor = m_pResMap.find(dwFileCRC);
|
||||
|
||||
if (m_pResMap.end() != itor)
|
||||
{
|
||||
TraceError("CResource::InsertResourcePointer: %s is already registered\n", pResource->GetFileName());
|
||||
assert(!"CResource::InsertResourcePointer: Resource already resistered");
|
||||
delete pResource;
|
||||
return itor->second;
|
||||
}
|
||||
|
||||
m_pResMap.insert(TResourcePointerMap::value_type(dwFileCRC, pResource));
|
||||
return pResource;
|
||||
}
|
||||
|
||||
|
||||
int __ConvertPathName(const char * c_szPathName, char * pszRetPathName, int retLen)
|
||||
{
|
||||
const char * pc;
|
||||
int len = 0;
|
||||
|
||||
for (pc = c_szPathName; *pc && len < retLen; ++pc, ++len)
|
||||
{
|
||||
if (*pc == '/')
|
||||
*(pszRetPathName++) = '\\';
|
||||
else
|
||||
*(pszRetPathName++) = (char) korean_tolower(*pc);
|
||||
}
|
||||
|
||||
*pszRetPathName = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
CResource * CResourceManager::GetTypeResourcePointer(const char * c_szFileName, int iType)
|
||||
{
|
||||
if (!c_szFileName || !*c_szFileName)
|
||||
{
|
||||
assert(c_szFileName != NULL && *c_szFileName != '\0');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * c_pszFile;
|
||||
DWORD dwFileCRC = __GetFileCRC(c_szFileName, &c_pszFile);
|
||||
CResource * pResource = FindResourcePointer(dwFileCRC);
|
||||
|
||||
if (pResource) // 이미 리소스가 있으면 리턴 한다.
|
||||
return pResource;
|
||||
|
||||
CResource * (*newFunc) (const char *) = NULL;
|
||||
|
||||
if (iType != -1)
|
||||
{
|
||||
TResourceNewFunctionByTypePointerMap::iterator f = m_pResNewFuncByTypeMap.find(iType);
|
||||
|
||||
if (m_pResNewFuncByTypeMap.end() != f)
|
||||
newFunc = f->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char * pcFileExt = strrchr(c_pszFile, '.');
|
||||
|
||||
if (pcFileExt)
|
||||
{
|
||||
static char s_szFileExt[8 + 1];
|
||||
strncpy(s_szFileExt, pcFileExt + 1, 8);
|
||||
|
||||
TResourceNewFunctionPointerMap::iterator f = m_pResNewFuncMap.find(s_szFileExt);
|
||||
|
||||
if (m_pResNewFuncMap.end() != f)
|
||||
newFunc = f->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!newFunc)
|
||||
{
|
||||
TraceError("ResourceManager::GetResourcePointer: NOT SUPPORT FILE %s", c_pszFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pResource = InsertResourcePointer(dwFileCRC, newFunc(c_pszFile));
|
||||
return pResource;
|
||||
}
|
||||
|
||||
CResource * CResourceManager::GetResourcePointer(const char * c_szFileName)
|
||||
{
|
||||
if (!c_szFileName || !*c_szFileName)
|
||||
{
|
||||
TraceError("CResourceManager::GetResourcePointer: filename error!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * c_pszFile;
|
||||
DWORD dwFileCRC = __GetFileCRC(c_szFileName, &c_pszFile);
|
||||
CResource * pResource = FindResourcePointer(dwFileCRC);
|
||||
|
||||
if (pResource) // 이미 리소스가 있으면 리턴 한다.
|
||||
return pResource;
|
||||
|
||||
const char * pcFileExt = strrchr(c_pszFile, '.');
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (!IsFileExist(c_szFileName) )
|
||||
{
|
||||
if( pcFileExt == NULL || (stricmp( pcFileExt, ".fnt" ) != 0) ) {
|
||||
TraceError("CResourceManager::GetResourcePointer: File not exist %s", c_szFileName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CResource * (*newFunc) (const char *) = NULL;
|
||||
|
||||
if (pcFileExt)
|
||||
{
|
||||
static char s_szFileExt[8 + 1];
|
||||
strncpy(s_szFileExt, pcFileExt + 1, 8);
|
||||
|
||||
TResourceNewFunctionPointerMap::iterator f = m_pResNewFuncMap.find(s_szFileExt);
|
||||
|
||||
if (m_pResNewFuncMap.end() != f)
|
||||
newFunc = f->second;
|
||||
}
|
||||
|
||||
if (!newFunc)
|
||||
{
|
||||
TraceError("ResourceManager::GetResourcePointer: NOT SUPPORT FILE %s", c_pszFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pResource = InsertResourcePointer(dwFileCRC, newFunc(c_pszFile));
|
||||
return pResource;
|
||||
}
|
||||
|
||||
CResource * CResourceManager::FindResourcePointer(DWORD dwFileCRC)
|
||||
{
|
||||
TResourcePointerMap::iterator itor = m_pResMap.find(dwFileCRC);
|
||||
|
||||
if (m_pResMap.end() == itor)
|
||||
return NULL;
|
||||
|
||||
return itor->second;
|
||||
}
|
||||
|
||||
bool CResourceManager::isResourcePointerData(DWORD dwFileCRC)
|
||||
{
|
||||
TResourcePointerMap::iterator itor = m_pResMap.find(dwFileCRC);
|
||||
|
||||
if (m_pResMap.end() == itor)
|
||||
return NULL;
|
||||
|
||||
return (itor->second)->IsData();
|
||||
}
|
||||
|
||||
DWORD CResourceManager::__GetFileCRC(const char * c_szFileName, const char ** c_ppszLowerFileName)
|
||||
{
|
||||
static char s_szFullPathFileName[MAX_PATH];
|
||||
const char * src = c_szFileName;
|
||||
char * dst = s_szFullPathFileName;
|
||||
int len = 0;
|
||||
|
||||
while (src[len])
|
||||
{
|
||||
if (src[len]=='/')
|
||||
dst[len] = '\\';
|
||||
else
|
||||
dst[len] = (char) korean_tolower(src[len]);
|
||||
|
||||
++len;
|
||||
}
|
||||
|
||||
dst[len] = '\0';
|
||||
|
||||
if (c_ppszLowerFileName)
|
||||
*c_ppszLowerFileName = &s_szFullPathFileName[0];
|
||||
|
||||
return (GetCRC32(s_szFullPathFileName, len));
|
||||
}
|
||||
|
||||
typedef struct SDumpData
|
||||
{
|
||||
const char * filename;
|
||||
float KB;
|
||||
DWORD cost;
|
||||
} TDumpData;
|
||||
|
||||
bool DumpKBCompare(const TDumpData& lhs, const TDumpData& rhs)
|
||||
{
|
||||
return (lhs.KB > rhs.KB) ? true : false;
|
||||
}
|
||||
|
||||
bool DumpCostCompare(const TDumpData& lhs, const TDumpData& rhs)
|
||||
{
|
||||
return (lhs.cost > rhs.cost) ? true : false;
|
||||
}
|
||||
|
||||
struct FDumpPrint
|
||||
{
|
||||
FILE * m_fp;
|
||||
static float m_totalKB;
|
||||
|
||||
void operator () (TDumpData & data)
|
||||
{
|
||||
m_totalKB += data.KB;
|
||||
fprintf(m_fp, "%6.1f %s\n", data.KB, data.filename);
|
||||
}
|
||||
};
|
||||
|
||||
float FDumpPrint::m_totalKB;
|
||||
|
||||
struct FDumpCostPrint
|
||||
{
|
||||
FILE * m_fp;
|
||||
|
||||
void operator() (TDumpData & data)
|
||||
{
|
||||
fprintf(m_fp, "%-4d %s\n", data.cost, data.filename);
|
||||
}
|
||||
};
|
||||
|
||||
void CResourceManager::DumpFileListToTextFile(const char* c_szFileName)
|
||||
{
|
||||
std::vector<TDumpData> dumpVector;
|
||||
|
||||
for (TResourcePointerMap::iterator i = m_pResMap.begin(); i != m_pResMap.end(); ++i)
|
||||
{
|
||||
CResource* pResource = i->second;
|
||||
TDumpData data;
|
||||
|
||||
if (pResource->IsEmpty())
|
||||
continue;
|
||||
|
||||
data.filename = pResource->GetFileName();
|
||||
|
||||
int filesize;
|
||||
|
||||
const char * ext = strrchr(data.filename, '.');
|
||||
|
||||
if (pResource->IsType(CGraphicImage::Type()) && strnicmp(ext, ".sub", 4))
|
||||
filesize = ((CGraphicImage*) pResource)->GetWidth() * ((CGraphicImage*) pResource)->GetHeight() * 4;
|
||||
else
|
||||
{
|
||||
FILE * fp2 = fopen(data.filename, "rb");
|
||||
|
||||
if (fp2)
|
||||
{
|
||||
fseek(fp2, 0L, SEEK_END);
|
||||
filesize = ftell(fp2);
|
||||
fclose(fp2);
|
||||
}
|
||||
else
|
||||
filesize = 0;
|
||||
}
|
||||
|
||||
data.KB = (float) filesize / (float) 1024;
|
||||
data.cost = pResource->GetLoadCostMilliSecond();
|
||||
|
||||
dumpVector.push_back(data);
|
||||
}
|
||||
|
||||
FILE * fp = fopen(c_szFileName, "w");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
std::sort(dumpVector.begin(), dumpVector.end(), DumpKBCompare);
|
||||
|
||||
FDumpPrint DumpPrint;
|
||||
DumpPrint.m_fp = fp;
|
||||
DumpPrint.m_totalKB = 0;
|
||||
|
||||
std::for_each(dumpVector.begin(), dumpVector.end(), DumpPrint);
|
||||
fprintf(fp, "total: %.2fmb", DumpPrint.m_totalKB / 1024.0f);
|
||||
|
||||
FDumpCostPrint DumpCostPrint;
|
||||
DumpCostPrint.m_fp = fp;
|
||||
|
||||
std::sort(dumpVector.begin(), dumpVector.end(), DumpCostCompare);
|
||||
std::for_each(dumpVector.begin(), dumpVector.end(), DumpCostPrint);
|
||||
fprintf(fp, "total: %.2fmb", DumpPrint.m_totalKB / 1024.0f);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
bool CResourceManager::IsFileExist(const char * c_szFileName)
|
||||
{
|
||||
return CEterPackManager::Instance().isExist(c_szFileName);
|
||||
}
|
||||
|
||||
void CResourceManager::Update()
|
||||
{
|
||||
DWORD CurrentTime = ELTimer_GetMSec();
|
||||
CResource * pResource;
|
||||
int Count = 0;
|
||||
|
||||
TResourceDeletingMap::iterator itor = m_ResourceDeletingMap.begin();
|
||||
|
||||
while (itor != m_ResourceDeletingMap.end())
|
||||
{
|
||||
pResource = itor->first;
|
||||
|
||||
if (CurrentTime >= itor->second)
|
||||
{
|
||||
if (pResource->canDestroy())
|
||||
{
|
||||
//Tracef("Resource Clear %s\n", pResource->GetFileName());
|
||||
pResource->Clear();
|
||||
}
|
||||
|
||||
itor = m_ResourceDeletingMap.erase(itor);
|
||||
|
||||
if (++Count >= c_DeletingCountPerFrame)
|
||||
break;
|
||||
}
|
||||
else
|
||||
++itor;
|
||||
}
|
||||
|
||||
ProcessBackgroundLoading();
|
||||
}
|
||||
|
||||
void CResourceManager::ReserveDeletingResource(CResource * pResource)
|
||||
{
|
||||
DWORD dwCurrentTime = ELTimer_GetMSec();
|
||||
m_ResourceDeletingMap.insert(TResourceDeletingMap::value_type(pResource, dwCurrentTime + c_Deleting_Wait_Time));
|
||||
}
|
||||
|
||||
CResourceManager::CResourceManager()
|
||||
{
|
||||
//ms_loadingThread.Create(0);
|
||||
}
|
||||
|
||||
CResourceManager::~CResourceManager()
|
||||
{
|
||||
Destroy();
|
||||
//ms_loadingThread.Shutdown();
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
#include "StdAfx.h"
|
||||
#include "../EterBase/CRC32.h"
|
||||
#include "PythonGridSlotWindow.h"
|
||||
|
||||
using namespace UI;
|
||||
|
||||
void CGridSlotWindow::OnRenderPickingSlot()
|
||||
{
|
||||
if (!UI::CWindowManager::Instance().IsAttaching())
|
||||
return;
|
||||
|
||||
BYTE byWidth, byHeight;
|
||||
UI::CWindowManager::Instance().GetAttachingIconSize(&byWidth, &byHeight);
|
||||
|
||||
std::list<TSlot*> SlotList;
|
||||
if (GetPickedSlotList(byWidth, byHeight, &SlotList))
|
||||
{
|
||||
DWORD dwSlotNumber = UI::CWindowManager::Instance().GetAttachingSlotNumber();
|
||||
DWORD dwItemIndex = UI::CWindowManager::Instance().GetAttachingIndex();
|
||||
|
||||
// UseMode 이고..
|
||||
if (m_isUseMode)
|
||||
{
|
||||
// Pick 된 아이템이 있으면..
|
||||
TSlot * pSlot = *SlotList.begin();
|
||||
TSlot * pCenterSlot;
|
||||
if (GetSlotPointer(pSlot->dwCenterSlotNumber, &pCenterSlot))
|
||||
if (pCenterSlot->isItem)
|
||||
{
|
||||
if (m_isUsableItem)
|
||||
CPythonGraphic::Instance().SetDiffuseColor(1.0f, 1.0f, 0.0f, 0.5f);
|
||||
else
|
||||
CPythonGraphic::Instance().SetDiffuseColor(1.0f, 0.0f, 0.0f, 0.5f);
|
||||
|
||||
CPythonGraphic::Instance().RenderBar2d( m_rect.left + pCenterSlot->ixPosition,
|
||||
m_rect.top + pCenterSlot->iyPosition,
|
||||
m_rect.left + pCenterSlot->ixPosition + pCenterSlot->byxPlacedItemSize * ITEM_WIDTH,
|
||||
m_rect.top + pCenterSlot->iyPosition + pCenterSlot->byyPlacedItemSize * ITEM_HEIGHT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 아니면 그냥 옮기기
|
||||
if (CheckMoving(dwSlotNumber, dwItemIndex, SlotList))
|
||||
CPythonGraphic::Instance().SetDiffuseColor(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
else
|
||||
CPythonGraphic::Instance().SetDiffuseColor(1.0f, 0.0f, 0.0f, 0.5f);
|
||||
|
||||
RECT Rect;
|
||||
Rect.left = m_rect.right;
|
||||
Rect.top = m_rect.bottom;
|
||||
Rect.right = 0;
|
||||
Rect.bottom = 0;
|
||||
|
||||
for (std::list<TSlot*>::iterator itor = SlotList.begin(); itor != SlotList.end(); ++itor)
|
||||
{
|
||||
TSlot * pSlot = *itor;
|
||||
Rect.left = min(Rect.left, m_rect.left + pSlot->ixPosition);
|
||||
Rect.top = min(Rect.top, m_rect.top + pSlot->iyPosition);
|
||||
Rect.right = max(Rect.right, m_rect.left + pSlot->ixPosition + pSlot->byxPlacedItemSize*ITEM_WIDTH);
|
||||
Rect.bottom = max(Rect.bottom, m_rect.top + pSlot->iyPosition + pSlot->byxPlacedItemSize*ITEM_HEIGHT);
|
||||
}
|
||||
|
||||
CPythonGraphic::Instance().RenderBar2d(Rect.left, Rect.top, Rect.right, Rect.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::GetPickedSlotPointer(TSlot ** ppSlot)
|
||||
{
|
||||
if (!UI::CWindowManager::Instance().IsAttaching())
|
||||
return CSlotWindow::GetPickedSlotPointer(ppSlot);
|
||||
|
||||
BYTE byWidth, byHeight;
|
||||
UI::CWindowManager::Instance().GetAttachingIconSize(&byWidth, &byHeight);
|
||||
|
||||
std::list<TSlot*> SlotList;
|
||||
if (!GetPickedSlotList(byWidth, byHeight, &SlotList))
|
||||
return FALSE;
|
||||
|
||||
TSlot * pMinSlot = NULL;
|
||||
//DWORD dwSlotNumber = UI::CWindowManager::Instance().GetAttachingSlotNumber();
|
||||
//DWORD dwAttachingItemIndex = UI::CWindowManager::Instance().GetAttachingIndex();
|
||||
|
||||
for (std::list<TSlot*>::iterator itor = SlotList.begin(); itor != SlotList.end(); ++itor)
|
||||
{
|
||||
TSlot * pSlot = *itor;
|
||||
|
||||
// NOTE : 한 슬롯 이상 사이즈의 아이템의 경우 가장 왼쪽 위의 슬롯 포인터를 리턴한다.
|
||||
// 명시적이지 못한 코드.. 더 좋은 방법은 없는가? - [levites]
|
||||
if (!pMinSlot)
|
||||
{
|
||||
pMinSlot = pSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSlot->dwSlotNumber < pMinSlot->dwSlotNumber)
|
||||
{
|
||||
pMinSlot = pSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pMinSlot->isItem && pSlot->isItem)
|
||||
{
|
||||
pMinSlot = pSlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pMinSlot)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
TSlot * pCenterSlot;
|
||||
if (!GetSlotPointer(pMinSlot->dwCenterSlotNumber, &pCenterSlot))
|
||||
return FALSE;
|
||||
|
||||
*ppSlot = pCenterSlot;
|
||||
|
||||
// 현재 아이템을 들고 있는 중이고..
|
||||
if (UI::CWindowManager::Instance().IsAttaching())
|
||||
{
|
||||
DWORD dwSlotNumber = UI::CWindowManager::Instance().GetAttachingSlotNumber();
|
||||
|
||||
if (dwSlotNumber == pCenterSlot->dwSlotNumber)
|
||||
{
|
||||
*ppSlot = pMinSlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::GetPickedSlotList(int iWidth, int iHeight, std::list<TSlot*> * pSlotPointerList)
|
||||
{
|
||||
long lx, ly;
|
||||
GetMouseLocalPosition(lx, ly);
|
||||
|
||||
if (lx < 0)
|
||||
return FALSE;
|
||||
if (ly < 0)
|
||||
return FALSE;
|
||||
if (lx >= GetWidth())
|
||||
return FALSE;
|
||||
if (ly >= GetHeight())
|
||||
return FALSE;
|
||||
|
||||
pSlotPointerList->clear();
|
||||
|
||||
int ix, iy;
|
||||
if (GetPickedGridSlotPosition(lx, ly, &ix, &iy))
|
||||
{
|
||||
int ixHalfStep = (iWidth / 2);
|
||||
//int iyHalfStep = (iHeight / 2);
|
||||
|
||||
int ixStart = int(ix) - int(ixHalfStep - (ixHalfStep % 2));
|
||||
int ixEnd = int(ix) + int(ixHalfStep);
|
||||
|
||||
// FIXME : 제대로 된 계산 공식을 찾자 - [levites]
|
||||
int iyStart = 0, iyEnd = 0;
|
||||
|
||||
if (1 == iHeight)
|
||||
{
|
||||
iyStart = iy;
|
||||
iyEnd = iy;
|
||||
}
|
||||
else if (2 == iHeight)
|
||||
{
|
||||
iyStart = iy;
|
||||
iyEnd = iy + 1;
|
||||
}
|
||||
else if (3 == iHeight)
|
||||
{
|
||||
iyStart = iy - 1;
|
||||
iyEnd = iy + 1;
|
||||
}
|
||||
|
||||
if (ixStart < 0)
|
||||
{
|
||||
ixEnd += -ixStart;
|
||||
ixStart = 0;
|
||||
}
|
||||
|
||||
if (iyStart < 0)
|
||||
{
|
||||
iyEnd += -iyStart;
|
||||
iyStart = 0;
|
||||
}
|
||||
|
||||
if (DWORD(ixEnd) >= m_dwxCount)
|
||||
{
|
||||
int ixTemporary = DWORD(ixEnd) - m_dwxCount + 1;
|
||||
ixStart -= ixTemporary;
|
||||
ixEnd -= ixTemporary;
|
||||
}
|
||||
|
||||
if (DWORD(iyEnd) >= m_dwyCount)
|
||||
{
|
||||
int iyTemporary = DWORD(iyEnd) - m_dwyCount + 1;
|
||||
iyStart -= iyTemporary;
|
||||
iyEnd -= iyTemporary;
|
||||
}
|
||||
|
||||
for (int i = ixStart; i <= ixEnd; ++i)
|
||||
for (int j = iyStart; j <= iyEnd; ++j)
|
||||
{
|
||||
TSlot * pSlot;
|
||||
if (GetGridSlotPointer(DWORD(i), DWORD(j), &pSlot))
|
||||
{
|
||||
pSlotPointerList->push_back(pSlot);
|
||||
}
|
||||
}
|
||||
|
||||
// Refine Scroll 등을 위한 예외 처리
|
||||
if (m_isUseMode && 1 == pSlotPointerList->size())
|
||||
{
|
||||
TSlot * pMainSlot = *pSlotPointerList->begin();
|
||||
|
||||
std::vector<TSlot *>::iterator itor = m_SlotVector.begin();
|
||||
for (; itor != m_SlotVector.end(); ++itor)
|
||||
{
|
||||
TSlot * pSlot = *itor;
|
||||
if (pSlot->dwCenterSlotNumber == pMainSlot->dwCenterSlotNumber)
|
||||
if (pSlotPointerList->end() == std::find(pSlotPointerList->begin(), pSlotPointerList->end(), pSlot))
|
||||
{
|
||||
pSlotPointerList->push_back(pSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pSlotPointerList->empty())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::GetGridSlotPointer(int ix, int iy, TSlot ** ppSlot)
|
||||
{
|
||||
DWORD dwSlotIndex = ix + iy*m_dwxCount;
|
||||
if (dwSlotIndex >= m_SlotVector.size())
|
||||
return FALSE;
|
||||
|
||||
*ppSlot = m_SlotVector[dwSlotIndex];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::GetPickedGridSlotPosition(int ixLocal, int iyLocal, int * pix, int * piy)
|
||||
{
|
||||
for (DWORD x = 0; x < m_dwxCount; ++x)
|
||||
for (DWORD y = 0; y < m_dwyCount; ++y)
|
||||
{
|
||||
TSlot * pSlot;
|
||||
if (!GetGridSlotPointer(x, y, &pSlot))
|
||||
continue;
|
||||
|
||||
if (ixLocal >= pSlot->ixPosition)
|
||||
if (iyLocal >= pSlot->iyPosition)
|
||||
if (ixLocal <= pSlot->ixPosition + pSlot->ixCellSize)
|
||||
if (iyLocal <= pSlot->iyPosition + pSlot->iyCellSize)
|
||||
{
|
||||
*pix = x;
|
||||
*piy = y;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CGridSlotWindow::ArrangeGridSlot(DWORD dwStartIndex, DWORD dwxCount, DWORD dwyCount, int ixSlotSize, int iySlotSize, int ixTemporarySize, int iyTemporarySize)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_dwxCount = dwxCount;
|
||||
m_dwyCount = dwyCount;
|
||||
|
||||
m_SlotVector.clear();
|
||||
m_SlotVector.resize(dwxCount*dwyCount);
|
||||
|
||||
for (DWORD x = 0; x < dwxCount; ++x)
|
||||
for (DWORD y = 0; y < dwyCount; ++y)
|
||||
{
|
||||
DWORD dwIndex = dwStartIndex + x + y * dwxCount;
|
||||
int ixPosition = x * (ixSlotSize + ixTemporarySize);
|
||||
int iyPosition = y * (iySlotSize + iyTemporarySize);
|
||||
|
||||
AppendSlot(dwIndex, ixPosition, iyPosition, ixSlotSize, iySlotSize);
|
||||
|
||||
m_SlotVector[x+y*dwxCount] = &(*m_SlotList.rbegin());
|
||||
}
|
||||
|
||||
int iWidth = dwxCount * (ixSlotSize + ixTemporarySize);
|
||||
int iHeight = dwyCount * (iySlotSize + iyTemporarySize);
|
||||
SetSize(iWidth, iHeight);
|
||||
}
|
||||
|
||||
void CGridSlotWindow::OnRefreshSlot()
|
||||
{
|
||||
DWORD x, y;
|
||||
|
||||
for (x = 0; x < m_dwxCount; ++x)
|
||||
for (y = 0; y < m_dwyCount; ++y)
|
||||
{
|
||||
TSlot * pSlot;
|
||||
if (!GetGridSlotPointer(x, y, &pSlot))
|
||||
continue;
|
||||
|
||||
pSlot->dwCenterSlotNumber = pSlot->dwSlotNumber;
|
||||
}
|
||||
|
||||
for (x = 0; x < m_dwxCount; ++x)
|
||||
for (y = 0; y < m_dwyCount; ++y)
|
||||
{
|
||||
TSlot * pSlot;
|
||||
if (!GetGridSlotPointer(x, y, &pSlot))
|
||||
continue;
|
||||
|
||||
if (pSlot->isItem)
|
||||
{
|
||||
for (DWORD xSub = 0; xSub < pSlot->byxPlacedItemSize; ++xSub)
|
||||
for (DWORD ySub = 0; ySub < pSlot->byyPlacedItemSize; ++ySub)
|
||||
{
|
||||
TSlot * pSubSlot;
|
||||
if (!GetGridSlotPointer(x+xSub, y+ySub, &pSubSlot))
|
||||
continue;
|
||||
|
||||
pSubSlot->dwCenterSlotNumber = pSlot->dwSlotNumber;
|
||||
pSubSlot->dwItemIndex = pSlot->dwItemIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSlot->dwItemIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::CheckMoving(DWORD dwSlotNumber, DWORD dwItemIndex, const std::list<TSlot*> & c_rSlotList)
|
||||
{
|
||||
if (m_dwSlotStyle != SLOT_STYLE_PICK_UP)
|
||||
return TRUE;
|
||||
|
||||
for (std::list<TSlot*>::const_iterator itor = c_rSlotList.begin(); itor != c_rSlotList.end(); ++itor)
|
||||
{
|
||||
TSlot * pSlot = *itor;
|
||||
|
||||
if (dwSlotNumber != pSlot->dwCenterSlotNumber) // 들었던 자리가 아닐 경우에
|
||||
{
|
||||
if (0 != pSlot->dwItemIndex || pSlot->dwCenterSlotNumber != pSlot->dwSlotNumber) // 아이템이 있고
|
||||
{
|
||||
if (dwItemIndex != pSlot->dwItemIndex) // 다른 아이템이면 못 옮김
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGridSlotWindow::Destroy()
|
||||
{
|
||||
CSlotWindow::Destroy();
|
||||
|
||||
m_SlotVector.clear();
|
||||
|
||||
__Initialize();
|
||||
}
|
||||
|
||||
void CGridSlotWindow::__Initialize()
|
||||
{
|
||||
m_dwxCount = 0;
|
||||
m_dwyCount = 0;
|
||||
}
|
||||
|
||||
DWORD CGridSlotWindow::Type()
|
||||
{
|
||||
static int s_Type = GetCRC32("CGridSlotWindow", strlen("CGridSlotWindow"));
|
||||
return s_Type;
|
||||
}
|
||||
|
||||
BOOL CGridSlotWindow::OnIsType(DWORD dwType)
|
||||
{
|
||||
if (CGridSlotWindow::Type() == dwType)
|
||||
return TRUE;
|
||||
|
||||
return CSlotWindow::OnIsType(dwType);
|
||||
}
|
||||
|
||||
CGridSlotWindow::CGridSlotWindow(PyObject * ppyObject) : CSlotWindow(ppyObject)
|
||||
{
|
||||
}
|
||||
|
||||
CGridSlotWindow::~CGridSlotWindow()
|
||||
{
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user