Browse Source

Stubify MaxFileData

So, yeah, this blows away MaxSceneViewer. We're never going to get around
to fixing that. In exchange for this massive code explosion, you get a
free MaxFileData stub type thing. It keeps all the data just so we don't
blow up Cyan's plugins. This fixes the "Missing Dll" messages people keep
whining about.
Adam Johnson 11 years ago
parent
commit
a4b1c53ea3
  1. 1
      Sources/Tools/CMakeLists.txt
  2. 1
      Sources/Tools/MaxMain/CMakeLists.txt
  3. 12
      Sources/Tools/MaxMain/GlobalUtility.cpp
  4. 4
      Sources/Tools/MaxMain/main.cpp
  5. 158
      Sources/Tools/MaxMain/plMaxFileData.cpp
  6. 24
      Sources/Tools/MaxMain/plMaxMenu.cpp
  7. 35
      Sources/Tools/MaxSceneViewer/CMakeLists.txt
  8. 678
      Sources/Tools/MaxSceneViewer/SceneSync.cpp
  9. 118
      Sources/Tools/MaxSceneViewer/SceneSync.h
  10. 296
      Sources/Tools/MaxSceneViewer/SceneViewer.cpp
  11. 77
      Sources/Tools/MaxSceneViewer/SceneViewer.h
  12. 368
      Sources/Tools/MaxSceneViewer/SceneWatcher.cpp
  13. 109
      Sources/Tools/MaxSceneViewer/SceneWatcher.h
  14. 103
      Sources/Tools/MaxSceneViewer/plKeyRefSort.cpp
  15. 75
      Sources/Tools/MaxSceneViewer/plKeyRefSort.h
  16. 293
      Sources/Tools/MaxSceneViewer/plMaxFileData.cpp
  17. 44
      Sources/Tools/MaxSceneViewer/plMaxFileData.h
  18. 67
      Sources/Tools/MaxSceneViewer/plPluginApp.cpp
  19. 59
      Sources/Tools/MaxSceneViewer/plPluginApp.h
  20. 307
      Sources/Tools/MaxSceneViewer/plPluginClient.cpp
  21. 81
      Sources/Tools/MaxSceneViewer/plPluginClient.h

1
Sources/Tools/CMakeLists.txt

@ -17,5 +17,4 @@ if(3dsm_BUILD_PLUGIN)
add_subdirectory(MaxMain)
add_subdirectory(MaxPlasmaLights)
add_subdirectory(MaxPlasmaMtls)
#add_subdirectory(MaxSceneViewer) # NOTE: Uses Plasma classes that do not exist
endif()

1
Sources/Tools/MaxMain/CMakeLists.txt

