/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "SceneViewer.h"
#include "SceneSync.h"
#include "MaxMain/plMaxCFGFile.h"
#include "MaxMain/resource.h"
// For ShellExecute
#include
static const char *kDebugClientExe = "plClient_dbg.exe";
static const char *kReleaseClientExe = "plClient.exe";
static const char *kSemaphoreName = "PlasmaSceneViewer";
static const char *kPipeName = "\\\\.\\pipe\\PlasmaSceneViewer";
SceneViewer::SceneViewer() : fhDlg(NULL)
{
// Get the plugin CFG dir
const char *plugFile = plMaxConfig::GetPluginIni();
fUpdate = (GetPrivateProfileInt("SceneViewer", "Update", 1, plugFile) != 0);
fUpdateFreq = GetPrivateProfileInt("SceneViewer", "UpdateFreq", 500, plugFile);
fLoadOld = (GetPrivateProfileInt("SceneViewer", "LoadOld", 0, plugFile) != 0);
fReleaseExe = (GetPrivateProfileInt("SceneViewer", "ReleaseExe", 1, plugFile) != 0);
}
SceneViewer::~SceneViewer()
{
// Make sure the client is shut down
ISetRunning(false);
// Get the plugin CFG dir
const char *plugFile = plMaxConfig::GetPluginIni();
char buf[20];
WritePrivateProfileString("SceneViewer", "Update", fUpdate ? "1" : "0", plugFile);
WritePrivateProfileString("SceneViewer", "UpdateFreq", itoa(fUpdateFreq, buf, 10), plugFile);
WritePrivateProfileString("SceneViewer", "LoadOld", fLoadOld ? "1" : "0", plugFile);
WritePrivateProfileString("SceneViewer", "ReleaseExe", fReleaseExe ? "1" : "0", plugFile);
}
SceneViewer &SceneViewer::Instance()
{
static SceneViewer theInstance;
return theInstance;
}
void SceneViewer::Show()
{
// If the dialog is already created, make sure it is visible
if (fhDlg)
{
if (IsIconic(fhDlg))
ShowWindow(fhDlg, SW_RESTORE);
}
else
{
fhDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_SCENEVIEWER), GetCOREInterface()->GetMAXHWnd(), ForwardDlgProc);
}
}
// Toggles the client and SceneSync
bool SceneViewer::IToggleRunning()
{
fRunning = !fRunning;
return ISetRunning(fRunning);
}
// Starts/Stops the client and SceneSync
bool SceneViewer::ISetRunning(bool running)
{
if (running)
{
// The client actually is running, hmmm
if (SceneSync::Instance().IsClientRunning())
return true;
// If we're not loading old data, or we are but it's not there, try to create some.
if (!fLoadOld || !SceneSync::Instance().CanLoadOldResMgr())
{
// If creation fails, fail
if (!SceneSync::Instance().CreateClientData())
return false;
}
char path[MAX_PATH];
SceneSync::Instance().GetOutputDir(path);
strcat(path, "dat\\");
// Start the client
char *options = TRACKED_NEW char[strlen(path)+2+strlen(kSemaphoreName)+strlen(kPipeName)+6];
sprintf(options, "-s %s %s \"%s\"", kSemaphoreName, kPipeName, path);
int ret = (int)ShellExecute(NULL,
"open",
fReleaseExe ? kReleaseClientExe : kDebugClientExe,
options,
plMaxConfig::GetClientPath(),
SW_SHOWNORMAL);
delete [] options;
// Client start failed
if (ret < 32)
return false;
// Start client sync
SceneSync::Instance().SetUpdateFreq(fUpdateFreq);
SceneSync::Instance().BeginClientSync(kSemaphoreName, kPipeName);
return true;
}
else
{
if (SceneSync::Instance().IsClientRunning())
SceneSync::Instance().EndClientSync(false);
return true;
}
}
BOOL SceneViewer::ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
return Instance().DlgProc(hDlg, msg, wParam, lParam);
}
BOOL SceneViewer::DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
fhDlg = hDlg;
// Set the exe to use
HWND hExeCombo = GetDlgItem(hDlg, IDC_EXE);
ComboBox_AddString(hExeCombo, "Release");
ComboBox_AddString(hExeCombo, "Debug");
ComboBox_SetCurSel(hExeCombo, fReleaseExe ? 0 : 1);
// Set the client path
const char *path = plMaxConfig::GetClientPath(false, true);
ICustEdit *edit = GetICustEdit(GetDlgItem(hDlg, IDC_CLIENT_PATH));
edit->SetText((char*)path);
// Set the "Load old data" checkbox
HWND hLoadOld = GetDlgItem(hDlg, IDC_REUSE_DATA);
Button_SetCheck(hLoadOld, fLoadOld ? BST_CHECKED : BST_UNCHECKED);
Button_Enable(hLoadOld, SceneSync::Instance().CanLoadOldResMgr());
// Set the update controls
float val = float(fUpdateFreq) / 1000.f;
ISpinnerControl *spin = SetupFloatSpinner(hDlg, IDC_SPINNER, IDC_EDIT, 0.1, 1.f, val);
spin->Enable(fUpdate);
CheckDlgButton(hDlg, IDC_UPDATE, fUpdate ? BST_CHECKED : BST_UNCHECKED);
IEnableSetupControls(!SceneSync::Instance().IsClientRunning());
}
return TRUE;
case WM_COMMAND:
// Start/Stop SceneViewer
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_START)
{
IToggleRunning();
IEnableSetupControls(!SceneSync::Instance().IsClientRunning());
return TRUE;
}
// Close dialog
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
{
DestroyWindow(hDlg);
fhDlg = NULL;
return TRUE;
}
// Browse for directory
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_DIR)
{
const char *path = plMaxConfig::GetClientPath(true);
if (path)
{
ICustEdit *edit = GetICustEdit(GetDlgItem(hDlg, IDC_CLIENT_PATH));
edit->SetText((char*)path);
}
return TRUE;
}
// "Load old data" selection changed
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_REUSE_DATA)
{
fLoadOld = (Button_GetCheck((HWND)lParam) == BST_CHECKED);
return TRUE;
}
// Release/Debug exe selection changed
else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_EXE)
{
int sel = ComboBox_GetCurSel((HWND)lParam);
fReleaseExe = (sel == 0);
return TRUE;
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_UPDATE)
{
fUpdate = (SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED);
ISpinnerControl *spin = GetISpinner(GetDlgItem(hDlg, IDC_SPINNER));
spin->Enable(fUpdate);
ReleaseISpinner(spin);
// If update was turned on, send out an update message so any dirty objects
// will be reconverted right away
if (fUpdate)
SceneSync::Instance().SetUpdateFreq(fUpdateFreq);
return TRUE;
}
break;
// Update frequency changed
case CC_SPINNER_CHANGE:
if (LOWORD(wParam) == IDC_SPINNER)
{
ISpinnerControl *spin = (ISpinnerControl*)lParam;
float val = spin->GetFVal();
fUpdateFreq = int(val*1000.f);
SceneSync::Instance().SetUpdateFreq(fUpdateFreq);
}
return TRUE;
// Type in directory
case WM_CUSTEDIT_ENTER:
if (wParam == IDC_CLIENT_PATH)
{
ICustEdit *edit = GetICustEdit((HWND)lParam);
char path[MAX_PATH];
edit->GetText(path, sizeof(path));
plMaxConfig::SetClientPath(path);
}
return TRUE;
}
return FALSE;
}
void SceneViewer::IEnableSetupControls(bool enable)
{
ICustEdit *edit = GetICustEdit(GetDlgItem(fhDlg, IDC_CLIENT_PATH));
edit->Enable(enable);
EnableWindow(GetDlgItem(fhDlg, IDC_DIR), enable);
EnableWindow(GetDlgItem(fhDlg, IDC_EXE), enable);
EnableWindow(GetDlgItem(fhDlg, IDC_REUSE_DATA), enable);
SetWindowText(GetDlgItem(fhDlg, IDC_START), enable ? "Start" : "Stop");
}