Merge pull request #755 from Areloch/MiscTerrainFixes

Misc Fixes for terrain material editing, creation and usage
This commit is contained in:
Brian Roberts 2022-03-31 19:42:56 -05:00 committed by GitHub
commit 798dd6ca6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 611 additions and 1408 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

@ -229,6 +229,9 @@ Material::Material()
dMemset(mEffectColor, 0, sizeof(mEffectColor));
mEffectColor[0] = LinearColorF::WHITE;
mEffectColor[1] = LinearColorF::WHITE;
mFootstepSoundId = -1; mImpactSoundId = -1;
mImpactFXIndex = -1;
INIT_ASSET(CustomFootstepSound);

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

@ -21,6 +21,9 @@ function AssetBrowser::createMaterialAsset(%this)
TamlWrite(%asset, %tamlpath);
//cleanup before proper init'ing
%assetName.delete();
%moduleDef = ModuleDatabase.findModule(%moduleName, 1);
AssetDatabase.addDeclaredAsset(%moduleDef, %tamlpath);

View file

@ -32,7 +32,7 @@ function AssetBrowser::createTerrainMaterialAsset(%this)
%fxMatDef = new Material("TerrainFX_" @ %assetName)
{
mapTo = %assetName;
mapTo = %moduleName @ ":" @ %assetName;
footstepSoundId = 0;
terrainMaterials = "1";
ShowDust = "1";
@ -48,6 +48,10 @@ function AssetBrowser::createTerrainMaterialAsset(%this)
TamlWrite(%asset, %tamlpath);
//cleanup before proper init'ing
%matDef.delete();
%fxMatDef.delete();
%moduleDef = ModuleDatabase.findModule(%moduleName, 1);
AssetDatabase.addDeclaredAsset(%moduleDef, %tamlpath);

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

@ -1963,7 +1963,24 @@ function MaterialEditorGui::save( %this )
MaterialEditorGui.copyMaterials( materialEd_previewMaterial, notDirtyMaterial );
%assetDef = AssetDatabase.acquireAsset(MaterialEditorGui.currentMaterialAsset);
%assetDef.saveAsset(); //write it out
%didEmbed = false;
%matScriptFile = %assetDef.getScriptPath();
if(%matScriptFile !$= "")
{
//lets up-convert to embedded
%assetDef.add(%assetDef.materialDefinitionName);
%assetDef.scriptFile = "";
%didEmbed = true;
}
//write it out
if(%assetDef.saveAsset())
{
if(%didEmbed)
{
fileDelete(%matScriptFile); //cleanup the old definition file
}
}
}
else
{

View file

@ -1203,7 +1203,7 @@ function T3Dpre4ProjectImporter::processTerrainMaterialObject(%this, %fileObject
{
%fxMatObj = getField(%fxMatList, %i);
%fxMatObjMapTo = findObjectField(%fxMatObj, "mapTo");
if(%fxMatObjMapTo $= %objectName)
if(%fxMatObjMapTo $= %objectName || %fxMatObjMapTo $= %assetName)
{
%fileObject.FXMaterial = %fxMatObj;
break;
@ -1215,7 +1215,7 @@ function T3Dpre4ProjectImporter::processTerrainMaterialObject(%this, %fileObject
if(%fileObject.FXMaterial !$= "")
{
//Ensure our mapto is up to date for any name sanitize/tweaks
setObjectField(%fileObject.FXMaterial, "mapTo", %objectName);
setObjectField(%fileObject.FXMaterial, "mapTo", %moduleName @ ":" @ %assetName);
//we associated to an FX material, so process that now
%objectDefinition = "";
@ -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 = %moduleName @ ":" @ %assetName;
};
%asset.add(%fxMat);
}
%success = false;
if(TamlWrite(%asset, %tamlpath))

View file

@ -109,6 +109,31 @@ function TerrainMaterialDlg::onWake( %this )
%item = %matLibTree.getFirstRootItem();
%matLibTree.expandItem( %item );
//Sounds
%this-->footstepSoundPopup.clear();
%this-->impactSoundPopup.clear();
%sounds = "<None>" TAB "<Soft>" TAB "<Hard>" TAB "<Metal>" TAB "<Snow>"; // Default sounds
%assetQuery = new AssetQuery();
AssetDatabase.findAssetType(%assetQuery, "SoundAsset");
%count = %assetQuery.getCount();
// Get custom sound assets
for(%i=0; %i < %count; %i++)
{
%assetId = %assetQuery.getAsset(%i);
%sounds = %sounds TAB %assetId;
}
%count = getFieldCount(%sounds);
for (%i = 0; %i < %count; %i++)
{
%name = getField(%sounds, %i);
%this-->footstepSoundPopup.add(%name);
%this-->impactSoundPopup.add(%name);
}
%this.activateMaterialCtrls( true );
}
@ -150,18 +175,8 @@ function TerrainMaterialDlg::dialogApply( %this )
%mat.delete();
}
// Make sure we save any changes to the current selection.
%this.saveDirtyMaterial( %this.activeMat );
// Delete the snapshot.
TerrainMaterialDlgSnapshot.delete();
// Remove ourselves from the canvas.
Canvas.popDialog( TerrainMaterialDlg );
call( %this.onApplyCallback, %this.activeMat, %this.matIndex );
TerrainMaterialDlg.matDirty = false;
%this.prepSaveDirtyMaterial();
}
//-----------------------------------------------------------------------------
@ -171,7 +186,7 @@ function TerrainMaterialDlg::dialogCancel( %this )
if(TerrainMaterialDlg.matDirty)
{
toolsMessageBoxYesNo("Save Dirty Material?", "The current material has been modified. Do you wish save your changes?",
"TerrainMaterialDlg.saveDirtyMaterial(" @ %this-->matLibTree.getSelectedItem() @ ");TerrainMaterialDlg.closeDialog();", "TerrainMaterialDlg.closeDialog();");
"TerrainMaterialDlg.prepSaveDirtyMaterial("@%this-->matLibTree.getSelectedItem()@");TerrainMaterialDlg.closeDialog();", "TerrainMaterialDlg.closeDialog();");
}
else
{
@ -380,13 +395,13 @@ function TerrainMaterialTreeCtrl::onSelect( %this, %item )
if(TerrainMaterialDlg.matDirty)
{
toolsMessageBoxYesNo("Save Dirty Material?", "The current material has been modified. Do you wish save your changes?",
"TerrainMaterialDlg.saveDirtyMaterial(" @ TerrainMaterialDlg.previousMat @ ");TerrainMaterialDlg.setActiveMaterial(" @ %item @ ");",
"TerrainMaterialDlg.prepSaveDirtyMaterial(" @ TerrainMaterialDlg.previousMat @ ");TerrainMaterialDlg.setActiveMaterial(" @ %item @ ");",
"TerrainMaterialDlg.setActiveMaterial(" @ %item @ ");");
}
else
{
TerrainMaterialDlg.setActiveMaterial( %item );
}
TerrainMaterialDlg.setActiveMaterial( %item );
}
}
//-----------------------------------------------------------------------------
@ -461,6 +476,32 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
%this-->isSRGB.setValue( %mat.isSRGB );
%this-->invertRoughness.setValue( %mat.invertRoughness );
//FX material stuffs
if(AssetDatabase.isDeclaredAsset(%mat.internalName))
{
%asset = AssetDatabase.acquireAsset(%mat.internalName);
%fxMat = %asset.getFXMaterialDefinition();
if(isObject(%fxMat))
{
%this-->effectColor0Swatch.color = %fxMat.effectColor[0];
%this-->effectColor1Swatch.color = %fxMat.effectColor[1];
%this-->showFootprintsCheckbox.setValue(%fxMat.showFootprints);
%this-->showDustCheckbox.setValue(%fxMat.showDust);
%this.updateSoundPopup("Footstep", %fxMat.footstepSoundId, %fxMat.customFootstepSound);
%this.updateSoundPopup("Impact", %fxMat.impactSoundId, %fxMat.customImpactSound);
}
else
{
%this-->effectColor0Swatch.color = "1 1 1 1";
%this-->effectColor1Swatch.color = "1 1 1 1";
%this-->showFootprintsCheckbox.setValue(0);
%this-->showFootprintsCheckbox.setValue(0);
%this.updateSoundPopup("Footstep", 0, "");
%this.updateSoundPopup("Impact", 0, "");
}
}
%this.activateMaterialCtrls( true );
}
else
@ -470,14 +511,132 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
}
}
//-----------------------------------------------------------------------------
function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
function TerrainMaterialDlg::updateSoundPopup(%this, %type, %defaultId, %customName)
{
%ctrl = TerrainMaterialDlg.findObjectByInternalName( %type @ "SoundPopup", true );
switch (%defaultId)
{
case 0: %name = "<Soft>";
case 1: %name = "<Hard>";
case 2: %name = "<Metal>";
case 3: %name = "<Snow>";
default:
if (%customName $= "")
%name = "<None>";
else
%name = %customName;
}
%r = %ctrl.findText(%name);
if (%r != -1)
%ctrl.setSelected(%r, false);
else
%ctrl.setText(%name);
}
function TerrainMaterialDlg::getBehaviorSound(%this, %type, %sound)
{
%defaultId = -1;
%customName = "";
switch$ (%sound)
{
case "<Soft>": %defaultId = 0;
case "<Hard>": %defaultId = 1;
case "<Metal>": %defaultId = 2;
case "<Snow>": %defaultId = 3;
default: %customName = %sound;
}
return %defaultId TAB %customName;
}
function TerrainMaterialDlg::updateEffectColor0(%this, %color)
{
%this-->effectColor0Swatch.color = %color;
}
function TerrainMaterialDlg::updateEffectColor1(%this, %color)
{
%this-->effectColor1Swatch.color = %color;
}
//-----------------------------------------------------------------------------
function TerrainMaterialDlg::prepSaveDirtyMaterial(%this, %material)
{
if(%material $= "")
%material = %this.activeMat;
if(!isObject(%material))
{
error("TerrainMaterialDlg::prepSaveDirtyMaterial() - active material is not a valid object");
return;
}
if(!AssetDatabase.isDeclaredAsset(%material.internalName))
{
//No valid asset, so we probably generated it as a stub due to a leftover
//reference. Let's generate a new asset
%assetId = %material.internalName;
%moduleSplit = strpos(%material.internalName, ":");
%moduleName = getSubStr(%material.internalName, 0, %moduleSplit);
%assetName = getSubStr(%material.internalName, %moduleSplit+1, -1);
if(ModuleDatabase.findModule(%moduleName) !$= "")
{
AssetBrowser.selectedModule = %moduleName;
}
//Clear the stub
TerrainMaterialSet.remove(%material);
%material.delete();
%oldMat = TerrainMaterialSet.findObjectByInternalName( %assetId );
AssetBrowser.setupCreateNewAsset("TerrainMaterialAsset", AssetBrowser.selectedModule, "TerrainMaterialDlg.saveDirtyMaterial", %assetName);
}
else
{
%assetDef = AssetDatabase.acquireAsset(%material.internalName);
//If we somehow don't have an FX material, make one
%fxMat = %assetDef.getFXMaterialDefinition();
if(!isObject(%fxMat))
{
%fxMat = new Material("TerrainFX_" @ %assetDef.assetName){
mapTo = %material.internalName;
};
%assetDef.add(%fxMat);
}
// Make sure we save any changes to the current selection.
%this.saveDirtyMaterial( %material.internalName );
}
}
function TerrainMaterialDlg::saveDirtyMaterial( %this, %materialAssetId )
{
%assetDef = "";
%mat = "";
//If we happen to have been handed an assetId, process it
if(AssetDatabase.isDeclaredAsset(%materialAssetId))
{
%assetDef = AssetDatabase.acquireAsset(%materialAssetId);
%mat = %assetDef.getMaterialDefinition();
}
else
{
error("TerrainMaterialDlg::saveDirtyMaterial() - attempting to save invalid assetId: " @ %materialAssetId);
return;
}
// Skip over obviously bad cases.
if ( !isObject( %mat ) ||
!%mat.isMemberOfClass( TerrainMaterial ) )
return;
%this.activeMat = %mat;
// Read out properties from the dialog.
@ -487,28 +646,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();
@ -527,6 +686,17 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
%isSRGB = %this-->isSRGB.getValue();
%invertRoughness = %this-->invertRoughness.getValue();
//Effects
%effectColor0 = %this-->effectColor0Swatch.color;
%effectColor1 = %this-->effectColor1Swatch.color;
%showFootsteps = %this-->showFootprintsCheckbox.getValue();
%showDust = %this-->showDustCheckbox.getValue();
%footstepSound = %this.getBehaviorSound("Footstep", %this-->footstepSoundPopup.getText());
%impactSound = %this.getBehaviorSound("Impact", %this-->impactSoundPopup.getText());
%fxMat = %assetDef.getFXMaterialDefinition();
// If no properties of this materials have changed,
// return.
@ -548,7 +718,15 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
%mat.blendHeightBase == %blendHeightBase &&
%mat.blendHeightContrast == %blendHeightContrast &&
%mat.isSRGB == %isSRGB &&
%mat.invertRoughness == %invertRoughness && false)
%mat.invertRoughness == %invertRoughness &&
%fxMat.effectColor[0] == %effectColor0 &&
%fxMat.effectColor[1] == %effectColor1 &&
%fxMat.showFootprints == %showFootsteps &&
%fxMat.showDust == %showDust &&
%fxMat.footstepSoundId == getField(%footstepSound, 0) &&
%fxMat.customFootstepSound == getField(%footstepSound, 1) &&
%fxMat.impactSoundId == getField(%impactSound, 0) &&
%fxMat.customImpactSound == getField(%impactSound, 1) && false)
return;
// Make sure the material name is unique.
@ -589,11 +767,54 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
%mat.isSRGB = %isSRGB;
%mat.invertRoughness = %invertRoughness;
//effects
%fxMat.effectColor[0] = %effectColor0;
%fxMat.effectColor[1] = %effectColor1;
%fxMat.showFootprints = %showFootsteps;
%fxMat.showDust = %showDust;
%fxMat.footstepSoundId = getField(%footstepSound, 0);
%fxMat.customFootstepSound = getField(%footstepSound, 1);
%fxMat.impactSoundId = getField(%impactSound, 0);
%fxMat.customImpactSound = getField(%impactSound, 1);
//Save the material asset
%assetDef = AssetDatabase.acquireAsset(%mat.internalName);
%assetDef.saveAsset();
%didEmbed = false;
%matScriptFile = %assetDef.getScriptPath();
if(%matScriptFile !$= "")
{
//lets up-convert to embedded
%assetDef.add(%mat);
%assetDef.add(%fxMat);
%assetDef.scriptFile = "";
%didEmbed = true;
}
//write it out
if(%assetDef.saveAsset())
{
if(%didEmbed)
{
fileDelete(%matScriptFile); //cleanup the old definition file
}
}
%this.schedule(32, "cleanupDirtyMaterial");
}
function TerrainMaterialDlg::cleanupDirtyMaterial(%this)
{
// Delete the snapshot.
TerrainMaterialDlgSnapshot.delete();
// Remove ourselves from the canvas.
Canvas.popDialog( TerrainMaterialDlg );
call( %this.onApplyCallback, %this.activeMat, %this.matIndex );
TerrainMaterialDlg.matDirty = false;
//%this.setActiveMaterial(%this.activeMat);
}
//-----------------------------------------------------------------------------
function TerrainMaterialDlg::snapshotMaterials( %this )