Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Subscenes, SceneGroups and Gamemodes #1311

Open
wants to merge 21 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ae8eca4
Implementation of Subscenes, SceneGroups and Gamemodes
Areloch Sep 1, 2024
d896a2b
Removed scan-down of subscenes from Scene's getObjectsByClass call
Areloch Sep 1, 2024
d7335a7
Removed dummy placeholder function stub
Areloch Sep 1, 2024
4bb26bf
Reorganized the exec's for datablocks in module template file to be w…
Areloch Sep 2, 2024
6ff92f6
Fixed SceneGroup onInspect call to call up through parent
Areloch Sep 3, 2024
a931e9a
Tweaks the Scene and SubScene save calls to handle simGroups to call …
Areloch Sep 5, 2024
20a01d9
Merge branch 'development' of https://github.com/TorqueGameEngines/To…
Areloch Sep 29, 2024
99bcf7c
fix forest editor failing to pop up a create new
Azaezel Oct 1, 2024
5f6fe21
Merge pull request #1326 from Azaezel/alpha41/forestfix
Azaezel Oct 1, 2024
bb432dc
fix(?) assimp to torquie matrix converter
Azaezel Oct 1, 2024
e4d07c7
Adds utility function and method to be able to enact a load of subsce…
Areloch Oct 4, 2024
020bd03
Adds logic so levels without a gamemode defined at all are treated as…
Areloch Oct 4, 2024
4350112
Merge pull request #1327 from Azaezel/alpha41/matrixMangle
Areloch Oct 4, 2024
dde0ffe
Merge branch 'SubScenes_Gamemode_PR' of https://github.com/Areloch/To…
Areloch Oct 20, 2024
484ece3
adds loadIf conditional eval, onLoad/UnloadCommands, ability to freez…
Areloch Oct 21, 2024
10d1aec
Shift tracking of dynamicObjects from strict child objects for Scenes…
Areloch Oct 28, 2024
e2d0cc1
Fixes issue where Regenerate Bounds button for SceneGroup/SubScenes w…
Areloch Nov 6, 2024
9ff2a56
Fixed issue of mis-transforming child objects so rotation would be we…
Areloch Nov 13, 2024
2c8adfd
Fixed child relative transforms for when SceneGroups are updated
Areloch Nov 15, 2024
75fb668
Fixed up render transform handling for SceneGroups
Areloch Nov 15, 2024
e56df92
Used the math from PathShape updating to standardize updating the tra…
Areloch Nov 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 131 additions & 43 deletions Engine/source/T3D/Scene.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
#include "Scene.h"
#include "T3D/assets/LevelAsset.h"
#include "T3D/gameBase/gameConnection.h"
#include "T3D/gameMode.h"

Scene * Scene::smRootScene = nullptr;
Vector<Scene*> Scene::smSceneList;

IMPLEMENT_CALLBACK(Scene, onSaving, void, (const char* fileName), (fileName),
"@brief Called when a scene is saved to allow scenes to special-handle prepwork for saving if required.\n\n"

"@param fileName The level file being saved\n");

IMPLEMENT_CO_NETOBJECT_V1(Scene);

Scene::Scene() :
mIsSubScene(false),
mParentScene(nullptr),
mSceneId(-1),
mIsEditing(false),
mIsDirty(false),
mEditPostFX(0)
{
mGameModeName = StringTable->EmptyString();
mGameModesNames = StringTable->EmptyString();
}

Scene::~Scene()
Expand All @@ -28,13 +34,12 @@ void Scene::initPersistFields()
Parent::initPersistFields();

