📄 interiorinstance.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "interior/interiorInstance.h"
#include "interior/lightUpdateGrouper.h"
#include "interior/interior.h"
#include "interior/interiorSubObject.h"
#include "interior/pathedInterior.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "core/bitStream.h"
#include "dgl/dgl.h"
#include "dgl/gBitmap.h"
#include "math/mathIO.h"
#include "dgl/materialList.h"
#include "editor/editor.h"
#include "interior/interiorResObjects.h"
#include "game/trigger.h"
#include "sim/simPath.h"
#include "interior/forceField.h"
#include "dgl/materialList.h"
#include "sceneGraph/lightManager.h"
#include "collision/convex.h"
#include "audio/audioDataBlock.h"
#include "core/frameAllocator.h"
#include "sim/netConnection.h"
#include "platform/profiler.h"
//--------------------------------------------------------------------------
//-------------------------------------- Local classes, data, and functions
//
const U32 csgMaxZoneSize = 256;
bool sgScopeBoolArray[256];
class InteriorRenderImage : public SceneRenderImage
{
public:
InteriorRenderImage() : mDetailLevel(0) { }
U32 mDetailLevel;
U32 mBaseZone;
};
ConsoleFunctionGroupBegin(Interiors, "");
#if defined(TORQUE_DEBUG) || defined (INTERNAL_RELEASE)
ConsoleFunction( setInteriorRenderMode, void, 2, 2, "(int modeNum)")
{
S32 mode = dAtoi(argv[1]);
if (mode < 0 || mode > Interior::ShowDetailLevel)
mode = 0;
Interior::smRenderMode = mode;
}
ConsoleFunction( setInteriorFocusedDebug, void, 2, 2, "(bool enable)")
{
if (dAtob(argv[1])) {
Interior::smFocusedDebug = true;
} else {
Interior::smFocusedDebug = false;
}
}
#endif
ConsoleFunction( isPointInside, bool, 2, 4, "(Point3F pos) or (float x, float y, float z)")
{
static bool lastValue = false;
if(!(argc == 2 || argc == 4))
{
Con::errorf(ConsoleLogEntry::General, "cIsPointInside: invalid parameters");
return(lastValue);
}
Point3F pos;
if(argc == 2)
dSscanf(argv[1], "%g %g %g", &pos.x, &pos.y, &pos.z);
else
{
pos.x = dAtof(argv[1]);
pos.y = dAtof(argv[2]);
pos.z = dAtof(argv[3]);
}
RayInfo collision;
if(gClientContainer.castRay(pos, Point3F(pos.x, pos.y, pos.z - 2000.f), InteriorObjectType, &collision))
{
if(collision.face == -1)
Con::errorf(ConsoleLogEntry::General, "cIsPointInside: failed to find hit face on interior");
else
{
InteriorInstance * interior = dynamic_cast<InteriorInstance *>(collision.object);
if(interior)
lastValue = !interior->getDetailLevel(0)->isSurfaceOutsideVisible(collision.face);
else
Con::errorf(ConsoleLogEntry::General, "cIsPointInside: invalid interior on collision");
}
}
return(lastValue);
}
ConsoleFunctionGroupEnd(Interiors);
ConsoleMethod( InteriorInstance, setAlarmMode, void, 3, 3, "(string mode) Mode is 'On' or 'Off'")
{
bool alarm;
if (dStricmp(argv[2], "On") == 0)
alarm = true;
else
alarm = false;
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
object->setAlarmMode(alarm);
}
ConsoleMethod( InteriorInstance, activateLight, void, 3, 3, "(string lightName)")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
const char* pLightName = argv[2];
object->activateLight(pLightName);
}
ConsoleMethod( InteriorInstance, deactivateLight, void, 3, 3, "(string lightName)")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
const char* pLightName = argv[2];
object->deactivateLight(pLightName);
}
ConsoleMethod( InteriorInstance, echoTriggerableLights, void, 2, 2, "List lights usable with activateLight()/deactivateLight().")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
object->echoTriggerableLights();
}
ConsoleMethod( InteriorInstance, magicButton, void, 2, 2, "@deprecated unimplemented")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
object->addChildren();
}
ConsoleMethod( InteriorInstance, setSkinBase, void, 3, 3, "(string basename)")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (object->isClientObject()) {
Con::errorf(ConsoleLogEntry::General, "InteriorInstance: client objects may not receive console commands. Ignored");
return;
}
#endif
object->setSkinBase(argv[2]);
}
ConsoleMethod( InteriorInstance, getNumDetailLevels, S32, 2, 2, "")
{
return(object->getNumDetailLevels());
}
ConsoleMethod( InteriorInstance, setDetailLevel, void, 3, 3, "(int level)")
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
if(object->isServerObject())
{
NetConnection * toServer = NetConnection::getConnectionToServer();
NetConnection * toClient = NetConnection::getLocalClientConnection();
if(!toClient || !toServer)
return;
S32 index = toClient->getGhostIndex(object);
if(index == -1)
return;
InteriorInstance * clientInstance = dynamic_cast<InteriorInstance*>(toServer->resolveGhost(index));
if(clientInstance)
clientInstance->setDetailLevel(dAtoi(argv[2]));
}
else
#endif
object->setDetailLevel(dAtoi(argv[2]));
}
//--------------------------------------------------------------------------
//-------------------------------------- Static functions
//
IMPLEMENT_CO_NETOBJECT_V1(InteriorInstance);
//------------------------------------------------------------------------------
//-------------------------------------- InteriorInstance
//
bool InteriorInstance::smDontRestrictOutside = false;
bool InteriorInstance::smRenderDynamicLights = true;
U32 InteriorInstance::smLightUpdatePeriod = 66; // 66 ms between updates
F32 InteriorInstance::smDetailModification = 1.0f;
InteriorInstance::InteriorInstance()
{
mAlarmState = false;
mDoSimpleDynamicRender = false;
mUseGLLighting = false;
mInteriorFileName = NULL;
mTypeMask = InteriorObjectType | StaticObjectType | StaticRenderedObjectType;
mNetFlags.set(Ghostable | ScopeAlways);
mUpdateGrouper = NULL;
mShowTerrainInside = false;
mSkinBase = StringTable->insert("base");
mAudioProfile = 0;
mAudioEnvironment = 0;
mForcedDetailLevel = -1;
mConvexList = new Convex;
#ifdef TGE_RPGCLIENT2//TGE_RPGClient2
mCRC = 1;
#else
mCRC = 0;
#endif
}
InteriorInstance::~InteriorInstance()
{
U32 i;
for (i = 0; i < mLightInfo.size(); i++)
destructInPlace(&mLightInfo[i]);
for (i = 0; i < mInteriorSubObjects.size(); i++)
{
// DMM: Fix for first-class objects...
for (U32 j = 0; j < mInteriorSubObjects[i].size(); j++)
delete (mInteriorSubObjects[i])[j];
destructInPlace(&mInteriorSubObjects[i]);
}
delete mUpdateGrouper;
delete mConvexList;
mConvexList = NULL;
for (i = 0; i < mVertexColorsNormal.size(); i++)
{
delete mVertexColorsNormal[i];
mVertexColorsNormal[i] = NULL;
}
for (i = 0; i < mVertexColorsAlarm.size(); i++)
{
delete mVertexColorsAlarm[i];
mVertexColorsAlarm[i] = NULL;
}
for (i = 0; i < mMaterialMaps.size(); i++)
{
delete mMaterialMaps[i];
mMaterialMaps[i] = NULL;
}
}
void InteriorInstance::init()
{
// Does nothing for the moment
}
void InteriorInstance::destroy()
{
// Also does nothing for the moment
}
//--------------------------------------------------------------------------
// Inspection
static AudioProfile * saveAudioProfile = 0;
static AudioEnvironment * saveAudioEnvironment = 0;
void InteriorInstance::inspectPreApply()
{
saveAudioProfile = mAudioProfile;
saveAudioEnvironment = mAudioEnvironment;
}
void InteriorInstance::inspectPostApply()
{
if((mAudioProfile != saveAudioProfile) || (mAudioEnvironment != saveAudioEnvironment))
setMaskBits(AudioMask);
// Update the Transform on Editor Apply.
setMaskBits(TransformMask);
}
void InteriorInstance::onStaticModified( const char* slotName )
{
if( (!dStricmp( slotName, "position") || !dStricmp( slotName, "rotation") || !dStricmp( slotName, "scale")) && !mUseGLLighting )
Con::executef( 1, "onNeedRelight" );
if( !dStricmp( slotName, "useGLLighting" ))
setMaskBits(InitMask);
}
//--------------------------------------------------------------------------
//-------------------------------------- Console functionality
//
void InteriorInstance::initPersistFields()
{
Parent::initPersistFields();
addGroup("Media");
addField("interiorFile", TypeFilename, Offset(mInteriorFileName, InteriorInstance));
endGroup("Media");
addGroup("Audio");
addField("audioProfile", TypeAudioProfilePtr, Offset(mAudioProfile, InteriorInstance));
addField("audioEnvironment", TypeAudioEnvironmentPtr, Offset(mAudioEnvironment, InteriorInstance));
endGroup("Audio");
addGroup("Misc");
addField("useGLLighting", TypeBool, Offset(mUseGLLighting, InteriorInstance));
addField("showTerrainInside", TypeBool, Offset(mShowTerrainInside, InteriorInstance));
endGroup("Misc");
}
void InteriorInstance::consoleInit()
{
Con::addVariable("pref::Interior::LightUpdatePeriod", TypeS32, &smLightUpdatePeriod);
Con::addVariable("pref::Interior::ShowEnvironmentMaps", TypeBool, &Interior::smRenderEnvironmentMaps);
Con::addVariable("pref::Interior::DynamicLights", TypeBool, &smRenderDynamicLights);
Con::addVariable("pref::Interior::VertexLighting", TypeBool, &Interior::smUseVertexLighting);
Con::addVariable("pref::Interior::TexturedFog", TypeBool, &Interior::smUseTexturedFog);
Con::addVariable("pref::Interior::lockArrays", TypeBool, &Interior::smLockArrays);
Con::addVariable("pref::Interior::detailAdjust", TypeF32, &InteriorInstance::smDetailModification);
// DEBUG ONLY!!!
#ifdef TORQUE_DEBUG
Con::addVariable("Interior::DontRestrictOutside", TypeBool, &smDontRestrictOutside);
#endif
}
//--------------------------------------------------------------------------
void InteriorInstance::renewOverlays()
{
StringTableEntry baseName = dStricmp(mSkinBase, "base") == 0 ? "blnd" : mSkinBase;
for (U32 i = 0; i < mMaterialMaps.size(); i++)
{
MaterialList* pMatList = mMaterialMaps[i];
for (U32 j = 0; j < pMatList->mMaterialNames.size(); j++)
{
const char* pName = pMatList->mMaterialNames[j];
const U32 len = dStrlen(pName);
if (len < 6)
continue;
const char* possible = pName + (len - 5);
if (dStricmp(".blnd", possible) == 0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -