Merge pull request #299 from Areloch/LevelDependencyLoadingAndFixes

Level Asset Dependency handling and various level fixes
This commit is contained in:
Brian Roberts 2020-08-21 07:28:24 -05:00 committed by GitHub
commit 8e61600a82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 263 additions and 255 deletions

View file

@ -1,4 +1,5 @@
#include "Scene.h" #include "Scene.h"
#include "T3D/assets/LevelAsset.h"
Scene * Scene::smRootScene = nullptr; Scene * Scene::smRootScene = nullptr;
Vector<Scene*> Scene::smSceneList; Vector<Scene*> Scene::smSceneList;
@ -180,6 +181,93 @@ void Scene::unpackUpdate(NetConnection *conn, BitStream *stream)
} }
void Scene::dumpUtilizedAssets()
{
Con::printf("Dumping utilized assets in scene!");
Vector<StringTableEntry> utilizedAssetsList;
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++)
{
Con::printf("Utilized Asset: %s", utilizedAssetsList[i]);
}
Con::printf("Utilized Asset dump complete!");
}
StringTableEntry Scene::getOriginatingFile()
{
return getFilename();
}
StringTableEntry Scene::getLevelAsset()
{
StringTableEntry levelFile = getFilename();
if (levelFile == StringTable->EmptyString())
return StringTable->EmptyString();
AssetQuery* query = new AssetQuery();
query->registerObject();
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(query, levelFile);
if (foundAssetcount == 0)
return StringTable->EmptyString();
else
return query->mAssetList[0];
}
bool Scene::saveScene(StringTableEntry fileName)
{
//So, we ultimately want to not only save out the level, but also collate all the assets utilized
//by the static objects in the scene so we can have those before we parse the level file itself
//Useful for preloading or stat tracking
//First, save the level file
if (fileName == StringTable->EmptyString())
{
fileName = getOriginatingFile();
}
bool saveSuccess = save(fileName);
if (!saveSuccess)
return false;
//Get the level asset
StringTableEntry levelAsset = getLevelAsset();
if (levelAsset == StringTable->EmptyString())
return saveSuccess;
LevelAsset* levelAssetDef = AssetDatabase.acquireAsset<LevelAsset>(levelAsset);
levelAssetDef->clearAssetDependencyFields("staticObjectAssetDependency");
//Next, lets build out our
Vector<StringTableEntry> utilizedAssetsList;
for (U32 i = 0; i < mPermanentObjects.size(); i++)
{
mPermanentObjects[i]->getUtilizedAssets(&utilizedAssetsList);
}
for (U32 i = 0; i < utilizedAssetsList.size(); i++)
{
levelAssetDef->addAssetDependencyField("staticObjectAssetDependency", utilizedAssetsList[i]);
}
saveSuccess = levelAssetDef->saveAsset();
return saveSuccess;
}
// //
Vector<SceneObject*> Scene::getObjectsByClass(String className, bool checkSubscenes) Vector<SceneObject*> Scene::getObjectsByClass(String className, bool checkSubscenes)
{ {
@ -251,3 +339,34 @@ DefineEngineMethod(Scene, getObjectsByClass, String, (String className), (""),
//return object->getObjectsByClass(className); //return object->getObjectsByClass(className);
return ""; return "";
} }
DefineEngineMethod(Scene, dumpUtilizedAssets, void, (), ,
"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")
{
object->dumpUtilizedAssets();
}
DefineEngineMethod(Scene, getOriginatingFile, const char*, (), ,
"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")
{
return object->getOriginatingFile();
}
DefineEngineMethod(Scene, getLevelAsset, const char*, (), ,
"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")
{
return object->getLevelAsset();
}
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));
}

View file

@ -62,6 +62,13 @@ public:
void addDynamicObject(SceneObject* object); void addDynamicObject(SceneObject* object);
void removeDynamicObject(SceneObject* object); void removeDynamicObject(SceneObject* object);
void dumpUtilizedAssets();
StringTableEntry getOriginatingFile();
StringTableEntry getLevelAsset();
bool saveScene(StringTableEntry fileName);
// //
//Networking //Networking
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream); U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);

