2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 10:37:41 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +1,102 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SCENE_SYNC_H
#define SCENE_SYNC_H
#include "Max.h"
#include "notify.h"
#include <vector>
#include <set>
class plMaxNode;
class hsSemaphore;
class SceneWatcher;
class plSceneNode;
#include "../pnKeyedObject/plUoid.h"
#include "../pnKeyedObject/plKey.h"
class SceneSync
{
protected:
SceneWatcher *fSceneWatcher;
hsSemaphore *fUpdateSignal;
const char *fPipeName;
int fTimerID;
int fUpdateFreq;
SceneSync();
public:
static SceneSync& Instance();
// Get the path where the current Max file will be exported to (not including "dat")
bool GetOutputDir(char *buf);
bool IsClientRunning();
// Is there valid data on disk that we can load into the ResMgr or do we need to reconvert?
bool CanLoadOldResMgr();
// Create client data
bool CreateClientData();
void SetUpdateFreq(int freq); // In milliseconds
// Start updating the client
bool BeginClientSync(const char *semaphoreName, const char *pipeName);
// Stop updating the client. If abort is true, don't try saving, something went wrong
void EndClientSync(bool abort);
protected:
bool SaveResMgr();
void IShutdownClient();
// Reconvert any dirty nodes to sync the Plasma database and the Max one
bool Update();
void AddSceneNodes(std::set<plSceneNode*>& sceneNodes, std::vector<plUoid>& delUoids, std::vector<plKey>& newKeys);
bool IStartWatching(bool forceWatch=false);
bool IStopWatching();
// Called by open and close scene.
bool IReadNodeMap(const char *dir);
bool IWriteNodeMap(const char *dir);
void IShutdown();
void IDeletePath(const char *path);
void IClearDirtyRecur(plMaxNode *node);
static void INotify(void *param, NotifyInfo *info);
static void CALLBACK ITimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
};
#endif //SCENE_SYNC_H
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SCENE_SYNC_H
#define SCENE_SYNC_H
#include "Max.h"
#include "notify.h"
#include <vector>
#include <set>
class plMaxNode;
class hsSemaphore;
class SceneWatcher;
class plSceneNode;
#include "../pnKeyedObject/plUoid.h"
#include "../pnKeyedObject/plKey.h"
class SceneSync
{
protected:
SceneWatcher *fSceneWatcher;
hsSemaphore *fUpdateSignal;
const char *fPipeName;
int fTimerID;
int fUpdateFreq;
SceneSync();
public:
static SceneSync& Instance();
// Get the path where the current Max file will be exported to (not including "dat")
bool GetOutputDir(char *buf);
bool IsClientRunning();
// Is there valid data on disk that we can load into the ResMgr or do we need to reconvert?
bool CanLoadOldResMgr();
// Create client data
bool CreateClientData();
void SetUpdateFreq(int freq); // In milliseconds
// Start updating the client
bool BeginClientSync(const char *semaphoreName, const char *pipeName);
// Stop updating the client. If abort is true, don't try saving, something went wrong
void EndClientSync(bool abort);
protected:
bool SaveResMgr();
void IShutdownClient();
// Reconvert any dirty nodes to sync the Plasma database and the Max one
bool Update();
void AddSceneNodes(std::set<plSceneNode*>& sceneNodes, std::vector<plUoid>& delUoids, std::vector<plKey>& newKeys);
bool IStartWatching(bool forceWatch=false);
bool IStopWatching();
// Called by open and close scene.
bool IReadNodeMap(const char *dir);
bool IWriteNodeMap(const char *dir);
void IShutdown();
void IDeletePath(const char *path);
void IClearDirtyRecur(plMaxNode *node);
static void INotify(void *param, NotifyInfo *info);
static void CALLBACK ITimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
};
#endif //SCENE_SYNC_H

View File

