- Reimplements autosave logic to handle levels, subscenes and terrains in a more consistent, reliable way.

- Adds entry to RMB menu in Asset Browser to restore an asset to a backup copy taken from autosaves
- Adds reparent out-of-bounds objects button to SceneGroup inspector
- Adds ability to have SubScene have a different loading bounds from the actual subscene bounds, allowing load triggering to happen ahead of the bounds of the subscene itself
- Fixes asset importer handling of animFPS field to be the correct type
- Adds onInspect handling to GameBase allowing better handling for any game class type with editor integration
- Add getAssetLooseFileCount and getAssetLooseFile to AssetManager to be able to iterate over all loose files associated to an asset
- Add standard/default preload function def to forestItem
- Fixes handling of text placement on GuiIconButtonCtrl when text is set to the right
- Adds setGlobalCenter utility function
- Adds ability to set guiInputCtrl active state
- Matched util functions for tracking if left and right mouse buttons are down to EditTSCtrl alongside the existing middle mouse
- Add empty element sanity check to appMesh loader
- Add callback for GameBase when game is created
- Add default graphics options config for steamdeck
- Fix typo in assetImportConfig default
- Filters SceneGroup utility buttons in inspector to only show for relevent class types
This commit is contained in:
JeffR 2025-05-25 07:40:10 -05:00
parent 70502d1b0f
commit bb7ee38bf4
33 changed files with 978 additions and 237 deletions

View file

@ -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);
}

View file

@ -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");
}
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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)
{

View file

@ -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!");
}
}

View file

@ -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();
}
}
}

View file

@ -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)

View file

@ -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

View file

@ -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\"));";
};
};

View file

@ -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 );