You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
10 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "GlobalUtility.h"
#include "hsResMgr.h"
#include "plMaxNode.h"
#include "MaxSceneViewer/SceneSync.h"
#include "MaxComponent/ComponentDummies.h"
#include "plActionTableMgr.h"
#include "plMaxMenu.h"
#include "MaxComponent/plComponentBase.h"
#include "MaxSceneViewer/plMaxFileData.h"
#include "pfPython/cyPythonInterface.h"
#include "MaxPlasmaMtls/Layers/plPlasmaMAXLayer.h"
#include "plMaxCFGFile.h"
#include "pfLocalizationMgr/pfLocalizationMgr.h"
extern plActionTableMgr theActionTableMgr;
extern HINSTANCE hInstance;
/*===========================================================================*\
| Class Descriptor
\*===========================================================================*/
static PlasmaMax gPlasmaMax;
class PlasmaMaxClassDesc : public ClassDesc
{
public:
int IsPublic() { return TRUE; }
void* Create(BOOL loading) { return &gPlasmaMax; }
const TCHAR* ClassName() { return _T("PlasmaMax"); }
SClass_ID SuperClassID() { return GUP_CLASS_ID; }
Class_ID ClassID() { return PLASMA_MAX_CLASSID; }
const TCHAR* Category() { return _T(""); }
// ************************* action table
// The following 2 lines are added for action tables and menu work
int NumActionTables() { return theActionTableMgr.NumActionTables(); }
ActionTable* GetActionTable(int i) { return theActionTableMgr.GetActionTable(i); }
};
static PlasmaMaxClassDesc PlasmaMaxCD;
ClassDesc* GetGUPDesc() { return &PlasmaMaxCD; }
//////////////////////////////////////////
// This function is from the console. This dummy version is here so that plNetLinkingMgr will build.
plKey FindSceneObjectByName(const char* name, const char* ageName, char* statusStr, bool subString)
{
return nil;
}
/*===========================================================================*\
| Global Utility interface (start/stop/control)
\*===========================================================================*/
PlasmaMax::PlasmaMax()
{
}
void DoAllRecur(PMaxNodeFunc p, plMaxNode *node)
{
(node->*p)(nil, nil);
for (int i = 0; i < node->NumberOfChildren(); i++)
{
plMaxNode *child = (plMaxNode*)node->GetChildNode(i);
DoAllRecur(p, child);
}
}
//#include "../MaxComponent/plComponentBase.h"
#include "MaxExport/plExportErrorMsg.h"
#include "MaxExport/plExportDlg.h"
static void NotifyProc(void *param, NotifyInfo *info)
{
if (info->intcode == NOTIFY_FILE_POST_OPEN)
{
plMaxNode *pNode = (plMaxNode*)GetCOREInterface()->GetRootNode();
DoAllRecur(&plMaxNode::ClearData, pNode);
}
else if (info->intcode == NOTIFY_SYSTEM_STARTUP)
{
int type;
float scale;
GetMasterUnitInfo(&type, &scale);
if (type != UNITS_FEET || scale != 1.f)
{
hsMessageBoxWithOwner(GetCOREInterface()->GetMAXHWnd(),
"Please set your system units to 1 unit = 1 foot.\n\n"
"Customize -> Units Setup... -> System Unit Setup",
"Plasma Units Error", hsMessageBoxNormal);
}
plExportDlg::Instance().StartAutoExport();
}
}
// Activate and Stay Resident
// The GUPRESULT_KEEP tells MAX that we want to remain loaded in the system
// Check the SDK Help File for other returns, to change the behavior
DWORD PlasmaMax::Start()
{
// Make sure component code isn't thrown away by the linker
DummyCodeIncludeFunc(); //Anim Comps
DummyCodeIncludeFuncActive(); //Activators
DummyCodeIncludeFuncResponder(); //Responders
DummyCodeIncludeFuncAudio(); //Audio Files
DummyCodeIncludeAvatarFunc(); //Avatar Comp
DummyCodeIncludeFuncTypes(); //Type (Portal, StartPoint, etc..)
DummyCodeIncludeFuncMisc(); //Misc (Room, PageInfo, Interesting, etc..)
DummyCodeIncludeFuncPhys(); //Phys Comps
DummyCodeIncludeFuncParticles(); //Particle Comps
DummyCodeIncludeFuncSmooth(); //Smooth Comp
DummyCodeIncludeFuncSeekPoint(); //Avatar SeekPoint Comp
DummyCodeIncludeFuncClickable(); //Clickable Comp
DummyCodeIncludeFuncSingleSht(); //OneShot Comp
DummyCodeIncludeFuncAGComp();
DummyCodeIncludeFuncClickDrag(); //Click-Draggable comp
DummyCodeIncludeFuncInventStuff(); //Inventory Object comp
DummyCodeIncludeFuncVolumeGadget(); // inside/enter/exit phys volume activator
// DummyCodeIncludeFuncActivatorGadget(); // activator activator
DummyCodeIncludeFuncImpactGadget(); // collision activator
DummyCodeIncludeFuncSoftVolume(); // Soft Volumes
DummyCodeIncludeFuncPhysConst(); // Phys Constraints
DummyCodeIncludeFuncCameras(); // new camera code
DummyCodeIncludePythonFileFunc();
DummyCodeIncludeFuncDistrib(); // Geometry distribution functions
DummyCodeIncludeFuncExcludeRegion();
DummyCodeIncludeFuncCluster(); // Geometry clustering functions
DummyCodeIncludeFuncGUI(); // User Interface components
DummyCodeIncludeFuncIgnore(); // Things to ignore completely or partially
DummyCodeIncludeFuncBlow(); // Procedural wind modifier
DummyCodeIncludeFuncWater(); // All things wet.
DummyCodeIncludeFuncLightMap(); // LightMap
DummyCodeIncludeFuncXImposter(); // Like a billboard, but exier.
DummyCodeIncludeFuncRepComp(); // Different representations
DummyCodeIncludeFuncLineFollow(); // Things that follow a line
DummyCodeIncludeFuncMorph(); // Like putty in my hands
DummyCodeIncludeFuncLODFade(); // Alpha blending lod transition
DummyCodeIncludeFuncBehaviors(); // Av Behaviors, like Sitting
DummyCodeIncludeFuncNavigablesRegion();
DummyCodeIncludeFuncTemplate();
DummyCodeIncludeFuncClothing();
DummyCodeIncludeFuncMultistageBeh();
DummyCodeIncludeFuncAnimDetector();
DummyCodeIncludeFuncShadow(); // Components controlling shadow generation.
DummyCodeIncludeFuncFootstepSound();
DummyCodeIncludeFuncFootPrint(); // dynamic decals
DummyCodeIncludFuncNPCSpawn();
DummyCodeIncludeFuncClimbTrigger();
DummyCodeIncludeFuncObjectFlocker();
DummyCodeIncludeFuncGrassShader();
// Register the SceneViewer with Max
#ifdef MAXSCENEVIEWER_ENABLED
SceneSync::Instance();
#endif
plComponentShow::Init();
plCreateMenu();
RegisterNotification(NotifyProc, 0, NOTIFY_FILE_POST_OPEN);
RegisterNotification(NotifyProc, 0, NOTIFY_SYSTEM_STARTUP);
#ifdef MAXSCENEVIEWER_ENABLED
InitMaxFileData();
#endif
// Setup the localization mgr
// Dirty hacks are because Cyan sucks...
const char* pathTemp = plMaxConfig::GetClientPath(false, true);
if (pathTemp == nil)
{
hsMessageBox("PlasmaMAX2.ini is missing or invalid", "Plasma/2.0 Error", hsMessageBoxNormal);
}
else
{
std::string clientPath(pathTemp);
clientPath += "dat";
pfLocalizationMgr::Initialize(clientPath);
}
return GUPRESULT_KEEP;
}
void PlasmaMax::Stop()
{
UnRegisterNotification(NotifyProc, 0, NOTIFY_FILE_POST_OPEN);
pfLocalizationMgr::Shutdown();
PythonInterface::WeAreInShutdown();
PythonInterface::finiPython();
hsgResMgr::Shutdown();
}
#include "plMtlCollector.h"
#ifdef MAXASS_AVAILABLE
#include "../../AssetMan/PublicInterface/AssManBaseTypes.h"
#endif
void TextureSet(Texmap* texmap, int iBmp, UInt64 assetId)
{
plPlasmaMAXLayer* layer = plPlasmaMAXLayer::GetPlasmaMAXLayer(texmap);
if (layer)
{
int numBitmaps = layer->GetNumBitmaps();
#ifdef MAXASS_AVAILABLE
if (iBmp < numBitmaps)
layer->SetBitmapAssetId(jvUniqueId(assetId), iBmp);
#endif
}
}
DWORD PlasmaMax::Control(DWORD parameter)
{
if (parameter == kGetTextures)
{
TexSet texmaps;
plMtlCollector::GetMtls(nil, &texmaps);
std::vector<TexInfo> texInfo;
TexSet::iterator texIt = texmaps.begin();
for (; texIt != texmaps.end(); texIt++)
{
Texmap* texmap = (*texIt);
plPlasmaMAXLayer* layer = plPlasmaMAXLayer::GetPlasmaMAXLayer(texmap);
if (layer)
{
int numBitmaps = layer->GetNumBitmaps();
for (int iBmp = 0; iBmp < numBitmaps; iBmp++)
{
// UPDATE: If someone merges in a material from another AssetMan
// controled scene the texture ID will already be set, when it
// shouldn't be. Because of that, we redo all the texture ID's
// every time.
// - Colin
// if (assetId.IsEmpty())
{
char fileName[MAX_PATH];
if (layer->GetBitmapFileName(fileName, sizeof(fileName), iBmp))
{
int texIdx = texInfo.size();
texInfo.resize(texIdx+1);
texInfo[texIdx].texmap = texmap;
texInfo[texIdx].iBmp = iBmp;
texInfo[texIdx].texName = fileName;
}
}
}
}
}
#ifdef MAXASS_AVAILABLE
jvArray<TexInfo>* textures = TRACKED_NEW jvArray<TexInfo>(texInfo.size());
for (int i = 0; i < texInfo.size(); i++)
(*textures)[i] = texInfo[i];
return DWORD(textures);
#else
return 0;
#endif
}
else if (parameter == kGetTextureSetFunc)
{
return DWORD(&TextureSet);
}
return 0;
}