@ -1,280 +1,280 @@
/*==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 <http://www.gnu.org/licenses/>.
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 <shellapi.h>
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");
}
/*==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 <http://www.gnu.org/licenses/>.
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 <shellapi.h>
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");
}

View File

@ -1,61 +1,61 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SceneViewer_h_inc
#define SceneViewer_h_inc
#include "hsWindows.h"
// The dialog for setting up and starting the SceneViewer. Controls starting the client
// and SceneSync; SceneSync controls the updates though.
class SceneViewer
{
protected:
bool fUpdate;
int fUpdateFreq; // Update rate (ms), -1 for no update
bool fLoadOld; // Load old data if possible
bool fReleaseExe; // True for release exe, false for debug
bool fRunning; // Do we think the client is currently running (not sure since the
// client can terminate without us knowing).
HWND fhDlg; // Handle to the setup dialog
SceneViewer();
static BOOL CALLBACK ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void IEnableSetupControls(bool enable);
bool IToggleRunning();
bool ISetRunning(bool running);
public:
~SceneViewer();
static SceneViewer &Instance();
void Show();
};
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SceneViewer_h_inc
#define SceneViewer_h_inc
#include "hsWindows.h"
// The dialog for setting up and starting the SceneViewer. Controls starting the client
// and SceneSync; SceneSync controls the updates though.
class SceneViewer
{
protected:
bool fUpdate;
int fUpdateFreq; // Update rate (ms), -1 for no update
bool fLoadOld; // Load old data if possible
bool fReleaseExe; // True for release exe, false for debug
bool fRunning; // Do we think the client is currently running (not sure since the
// client can terminate without us knowing).
HWND fhDlg; // Handle to the setup dialog
SceneViewer();
static BOOL CALLBACK ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void IEnableSetupControls(bool enable);
bool IToggleRunning();
bool ISetRunning(bool running);
public:
~SceneViewer();
static SceneViewer &Instance();
void Show();
};
#endif // SceneViewer_h_inc

View File

@ -1,352 +1,352 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "SceneWatcher.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxComponent/plComponent.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../pnKeyedObject/plKey.h"
SceneWatcher::SceneWatcher() : fDirty(false)
{
RegisterNotification(INotify, this, NOTIFY_NODE_CREATED);
IAddNodeRecur((plMaxNode*)GetCOREInterface()->GetRootNode());
}
SceneWatcher::~SceneWatcher()
{
DeleteAllRefsFromMe();
UnRegisterNotification(INotify, this, NOTIFY_NODE_CREATED);
}
int SceneWatcher::NumRefs()
{
return fNodes.size();
}
RefTargetHandle SceneWatcher::GetReference(int i)
{
if (i < fNodes.size())
return fNodes[i];
hsAssert(0, "Index out of range");
return nil;
}
void SceneWatcher::SetReference(int i, RefTargetHandle rtarg)
{
if (i < fNodes.size())
fNodes[i] = (plMaxNode*)rtarg;
else
hsAssert(0, "Index out of range");
}
//
// Something in the scene has changed.
//
RefResult SceneWatcher::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
plMaxNode *node = (plMaxNode *)hTarget;
#ifdef HS_DEBUGGING
char *tmp = node->GetName();
#endif
if (message == REFMSG_CHANGE)
{
// If the message is from a component, and was not generated locally (ie.
// it came from a ref parameter), ignore it. There is no way to tell if
// one of these messages is an actual change to the component or just a
// change to the referenced object. We'll catch the real changes with
// REFMSG_USER_COMP_REF_CHANGED below.
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
if (!comp->IsCurMsgLocal())
return REF_SUCCEED;
}
// If this is a static light, ignore it
Object *obj = node->GetObjectRef();
if (obj && obj->SuperClassID() == LIGHT_CLASS_ID && !node->GetRunTimeLight())
return REF_SUCCEED;
node->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
else if (message == REFMSG_TARGET_DELETED)
{
// If the deleted node was a component, dirty everyone it was attached to
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
for (UInt32 i = 0; i < comp->NumTargets(); i++)
{
if (comp->GetTarget(i))
comp->GetTarget(i)->SetDirty(plMaxNode::kGeomDirty, true);
}
}
fDeleted.push_back(node->GetKey());
IRemoveRef(node);
ISetDirty();
}
else if (message == REFMSG_NODE_MATERIAL_CHANGED ||
message == REFMSG_USER_MAT)
{
if (!node->IsComponent())
{
node->SetDirty(plMaxNode::kMatDirty, true);
ISetDirty();
}
}
// A node was added to the components target list
else if (message == REFMSG_USER_TARGET_ADD)
{
plMaxNode *target = (plMaxNode*)partID;
target->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
// A node was deleted from the components target list
else if (message == REFMSG_USER_TARGET_DELETE)
{
plMaxNode *target = (plMaxNode*)partID;
target->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
// A ref maintained by a component PB changed (not just a propagated message
// from the ref)
else if (message == REFMSG_USER_COMP_REF_CHANGED)
{
node->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
return REF_SUCCEED;
}
bool SceneWatcher::AnyDeleted()
{
return !fDeleted.empty();
}
SceneWatcher::KeyList& SceneWatcher::GetDeleted()
{
return fDeleted;
}
const SceneWatcher::NodeList& SceneWatcher::GetWatchNodes()
{
return fNodes;
}
bool SceneWatcher::AnyDirty()
{
return fDirty;
}
void SceneWatcher::GetDirty(NodeSet& dirtyNodes)
{
int size = fNodes.size();
for (int i = 0; i < size; i++)
{
plMaxNode *node = fNodes[i];
#ifdef HS_DEBUGGING
const char *tmp = node ? node->GetName() : nil;
#endif
// If any dirty flags are set, add to dirty list
if (node && node->GetDirty(plMaxNode::kAllDirty))
IGetDependents(node, dirtyNodes);
}
fDirty = false;
}
void SceneWatcher::IAddRef(plMaxNode *node)
{
// Ensure that we don't already ref this node
if (FindRef(node) != -1)
return;
// Make a ref
int size = fNodes.size();
fNodes.resize(size+1);
MakeRefByID(FOREVER, size, node);
}
void SceneWatcher::IRemoveRef(plMaxNode *node)
{
// Delete the reference if it's in our list
int i = FindRef(node);
if (i != -1)
{
// Clear the node data, in case it is undeleted later
// (when it will be invalid)
node->ClearData(nil, nil);
node->SetDirty(plMaxNode::kAllDirty, true);
// We can never really delete this reference because the user may "undo"
// and cause it to come back, which just sets the reference again.
fNodes[i] = nil;
}
}
void SceneWatcher::IAddNodeRecur(plMaxNode *node)
{
IAddRef(node);
// If a node is dirty, make sure to set the dirty flag (since nodes may have
// been dirtied in a previous run but not reconverted yet).
if (node->GetDirty(plMaxNode::kAllDirty))
fDirty = true;
for (int i = 0; i < node->NumberOfChildren(); ++i)
{
plMaxNode *childNode = (plMaxNode*)node->GetChildNode(i);
IAddNodeRecur(childNode);
}
}
void SceneWatcher::INotify(void *param, NotifyInfo *info)
{
SceneWatcher *inst = (SceneWatcher*)param;
int code = info->intcode;
// New node was added to the scene, add it to our refs
if (code == NOTIFY_NODE_CREATED)
{
plMaxNode *node = (plMaxNode*)info->callParam;
// Add a ref to the node and set it to dirty
inst->IAddRef(node);
node->SetDirty(plMaxNodeBase::kAllDirty, true);
inst->ISetDirty();
}
}
void SceneWatcher::ISetDirty()
{
fDirty = true;
}
#include "../MaxComponent/plMiscComponents.h"
#include "../MaxExport/plExportErrorMsg.h"
#include "../MaxExport/plExportProgressBar.h"
#include "../MaxComponent/plResponderComponent.h" // Just need the CID
void SceneWatcher::IGetLogicDependents(plMaxNode *node, NodeSet& nodes)
{
int attached = node->NumAttachedComponents();
for (int i = 0; i < attached; i++)
{
plComponentBase *comp = node->GetAttachedComponent(i);
/*
if (comp->ClassID() == ACTIVATOR_CID)
{
plMaxNodeBase *activatorNode = comp->GetINode();
int numResponders = activatorNode->NumAttachedComponents(true);
for (int i = 0; i < numResponders; i++)
{
plComponentBase *responderComp = activatorNode->GetAttachedComponent(i, true);
if (responderComp->ClassID() == RESPONDER_CID)
{
for (int j = 0; j < responderComp->NumTargets(); j++)
{
plMaxNode *targ = (plMaxNode*)responderComp->GetTarget(j);
if (targ && nodes.find(targ) == nodes.end())
{
nodes.insert(targ);
IGetLogicDependents(targ, nodes);
}
}
}
}
}
else
*/
if (comp->ClassID() == RESPONDER_CID)
{
int activatorCnt = ResponderGetActivatorCount(comp);
for (int i = 0; i < activatorCnt; i++)
{
plComponentBase *activator = ResponderGetActivator(comp, i);
for (int j = 0; j < activator->NumTargets(); j++)
{
plMaxNode *targ = (plMaxNode*)activator->GetTarget(j);
if (targ && nodes.find(targ) == nodes.end())
{
nodes.insert(targ);
IGetLogicDependents(targ, nodes);
}
}
}
}
}
}
void SceneWatcher::IGetDependents(plMaxNode *node, NodeSet& nodes)
{
NodeSet dependents;
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
if (comp->ClassID() == ROOM_CID || comp->ClassID() == PAGEINFO_CID)
return;
for (int i = 0; i < comp->NumTargets(); i++)
{
plMaxNode *targ = (plMaxNode*)comp->GetTarget(i);
if (targ)
{
dependents.insert(targ);
IGetLogicDependents(targ, dependents);
}
}
}
else
{
dependents.insert(node);
IGetLogicDependents(node, dependents);
}
// Bug in VC++?
// nodes.insert(dependents.begin(), dependents.end());
for (NodeSet::iterator i = dependents.begin(); i != dependents.end(); i++)
nodes.insert(*i);
/*==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 <http://www.gnu.org/licenses/>.
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 "SceneWatcher.h"
#include "../MaxMain/plMaxNode.h"
#include "../MaxComponent/plComponent.h"
#include "../MaxMain/plPlasmaRefMsgs.h"
#include "../pnKeyedObject/plKey.h"
SceneWatcher::SceneWatcher() : fDirty(false)
{
RegisterNotification(INotify, this, NOTIFY_NODE_CREATED);
IAddNodeRecur((plMaxNode*)GetCOREInterface()->GetRootNode());
}
SceneWatcher::~SceneWatcher()
{
DeleteAllRefsFromMe();
UnRegisterNotification(INotify, this, NOTIFY_NODE_CREATED);
}
int SceneWatcher::NumRefs()
{
return fNodes.size();
}
RefTargetHandle SceneWatcher::GetReference(int i)
{
if (i < fNodes.size())
return fNodes[i];
hsAssert(0, "Index out of range");
return nil;
}
void SceneWatcher::SetReference(int i, RefTargetHandle rtarg)
{
if (i < fNodes.size())
fNodes[i] = (plMaxNode*)rtarg;
else
hsAssert(0, "Index out of range");
}
//
// Something in the scene has changed.
//
RefResult SceneWatcher::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message)
{
plMaxNode *node = (plMaxNode *)hTarget;
#ifdef HS_DEBUGGING
char *tmp = node->GetName();
#endif
if (message == REFMSG_CHANGE)
{
// If the message is from a component, and was not generated locally (ie.
// it came from a ref parameter), ignore it. There is no way to tell if
// one of these messages is an actual change to the component or just a
// change to the referenced object. We'll catch the real changes with
// REFMSG_USER_COMP_REF_CHANGED below.
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
if (!comp->IsCurMsgLocal())
return REF_SUCCEED;
}
// If this is a static light, ignore it
Object *obj = node->GetObjectRef();
if (obj && obj->SuperClassID() == LIGHT_CLASS_ID && !node->GetRunTimeLight())
return REF_SUCCEED;
node->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
else if (message == REFMSG_TARGET_DELETED)
{
// If the deleted node was a component, dirty everyone it was attached to
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
for (UInt32 i = 0; i < comp->NumTargets(); i++)
{
if (comp->GetTarget(i))
comp->GetTarget(i)->SetDirty(plMaxNode::kGeomDirty, true);
}
}
fDeleted.push_back(node->GetKey());
IRemoveRef(node);
ISetDirty();
}
else if (message == REFMSG_NODE_MATERIAL_CHANGED ||
message == REFMSG_USER_MAT)
{
if (!node->IsComponent())
{
node->SetDirty(plMaxNode::kMatDirty, true);
ISetDirty();
}
}
// A node was added to the components target list
else if (message == REFMSG_USER_TARGET_ADD)
{
plMaxNode *target = (plMaxNode*)partID;
target->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
// A node was deleted from the components target list
else if (message == REFMSG_USER_TARGET_DELETE)
{
plMaxNode *target = (plMaxNode*)partID;
target->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
// A ref maintained by a component PB changed (not just a propagated message
// from the ref)
else if (message == REFMSG_USER_COMP_REF_CHANGED)
{
node->SetDirty(plMaxNode::kGeomDirty, true);
ISetDirty();
}
return REF_SUCCEED;
}
bool SceneWatcher::AnyDeleted()
{
return !fDeleted.empty();
}
SceneWatcher::KeyList& SceneWatcher::GetDeleted()
{
return fDeleted;
}
const SceneWatcher::NodeList& SceneWatcher::GetWatchNodes()
{
return fNodes;
}
bool SceneWatcher::AnyDirty()
{
return fDirty;
}
void SceneWatcher::GetDirty(NodeSet& dirtyNodes)
{
int size = fNodes.size();
for (int i = 0; i < size; i++)
{
plMaxNode *node = fNodes[i];
#ifdef HS_DEBUGGING
const char *tmp = node ? node->GetName() : nil;
#endif
// If any dirty flags are set, add to dirty list
if (node && node->GetDirty(plMaxNode::kAllDirty))
IGetDependents(node, dirtyNodes);
}
fDirty = false;
}
void SceneWatcher::IAddRef(plMaxNode *node)
{
// Ensure that we don't already ref this node
if (FindRef(node) != -1)
return;
// Make a ref
int size = fNodes.size();
fNodes.resize(size+1);
MakeRefByID(FOREVER, size, node);
}
void SceneWatcher::IRemoveRef(plMaxNode *node)
{
// Delete the reference if it's in our list
int i = FindRef(node);
if (i != -1)
{
// Clear the node data, in case it is undeleted later
// (when it will be invalid)
node->ClearData(nil, nil);
node->SetDirty(plMaxNode::kAllDirty, true);
// We can never really delete this reference because the user may "undo"
// and cause it to come back, which just sets the reference again.
fNodes[i] = nil;
}
}
void SceneWatcher::IAddNodeRecur(plMaxNode *node)
{
IAddRef(node);
// If a node is dirty, make sure to set the dirty flag (since nodes may have
// been dirtied in a previous run but not reconverted yet).
if (node->GetDirty(plMaxNode::kAllDirty))
fDirty = true;
for (int i = 0; i < node->NumberOfChildren(); ++i)
{
plMaxNode *childNode = (plMaxNode*)node->GetChildNode(i);
IAddNodeRecur(childNode);
}
}
void SceneWatcher::INotify(void *param, NotifyInfo *info)
{
SceneWatcher *inst = (SceneWatcher*)param;
int code = info->intcode;
// New node was added to the scene, add it to our refs
if (code == NOTIFY_NODE_CREATED)
{
plMaxNode *node = (plMaxNode*)info->callParam;
// Add a ref to the node and set it to dirty
inst->IAddRef(node);
node->SetDirty(plMaxNodeBase::kAllDirty, true);
inst->ISetDirty();
}
}
void SceneWatcher::ISetDirty()
{
fDirty = true;
}
#include "../MaxComponent/plMiscComponents.h"
#include "../MaxExport/plExportErrorMsg.h"
#include "../MaxExport/plExportProgressBar.h"
#include "../MaxComponent/plResponderComponent.h" // Just need the CID
void SceneWatcher::IGetLogicDependents(plMaxNode *node, NodeSet& nodes)
{
int attached = node->NumAttachedComponents();
for (int i = 0; i < attached; i++)
{
plComponentBase *comp = node->GetAttachedComponent(i);
/*
if (comp->ClassID() == ACTIVATOR_CID)
{
plMaxNodeBase *activatorNode = comp->GetINode();
int numResponders = activatorNode->NumAttachedComponents(true);
for (int i = 0; i < numResponders; i++)
{
plComponentBase *responderComp = activatorNode->GetAttachedComponent(i, true);
if (responderComp->ClassID() == RESPONDER_CID)
{
for (int j = 0; j < responderComp->NumTargets(); j++)
{
plMaxNode *targ = (plMaxNode*)responderComp->GetTarget(j);
if (targ && nodes.find(targ) == nodes.end())
{
nodes.insert(targ);
IGetLogicDependents(targ, nodes);
}
}
}
}
}
else
*/
if (comp->ClassID() == RESPONDER_CID)
{
int activatorCnt = ResponderGetActivatorCount(comp);
for (int i = 0; i < activatorCnt; i++)
{
plComponentBase *activator = ResponderGetActivator(comp, i);
for (int j = 0; j < activator->NumTargets(); j++)
{
plMaxNode *targ = (plMaxNode*)activator->GetTarget(j);
if (targ && nodes.find(targ) == nodes.end())
{
nodes.insert(targ);
IGetLogicDependents(targ, nodes);
}
}
}
}
}
}
void SceneWatcher::IGetDependents(plMaxNode *node, NodeSet& nodes)
{
NodeSet dependents;
if (node->IsComponent())
{
plComponentBase *comp = node->ConvertToComponent();
if (comp->ClassID() == ROOM_CID || comp->ClassID() == PAGEINFO_CID)
return;
for (int i = 0; i < comp->NumTargets(); i++)
{
plMaxNode *targ = (plMaxNode*)comp->GetTarget(i);
if (targ)
{
dependents.insert(targ);
IGetLogicDependents(targ, dependents);
}
}
}
else
{
dependents.insert(node);
IGetLogicDependents(node, dependents);
}
// Bug in VC++?
// nodes.insert(dependents.begin(), dependents.end());
for (NodeSet::iterator i = dependents.begin(); i != dependents.end(); i++)
nodes.insert(*i);
}