View file

@ -330,9 +330,52 @@ void LevelAsset::setNavmeshFile(const char* pNavmeshFile)
refreshAsset(); refreshAsset();
} }
void LevelAsset::loadDependencies()
{
//First, load any material, animation, etc assets we may be referencing in our asset
// Find any asset dependencies.
AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
// Does the asset have any dependencies?
if (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end())
{
// Iterate all dependencies.
while (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end() && assetDependenciesItr->key == mpAssetDefinition->mAssetId)
{
//Force it to be loaded by acquiring it
StringTableEntry assetId = assetDependenciesItr->value;
mAssetDependencies.push_back(AssetDatabase.acquireAsset<AssetBase>(assetId));
// Next dependency.
assetDependenciesItr++;
}
}
}
void LevelAsset::unloadDependencies()
{
for (U32 i = 0; i < mAssetDependencies.size(); i++)
{
AssetBase* assetDef = mAssetDependencies[i];
AssetDatabase.releaseAsset(assetDef->getAssetId());
}
}
DefineEngineMethod(LevelAsset, getLevelFile, const char*, (),, DefineEngineMethod(LevelAsset, getLevelFile, const char*, (),,
"Creates a new script asset using the targetFilePath.\n" "Creates a new script asset using the targetFilePath.\n"
"@return The bool result of calling exec") "@return The bool result of calling exec")
{ {
return object->getLevelPath(); return object->getLevelPath();
} }
DefineEngineMethod(LevelAsset, loadDependencies, void, (), ,
"Initiates the loading of asset dependencies for this level.")
{
return object->loadDependencies();
}
DefineEngineMethod(LevelAsset, unloadDependencies, void, (), ,
"Initiates the unloading of previously loaded asset dependencies for this level.")
{
return object->unloadDependencies();
}

View file

@ -67,6 +67,8 @@ class LevelAsset : public AssetBase
StringTableEntry mGamemodeName; StringTableEntry mGamemodeName;
Vector<AssetBase*> mAssetDependencies;
public: public:
LevelAsset(); LevelAsset();
virtual ~LevelAsset(); virtual ~LevelAsset();
@ -78,6 +80,9 @@ public:
/// Declare Console Object. /// Declare Console Object.
DECLARE_CONOBJECT(LevelAsset); DECLARE_CONOBJECT(LevelAsset);
void loadDependencies();
void unloadDependencies();
void setLevelFile(const char* pImageFile); void setLevelFile(const char* pImageFile);
inline StringTableEntry getLevelFile(void) const { return mLevelFile; }; inline StringTableEntry getLevelFile(void) const { return mLevelFile; };
void setPostFXPresetFile(const char* pPostFXPresetFile); void setPostFXPresetFile(const char* pPostFXPresetFile);

View file

@ -221,7 +221,6 @@ bool TerrainAsset::loadTerrain()
//Force the asset to become initialized if it hasn't been already //Force the asset to become initialized if it hasn't been already
AssetPtr<TerrainMaterialAsset> matAsset = assetId; AssetPtr<TerrainMaterialAsset> matAsset = assetId;
mTerrMaterialAssets.push_front(matAsset); mTerrMaterialAssets.push_front(matAsset);
} }

View file

@ -1691,6 +1691,12 @@ void TSStatic::updateMaterials()
mShapeInstance->initMaterialList(); mShapeInstance->initMaterialList();
} }
void TSStatic::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
{
if(!mShapeAsset.isNull())
usedAssetsList->push_back_unique(mShapeAssetId);
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
//These functions are duplicated in tsStatic and shapeBase. //These functions are duplicated in tsStatic and shapeBase.
//They each function a little differently; but achieve the same purpose of gathering //They each function a little differently; but achieve the same purpose of gathering

View file

@ -286,6 +286,8 @@ public:
bool isAnimated() { return mPlayAmbient; } bool isAnimated() { return mPlayAmbient; }
virtual void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList);
private: private:
virtual void onStaticModified(const char* slotName, const char* newValue = NULL); virtual void onStaticModified(const char* slotName, const char* newValue = NULL);
protected: protected:

