Fixed formatting to match the standard for TerrainMaterialAsset inspector fields

Added utility functions to TerrainMaterialAsset for getting the material and fx material definitions
Fixed logical flaw with the initialization code that could cause the materialDefinition to be nulled in terrainmaterialassets
Fixed layer handling in GroundCover to properly work with TerrainMaterialAssets
Added logic to properly exit out of the onAdd in the event no internal name is assigned or if there is a collision. This prevents duplicates from appearing in the terr mat editor when creating a new material
Fixed issue where going from a creator item in the AB to selecting a particular asset type would break the filtering because select mode removed collections and creator items, changing all the item ids and breaking references.
Added sanity check to prevent attempting to acquire non-assets in the AB, such as creator entries, which would cause console spam
Added optional field to provide an override new asset name to the New Asset window
Added logic so in the event no FX Material is found when importing a terrain material, it will create a stub entry so it always has one defined
Added logic to handle situations where a terrain has a reference to an assetId, but the asset does not exist for whatever reason. Will prompt to create the missing asset, then continue on with the regular saving/editing process as normal
Fixed issue where the terrain material editor would try and reference the preview images being used in the display on the editor instead of the proper assetId itself
This commit is contained in:
JeffR 2022-03-29 01:40:07 -05:00
parent 3e39347167
commit 81aa43a4bd
9 changed files with 142 additions and 134 deletions

View file