View File

@ -1,93 +1,93 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SCENE_WATCHER_H
#define SCENE_WATCHER_H
#include "Max.h"
#include "notify.h"
#include <vector>
#include <set>
#include "../pnKeyedObject/plKey.h"
class plMaxNode;
class SceneWatcher : public ReferenceMaker
{
public:
typedef std::vector<plMaxNode*> NodeList;
typedef std::set<plMaxNode*> NodeSet;
typedef std::vector<plKey> KeyList;
protected:
NodeList fNodes;
KeyList fDeleted;
bool fDirty;
public:
SceneWatcher();
~SceneWatcher();
////////////////////////////////////////////////////////////////////////////
// ReferenceMaker functions
//
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
BOOL IsRealDependency(ReferenceTarget *rtarg) { return FALSE; }
// Get all the nodes we're watching
const NodeList& GetWatchNodes();
// Get all the nodes that need to be reconverted
bool AnyDirty();
void GetDirty(NodeSet& dirtyNodes);
bool AnyDeleted();
KeyList& GetDeleted();
protected:
void IAddRef(plMaxNode *node);
void IRemoveRef(plMaxNode *node);
void IAddNodeRecur(plMaxNode *node);
// Helpers for GetDirtyNodes
void IGetDependents(plMaxNode *node, NodeSet& nodes);
void IGetLogicDependents(plMaxNode *node, NodeSet& nodes);
void ISetDirty();
static void INotify(void *param, NotifyInfo *info);
};
#endif //SCENE_WATCHER_H
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef SCENE_WATCHER_H
#define SCENE_WATCHER_H
#include "Max.h"
#include "notify.h"
#include <vector>
#include <set>
#include "../pnKeyedObject/plKey.h"
class plMaxNode;
class SceneWatcher : public ReferenceMaker
{
public:
typedef std::vector<plMaxNode*> NodeList;
typedef std::set<plMaxNode*> NodeSet;
typedef std::vector<plKey> KeyList;
protected:
NodeList fNodes;
KeyList fDeleted;
bool fDirty;
public:
SceneWatcher();
~SceneWatcher();
////////////////////////////////////////////////////////////////////////////
// ReferenceMaker functions
//
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
PartID& partID, RefMessage message);
int NumRefs();
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
BOOL IsRealDependency(ReferenceTarget *rtarg) { return FALSE; }
// Get all the nodes we're watching
const NodeList& GetWatchNodes();
// Get all the nodes that need to be reconverted
bool AnyDirty();
void GetDirty(NodeSet& dirtyNodes);
bool AnyDeleted();
KeyList& GetDeleted();
protected:
void IAddRef(plMaxNode *node);
void IRemoveRef(plMaxNode *node);
void IAddNodeRecur(plMaxNode *node);
// Helpers for GetDirtyNodes
void IGetDependents(plMaxNode *node, NodeSet& nodes);
void IGetLogicDependents(plMaxNode *node, NodeSet& nodes);
void ISetDirty();
static void INotify(void *param, NotifyInfo *info);
};
#endif //SCENE_WATCHER_H