View file

@ -253,30 +253,22 @@ bool AssetManager::loadModuleAutoLoadAssets(ModuleDefinition* pModuleDefinition)
if (assetDef->mAssetType == pAutoloadAssets->getAssetType()) if (assetDef->mAssetType == pAutoloadAssets->getAssetType())
{ {
//TODO: this is stupid and ugly, need to properly automagically parse the class for registration String assetPath = assetDef->mAssetBaseFilePath;
AssetBase* assetBase = nullptr; assetPath.replace("//", "/");
if (assetDef->mAssetType == StringTable->insert("GUIAsset")) String autoLoadPath = pModuleDefinition->getModulePath();
{ autoLoadPath += "/";
assetBase = mTaml.read<GUIAsset>(assetDef->mAssetBaseFilePath); autoLoadPath += pAutoloadAssets->getPath();
}
else if (assetDef->mAssetType == StringTable->insert("ScriptAsset"))
{
assetBase = mTaml.read<ScriptAsset>(assetDef->mAssetBaseFilePath);
}
else if (assetDef->mAssetType == StringTable->insert("MaterialAsset"))
{
assetBase = mTaml.read<MaterialAsset>(assetDef->mAssetBaseFilePath);
}
else if (assetDef->mAssetType == StringTable->insert("GameObjectAsset"))
{
assetBase = mTaml.read<GameObjectAsset>(assetDef->mAssetBaseFilePath);
}
//load the asset now if valid if (pAutoloadAssets->getPath() == StringTable->EmptyString() || assetPath.startsWith(autoLoadPath.c_str()))
if (assetBase)
{ {
assetBase->setOwned(this, assetDef); AssetBase* assetBase = dynamic_cast<AssetBase*>(mTaml.read(assetDef->mAssetBaseFilePath));
//load the asset now if valid
if (assetBase)
{
assetBase->setOwned(this, assetDef);
}
} }
} }
} }

View file

@ -942,6 +942,8 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
/// notification that a direct child object has been detached /// notification that a direct child object has been detached
virtual void onLostChild(SceneObject *subObject); virtual void onLostChild(SceneObject *subObject);
// PATHSHAPE END // PATHSHAPE END
virtual void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList) {}
}; };
#endif // _SCENEOBJECT_H_ #endif // _SCENEOBJECT_H_

View file

@ -1420,6 +1420,11 @@ void TerrainBlock::getMinMaxHeight( F32 *minHeight, F32 *maxHeight ) const
*maxHeight = fixedToFloat( sq->maxHeight ); *maxHeight = fixedToFloat( sq->maxHeight );
} }
void TerrainBlock::getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList)
{
if (!mTerrainAsset.isNull())
usedAssetsList->push_back_unique(mTerrainAssetId);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Console Methods // Console Methods
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -475,6 +475,8 @@ public:
void unpackUpdate(NetConnection *conn, BitStream *stream); void unpackUpdate(NetConnection *conn, BitStream *stream);
void inspectPostApply(); void inspectPostApply();
virtual void getUtilizedAssets(Vector<StringTableEntry>* usedAssetsList);
protected: protected:
bool mIgnoreZodiacs; bool mIgnoreZodiacs;
U16* zode_primBuffer; U16* zode_primBuffer;

View file

@ -60,11 +60,11 @@ function Core_ClientServer::onDestroy( %this )
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function StartGame( %mission, %hostingType ) function StartGame( %levelAsset, %hostingType )
{ {
if( %mission $= "" ) if( %levelAsset $= "" )
{ {
%mission = $selectedLevelFile; %levelAsset = $selectedLevelAsset;
} }
if (%hostingType !$= "") if (%hostingType !$= "")
@ -88,7 +88,7 @@ function StartGame( %mission, %hostingType )
Canvas.repaint(); Canvas.repaint();
} }
createAndConnectToLocalServer( %serverType, %mission ); createAndConnectToLocalServer( %serverType, %levelAsset );
} }
function JoinGame( %serverIndex ) function JoinGame( %serverIndex )

