mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Merge pull request #1481 from Areloch/MiscFixes_20250525
Misc Fixes and improvements including updated autosave handling
This commit is contained in:
commit
a43458677a
|
|
@ -291,7 +291,7 @@ StringTableEntry Scene::getLevelAsset()
|
|||
return query->mAssetList[0];
|
||||
}
|
||||
|
||||
bool Scene::saveScene(StringTableEntry fileName)
|
||||
bool Scene::saveScene(StringTableEntry fileName, const bool& saveSubScenes)
|
||||
{
|
||||
if (!isServerObject())
|
||||
return false;
|
||||
|
|
@ -316,9 +316,12 @@ bool Scene::saveScene(StringTableEntry fileName)
|
|||
|
||||
//Inform our subscenes we're saving so they can do any
|
||||
//special work required as well
|
||||
for (U32 i = 0; i < mSubScenes.size(); i++)
|
||||
if (saveSubScenes)
|
||||
{
|
||||
mSubScenes[i]->save();
|
||||
for (U32 i = 0; i < mSubScenes.size(); i++)
|
||||
{
|
||||
mSubScenes[i]->save();
|
||||
}
|
||||
}
|
||||
|
||||
bool saveSuccess = save(fileName);
|
||||
|
|
@ -381,9 +384,30 @@ void Scene::getUtilizedAssetsFromSceneObject(SimObject* object, Vector<StringTab
|
|||
}
|
||||
|
||||
//
|
||||
Vector<SceneObject*> Scene::getObjectsByClass(String className)
|
||||
void Scene::getObjectsByClass(SimObject* object, StringTableEntry className, Vector<SimObject*>* objectsList, bool checkSubscenes)
|
||||
{
|
||||
return Vector<SceneObject*>();
|
||||
if(object->getClassName() == className)
|
||||
{
|
||||
objectsList->push_back(object);
|
||||
}
|
||||
|
||||
//If it's a subscene and we DON'T want to scan through them, bail out now
|
||||
SubScene* subScene = dynamic_cast<SubScene*>(object);
|
||||
if (subScene && !checkSubscenes)
|
||||
return;
|
||||
|
||||
//If possible, now we iterate over the children
|
||||
SimGroup* group = dynamic_cast<SimGroup*>(object);
|
||||
if (group)
|
||||
{
|
||||
for (U32 c = 0; c < group->size(); c++)
|
||||
{
|
||||
SimObject* childObj = dynamic_cast<SimObject*>(group->getObject(c));
|
||||
|
||||
//Recurse down
|
||||
getObjectsByClass(childObj, className, objectsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::loadAtPosition(const Point3F& position)
|
||||
|
|
@ -460,15 +484,37 @@ DefineEngineMethod(Scene, removeDynamicObject, void, (SceneObject* sceneObj), (n
|
|||
object->removeDynamicObject(sceneObj);
|
||||
}
|
||||
|
||||
DefineEngineMethod(Scene, getObjectsByClass, String, (String className), (""),
|
||||
DefineEngineMethod(Scene, getObjectsByClass, String, (String className, bool checkSubScenes), ("", false),
|
||||
"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")
|
||||
"@param className The name of the class of objects to get a list of.\n"
|
||||
"@param checkSubScenes If true, will also scan through currently loaded subscenes to get matching objects.\n"
|
||||
"@return A space-separated list of object ids that match the searched-for className")
|
||||
{
|
||||
if (className == String::EmptyString)
|
||||
return "";
|
||||
|
||||
//return object->getObjectsByClass(className);
|
||||
return "";
|
||||
Vector<SimObject*>* objectsList = new Vector<SimObject*>();
|
||||
|
||||
object->getObjectsByClass(object, StringTable->insert(className.c_str()), objectsList, checkSubScenes);
|
||||
|
||||
char* retBuffer = Con::getReturnBuffer(1024);
|
||||
|
||||
U32 len = 0;
|
||||
S32 i;
|
||||
//Get the length of our return string
|
||||
for(U32 i=0; i < objectsList->size(); i++)
|
||||
len += dStrlen((*objectsList)[i]->getIdString());
|
||||
|
||||
char* ret = Con::getReturnBuffer(len + 1);
|
||||
ret[0] = 0;
|
||||
for (U32 i = 0; i < objectsList->size(); i++)
|
||||
{
|
||||
dStrcat(ret, (*objectsList)[i]->getIdString(), len + 1);
|
||||
dStrcat(ret, " ", len + 1);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DefineEngineMethod(Scene, dumpUtilizedAssets, void, (), ,
|
||||
|
|
@ -492,12 +538,12 @@ DefineEngineMethod(Scene, getLevelAsset, const char*, (), ,
|
|||
return object->getLevelAsset();
|
||||
}
|
||||
|
||||
DefineEngineMethod(Scene, save, bool, (const char* fileName), (""),
|
||||
DefineEngineMethod(Scene, save, bool, (const char* fileName, bool saveSubScenes), ("", true),
|
||||
"Save out the object to the given file.\n"
|
||||
"@param fileName The name of the file to save to."
|
||||
"@param True on success, false on failure.")
|
||||
{
|
||||
return object->saveScene(StringTable->insert(fileName));
|
||||
return object->saveScene(StringTable->insert(fileName), saveSubScenes);
|
||||
}
|
||||
|
||||
DefineEngineMethod(Scene, loadAtPosition, void, (Point3F position), (Point3F::Zero),
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public:
|
|||
StringTableEntry getOriginatingFile();
|
||||
StringTableEntry getLevelAsset();
|
||||
|
||||
bool saveScene(StringTableEntry fileName);
|
||||
bool saveScene(StringTableEntry fileName, const bool& saveSubScenes = true);
|
||||
|
||||
//
|
||||
//Networking
|
||||
|
|
@ -86,7 +86,7 @@ public:
|
|||
void unpackUpdate(NetConnection *conn, BitStream *stream) override;
|
||||
|
||||
//
|
||||
Vector<SceneObject*> getObjectsByClass(String className);
|
||||
void getObjectsByClass(SimObject* object, StringTableEntry className, Vector<SimObject*>* objectsList, bool checkSubscenes = false);
|
||||
|
||||
void getUtilizedAssetsFromSceneObject(SimObject* object, Vector<StringTableEntry>* usedAssetsList);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "physics/physicsShape.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "Scene.h"
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(SceneGroup);
|
||||
|
||||
|
|
@ -156,6 +157,37 @@ void SceneGroup::onInspect(GuiInspector* inspector)
|
|||
regenButton->setConsoleCommand(rgBuffer);
|
||||
|
||||
regenFieldGui->addObject(regenButton);
|
||||
|
||||
//
|
||||
//Regen bounds button
|
||||
GuiInspectorField* reparentFieldGui = sceneGroupGrp->createInspectorField();
|
||||
reparentFieldGui->init(inspector, sceneGroupGrp);
|
||||
|
||||
reparentFieldGui->setSpecialEditField(true);
|
||||
reparentFieldGui->setTargetObject(this);
|
||||
|
||||
fldnm = StringTable->insert("ReparentOOBObjs");
|
||||
|
||||
reparentFieldGui->setSpecialEditVariableName(fldnm);
|
||||
|
||||
reparentFieldGui->setInspectorField(NULL, fldnm);
|
||||
reparentFieldGui->setDocs("");
|
||||
|
||||
stack->addObject(reparentFieldGui);
|
||||
|
||||
GuiButtonCtrl* reparentButton = new GuiButtonCtrl();
|
||||
reparentButton->registerObject();
|
||||
reparentButton->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiButtonProfile");
|
||||
reparentButton->setText("Reparent Out-of-bounds Objs");
|
||||
reparentButton->resize(Point2I::Zero, regenFieldGui->getExtent());
|
||||
reparentButton->setHorizSizing(GuiControl::horizResizeWidth);
|
||||
reparentButton->setVertSizing(GuiControl::vertResizeHeight);
|
||||
|
||||
char rprntBuffer[512];
|
||||
dSprintf(rprntBuffer, 512, "%d.reparentOOBObjects();", this->getId());
|
||||
reparentButton->setConsoleCommand(rprntBuffer);
|
||||
|
||||
reparentFieldGui->addObject(reparentButton);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -279,6 +311,27 @@ void SceneGroup::recalculateBoundingBox()
|
|||
setMaskBits(TransformMask);
|
||||
}
|
||||
|
||||
void SceneGroup::reparentOOBObjects()
|
||||
{
|
||||
if (empty())
|
||||
return;
|
||||
|
||||
// Extend the bounding box to include each child's bounding box
|
||||
for (SimSetIterator itr(this); *itr; ++itr)
|
||||
{
|
||||
SceneObject* child = dynamic_cast<SceneObject*>(*itr);
|
||||
if (child)
|
||||
{
|
||||
const Box3F& childBox = child->getWorldBox();
|
||||
|
||||
if(!mWorldBox.isOverlapped(childBox))
|
||||
{
|
||||
Scene::getRootScene()->addObject(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U32 SceneGroup::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
||||
|
|
@ -363,3 +416,9 @@ DefineEngineMethod(SceneGroup, recalculateBounds, void, (), ,
|
|||
{
|
||||
object->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
DefineEngineMethod(SceneGroup, reparentOOBObjects, void, (), ,
|
||||
"Finds objects that are children of the SceneGroup and, if not overlapping or in the bounds, reparents them to the root scene.\n")
|
||||
{
|
||||
object->reparentOOBObjects();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
void addObject(SimObject* object) override;
|
||||
void removeObject(SimObject* object) override;
|
||||
void recalculateBoundingBox();
|
||||
void reparentOOBObjects();
|
||||
|
||||
///
|
||||
bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& sphere) override;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#include "gui/worldEditor/editor.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "T3D/gameBase/gameBase.h"
|
||||
|
||||
bool SubScene::smTransformChildren = false;
|
||||
|
|
@ -32,7 +34,9 @@ SubScene::SubScene() :
|
|||
mTickPeriodMS(1000),
|
||||
mCurrTick(0),
|
||||
mGlobalLayer(false),
|
||||
mSaving(false)
|
||||
mSaving(false),
|
||||
mUseSeparateLoadBounds(false),
|
||||
mLoadBounds(Point3F::One)
|
||||
{
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
|
|
@ -70,6 +74,8 @@ void SubScene::initPersistFields()
|
|||
INITPERSISTFIELD_SUBSCENEASSET(SubScene, SubScene, "The subscene asset to load.");
|
||||
addField("tickPeriodMS", TypeS32, Offset(mTickPeriodMS, SubScene), "evaluation rate (ms)");
|
||||
addField("gameModes", TypeGameModeList, Offset(mGameModesNames, SubScene), "The game modes that this subscene is associated with.");
|
||||
addField("UseSeparateLoadBounds", TypeBool, Offset(mUseSeparateLoadBounds, SubScene), "If true, this subscene will utilize a separate bounds for triggering loading/unloading than it's object bounds");
|
||||
addField("LoadBounds", TypePoint3F, Offset(mLoadBounds, SubScene), "If UseSeparateLoadBounds is true, this subscene will use this value to set up the load/unload bounds");
|
||||
endGroup("SubScene");
|
||||
|
||||
addGroup("LoadingManagement");
|
||||
|
|
@ -113,6 +119,11 @@ U32 SubScene::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
|
|||
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
||||
|
||||
stream->writeFlag(mGlobalLayer);
|
||||
if(stream->writeFlag(mUseSeparateLoadBounds))
|
||||
{
|
||||
mathWrite(*stream, mLoadBounds);
|
||||
}
|
||||
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
|
@ -123,6 +134,11 @@ void SubScene::unpackUpdate(NetConnection* conn, BitStream* stream)
|
|||
|
||||
mGlobalLayer = stream->readFlag();
|
||||
|
||||
mUseSeparateLoadBounds = stream->readFlag();
|
||||
if(mUseSeparateLoadBounds)
|
||||
{
|
||||
mathRead(*stream, &mLoadBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void SubScene::onInspect(GuiInspector* inspector)
|
||||
|
|
@ -220,7 +236,21 @@ bool SubScene::testBox(const Box3F& testBox)
|
|||
bool passes = mGlobalLayer;
|
||||
|
||||
if (!passes)
|
||||
passes = getWorldBox().isOverlapped(testBox);
|
||||
{
|
||||
if(mUseSeparateLoadBounds)
|
||||
{
|
||||
Box3F loadBox = Box3F(-mLoadBounds.x, -mLoadBounds.y, -mLoadBounds.z,
|
||||
mLoadBounds.x, mLoadBounds.y, mLoadBounds.z);
|
||||
|
||||
loadBox.setCenter(getPosition());
|
||||
|
||||
passes = loadBox.isOverlapped(testBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
passes = getWorldBox().isOverlapped(testBox);
|
||||
}
|
||||
}
|
||||
|
||||
if (passes)
|
||||
passes = evaluateCondition();
|
||||
|
|
@ -268,6 +298,9 @@ void SubScene::processTick(const Move* move)
|
|||
|
||||
void SubScene::_onFileChanged(const Torque::Path& path)
|
||||
{
|
||||
if (gEditingMission)
|
||||
return;
|
||||
|
||||
if(mSubSceneAsset.isNull() || Torque::Path(mSubSceneAsset->getLevelPath()) != path)
|
||||
return;
|
||||
|
||||
|
|
@ -426,7 +459,7 @@ void SubScene::unload()
|
|||
|
||||
}
|
||||
|
||||
bool SubScene::save()
|
||||
bool SubScene::save(const String& filename)
|
||||
{
|
||||
if (!isServerObject())
|
||||
return false;
|
||||
|
|
@ -451,6 +484,9 @@ bool SubScene::save()
|
|||
|
||||
StringTableEntry levelPath = mSubSceneAsset->getLevelPath();
|
||||
|
||||
if (filename.isNotEmpty())
|
||||
levelPath = StringTable->insert(filename.c_str());
|
||||
|
||||
FileStream fs;
|
||||
fs.open(levelPath, Torque::FS::File::Write);
|
||||
fs.close();
|
||||
|
|
@ -547,8 +583,26 @@ void SubScene::renderObject(ObjectRenderInst* ri,
|
|||
//Box3F scale = getScale()
|
||||
//Box3F bounds = Box3F(-m)
|
||||
|
||||
if(mUseSeparateLoadBounds && !mGlobalLayer)
|
||||
{
|
||||
Box3F loadBounds = Box3F(-mLoadBounds.x, -mLoadBounds.y, -mLoadBounds.z,
|
||||
mLoadBounds.x, mLoadBounds.y, mLoadBounds.z);
|
||||
|
||||
//bounds.setCenter(getPosition());
|
||||
|
||||
ColorI loadBoundsColor = ColorI(200, 200, 100, 50);
|
||||
|
||||
drawer->drawCube(desc, loadBounds, loadBoundsColor);
|
||||
|
||||
// Render wireframe.
|
||||
|
||||
desc.setFillModeWireframe();
|
||||
drawer->drawCube(desc, loadBounds, ColorI::BLACK);
|
||||
desc.setFillModeSolid();
|
||||
}
|
||||
|
||||
Point3F scale = getScale();
|
||||
Box3F bounds = Box3F(-scale/2, scale/2);
|
||||
Box3F bounds = Box3F(-scale / 2, scale / 2);
|
||||
|
||||
ColorI boundsColor = ColorI(135, 206, 235, 50);
|
||||
|
||||
|
|
@ -565,10 +619,11 @@ void SubScene::renderObject(ObjectRenderInst* ri,
|
|||
drawer->drawCube(desc, bounds, ColorI::BLACK);
|
||||
}
|
||||
|
||||
DefineEngineMethod(SubScene, save, bool, (),,
|
||||
"Save out the subScene.\n")
|
||||
DefineEngineMethod(SubScene, save, bool, (const char* filename), (""),
|
||||
"Save out the subScene.\n"
|
||||
"@param filename (optional) If empty, the subScene will save to it's regular asset path. If defined, it will save out to the filename provided")
|
||||
{
|
||||
return object->save();
|
||||
return object->save(filename);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ private:
|
|||
|
||||
bool mGlobalLayer;
|
||||
|
||||
bool mUseSeparateLoadBounds;
|
||||
Point3F mLoadBounds;
|
||||
|
||||
public:
|
||||
SubScene();
|
||||
virtual ~SubScene();
|
||||
|
|
@ -118,7 +121,7 @@ public:
|
|||
return mStartUnloadTimerMS;
|
||||
}
|
||||
|
||||
bool save();
|
||||
bool save(const String& filename = String());
|
||||
|
||||
DECLARE_CALLBACK(void, onLoaded, ());
|
||||
DECLARE_CALLBACK(void, onUnloaded, ());
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ AssetImportConfig::AssetImportConfig() :
|
|||
SeparateAnimations(false),
|
||||
SeparateAnimationPrefix(""),
|
||||
animTiming("FrameCount"),
|
||||
animFPS(false),
|
||||
animFPS(30),
|
||||
AlwaysAddShapeAnimationSuffix(true),
|
||||
AddedShapeAnimationSuffix("_anim"),
|
||||
GenerateCollisions(false),
|
||||
|
|
@ -193,7 +193,7 @@ void AssetImportConfig::initPersistFields()
|
|||
addField("SeparateAnimations", TypeBool, Offset(SeparateAnimations, AssetImportConfig), "When importing a shape file, should the animations within be separated out into unique files");
|
||||
addField("SeparateAnimationPrefix", TypeRealString, Offset(SeparateAnimationPrefix, AssetImportConfig), "If separating animations out from a source file, what prefix should be added to the names for grouping association");
|
||||
addField("animTiming", TypeRealString, Offset(animTiming, AssetImportConfig), "Defines the animation timing for the given animation sequence. Options are FrameTime, Seconds, Milliseconds");
|
||||
addField("animFPS", TypeBool, Offset(animFPS, AssetImportConfig), "The FPS of the animation sequence");
|
||||
addField("animFPS", TypeF32, Offset(animFPS, AssetImportConfig), "The FPS of the animation sequence");
|
||||
addField("AlwaysAddShapeAnimationSuffix", TypeBool, Offset(AlwaysAddShapeAnimationSuffix, AssetImportConfig), "When importing a shape animation, this indicates if it should automatically add a standard suffix onto the name");
|
||||
addField("AddedShapeAnimationSuffix", TypeString, Offset(AddedShapeAnimationSuffix, AssetImportConfig), " If AlwaysAddShapeAnimationSuffix is on, this is the suffix to be added");
|
||||
endGroup("Animation");
|
||||
|
|
|
|||
|
|
@ -349,6 +349,14 @@ void GameBase::inspectPostApply()
|
|||
setMaskBits(ExtendedInfoMask);
|
||||
}
|
||||
|
||||
void GameBase::onInspect(GuiInspector* inspector)
|
||||
{
|
||||
if (mDataBlock && mDataBlock->isMethod("onInspect"))
|
||||
Con::executef(mDataBlock, "onInspect", this, inspector);
|
||||
else
|
||||
Parent::onInspect(inspector);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void GameBase::processTick(const Move * move)
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ public:
|
|||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
virtual void onInspect(GuiInspector*) override;
|
||||
|
||||
/// @}
|
||||
|
||||
///@name Datablock
|
||||
|
|
|
|||
|
|
@ -2435,6 +2435,69 @@ AssetManager::typeAssetDependsOnHash* AssetManager::getDependedOnAssets()
|
|||
// Find any asset dependencies.
|
||||
return &mAssetDependsOn;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 AssetManager::getAssetLooseFileCount(const char* pAssetId)
|
||||
{
|
||||
// Debug Profiling.
|
||||
PROFILE_SCOPE(AssetManager_getAssetLooseFileCount);
|
||||
|
||||
// Sanity!
|
||||
AssertFatal(pAssetId != NULL, "Cannot get loose files for NULL asset Id.");
|
||||
|
||||
// Find asset.
|
||||
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
||||
|
||||
// Did we find the asset?
|
||||
if (pAssetDefinition == NULL)
|
||||
{
|
||||
// No, so warn.
|
||||
Con::warnf("Asset Manager: Failed to get loose files for asset Id '%s' as it does not exist.", pAssetId);
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 looseFileCount = pAssetDefinition->mAssetLooseFiles.size();
|
||||
|
||||
// Cleanup our reference
|
||||
pAssetDefinition = NULL;
|
||||
|
||||
return looseFileCount;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char* AssetManager::getAssetLooseFile(const char* pAssetId, const S32& index)
|
||||
{
|
||||
// Debug Profiling.
|
||||
PROFILE_SCOPE(AssetManager_getAssetLooseFile);
|
||||
|
||||
// Sanity!
|
||||
AssertFatal(pAssetId != NULL, "Cannot get loose file for NULL asset Id.");
|
||||
|
||||
// Find asset.
|
||||
AssetDefinition* pAssetDefinition = findAsset(pAssetId);
|
||||
|
||||
// Did we find the asset?
|
||||
if (pAssetDefinition == NULL)
|
||||
{
|
||||
// No, so warn.
|
||||
Con::warnf("Asset Manager: Failed to get loose file for asset Id '%s' as it does not exist.", pAssetId);
|
||||
return StringTable->EmptyString();
|
||||
}
|
||||
|
||||
if(index < 0 || index >= pAssetDefinition->mAssetLooseFiles.size())
|
||||
{
|
||||
Con::warnf("Asset Manager : Failed to get loose file for asset Id '%s' as the index was out of range.", pAssetId);
|
||||
}
|
||||
|
||||
StringTableEntry looseFile = pAssetDefinition->mAssetLooseFiles[index];
|
||||
|
||||
// Cleanup our reference
|
||||
pAssetDefinition = NULL;
|
||||
|
||||
return looseFile;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension, const bool recurse, ModuleDefinition* pModuleDefinition )
|
||||
|
|
|
|||
|
|
@ -376,6 +376,9 @@ public:
|
|||
|
||||
typeAssetDependsOnHash* getDependedOnAssets();
|
||||
|
||||
S32 getAssetLooseFileCount(const char* pAssetId);
|
||||
const char* getAssetLooseFile(const char* pAssetId, const S32& index);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT( AssetManager );
|
||||
|
||||
|
|
|
|||
|
|
@ -763,6 +763,36 @@ DefineEngineMethod(AssetManager, findAssetLooseFile, S32, (const char* assetQuer
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod(AssetManager, getAssetLooseFileCount, S32, (const char* assetId), (""),
|
||||
"Gets the number of loose files associated with the given assetId.\n"
|
||||
"@param assetId The assetId to check.\n"
|
||||
"@return The number of loose files associated with the assetId.\n")
|
||||
{
|
||||
// Fetch asset loose file.
|
||||
const char* pAssetId = assetId;
|
||||
|
||||
// Perform query.
|
||||
return object->getAssetLooseFileCount(pAssetId);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod(AssetManager, getAssetLooseFile, const char*, (const char* assetId, S32 index), ("", 0),
|
||||
"Gets the loose file associated to the given assetId at the provided index.\n"
|
||||
"@param assetId The assetId to check.\n"
|
||||
"@param index The index of the loose file to get.\n"
|
||||
"@return The file name of the associated loose file.\n")
|
||||
{
|
||||
|
||||
// Fetch asset loose file.
|
||||
const char* pAssetId = assetId;
|
||||
|
||||
// Perform query.
|
||||
return object->getAssetLooseFile(pAssetId, index);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod(AssetManager, getDeclaredAssetCount, bool, (),,
|
||||
"Gets the number of declared assets.\n"
|
||||
"@return Returns the number of declared assets.\n")
|
||||
|
|
|
|||
|
|
@ -118,9 +118,10 @@ public:
|
|||
|
||||
/// Called from Forest the first time a datablock is used
|
||||
/// in order to lazy load content.
|
||||
void preload()
|
||||
{
|
||||
if ( !mNeedPreload )
|
||||
bool preload(bool server, String& errorStr) override { return false; }; // we don't ghost ForestItemData specifically. we do do so for TSForestItemData
|
||||
void preload()
|
||||
{
|
||||
if (!mNeedPreload)
|
||||
return;
|
||||
|
||||
_preload();
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ void GuiIconButtonCtrl::renderButton( Point2I &offset, const RectI& updateRect )
|
|||
Point2I start( mTextMargin, ( getHeight() - mProfile->mFont->getHeight() ) / 2 );
|
||||
if (mBitmapAsset.notNull() && mIconLocation != IconLocNone)
|
||||
{
|
||||
start.x = iconRect.extent.x + mButtonMargin.x + mTextMargin;
|
||||
start.x = getWidth() - (iconRect.extent.x + mButtonMargin.x + textWidth);
|
||||
}
|
||||
|
||||
drawer->setBitmapModulation(fontColor);
|
||||
|
|
|
|||
|
|
@ -2855,6 +2855,23 @@ DefineEngineMethod( GuiControl, getGlobalCenter, Point2I, (),,
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod(GuiControl, setGlobalCenter, void, (S32 x, S32 y), ,
|
||||
"Set the coordinate of the control's center point in coordinates relative to the root control in its control hierarchy.\n"
|
||||
"@param x The X coordinate of the new center point of the control relative to the root control's.\n"
|
||||
"@param y The Y coordinate of the new center point of the control relative to the root control's.")
|
||||
{
|
||||
//see if we can turn the x/y into ints directly,
|
||||
Point2I lPosOffset = object->globalToLocalCoord(Point2I(x, y));
|
||||
|
||||
lPosOffset += object->getPosition();
|
||||
|
||||
const Point2I ext = object->getExtent();
|
||||
Point2I newpos(lPosOffset.x - ext.x / 2, lPosOffset.y - ext.y / 2);
|
||||
object->setPosition(newpos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiControl, getGlobalPosition, Point2I, (),,
|
||||
"Get the position of the control relative to the root of the GuiControl hierarchy it is contained in.\n"
|
||||
"@return The control's current position in root-relative coordinates." )
|
||||
|
|
|
|||
|
|
@ -133,6 +133,25 @@ void GuiInputCtrl::onSleep()
|
|||
clearFirstResponder();
|
||||
}
|
||||
|
||||
void GuiInputCtrl::setActive(bool value)
|
||||
{
|
||||
Parent::setActive(value);
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (!smDesignTime && !mIgnoreMouseEvents)
|
||||
mouseLock();
|
||||
|
||||
setFirstResponder();
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseUnlock();
|
||||
clearFirstResponder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isModifierKey( U16 keyCode )
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ public:
|
|||
bool onWake() override;
|
||||
void onSleep() override;
|
||||
|
||||
virtual void setActive(bool state);
|
||||
|
||||
bool onInputEvent( const InputEventInfo &event ) override;
|
||||
|
||||
static void initPersistFields();
|
||||
|
|
|
|||
|
|
@ -1409,3 +1409,13 @@ DefineEngineMethod( EditTSCtrl, isMiddleMouseDown, bool, (),, "" )
|
|||
{
|
||||
return object->isMiddleMouseDown();
|
||||
}
|
||||
|
||||
DefineEngineMethod(EditTSCtrl, isLeftMouseDown, bool, (), , "")
|
||||
{
|
||||
return object->isLeftMouseDown();
|
||||
}
|
||||
|
||||
DefineEngineMethod(EditTSCtrl, isRightMouseDown, bool, (), , "")
|
||||
{
|
||||
return object->isRightMouseDown();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,7 +189,9 @@ class EditTSCtrl : public GuiTSCtrl
|
|||
virtual void on3DMouseWheelDown(const Gui3DMouseEvent &){};
|
||||
virtual void get3DCursor(GuiCursor *&cursor, bool &visible, const Gui3DMouseEvent &);
|
||||
|
||||
virtual bool isLeftMouseDown() { return mLeftMouseDown; }
|
||||
virtual bool isMiddleMouseDown() {return mMiddleMouseDown;}
|
||||
virtual bool isRightMouseDown() { return mLeftMouseDown; }
|
||||
|
||||
bool resize(const Point2I& newPosition, const Point2I& newExtent) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ void AssimpAppMesh::computeBounds(Box3F& bounds)
|
|||
|
||||
TSMesh* AssimpAppMesh::constructTSMesh()
|
||||
{
|
||||
if (points.empty() || normals.empty() || primitives.empty() || indices.empty())
|
||||
return NULL;
|
||||
|
||||
TSMesh* tsmesh;
|
||||
if (isSkin())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ void AppMesh::computeNormals()
|
|||
|
||||
TSMesh* AppMesh::constructTSMesh()
|
||||
{
|
||||
if (points.empty() || normals.empty() || primitives.empty() || indices.empty())
|
||||
return NULL;
|
||||
|
||||
TSMesh* tsmesh;
|
||||
if (isSkin())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ function loadMissionStage3()
|
|||
function GameBase::onCreateGame(%this)
|
||||
{
|
||||
%db = %this.getDatablock();
|
||||
if (%db.isMethod("onCreateGame"))
|
||||
if (isObject(%db) && %db.isMethod("onCreateGame"))
|
||||
{
|
||||
%db.onCreateGame(%this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1199,140 +1199,169 @@ function AutodetectGraphics()
|
|||
%intel = ( strstr( strupr( getDisplayDeviceInformation() ), "INTEL" ) != -1 ) ? true : false;
|
||||
%videoMem = GFXCardProfilerAPI::getVideoMemoryMB();
|
||||
|
||||
if ( %shaderVer < 2.0 )
|
||||
{
|
||||
echo("Your video card does not meet the minimum requirment of shader model 2.0.");
|
||||
}
|
||||
|
||||
if ( %shaderVer < 3.0 || %intel )
|
||||
//Is this a steamdeck?
|
||||
if(startsWith(getDisplayDeviceInformation(), "AMD Custom GPU 0405"))
|
||||
{
|
||||
// Allow specular and normals for 2.0a and 2.0b
|
||||
if ( %shaderVer > 2.0 )
|
||||
{
|
||||
MeshQualityGroup.applySetting("Lowest");
|
||||
TextureQualityGroup.applySetting("Lowest");
|
||||
GroundCoverDensityGroup.applySetting("Lowest");
|
||||
DecalLifetimeGroup.applySetting("None");
|
||||
TerrainQualityGroup.applySetting("Lowest");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("Off");
|
||||
ParallaxOptionsGroup.applySetting("Off");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("Off");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshQualityGroup.applySetting("Lowest");
|
||||
TextureQualityGroup.applySetting("Lowest");
|
||||
GroundCoverDensityGroup.applySetting("Lowest");
|
||||
DecalLifetimeGroup.applySetting("None");
|
||||
TerrainQualityGroup.applySetting("Lowest");
|
||||
ShaderQualityGroup.applySetting("Low");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("Off");
|
||||
ParallaxOptionsGroup.applySetting("Off");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("Off");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
}
|
||||
}
|
||||
//If we're on a steamdeck, we can specifically calibrate settings for the platform here
|
||||
MeshQualityGroup.applySetting("Medium");
|
||||
TextureQualityGroup.applySetting("Medium");
|
||||
GroundCoverDensityGroup.applySetting("Medium");
|
||||
DecalLifetimeGroup.applySetting("Medium");
|
||||
TerrainQualityGroup.applySetting("Medium");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Low");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("4x");
|
||||
AntiAliasingOptionsGroup.applySetting("SMAA");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("On");
|
||||
PostFXVignetteOptionsGroup.applySetting("On");
|
||||
PostFXLightRayOptionsGroup.applySetting("On");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( %videoMem > 1000 )
|
||||
{
|
||||
MeshQualityGroup.applySetting("High");
|
||||
TextureQualityGroup.applySetting("High");
|
||||
GroundCoverDensityGroup.applySetting("High");
|
||||
DecalLifetimeGroup.applySetting("High");
|
||||
TerrainQualityGroup.applySetting("High");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("High");
|
||||
|
||||
SoftShadowList.applySetting("High");
|
||||
|
||||
//Should this default to on in ultra settings?
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("16x");
|
||||
AntiAliasingOptionsGroup.applySetting("SMAA High");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("On");
|
||||
PostFXDOFOptionsGroup.applySetting("On");
|
||||
PostFXVignetteOptionsGroup.applySetting("On");
|
||||
PostFXLightRayOptionsGroup.applySetting("On");
|
||||
if ( %shaderVer < 2.0 )
|
||||
{
|
||||
echo("Your video card does not meet the minimum requirment of shader model 2.0.");
|
||||
}
|
||||
else if ( %videoMem > 400 || %videoMem == 0 )
|
||||
|
||||
if ( %shaderVer < 3.0 || %intel )
|
||||
{
|
||||
MeshQualityGroup.applySetting("Medium");
|
||||
TextureQualityGroup.applySetting("Medium");
|
||||
GroundCoverDensityGroup.applySetting("Medium");
|
||||
DecalLifetimeGroup.applySetting("Medium");
|
||||
TerrainQualityGroup.applySetting("Medium");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("Medium");
|
||||
|
||||
SoftShadowList.applySetting("Low");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("4x");
|
||||
AntiAliasingOptionsGroup.applySetting("SMAA");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("On");
|
||||
PostFXVignetteOptionsGroup.applySetting("On");
|
||||
PostFXLightRayOptionsGroup.applySetting("On");
|
||||
|
||||
if ( %videoMem == 0 )
|
||||
echo("Torque was unable to detect available video memory. Applying 'Medium' quality.");
|
||||
}
|
||||
// Allow specular and normals for 2.0a and 2.0b
|
||||
if ( %shaderVer > 2.0 )
|
||||
{
|
||||
MeshQualityGroup.applySetting("Lowest");
|
||||
TextureQualityGroup.applySetting("Lowest");
|
||||
GroundCoverDensityGroup.applySetting("Lowest");
|
||||
DecalLifetimeGroup.applySetting("None");
|
||||
TerrainQualityGroup.applySetting("Lowest");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("Off");
|
||||
ParallaxOptionsGroup.applySetting("Off");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("Off");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshQualityGroup.applySetting("Lowest");
|
||||
TextureQualityGroup.applySetting("Lowest");
|
||||
GroundCoverDensityGroup.applySetting("Lowest");
|
||||
DecalLifetimeGroup.applySetting("None");
|
||||
TerrainQualityGroup.applySetting("Lowest");
|
||||
ShaderQualityGroup.applySetting("Low");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("Off");
|
||||
ParallaxOptionsGroup.applySetting("Off");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("Off");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshQualityGroup.applySetting("Low");
|
||||
TextureQualityGroup.applySetting("Low");
|
||||
GroundCoverDensityGroup.applySetting("Low");
|
||||
DecalLifetimeGroup.applySetting("Low");
|
||||
TerrainQualityGroup.applySetting("Low");
|
||||
ShaderQualityGroup.applySetting("Low");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("FXAA");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
if ( %videoMem > 1000 )
|
||||
{
|
||||
MeshQualityGroup.applySetting("High");
|
||||
TextureQualityGroup.applySetting("High");
|
||||
GroundCoverDensityGroup.applySetting("High");
|
||||
DecalLifetimeGroup.applySetting("High");
|
||||
TerrainQualityGroup.applySetting("High");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("High");
|
||||
|
||||
SoftShadowList.applySetting("High");
|
||||
|
||||
//Should this default to on in ultra settings?
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("16x");
|
||||
AntiAliasingOptionsGroup.applySetting("SMAA High");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("On");
|
||||
PostFXDOFOptionsGroup.applySetting("On");
|
||||
PostFXVignetteOptionsGroup.applySetting("On");
|
||||
PostFXLightRayOptionsGroup.applySetting("On");
|
||||
}
|
||||
else if ( %videoMem > 400 || %videoMem == 0 )
|
||||
{
|
||||
MeshQualityGroup.applySetting("Medium");
|
||||
TextureQualityGroup.applySetting("Medium");
|
||||
GroundCoverDensityGroup.applySetting("Medium");
|
||||
DecalLifetimeGroup.applySetting("Medium");
|
||||
TerrainQualityGroup.applySetting("Medium");
|
||||
ShaderQualityGroup.applySetting("High");
|
||||
|
||||
ShadowQualityList.applySetting("Medium");
|
||||
|
||||
SoftShadowList.applySetting("Low");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("4x");
|
||||
AntiAliasingOptionsGroup.applySetting("SMAA");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("On");
|
||||
PostFXVignetteOptionsGroup.applySetting("On");
|
||||
PostFXLightRayOptionsGroup.applySetting("On");
|
||||
|
||||
if ( %videoMem == 0 )
|
||||
echo("Torque was unable to detect available video memory. Applying 'Medium' quality.");
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshQualityGroup.applySetting("Low");
|
||||
TextureQualityGroup.applySetting("Low");
|
||||
GroundCoverDensityGroup.applySetting("Low");
|
||||
DecalLifetimeGroup.applySetting("Low");
|
||||
TerrainQualityGroup.applySetting("Low");
|
||||
ShaderQualityGroup.applySetting("Low");
|
||||
|
||||
ShadowQualityList.applySetting("None");
|
||||
|
||||
SoftShadowList.applySetting("Off");
|
||||
|
||||
$pref::Shadows::useShadowCaching = true;
|
||||
|
||||
AnisotropicFilterOptionsGroup.applySetting("None");
|
||||
AntiAliasingOptionsGroup.applySetting("FXAA");
|
||||
ParallaxOptionsGroup.applySetting("On");
|
||||
TrueWaterReflectionsOptionsGroup.applySetting("On");
|
||||
PostFXSSAOOptionsGroup.applySetting("Off");
|
||||
PostFXDOFOptionsGroup.applySetting("Off");
|
||||
PostFXVignetteOptionsGroup.applySetting("Off");
|
||||
PostFXLightRayOptionsGroup.applySetting("Off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,7 @@
|
|||
<Setting
|
||||
name="AutomaticallyPromptMissingFiles">0</Setting>
|
||||
<Setting
|
||||
name="DuplicatAutoResolution">AutoPrune</Setting>
|
||||
<Setting
|
||||
name="DuplicateAutoResolution">FolderPrefix</Setting>
|
||||
name="DuplicateAutoResolution">AutoPrune</Setting>
|
||||
<Setting
|
||||
name="PreventImportWithErrors">1</Setting>
|
||||
<Setting
|
||||
|
|
|
|||
|
|
@ -99,6 +99,52 @@ function LevelAsset::onEdit(%this)
|
|||
schedule( 1, 0, "EditorOpenMission", %this);
|
||||
}
|
||||
|
||||
function LevelAsset::onShowActionMenu(%this)
|
||||
{
|
||||
if( !isObject( EditLevelAssetPopup ) )
|
||||
{
|
||||
new PopupMenu( EditLevelAssetPopup )
|
||||
{
|
||||
superClass = "MenuBuilder";
|
||||
class = "EditorWorldMenu";
|
||||
|
||||
jumpFileName = "";
|
||||
jumpLineNumber = "";
|
||||
};
|
||||
}
|
||||
|
||||
//Regen the menu so we're fully up and current with options and references
|
||||
EditLevelAssetPopup.clearItems();
|
||||
|
||||
EditLevelAssetPopup.appendItem("Edit Asset" TAB "" TAB $CurrentAssetBrowser @ ".editAsset();");
|
||||
EditLevelAssetPopup.appendItem("Rename Asset" TAB "" TAB $CurrentAssetBrowser @ ".renameAsset();");
|
||||
EditLevelAssetPopup.appendItem("Reload Asset" TAB "" TAB $CurrentAssetBrowser @ ".refreshAsset();");
|
||||
EditLevelAssetPopup.appendItem("Asset Properties" TAB "" TAB $CurrentAssetBrowser @ ".editAssetInfo();");
|
||||
EditLevelAssetPopup.appendItem("-");
|
||||
EditLevelAssetPopup.appendItem("Duplicate Asset" TAB "" TAB $CurrentAssetBrowser @ ".duplicateAsset();");
|
||||
EditLevelAssetPopup.appendItem("-");
|
||||
EditLevelAssetPopup.appendItem("Regenerate Preview Image" TAB "" TAB $CurrentAssetBrowser @ ".regeneratePreviewImage();");
|
||||
EditLevelAssetPopup.appendItem("-");
|
||||
EditLevelAssetPopup.appendItem("Restore Backup" TAB RestoreBackupListPopup);
|
||||
EditLevelAssetPopup.appendItem("-");
|
||||
EditLevelAssetPopup.appendItem("Open File Location" TAB "" TAB $CurrentAssetBrowser @ ".openFileLocation();");
|
||||
EditLevelAssetPopup.appendItem("-");
|
||||
EditLevelAssetPopup.appendItem("Delete Asset" TAB "" TAB $CurrentAssetBrowser @ ".deleteAsset();");
|
||||
|
||||
%assetId = %this.getAssetId();
|
||||
%assetType = AssetDatabase.getAssetType(%assetId);
|
||||
|
||||
EditLevelAssetPopup.objectData = %assetId;
|
||||
EditLevelAssetPopup.objectType = %assetType;
|
||||
|
||||
RestoreBackupListPopup.populateList(%assetId);
|
||||
EditLevelAssetPopup.reloadItems();
|
||||
|
||||
EditLevelAssetPopup.showPopup(Canvas);
|
||||
|
||||
$CurrentAssetBrowser.popupMenu = EditLevelAssetPopup;
|
||||
}
|
||||
|
||||
function LevelAsset::buildBrowserElement(%this, %previewData)
|
||||
{
|
||||
%previewData.assetName = %this.assetName;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,52 @@ function SubSceneAsset::onCreateNew(%this)
|
|||
return %tamlpath;
|
||||
}
|
||||
|
||||
function SubSceneAsset::onShowActionMenu(%this)
|
||||
{
|
||||
if( !isObject( EditSubSceneAssetPopup ) )
|
||||
{
|
||||
new PopupMenu( EditSubSceneAssetPopup )
|
||||
{
|
||||
superClass = "MenuBuilder";
|
||||
class = "EditorWorldMenu";
|
||||
|
||||
jumpFileName = "";
|
||||
jumpLineNumber = "";
|
||||
};
|
||||
}
|
||||
|
||||
//Regen the menu so we're fully up and current with options and references
|
||||
EditSubSceneAssetPopup.clearItems();
|
||||
|
||||
EditSubSceneAssetPopup.appendItem("Edit Asset" TAB "" TAB $CurrentAssetBrowser @ ".editAsset();");
|
||||
EditSubSceneAssetPopup.appendItem("Rename Asset" TAB "" TAB $CurrentAssetBrowser @ ".renameAsset();");
|
||||
EditSubSceneAssetPopup.appendItem("Reload Asset" TAB "" TAB $CurrentAssetBrowser @ ".refreshAsset();");
|
||||
EditSubSceneAssetPopup.appendItem("Asset Properties" TAB "" TAB $CurrentAssetBrowser @ ".editAssetInfo();");
|
||||
EditSubSceneAssetPopup.appendItem("-");
|
||||
EditSubSceneAssetPopup.appendItem("Duplicate Asset" TAB "" TAB $CurrentAssetBrowser @ ".duplicateAsset();");
|
||||
EditSubSceneAssetPopup.appendItem("-");
|
||||
EditSubSceneAssetPopup.appendItem("Regenerate Preview Image" TAB "" TAB $CurrentAssetBrowser @ ".regeneratePreviewImage();");
|
||||
EditSubSceneAssetPopup.appendItem("-");
|
||||
EditSubSceneAssetPopup.appendItem("Restore Backup" TAB RestoreBackupListPopup);
|
||||
EditSubSceneAssetPopup.appendItem("-");
|
||||
EditSubSceneAssetPopup.appendItem("Open File Location" TAB "" TAB $CurrentAssetBrowser @ ".openFileLocation();");
|
||||
EditSubSceneAssetPopup.appendItem("-");
|
||||
EditSubSceneAssetPopup.appendItem("Delete Asset" TAB "" TAB $CurrentAssetBrowser @ ".deleteAsset();");
|
||||
|
||||
%assetId = %this.getAssetId();
|
||||
%assetType = AssetDatabase.getAssetType(%assetId);
|
||||
|
||||
EditSubSceneAssetPopup.objectData = %assetId;
|
||||
EditSubSceneAssetPopup.objectType = %assetType;
|
||||
|
||||
RestoreBackupListPopup.populateList(%assetId);
|
||||
EditSubSceneAssetPopup.reloadItems();
|
||||
|
||||
EditSubSceneAssetPopup.showPopup(Canvas);
|
||||
|
||||
$CurrentAssetBrowser.popupMenu = EditSubSceneAssetPopup;
|
||||
}
|
||||
|
||||
function SubSceneAsset::buildBrowserElement(%this, %previewData)
|
||||
{
|
||||
%previewData.assetName = %this.assetName;
|
||||
|
|
|
|||
|
|
@ -132,6 +132,49 @@ function createTerrainBlock(%assetId)
|
|||
//
|
||||
}
|
||||
|
||||
function TerrainAsset::onShowActionMenu(%this)
|
||||
{
|
||||
if( !isObject( EditTerrainAssetPopup ) )
|
||||
{
|
||||
new PopupMenu( EditTerrainAssetPopup )
|
||||
{
|
||||
superClass = "MenuBuilder";
|
||||
class = "EditorWorldMenu";
|
||||
|
||||
jumpFileName = "";
|
||||
jumpLineNumber = "";
|
||||
};
|
||||
}
|
||||
|
||||
//Regen the menu so we're fully up and current with options and references
|
||||
EditTerrainAssetPopup.clearItems();
|
||||
|
||||
EditTerrainAssetPopup.appendItem("Edit Asset" TAB "" TAB $CurrentAssetBrowser @ ".editAsset();");
|
||||
EditTerrainAssetPopup.appendItem("Rename Asset" TAB "" TAB $CurrentAssetBrowser @ ".renameAsset();");
|
||||
EditTerrainAssetPopup.appendItem("Reload Asset" TAB "" TAB $CurrentAssetBrowser @ ".refreshAsset();");
|
||||
EditTerrainAssetPopup.appendItem("Asset Properties" TAB "" TAB $CurrentAssetBrowser @ ".editAssetInfo();");
|
||||
EditTerrainAssetPopup.appendItem("-");
|
||||
EditTerrainAssetPopup.appendItem("Duplicate Asset" TAB "" TAB $CurrentAssetBrowser @ ".duplicateAsset();");
|
||||
EditTerrainAssetPopup.appendItem("-");
|
||||
EditTerrainAssetPopup.appendItem("Restore Backup" TAB RestoreBackupListPopup);
|
||||
EditTerrainAssetPopup.appendItem("-");
|
||||
EditTerrainAssetPopup.appendItem("Open File Location" TAB "" TAB $CurrentAssetBrowser @ ".openFileLocation();");
|
||||
EditTerrainAssetPopup.appendItem("-");
|
||||
EditTerrainAssetPopup.appendItem("Delete Asset" TAB "" TAB $CurrentAssetBrowser @ ".deleteAsset();");
|
||||
|
||||
%assetId = %this.getAssetId();
|
||||
%assetType = AssetDatabase.getAssetType(%assetId);
|
||||
|
||||
EditTerrainAssetPopup.objectData = %assetId;
|
||||
EditTerrainAssetPopup.objectType = %assetType;
|
||||
|
||||
RestoreBackupListPopup.populateList(%assetId);
|
||||
EditTerrainAssetPopup.reloadItems();
|
||||
|
||||
EditTerrainAssetPopup.showPopup(Canvas);
|
||||
|
||||
$CurrentAssetBrowser.popupMenu = EditTerrainAssetPopup;
|
||||
}
|
||||
|
||||
function TerrainAsset::onWorldEditorDropped(%this, %position)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -520,4 +520,87 @@ function AssetBrowser::openFolderLocation(%this, %folderPath)
|
|||
systemCommand(%cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
function AssetBrowser::getAssetBackupCount(%this, %assetId)
|
||||
{
|
||||
//process it and then check if we have any autosave backups
|
||||
%processedId = strReplace(EditAssetPopup.assetId, ":", "_");
|
||||
%autosavePath = "tools/autosave/" @ %processedId @ "/";
|
||||
|
||||
RestoreBackupListPopup.clearItems();
|
||||
|
||||
if(isDirectory(%autosavePath))
|
||||
{
|
||||
%dirs = getDirectoryList(%autosavePath);
|
||||
%count = getFieldCount(%dirs);
|
||||
|
||||
return %count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function AssetBrowser::restoreAssetBackup(%this, %assetId, %index)
|
||||
{
|
||||
if(!AssetDatabase.isDeclaredAsset(%assetId))
|
||||
{
|
||||
error("AssetBrowser::restoreAssetBackup() - Attempted to restore backed up version of asset: " @ %assetId @ " but asset is not validly declared!");
|
||||
return;
|
||||
}
|
||||
|
||||
//process it and then check if we have any autosave backups
|
||||
%processedId = strReplace(%assetId, ":", "_");
|
||||
%autosavePath = "tools/autosave/" @ %processedId @ "/";
|
||||
|
||||
if(isDirectory(%autosavePath))
|
||||
{
|
||||
%dirs = getDirectoryList(%autosavePath);
|
||||
%count = getFieldCount(%dirs);
|
||||
if(%count > 0)
|
||||
{
|
||||
%saveArray = new ArrayObject(){};
|
||||
//loop over the entries and find the oldest one
|
||||
for(%f=0; %f < %count; %f++)
|
||||
{
|
||||
%saveArray.add(getField(%dirs, %f));
|
||||
}
|
||||
|
||||
%saveArray.sortk();
|
||||
|
||||
%folderName = %saveArray.getKey(%index);
|
||||
|
||||
//now we just copy the contents of the folder into our assetId path and refresh
|
||||
%assetPath = AssetDatabase.getAssetPath(%assetId);
|
||||
|
||||
%autosaveFullPath = %autosavePath @ "/" @ %folderName @ "/";
|
||||
%autosaveFullPath = strReplace(%autosaveFullPath, "//", "/");
|
||||
|
||||
%file = findFirstFile( %autosaveFullPath @ "*.*" );
|
||||
while( %file !$= "" )
|
||||
{
|
||||
%fileName = fileName(%file);
|
||||
%assetFileName = %assetPath @ "/" @ %fileName;
|
||||
|
||||
warn("| Copying file from: " @ %file @ " to: " @ %assetFileName);
|
||||
if(!pathCopy(%file, %assetFileName, false))
|
||||
{
|
||||
error("AssetBrowser::restoreAssetBackup() - Something went wrong when copying the file: " @ %file @ " to " @ %assetFileName);
|
||||
}
|
||||
|
||||
%file = findNextFile( %autosaveFullPath @ "*.*" );
|
||||
}
|
||||
|
||||
AssetBrowser.reloadAsset(%assetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("AssetBrowser::restoreAssetBackup() - Attempted to restore backed up version of asset: " @ %assetId @ " but no autosaves were found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error("AssetBrowser::restoreAssetBackup() - Attempted to restore backed up version of asset: " @ %assetId @ " but autosave directory doesn't exist!");
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,18 @@ function AssetBrowser::buildPopupMenus(%this)
|
|||
};
|
||||
}
|
||||
|
||||
if( !isObject( RestoreBackupListPopup ) )
|
||||
{
|
||||
new PopupMenu( RestoreBackupListPopup )
|
||||
{
|
||||
superClass = "MenuBuilder";
|
||||
class = "EditorWorldMenu";
|
||||
//isPopup = true;
|
||||
|
||||
radioSelection = false;
|
||||
};
|
||||
}
|
||||
|
||||
if( !isObject( EditLevelAssetPopup ) )
|
||||
{
|
||||
new PopupMenu( EditLevelAssetPopup )
|
||||
|
|
@ -59,9 +71,11 @@ function AssetBrowser::buildPopupMenus(%this)
|
|||
item[ 5 ] = "-";
|
||||
Item[ 6 ] = "Duplicate Asset" TAB "" TAB "AssetBrowser.duplicateAsset();";
|
||||
item[ 7 ] = "-";
|
||||
item[ 8 ] = "Open File Location" TAB "" TAB "AssetBrowser.openFileLocation();";
|
||||
Item[ 8 ] = "Restore Backup" TAB RestoreBackupListPopup;
|
||||
item[ 9 ] = "-";
|
||||
item[ 10 ] = "Delete Asset" TAB "" TAB "AssetBrowser.deleteAsset();";
|
||||
item[ 10 ] = "Open File Location" TAB "" TAB "AssetBrowser.openFileLocation();";
|
||||
item[ 11 ] = "-";
|
||||
item[ 12 ] = "Delete Asset" TAB "" TAB "AssetBrowser.deleteAsset();";
|
||||
|
||||
jumpFileName = "";
|
||||
jumpLineNumber = "";
|
||||
|
|
@ -82,9 +96,11 @@ function AssetBrowser::buildPopupMenus(%this)
|
|||
item[ 3 ] = "-";
|
||||
Item[ 4 ] = "Duplicate Asset" TAB "" TAB "AssetBrowser.duplicateAsset();";
|
||||
item[ 5 ] = "-";
|
||||
item[ 6 ] = "Open File Location" TAB "" TAB "AssetBrowser.openFileLocation();";
|
||||
Item[ 6 ] = "Restore Backup" TAB RestoreBackupListPopup;
|
||||
item[ 7 ] = "-";
|
||||
item[ 8 ] = "Delete Asset" TAB "" TAB "AssetBrowser.deleteAsset();";
|
||||
item[ 8 ] = "Open File Location" TAB "" TAB "AssetBrowser.openFileLocation();";
|
||||
item[ 9 ] = "-";
|
||||
item[ 10 ] = "Delete Asset" TAB "" TAB "AssetBrowser.deleteAsset();";
|
||||
|
||||
jumpFileName = "";
|
||||
jumpLineNumber = "";
|
||||
|
|
@ -398,3 +414,41 @@ function AddNewScriptAssetPopupMenu::setupDefaultState(%this)
|
|||
function AddNewScriptAssetPopupMenu::setupGuiControls(%this)
|
||||
{
|
||||
}
|
||||
|
||||
function RestoreBackupListPopup::populateList(%this, %assetId)
|
||||
{
|
||||
//process it and then check if we have any autosave backups
|
||||
%processedId = strReplace(%assetId, ":", "_");
|
||||
%autosavePath = "tools/autosave/" @ %processedId @ "/";
|
||||
|
||||
RestoreBackupListPopup.clearItems();
|
||||
|
||||
if(isDirectory(%autosavePath))
|
||||
{
|
||||
%dirs = getDirectoryList(%autosavePath);
|
||||
%count = getFieldCount(%dirs);
|
||||
|
||||
if(%count > 0)
|
||||
{
|
||||
%saveArray = new ArrayObject(){};
|
||||
//loop over the entries and find the oldest one
|
||||
for(%f=0; %f < %count; %f++)
|
||||
{
|
||||
%saveArray.add(getField(%dirs, %f));
|
||||
}
|
||||
|
||||
%saveArray.sortk();
|
||||
|
||||
for(%i=0; %i < %count; %i++)
|
||||
{
|
||||
%folderName = %saveArray.getKey(%i);
|
||||
%labelText = %folderName @ " (" @ fileModifiedTime(%autosavePath @ %folderName) @ ")";
|
||||
RestoreBackupListPopup.addItem(%i, %labelText TAB "" TAB "AssetBrowser.restoreAssetBackup(\"" @ %assetId @ "\"," @ %i @ ");");
|
||||
|
||||
echo("Added restore item: " @ %labelText TAB "" TAB "AssetBrowser.restoreAssetBackup(\"" @ %assetId @ "\"," @ %i @ ");");
|
||||
}
|
||||
|
||||
%saveArray.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,11 +333,13 @@ function MenuBuilder::addItem(%this, %pos, %item)
|
|||
{
|
||||
%this.insertItem(%pos, %name !$= "-" ? %name : "", %accel, %cmd, %bitmapIdx $= "" ? -1 : %bitmapIdx);
|
||||
}
|
||||
|
||||
return %pos;
|
||||
}
|
||||
|
||||
function MenuBuilder::appendItem(%this, %item)
|
||||
{
|
||||
%this.addItem(%this.getItemCount(), %item);
|
||||
return %this.addItem(%this.getItemCount(), %item);
|
||||
}
|
||||
|
||||
function MenuBuilder::onAdd(%this)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
<Setting
|
||||
name="doubleClickAction">Edit Asset</Setting>
|
||||
<Setting
|
||||
name="LastPosExt">0 634 1560 360</Setting>
|
||||
name="LastPosExt">0 1047 2200 360</Setting>
|
||||
<Setting
|
||||
name="previewTileSize">1</Setting>
|
||||
<Setting
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
<Group
|
||||
name="Grid">
|
||||
<Setting
|
||||
name="forceSnapRotations">1</Setting>
|
||||
name="forceSnapRotations">0</Setting>
|
||||
<Setting
|
||||
name="gridColor">255 255 255 20</Setting>
|
||||
<Setting
|
||||
|
|
@ -210,7 +210,7 @@
|
|||
<Setting
|
||||
name="backgroundBuild">1</Setting>
|
||||
<Setting
|
||||
name="SpawnClass">AIPlayer</Setting>
|
||||
name="SpawnClass">Player</Setting>
|
||||
<Setting
|
||||
name="spawnDatablock">DefaultPlayerData</Setting>
|
||||
</Group>
|
||||
|
|
@ -276,7 +276,7 @@
|
|||
<Group
|
||||
name="TerrainEditor">
|
||||
<Setting
|
||||
name="currentAction">lowerHeight</Setting>
|
||||
name="currentAction">raiseHeight</Setting>
|
||||
<Group
|
||||
name="ActionValues">
|
||||
<Setting
|
||||
|
|
@ -367,6 +367,8 @@
|
|||
name="dropType">screenCenter</Setting>
|
||||
<Setting
|
||||
name="EditorLayoutMode">Modern</Setting>
|
||||
<Setting
|
||||
name="forceLoadDAE">0</Setting>
|
||||
<Setting
|
||||
name="forceSidebarToSide">1</Setting>
|
||||
<Setting
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ function simGroup::onInspectPostApply(%this)
|
|||
%this.callOnChildren("setLocked",%this.locked);
|
||||
}
|
||||
|
||||
function simGroup::SelectFiteredObjects(%this, %min, %max)
|
||||
function simGroup::SelectFilteredObjects(%this, %min, %max)
|
||||
{
|
||||
EWorldEditor.clearSelection();
|
||||
%this.callOnChildren("filteredSelect", %min, %max );
|
||||
|
|
@ -577,16 +577,29 @@ function SceneObject::filteredSelect(%this, %min, %max)
|
|||
|
||||
function simGroup::onInspect(%obj, %inspector)
|
||||
{
|
||||
//Find the 'Editing' group in the inspector
|
||||
%group = %inspector.findExistentGroup("Editing");
|
||||
if(isObject(%group))
|
||||
if(%obj.isInNamespaceHierarchy("SceneGroup") || %obj.isInNamespaceHierarchy("SubScene"))
|
||||
{
|
||||
//We add a field of the type 'SimGroupSelectionButton'. This isn't a 'real' type, so when the inspector group tries to add it
|
||||
//it will route down through GuiInspectorGroup(the namespace of %group) and call onConstructField in an attemp to see if there's any
|
||||
//script defined functions that can build a field of that type.
|
||||
//We happen to define the required 'build @ <fieldTypeName> @ Field()' function below, allowing us to build out the custom field type
|
||||
%group.addField("Select Objects", "SimGroupSelectionButton", "Select filtered objects");
|
||||
}
|
||||
//Find the 'Editing' group in the inspector
|
||||
%group = %inspector.findExistentGroup("Editing");
|
||||
if(isObject(%group))
|
||||
{
|
||||
//We add a field of the type 'SimGroupSelectionButton'. This isn't a 'real' type, so when the inspector group tries to add it
|
||||
//it will route down through GuiInspectorGroup(the namespace of %group) and call onConstructField in an attemp to see if there's any
|
||||
//script defined functions that can build a field of that type.
|
||||
//We happen to define the required 'build @ <fieldTypeName> @ Field()' function below, allowing us to build out the custom field type
|
||||
%group.addField("Select Objects", "SimGroupSelectionButton", "Select filtered objects");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scene::onInspect(%obj, %inspector)
|
||||
{
|
||||
simGroup::onInspect(%obj, %inspector);
|
||||
}
|
||||
|
||||
function subScene::onInspect(%obj, %inspector)
|
||||
{
|
||||
simGroup::onInspect(%obj, %inspector);
|
||||
}
|
||||
|
||||
function GuiInspectorGroup::buildSimGroupSelectionButtonField(%this, %fieldName, %fieldLabel, %fieldDesc,
|
||||
|
|
@ -687,7 +700,7 @@ function GuiInspectorGroup::buildSimGroupSelectionButtonField(%this, %fieldName,
|
|||
tooltipProfile = "EditorToolTipProfile";
|
||||
text = "Select";
|
||||
maxLength = "1024";
|
||||
command = %ownerObj @ ".SelectFiteredObjects("@ %ownerObj.minSize @","@ %ownerObj.maxSize @");";
|
||||
command = %ownerObj @ ".SelectFilteredObjects("@ %ownerObj @".getFieldValue(\"minSize\"),"@ %ownerObj @".getFieldValue(\"maxSize\"));";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -427,79 +427,148 @@ function EditorSaveMissionAs( %levelAsset )
|
|||
|
||||
function EditorAutoSaveMission()
|
||||
{
|
||||
// just save the mission without renaming it
|
||||
//re-init the schedule
|
||||
%autosaveInterval = EditorSettings.value("WorldEditor/AutosaveInterval", "5");
|
||||
%autosaveInterval = %autosaveInterval * 60000; //convert to milliseconds from minutes
|
||||
|
||||
if($Editor::AutoSaveIndex $= "" || $Editor::AutoSaveIndex $= "5")
|
||||
$Editor::AutoSaveIndex = 1;
|
||||
else
|
||||
$Editor::AutoSaveIndex++;
|
||||
if(EditorGui.autosaveSchedule !$= "")
|
||||
cancel(EditorGui.autosaveSchedule);
|
||||
|
||||
%autosaveFileName = "tools/autosave/" @ fileBase($Server::MissionFile) @ "_autosave" @ $Editor::AutoSaveIndex @ fileExt($Server::MissionFile);
|
||||
EditorGui.autosaveSchedule = schedule( %autosaveInterval, 0, "EditorAutoSaveMission" );
|
||||
|
||||
// first check for dirty and read-only files:
|
||||
if((EWorldEditor.isDirty || ETerrainEditor.isMissionDirty) && !isWriteableFileName(%autosaveFileName))
|
||||
// first check for dirty
|
||||
if(!EWorldEditor.isDirty && !ETerrainEditor.isMissionDirty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: Make Autosave work with terrains
|
||||
/*if(ETerrainEditor.isDirty)
|
||||
{
|
||||
// Find all of the terrain files
|
||||
initContainerTypeSearch($TypeMasks::TerrainObjectType);
|
||||
|
||||
while ((%terrainObject = containerSearchNext()) != 0)
|
||||
{
|
||||
if (!isWriteableFileName(%terrainObject.terrainFile))
|
||||
{
|
||||
if (toolsMessageBox("Error", "Terrain file \""@ %terrainObject.terrainFile @ "\" is read-only. Continue?", "Ok", "Stop") == $MROk)
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// now write the terrain and mission files out:
|
||||
|
||||
if(EWorldEditor.isDirty || ETerrainEditor.isMissionDirty)
|
||||
getScene(0).save(%autosaveFileName);
|
||||
//Also skip out if we're actively performing an action
|
||||
if(EditorGui.currentEditor.editorGui.isLeftMouseDown() || EditorGui.currentEditor.editorGui.isMiddleMouseDown() ||
|
||||
EditorGui.currentEditor.editorGui.isRightMouseDown())
|
||||
return false;
|
||||
|
||||
//TODO: Make Autosave work with terrains
|
||||
/*if(ETerrainEditor.isDirty)
|
||||
%backupFilePathBase = "tools/autosave/";
|
||||
if(!isObject(AssetBackupListArray))
|
||||
{
|
||||
// Find all of the terrain files
|
||||
initContainerTypeSearch($TypeMasks::TerrainObjectType);
|
||||
|
||||
while ((%terrainObject = containerSearchNext()) != 0)
|
||||
new ArrayObject(AssetBackupListArray){};
|
||||
}
|
||||
|
||||
AssetBackupListArray.empty();
|
||||
|
||||
//Next, we figure out what all we're planning to save
|
||||
%terrainObjects = getRootScene().getObjectsByClass("TerrainBlock", false);
|
||||
for(%i=0; %i < getWordCount(%terrainObjects); %i++)
|
||||
{
|
||||
%terrObj = getWord(%terrainObjects, %i);
|
||||
%terrAssetId = %terrObj.terrainAsset;
|
||||
|
||||
%sanitizedName = strReplace(%terrAssetId, ":", "_");
|
||||
|
||||
%terrAssetBackupPath = %backupFilePathBase @ %sanitizedName @ "/";
|
||||
|
||||
AssetBackupListArray.add(%terrAssetBackupPath, %terrAssetId SPC %terrObj);
|
||||
}
|
||||
|
||||
%subScenes = getRootScene().getObjectsByClass("SubScene", false);
|
||||
for(%i=0; %i < getWordCount(%subScenes); %i++)
|
||||
{
|
||||
%subSceneObj = getWord(%subScenes, %i);
|
||||
%subSceneAssetId = %subSceneObj.levelAsset;
|
||||
|
||||
%sanitizedName = strReplace(%subSceneAssetId, ":", "_");
|
||||
|
||||
%subSceneAssetBackupPath = %backupFilePathBase @ %sanitizedName @ "/";
|
||||
|
||||
AssetBackupListArray.add(%subSceneAssetBackupPath, %subSceneAssetId SPC %subSceneObj);
|
||||
}
|
||||
|
||||
%levelAssetId = $Server::LevelAsset.getAssetId();
|
||||
%levelSanitizedName = strReplace(%levelAssetId, ":", "_");
|
||||
%levelAssetBackupPath = %backupFilePathBase @ %levelSanitizedName @ "/";
|
||||
AssetBackupListArray.add(%levelAssetBackupPath, %levelAssetId SPC getRootScene());
|
||||
|
||||
//Now we process through our assets to find index counts and save off a copy duplicate to the backup path
|
||||
if($Editor::MaxAutosaves $= "")
|
||||
$Editor::MaxAutosaves = 10;
|
||||
|
||||
for(%i=0; %i < AssetBackupListArray.count(); %i++)
|
||||
{
|
||||
%path = AssetBackupListArray.getKey(%i);
|
||||
%assetId = getWord(AssetBackupListArray.getValue(%i), 0);
|
||||
%obj = getWord(AssetBackupListArray.getValue(%i), 1);
|
||||
|
||||
%dirList = getDirectoryList(%path);
|
||||
%savesCount = getFieldCount(%dirList);
|
||||
%newestFolder = 0;
|
||||
%oldestFolder = -1;
|
||||
|
||||
if(%savesCount != 0)
|
||||
{
|
||||
if(%terrainObject.terrainAsset !$= "")
|
||||
%saveArray = new ArrayObject(){};
|
||||
//loop over the entries and find the oldest one
|
||||
for(%f=0; %f < %savesCount; %f++)
|
||||
{
|
||||
//we utilize a terrain asset, so we'll update our dependencies while we're at it
|
||||
%terrainObject.saveAsset();
|
||||
%saveArray.add(getField(%dirList, %f), %f);
|
||||
}
|
||||
else
|
||||
|
||||
%saveArray.sortk(true);
|
||||
|
||||
%oldestFolder = %saveArray.getKey(0);
|
||||
%newestFolder = %saveArray.getKey(%savesCount-1);
|
||||
|
||||
%saveArray.delete();
|
||||
}
|
||||
|
||||
if(%savesCount >= $Editor::MaxAutosaves)
|
||||
{
|
||||
AssetBrowser.dirHandler.deleteFolder(%path @ %oldestFolder @ "/");
|
||||
}
|
||||
|
||||
%newSaveFolder = %newestFolder + 1;
|
||||
%newSaveFolderPath = %path @ %newSaveFolder @ "/";
|
||||
|
||||
if(!isDirectory(%newSaveFolderPath))
|
||||
{
|
||||
AssetBrowser.dirHandler.createFolder(%newSaveFolderPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("EditorAutoSaveMission() - Somehow we indicated a brand new save folder, but it already exists? Stopping to avoid problems");
|
||||
continue;
|
||||
}
|
||||
|
||||
%assetFilePath = AssetDatabase.getAssetFilePath(%assetId);
|
||||
%assetFileName = fileName(%assetFilePath);
|
||||
%assetPath = filePath(%assetFilePath) @ "/";
|
||||
|
||||
if(!pathCopy(%assetFilePath, %newSaveFolderPath @ %assetFileName))
|
||||
{
|
||||
error("EditorAutoSaveMission() - failed to copy the asset file: " @ %assetFilePath @ " to backup directory!");
|
||||
continue;
|
||||
}
|
||||
|
||||
//Do the actual copy of the files for backup purposes now
|
||||
%looseFileCount = AssetDatabase.getAssetLooseFileCount(%assetId);
|
||||
for(%lf = 0; %lf < %looseFileCount; %lf++)
|
||||
{
|
||||
%looseFile = AssetDatabase.getAssetLooseFile(%assetId, %lf);
|
||||
%looseFileName = fileName(%looseFile);
|
||||
|
||||
if(!isFile(%looseFile))
|
||||
continue; //only bother with real files
|
||||
|
||||
if(!pathCopy(%looseFile, %newSaveFolderPath @ %looseFileName))
|
||||
{
|
||||
%terrainObject.save(%terrainObject.terrainFile);
|
||||
error("EditorAutoSaveMission() - failed to copy the asset loose file: " @ %assetPath @ %looseFileName @ " to backup directory!");
|
||||
}
|
||||
|
||||
%fileExt = fileExt(%looseFile);
|
||||
if(%fileExt $= ".mis")
|
||||
%obj.save(%newSaveFolderPath @ %looseFileName, false);
|
||||
else if(%fileExt $= ".subMis" || %fileExt $= ".ter")
|
||||
%obj.save(%newSaveFolderPath @ %looseFileName); //Save out the current status of it to the file so we have our actual snapshot
|
||||
}
|
||||
}
|
||||
|
||||
ETerrainPersistMan.saveDirty();*/
|
||||
|
||||
// Give EditorPlugins a chance to save.
|
||||
for ( %i = 0; %i < EditorPluginSet.getCount(); %i++ )
|
||||
{
|
||||
%obj = EditorPluginSet.getObject(%i);
|
||||
if ( %obj.isDirty() )
|
||||
%obj.onSaveMission( %autosaveFileName );
|
||||
}
|
||||
|
||||
%autosaveInterval = EditorSettings.value("WorldEditor/AutosaveInterval", "5");
|
||||
%autosaveInterval = %autosaveInterval * 60000; //convert to milliseconds from minutes
|
||||
EditorGui.autosaveSchedule = schedule( %autosaveInterval, 0, "EditorAutoSaveMission" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function EditorOpenMission(%levelAsset)
|
||||
|
|
@ -722,6 +791,14 @@ function EditorExplodePrefab()
|
|||
|
||||
function makeSelectedAMesh(%assetId)
|
||||
{
|
||||
%selectedCount = EWorldEditor.getSelectionSize();
|
||||
|
||||
if(!%selectedCount)
|
||||
{
|
||||
error("You need to select at least one object to turn it into a mesh!");
|
||||
return;
|
||||
}
|
||||
|
||||
%assetDef = AssetDatabase.acquireAsset(%assetId);
|
||||
|
||||
%assetPath = AssetDatabase.getAssetPath(%assetId);
|
||||
|
|
@ -740,6 +817,21 @@ function makeSelectedAMesh(%assetId)
|
|||
{
|
||||
//Next, for safety purposes(and convenience!) we'll make them a prefab aping off the filepath/name provided
|
||||
//TODO: Make this an editor option
|
||||
|
||||
//We want to figure out where this stuff goes, so scan through our selected objects
|
||||
//And see if we have a common parent
|
||||
%sameParent = true;
|
||||
%firstParent = EWorldEditor.getSelectedObject(0).parentGroup;
|
||||
for(%i=1; %i < %selectedCount; %i++)
|
||||
{
|
||||
%selectedObj = EWorldEditor.getSelectedObject(%i);
|
||||
if(%firstParent != %selectedObj.parentGroup)
|
||||
{
|
||||
%sameParent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
%prefabPath = %assetPath @ "/" @ %assetDef.AssetName @ ".prefab";
|
||||
EWorldEditor.makeSelectionPrefab(%prefabPath, false);
|
||||
%selectionPos = EWorldEditor.getSelectedObject(0).getPosition();
|
||||
|
|
@ -752,8 +844,14 @@ function makeSelectedAMesh(%assetId)
|
|||
shapeAsset = %assetId;
|
||||
position = %selectionPos;
|
||||
};
|
||||
|
||||
getRootScene().add(%newStatic);
|
||||
|
||||
if(%sameParent)
|
||||
%firstParent.add(%newStatic);
|
||||
else
|
||||
getRootScene().add(%newStatic);
|
||||
|
||||
EWorldEditor.clearSelection();
|
||||
EWorldEditor.selectObject(%newStatic);
|
||||
}
|
||||
|
||||
EditorTree.buildVisibleTree( true );
|
||||
|
|
|
|||
Loading…
Reference in a new issue