|
@@ -7,16 +7,25 @@
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "gfx/gfxTransformSaver.h"
|
|
#include "gfx/gfxTransformSaver.h"
|
|
#include "gui/editor/inspector/group.h"
|
|
#include "gui/editor/inspector/group.h"
|
|
|
|
+#include "T3D/gameBase/gameBase.h"
|
|
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1(SubScene);
|
|
IMPLEMENT_CO_NETOBJECT_V1(SubScene);
|
|
|
|
|
|
S32 SubScene::mUnloadTimeoutMs = 5000;
|
|
S32 SubScene::mUnloadTimeoutMs = 5000;
|
|
|
|
|
|
|
|
+IMPLEMENT_CALLBACK(SubScene, onLoaded, void, (), (),
|
|
|
|
+ "@brief Called when a subScene has been loaded and has game mode implications.\n\n");
|
|
|
|
+IMPLEMENT_CALLBACK(SubScene, onUnloaded, void, (), (),
|
|
|
|
+ "@brief Called when a subScene has been unloaded and has game mode implications.\n\n");
|
|
|
|
+
|
|
SubScene::SubScene() :
|
|
SubScene::SubScene() :
|
|
mLevelAssetId(StringTable->EmptyString()),
|
|
mLevelAssetId(StringTable->EmptyString()),
|
|
mGameModesNames(StringTable->EmptyString()),
|
|
mGameModesNames(StringTable->EmptyString()),
|
|
mScopeDistance(-1),
|
|
mScopeDistance(-1),
|
|
mLoaded(false),
|
|
mLoaded(false),
|
|
|
|
+ mFreezeLoading(false),
|
|
|
|
+ mTickPeriodMS(1000),
|
|
|
|
+ mCurrTick(0),
|
|
mGlobalLayer(false)
|
|
mGlobalLayer(false)
|
|
{
|
|
{
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
@@ -33,6 +42,8 @@ bool SubScene::onAdd()
|
|
if (!Parent::onAdd())
|
|
if (!Parent::onAdd())
|
|
return false;
|
|
return false;
|
|
|
|
|
|
|
|
+ setProcessTick(true);
|
|
|
|
+
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -41,6 +52,8 @@ void SubScene::onRemove()
|
|
if (isClientObject())
|
|
if (isClientObject())
|
|
removeFromScene();
|
|
removeFromScene();
|
|
|
|
|
|
|
|
+ unload();
|
|
|
|
+
|
|
Parent::onRemove();
|
|
Parent::onRemove();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -49,10 +62,20 @@ void SubScene::initPersistFields()
|
|
addGroup("SubScene");
|
|
addGroup("SubScene");
|
|
addField("isGlobalLayer", TypeBool, Offset(mGlobalLayer, SubScene), "");
|
|
addField("isGlobalLayer", TypeBool, Offset(mGlobalLayer, SubScene), "");
|
|
INITPERSISTFIELD_LEVELASSET(Level, SubScene, "The level asset to load.");
|
|
INITPERSISTFIELD_LEVELASSET(Level, SubScene, "The level asset to load.");
|
|
- addField("loadIf", TypeCommand, Offset(mLoadIf, SubScene), "evaluation condition (true/false)");
|
|
|
|
addField("gameModes", TypeGameModeList, Offset(mGameModesNames, SubScene), "The game modes that this subscene is associated with.");
|
|
addField("gameModes", TypeGameModeList, Offset(mGameModesNames, SubScene), "The game modes that this subscene is associated with.");
|
|
endGroup("SubScene");
|
|
endGroup("SubScene");
|
|
|
|
|
|
|
|
+ addGroup("LoadingManagement");
|
|
|
|
+ addField("freezeLoading", TypeBool, Offset(mFreezeLoading, SubScene), "If true, will prevent the zone from being changed from it's current loading state.");
|
|
|
|
+ addField("loadIf", TypeCommand, Offset(mLoadIf, SubScene), "evaluation condition (true/false)");
|
|
|
|
+
|
|
|
|
+ addField("tickPeriodMS", TypeS32, Offset(mTickPeriodMS, SubScene), "evaluation rate (ms)");
|
|
|
|
+
|
|
|
|
+ addField("onLoadCommand", TypeCommand, Offset(mOnLoadCommand, SubScene), "The command to execute when the subscene is loaded. Maximum 1023 characters.");
|
|
|
|
+ addField("onUnloadCommand", TypeCommand, Offset(mOnUnloadCommand, SubScene), "The command to execute when subscene is unloaded. Maximum 1023 characters.");
|
|
|
|
+ endGroup("LoadingManagement");
|
|
|
|
+
|
|
|
|
+
|
|
Parent::initPersistFields();
|
|
Parent::initPersistFields();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -139,22 +162,29 @@ void SubScene::inspectPostApply()
|
|
setMaskBits(-1);
|
|
setMaskBits(-1);
|
|
}
|
|
}
|
|
|
|
|
|
-bool SubScene::testBox(const Box3F& testBox)
|
|
|
|
|
|
+bool SubScene::evaluateCondition()
|
|
{
|
|
{
|
|
- if (mGlobalLayer)
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- bool passes = getWorldBox().isOverlapped(testBox);
|
|
|
|
- if (passes && !mLoadIf.isEmpty())
|
|
|
|
|
|
+ if (!mLoadIf.isEmpty())
|
|
{
|
|
{
|
|
//test the mapper plugged in condition line
|
|
//test the mapper plugged in condition line
|
|
String resVar = getIdString() + String(".result");
|
|
String resVar = getIdString() + String(".result");
|
|
Con::setBoolVariable(resVar.c_str(), false);
|
|
Con::setBoolVariable(resVar.c_str(), false);
|
|
String command = resVar + "=" + mLoadIf + ";";
|
|
String command = resVar + "=" + mLoadIf + ";";
|
|
|
|
+
|
|
Con::evaluatef(command.c_str());
|
|
Con::evaluatef(command.c_str());
|
|
- passes = Con::getBoolVariable(resVar.c_str());
|
|
|
|
|
|
+ return Con::getBoolVariable(resVar.c_str());
|
|
}
|
|
}
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
|
|
|
|
+bool SubScene::testBox(const Box3F& testBox)
|
|
|
|
+{
|
|
|
|
+ if (mGlobalLayer)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ bool passes = getWorldBox().isOverlapped(testBox);
|
|
|
|
+ if (passes)
|
|
|
|
+ passes = evaluateCondition();
|
|
return passes;
|
|
return passes;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -187,6 +217,14 @@ void SubScene::write(Stream& stream, U32 tabStop, U32 flags)
|
|
|
|
|
|
void SubScene::processTick(const Move* move)
|
|
void SubScene::processTick(const Move* move)
|
|
{
|
|
{
|
|
|
|
+ mCurrTick += TickMs;
|
|
|
|
+ if (mCurrTick > mTickPeriodMS)
|
|
|
|
+ {
|
|
|
|
+ mCurrTick = 0;
|
|
|
|
+ //re-evaluate
|
|
|
|
+ if (!evaluateCondition())
|
|
|
|
+ unload();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void SubScene::_onFileChanged(const Torque::Path& path)
|
|
void SubScene::_onFileChanged(const Torque::Path& path)
|
|
@@ -201,19 +239,34 @@ void SubScene::_onFileChanged(const Torque::Path& path)
|
|
setMaskBits(U32_MAX);
|
|
setMaskBits(U32_MAX);
|
|
}
|
|
}
|
|
|
|
|
|
-void SubScene::_closeFile(bool removeFileNotify)
|
|
|
|
|
|
+void SubScene::_removeContents(SimGroupIterator set)
|
|
{
|
|
{
|
|
- AssertFatal(isServerObject(), "Trying to close out a subscene file on the client is bad!");
|
|
|
|
-
|
|
|
|
- U32 count = size();
|
|
|
|
-
|
|
|
|
- for (SimSetIterator itr(this); *itr; ++itr)
|
|
|
|
|
|
+ for (SimGroupIterator itr(set); *itr; ++itr)
|
|
{
|
|
{
|
|
- SimObject* child = dynamic_cast<SimObject*>(*itr);
|
|
|
|
|
|
|
|
|
|
+ SimGroup* child = dynamic_cast<SimGroup*>(*itr);
|
|
if (child)
|
|
if (child)
|
|
|
|
+ {
|
|
|
|
+ _removeContents(SimGroupIterator(child));
|
|
|
|
+
|
|
|
|
+ GameBase* asGameBase = dynamic_cast<GameBase*>(child);
|
|
|
|
+ if (asGameBase)
|
|
|
|
+ {
|
|
|
|
+ asGameBase->scriptOnRemove();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Sim::cancelPendingEvents(child);
|
|
|
|
+
|
|
child->safeDeleteObject();
|
|
child->safeDeleteObject();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void SubScene::_closeFile(bool removeFileNotify)
|
|
|
|
+{
|
|
|
|
+ AssertFatal(isServerObject(), "Trying to close out a subscene file on the client is bad!");
|
|
|
|
+
|
|
|
|
+ _removeContents(SimGroupIterator(this));
|
|
|
|
|
|
if (removeFileNotify && mLevelAsset.notNull() && mLevelAsset->getLevelPath() != StringTable->EmptyString())
|
|
if (removeFileNotify && mLevelAsset.notNull() && mLevelAsset->getLevelPath() != StringTable->EmptyString())
|
|
{
|
|
{
|
|
@@ -249,14 +302,24 @@ void SubScene::load()
|
|
if (mLoaded)
|
|
if (mLoaded)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ if (mFreezeLoading)
|
|
|
|
+ return;
|
|
|
|
+
|
|
_loadFile(true);
|
|
_loadFile(true);
|
|
mLoaded = true;
|
|
mLoaded = true;
|
|
|
|
|
|
GameMode::findGameModes(mGameModesNames, &mGameModesList);
|
|
GameMode::findGameModes(mGameModesNames, &mGameModesList);
|
|
|
|
|
|
|
|
+ onLoaded_callback();
|
|
for (U32 i = 0; i < mGameModesList.size(); i++)
|
|
for (U32 i = 0; i < mGameModesList.size(); i++)
|
|
{
|
|
{
|
|
- mGameModesList[i]->onSubsceneLoaded_callback();
|
|
|
|
|
|
+ mGameModesList[i]->onSubsceneLoaded_callback(this);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!mOnLoadCommand.isEmpty())
|
|
|
|
+ {
|
|
|
|
+ String command = "%this = " + String(getIdString()) + "; " + mLoadIf + ";";
|
|
|
|
+ Con::evaluatef(command.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -265,6 +328,9 @@ void SubScene::unload()
|
|
if (!mLoaded)
|
|
if (!mLoaded)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ if (mFreezeLoading)
|
|
|
|
+ return;
|
|
|
|
+
|
|
if (isSelected())
|
|
if (isSelected())
|
|
{
|
|
{
|
|
mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
@@ -273,33 +339,43 @@ void SubScene::unload()
|
|
|
|
|
|
//scan down through our child objects, see if any are marked as selected,
|
|
//scan down through our child objects, see if any are marked as selected,
|
|
//if so, skip unloading and reset the timer
|
|
//if so, skip unloading and reset the timer
|
|
- for (SimSetIterator itr(this); *itr; ++itr)
|
|
|
|
|
|
+ for (SimGroupIterator itr(this); *itr; ++itr)
|
|
{
|
|
{
|
|
SimGroup* childGrp = dynamic_cast<SimGroup*>(*itr);
|
|
SimGroup* childGrp = dynamic_cast<SimGroup*>(*itr);
|
|
- if (childGrp && childGrp->isSelected())
|
|
|
|
|
|
+ if (childGrp)
|
|
{
|
|
{
|
|
- mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
|
|
- return; //if a child is selected, then we don't want to unload
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for (SimSetIterator cldItr(childGrp); *cldItr; ++cldItr)
|
|
|
|
- {
|
|
|
|
- SimObject* chldChld = dynamic_cast<SimObject*>(*cldItr);
|
|
|
|
- if (chldChld && chldChld->isSelected())
|
|
|
|
|
|
+ if (childGrp->isSelected())
|
|
{
|
|
{
|
|
mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
return; //if a child is selected, then we don't want to unload
|
|
return; //if a child is selected, then we don't want to unload
|
|
}
|
|
}
|
|
|
|
+ for (SimGroupIterator cldItr(childGrp); *cldItr; ++cldItr)
|
|
|
|
+ {
|
|
|
|
+ SimObject* chldChld = dynamic_cast<SimObject*>(*cldItr);
|
|
|
|
+ if (chldChld && chldChld->isSelected())
|
|
|
|
+ {
|
|
|
|
+ mStartUnloadTimerMS = Sim::getCurrentTime();
|
|
|
|
+ return; //if a child is selected, then we don't want to unload
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- _closeFile(true);
|
|
|
|
- mLoaded = false;
|
|
|
|
-
|
|
|
|
|
|
+ onUnloaded_callback();
|
|
for (U32 i = 0; i < mGameModesList.size(); i++)
|
|
for (U32 i = 0; i < mGameModesList.size(); i++)
|
|
{
|
|
{
|
|
- mGameModesList[i]->onSubsceneUnloaded_callback();
|
|
|
|
|
|
+ mGameModesList[i]->onSubsceneUnloaded_callback(this);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (!mOnUnloadCommand.isEmpty())
|
|
|
|
+ {
|
|
|
|
+ String command = "%this = " + String(getIdString()) + "; " + mOnUnloadCommand + ";";
|
|
|
|
+ Con::evaluatef(command.c_str());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _closeFile(true);
|
|
|
|
+ mLoaded = false;
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
bool SubScene::save()
|
|
bool SubScene::save()
|