@ -62,6 +62,7 @@ set(MaxMain_SOURCES
plGetLocationDlg.cpp
plMaxAccelerators.cpp
plMaxCFGFile.cpp
plMaxFileData.cpp
plMaxMenu.cpp
plMaxMeshExtractor.cpp
plMaxNode.cpp

12
Sources/Tools/MaxMain/GlobalUtility.cpp

@ -52,12 +52,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "GlobalUtility.h"
#include "MaxSceneViewer/SceneSync.h"
#include "MaxComponent/ComponentDummies.h"
#include "plActionTableMgr.h"
#include "plMaxMenu.h"
#include "MaxSceneViewer/plMaxFileData.h"
#include "pfPython/cyPythonInterface.h"
#include "MaxPlasmaMtls/Layers/plPlasmaMAXLayer.h"
@ -204,15 +201,6 @@ DWORD PlasmaMax::Start()
DummyCodeIncludeFuncObjectFlocker();
DummyCodeIncludeFuncGrassShader();
// Register the SceneViewer with Max
#ifdef MAXSCENEVIEWER_ENABLED
SceneSync::Instance();
#endif
#ifdef MAXSCENEVIEWER_ENABLED
InitMaxFileData();
#endif
// Setup the localization mgr
// Dirty hacks are because Cyan sucks...
plFileName pathTemp = plMaxConfig::GetClientPath(false, true);

4
Sources/Tools/MaxMain/main.cpp

@ -123,11 +123,7 @@ __declspec(dllexport) ClassDesc *LibClassDesc(int i)
case 4:
return GetComponentMgrDesc();
case 5:
#ifdef MAXSCENEVIEWER_ENABLED
return GetMaxFileDataDesc();
#else
return 0;
#endif
case 6:
return GetMaxUtilsDesc();
default:

158
Sources/Tools/MaxMain/plMaxFileData.cpp

@ -0,0 +1,158 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.h"
#include "plString.h"
#include <max.h>
#pragma hdrstop
/** \file This file contains a stub implementation for the ClassDescs left behind by
* Cyan's SceneViewer crap. This just keeps new versions of 3ds Max from crashing on
* null ClassDescs returned by the GUP. It also silences that "Dll Missing" dialog that
* everyone evar wants to whine about even though it means absolutely nothing.
*/
#define PLASMA_FILE_DATA_CID Class_ID(0x255a700a, 0x285279dc)
#define MAXFILE_DATA_CHUNK 1001
static const uint8_t kVersion = 1;
class plMaxFileDataControl : public StdControl
{
public:
SYSTEMTIME fCodeBuildTime;
char fBranch[128];
plMaxFileDataControl()
{
memset(&fCodeBuildTime, 0, sizeof(SYSTEMTIME));
memset(&fBranch, 0, arrsize(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 = "DEAD - SceneViewer"; }
// Control methods
RefTargetHandle Clone(RemapDir& remap) { return 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 nullptr; }
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);
};
IOResult plMaxFileDataControl::Load(ILoad *iload)
{
ULONG nb;
IOResult res;
while (IO_OK==(res=iload->OpenChunk()))
{
if (iload->CurChunkID() == MAXFILE_DATA_CHUNK)
{
uint8_t version = 0;
res = iload->Read(&version, sizeof(uint8_t), &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 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; }

24
Sources/Tools/MaxMain/plMaxMenu.cpp

@ -60,7 +60,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plMaxCFGFile.h"
#include "plResCollector.h"
#include "plAgeDescInterface.h"
#include "MaxSceneViewer/SceneViewer.h"
#include "plNodeLock.h"
#include "plResetXform.h"
#include "plTextureSearch.h"
@ -81,7 +80,7 @@ enum
kActionResCollect,
kActionAgeDesc,
kActionCompCopy,
kActionSceneViewer,
kActionSceneViewer, // DEAD. But I don't dare remove it--don't want to break stuff :/
kActionLock,
kActionUnlock,
kActionTexSearch,
@ -201,15 +200,6 @@ bool DoAction(int id)
CopyComponents();
return true;
case kActionSceneViewer:
#ifdef MAXSCENEVIEWER_ENABLED
SceneViewer::Instance().Show();
return true;
#else
hsMessageBox("The SceneViewer has been disabled in this build", "Disabled", 0);
return true;
#endif
case kActionLock:
plNodeLock().Lock();
return true;
@ -420,18 +410,6 @@ void plCreateMenu()
pMenuItem->ActAsSeparator();
pPlasmaMenu->AddItem(pMenuItem);
#ifdef MAXSCENEVIEWER_ENABLED
// Add the SceneViewer to the menu
pMenuItem = GetIMenuItem();
pMenuItem->SetActionItem(pActionTable->GetAction(kActionSceneViewer));
pPlasmaMenu->AddItem(pMenuItem);
#endif
// Add a separator
pMenuItem = GetIMenuItem();
pMenuItem->ActAsSeparator();
pPlasmaMenu->AddItem(pMenuItem);
// Add the Lock Selected to the menu
pMenuItem = GetIMenuItem();
pMenuItem->SetActionItem(pActionTable->GetAction(kActionLock));

35
Sources/Tools/MaxSceneViewer/CMakeLists.txt

@ -1,35 +0,0 @@
include_directories("../")
include_directories("../../Plasma/Apps")
include_directories("../../Plasma/CoreLib")
include_directories("../../Plasma/FeatureLib")
include_directories("../../Plasma/FeatureLib/inc")
include_directories("../../Plasma/NucleusLib")
include_directories("../../Plasma/NucleusLib/inc")
include_directories("../../Plasma/PubUtilLib")
include_directories("../../Plasma/PubUtilLib/inc")
include_directories(${3dsm_INCLUDE_DIR})
set(MaxSceneViewer_HEADERS
plKeyRefSort.h
plMaxFileData.h
plPluginApp.h
plPluginClient.h
SceneSync.h
SceneViewer.h
SceneWatcher.h
)
set(MaxSceneViewer_SOURCES
plKeyRefSort.cpp
plMaxFileData.cpp
plPluginApp.cpp
plPluginClient.cpp
SceneSync.cpp
SceneViewer.cpp
SceneWatcher.cpp
)
add_library(MaxSceneViewer STATIC ${MaxSceneViewer_HEADERS} ${MaxSceneViewer_SOURCES})
source_group("Header Files" FILES ${MaxSceneViewer_HEADERS})
source_group("Source Files" FILES ${MaxSceneViewer_SOURCES})

678
Sources/Tools/MaxSceneViewer/SceneSync.cpp

@ -1,678 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.h"
#include "SceneSync.h"
#include "SceneWatcher.h"
#define MAXPLUGINCODE
#include "pnSceneObject/plSceneObject.h"
#include "MaxMain/plMaxNode.h"
#include "MaxMain/plPluginResManager.h"
#include "MaxConvert/plConvert.h"
#include "MaxConvert/hsMaterialConverter.h"
#include "MaxComponent/plComponent.h"
#include "hsThread.h"
#include "hsSTLStream.h"
#include "plClient/plClientUpdateFormat.h"
#include "plMaxFileData.h"
SceneSync& SceneSync::Instance()
{
static SceneSync theInstance;
return theInstance;
}
SceneSync::SceneSync() : fUpdateSignal(nil), fSceneWatcher(nil), fTimerID(0), fUpdateFreq(-1)
{
// Need to save the current state
RegisterNotification(INotify, 0, NOTIFY_SYSTEM_PRE_RESET);
RegisterNotification(INotify, 0, NOTIFY_SYSTEM_PRE_NEW);
RegisterNotification(INotify, 0, NOTIFY_FILE_PRE_OPEN);
RegisterNotification(INotify, 0, NOTIFY_PRE_EXPORT);
// Need to load the saved state
RegisterNotification(INotify, 0, NOTIFY_FILE_POST_OPEN);
RegisterNotification(INotify, 0, NOTIFY_POST_EXPORT);
RegisterNotification(INotify, 0, NOTIFY_EXPORT_FAILED);
// Need to save the current state and cleanup
RegisterNotification(INotify, 0, NOTIFY_SYSTEM_SHUTDOWN);
}
void SceneSync::IShutdown()
{
UnRegisterNotification(INotify, 0, NOTIFY_SYSTEM_PRE_RESET);
UnRegisterNotification(INotify, 0, NOTIFY_SYSTEM_PRE_NEW);
UnRegisterNotification(INotify, 0, NOTIFY_FILE_PRE_OPEN);
UnRegisterNotification(INotify, 0, NOTIFY_PRE_EXPORT);
UnRegisterNotification(INotify, 0, NOTIFY_FILE_POST_OPEN);
UnRegisterNotification(INotify, 0, NOTIFY_POST_EXPORT);
UnRegisterNotification(INotify, 0, NOTIFY_EXPORT_FAILED);
UnRegisterNotification(INotify, 0, NOTIFY_SYSTEM_SHUTDOWN);
delete fUpdateSignal;
fUpdateSignal = nil;
}
#include <shellapi.h>
#include "../MaxMain/plMaxCFGFile.h"
#include "../MaxExport/plExportErrorMsg.h"
// TEMP
#include <direct.h>
bool SceneSync::CreateClientData()
{
char path[MAX_PATH];
if (!GetOutputDir(path))
return false;
char datPath[MAX_PATH];
sprintf(datPath, "%sdat", path);
// Setup for the convert
plExportErrorMsg msg;
plConvertSettings settings;
settings.fSceneViewer = true;
plConvert::Instance().Init(GetCOREInterface(), &msg, &settings);
// Do the convert
plConvert::Instance().Convert();
// If convert failed, fail too
if (msg.IsBogus())
return false;
// Clear the dirty flags since everything is fresh
IClearDirtyRecur((plMaxNode*)GetCOREInterface()->GetRootNode());
//
// Write the converted data out and page out the objects
//
IDeletePath(path);
CreateDirectory(path, NULL);
CreateDirectory(datPath, NULL);
// TEMP
char oldCWD[MAX_PATH];
getcwd(oldCWD, MAX_PATH);
chdir(path);
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->Write();
// TEMP
chdir(oldCWD);
IWriteNodeMap(path);
// TEMP
hsMaterialConverter::Instance().FreeMaterialCache(path);
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->PageOutConverted();
hsgResMgr::Reset();
return true;
}
bool SceneSync::IsClientRunning()
{
return (fUpdateSignal != nil);
}
void SceneSync::IShutdownClient()
{
hsNamedPipeStream outStream(hsNamedPipeStream::kThrowOnError, 500);
try
{
if (outStream.Open(fPipeName, "w"))
{
// Signal the Client
fUpdateSignal->Signal();
if (outStream.WaitForClientConnect())
outStream.WriteByte(ClientUpdate::kShutdown);
outStream.Close();
}
}
catch (hsNamedPipeStream*)
{
hsAssert(0, "Error writing to pipe");
outStream.Close();
}
}
void SceneSync::SetUpdateFreq(int freq)
{
fUpdateFreq = freq;
// If the client is running, change it's update freq
if (IsClientRunning())
{
// Kill the old timer
if (fTimerID != 0)
{
KillTimer(NULL, fTimerID);
fTimerID = 0;
}
// Create a new timer
if (fUpdateFreq != -1)
fTimerID = SetTimer(NULL, 0, fUpdateFreq, ITimerProc);
}
}
bool SceneSync::BeginClientSync(const char *semaphoreName, const char *pipeName)
{
char path[MAX_PATH];
if (!GetOutputDir(path))
return false;
char datPath[MAX_PATH];
sprintf(datPath, "%sdat", path);
// Load the saved rooms and their keys (but not objects)
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->ForceLoadDirectory(datPath, true/*false*/); // TEMP
// Set the keys in the plMaxNodes. Also, delete Plasma objects for any
// plMaxNodes that can't be found (must have been deleted).
IReadNodeMap(path);
if (!fSceneWatcher)
IStartWatching(true);
if (fUpdateFreq != -1)
fTimerID = SetTimer(NULL, 0, fUpdateFreq, ITimerProc);
// Update();
fUpdateSignal = new hsSemaphore(0, semaphoreName);
fPipeName = pipeName;
return true;
}
void SceneSync::EndClientSync(bool abort)
{
if (fTimerID != 0 || fUpdateSignal)
{
KillTimer(NULL, fTimerID);
fTimerID = 0;
if (!abort)
{
SaveResMgr();
IShutdownClient();
}
else
{
// Delete files so we won't try to run with this possibly corrupted data
char path[MAX_PATH];
if (GetOutputDir(path))
IDeletePath(path);
}
delete fUpdateSignal;
fUpdateSignal = nil;
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->PageOutConverted();
// hsgResMgr::Reset();
}
}
#include "../pnKeyedObject/plKey.h"
void SceneSync::IClearDirtyRecur(plMaxNode *node)
{
node->SetDirty(plMaxNode::kAllDirty, false);
for (int i = 0; i < node->NumberOfChildren(); i++)
IClearDirtyRecur((plMaxNode*)node->GetChildNode(i));
}
void SceneSync::IDeletePath(const char *path)
{
// Remove any files in the dat directory
char datPath[MAX_PATH];
sprintf(datPath, "%sdat\\", path);
hsFolderIterator folder(datPath);
while (folder.NextFile())
{
char file[MAX_PATH];
folder.GetPathAndName(file);
DeleteFile(file);
}
// Remove the dat directory
// RemoveDirectory(datPath);
// Remove any files in the root dir
folder.SetPath(path);
while (folder.NextFile())
{
char file[MAX_PATH];
folder.GetPathAndName(file);
DeleteFile(file);
}
}
bool SceneSync::SaveResMgr()
{
// Get the output directory for the current file
char path[MAX_PATH];
if (!GetOutputDir(path))
return false;
IWriteNodeMap(path);
return true;
}
bool SceneSync::GetOutputDir(char *buf)
{
const char *path = plMaxConfig::GetClientPath();
if (!path)
return false;
const char *file = GetCOREInterface()->GetCurFileName();
if (!file || *file == '\0')
return false;
char filecpy[_MAX_FNAME];
_splitpath(file, nil, nil, filecpy, nil);
strcpy(buf, path);
strcat(buf, "SceneViewer\\");
// Make sure the SceneViewer directory is created (CreateDirectory sucks)
// CreateDirectory(buf, nil);
strcat(buf, filecpy);
strcat(buf, "\\");
return true;
}
bool SceneSync::IStartWatching(bool forceWatch)
{
IStopWatching();
// Ref all the nodes in the scene if:
// a) we are being forced to watch (starting SceneViewer)
// b) there is previously saved data for this scene (we need to keep up to date)
if (forceWatch || CanLoadOldResMgr())
{
fSceneWatcher = new SceneWatcher;
}
return true;
}
bool SceneSync::IStopWatching()
{
if (!fSceneWatcher)
return true;
delete fSceneWatcher;
fSceneWatcher = nil;
return true;
}
static const char *kKeysFile = "NodeMap.dat";
bool SceneSync::CanLoadOldResMgr()
{
char path[MAX_PATH];
if (!GetOutputDir(path))
return false;
strcat(path, kKeysFile);
hsUNIXStream s;
if (s.Open(path))
{
s.Close();
return true;
}
return false;
}
static void IGetNodes(std::vector<plMaxNode*>& nodes, plMaxNode *curNode=nil)
{
if (!curNode)
curNode = (plMaxNode*)GetCOREInterface()->GetRootNode();
else
nodes.push_back(curNode);
for (int i = 0; i < curNode->NumberOfChildren(); i++)
{
plMaxNode *childNode = (plMaxNode*)curNode->GetChildNode(i);
if (childNode)
IGetNodes(nodes, childNode);
}
}
////////////////////////////////////////////////////////////////////////////////
// The NodeMap is a mapping from unique node id's to Uoid's.
// It is used to figure out the plKey associated with a particular node, which
// will be needed if the node's data needs to be deleted out of the Plasma scene.
//
bool SceneSync::IWriteNodeMap(const char *dir)
{
char path[MAX_PATH];
strcpy(path, dir);
strcat(path, kKeysFile);
hsUNIXStream s;
if (!s.Open(path, "wb"))
return false;
int numWritten = 0;
s.WriteSwap32(numWritten);
std::vector<plMaxNode*> nodes;
IGetNodes(nodes);
int numNodes = nodes.size();
for (int i = 0; i < numNodes; i++)
{
plMaxNode *node = nodes[i];
if (node->GetKey())
{
s.WriteSwap32(node->GetHandle());
node->GetKey()->GetUoid().Write(&s);
numWritten++;
}
}
s.Rewind();
s.WriteSwap32(numWritten);
s.Close();
return true;
}
#include "../MaxMain/plMaxNodeData.h"
bool SceneSync::IReadNodeMap(const char *dir)
{
char path[MAX_PATH];
strcpy(path, dir);
strcat(path, kKeysFile);
hsUNIXStream s;
if (!s.Open(path, "rb"))
return false;
int numWritten = s.ReadSwap32();
for (int i = 0; i < numWritten; i++)
{
// Read in the node handle and get the actual node
ULONG handle = s.ReadSwap32();
plMaxNode *node = (plMaxNode*)GetCOREInterface()->GetINodeByHandle(handle);
// Read in the Uoid and get the key
plUoid uoid;
uoid.Read(&s);
plKey key = hsgResMgr::ResMgr()->FindKey(uoid);
// A node with that handle wasn't found, it must have been deleted.
// Delete it from the Plasma scene.
if (!node)
{
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->RemoveObject(key);
}
else
{
// Save the node's key in the node data
plMaxNodeData *dat = node->GetMaxNodeData();
// Allocate the node data if it doesn't have any
if (!dat)
{
plMaxNodeData data;
node->SetMaxNodeData(&data);
dat = node->GetMaxNodeData();
}
dat->SetKey(key);
dat->SetSceneObject(plSceneObject::ConvertNoRef(key->GetObjectPtr()));
node->CanConvert();
}
}
s.Close();
return true;
}
#include "plKeyRefSort.h"
bool SceneSync::Update()
{
// If there are no dirty nodes, and nothing was deleted, return now
if (!fSceneWatcher || (!fSceneWatcher->AnyDirty() && !fSceneWatcher->AnyDeleted()))
return false;
std::vector<plUoid> delUoids;
// If any nodes were deleted, remove them from the ResManager
if (fSceneWatcher->AnyDeleted())
{
SceneWatcher::KeyList& deleted = fSceneWatcher->GetDeleted();
for (int i = 0; i < deleted.size(); i++)
{
delUoids.push_back(deleted[i]->GetUoid());
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->RemoveObject(deleted[i]);
}
deleted.clear();
}
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->SaveNewKeys(true);
// If any nodes are dirty, reconvert them
if (fSceneWatcher->AnyDirty())
{
// Go through all the referenced nodes and put all the ones that need to be
// reconverted in a list
SceneWatcher::NodeSet dirtyNodes;
fSceneWatcher->GetDirty(dirtyNodes);
// Delete the SceneObjects for all the dirty nodes, and put them in a list
// that we can send to the converter
hsTArray<plMaxNode*> nodes;
for (SceneWatcher::NodeSet::iterator it = dirtyNodes.begin(); it != dirtyNodes.end(); it++)
{
// If the material is dirty, tell the material converter to release
// it's ref, so it will be recreated.
if ((*it)->GetDirty(plMaxNode::kMatDirty))
hsMaterialConverter::Instance().ClearDoneMaterials(*it);
plKey key = (*it)->GetKey();
if (key)
{
delUoids.push_back(key->GetUoid());
hsAssert( false, "YOU NEED TO FIX ME" );
// hsgResMgr::ResMgr()->RemoveObject(key);
}
nodes.Append(*it);
}
// Convert
plExportErrorMsg msg;
plConvertSettings settings;
settings.fSceneViewer = true;
plConvert::Instance().Init(GetCOREInterface(), &msg, &settings);
bool ret = plConvert::Instance().Convert(nodes);
// REMOVE/FIX (COLIN)
hsMaterialConverter::Instance().FreeMaterialCache(nil);
}
//
// Sort the new keys
//
hsAssert( false, "YOU NEED TO FIX ME" );
// const plUpdatableResManager::KeyList& keys = hsgResMgr::ResMgr()->GetNewKeys();
std::vector<plKey> newKeys;// = keys;
plKeyRefSort::Sort(&newKeys);
#if 0
hsStatusMessage("New Keys (Sorted):\n");
for (int x = 0; x < newKeys.size(); x++)
{
hsStatusMessage(" ");
hsStatusMessage(newKeys[x]->GetName());
hsStatusMessage("\n");
}
#endif
//
// Write out the data to the client
//
hsNamedPipeStream outStream(hsNamedPipeStream::kThrowOnError);
try
{
if (outStream.Open(fPipeName, "w"))
{
// Signal the Client
fUpdateSignal->Signal();
if (outStream.WaitForClientConnect())
{
outStream.WriteByte(ClientUpdate::kUpdate);
int i;
// Write out the deleted Uoids
int numUoids = delUoids.size();
outStream.WriteSwap32(numUoids);
for (i = 0; i < numUoids; i++)
{
delUoids[i].Write(&outStream);
}
hsAssert( false, "NEED TO FIX ME!" );
// hsgResMgr::ResMgr()->WriteChangedSpans(&outStream);
// Write out the new keys (and objects)
int numKeys = newKeys.size();
outStream.WriteSwap32(numKeys);
for (i = 0; i < numKeys; i++)
{
plKey key = newKeys[i];
if (key && key->GetObjectPtr())
hsgResMgr::ResMgr()->WriteCreatable(&outStream, key->GetObjectPtr());
}
}
outStream.Close();
}
}
catch (...)
{
hsAssert(0, "Error writing to pipe");
outStream.Close();
EndClientSync(true);
}
hsAssert( false, "NEED TO FIX ME!" );
// hsgResMgr::ResMgr()->SaveNewKeys(false);
return true;
}
void SceneSync::INotify(void *param, NotifyInfo *info)
{
SceneSync &inst = SceneSync::Instance();
int code = info->intcode;
// Need to save the current state
if (code == NOTIFY_SYSTEM_PRE_RESET ||
code == NOTIFY_SYSTEM_PRE_NEW ||
code == NOTIFY_FILE_PRE_OPEN ||
code == NOTIFY_PRE_EXPORT)
{
inst.IStopWatching();
}
// Need to load the saved state
else if (code == NOTIFY_FILE_POST_OPEN ||
code == NOTIFY_POST_EXPORT ||
code == NOTIFY_EXPORT_FAILED)
{
inst.IStartWatching();
}
// Need to save the current state and cleanup
else if (code == NOTIFY_SYSTEM_SHUTDOWN)
{
inst.SaveResMgr();
inst.IStopWatching();
inst.IShutdown();
}
}
void CALLBACK SceneSync::ITimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
Instance().Update();
}

118
Sources/Tools/MaxSceneViewer/SceneSync.h

@ -1,118 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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

296
Sources/Tools/MaxSceneViewer/SceneViewer.cpp

@ -1,296 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.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 = 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");
}

77
Sources/Tools/MaxSceneViewer/SceneViewer.h

@ -1,77 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.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

368
Sources/Tools/MaxSceneViewer/SceneWatcher.cpp

@ -1,368 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.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_t 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);
}

109
Sources/Tools/MaxSceneViewer/SceneWatcher.h

@ -1,109 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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

103
Sources/Tools/MaxSceneViewer/plKeyRefSort.cpp

@ -1,103 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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());
}

