|
|
|
/*==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;
|
|
|
|
}
|