addGroup("Internal");
addField("isSubscene", TypeBool, Offset(mIsSubScene, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
addField("isEditing", TypeBool, Offset(mIsEditing, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
addField("isDirty", TypeBool, Offset(mIsDirty, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
endGroup("Internal");

addGroup("Gameplay");
addField("gameModeName", TypeString, Offset(mGameModeName, Scene), "The name of the gamemode that this scene utilizes");
addField("gameModes", TypeGameModeList, Offset(mGameModesNames, Scene), "The game modes that this Scene is associated with.");
endGroup("Gameplay");

addGroup("PostFX");
Expand All @@ -51,48 +56,33 @@ bool Scene::onAdd()
smSceneList.push_back(this);
mSceneId = smSceneList.size() - 1;

/*if (smRootScene == nullptr)
{
//we're the first scene, so we're the root. woo!
smRootScene = this;
}
else
{
mIsSubScene = true;
smRootScene->mSubScenes.push_back(this);
}*/
GameMode::findGameModes(mGameModesNames, &mGameModesList);

return true;
}

void Scene::onRemove()
{
for (U32 i = 0; i < mGameModesList.size(); i++)
{
mGameModesList[i]->onSceneUnloaded_callback();
}

Parent::onRemove();

smSceneList.remove(this);
mSceneId = -1;

/*if (smRootScene == this)
{
for (U32 i = 0; i < mSubScenes.size(); i++)
{
mSubScenes[i]->deleteObject();
}
}
else if (smRootScene != nullptr)
{
for (U32 i = 0; i < mSubScenes.size(); i++)
{
if(mSubScenes[i]->getId() == getId())
smRootScene->mSubScenes.erase(i);
}
}*/
}

void Scene::onPostAdd()
{
if (isMethod("onPostAdd"))
Con::executef(this, "onPostAdd");

for (U32 i = 0; i < mGameModesList.size(); i++)
{
mGameModesList[i]->onSceneLoaded_callback();
}
}

bool Scene::_editPostEffects(void* object, const char* index, const char* data)
Expand All @@ -110,11 +100,12 @@ bool Scene::_editPostEffects(void* object, const char* index, const char* data)
void Scene::addObject(SimObject* object)
{
//Child scene
Scene* scene = dynamic_cast<Scene*>(object);
SubScene* scene = dynamic_cast<SubScene*>(object);
if (scene)
{
//We'll keep these principly separate so they don't get saved into each other
mSubScenes.push_back(scene);
Parent::addObject(object);
return;
}

Expand All @@ -135,7 +126,7 @@ void Scene::addObject(SimObject* object)
void Scene::removeObject(SimObject* object)
{
//Child scene
Scene* scene = dynamic_cast<Scene*>(object);
SubScene* scene = dynamic_cast<SubScene*>(object);
if (scene)
{
//We'll keep these principly separate so they don't get saved into each other
Expand All @@ -157,30 +148,88 @@ void Scene::removeObject(SimObject* object)
Parent::removeObject(object);
}

void Scene::addDynamicObject(SceneObject* object)
void Scene::addDynamicObject(SimObject* object)
{
mDynamicObjects.push_back(object);

SimGroup* cleanupGroup;
if(Sim::findObject("MissionCleanup", cleanupGroup))
{
cleanupGroup->addObject(object);
}

//Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
Parent::addObject(object);
//Parent::addObject(object);
}

void Scene::removeDynamicObject(SceneObject* object)
void Scene::removeDynamicObject(SimObject* object)
{
mDynamicObjects.remove(object);

SimGroup* cleanupGroup;
if (Sim::findObject("MissionCleanup", cleanupGroup))
{
cleanupGroup->removeObject(object);
}

//Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
Parent::removeObject(object);
//Parent::removeObject(object);
}

void Scene::interpolateTick(F32 delta)
{

}

void Scene::processTick()
{
if (!isServerObject())
return;

//iterate over our subscenes to update their status of loaded or unloaded based on if any control objects intersect their bounds
for (U32 i = 0; i < mSubScenes.size(); i++)
{
bool hasClients = false;

SimGroup* pClientGroup = Sim::getClientGroup();
for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++)
{
GameConnection* gc = dynamic_cast<GameConnection*>(*itr);
if (gc)
{
GameBase* controlObj = gc->getControlObject();
if (controlObj == nullptr)
{
controlObj = gc->getCameraObject();
}

if (controlObj != nullptr)
{
if (mSubScenes[i]->testBox(controlObj->getWorldBox()))
{
//we have a client controlling object in the bounds, so we ensure the contents are loaded
hasClients = true;
break;
}
}
}
}

if (hasClients)
{
mSubScenes[i]->setUnloadTimeMS(-1);
mSubScenes[i]->load();
}
else
{
if (mSubScenes[i]->isLoaded() && mSubScenes[i]->getUnloadTimsMS() == -1)
{
mSubScenes[i]->setUnloadTimeMS(Sim::getCurrentTime());
}

if (Sim::getCurrentTime() - mSubScenes[i]->getUnloadTimsMS() > 5000)
mSubScenes[i]->unload();
}
}
}

void Scene::advanceTime(F32 timeDelta)
Expand All @@ -205,15 +254,15 @@ void Scene::dumpUtilizedAssets()
Con::printf("Dumping utilized assets in scene!");

Vector<StringTableEntry> utilizedAssetsList;
for (U32 i = 0; i < mPermanentObjects.size(); i++)
/*for (U32 i = 0; i < mPermanentObjects.size(); i++)
{
mPermanentObjects[i]->getUtilizedAssets(&utilizedAssetsList);
}

for (U32 i = 0; i < mDynamicObjects.size(); i++)
{
mDynamicObjects[i]->getUtilizedAssets(&utilizedAssetsList);
}
}*/

for (U32 i = 0; i < utilizedAssetsList.size(); i++)
{
Expand Down Expand Up @@ -257,6 +306,23 @@ bool Scene::saveScene(StringTableEntry fileName)
fileName = getOriginatingFile();
}

for (SimGroupIterator itr(this); *itr; ++itr)
{
if((*itr)->isMethod("onSaving"))
{
ConsoleValue vars[3];
vars[2].setString(fileName);
Con::execute((*itr), 3, vars);
}
}

//Inform our subscenes we're saving so they can do any
//special work required as well
for (U32 i = 0; i < mSubScenes.size(); i++)
{
mSubScenes[i]->save();
}

bool saveSuccess = save(fileName);

if (!saveSuccess)
Expand Down Expand Up @@ -286,9 +352,12 @@ bool Scene::saveScene(StringTableEntry fileName)
dSprintf(depValue, sizeof(depValue), "%s=%s", ASSET_ID_SIGNATURE, utilizedAssetsList[i]);

levelAssetDef->setDataField(StringTable->insert(depSlotName), NULL, StringTable->insert(depValue));

}

//update the gamemode list as well
levelAssetDef->setDataField(StringTable->insert("gameModesNames"), NULL, StringTable->insert(mGameModesNames));

//Finally, save
saveSuccess = levelAssetDef->saveAsset();

return saveSuccess;
Expand All @@ -314,11 +383,26 @@ void Scene::getUtilizedAssetsFromSceneObject(SimObject* object, Vector<StringTab
}

//
Vector<SceneObject*> Scene::getObjectsByClass(String className, bool checkSubscenes)
Vector<SceneObject*> Scene::getObjectsByClass(String className)
{
return Vector<SceneObject*>();
}

void Scene::loadAtPosition(const Point3F& position)
{
for (U32 i = 0; i < mSubScenes.size(); i++)
{
Box3F testBox = Box3F(0.5);
testBox.setCenter(position);

if (mSubScenes[i]->testBox(testBox))
{
mSubScenes[i]->setUnloadTimeMS(-1);
mSubScenes[i]->load();
}
}
}

DefineEngineFunction(getScene, Scene*, (U32 sceneId), (0),
"Get the root Scene object that is loaded.\n"
"@return The id of the Root Scene. Will be 0 if no root scene is loaded")
Expand Down Expand Up @@ -413,9 +497,13 @@ DefineEngineMethod(Scene, getLevelAsset, const char*, (), ,
DefineEngineMethod(Scene, save, bool, (const char* fileName), (""),
"Save out the object to the given file.\n"
"@param fileName The name of the file to save to."
"@param selectedOnly If true, only objects marked as selected will be saved out.\n"
"@param preAppendString Text which will be preprended directly to the object serialization.\n"
"@param True on success, false on failure.")
{
return object->saveScene(StringTable->insert(fileName));
}

DefineEngineMethod(Scene, loadAtPosition, void, (Point3F position), (Point3F::Zero),
"Loads any subscenes at a given point by force.\n")
{
object->loadAtPosition(position);
}
Loading
Loading