View file

@ -33,22 +33,26 @@ $MissionLoadPause = 5000;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//This is the first call made by the server to kick the loading process off //This is the first call made by the server to kick the loading process off
function loadMission( %missionName, %isFirstMission ) function loadMission( %levelAsset, %isFirstMission )
{ {
endMission(); endMission();
echo("*** LOADING MISSION: " @ %missionName); $Server::LevelAsset = AssetDatabase.acquireAsset(%levelAsset);
echo("*** LOADING MISSION: " @ $Server::LevelAsset.LevelName);
echo("*** Stage 1 load"); echo("*** Stage 1 load");
// increment the mission sequence (used for ghost sequencing) // increment the mission sequence (used for ghost sequencing)
$missionSequence++; $missionSequence++;
$missionRunning = false; $missionRunning = false;
$Server::MissionFile = %missionName; $Server::MissionFile = $Server::LevelAsset.getLevelFile();
$Server::LoadFailMsg = ""; $Server::LoadFailMsg = "";
$Server::LevelAsset.loadDependencies();
// Extract mission info from the mission file, // Extract mission info from the mission file,
// including the display name and stuff to send // including the display name and stuff to send
// to the client. // to the client.
buildLoadInfo( %missionName ); buildLoadInfo( $Server::MissionFile );
// Download mission info to the clients // Download mission info to the clients
%count = ClientGroup.getCount(); %count = ClientGroup.getCount();
@ -163,6 +167,9 @@ function endMission()
getScene(0).delete(); getScene(0).delete();
MissionCleanup.delete(); MissionCleanup.delete();
if(isObject($Server::LevelAsset))
AssetDatabase.releaseAsset($Server::LevelAsset.getAssetId()); //cleanup
if ($Pref::Server::EnableDatablockCache) if ($Pref::Server::EnableDatablockCache)
resetDatablockCache(); resetDatablockCache();
DatablockFilesList.empty(); DatablockFilesList.empty();

View file

@ -93,9 +93,9 @@ function portInit(%port)
/// create a local client connection to the server. /// create a local client connection to the server.
// //
/// @return true if successful. /// @return true if successful.
function createAndConnectToLocalServer( %serverType, %level ) function createAndConnectToLocalServer( %serverType, %levelAsset )
{ {
if( !createServer( %serverType, %level ) ) if( !createServer( %serverType, %levelAsset ) )
return false; return false;
%conn = new GameConnection( ServerConnection ); %conn = new GameConnection( ServerConnection );
@ -124,7 +124,7 @@ function createAndConnectToLocalServer( %serverType, %level )
/// Create a server with either a "SinglePlayer" or "MultiPlayer" type /// Create a server with either a "SinglePlayer" or "MultiPlayer" type
/// Specify the level to load on the server /// Specify the level to load on the server
function createServer(%serverType, %level) function createServer(%serverType, %levelAsset)
{ {
if($Game::firstTimeServerRun == true) if($Game::firstTimeServerRun == true)
{ {
@ -135,7 +135,7 @@ function createServer(%serverType, %level)
// working with the server session we think we are. // working with the server session we think we are.
$Server::Session++; $Server::Session++;
if (%level $= "") if (%levelAsset $= "")
{ {
error("createServer(): level name unspecified"); error("createServer(): level name unspecified");
return false; return false;
@ -143,7 +143,7 @@ function createServer(%serverType, %level)
// Make sure our level name is relative so that it can send // Make sure our level name is relative so that it can send
// across the network correctly // across the network correctly
%level = makeRelativePath(%level, getWorkingDirectory()); //%level = makeRelativePath(%level, getWorkingDirectory());
destroyServer(); destroyServer();
@ -176,7 +176,7 @@ function createServer(%serverType, %level)
// the server has been created // the server has been created
onServerCreated(); onServerCreated();
loadMission(%level, true); loadMission(%levelAsset, true);
$Game::running = true; $Game::running = true;

View file

@ -52,6 +52,9 @@ function ChooseLevelDlg::onWake( %this )
{ {
%assetId = %assetQuery.getAsset(%i); %assetId = %assetQuery.getAsset(%i);
if(AssetDatabase.getAssetModule(%assetId).ModuleId $= "ToolsModule")
continue;
%levelAsset = AssetDatabase.acquireAsset(%assetId); %levelAsset = AssetDatabase.acquireAsset(%assetId);
%file = %levelAsset.getLevelFile(); %file = %levelAsset.getLevelFile();
@ -93,53 +96,6 @@ function ChooseLevelDlg::onWake( %this )
else else
LevelSelectTitle.setText("CREATE SERVER"); LevelSelectTitle.setText("CREATE SERVER");
/*for (%i = 0; %i < LevelList.rowCount(); %i++)
{
%preview = new GuiButtonCtrl() {
profile = "GuiMenuButtonProfile";
internalName = "SmallPreview" @ %i;
Extent = "368 35";
text = getField(CL_levelList.getRowText(%i), 0);
command = "ChooseLevelWindow.previewSelected(ChooseLevelWindow->SmallPreviews->SmallPreview" @ %i @ ");";
buttonType = "RadioButton";
};
ChooseLevelWindow->SmallPreviews.add(%preview);
%rowText = CL_levelList.getRowText(%i);
// Set the level index
%preview.levelIndex = %i;
// Get the name
%name = getField(CL_levelList.getRowText(%i), 0);
%preview.levelName = %name;
%file = getField(CL_levelList.getRowText(%i), 1);
// Find the preview image
%levelPreview = getField(CL_levelList.getRowText(%i), 3);
// Test against all of the different image formats
// This should probably be moved into an engine function
if (isFile(%levelPreview @ ".png") ||
isFile(%levelPreview @ ".jpg") ||
isFile(%levelPreview @ ".bmp") ||
isFile(%levelPreview @ ".gif") ||
isFile(%levelPreview @ ".jng") ||
isFile(%levelPreview @ ".mng") ||
isFile(%levelPreview @ ".tga"))
{
%preview.bitmap = %levelPreview;
}
// Get the description
%desc = getField(CL_levelList.getRowText(%i), 2);
%preview.levelDesc = %desc;
}*/
ChooseLevelButtonHolder.setActive(); ChooseLevelButtonHolder.setActive();
} }
@ -184,28 +140,7 @@ function ChooseLevelDlg::addMissionFile( %this, %file )
function ChooseLevelDlg::addLevelAsset( %this, %levelAsset ) function ChooseLevelDlg::addLevelAsset( %this, %levelAsset )
{ {
%file = %levelAsset.getLevelFile(); %file = %levelAsset.getAssetId();
/*%levelName = fileBase(%file);
%levelDesc = "A Torque level";
%LevelInfoObject = getLevelInfo(%file);
if (%LevelInfoObject != 0)
{
if(%LevelInfoObject.levelName !$= "")
%levelName = %LevelInfoObject.levelName;
else if(%LevelInfoObject.name !$= "")
%levelName = %LevelInfoObject.name;
if (%LevelInfoObject.desc0 !$= "")
%levelDesc = %LevelInfoObject.desc0;
if (%LevelInfoObject.preview !$= "")
%levelPreview = %LevelInfoObject.preview;
%LevelInfoObject.delete();
}*/
%levelName = %levelAsset.LevelName; %levelName = %levelAsset.LevelName;
%levelDesc = %levelAsset.description; %levelDesc = %levelAsset.description;
@ -224,7 +159,7 @@ function LevelList::onChange(%this)
ChooseLevelWindow->LevelName.text = getField(%levelEntry, 0); ChooseLevelWindow->LevelName.text = getField(%levelEntry, 0);
// Get the level file // Get the level file
$selectedLevelFile = getField(%levelEntry, 1); $selectedLevelAsset = getField(%levelEntry, 1);
// Find the preview image // Find the preview image
%levelPreview = getField(%levelEntry, 3); %levelPreview = getField(%levelEntry, 3);

View file

@ -16,7 +16,7 @@ function ToolsModule::onCreate(%this)
// to find exactly which subsystems should be readied before kicking things off. // to find exactly which subsystems should be readied before kicking things off.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
ModuleDatabase.LoadExplicit( "MainEditor" ); //ModuleDatabase.LoadExplicit( "MainEditor" );
//ModuleDatabase.LoadExplicit( "Tools_ObjectViewer" ); //ModuleDatabase.LoadExplicit( "Tools_ObjectViewer" );
} }

View file

@ -5,4 +5,10 @@
ScriptFile="Tools.cs" ScriptFile="Tools.cs"
CreateFunction="onCreate" CreateFunction="onCreate"
DestroyFunction="onDestroy" DestroyFunction="onDestroy"
Group="Tools"/> Group="Tools">
<DeclaredAssets
canSave="true"
canSaveDynamicFields="true"
Extension="asset.taml"
Recurse="true" />
</ModuleDefinition>

View file

@ -1,141 +0,0 @@
//--- OBJECT WRITE BEGIN ---
new Scene(EditorTemplateLevel) {
canSave = "1";
canSaveDynamicFields = "1";
isSubScene = "0";
isEditing = "0";
isDirty = "0";
cdTrack = "2";
CTF_scoreLimit = "5";
Enabled = "1";
musicTrack = "lush";
new LevelInfo(theLevelInfo) {
nearClip = "0.1";
visibleDistance = "1000";
visibleGhostDistance = "0";
decalBias = "0.0015";
fogColor = "0.6 0.6 0.7 1";
fogDensity = "0";
fogDensityOffset = "700";
fogAtmosphereHeight = "0";
canvasClearColor = "0 0 0 255";
ambientLightBlendPhase = "1";
ambientLightBlendCurve = "0 0 -1 -1";
soundAmbience = "AudioAmbienceDefault";
soundDistanceModel = "Linear";
canSave = "1";
canSaveDynamicFields = "1";
advancedLightmapSupport = "0";
desc0 = "A blank room template that acts as a starting point.";
Enabled = "1";
LevelName = "Blank Room Template";
};
new SkyBox(theSky) {
Material = "BlankSkyMat";
drawBottom = "0";
fogBandHeight = "0";
dirtyGameObject = "0";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
canSave = "1";
canSaveDynamicFields = "1";
};
new Sun(theSun) {
azimuth = "230.396";
elevation = "45";
color = "0.968628 0.901961 0.901961 1";
ambient = "0.337255 0.533333 0.619608 1";
brightness = "1";
castShadows = "1";
staticRefreshFreq = "250";
dynamicRefreshFreq = "8";
coronaEnabled = "1";
coronaScale = "0.5";
coronaTint = "1 1 1 1";
coronaUseLightColor = "1";
flareScale = "1";
attenuationRatio = "0 1 1";
shadowType = "PSSM";
texSize = "2048";
overDarkFactor = "3000 1500 750 250";
shadowDistance = "200";
shadowSoftness = "0.25";
numSplits = "4";
logWeight = "0.9";
fadeStartDistance = "0";
lastSplitTerrainOnly = "0";
representedInLightmap = "0";
shadowDarkenColor = "0 0 0 -1";
includeLightmappedGeometryInShadow = "0";
dirtyGameObject = "0";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
canSave = "1";
canSaveDynamicFields = "1";
bias = "0.1";
Blur = "1";
Enabled = "1";
height = "1024";
lightBleedFactor = "0.8";
minVariance = "0";
pointShadowType = "PointShadowType_Paraboloid";
shadowBox = "-100 -100 -100 100 100 100";
splitFadeDistances = "1 1 1 1";
width = "3072";
};
new GroundPlane() {
squareSize = "128";
scaleU = "25";
scaleV = "25";
Material = "Grid_512_Grey";
dirtyGameObject = "0";
canSave = "1";
canSaveDynamicFields = "1";
Enabled = "1";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
};
new Skylight() {
Enabled = "1";
ReflectionMode = "Baked Cubemap";
dirtyGameObject = "0";
position = "1.37009 -5.23561 46.5817";
rotation = "1 0 0 0";
canSave = "1";
canSaveDynamicFields = "1";
persistentId = "d5eb3afb-dced-11e9-a423-bb0e346e3870";
reflectionPath = "tools/levels/BlankRoom/probes/";
};
new TSStatic() {
ShapeAsset = "pbr:material_ball";
playAmbient = "1";
meshCulling = "0";
originSort = "0";
overrideColor = "0 0 0 0";
collisionType = "Collision Mesh";
decalType = "Collision Mesh";
allowPlayerStep = "0";
alphaFadeEnable = "0";
alphaFadeStart = "100";
alphaFadeEnd = "150";
alphaFadeInverse = "0";
renderNormals = "0";
forceDetail = "-1";
ignoreZodiacs = "0";
useGradientRange = "0";
gradientRange = "0 180";
invertGradientRange = "0";
dirtyGameObject = "0";
position = "-0.000554562 -0.0734091 1.05277";
rotation = "1 0 0 0";
scale = "1 1 1";
canSave = "1";
canSaveDynamicFields = "1";
materialSlot0 = "base_material_ball";
};
};
//--- OBJECT WRITE END ---

View file

@ -0,0 +1,10 @@
<LevelAsset
canSave="true"
canSaveDynamicFields="true"
AssetName="DefaultEditorLevel"
LevelFile="@assetFile=DefaultEditorLevel.mis"
LevelName="DefaultEditorLevel"
isSubScene="false"
description="An empty room"
staticObjectAssetDependency0="@Asset=FPSGameplay:station01"
VersionId="1" />

View file

@ -272,7 +272,7 @@ function fastLoadWorldEdit(%val)
if( !$missionRunning ) if( !$missionRunning )
{ {
EditorNewLevel("tools/levels/DefaultEditorLevel.mis"); EditorNewLevel("ToolsModule:DefaultEditorLevel");
} }
else else
{ {

View file

@ -199,7 +199,7 @@ function EditorOpenDeclarationInTorsion( %object )
EditorOpenFileInTorsion( makeFullPath( %fileName ), %object.getDeclarationLine() ); EditorOpenFileInTorsion( makeFullPath( %fileName ), %object.getDeclarationLine() );
} }
function EditorNewLevel( %file ) function EditorNewLevel( %level )
{ {
%saveFirst = false; %saveFirst = false;
if ( EditorIsDirty() ) if ( EditorIsDirty() )
@ -219,18 +219,18 @@ function EditorNewLevel( %file )
Editor.getUndoManager().clearAll(); Editor.getUndoManager().clearAll();
} }
if( %file $= "" ) if( %level $= "" )
{ {
%file = "tools/levels/DefaultEditorLevel.mis"; %level = "ToolsModule:DefaultEditorLevel";
} }
if( !$missionRunning ) if( !$missionRunning )
{ {
activatePackage( "BootEditor" ); activatePackage( "BootEditor" );
StartGame( %file ); StartGame( %level );
} }
else else
EditorOpenMission(%file); EditorOpenMission(%level);
//EWorldEditor.isDirty = true; //EWorldEditor.isDirty = true;
//ETerrainEditor.isDirty = true; //ETerrainEditor.isDirty = true;
@ -360,6 +360,15 @@ function EditorSaveMissionAs( %levelAsset )
if( fileExt( %missionName ) !$= ".mis" ) if( fileExt( %missionName ) !$= ".mis" )
%missionName = %missionName @ ".mis"; %missionName = %missionName @ ".mis";
//Update to be our active
$Server::MissionFile = %missionName;
%Server::LevelAsset = %levelAssetDef;
//Do the save
EditorSaveMission();
//TODO: doublecheck that we rename the scene properly
//Make sure we have a selected module so we can create our module //Make sure we have a selected module so we can create our module
//if(AssetBrowser.selectedModule $= "") //if(AssetBrowser.selectedModule $= "")
// Canvas.pushDialog( // Canvas.pushDialog(