2
0
Эх сурвалжийг харах

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

JeffR 3 жил өмнө
parent
commit
81aa43a4bd

+ 56 - 90
Engine/source/T3D/assets/TerrainMaterialAsset.cpp

@@ -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);
-
-   mMatPreviewButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
-   mMatPreviewButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
-   mMatPreviewButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+   mBrowseButton->setField("Command", szBuffer);
 
-   StringBuilder strbld;
-   strbld.append(matAsset->getMaterialDefinitionName());
-   strbld.append("\n");
-   strbld.append("Open this asset in the Material Editor");
+   setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
 
-   mMatPreviewButton->setDataField(StringTable->insert("tooltip"), NULL, strbld.data());
+   // Create "Open in Editor" button
+   mEditButton = new GuiBitmapButtonCtrl();
 
-   _registerEditControl(mMatPreviewButton);
-   //mMatPreviewButton->registerObject();
-   mMatEdContainer->addObject(mMatPreviewButton);
+   dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.editAsset(%d.getText());", retCtrl->getId());
+   mEditButton->setField("Command", szBuffer);
 
-   mMatAssetIdTxt = new GuiTextEditCtrl();
-   mMatAssetIdTxt->registerObject();
-   mMatAssetIdTxt->setActive(false);
+   char bitmapName[512] = "ToolsModule:material_editor_n_image";
+   mEditButton->setBitmap(StringTable->insert(bitmapName));
 
-   mMatAssetIdTxt->setText(matAssetId);
+   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->setBounds(100, 0, 150, 18);
-   mMatEdContainer->addObject(mMatAssetIdTxt);
+   mEditButton->registerObject();
+   addObject(mEditButton);
 
-   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,

+ 6 - 7
Engine/source/T3D/assets/TerrainMaterialAsset.h

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

+ 3 - 1
Engine/source/T3D/fx/groundCover.cpp

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

+ 1 - 1
Engine/source/T3D/fx/groundCover.h

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

+ 10 - 4
Engine/source/terrain/terrMaterial.cpp

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

+ 16 - 19
Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript

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

+ 6 - 2
Templates/BaseGame/game/tools/assetBrowser/scripts/newAsset.tscript

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

+ 9 - 0
Templates/BaseGame/game/tools/projectImporter/importers/pre40/T3Dpre4ProjectImporter.tscript

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

+ 35 - 10
Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.tscript

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