@ -177,11 +177,6 @@ void TerrainMaterialAsset::initializeAsset()
return;
}
if (mMatDefinitionName == StringTable->insert("DetailBlue"))
{
bool asdfsd = true;
}
if (size() != 0 && mScriptPath == StringTable->EmptyString())
{
mLoadedState = EmbeddedDefinition;
@ -267,18 +262,20 @@ void TerrainMaterialAsset::loadMaterial()
{
for (U32 i = 0; i < size(); i++)
{
mMaterialDefinition = dynamic_cast<TerrainMaterial*>(getObject(i));
if (mMaterialDefinition)
TerrainMaterial* terrMat = dynamic_cast<TerrainMaterial*>(getObject(i));
if (terrMat)
{
mMaterialDefinition = terrMat;
mLoadedState = Ok;
mMaterialDefinition->setInternalName(getAssetId());
continue;
}
//Otherwise, check if it's our FX material
mFXMaterialDefinition = dynamic_cast<Material*>(getObject(i));
if (mFXMaterialDefinition)
Material* fxMat = dynamic_cast<Material*>(getObject(i));
if (fxMat)
{
mFXMaterialDefinition = fxMat;
//mMaterialDefinition->setInternalName(getAssetId());
mFXMaterialDefinition->reload();
continue;
@ -286,6 +283,9 @@ void TerrainMaterialAsset::loadMaterial()
}
}
if(mLoadedState == Ok)
return;
}
else if ((mLoadedState == ScriptLoaded || mLoadedState == DefinitionAlreadyExists) && mMatDefinitionName != StringTable->EmptyString())
{
@ -460,6 +460,28 @@ DefineEngineMethod(TerrainMaterialAsset, getScriptPath, const char*, (), ,
{
return object->getScriptPath();
}
DefineEngineMethod(TerrainMaterialAsset, getMaterialDefinition, S32, (), ,
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
"@return The AssetId of the associated asset, if any.")
{
SimObjectPtr<TerrainMaterial> mat = object->getMaterialDefinition();
if (mat.isValid())
return mat->getId();
else
return 0;
}
DefineEngineMethod(TerrainMaterialAsset, getFXMaterialDefinition, S32, (), ,
"Queries the Asset Database to see if any asset exists that is associated with the provided material name.\n"
"@return The AssetId of the associated asset, if any.")
{
SimObjectPtr<Material> mat = object->getFXMaterialDefinition();
if (mat.isValid())
return mat->getId();
else
return 0;
}
#endif
//-----------------------------------------------------------------------------
// GuiInspectorTypeAssetId
@ -483,68 +505,36 @@ void GuiInspectorTypeTerrainMaterialAssetPtr::consoleInit()
GuiControl* GuiInspectorTypeTerrainMaterialAssetPtr::constructEditControl()
{
// Create base filename edit controls
mUseHeightOverride = true;
mHeightOverride = 100;
mMatEdContainer = new GuiControl();
mMatEdContainer->registerObject();
addObject(mMatEdContainer);
// Create "Open in ShapeEditor" button
mMatPreviewButton = new GuiBitmapButtonCtrl();
const char* matAssetId = getData();
TerrainMaterialAsset* matAsset = AssetDatabase.acquireAsset< TerrainMaterialAsset>(matAssetId);
TerrainMaterial* materialDef = nullptr;
char bitmapName[512] = "ToolsModule:material_editor_n_image";
/*if (!Sim::findObject(matAsset->getMaterialDefinitionName(), materialDef))
{
Con::errorf("GuiInspectorTypeTerrainMaterialAssetPtr::constructEditControl() - unable to find material in asset");
}
else
{
mMatPreviewButton->setBitmap(materialDef->mDiffuseMapFilename[0]);
}*/
mMatPreviewButton->setPosition(0, 0);
mMatPreviewButton->setExtent(100,100);
GuiControl* retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainMaterialAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainMaterialAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
mInspector->getIdString(), mCaption);
mMatPreviewButton->setField("Command", szBuffer);
mBrowseButton->setField("Command", szBuffer);
mMatPreviewButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mMatPreviewButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mMatPreviewButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
StringBuilder strbld;
strbld.append(matAsset->getMaterialDefinitionName());
strbld.append("\n");
strbld.append("Open this asset in the Material Editor");
// Create "Open in Editor" button
mEditButton = new GuiBitmapButtonCtrl();
mMatPreviewButton->setDataField(StringTable->insert("tooltip"), NULL, strbld.data());
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.editAsset(%d.getText());", retCtrl->getId());
mEditButton->setField("Command", szBuffer);
_registerEditControl(mMatPreviewButton);
//mMatPreviewButton->registerObject();
mMatEdContainer->addObject(mMatPreviewButton);
char bitmapName[512] = "ToolsModule:material_editor_n_image";
mEditButton->setBitmap(StringTable->insert(bitmapName));
mMatAssetIdTxt = new GuiTextEditCtrl();
mMatAssetIdTxt->registerObject();
mMatAssetIdTxt->setActive(false);
mEditButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mEditButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this asset in the Terrain Material Editor");
mMatAssetIdTxt->setText(matAssetId);
mEditButton->registerObject();
addObject(mEditButton);
mMatAssetIdTxt->setBounds(100, 0, 150, 18);
mMatEdContainer->addObject(mMatAssetIdTxt);
return mMatEdContainer;
return retCtrl;
}
bool GuiInspectorTypeTerrainMaterialAssetPtr::updateRects()
@ -558,45 +548,21 @@ bool GuiInspectorTypeTerrainMaterialAssetPtr::updateRects()
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mMatEdContainer != nullptr)
if (mBrowseButton != NULL)
{
mMatPreviewButton->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
}
if (mMatPreviewButton != nullptr)
if (mEditButton != NULL)
{
mMatPreviewButton->resize(Point2I::Zero, Point2I(100, 100));
}
if (mMatAssetIdTxt != nullptr)
{
mMatAssetIdTxt->resize(Point2I(100, 0), Point2I(mEditCtrlRect.extent.x - 100, 18));
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
resized |= mEditButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
return resized;
}
void GuiInspectorTypeTerrainMaterialAssetPtr::setMaterialAsset(String assetId)
{
mTargetObject->setDataField(mCaption, "", assetId);
//force a refresh
SimObject* obj = mInspector->getInspectObject();
mInspector->inspectObject(obj);
}
DefineEngineMethod(GuiInspectorTypeTerrainMaterialAssetPtr, setMaterialAsset, void, (String assetId), (""),
"Gets a particular shape animation asset for this shape.\n"
"@param animation asset index.\n"
"@return Shape Animation Asset.\n")
{
if (assetId == String::EmptyString)
return;
return object->setMaterialAsset(assetId);
}
IMPLEMENT_CONOBJECT(GuiInspectorTypeTerrainMaterialAssetId);
ConsoleDocClass(GuiInspectorTypeTerrainMaterialAssetId,

View file

@ -94,6 +94,8 @@ public:
StringTableEntry getMaterialDefinitionName() { return mMatDefinitionName; }
SimObjectPtr<TerrainMaterial> getMaterialDefinition() { return mMaterialDefinition; }
SimObjectPtr<Material> getFXMaterialDefinition() { return mFXMaterialDefinition; }
void setScriptFile(const char* pScriptFile);
inline StringTableEntry getScriptFile(void) const { return mScriptFile; };
@ -127,26 +129,23 @@ protected:
};
DefineConsoleType(TypeTerrainMaterialAssetPtr, TerrainMaterialAsset)
DefineConsoleType(TypeMaterialAssetId, String)
DefineConsoleType(TypeTerrainMaterialAssetId, String)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeTerrainMaterialAssetPtr : public GuiInspectorField
class GuiInspectorTypeTerrainMaterialAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorField Parent;
typedef GuiInspectorTypeFileName Parent;
public:
GuiControl* mMatEdContainer;
GuiBitmapButtonCtrl *mMatPreviewButton;
GuiTextEditCtrl *mMatAssetIdTxt;
GuiBitmapButtonCtrl* mEditButton;
DECLARE_CONOBJECT(GuiInspectorTypeTerrainMaterialAssetPtr);
static void consoleInit();
virtual GuiControl* constructEditControl();
virtual bool updateRects();
void setMaterialAsset(String assetId);
};
class GuiInspectorTypeTerrainMaterialAssetId : public GuiInspectorTypeTerrainMaterialAssetPtr
{

View file

@ -50,6 +50,7 @@
#include "renderInstance/renderDeferredMgr.h"
#include "console/engineAPI.h"
#include "T3D/assets/MaterialAsset.h"
#include "T3D/assets/TerrainMaterialAsset.h"
/// This is used for rendering ground cover billboards.
GFXImplementVertexFormat( GCVertex )
@ -564,7 +565,7 @@ void GroundCover::initPersistFields()
addField("shapeFilename", TypeFilename, Offset(mShapeName, GroundCover), MAX_COVERTYPES, "The cover shape filename. [Optional]", AbstractClassRep::FIELD_HideInInspectors);
INITPERSISTFIELD_SHAPEASSET_ARRAY(Shape, MAX_COVERTYPES, GroundCover, "The cover shape. [Optional]");
addField( "layer", TypeTerrainMaterialName, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material name to limit coverage to, or blank to not limit." );
addField( "layer", TypeTerrainMaterialAssetId, Offset( mLayer, GroundCover ), MAX_COVERTYPES, "Terrain material assetId to limit coverage to, or blank to not limit." );
addField( "invertLayer", TypeBool, Offset( mInvertLayer, GroundCover ), MAX_COVERTYPES, "Indicates that the terrain material index given in 'layer' is an exclusion mask." );
@ -1178,6 +1179,7 @@ GroundCoverCell* GroundCover::_generateCell( const Point2I& index,
const bool typeIsShape = mShapeInstances[ type ] != NULL;
const Box3F typeShapeBounds = typeIsShape ? mShapeInstances[ type ]->getShape()->mBounds : Box3F();
const F32 typeWindScale = mWindScale[type];
StringTableEntry typeLayer = mLayer[type];
const bool typeInvertLayer = mInvertLayer[type];

View file

@ -312,7 +312,7 @@ protected:
/// The maximum world space elevation for placement.
F32 mMaxElevation[MAX_COVERTYPES];
/// Terrain material name to limit coverage to, or
/// Terrain material assetId to limit coverage to, or
/// left empty to cover entire terrain.
StringTableEntry mLayer[MAX_COVERTYPES];

View file

@ -137,13 +137,19 @@ bool TerrainMaterial::onAdd()
SimSet *set = Sim::getTerrainMaterialSet();
// Make sure we have an internal name set.
if ( !mInternalName || !mInternalName[0] )
Con::warnf( "TerrainMaterial::onAdd() - No internal name set!" );
if (!mInternalName || !mInternalName[0])
{
Con::warnf("TerrainMaterial::onAdd() - No internal name set!");
return false;
}
else
{
SimObject *object = set->findObjectByInternalName( mInternalName );
if ( object )
Con::warnf( "TerrainMaterial::onAdd() - Internal name collision; '%s' already exists!", mInternalName );
if (object)
{
Con::warnf("TerrainMaterial::onAdd() - Internal name collision; '%s' already exists!", mInternalName);
return false;
}
}
set->addObject( this );

View file

@ -639,9 +639,18 @@ function AssetBrowser::loadDirectories( %this )
%dataItem = AssetBrowser-->filterTree.insertItem(AssetBrowser-->filterTree.modulesIdx, "data");
AssetBrowser-->filterTree.tagsIdx = AssetBrowser-->filterTree.insertItem(1, "Tags");
if(!%this.selectMode)
AssetBrowser-->filterTree.creatorIdx = AssetBrowser-->filterTree.insertItem(1, "Creator");
AssetBrowser-->filterTree.clearSelection();
if(%this.selectMode)
{
AssetBrowser-->filterTree.addSelection(AssetBrowser-->filterTree.collectionsIdx);
AssetBrowser-->filterTree.addSelection(AssetBrowser-->filterTree.creatorIdx);
AssetBrowser-->filterTree.hideSelection();
}
%this.dirHandler.loadFolders("data", %dataItem);
%this.loadCollectionSets();
@ -750,20 +759,6 @@ function AssetBrowser::loadDirectories( %this )
function AssetBrowser::updateSelection( %this, %asset, %moduleName )
{
/*%isAssetBorder = 0;
eval("%isAssetBorder = isObject(AssetBrowser-->"@%asset@"Border);");
if( %isAssetBorder )
{
eval( "AssetBrowser-->"@%asset@"Border.setStateOn(1);");
}
%isAssetBorderPrevious = 0;
eval("%isAssetBorderPrevious = isObject(AssetBrowser-->"@%this.prevSelectedMaterialHL@"Border);");
if( %isAssetBorderPrevious )
{
eval( "AssetBrowser-->"@%this.prevSelectedMaterialHL@"Border.setStateOn(0);");
}*/
//If we had an existing selected assetDef, clear the reference
if(isObject(AssetBrowser.selectedAssetDef))
AssetDatabase.releaseAsset(AssetBrowser.selectedAssetDef.getAssetId());
@ -775,11 +770,13 @@ function AssetBrowser::updateSelection( %this, %asset, %moduleName )
if(strstr(%moduleName, "/") != -1)
return;
//Otherwise, it's an asset so we'll select the definition while we're at it
//Check if this is an actual assetId, or if it's just a programmatic reference
//like what we use for the creator entries
if(AssetDatabase.isDeclaredAsset(AssetBrowser.selectedAsset))
{
//Looks good, it's an asset so we'll select the definition while we're at it
AssetBrowser.selectedAssetDef = AssetDatabase.acquireAsset(AssetBrowser.selectedAsset);
//AssetBrowser.selectedPreviewImagePath = %previewImagePath;
//%this.prevSelectedMaterialHL = %asset;
}
}
function AssetBrowser::loadCollectionSets(%this)

View file

@ -85,7 +85,7 @@ function NewAssetModuleBtn::onClick(%this)
AssetBrowser_addModuleWindow.selectWindow();
}
function AssetBrowser::setupCreateNewAsset(%this, %assetType, %moduleName, %callback)
function AssetBrowser::setupCreateNewAsset(%this, %assetType, %moduleName, %callback, %nameOverride)
{
Canvas.pushDialog(AssetBrowser_newAsset);
@ -106,8 +106,12 @@ function AssetBrowser::setupCreateNewAsset(%this, %assetType, %moduleName, %call
%this.newAssetSettings.assetType = %assetType;
%this.newAssetSettings.moduleName = %moduleName;
%newAssetName = "New" @ %shortAssetTypeName;
if(%nameOverride !$= "")
%newAssetName = %nameOverride;
NewAssetPropertiesInspector.startGroup("General");
NewAssetPropertiesInspector.addField("assetName", "New Asset Name", "String", "Name of the new asset", "New" @ %shortAssetTypeName, "", %this.newAssetSettings);
NewAssetPropertiesInspector.addField("assetName", "New Asset Name", "String", "Name of the new asset", %newAssetName, "", %this.newAssetSettings);
//NewAssetPropertiesInspector.addField("AssetType", "New Asset Type", "List", "Type of the new asset", %assetType, "Component,Image,Material,Shape,Sound,State Machine", %newAssetSettings);
//NewAssetPropertiesInspector.addField("friendlyName", "Friendly Name", "String", "Human-readable name of new asset", "", "", %this.newAssetSettings);

View file

@ -1244,6 +1244,15 @@ function T3Dpre4ProjectImporter::processTerrainMaterialObject(%this, %fileObject
%fileObject.FXMaterial.processed = true;
%fileObject.FXMaterial.skip = true;
}
else
{
//if after all that we still have no FXMaterial, just create a new one
%fxMat = new Material("TerrainFX_" @ %objectName)
{
mapTo = %objectName;
};
%asset.add(%fxMat);
}
%success = false;
if(TamlWrite(%asset, %tamlpath))

View file

@ -474,11 +474,36 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
{
//If we happen to have been handed an assetId, process it
if(AssetDatabase.isDeclaredAsset(%mat))
{
%assetDef = AssetDatabase.acquireAsset(%mat);
%mat = %assetDef.getMaterialDefinition();
}
// Skip over obviously bad cases.
if ( !isObject( %mat ) ||
!%mat.isMemberOfClass( TerrainMaterial ) )
return;
//Lets validate it wasn't a generated stub. if so, we need to add an intermediate
//step to create the asset
%assetDef = AssetDatabase.acquireAsset(%mat.internalName);
if(%assetDef $= "")
{
%moduleSplit = strpos(%mat.internalName, ":");
%moduleName = getSubStr(%mat.internalName, 0, %moduleSplit);
%assetName = getSubStr(%mat.internalName, %moduleSplit+1, -1);
if(ModuleDatabase.findModule(%moduleName) !$= "")
{
AssetBrowser.selectedModule = %moduleName;
}
//we need to create an actual asset here
AssetBrowser.setupCreateNewAsset("TerrainMaterialAsset", AssetBrowser.selectedModule, "TerrainMaterialDlg.saveDirtyMaterial", %assetName);
return;
}
// Read out properties from the dialog.
%newName = %this-->matNameCtrl.getText();
@ -487,28 +512,28 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
//---
%newDiffuse = %this-->texDiffuseMap.getBitmap();
if(%newDiffuse $= $TerrainMaterialEditor::emptyMaterialImage || %newDiffuse $= %blankBitmap)
%newDiffuse = %this-->diffuseMapAssetId.text;
if(%newDiffuse $= "None")
%newDiffuse = "";
//---
%newNormal = %this-->texNormalMap.getBitmap();
if(%newNormal $= $TerrainMaterialEditor::emptyMaterialImage || %newNormal $= %blankBitmap)
%newNormal = %this-->normalMapAssetId.text;
if(%newNormal $= "None")
%newNormal = "";
//---
%newormConfig = %this-->texORMConfigMap.getBitmap();
if(%newormConfig $= $TerrainMaterialEditor::emptyMaterialImage || %newormConfig $= %blankBitmap)
%newormConfig = %this-->ORMMapAssetId.text;
if(%newormConfig $= "None")
%newormConfig = "";
//---
%newDetail = %this-->texDetailMap.getBitmap();
if(%newDetail $= $TerrainMaterialEditor::emptyMaterialImage || %newDetail $= %blankBitmap)
%newDetail = %this-->detailMapAssetId.text;
if(%newDetail $= "None")
%newDetail = "";
//---
%newMacro = %this-->texMacroMap.getBitmap();
if(%newMacro $= $TerrainMaterialEditor::emptyMaterialImage || %newMacro $= %blankBitmap)
%newMacro = %this-->macroMapAssetId.text;
if(%newMacro $= "None")
%newMacro = "";
%detailSize = %this-->detSizeCtrl.getText();