75
Sources/Tools/MaxSceneViewer/plKeyRefSort.h

@ -1,75 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.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) {}
bool 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);
};

293
Sources/Tools/MaxSceneViewer/plMaxFileData.cpp

@ -1,293 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.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 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_t kVersion = 1;
IOResult plMaxFileDataControl::Load(ILoad *iload)
{
ULONG nb;
IOResult res;
while (IO_OK==(res=iload->OpenChunk()))
{
if (iload->CurChunkID() == MAXFILE_DATA_CHUNK)
{
uint8_t version = 0;
res = iload->Read(&version, sizeof(uint8_t), &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 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);
}

44
Sources/Tools/MaxSceneViewer/plMaxFileData.h

@ -1,44 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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();
ClassDesc* GetMaxFileDataDesc();

67
Sources/Tools/MaxSceneViewer/plPluginApp.cpp

@ -1,67 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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;
}
}

59
Sources/Tools/MaxSceneViewer/plPluginApp.h

@ -1,59 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "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();
};

307
Sources/Tools/MaxSceneViewer/plPluginClient.cpp

@ -1,307 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "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 = 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_t 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();
}
}
bool 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;
}
bool plUpdatableClient::MainLoop()
{
IGetUpdate();
if (fActive)
return plClient::MainLoop();
else
{
Sleep(100);
return true;
}
}
#include <direct.h>
bool 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 = new plProxyDrawMsg(plProxyDrawMsg::kAudible | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kOccluderProxy)
{
plProxyDrawMsg* msg = new plProxyDrawMsg(plProxyDrawMsg::kOccluder | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kPhysicalProxy)
{
plProxyDrawMsg* msg = new plProxyDrawMsg(plProxyDrawMsg::kPhysical | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
if (fPipeline->GetDrawableTypeMask() & plDrawableSpans::kLightProxy)
{
plProxyDrawMsg* msg = new plProxyDrawMsg(plProxyDrawMsg::kLight | plProxyDrawMsg::kCreate);
plgDispatch::MsgSend(msg);
}
}
else
{
// notify any and all drawable proxies to stop drawing...
plProxyDrawMsg* nuke = new plProxyDrawMsg(plProxyDrawMsg::kAudible
| plProxyDrawMsg::kOccluder
| plProxyDrawMsg::kPhysical
| plProxyDrawMsg::kLight
| plProxyDrawMsg::kDestroy);
plgDispatch::MsgSend(nuke);
}
}
void plUpdatableClient::WindowActivate(bool active)
{
fActive = active;
}

81
Sources/Tools/MaxSceneViewer/plPluginClient.h

@ -1,81 +0,0 @@
/*==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/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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 "HeadSpin.h"
#include "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 bool Init();
virtual bool MainLoop();
virtual bool Shutdown();
void InitUpdate(const char *semaphoreName, const char *pipeName, const char *dir);
virtual void WindowActivate(bool active);
};
#endif // plUpdatableClient_h_inc
Loading…
Cancel
Save