View File

@ -1,87 +1,87 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "plKeyRefSort.h"
#include "../pnKeyedObject/plKeyImp.h"
#include <algorithm>
std::vector<plKey>* plKeyRefSort::fKeys = nil;
std::vector<plKeyRefSort::KeyRefs> plKeyRefSort::fNumRefs;
int plKeyRefSort::CountRefsRecur(plKey key, std::vector<plKey>& traversedKeys)
{
int numRefs = 0;
if (std::find(traversedKeys.begin(), traversedKeys.end(), key) == traversedKeys.end())
{
traversedKeys.push_back(key);
plKeyImp* iKey = (plKeyImp*)key;
for (int i = 0; i < iKey->GetNumRefs(); i++)
{
plKey refKey = iKey->GetRef(i);
if (std::find(fKeys->begin(), fKeys->end(), refKey) != fKeys->end())
numRefs++;
numRefs += CountRefsRecur(refKey, traversedKeys);
}
}
return numRefs;
}
class RefComp
{
public:
bool operator() (plKey key1, plKey key2) const
{
std::vector<plKeyRefSort::KeyRefs>::iterator it1 = std::find(plKeyRefSort::fNumRefs.begin(), plKeyRefSort::fNumRefs.end(), key1);
std::vector<plKeyRefSort::KeyRefs>::iterator it2 = std::find(plKeyRefSort::fNumRefs.begin(), plKeyRefSort::fNumRefs.end(), key2);
return ((*it1).fNumRefs < (*it2).fNumRefs);
}
};
void plKeyRefSort::Sort(std::vector<plKey>* keys)
{
fKeys = keys;
int numKeys = keys->size();
fNumRefs.resize(numKeys);
int i;
for (i = 0; i < numKeys; i++)
{
plKey curKey = (*keys)[i];
std::vector<plKey> traversedKeys;
int numRefs = CountRefsRecur(curKey, traversedKeys);
fNumRefs[i] = KeyRefs(curKey, numRefs);
}
std::sort(fKeys->begin(), fKeys->end(), RefComp());
/*==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 <http://www.gnu.org/licenses/>.
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 "plKeyRefSort.h"
#include "../pnKeyedObject/plKeyImp.h"
#include <algorithm>
std::vector<plKey>* plKeyRefSort::fKeys = nil;
std::vector<plKeyRefSort::KeyRefs> plKeyRefSort::fNumRefs;
int plKeyRefSort::CountRefsRecur(plKey key, std::vector<plKey>& traversedKeys)
{
int numRefs = 0;
if (std::find(traversedKeys.begin(), traversedKeys.end(), key) == traversedKeys.end())
{
traversedKeys.push_back(key);
plKeyImp* iKey = (plKeyImp*)key;
for (int i = 0; i < iKey->GetNumRefs(); i++)
{
plKey refKey = iKey->GetRef(i);
if (std::find(fKeys->begin(), fKeys->end(), refKey) != fKeys->end())
numRefs++;
numRefs += CountRefsRecur(refKey, traversedKeys);
}
}
return numRefs;
}
class RefComp
{
public:
bool operator() (plKey key1, plKey key2) const
{
std::vector<plKeyRefSort::KeyRefs>::iterator it1 = std::find(plKeyRefSort::fNumRefs.begin(), plKeyRefSort::fNumRefs.end(), key1);
std::vector<plKeyRefSort::KeyRefs>::iterator it2 = std::find(plKeyRefSort::fNumRefs.begin(), plKeyRefSort::fNumRefs.end(), key2);
return ((*it1).fNumRefs < (*it2).fNumRefs);
}
};
void plKeyRefSort::Sort(std::vector<plKey>* keys)
{
fKeys = keys;
int numKeys = keys->size();
fNumRefs.resize(numKeys);
int i;
for (i = 0; i < numKeys; i++)
{
plKey curKey = (*keys)[i];
std::vector<plKey> traversedKeys;
int numRefs = CountRefsRecur(curKey, traversedKeys);
fNumRefs[i] = KeyRefs(curKey, numRefs);
}
std::sort(fKeys->begin(), fKeys->end(), RefComp());
}

View File

@ -1,59 +1,59 @@
/*==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 <http://www.gnu.org/licenses/>.
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 <vector>
#include "../pnKeyedObject/plKey.h"
// A really crappy sort of a list of keys from the most referenced key to the least.
// This allows you to write out and read in the keys without having to worry about
// one referencing another that isn't loaded yet (ie, in the SceneViewer)
class plKeyRefSort
{
protected:
class KeyRefs
{
public:
plKey fKey;
int fNumRefs;
KeyRefs() : fKey(nil), fNumRefs(-1) {}
KeyRefs(plKey key, int numRefs) : fKey(key), fNumRefs(numRefs) {}
hsBool operator== (const plKey key)
{
return (fKey == key);
}
};
static std::vector<plKey>* fKeys;
static std::vector<KeyRefs> fNumRefs;
friend class RefComp;
static int CountRefsRecur(plKey key, std::vector<plKey>& traversedKeys);
public:
static void Sort(std::vector<plKey>* keys);
};
/*==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 <http://www.gnu.org/licenses/>.
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 <vector>
#include "../pnKeyedObject/plKey.h"
// A really crappy sort of a list of keys from the most referenced key to the least.
// This allows you to write out and read in the keys without having to worry about
// one referencing another that isn't loaded yet (ie, in the SceneViewer)
class plKeyRefSort
{
protected:
class KeyRefs
{
public:
plKey fKey;
int fNumRefs;
KeyRefs() : fKey(nil), fNumRefs(-1) {}
KeyRefs(plKey key, int numRefs) : fKey(key), fNumRefs(numRefs) {}
hsBool operator== (const plKey key)
{
return (fKey == key);
}
};
static std::vector<plKey>* fKeys;
static std::vector<KeyRefs> fNumRefs;
friend class RefComp;
static int CountRefsRecur(plKey key, std::vector<plKey>& traversedKeys);
public:
static void Sort(std::vector<plKey>* keys);
};

View File

@ -1,277 +1,277 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "plMaxFileData.h"
#include "hsUtils.h"
#include "max.h"
#include "notify.h"
#include "tvnode.h"
#define PLASMA_FILE_DATA_CID Class_ID(0x255a700a, 0x285279dc)
// MyControl is derived from StdControl, but has no controller functionality. It simply has some
// membervariables and saves these by Load and Save.
// EditTrackParams and TrackParamsType are responsible for displaying a user interface (RightClick->Properties)
// on the controler. With these functions you can avoid it, having an interface !
// As you can see, most of these methods are stubbed. Only Load and Save are implemented
// and of course the methods, to access the membervariables.
class plMaxFileDataControl : public StdControl
{
public:
SYSTEMTIME fCodeBuildTime;
char fBranch[128];
plMaxFileDataControl()
{
memset(&fCodeBuildTime, 0, sizeof(SYSTEMTIME));
memset(&fBranch, 0, sizeof(fBranch));
}
// Animatable
virtual void EditTrackParams(TimeValue t, ParamDimensionBase *dim,TCHAR *pname,HWND hParent, IObjParam *ip, DWORD flags){};
int TrackParamsType() { return TRACKPARAMS_WHOLE; }
virtual void DeleteThis() { delete this; }
// ReferenceMaker
virtual RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID,RefMessage message)
{return REF_DONTCARE;}
Class_ID ClassID() { return PLASMA_FILE_DATA_CID; }
SClass_ID SuperClassID() { return CTRL_FLOAT_CLASS_ID; }
void GetClassName(TSTR& s) {s = "blah";}
// Control methods
RefTargetHandle Clone(RemapDir& remap) { return TRACKED_NEW plMaxFileDataControl(); }
void Copy(Control *from) {}
virtual BOOL IsReplaceable() { return FALSE; }
// StdControl methods
void GetValueLocalTime(TimeValue t, void *val, Interval &valid, GetSetMethod method=CTRL_ABSOLUTE){}
void SetValueLocalTime(TimeValue t, void *val, int commit, GetSetMethod method) {}
void Extrapolate(Interval range,TimeValue t,void *val,Interval &valid,int type){}
void *CreateTempValue() {return NULL;}
void DeleteTempValue(void *val) {}
void ApplyValue(void *val, void *delta) {}
void MultiplyValue(void *val, float m) {}
// MyControl methods
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
};
#define MAXFILE_DATA_CHUNK 1001
static const UInt8 kVersion = 1;
IOResult plMaxFileDataControl::Load(ILoad *iload)
{
ULONG nb;
IOResult res;
while (IO_OK==(res=iload->OpenChunk()))
{
if (iload->CurChunkID() == MAXFILE_DATA_CHUNK)
{
UInt8 version = 0;
res = iload->Read(&version, sizeof(UInt8), &nb);
res = iload->Read(&fCodeBuildTime, sizeof(SYSTEMTIME), &nb);
int branchLen = 0;
iload->Read(&branchLen, sizeof(int), &nb);
iload->Read(&fBranch, branchLen, &nb);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
IOResult plMaxFileDataControl::Save(ISave *isave)
{
ULONG nb;
isave->BeginChunk(MAXFILE_DATA_CHUNK);
isave->Write(&kVersion, sizeof(kVersion), &nb);
isave->Write(&fCodeBuildTime, sizeof(SYSTEMTIME), &nb);
int branchLen = strlen(fBranch)+1;
isave->Write(&branchLen, sizeof(int), &nb);
isave->Write(&fBranch, branchLen, &nb);
isave->EndChunk();
return IO_OK;
}
class MaxFileDataClassDesc : public ClassDesc
{
public:
int IsPublic() { return FALSE; }
void* Create(BOOL loading) { return TRACKED_NEW plMaxFileDataControl; }
const TCHAR* ClassName() { return _T("MaxFileData"); }
SClass_ID SuperClassID() { return CTRL_FLOAT_CLASS_ID; }
Class_ID ClassID() { return PLASMA_FILE_DATA_CID; }
const TCHAR* Category() { return _T(""); }
};
MaxFileDataClassDesc gMaxFileDataClassDesc;
ClassDesc *GetMaxFileDataDesc() { return &gMaxFileDataClassDesc; }
// This functions searches for Trackviewnode and the Controller and creates one, if none is present.
plMaxFileDataControl *GetMaxFileData(bool& created)
{
plMaxFileDataControl *pCtrl = NULL;
ITrackViewNode *tvNode = NULL;
ITrackViewNode *tvRoot = GetCOREInterface()->GetTrackViewRootNode();
int i = tvRoot->FindItem(PLASMA_FILE_DATA_CID);
if (i < 0)
{
created = true;
tvNode = CreateITrackViewNode();
// This method adds the Node with the specific Title (e.g. "My Settings")
tvRoot->AddNode(tvNode, "Plasma Globals", PLASMA_FILE_DATA_CID);
pCtrl = (plMaxFileDataControl*)CreateInstance(CTRL_FLOAT_CLASS_ID, PLASMA_FILE_DATA_CID);
TSTR s;
pCtrl->GetClassName(s);
// This adds the controller
tvNode->AddController(pCtrl, s, PLASMA_FILE_DATA_CID);
tvNode->HideChildren(TRUE);
}
else
{
created = false;
tvNode = tvRoot->GetNode(i);
pCtrl = (plMaxFileDataControl*)tvNode->GetController(PLASMA_FILE_DATA_CID);
}
return pCtrl;
}
static SYSTEMTIME gThisCodeBuildTime;
static char gThisBranch[128];
static void PrintTime(SYSTEMTIME& time, char* buf)
{
sprintf(buf, "%d/%d/%d %d:%02d %s", time.wMonth, time.wDay, time.wYear,
(time.wHour <= 12) ? time.wHour : time.wHour-12,
time.wMinute,
(time.wHour < 12 || time.wHour == 24) ? "AM" : "PM");
}
static void NotifyProc(void *param, NotifyInfo *info)
{
if (info->intcode == NOTIFY_FILE_POST_OPEN)
{
bool created;
plMaxFileDataControl* data = GetMaxFileData(created);
if (!created)
{
FILETIME fileTime, pluginTime;
SystemTimeToFileTime(&gThisCodeBuildTime, &pluginTime);
SystemTimeToFileTime(&data->fCodeBuildTime, &fileTime);
if (CompareFileTime(&fileTime, &pluginTime) > 0)
{
if (hsMessageBox_SuppressPrompts)
return;
char buf[1024];
strcpy(buf, "This file was last saved with plugins stamped:\n\n");
char timeBuf[128];
PrintTime(data->fCodeBuildTime, timeBuf);
strcat(buf, timeBuf);
strcat(buf, "\n");
strcat(buf, data->fBranch);
strcat(buf, "\n\nThese plugins are stamped:\n\n");
PrintTime(gThisCodeBuildTime, timeBuf);
strcat(buf, timeBuf);
strcat(buf, "\n");
strcat(buf, gThisBranch);
strcat(buf,
"\n\nNew features may have been added to the newer plugins,\n"
"so saving this file could cause data to be lost.");
MessageBox(GetCOREInterface()->GetMAXHWnd(), buf, "Plugin Warning", MB_OK | MB_ICONEXCLAMATION);
}
}
strcpy(data->fBranch, gThisBranch);
memcpy(&data->fCodeBuildTime, &gThisCodeBuildTime, sizeof(SYSTEMTIME));
}
}
static void IGetString(int resID, char *destBuffer, int size)
{
HRSRC rsrc = ::FindResource(hInstance, MAKEINTRESOURCE(resID), RT_RCDATA);
if (rsrc != NULL)
{
HGLOBAL handle = ::LoadResource(hInstance, rsrc);
if (handle != NULL)
{
char* str = (char*)::LockResource(handle);
strncpy(destBuffer, str, size);
UnlockResource(handle);
}
}
}
void InitMaxFileData()
{
memset(&gThisCodeBuildTime, 0, sizeof(SYSTEMTIME));
// Date
char buf[128];
IGetString(1000, buf, sizeof(buf) - 1);
sscanf(buf, "%hu/%hu/%hu", &gThisCodeBuildTime.wMonth, &gThisCodeBuildTime.wDay, &gThisCodeBuildTime.wYear);
// Time
IGetString(1001, buf, sizeof(buf) - 1);
sscanf(buf, "%hu:%hu", &gThisCodeBuildTime.wHour, &gThisCodeBuildTime.wMinute);
if (strstr(buf, "PM") != nil)
{
gThisCodeBuildTime.wHour += 12;
}
IGetString(1002, gThisBranch, sizeof(gThisBranch) - 1);
RegisterNotification(NotifyProc, 0, NOTIFY_FILE_POST_OPEN);
}
/*==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 <http://www.gnu.org/licenses/>.
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 "plMaxFileData.h"
#include "hsUtils.h"
#include "max.h"
#include "notify.h"
#include "tvnode.h"
#define PLASMA_FILE_DATA_CID Class_ID(0x255a700a, 0x285279dc)
// MyControl is derived from StdControl, but has no controller functionality. It simply has some
// membervariables and saves these by Load and Save.
// EditTrackParams and TrackParamsType are responsible for displaying a user interface (RightClick->Properties)
// on the controler. With these functions you can avoid it, having an interface !
// As you can see, most of these methods are stubbed. Only Load and Save are implemented
// and of course the methods, to access the membervariables.
class plMaxFileDataControl : public StdControl
{
public:
SYSTEMTIME fCodeBuildTime;
char fBranch[128];
plMaxFileDataControl()
{
memset(&fCodeBuildTime, 0, sizeof(SYSTEMTIME));
memset(&fBranch, 0, sizeof(fBranch));
}
// Animatable
virtual void EditTrackParams(TimeValue t, ParamDimensionBase *dim,TCHAR *pname,HWND hParent, IObjParam *ip, DWORD flags){};
int TrackParamsType() { return TRACKPARAMS_WHOLE; }
virtual void DeleteThis() { delete this; }
// ReferenceMaker
virtual RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID,RefMessage message)
{return REF_DONTCARE;}
Class_ID ClassID() { return PLASMA_FILE_DATA_CID; }
SClass_ID SuperClassID() { return CTRL_FLOAT_CLASS_ID; }
void GetClassName(TSTR& s) {s = "blah";}
// Control methods
RefTargetHandle Clone(RemapDir& remap) { return TRACKED_NEW plMaxFileDataControl(); }
void Copy(Control *from) {}
virtual BOOL IsReplaceable() { return FALSE; }
// StdControl methods
void GetValueLocalTime(TimeValue t, void *val, Interval &valid, GetSetMethod method=CTRL_ABSOLUTE){}
void SetValueLocalTime(TimeValue t, void *val, int commit, GetSetMethod method) {}
void Extrapolate(Interval range,TimeValue t,void *val,Interval &valid,int type){}
void *CreateTempValue() {return NULL;}
void DeleteTempValue(void *val) {}
void ApplyValue(void *val, void *delta) {}
void MultiplyValue(void *val, float m) {}
// MyControl methods
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
};
#define MAXFILE_DATA_CHUNK 1001
static const UInt8 kVersion = 1;
IOResult plMaxFileDataControl::Load(ILoad *iload)
{
ULONG nb;
IOResult res;
while (IO_OK==(res=iload->OpenChunk()))
{
if (iload->CurChunkID() == MAXFILE_DATA_CHUNK)
{
UInt8 version = 0;
res = iload->Read(&version, sizeof(UInt8), &nb);
res = iload->Read(&fCodeBuildTime, sizeof(SYSTEMTIME), &nb);
int branchLen = 0;
iload->Read(&branchLen, sizeof(int), &nb);
iload->Read(&fBranch, branchLen, &nb);
}
iload->CloseChunk();
if (res != IO_OK)
return res;
}
return IO_OK;
}
IOResult plMaxFileDataControl::Save(ISave *isave)
{
ULONG nb;
isave->BeginChunk(MAXFILE_DATA_CHUNK);
isave->Write(&kVersion, sizeof(kVersion), &nb);
isave->Write(&fCodeBuildTime, sizeof(SYSTEMTIME), &nb);
int branchLen = strlen(fBranch)+1;
isave->Write(&branchLen, sizeof(int), &nb);
isave->Write(&fBranch, branchLen, &nb);
isave->EndChunk();
return IO_OK;
}
class MaxFileDataClassDesc : public ClassDesc
{
public:
int IsPublic() { return FALSE; }
void* Create(BOOL loading) { return TRACKED_NEW plMaxFileDataControl; }
const TCHAR* ClassName() { return _T("MaxFileData"); }
SClass_ID SuperClassID() { return CTRL_FLOAT_CLASS_ID; }
Class_ID ClassID() { return PLASMA_FILE_DATA_CID; }
const TCHAR* Category() { return _T(""); }
};
MaxFileDataClassDesc gMaxFileDataClassDesc;
ClassDesc *GetMaxFileDataDesc() { return &gMaxFileDataClassDesc; }
// This functions searches for Trackviewnode and the Controller and creates one, if none is present.
plMaxFileDataControl *GetMaxFileData(bool& created)
{
plMaxFileDataControl *pCtrl = NULL;
ITrackViewNode *tvNode = NULL;
ITrackViewNode *tvRoot = GetCOREInterface()->GetTrackViewRootNode();
int i = tvRoot->FindItem(PLASMA_FILE_DATA_CID);
if (i < 0)
{
created = true;
tvNode = CreateITrackViewNode();
// This method adds the Node with the specific Title (e.g. "My Settings")
tvRoot->AddNode(tvNode, "Plasma Globals", PLASMA_FILE_DATA_CID);
pCtrl = (plMaxFileDataControl*)CreateInstance(CTRL_FLOAT_CLASS_ID, PLASMA_FILE_DATA_CID);
TSTR s;
pCtrl->GetClassName(s);
// This adds the controller
tvNode->AddController(pCtrl, s, PLASMA_FILE_DATA_CID);
tvNode->HideChildren(TRUE);
}
else
{
created = false;
tvNode = tvRoot->GetNode(i);
pCtrl = (plMaxFileDataControl*)tvNode->GetController(PLASMA_FILE_DATA_CID);
}
return pCtrl;
}
static SYSTEMTIME gThisCodeBuildTime;
static char gThisBranch[128];
static void PrintTime(SYSTEMTIME& time, char* buf)
{
sprintf(buf, "%d/%d/%d %d:%02d %s", time.wMonth, time.wDay, time.wYear,
(time.wHour <= 12) ? time.wHour : time.wHour-12,
time.wMinute,
(time.wHour < 12 || time.wHour == 24) ? "AM" : "PM");
}
static void NotifyProc(void *param, NotifyInfo *info)
{
if (info->intcode == NOTIFY_FILE_POST_OPEN)
{
bool created;
plMaxFileDataControl* data = GetMaxFileData(created);
if (!created)
{
FILETIME fileTime, pluginTime;
SystemTimeToFileTime(&gThisCodeBuildTime, &pluginTime);
SystemTimeToFileTime(&data->fCodeBuildTime, &fileTime);
if (CompareFileTime(&fileTime, &pluginTime) > 0)
{
if (hsMessageBox_SuppressPrompts)
return;
char buf[1024];
strcpy(buf, "This file was last saved with plugins stamped:\n\n");
char timeBuf[128];
PrintTime(data->fCodeBuildTime, timeBuf);
strcat(buf, timeBuf);
strcat(buf, "\n");
strcat(buf, data->fBranch);
strcat(buf, "\n\nThese plugins are stamped:\n\n");
PrintTime(gThisCodeBuildTime, timeBuf);
strcat(buf, timeBuf);
strcat(buf, "\n");
strcat(buf, gThisBranch);
strcat(buf,
"\n\nNew features may have been added to the newer plugins,\n"
"so saving this file could cause data to be lost.");
MessageBox(GetCOREInterface()->GetMAXHWnd(), buf, "Plugin Warning", MB_OK | MB_ICONEXCLAMATION);
}
}
strcpy(data->fBranch, gThisBranch);
memcpy(&data->fCodeBuildTime, &gThisCodeBuildTime, sizeof(SYSTEMTIME));
}
}
static void IGetString(int resID, char *destBuffer, int size)
{
HRSRC rsrc = ::FindResource(hInstance, MAKEINTRESOURCE(resID), RT_RCDATA);
if (rsrc != NULL)
{
HGLOBAL handle = ::LoadResource(hInstance, rsrc);
if (handle != NULL)
{
char* str = (char*)::LockResource(handle);
strncpy(destBuffer, str, size);
UnlockResource(handle);
}
}
}
void InitMaxFileData()
{
memset(&gThisCodeBuildTime, 0, sizeof(SYSTEMTIME));
// Date
char buf[128];
IGetString(1000, buf, sizeof(buf) - 1);
sscanf(buf, "%hu/%hu/%hu", &gThisCodeBuildTime.wMonth, &gThisCodeBuildTime.wDay, &gThisCodeBuildTime.wYear);
// Time
IGetString(1001, buf, sizeof(buf) - 1);
sscanf(buf, "%hu:%hu", &gThisCodeBuildTime.wHour, &gThisCodeBuildTime.wMinute);
if (strstr(buf, "PM") != nil)
{
gThisCodeBuildTime.wHour += 12;
}
IGetString(1002, gThisBranch, sizeof(gThisBranch) - 1);
RegisterNotification(NotifyProc, 0, NOTIFY_FILE_POST_OPEN);
}

View File

@ -1,26 +1,26 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
void InitMaxFileData();
/*==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 <http://www.gnu.org/licenses/>.
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==*/
void InitMaxFileData();

View File

@ -1,51 +1,51 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "plPluginClient.h"
#include "plPluginApp.h"
#include "../pnNetCommon/plNetApp.h"
plClient *plPluginApp::Startup(char *pCmdLine)
{
// Create the client
fClient = new plPluginClient;
// disable networking always
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kDisabled);
// and set local triggers
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kLocalTriggers);
return fClient;
}
void plPluginApp::Shutdown()
{
// Destroy the client
if (fClient)
{
fClient->Shutdown();
fClient = nil;
}
}
/*==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 <http://www.gnu.org/licenses/>.
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 "plPluginClient.h"
#include "plPluginApp.h"
#include "../pnNetCommon/plNetApp.h"
plClient *plPluginApp::Startup(char *pCmdLine)
{
// Create the client
fClient = new plPluginClient;
// disable networking always
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kDisabled);
// and set local triggers
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kLocalTriggers);
return fClient;
}
void plPluginApp::Shutdown()
{
// Destroy the client
if (fClient)
{
fClient->Shutdown();
fClient = nil;
}
}

View File

@ -1,43 +1,43 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "../../Plasma/Apps/plClient/plApp.h"
class plPluginClient;
//
// Plugin app class. Creates and destroys the client, leaves the resmanager
//
class plPluginApp : public plApp
{
protected:
plPluginClient *fClient;
public:
plPluginApp() : fClient(NULL) {}
virtual plClient *Startup(char *CmdLine);
virtual void Shutdown();
/*==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 <http://www.gnu.org/licenses/>.
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 "../../Plasma/Apps/plClient/plApp.h"
class plPluginClient;
//
// Plugin app class. Creates and destroys the client, leaves the resmanager
//
class plPluginApp : public plApp
{
protected:
plPluginClient *fClient;
public:
plPluginApp() : fClient(NULL) {}
virtual plClient *Startup(char *CmdLine);
virtual void Shutdown();
};

View File

@ -1,291 +1,291 @@
/*==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 <http://www.gnu.org/licenses/>.
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 "plPluginClient.h"
#include "../../../Plasma/PubUtilLib/plPipeline/hsG3DDeviceSelector.h"
#include "hsThread.h"
#include "hsSTLStream.h"
#include "../pnKeyedObject/plUoid.h"
#include "../plResMgr/plUpdatableResManager.h"
#include "../plStatusLog/plStatusLog.h"
// Needed for IEnableProxies
#include "plPipeline.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../pnMessage/plProxyDrawMsg.h"
#include "plgDispatch.h"
#define LOG_SCENEVIWER
static plUpdatableResManager *GetResMgr()
{
return (plUpdatableResManager*)hsgResMgr::ResMgr();
}
plUpdatableClient::plUpdatableClient() : fPipeName(nil), fUpdateSignal(nil), fDataPath(nil), fActive(true), fDirty(false)
{
#ifdef LOG_SCENEVIWER
fLog = plStatusLogMgr::GetInstance().CreateStatusLog(25, "SceneViewer",
plStatusLog::kDontWriteFile | plStatusLog::kFilledBackground | plStatusLog::kAlignToTop);
#endif // LOG_SCENEVIWER
}
plUpdatableClient::~plUpdatableClient()
{
if (fUpdateSignal)
{
delete fUpdateSignal;
fUpdateSignal = nil;
}
if (fLog)
{
delete fLog;
fLog = nil;
}
}
void plUpdatableClient::InitUpdate(const char *semaphoreName, const char *pipeName, const char *dir)
{
fUpdateSignal = TRACKED_NEW hsSemaphore(0, semaphoreName);
fPipeName = pipeName;
fDataPath = dir;
}
hsG3DDeviceModeRecord plUpdatableClient::ILoadDevMode(const char* devModeFile)
{
// Get the usual devmode
hsG3DDeviceModeRecord dmr = plClient::ILoadDevMode(devModeFile);
// Override the mode with a windowed one
hsG3DDeviceMode *mode = (hsG3DDeviceMode*)dmr.GetMode();
mode->SetColorDepth(0);
return hsG3DDeviceModeRecord(*dmr.GetDevice(), *mode);
}
#include "../../../Plasma/Apps/plClient/plClientUpdateFormat.h"
#include "../pnKeyedObject/plKey.h"
void plUpdatableClient::IGetUpdate()
{
// If the semaphore is signaled an update is ready
if (fUpdateSignal && fUpdateSignal->Wait(0))
{
hsNamedPipeStream s;
s.Open(fPipeName, "r");
#ifdef LOG_SCENEVIWER
fLog->Clear();
static int numUpdates = 0;
numUpdates++;
fLog->AddLineF(plStatusLog::kBlue, "SceneViewer Update #%d", numUpdates);
#endif // LOG_SCENEVIWER
UInt8 type = s.ReadByte();
if (type == ClientUpdate::kShutdown)
{
#ifdef LOG_SCENEVIWER
fLog->AddLine("Client shutdown");
#endif // LOG_SCENEVIWER
PostMessage(GetWindowHandle(), WM_SYSCOMMAND, SC_CLOSE, 0);
}
else if (type == ClientUpdate::kUpdate)
{
fDirty = true;
IEnableProxies(false);
int i;
//
// Delete the deleted keys
//
int numDeleted = s.ReadSwap32();
std::vector<plKey*> delKeys;
delKeys.reserve(numDeleted);
for (i = 0; i < numDeleted; i++)
{
plUoid uoid;
uoid.Read(&s);
plKey *key = hsgResMgr::ResMgr()->FindKey(uoid);
hsAssert(key, "Key to delete not found");
if (key)
{
#ifdef LOG_SCENEVIWER
fLog->AddLineF("Remove: %s", key->GetName());
#endif // LOG_SCENEVIWER
GetResMgr()->RemoveObject(key, false);
delKeys.push_back(key);
}
}
GetResMgr()->DelayLoad(true);
//
// Read in the changed spans
//
hsStatusMessage("ReadChangedSpans\n");
GetResMgr()->ReadChangedSpans(&s);
//
// Read in the new keys and objects
//
int numNew = s.ReadSwap32();
for (i = 0; i < numNew; i++)
{
plCreatable *cre = GetResMgr()->ReadCreatable(&s);
hsKeyedObject *ko = hsKeyedObject::ConvertNoRef(cre);
#ifdef LOG_SCENEVIWER
if (ko)
fLog->AddLineF("Read: %s", ko->GetKey()->GetName());
else
fLog->AddLine("Read: (null)");
#endif // LOG_SCENEVIWER
}
GetResMgr()->DelayLoad(false);
// Clear out any objects that were never reloaded (really deleted)
for (i = 0; i < delKeys.size(); i++)
{
plKey *key = delKeys[i];
if (!key->ObjectIsLoaded())
{
#ifdef LOG_SCENEVIWER
fLog->AddLineF("Key deleted: %s", key->GetName());
#endif // LOG_SCENEVIWER
GetResMgr()->RemoveObject(key);
}
}
IEnableProxies(true);
}
s.Close();
}
}
hsBool plUpdatableClient::Init()
{
if (plClient::Init())
{
GetResMgr()->ForceLoadDirectory(fDataPath, true);
// Page in the SceneViewer now that our key is ready
GetResMgr()->PageInSceneViewer();
return true;
}
return false;
}
hsBool plUpdatableClient::MainLoop()
{
IGetUpdate();
if (fActive)
return plClient::MainLoop();
else
{
Sleep(100);
return true;
}
}
#include <direct.h>
hsBool plUpdatableClient::Shutdown()
{
if (fDirty && fDataPath)
{
char oldCwd[MAX_PATH];
getcwd(oldCwd, sizeof(oldCwd));
// Even bigger hack
char tempCrap[MAX_PATH];
strcpy(tempCrap, fDataPath);
tempCrap[strlen(tempCrap)-strlen("dat\\")] = '\0';
chdir(tempCrap);
GetResMgr()->WriteSceneViewer();
chdir(oldCwd);
}
return plClient::Shutdown();
}
void plUpdatableClient::IEnableProxies(bool enable)
{
if (enable)
{
// switch back on any drawable proxies
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kAudibleProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kAudible | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kOccluderProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kOccluder | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kPhysicalProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kPhysical | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kLightProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kLight | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
}
else
{
// notify any and all drawable proxies to stop drawing...
plProxyDrawMsg* nuke = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kAudible
| plProxyDrawMsg::kOccluder
| plProxyDrawMsg::kPhysical
| plProxyDrawMsg::kLight
| plProxyDrawMsg::kDestroy);
plgDispatch::MsgSend(nuke);
}
}
void plUpdatableClient::WindowActivate(bool active)
{
fActive = active;
}
/*==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 <http://www.gnu.org/licenses/>.
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 "plPluginClient.h"
#include "../../../Plasma/PubUtilLib/plPipeline/hsG3DDeviceSelector.h"
#include "hsThread.h"
#include "hsSTLStream.h"
#include "../pnKeyedObject/plUoid.h"
#include "../plResMgr/plUpdatableResManager.h"
#include "../plStatusLog/plStatusLog.h"
// Needed for IEnableProxies
#include "plPipeline.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../pnMessage/plProxyDrawMsg.h"
#include "plgDispatch.h"
#define LOG_SCENEVIWER
static plUpdatableResManager *GetResMgr()
{
return (plUpdatableResManager*)hsgResMgr::ResMgr();
}
plUpdatableClient::plUpdatableClient() : fPipeName(nil), fUpdateSignal(nil), fDataPath(nil), fActive(true), fDirty(false)
{
#ifdef LOG_SCENEVIWER
fLog = plStatusLogMgr::GetInstance().CreateStatusLog(25, "SceneViewer",
plStatusLog::kDontWriteFile | plStatusLog::kFilledBackground | plStatusLog::kAlignToTop);
#endif // LOG_SCENEVIWER
}
plUpdatableClient::~plUpdatableClient()
{
if (fUpdateSignal)
{
delete fUpdateSignal;
fUpdateSignal = nil;
}
if (fLog)
{
delete fLog;
fLog = nil;
}
}
void plUpdatableClient::InitUpdate(const char *semaphoreName, const char *pipeName, const char *dir)
{
fUpdateSignal = TRACKED_NEW hsSemaphore(0, semaphoreName);
fPipeName = pipeName;
fDataPath = dir;
}
hsG3DDeviceModeRecord plUpdatableClient::ILoadDevMode(const char* devModeFile)
{
// Get the usual devmode
hsG3DDeviceModeRecord dmr = plClient::ILoadDevMode(devModeFile);
// Override the mode with a windowed one
hsG3DDeviceMode *mode = (hsG3DDeviceMode*)dmr.GetMode();
mode->SetColorDepth(0);
return hsG3DDeviceModeRecord(*dmr.GetDevice(), *mode);
}
#include "../../../Plasma/Apps/plClient/plClientUpdateFormat.h"
#include "../pnKeyedObject/plKey.h"
void plUpdatableClient::IGetUpdate()
{
// If the semaphore is signaled an update is ready
if (fUpdateSignal && fUpdateSignal->Wait(0))
{
hsNamedPipeStream s;
s.Open(fPipeName, "r");
#ifdef LOG_SCENEVIWER
fLog->Clear();
static int numUpdates = 0;
numUpdates++;
fLog->AddLineF(plStatusLog::kBlue, "SceneViewer Update #%d", numUpdates);
#endif // LOG_SCENEVIWER
UInt8 type = s.ReadByte();
if (type == ClientUpdate::kShutdown)
{
#ifdef LOG_SCENEVIWER
fLog->AddLine("Client shutdown");
#endif // LOG_SCENEVIWER
PostMessage(GetWindowHandle(), WM_SYSCOMMAND, SC_CLOSE, 0);
}
else if (type == ClientUpdate::kUpdate)
{
fDirty = true;
IEnableProxies(false);
int i;
//
// Delete the deleted keys
//
int numDeleted = s.ReadSwap32();
std::vector<plKey*> delKeys;
delKeys.reserve(numDeleted);
for (i = 0; i < numDeleted; i++)
{
plUoid uoid;
uoid.Read(&s);
plKey *key = hsgResMgr::ResMgr()->FindKey(uoid);
hsAssert(key, "Key to delete not found");
if (key)
{
#ifdef LOG_SCENEVIWER
fLog->AddLineF("Remove: %s", key->GetName());
#endif // LOG_SCENEVIWER
GetResMgr()->RemoveObject(key, false);
delKeys.push_back(key);
}
}
GetResMgr()->DelayLoad(true);
//
// Read in the changed spans
//
hsStatusMessage("ReadChangedSpans\n");
GetResMgr()->ReadChangedSpans(&s);
//
// Read in the new keys and objects
//
int numNew = s.ReadSwap32();
for (i = 0; i < numNew; i++)
{
plCreatable *cre = GetResMgr()->ReadCreatable(&s);
hsKeyedObject *ko = hsKeyedObject::ConvertNoRef(cre);
#ifdef LOG_SCENEVIWER
if (ko)
fLog->AddLineF("Read: %s", ko->GetKey()->GetName());
else
fLog->AddLine("Read: (null)");
#endif // LOG_SCENEVIWER
}
GetResMgr()->DelayLoad(false);
// Clear out any objects that were never reloaded (really deleted)
for (i = 0; i < delKeys.size(); i++)
{
plKey *key = delKeys[i];
if (!key->ObjectIsLoaded())
{
#ifdef LOG_SCENEVIWER
fLog->AddLineF("Key deleted: %s", key->GetName());
#endif // LOG_SCENEVIWER
GetResMgr()->RemoveObject(key);
}
}
IEnableProxies(true);
}
s.Close();
}
}
hsBool plUpdatableClient::Init()
{
if (plClient::Init())
{
GetResMgr()->ForceLoadDirectory(fDataPath, true);
// Page in the SceneViewer now that our key is ready
GetResMgr()->PageInSceneViewer();
return true;
}
return false;
}
hsBool plUpdatableClient::MainLoop()
{
IGetUpdate();
if (fActive)
return plClient::MainLoop();
else
{
Sleep(100);
return true;
}
}
#include <direct.h>
hsBool plUpdatableClient::Shutdown()
{
if (fDirty && fDataPath)
{
char oldCwd[MAX_PATH];
getcwd(oldCwd, sizeof(oldCwd));
// Even bigger hack
char tempCrap[MAX_PATH];
strcpy(tempCrap, fDataPath);
tempCrap[strlen(tempCrap)-strlen("dat\\")] = '\0';
chdir(tempCrap);
GetResMgr()->WriteSceneViewer();
chdir(oldCwd);
}
return plClient::Shutdown();
}
void plUpdatableClient::IEnableProxies(bool enable)
{
if (enable)
{
// switch back on any drawable proxies
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kAudibleProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kAudible | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kOccluderProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kOccluder | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kPhysicalProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kPhysical | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kLightProxy)
{
plProxyDrawMsg* msg = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kLight | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
}
else
{
// notify any and all drawable proxies to stop drawing...
plProxyDrawMsg* nuke = TRACKED_NEW plProxyDrawMsg(plProxyDrawMsg::kAudible
| plProxyDrawMsg::kOccluder
| plProxyDrawMsg::kPhysical
| plProxyDrawMsg::kLight
| plProxyDrawMsg::kDestroy);
plgDispatch::MsgSend(nuke);
}
}
void plUpdatableClient::WindowActivate(bool active)
{
fActive = active;
}

View File

@ -1,65 +1,65 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef plUpdatableClient_h_inc
#define plUpdatableClient_h_inc
#include "hsTypes.h"
#include "../../Plasma/Apps/plClient/plClient.h"
class hsSemaphore;
class plStatusLog;
class plUpdatableClient : public plClient
{
protected:
hsSemaphore *fUpdateSignal;
const char *fPipeName;
const char *fDataPath;
bool fActive;
bool fDirty;
plStatusLog *fLog;
void IEnableProxies(bool enable);
void IGetUpdate();
public:
plUpdatableClient();
virtual ~plUpdatableClient();
virtual hsG3DDeviceModeRecord ILoadDevMode(const char* devModeFile);
virtual hsBool Init();
virtual hsBool MainLoop();
virtual hsBool Shutdown();
void InitUpdate(const char *semaphoreName, const char *pipeName, const char *dir);
virtual void WindowActivate(bool active);
};
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#ifndef plUpdatableClient_h_inc
#define plUpdatableClient_h_inc
#include "hsTypes.h"
#include "../../Plasma/Apps/plClient/plClient.h"
class hsSemaphore;
class plStatusLog;
class plUpdatableClient : public plClient
{
protected:
hsSemaphore *fUpdateSignal;
const char *fPipeName;
const char *fDataPath;
bool fActive;
bool fDirty;
plStatusLog *fLog;
void IEnableProxies(bool enable);
void IGetUpdate();
public:
plUpdatableClient();
virtual ~plUpdatableClient();
virtual hsG3DDeviceModeRecord ILoadDevMode(const char* devModeFile);
virtual hsBool Init();
virtual hsBool MainLoop();
virtual hsBool Shutdown();
void InitUpdate(const char *semaphoreName, const char *pipeName, const char *dir);
virtual void WindowActivate(bool active);
};
#endif // plUpdatableClient_h_inc