mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 02:33:23 +02:00
Add progress bar
This commit is contained in:
parent
7aef864d7f
commit
9f110cac13
8 changed files with 281 additions and 96 deletions
|
@ -92,7 +92,8 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION
|
|||
EXSTYLE WS_EX_APPWINDOW
|
||||
FONT 10, "MS Shell Dlg", 400, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "",IDC_VOXEL,"Static",SS_BLACKRECT,65,27,174,123
|
||||
CONTROL "",IDC_VOXEL,"Static",SS_BLACKRECT,65,3,174,123, NOT WS_VISIBLE
|
||||
CONTROL "", IDC_PROGRESS, "Static", SS_BLACKRECT, 35, 165, 239, 5, NOT WS_VISIBLE
|
||||
EDITTEXT IDC_ORGNAME,44,68,219,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER
|
||||
EDITTEXT IDC_USERNAME,44,95,219,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER
|
||||
EDITTEXT IDC_PASSWORD,44,122,219,12,ES_PASSWORD | ES_AUTOHSCROLL | NOT WS_VISIBLE | NOT WS_BORDER
|
||||
|
@ -101,8 +102,8 @@ BEGIN
|
|||
LTEXT "Password",IDC_PASSWORD_BANNER,48,122,219,12,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_MESSAGE_LABEL,5,39,299,23,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_ACTION_LABEL,10,15,286,25,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_MESSAGE2_LABEL,35,148,239,15,NOT WS_VISIBLE
|
||||
CTEXT "",IDC_ACTION2_LABEL,15,123,278,25,NOT WS_VISIBLE
|
||||
RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE
|
||||
CONTROL "",IDC_TERMS_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15
|
||||
CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE
|
||||
|
|
|
@ -109,8 +109,10 @@ BOOL CLauncherDlg::OnInitDialog() {
|
|||
m_trouble = (CStatic *)GetDlgItem(IDC_TROUBLE);
|
||||
|
||||
m_voxel = (CStatic *)GetDlgItem(IDC_VOXEL);
|
||||
m_progress = (CStatic *)GetDlgItem(IDC_PROGRESS);
|
||||
|
||||
m_voxel->EnableD2DSupport();
|
||||
m_progress->EnableD2DSupport();
|
||||
|
||||
m_pRenderTarget = GetRenderTarget();
|
||||
|
||||
|
@ -292,8 +294,9 @@ afx_msg void CLauncherDlg::OnNextClicked() {
|
|||
|
||||
void CLauncherDlg::drawBackground(CHwndRenderTarget* pRenderTarget) {
|
||||
CD2DBitmap m_pBitmamBackground(pRenderTarget, IDB_PNG1, _T("PNG"));
|
||||
auto size = pRenderTarget->GetSize();
|
||||
auto size = GetRenderTarget()->GetSize();
|
||||
CD2DRectF backRec(0.0f, 0.0f, size.width, size.height);
|
||||
GetRenderTarget()->DrawBitmap(&m_pBitmamBackground, backRec);
|
||||
pRenderTarget->DrawBitmap(&m_pBitmamBackground, backRec);
|
||||
}
|
||||
|
||||
|
@ -303,7 +306,7 @@ void CLauncherDlg::drawLogo(CHwndRenderTarget* pRenderTarget) {
|
|||
int logoWidth = 231;
|
||||
int logoHeight = 173;
|
||||
float logoPosX = 0.5f * (size.width - logoWidth);
|
||||
float logoPosY = 0.95f * (size.height - logoHeight);
|
||||
float logoPosY = 0.5f * (size.height - logoHeight);
|
||||
CD2DRectF logoRec(logoPosX, logoPosY, logoPosX + logoWidth, logoPosY + logoHeight);
|
||||
pRenderTarget->DrawBitmap(&m_pBitmamLogo, logoRec);
|
||||
}
|
||||
|
@ -338,6 +341,26 @@ void CLauncherDlg::drawVoxel(CHwndRenderTarget* pRenderTarget) {
|
|||
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||
}
|
||||
|
||||
void CLauncherDlg::drawProgress(CHwndRenderTarget* pRenderTarget, float progress, const D2D1::ColorF& color) {
|
||||
auto size = pRenderTarget->GetPixelSize();
|
||||
if (progress == 0.0f) {
|
||||
return;
|
||||
}
|
||||
CRect winRec;
|
||||
CD2DRectF bkCircleRect1 = CD2DRectF(0,0,(float)size.height, (float)size.height);
|
||||
progress = min(1.0f, progress);
|
||||
CD2DRectF bkCircleRect2 = CD2DRectF((float)size.width * progress - (float)size.height, 0,
|
||||
(float)size.width * progress, (float)size.height);
|
||||
CD2DRectF bkRect = CD2DRectF(0.5f*(float)size.height, 0,
|
||||
(float)size.width*progress - 0.5f*(float)size.height, (float)size.height);
|
||||
CD2DEllipse bkCircle1 = CD2DEllipse(bkCircleRect1);
|
||||
CD2DEllipse bkCircle2 = CD2DEllipse(bkCircleRect2);
|
||||
CD2DSolidColorBrush brush(pRenderTarget, color);
|
||||
pRenderTarget->FillEllipse(bkCircle1, &brush);
|
||||
pRenderTarget->FillEllipse(bkCircle2, &brush);
|
||||
pRenderTarget->FillRectangle(bkRect, &brush);
|
||||
}
|
||||
|
||||
void CLauncherDlg::showWindows(std::vector<CStatic*> windows, bool show) {
|
||||
for (auto window : windows) {
|
||||
window->ShowWindow(show ? SW_SHOW : SW_HIDE);
|
||||
|
@ -346,6 +369,7 @@ void CLauncherDlg::showWindows(std::vector<CStatic*> windows, bool show) {
|
|||
|
||||
void CLauncherDlg::prepareLogin(DrawStep step) {
|
||||
m_voxel->ShowWindow(SW_HIDE);
|
||||
m_progress->ShowWindow(SW_HIDE);
|
||||
m_orgname_banner->SetWindowTextW(_T("Organization Name"));
|
||||
m_username_banner->SetWindowTextW(_T("Username"));
|
||||
m_password_banner->SetWindowTextW(_T("Password"));
|
||||
|
@ -370,7 +394,6 @@ void CLauncherDlg::prepareLogin(DrawStep step) {
|
|||
m_trouble->SetWindowTextW(_T("Having Trouble?"));
|
||||
m_trouble->ShowWindow(SW_SHOW);
|
||||
m_trouble_link.ShowWindow(SW_SHOW);
|
||||
|
||||
}
|
||||
|
||||
void CLauncherDlg::prepareChoose() {
|
||||
|
@ -410,6 +433,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
|
|||
m_action_label->ShowWindow(SW_HIDE);
|
||||
m_message_label->ShowWindow(SW_HIDE);
|
||||
m_voxel->ShowWindow(SW_SHOW);
|
||||
m_progress->ShowWindow(SW_SHOW);
|
||||
CString actionText = _T("");
|
||||
CString messageText = _T("");
|
||||
|
||||
|
@ -440,6 +464,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
|
|||
setVerticalElement(m_message2_label, 0, 5, false);
|
||||
setVerticalElement(&m_btnNext, 10);
|
||||
m_btnNext.ShowWindow(SW_SHOW);
|
||||
m_progress->ShowWindow(SW_HIDE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -503,7 +528,6 @@ BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) {
|
|||
|
||||
HBRUSH CLauncherDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
|
||||
{
|
||||
|
||||
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
|
||||
TextFormat textFormat;
|
||||
int resId = pWnd->GetDlgCtrlID();
|
||||
|
@ -523,6 +547,7 @@ HBRUSH CLauncherDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
|
|||
CRect lineRect = CRect(rect.left + padding, rect.bottom, rect.right - padding, rect.bottom + borderThick);
|
||||
lineRect.MoveToY(lineRect.bottom + 1);
|
||||
pDC->FillSolidRect(lineRect, COLOR_GREY);
|
||||
|
||||
}
|
||||
}
|
||||
return (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
|
@ -622,7 +647,9 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
if (_drawStep != DrawStep::DrawError) {
|
||||
if (_drawStep == DrawStep::DrawProcessSetup ||
|
||||
_drawStep == DrawStep::DrawProcessUpdate ||
|
||||
_drawStep == DrawStep::DrawProcessUninstall) {
|
||||
_drawStep == DrawStep::DrawProcessUninstall ||
|
||||
_drawStep == DrawStep::DrawProcessFinishHq ||
|
||||
_drawStep == DrawStep::DrawProcessFinishUpdate) {
|
||||
// Refresh
|
||||
setDrawDialog(_drawStep, true);
|
||||
}
|
||||
|
@ -631,13 +658,11 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
if (theApp._manager.needsUninstall()) {
|
||||
theApp._manager.addToLog(_T("Waiting to uninstall"));
|
||||
setDrawDialog(DrawStep::DrawProcessUninstall);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Start splash screen"));
|
||||
setDrawDialog(DrawStep::DrawLogo);
|
||||
}
|
||||
}
|
||||
else if (_splashStep > 100) {
|
||||
} else if (_splashStep > 100) {
|
||||
_showSplash = false;
|
||||
if (theApp._manager.shouldShutDown()) {
|
||||
if (_applicationWND != NULL) {
|
||||
|
@ -647,21 +672,17 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
if (LauncherUtils::isProcessWindowOpened(L"interface.exe")) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else if (theApp._manager.needsUpdate()) {
|
||||
} else if (theApp._manager.needsUpdate()) {
|
||||
startProcess();
|
||||
}
|
||||
else if (theApp._manager.needsUninstall()) {
|
||||
} else if (theApp._manager.needsUninstall()) {
|
||||
if (theApp._manager.uninstallApplication()) {
|
||||
theApp._manager.addToLog(_T("HQ uninstalled successfully."));
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("HQ failed to uninstall."));
|
||||
theApp._manager.setFailed(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
theApp._manager.addToLog(_T("Starting login"));
|
||||
setDrawDialog(DrawStep::DrawLoginLogin);
|
||||
}
|
||||
|
@ -673,6 +694,10 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
|
|||
}
|
||||
}
|
||||
if (theApp._manager.shouldLaunch()) {
|
||||
if (theApp._manager.needsInstall() || theApp._manager.needsUpdate()) {
|
||||
auto finishProcess = theApp._manager.needsUpdate() ? DrawStep::DrawProcessFinishUpdate : DrawStep::DrawProcessFinishHq;
|
||||
setDrawDialog(finishProcess);
|
||||
}
|
||||
_applicationWND = theApp._manager.launchApplication();
|
||||
}
|
||||
}
|
||||
|
@ -699,16 +724,16 @@ void CLauncherDlg::setVerticalElement(CWnd* element, int verticalOffset, int hei
|
|||
|
||||
void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) {
|
||||
_drawStep = step;
|
||||
float progress = 0.0f;
|
||||
auto m_pRenderTarget = GetRenderTarget();
|
||||
auto m_voxelRenderTarget = m_voxel->GetRenderTarget();
|
||||
auto m_progressRenderTarget = m_progress->GetRenderTarget();
|
||||
switch (_drawStep) {
|
||||
case DrawStep::DrawLogo:
|
||||
m_pRenderTarget->BeginDraw();
|
||||
drawBackground(m_pRenderTarget);
|
||||
drawLogo(m_pRenderTarget);
|
||||
m_pRenderTarget->EndDraw();
|
||||
m_voxelRenderTarget->BeginDraw();
|
||||
drawLogo(m_voxelRenderTarget);
|
||||
m_voxelRenderTarget->EndDraw();
|
||||
break;
|
||||
case DrawStep::DrawLoginLogin:
|
||||
case DrawStep::DrawLoginErrorOrg:
|
||||
|
@ -744,7 +769,12 @@ void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) {
|
|||
drawSmallLogo(m_pRenderTarget);
|
||||
m_pRenderTarget->EndDraw();
|
||||
RedrawWindow();
|
||||
}
|
||||
}
|
||||
m_progressRenderTarget->BeginDraw();
|
||||
m_progressRenderTarget->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
drawProgress(m_progressRenderTarget, 1.0f, D2D1::ColorF(0.2f, 0.2f, 0.2f));
|
||||
drawProgress(m_progressRenderTarget, theApp._manager.getProgress(), D2D1::ColorF(0.0f, 0.62f, 0.9f));
|
||||
m_progressRenderTarget->EndDraw();
|
||||
m_voxelRenderTarget->BeginDraw();
|
||||
drawVoxel(m_voxelRenderTarget);
|
||||
m_voxelRenderTarget->EndDraw();
|
||||
|
|
|
@ -53,9 +53,7 @@ protected:
|
|||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
void startProcess();
|
||||
void setCustomDialog();
|
||||
|
||||
void setVerticalElement(CWnd* element, int verticalOffset, int heightOffset = 0, bool fromMainWindowBottom = true);
|
||||
|
||||
void setVerticalElement(CWnd* element, int verticalOffset, int heightOffset = 0, bool fromMainWindowBottom = true);
|
||||
BOOL getHQInfo(const CString& orgname);
|
||||
DrawStep _drawStep { DrawStep::DrawLogo };
|
||||
BOOL getTextFormat(int ResID, TextFormat& formatOut);
|
||||
|
@ -86,6 +84,7 @@ protected:
|
|||
CStatic* m_terms;
|
||||
CStatic* m_trouble;
|
||||
CStatic* m_voxel;
|
||||
CStatic* m_progress;
|
||||
|
||||
CEdit m_orgname;
|
||||
CEdit m_username;
|
||||
|
@ -101,6 +100,7 @@ protected:
|
|||
void drawLogo(CHwndRenderTarget* pRenderTarget);
|
||||
void drawSmallLogo(CHwndRenderTarget* pRenderTarget);
|
||||
void drawVoxel(CHwndRenderTarget* pRenderTarget);
|
||||
void drawProgress(CHwndRenderTarget* pRenderTarget, float progress, const D2D1::ColorF& color);
|
||||
|
||||
void prepareLogin(DrawStep step);
|
||||
void prepareProcess(DrawStep step);
|
||||
|
|
|
@ -24,7 +24,8 @@ LauncherManager::~LauncherManager() {
|
|||
void LauncherManager::init() {
|
||||
initLog();
|
||||
addToLog(_T("Getting most recent build"));
|
||||
LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion);
|
||||
CString response;
|
||||
LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion, response);
|
||||
if (error == LauncherUtils::ResponseError::NoError) {
|
||||
addToLog(_T("Latest version: ") + _latestVersion);
|
||||
CString currentVersion;
|
||||
|
@ -41,14 +42,17 @@ void LauncherManager::init() {
|
|||
} else if (_loggedIn) {
|
||||
addToLog(_T("Interface not found but logged in. Reinstalling"));
|
||||
_shouldUpdate = TRUE;
|
||||
} else {
|
||||
_shouldInstall = TRUE;
|
||||
}
|
||||
} else {
|
||||
_hasFailed = true;
|
||||
CString msg;
|
||||
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
|
||||
addToLog(msg);
|
||||
msg.Format(_T("Response: %s"), response);
|
||||
addToLog(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOL LauncherManager::initLog() {
|
||||
|
@ -146,6 +150,37 @@ BOOL LauncherManager::restartLauncher() {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void LauncherManager::updateProgress(ProcessType processType, float progress) {
|
||||
switch (processType) {
|
||||
case LauncherManager::DownloadContent:
|
||||
_progress = DOWNLOAD_CONTENT_INSTALL_WEIGHT * progress;
|
||||
break;
|
||||
case LauncherManager::UnzipContent:
|
||||
_progress = DOWNLOAD_CONTENT_INSTALL_WEIGHT +
|
||||
EXTRACT_CONTENT_INSTALL_WEIGHT * progress;
|
||||
break;
|
||||
case LauncherManager::DownloadApplication:
|
||||
_progress = !_shouldUpdate ?
|
||||
(DOWNLOAD_CONTENT_INSTALL_WEIGHT +
|
||||
EXTRACT_CONTENT_INSTALL_WEIGHT +
|
||||
DOWNLOAD_APPLICATION_INSTALL_WEIGHT * progress) :
|
||||
DOWNLOAD_APPLICATION_UPDATE_WEIGHT * progress;
|
||||
break;
|
||||
case LauncherManager::UnzipApplication:
|
||||
_progress = !_shouldUpdate ?
|
||||
(DOWNLOAD_CONTENT_INSTALL_WEIGHT +
|
||||
EXTRACT_CONTENT_INSTALL_WEIGHT +
|
||||
DOWNLOAD_APPLICATION_INSTALL_WEIGHT +
|
||||
EXTRACT_APPLICATION_INSTALL_WEIGHT * progress) :
|
||||
(DOWNLOAD_APPLICATION_UPDATE_WEIGHT +
|
||||
EXTRACT_APPLICATION_UPDATE_WEIGHT * progress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TRACE("progress = %f\n", _progress);
|
||||
}
|
||||
|
||||
BOOL LauncherManager::createShortcuts() {
|
||||
CString desktopLnkPath;
|
||||
addToLog(_T("Creating shortcuts."));
|
||||
|
@ -301,7 +336,8 @@ BOOL LauncherManager::createConfigJSON() {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain, CString& content, bool& loggedIn) {
|
||||
LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain,
|
||||
CString& content, bool& loggedIn) {
|
||||
CString configPath;
|
||||
getAndCreatePaths(PathType::Interface_Directory, configPath);
|
||||
configPath += "\\config.json";
|
||||
|
@ -329,8 +365,10 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString
|
|||
CString contentTypeJson = L"content-type:application/json";
|
||||
CString response;
|
||||
CString url = _T("/organizations/") + hash + _T(".json");
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"orgs.highfidelity.com", url,
|
||||
contentTypeJson, CStringA(), response, false);
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher",
|
||||
L"orgs.highfidelity.com", url,
|
||||
contentTypeJson, CStringA(),
|
||||
response, false);
|
||||
if (error != LauncherUtils::ResponseError::NoError) {
|
||||
return error;
|
||||
}
|
||||
|
@ -345,11 +383,14 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString
|
|||
return LauncherUtils::ResponseError::ParsingJSON;
|
||||
}
|
||||
|
||||
LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut) {
|
||||
LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut, CString& versionOut,
|
||||
CString& response) {
|
||||
CString contentTypeJson = L"content-type:application/json";
|
||||
CString response;
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"thunder.highfidelity.com", L"/builds/api/tags/latest?format=json",
|
||||
contentTypeJson, CStringA(), response, false);
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher",
|
||||
L"thunder.highfidelity.com",
|
||||
L"/builds/api/tags/latest?format=json",
|
||||
contentTypeJson, CStringA(),
|
||||
response, false);
|
||||
if (error != LauncherUtils::ResponseError::NoError) {
|
||||
return error;
|
||||
}
|
||||
|
@ -377,7 +418,8 @@ LauncherUtils::ResponseError LauncherManager::getMostRecentBuild(CString& urlOut
|
|||
return LauncherUtils::ResponseError::ParsingJSON;
|
||||
}
|
||||
|
||||
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username, const CString& password) {
|
||||
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username,
|
||||
const CString& password) {
|
||||
CStringA post = "grant_type=password&username=";
|
||||
post += username;
|
||||
post += "&password=";
|
||||
|
@ -386,8 +428,11 @@ LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const
|
|||
|
||||
CString contentTypeText = L"content-type:application/x-www-form-urlencoded";
|
||||
CString response;
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher", L"metaverse.highfidelity.com", L"/oauth/token",
|
||||
contentTypeText, post, response, true);
|
||||
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(L"HQ Launcher",
|
||||
L"metaverse.highfidelity.com",
|
||||
L"/oauth/token",
|
||||
contentTypeText, post,
|
||||
response, true);
|
||||
if (error != LauncherUtils::ResponseError::NoError) {
|
||||
return error;
|
||||
}
|
||||
|
@ -438,11 +483,11 @@ BOOL LauncherManager::uninstallApplication() {
|
|||
return success;
|
||||
}
|
||||
|
||||
void LauncherManager::onZipExtracted(ZipType type, int size) {
|
||||
if (type == ZipType::ZipContent) {
|
||||
void LauncherManager::onZipExtracted(ProcessType type, int size) {
|
||||
if (type == ProcessType::UnzipContent) {
|
||||
addToLog(_T("Downloading application."));
|
||||
downloadApplication();
|
||||
} else if (type == ZipType::ZipApplication) {
|
||||
} else if (type == ProcessType::UnzipApplication) {
|
||||
createShortcuts();
|
||||
addToLog(_T("Launching application."));
|
||||
_shouldLaunch = TRUE;
|
||||
|
@ -457,17 +502,23 @@ void LauncherManager::onZipExtracted(ZipType type, int size) {
|
|||
BOOL LauncherManager::extractApplication() {
|
||||
CString installPath;
|
||||
getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installPath);
|
||||
addToLog(_T("Creating config.json"));
|
||||
createConfigJSON();
|
||||
BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipApplication, LauncherUtils::cStringToStd(_applicationZipPath),
|
||||
LauncherUtils::cStringToStd(installPath), [&](int type, int size) {
|
||||
std::function<void(int, int)> onExtractFinished = [&](int type, int size) {
|
||||
addToLog(_T("Creating config.json"));
|
||||
createConfigJSON();
|
||||
if (size > 0) {
|
||||
onZipExtracted((ZipType)type, size);
|
||||
onZipExtracted((ProcessType)type, size);
|
||||
} else {
|
||||
addToLog(_T("Error decompressing application zip file."));
|
||||
_hasFailed = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
std::function<void(float)> onProgress = [&](float progress) {
|
||||
updateProgress(ProcessType::UnzipApplication, progress);
|
||||
};
|
||||
BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipApplication,
|
||||
LauncherUtils::cStringToStd(_applicationZipPath),
|
||||
LauncherUtils::cStringToStd(installPath),
|
||||
onExtractFinished, onProgress);
|
||||
if (success) {
|
||||
addToLog(_T("Created thread for unzipping application."));
|
||||
} else {
|
||||
|
@ -476,8 +527,8 @@ BOOL LauncherManager::extractApplication() {
|
|||
return success;
|
||||
}
|
||||
|
||||
void LauncherManager::onFileDownloaded(DownloadType type) {
|
||||
if (type == DownloadType::DownloadContent) {
|
||||
void LauncherManager::onFileDownloaded(ProcessType type) {
|
||||
if (type == ProcessType::DownloadContent) {
|
||||
addToLog(_T("Deleting content directory before install"));
|
||||
CString contentDir;
|
||||
getAndCreatePaths(PathType::Content_Directory, contentDir);
|
||||
|
@ -490,7 +541,7 @@ void LauncherManager::onFileDownloaded(DownloadType type) {
|
|||
setFailed(true);
|
||||
}
|
||||
});
|
||||
} else if (type == DownloadType::DownloadApplication) {
|
||||
} else if (type == ProcessType::DownloadApplication) {
|
||||
addToLog(_T("Deleting application directory before install"));
|
||||
CString applicationDir;
|
||||
getAndCreatePaths(PathType::Interface_Directory, applicationDir);
|
||||
|
@ -511,16 +562,21 @@ BOOL LauncherManager::installContent() {
|
|||
std::string contentZipFile = LauncherUtils::cStringToStd(_contentZipPath);
|
||||
CString contentPath;
|
||||
getAndCreatePaths(LauncherManager::PathType::Content_Directory, contentPath);
|
||||
BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipContent, contentZipFile,
|
||||
LauncherUtils::cStringToStd(contentPath), [&](int type, int size) {
|
||||
std::function<void(int, int)> onInstallFinished = [&](int type, int size) {
|
||||
if (size > 0) {
|
||||
addToLog(_T("Content zip decompresed."));
|
||||
onZipExtracted((ZipType)type, size);
|
||||
} else {
|
||||
onZipExtracted((ProcessType)type, size);
|
||||
}
|
||||
else {
|
||||
addToLog(_T("Error decompressing content zip file."));
|
||||
_hasFailed = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
std::function<void(float)> onProgress = [&](float progress) {
|
||||
updateProgress(ProcessType::UnzipContent, progress);
|
||||
};
|
||||
BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipContent, contentZipFile,
|
||||
LauncherUtils::cStringToStd(contentPath), onInstallFinished, onProgress);
|
||||
if (success) {
|
||||
addToLog(_T("Created thread for unzipping content."));
|
||||
} else {
|
||||
|
@ -530,25 +586,32 @@ BOOL LauncherManager::installContent() {
|
|||
}
|
||||
|
||||
|
||||
BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CString& outPath) {
|
||||
BOOL LauncherManager::downloadFile(ProcessType type, const CString& url, CString& outPath) {
|
||||
CString fileName = url.Mid(url.ReverseFind('/') + 1);
|
||||
CString downloadDirectory;
|
||||
BOOL success = getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDirectory);
|
||||
outPath = downloadDirectory + fileName;
|
||||
_currentProcess = type;
|
||||
if (success) {
|
||||
addToLog(_T("Downloading: ") + url);
|
||||
if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type, bool error) {
|
||||
std::function<void(int, bool)> onDownloadFinished = [&](int type, bool error) {
|
||||
if (!error) {
|
||||
onFileDownloaded((DownloadType)type);
|
||||
} else {
|
||||
if (type == DownloadType::DownloadApplication) {
|
||||
onFileDownloaded((ProcessType)type);
|
||||
}
|
||||
else {
|
||||
if (type == ProcessType::DownloadApplication) {
|
||||
addToLog(_T("Error downloading content."));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
addToLog(_T("Error downloading application."));
|
||||
}
|
||||
_hasFailed = true;
|
||||
}
|
||||
})) {
|
||||
};
|
||||
std::function<void(float)> onProgress = [&](float progress) {
|
||||
updateProgress(_currentProcess, progress);
|
||||
};
|
||||
if (!LauncherUtils::downloadFileOnThread(type, url, outPath, onDownloadFinished, onProgress)) {
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -558,10 +621,10 @@ BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CStrin
|
|||
BOOL LauncherManager::downloadContent() {
|
||||
addToLog(_T("Downloading content."));
|
||||
CString contentURL = getContentURL();
|
||||
return downloadFile(DownloadType::DownloadContent, contentURL, _contentZipPath);
|
||||
return downloadFile(ProcessType::DownloadContent, contentURL, _contentZipPath);
|
||||
}
|
||||
|
||||
BOOL LauncherManager::downloadApplication() {
|
||||
CString applicationURL = getLatestInterfaceURL();
|
||||
return downloadFile(DownloadType::DownloadApplication, applicationURL, _applicationZipPath);
|
||||
}
|
||||
return downloadFile(ProcessType::DownloadApplication, applicationURL, _applicationZipPath);
|
||||
}
|
|
@ -19,6 +19,12 @@ const CString DIRECTORY_NAME_CONTENT = _T("content");
|
|||
const CString EXTRA_PARAMETERS = _T(" --suppress-settings-reset --no-launcher --no-updater");
|
||||
const CString LAUNCHER_EXE_FILENAME = _T("HQ Launcher.exe");
|
||||
const bool INSTALL_ZIP = true;
|
||||
const float DOWNLOAD_CONTENT_INSTALL_WEIGHT = 0.2f;
|
||||
const float EXTRACT_CONTENT_INSTALL_WEIGHT = 0.1f;
|
||||
const float DOWNLOAD_APPLICATION_INSTALL_WEIGHT = 0.5f;
|
||||
const float EXTRACT_APPLICATION_INSTALL_WEIGHT = 0.2f;
|
||||
const float DOWNLOAD_APPLICATION_UPDATE_WEIGHT = 0.75f;
|
||||
const float EXTRACT_APPLICATION_UPDATE_WEIGHT = 0.25f;
|
||||
|
||||
class LauncherManager
|
||||
{
|
||||
|
@ -33,16 +39,8 @@ public:
|
|||
StartMenu_Directory,
|
||||
Temp_Directory
|
||||
};
|
||||
enum ZipType {
|
||||
ZipContent = 0,
|
||||
ZipApplication
|
||||
};
|
||||
enum DownloadType {
|
||||
DownloadContent = 0,
|
||||
DownloadApplication
|
||||
};
|
||||
enum ErrorType {
|
||||
ErrorNetworkAuth,
|
||||
ErrorNetworkAuth = 0,
|
||||
ErrorNetworkUpdate,
|
||||
ErrorNetworkHq,
|
||||
ErrorDownloading,
|
||||
|
@ -50,6 +48,12 @@ public:
|
|||
ErrorInstall,
|
||||
ErrorIOFiles
|
||||
};
|
||||
enum ProcessType {
|
||||
DownloadContent,
|
||||
DownloadApplication,
|
||||
UnzipContent,
|
||||
UnzipApplication
|
||||
};
|
||||
LauncherManager();
|
||||
~LauncherManager();
|
||||
void init();
|
||||
|
@ -62,7 +66,7 @@ public:
|
|||
BOOL isApplicationInstalled(CString& version, CString& domain,
|
||||
CString& content, bool& loggedIn);
|
||||
LauncherUtils::ResponseError getAccessTokenForCredentials(const CString& username, const CString& password);
|
||||
LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut);
|
||||
LauncherUtils::ResponseError getMostRecentBuild(CString& urlOut, CString& versionOut, CString& response);
|
||||
LauncherUtils::ResponseError readOrganizationJSON(const CString& hash);
|
||||
LauncherUtils::ResponseError readConfigJSON(CString& version, CString& domain,
|
||||
CString& content, bool& loggedIn);
|
||||
|
@ -84,6 +88,7 @@ public:
|
|||
BOOL shouldLaunch() const { return _shouldLaunch; }
|
||||
BOOL needsUpdate() { return _shouldUpdate; }
|
||||
BOOL needsUninstall() { return _shouldUninstall; }
|
||||
BOOL needsInstall() { return _shouldInstall; }
|
||||
void setDisplayName(const CString& displayName) { _displayName = displayName; }
|
||||
bool isLoggedIn() { return _loggedIn; }
|
||||
bool hasFailed() { return _hasFailed; }
|
||||
|
@ -91,15 +96,18 @@ public:
|
|||
const CString& getLatestInterfaceURL() const { return _latestApplicationURL; }
|
||||
void uninstall() { _shouldUninstall = true; };
|
||||
|
||||
BOOL downloadFile(DownloadType type, const CString& url, CString& localPath);
|
||||
BOOL downloadFile(ProcessType type, const CString& url, CString& localPath);
|
||||
BOOL downloadContent();
|
||||
BOOL downloadApplication();
|
||||
BOOL installContent();
|
||||
BOOL extractApplication();
|
||||
void onZipExtracted(ZipType type, int size);
|
||||
void onFileDownloaded(DownloadType type);
|
||||
void onZipExtracted(ProcessType type, int size);
|
||||
void onFileDownloaded(ProcessType type);
|
||||
float getProgress() { return _progress; }
|
||||
|
||||
private:
|
||||
void updateProgress(ProcessType processType, float progress);
|
||||
ProcessType _currentProcess { ProcessType::DownloadApplication };
|
||||
CString _latestApplicationURL;
|
||||
CString _latestVersion;
|
||||
CString _contentURL;
|
||||
|
@ -109,12 +117,14 @@ private:
|
|||
CString _tokensJSON;
|
||||
CString _applicationZipPath;
|
||||
CString _contentZipPath;
|
||||
bool _loggedIn{ false };
|
||||
bool _hasFailed{ false };
|
||||
BOOL _shouldUpdate{ FALSE };
|
||||
BOOL _shouldUninstall{ FALSE };
|
||||
BOOL _shouldShutdown{ FALSE };
|
||||
BOOL _shouldLaunch{ FALSE };
|
||||
bool _loggedIn { false };
|
||||
bool _hasFailed { false };
|
||||
BOOL _shouldUpdate { FALSE };
|
||||
BOOL _shouldUninstall { FALSE };
|
||||
BOOL _shouldInstall { FALSE };
|
||||
BOOL _shouldShutdown { FALSE };
|
||||
BOOL _shouldLaunch { FALSE };
|
||||
float _progress { 0.0f };
|
||||
CStdioFile _logFile;
|
||||
};
|
||||
|
||||
|
|
|
@ -272,7 +272,9 @@ BOOL LauncherUtils::getFont(const CString& fontName, int fontSize, bool isBold,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string& path, std::vector<std::string>& files) {
|
||||
uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string& path,
|
||||
std::vector<std::string>& files,
|
||||
std::function<void(float)> progressCallback) {
|
||||
{
|
||||
CString msg;
|
||||
msg.Format(_T("Reading zip file %s, extracting to %s"), CString(zipFile.c_str()), CString(path.c_str()));
|
||||
|
@ -292,7 +294,6 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string
|
|||
theApp._manager.addToLog(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive);
|
||||
{
|
||||
CString msg;
|
||||
|
@ -313,6 +314,7 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string
|
|||
// Get root folder
|
||||
CString lastDir = _T("");
|
||||
uint64_t totalSize = 0;
|
||||
uint64_t totalCompressedSize = 0;
|
||||
bool _shouldFail = false;
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue;
|
||||
|
@ -335,7 +337,9 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string
|
|||
}
|
||||
CT2A destFile(fullFilename);
|
||||
if (mz_zip_reader_extract_to_file(&zip_archive, i, destFile, 0)) {
|
||||
totalCompressedSize += (uint64_t)file_stat.m_comp_size;
|
||||
totalSize += (uint64_t)file_stat.m_uncomp_size;
|
||||
progressCallback((float)totalCompressedSize / (float)zip_archive.m_archive_size);
|
||||
files.emplace_back(destFile);
|
||||
} else {
|
||||
CString msg;
|
||||
|
@ -466,7 +470,7 @@ BOOL LauncherUtils::hMac256(const CString& cmessage, const char* keystr, CString
|
|||
|
||||
DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
|
||||
UnzipThreadData& data = *((UnzipThreadData*)lpParameter);
|
||||
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>());
|
||||
uint64_t size = LauncherUtils::extractZip(data._zipFile, data._path, std::vector<std::string>(), data.progressCallback);
|
||||
int mb_size = (int)(size * 0.001f);
|
||||
data.callback(data._type, mb_size);
|
||||
delete &data;
|
||||
|
@ -475,7 +479,10 @@ DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
|
|||
|
||||
DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) {
|
||||
DownloadThreadData& data = *((DownloadThreadData*)lpParameter);
|
||||
auto hr = URLDownloadToFile(0, data._url, data._file, 0, NULL);
|
||||
ProgressCallback progressCallback;
|
||||
progressCallback.setProgressCallback(data.progressCallback);
|
||||
auto hr = URLDownloadToFile(0, data._url, data._file, 0,
|
||||
static_cast<LPBINDSTATUSCALLBACK>(&progressCallback));
|
||||
data.callback(data._type, hr != S_OK);
|
||||
return 0;
|
||||
}
|
||||
|
@ -487,13 +494,16 @@ DWORD WINAPI LauncherUtils::deleteDirectoryThread(LPVOID lpParameter) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback) {
|
||||
BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, const std::string& path,
|
||||
std::function<void(int, int)> callback,
|
||||
std::function<void(float)> progressCallback) {
|
||||
DWORD myThreadID;
|
||||
UnzipThreadData* unzipThreadData = new UnzipThreadData();
|
||||
unzipThreadData->_type = type;
|
||||
unzipThreadData->_zipFile = zipFile;
|
||||
unzipThreadData->_path = path;
|
||||
unzipThreadData->setCallback(callback);
|
||||
unzipThreadData->setProgressCallback(progressCallback);
|
||||
HANDLE myHandle = CreateThread(0, 0, unzipThread, unzipThreadData, 0, &myThreadID);
|
||||
if (myHandle) {
|
||||
CloseHandle(myHandle);
|
||||
|
@ -502,13 +512,16 @@ BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, cons
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int, bool)> callback) {
|
||||
BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file,
|
||||
std::function<void(int, bool)> callback,
|
||||
std::function<void(float)> progressCallback) {
|
||||
DWORD myThreadID;
|
||||
DownloadThreadData* downloadThreadData = new DownloadThreadData();
|
||||
downloadThreadData->_type = type;
|
||||
downloadThreadData->_url = url;
|
||||
downloadThreadData->_file = file;
|
||||
downloadThreadData->setCallback(callback);
|
||||
downloadThreadData->setProgressCallback(progressCallback);
|
||||
HANDLE myHandle = CreateThread(0, 0, downloadThread, downloadThreadData, 0, &myThreadID);
|
||||
if (myHandle) {
|
||||
CloseHandle(myHandle);
|
||||
|
|
|
@ -15,9 +15,57 @@
|
|||
#include "libs/json/json.h"
|
||||
#include "libs/miniz.h"
|
||||
|
||||
class LauncherUtils
|
||||
{
|
||||
class LauncherUtils {
|
||||
public:
|
||||
class ProgressCallback : public IBindStatusCallback {
|
||||
public:
|
||||
HRESULT __stdcall QueryInterface(const IID &, void **) {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
ULONG STDMETHODCALLTYPE AddRef(void) {
|
||||
return 1;
|
||||
}
|
||||
ULONG STDMETHODCALLTYPE Release(void) {
|
||||
return 1;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding *pib) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG *pnPriority) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved) {
|
||||
return S_OK;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize,
|
||||
FORMATETC *pformatetc, STGMEDIUM *pstgmed) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, IUnknown *punk) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax,
|
||||
ULONG ulStatusCode, LPCWSTR szStatusText) {
|
||||
float progress = (float)ulProgress / ulProgressMax;
|
||||
if (!isnan(progress)) {
|
||||
onProgressCallback(progress);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
onProgressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
private:
|
||||
std::function<void(float)> onProgressCallback;
|
||||
};
|
||||
|
||||
enum ResponseError {
|
||||
Open = 0,
|
||||
Connect,
|
||||
|
@ -35,10 +83,14 @@ public:
|
|||
CString _url;
|
||||
CString _file;
|
||||
std::function<void(int, bool)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
// function(type, errorType)
|
||||
void setCallback(std::function<void(int, bool)> fn) {
|
||||
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
struct UnzipThreadData {
|
||||
|
@ -47,15 +99,23 @@ public:
|
|||
std::string _path;
|
||||
// function(type, size)
|
||||
std::function<void(int, int)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
void setCallback(std::function<void(int, int)> fn) {
|
||||
callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
struct DeleteThreadData {
|
||||
CString _dirPath;
|
||||
std::function<void(bool)> callback;
|
||||
std::function<void(float)> progressCallback;
|
||||
void setCallback(std::function<void(bool)> fn) { callback = std::bind(fn, std::placeholders::_1); }
|
||||
void setProgressCallback(std::function<void(float)> fn) {
|
||||
progressCallback = std::bind(fn, std::placeholders::_1);
|
||||
}
|
||||
};
|
||||
|
||||
struct ProcessData {
|
||||
|
@ -79,11 +139,18 @@ public:
|
|||
static BOOL deleteFileOrDirectory(const CString& dirPath, bool noRecycleBin = true);
|
||||
static HRESULT createLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszArgs = _T(""));
|
||||
static BOOL hMac256(const CString& message, const char* key, CString& hashOut);
|
||||
static uint64_t extractZip(const std::string& zipFile, const std::string& path, std::vector<std::string>& files);
|
||||
static uint64_t extractZip(const std::string& zipFile, const std::string& path,
|
||||
std::vector<std::string>& files,
|
||||
std::function<void(float)> progressCallback);
|
||||
static BOOL deleteRegistryKey(const CString& registryPath);
|
||||
static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback);
|
||||
static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int, bool)> callback);
|
||||
static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path,
|
||||
std::function<void(int, int)> callback,
|
||||
std::function<void(float)> progressCallback);
|
||||
static BOOL downloadFileOnThread(int type, const CString& url, const CString& file,
|
||||
std::function<void(int, bool)> callback,
|
||||
std::function<void(float)> progressCallback);
|
||||
static BOOL deleteDirectoryOnThread(const CString& dirPath, std::function<void(bool)> callback);
|
||||
|
||||
static CString urlEncodeString(const CString& url);
|
||||
static HWND executeOnForeground(const CString& path, const CString& params);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define IDC_TERMS_LINK 1022
|
||||
#define IDC_TROUBLE 1023
|
||||
#define IDC_VOXEL 1024
|
||||
#define IDC_PROGRESS 1025
|
||||
#define IDC_TROUBLE_LINK 1027
|
||||
|
||||
// Next default values for new objects
|
||||
|
|
Loading…
Reference in a new issue