350 lines
8.3 KiB
C++
350 lines
8.3 KiB
C++
|
|
#define _WIN32_WINNT 0x0500
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <commctrl.h>
|
|
#include <shlwapi.h>
|
|
#include <stdio.h>
|
|
#include "SCENE.H"
|
|
|
|
char ToUpper(char H)
|
|
{
|
|
if ((H >= 'a') && (H <= 'z')) return 'A' + H - 'a';
|
|
return H;
|
|
}
|
|
|
|
|
|
typedef void (CALLBACK *FileChangeCallback)(LPTSTR, void *M,DWORD action);
|
|
|
|
typedef struct tagDIR_MONITOR
|
|
{
|
|
OVERLAPPED ol;
|
|
HANDLE hDir;
|
|
BYTE buffer[32 * 1024];
|
|
LPARAM lParam;
|
|
DWORD notifyFilter;
|
|
BOOL fStop;
|
|
char szTrackedDir[MAX_PATH];
|
|
void *psCene;
|
|
FileChangeCallback callback;
|
|
} *HDIR_MONITOR;
|
|
|
|
HDIR_MONITOR h = NULL;
|
|
HDIR_MONITOR hLua = NULL;
|
|
|
|
|
|
VOID CALLBACK MonitorCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
|
|
{
|
|
TCHAR szFile[MAX_PATH];
|
|
PFILE_NOTIFY_INFORMATION pNotify;
|
|
HDIR_MONITOR pMonitor = (HDIR_MONITOR) lpOverlapped;
|
|
size_t offset = 0;
|
|
BOOL RefreshMonitoring(HDIR_MONITOR pMonitor);
|
|
|
|
if (pMonitor != h && pMonitor != hLua)
|
|
return;
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
do
|
|
{
|
|
pNotify = (PFILE_NOTIFY_INFORMATION) &pMonitor->buffer[offset];
|
|
offset += pNotify->NextEntryOffset;
|
|
|
|
# if defined(UNICODE)
|
|
{
|
|
lstrcpynW(szFile, pNotify->FileName,
|
|
min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1));
|
|
}
|
|
# else
|
|
{
|
|
int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName,
|
|
pNotify->FileNameLength / sizeof(WCHAR),
|
|
szFile, MAX_PATH - 1, NULL, NULL);
|
|
szFile[count] = TEXT('\0');
|
|
}
|
|
# endif
|
|
|
|
|
|
pMonitor->callback(szFile, pMonitor,pNotify->Action);
|
|
|
|
} while (pNotify->NextEntryOffset != 0);
|
|
}
|
|
|
|
if (!pMonitor->fStop)
|
|
{
|
|
RefreshMonitoring(pMonitor);
|
|
}
|
|
}
|
|
//*/
|
|
/*
|
|
* Refreshes the directory monitoring.
|
|
*/
|
|
BOOL RefreshMonitoring(HDIR_MONITOR pMonitor)
|
|
{
|
|
return
|
|
ReadDirectoryChangesW(pMonitor->hDir, pMonitor->buffer, sizeof(pMonitor->buffer), TRUE,
|
|
pMonitor->notifyFilter, NULL, &pMonitor->ol, MonitorCallback);
|
|
}
|
|
|
|
/*
|
|
* Stops monitoring a directory.
|
|
*/
|
|
void StopMonitoring(HDIR_MONITOR pMonitor)
|
|
{
|
|
if (pMonitor)
|
|
{
|
|
pMonitor->fStop = TRUE;
|
|
|
|
CancelIo(pMonitor->hDir);
|
|
|
|
while (!HasOverlappedIoCompleted(&pMonitor->ol))
|
|
{
|
|
//SleepEx(5, TRUE);
|
|
Sleep(5);
|
|
}
|
|
|
|
CloseHandle(pMonitor->ol.hEvent);
|
|
CloseHandle(pMonitor->hDir);
|
|
HeapFree(GetProcessHeap(), 0, pMonitor);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Starts monitoring a directory.
|
|
*/
|
|
HDIR_MONITOR StartMonitoring(LPCTSTR szDirectory, DWORD notifyFilter, FileChangeCallback callback,void *pScene)
|
|
{
|
|
HDIR_MONITOR pMonitor = (HDIR_MONITOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pMonitor));
|
|
|
|
pMonitor->hDir = CreateFile(szDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
|
|
|
|
strcpy(pMonitor->szTrackedDir,szDirectory);
|
|
pMonitor->psCene = pScene;
|
|
|
|
if (pMonitor->hDir != INVALID_HANDLE_VALUE)
|
|
{
|
|
pMonitor->ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
pMonitor->notifyFilter = notifyFilter;
|
|
pMonitor->callback = callback;
|
|
|
|
if (RefreshMonitoring(pMonitor))
|
|
{
|
|
return pMonitor;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(pMonitor->ol.hEvent);
|
|
CloseHandle(pMonitor->hDir);
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pMonitor);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void DW_WatchDirectoryCheck()
|
|
{
|
|
while (WAIT_IO_COMPLETION == MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE)) ;
|
|
}
|
|
|
|
int MyStrCompare(char *S1,char *S2)
|
|
{
|
|
while (*S1 && *S2)
|
|
{
|
|
if (((*S1 == '\\') || (*S1 == '/')) &&
|
|
((*S2 == '\\') || (*S2 == '/')))
|
|
{
|
|
// OK
|
|
} else
|
|
if (ToUpper(*S1) == ToUpper(*S2))
|
|
{
|
|
// OK
|
|
} else return 0;
|
|
S2++;
|
|
S1++;
|
|
}
|
|
if ((*S1 == 0) && (*S1 == *S2)) return 1;
|
|
return 0;
|
|
}
|
|
|
|
void CALLBACK FileCallback(LPTSTR szFile, void*M,DWORD action)
|
|
{
|
|
//return;
|
|
|
|
HDIR_MONITOR Monitor;
|
|
Monitor =(HDIR_MONITOR)M;
|
|
WORLD *pScene;
|
|
u32 Counter;
|
|
char szFileComplete[MAX_PATH];
|
|
sprintf(szFileComplete,"%s%s",(char *)Monitor->szTrackedDir,szFile);
|
|
|
|
FILE *F;
|
|
F = fopen(szFileComplete,"rb");
|
|
if (!F) return; // <= File is destroyed. Return;
|
|
char Buf[32];
|
|
if (fread(Buf,1,16,F) < 4)
|
|
{
|
|
fclose(F);
|
|
return;
|
|
}
|
|
fclose(F);
|
|
F = fopen(szFileComplete,"ab");
|
|
if (!F) return; // <= File is open. Return;
|
|
fclose(F);
|
|
|
|
if (action == FILE_ACTION_MODIFIED)// && */(Dico.mpst_Dico[ID].AssociatedValue > 1))
|
|
{
|
|
pScene = (WORLD *)Monitor->psCene;
|
|
switch (GetFileNameExtend((char *)szFile))
|
|
{
|
|
case '.CCM':
|
|
#ifndef USER_MODE
|
|
#ifndef ONLINE_MODE
|
|
{
|
|
pScene->LoadIniFile((char *)szFile);
|
|
};
|
|
#endif
|
|
#endif
|
|
break;
|
|
case '.LUA':
|
|
#ifndef USER_MODE
|
|
if ((pScene->WFlags & LUA_AUTO_RELOAD) && GetFileNameExtend(pScene->ScriptNameStack[pScene->currentScript]) == '.LUA')
|
|
pScene->LoadLua(pScene->ScriptNameStack[pScene->currentScript], 2);
|
|
#endif
|
|
break;
|
|
case '.SVG':
|
|
#ifdef USE_SVG
|
|
{
|
|
return; //TO FINISH
|
|
|
|
if(strncmp(szFile, "SVG", 3) != 0) return;
|
|
//asking for reconvert SVG file
|
|
extern HWND hWnd;
|
|
char Text[2048];
|
|
sprintf(Text,"SVG file %s has been modified outside camcam\nDo you want to reconvert it to a MAD file ?",szFile);
|
|
if(MessageBox(GetDesktopWindow(),Text,"Camcam message",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
|
|
{
|
|
char svgCompleteFilename[260]; strcpy(svgCompleteFilename, szFile);
|
|
char madCompleteFilename[260]; sprintf(madCompleteFilename, "Mads\\%s.mad", szFile+4);
|
|
|
|
extern bool svg2mad(char* svgFilename, char* destMadFilename);
|
|
svg2mad(svgCompleteFilename, madCompleteFilename);
|
|
}
|
|
};
|
|
#endif
|
|
break;
|
|
case '.MAD':
|
|
{
|
|
//reentrance support
|
|
static bool firstEntry = true;
|
|
static time_t lastTime;
|
|
if(!firstEntry)
|
|
{
|
|
time_t diffOfTime = time(NULL)-lastTime;
|
|
if(diffOfTime<2)
|
|
{
|
|
lastTime = time(NULL);
|
|
return;
|
|
}
|
|
}
|
|
firstEntry = false;
|
|
|
|
//asking for reimport MAD file
|
|
char Text[2048];
|
|
sprintf(Text,"MAD file %s has been modified outside camcam\nDo you want to reimport it ?",szFile);
|
|
if ((pScene->WFlags & MAD_AUTO_RELOAD) || (MessageBox(GetDesktopWindow(),Text,"Camcam message",MB_YESNO|MB_SYSTEMMODAL) == IDYES))
|
|
{
|
|
extern u32 MAD_2_CAMCAM(char *FileName);
|
|
MAD_2_CAMCAM(szFileComplete);
|
|
}
|
|
|
|
//reentrance support
|
|
lastTime = time(NULL);
|
|
};
|
|
break;
|
|
case '.MMT':
|
|
case '.MAT':
|
|
case '.MSH':
|
|
case '.OBJ':
|
|
case '.SSC':
|
|
case '.IKM':
|
|
case '.LGH':
|
|
/* a small scene must be update */
|
|
if (pScene->WFlags & LUA_AUTO_RELOAD)
|
|
pScene->TouchSmallScene(szFileComplete);
|
|
break;
|
|
case '.JPG':
|
|
case '.PNG':
|
|
case '.TGA':
|
|
case '.PSD':
|
|
case '.BMP':
|
|
case 'TEXT':
|
|
case '.TXT':
|
|
/* maybe a media must be update */
|
|
pScene->TouchMedia(szFileComplete);
|
|
if ((szFileComplete[0] == '.') && (szFileComplete[1] == '\\'))
|
|
pScene->TouchMedia(szFileComplete+2);
|
|
break;
|
|
case '.PGR':
|
|
pScene->TouchPGenerator(szFileComplete);
|
|
break;
|
|
case '.FUR':
|
|
pScene->TouchFur(szFileComplete);
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
int DW_WatchDirectory(char *DirectoryToWatch,void (*fn)(void *,char *),void *pS)
|
|
{
|
|
if (h) StopMonitoring(h);
|
|
h = NULL;
|
|
h = StartMonitoring(TEXT(DirectoryToWatch),
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME,
|
|
FileCallback,pS);
|
|
return TRUE;
|
|
}
|
|
|
|
int DW_UnWatchDirectory()
|
|
{
|
|
if (h) StopMonitoring(h);
|
|
h= NULL;
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
// ************** LUA DIR WATCH **************************
|
|
|
|
void CALLBACK LuaCallback(LPTSTR szFile, void*M,DWORD action)
|
|
{
|
|
HDIR_MONITOR Monitor =(HDIR_MONITOR)M;
|
|
WORLD *pScene = (WORLD *)Monitor->psCene;
|
|
ObjectEventDatas datas;
|
|
|
|
datas.type = EVENT_TYPE_STRING;
|
|
sprintf(datas.data,"%s/%s",(char *)Monitor->szTrackedDir,szFile);
|
|
//sprintf(datas.data,"%s",szFile);
|
|
|
|
pScene->LuaProcessEventDatas(EVT_onDirWatch, &datas);
|
|
}
|
|
|
|
int DWLua_WatchDirectory(char *DirectoryToWatch, void *pS)
|
|
{
|
|
if (hLua) StopMonitoring(hLua);
|
|
hLua = NULL;
|
|
hLua = StartMonitoring(TEXT(DirectoryToWatch),
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME,
|
|
LuaCallback,pS);
|
|
return TRUE;
|
|
}
|
|
|
|
int DWLua_UnWatchDirectory()
|
|
{
|
|
if (hLua) StopMonitoring(hLua);
|
|
hLua = NULL;
|
|
return 1;
|
|
}
|