Reworks the terrain loader code to work with the assets.

Fixes the terrain asset creation, makes the loading logic go through the asset auto-import behavior when a filename or assetid is bound that is not found.
Corrects terrain material binding to properly save and load
Makes the terrain asset inspector fields work as expected.
This commit is contained in:
Areloch 2020-06-25 23:33:01 -05:00
parent 3e1795ba1d
commit 4ce558f042
15 changed files with 500 additions and 283 deletions

View file

@ -123,5 +123,20 @@ DefineConsoleType(TypeImageAssetPtr, ImageAsset)
typedef ImageAsset::ImageTypes ImageAssetType; typedef ImageAsset::ImageTypes ImageAssetType;
DefineEnumType(ImageAssetType); DefineEnumType(ImageAssetType);
#define assetText(x,suff) std::string(std::string(#x) + std::string(#suff)).c_str()
#define scriptBindMapSlot(name, consoleClass) addField(#name, TypeImageFilename, Offset(m##name##Filename, consoleClass), assetText(name,texture map.)); \
addField(assetText(name,Asset), TypeImageAssetPtr, Offset(m##name##AssetId, consoleClass), assetText(name,asset reference.));
#define scriptBindMapArraySlot(name, arraySize, consoleClass) addField(#name, TypeImageFilename, Offset(m##name##Filename, consoleClass), arraySize, assetText(name,texture map.)); \
addField(assetText(name,Asset), TypeImageAssetPtr, Offset(m##name##AssetId, consoleClass), arraySize, assetText(name,asset reference.));
#define DECLARE_TEXTUREMAP(name) FileName m##name##Filename;\
StringTableEntry m##name##AssetId;\
AssetPtr<ImageAsset> m##name##Asset;
#define DECLARE_TEXTUREARRAY(name,max) FileName m##name##Filename[max];\
StringTableEntry m##name##AssetId[max];\
AssetPtr<ImageAsset> m##name##Asset[max];
#endif #endif

View file

@ -366,6 +366,9 @@ bool ShapeAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<ShapeAss
StringTableEntry ShapeAsset::getAssetIdByFilename(StringTableEntry fileName) StringTableEntry ShapeAsset::getAssetIdByFilename(StringTableEntry fileName)
{ {
if (fileName == StringTable->EmptyString())
return StringTable->EmptyString();
StringTableEntry shapeAssetId = StringTable->EmptyString(); StringTableEntry shapeAssetId = StringTable->EmptyString();
AssetQuery query; AssetQuery query;

View file

@ -42,6 +42,8 @@
#include "T3D/assets/TerrainMaterialAsset.h" #include "T3D/assets/TerrainMaterialAsset.h"
#include "assetImporter.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(TerrainAsset); IMPLEMENT_CONOBJECT(TerrainAsset);
@ -87,6 +89,37 @@ ConsoleSetType(TypeTerrainAssetPtr)
Con::warnf("(TypeTerrainAssetPtr) - Cannot set multiple args to a single asset."); Con::warnf("(TypeTerrainAssetPtr) - Cannot set multiple args to a single asset.");
} }
//-----------------------------------------------------------------------------
ConsoleType(assetIdString, TypeTerrainAssetId, String, ASSET_ID_FIELD_PREFIX)
ConsoleGetType(TypeTerrainAssetId)
{
// Fetch asset Id.
return *((const char**)(dptr));
}
ConsoleSetType(TypeTerrainAssetId)
{
// Was a single argument specified?
if (argc == 1)
{
// Yes, so fetch field value.
const char* pFieldValue = argv[0];
// Fetch asset Id.
StringTableEntry* assetId = (StringTableEntry*)(dptr);
// Update asset value.
*assetId = StringTable->insert(pFieldValue);
return;
}
// Warn.
Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset.");
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
TerrainAsset::TerrainAsset() TerrainAsset::TerrainAsset()
@ -202,7 +235,184 @@ bool TerrainAsset::loadTerrain()
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//Utility function to 'fill out' bindings and resources with a matching asset if one exists
bool TerrainAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr<TerrainAsset>* shapeAsset)
{
AssetQuery query;
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, fileName);
if (foundAssetcount == 0)
{
//Didn't find any assets
//If possible, see if we can run an in-place import and the get the asset from that
#if TORQUE_DEBUG
Con::warnf("TerrainAsset::getAssetByFilename - Attempted to in-place import a terrainFile(%s) that had no associated asset", fileName);
#endif
Torque::Path terrFilePath = fileName;
TerrainAsset* newTerrainAsset = new TerrainAsset();
newTerrainAsset->setAssetName(terrFilePath.getFileName().c_str());
String terrainPathBind = String("@=") + terrFilePath.getFileName() + terrFilePath.getExtension();
newTerrainAsset->mTerrainFilePath = StringTable->insert(terrainPathBind.c_str());
newTerrainAsset->saveAsset();
Taml taml;
// Yes, so set it.
taml.setFormatMode(Taml::getFormatModeEnum("xml"));
// Turn-off auto-formatting.
taml.setAutoFormat(false);
String tamlPath = terrFilePath.getFullPath() + "/" + terrFilePath.getFileName() + ".asset.taml";
// Read object.
bool success = taml.write(newTerrainAsset, tamlPath.c_str());
if (!success)
{
Con::printf("TerrainAsset::getAssetByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset", fileName);
return false;
}
ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(fileName);
if (!targetModuleDef)
{
Con::printf("TerrainAsset::getAssetByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset, unable to find a valid Module for the filePath", fileName);
return false;
}
success = AssetDatabase.addDeclaredAsset(targetModuleDef, tamlPath.c_str());
if (!success)
{
Con::printf("TerrainAsset::getAssetByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset, unable to find a register asset with path", tamlPath.c_str());
return false;
}
String assetId = targetModuleDef->getModuleId();
assetId += ":";
assetId += terrFilePath.getFileName().c_str();
StringTableEntry resultingAssetId = StringTable->insert(assetId.c_str());
if (resultingAssetId != StringTable->EmptyString())
{
shapeAsset->setAssetId(resultingAssetId);
if (!shapeAsset->isNull())
return true;
}
//That didn't work, so fail out
return false;
}
else
{
//acquire and bind the asset, and return it out
shapeAsset->setAssetId(query.mAssetList[0]);
return true;
}
}
StringTableEntry TerrainAsset::getAssetIdByFilename(StringTableEntry fileName)
{
if (fileName == StringTable->EmptyString())
return StringTable->EmptyString();
StringTableEntry shapeAssetId = StringTable->EmptyString();
AssetQuery query;
S32 foundAssetcount = AssetDatabase.findAssetLooseFile(&query, fileName);
if (foundAssetcount == 0)
{
//Didn't find any assets
//If possible, see if we can run an in-place import and the get the asset from that
#if TORQUE_DEBUG
Con::warnf("TerrainAsset::getAssetByFilename - Attempted to in-place import a terrainFile(%s) that had no associated asset", fileName);
#endif
Torque::Path terrFilePath = fileName;
TerrainAsset* newTerrainAsset = new TerrainAsset();
newTerrainAsset->setAssetName(terrFilePath.getFileName().c_str());
String terrainPathBind = String("@=") + terrFilePath.getFileName() + terrFilePath.getExtension();
newTerrainAsset->mTerrainFilePath = StringTable->insert(terrainPathBind.c_str());
newTerrainAsset->saveAsset();
Taml taml;
// Yes, so set it.
taml.setFormatMode(Taml::getFormatModeEnum("xml"));
// Turn-off auto-formatting.
taml.setAutoFormat(false);
String tamlPath = terrFilePath.getFullPath() + "/" + terrFilePath.getFileName() + ".asset.taml";
// Read object.
bool success = taml.write(newTerrainAsset, tamlPath.c_str());
if (!success)
{
Con::printf("TerrainAsset::getAssetIdByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset", fileName);
return false;
}
ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(fileName);
if (!targetModuleDef)
{
Con::printf("TerrainAsset::getAssetIdByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset, unable to find a valid Module for the filePath", fileName);
return false;
}
success = AssetDatabase.addDeclaredAsset(targetModuleDef, tamlPath.c_str());
if (!success)
{
Con::printf("TerrainAsset::getAssetIdByFilename() - failed to auto-import terrainfile(%s) as an TerrainAsset, unable to find a register asset with path", tamlPath.c_str());
return false;
}
String assetId = targetModuleDef->getModuleId();
assetId += ":";
assetId += terrFilePath.getFileName().c_str();
StringTableEntry resultingAssetId = StringTable->insert(assetId.c_str());
if (resultingAssetId != StringTable->EmptyString())
{
shapeAssetId = resultingAssetId;
return shapeAssetId;
}
}
else
{
//acquire and bind the asset, and return it out
shapeAssetId = query.mAssetList[0];
}
return shapeAssetId;
}
bool TerrainAsset::getAssetById(StringTableEntry assetId, AssetPtr<TerrainAsset>* shapeAsset)
{
(*shapeAsset) = assetId;
if (!shapeAsset->isNull())
return true;
return false;
}
//------------------------------------------------------------------------------
void TerrainAsset::copyTo(SimObject* object) void TerrainAsset::copyTo(SimObject* object)
{ {
// Call to parent. // Call to parent.
@ -231,68 +441,37 @@ void GuiInspectorTypeTerrainAssetPtr::consoleInit()
GuiControl* GuiInspectorTypeTerrainAssetPtr::constructEditControl() GuiControl* GuiInspectorTypeTerrainAssetPtr::constructEditControl()
{ {
// Create base filename edit controls // Create base filename edit controls
mUseHeightOverride = true; GuiControl* retCtrl = Parent::constructEditControl();
mHeightOverride = 100; if (retCtrl == NULL)
return retCtrl;
mMatEdContainer = new GuiControl();
mMatEdContainer->registerObject();
addObject(mMatEdContainer);
// Create "Open in ShapeEditor" button
mMatPreviewButton = new GuiBitmapButtonCtrl();
const char* matAssetId = getData();
TerrainAsset* matAsset = AssetDatabase.acquireAsset< TerrainAsset>(matAssetId);
//TerrainMaterial* materialDef = nullptr;
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
/*if (!Sim::findObject(matAsset->getMaterialDefinitionName(), materialDef))
{
Con::errorf("GuiInspectorTypeTerrainAssetPtr::constructEditControl() - unable to find material in asset");
}
else
{
mMatPreviewButton->setBitmap(materialDef->mDiffuseMapFilename[0]);
}*/
mMatPreviewButton->setPosition(0, 0);
mMatPreviewButton->setExtent(100,100);
// Change filespec // Change filespec
char szBuffer[512]; char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainAsset\", \"AssetBrowser.changeAsset\", %d, %s);", dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
mInspector->getComponentGroupTargetId(), mCaption); mInspector->getInspectObject()->getIdString(), mCaption);
mMatPreviewButton->setField("Command", szBuffer); mBrowseButton->setField("Command", szBuffer);
mMatPreviewButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile"); const char* id = mInspector->getInspectObject()->getIdString();
mMatPreviewButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mMatPreviewButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
StringBuilder strbld; setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
/*strbld.append(matAsset->getMaterialDefinitionName());
strbld.append("\n");
strbld.append("Open this file in the Material Editor");*/
mMatPreviewButton->setDataField(StringTable->insert("tooltip"), NULL, strbld.data()); // Create "Open in ShapeEditor" button
mShapeEdButton = new GuiBitmapButtonCtrl();
_registerEditControl(mMatPreviewButton); mShapeEdButton->setField("Command", "EditorGui.setEditor(TerrainEditorPlugin);");
//mMatPreviewButton->registerObject();
mMatEdContainer->addObject(mMatPreviewButton);
mMatAssetIdTxt = new GuiTextEditCtrl(); char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mMatAssetIdTxt->registerObject(); mShapeEdButton->setBitmap(bitmapName);
mMatAssetIdTxt->setActive(false);
mMatAssetIdTxt->setText(matAssetId); mShapeEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
mShapeEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
mShapeEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
mShapeEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the Shape Editor");
mMatAssetIdTxt->setBounds(100, 0, 150, 18); mShapeEdButton->registerObject();
mMatEdContainer->addObject(mMatAssetIdTxt); addObject(mShapeEdButton);
return mMatEdContainer; return retCtrl;
} }
bool GuiInspectorTypeTerrainAssetPtr::updateRects() bool GuiInspectorTypeTerrainAssetPtr::updateRects()
@ -306,21 +485,32 @@ bool GuiInspectorTypeTerrainAssetPtr::updateRects()
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y); mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent); bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
if (mBrowseButton != NULL)
if (mMatEdContainer != nullptr)
{ {
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 (mShapeEdButton != NULL)
{ {
mMatPreviewButton->resize(Point2I::Zero, Point2I(100, 100)); RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
} resized |= mShapeEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
if (mMatAssetIdTxt != nullptr)
{
mMatAssetIdTxt->resize(Point2I(100, 0), Point2I(mEditCtrlRect.extent.x - 100, 18));
} }
return resized; return resized;
} }
IMPLEMENT_CONOBJECT(GuiInspectorTypeTerrainAssetId);
ConsoleDocClass(GuiInspectorTypeTerrainAssetId,
"@brief Inspector field type for Shapes\n\n"
"Editor use only.\n\n"
"@internal"
);
void GuiInspectorTypeTerrainAssetId::consoleInit()
{
Parent::consoleInit();
ConsoleBaseType::getType(TypeTerrainAssetId)->setInspectorFieldType("GuiInspectorTypeTerrainAssetId");
}

View file

@ -82,6 +82,10 @@ public:
bool loadTerrain(); bool loadTerrain();
static bool getAssetByFilename(StringTableEntry fileName, AssetPtr<TerrainAsset>* shapeAsset);
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
static bool getAssetById(StringTableEntry assetId, AssetPtr<TerrainAsset>* shapeAsset);
/// Declare Console Object. /// Declare Console Object.
DECLARE_CONOBJECT(TerrainAsset); DECLARE_CONOBJECT(TerrainAsset);
@ -94,18 +98,17 @@ protected:
}; };
DefineConsoleType(TypeTerrainAssetPtr, TerrainAsset) DefineConsoleType(TypeTerrainAssetPtr, TerrainAsset)
DefineConsoleType(TypeTerrainAssetId, String)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class // TypeAssetId GuiInspectorField Class
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class GuiInspectorTypeTerrainAssetPtr : public GuiInspectorField class GuiInspectorTypeTerrainAssetPtr : public GuiInspectorTypeFileName
{ {
typedef GuiInspectorField Parent; typedef GuiInspectorTypeFileName Parent;
public: public:
GuiControl* mMatEdContainer; GuiBitmapButtonCtrl* mShapeEdButton;
GuiBitmapButtonCtrl *mMatPreviewButton;
GuiTextEditCtrl *mMatAssetIdTxt;
DECLARE_CONOBJECT(GuiInspectorTypeTerrainAssetPtr); DECLARE_CONOBJECT(GuiInspectorTypeTerrainAssetPtr);
static void consoleInit(); static void consoleInit();
@ -114,5 +117,14 @@ public:
virtual bool updateRects(); virtual bool updateRects();
}; };
class GuiInspectorTypeTerrainAssetId : public GuiInspectorTypeTerrainAssetPtr
{
typedef GuiInspectorTypeTerrainAssetPtr Parent;
public:
DECLARE_CONOBJECT(GuiInspectorTypeTerrainAssetId);
static void consoleInit();
};
#endif // _ASSET_BASE_H_ #endif // _ASSET_BASE_H_

View file

@ -1485,7 +1485,7 @@ StringTableEntry AssetImporter::autoImportFile(Torque::Path filePath)
} }
//Find out if the filepath has an associated module to it. If we're importing in-place, it needs to be within a module's directory //Find out if the filepath has an associated module to it. If we're importing in-place, it needs to be within a module's directory
ModuleDefinition* targetModuleDef = getModuleFromPath(filePath); ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(filePath);
if (targetModuleDef == nullptr) if (targetModuleDef == nullptr)
{ {

View file

@ -603,7 +603,7 @@ public:
/// <para>@param filePath, File path to parse the the module from</para> /// <para>@param filePath, File path to parse the the module from</para>
/// <para>@return ModuleDefinition that was found</para> /// <para>@return ModuleDefinition that was found</para>
/// </summary> /// </summary>
ModuleDefinition* getModuleFromPath(Torque::Path filePath); static ModuleDefinition* getModuleFromPath(Torque::Path filePath);
/// <summary> /// <summary>
/// Parses an asset's name to try and find if any of the import config's suffix lists match to it /// Parses an asset's name to try and find if any of the import config's suffix lists match to it

View file

@ -151,11 +151,6 @@ Material::Material()
initMapSlot(GlowMap, i); initMapSlot(GlowMap, i);
initMapSlot(DetailNormalMap, i); initMapSlot(DetailNormalMap, i);
//cogs specific
initMapSlot(AlbedoDamageMap, i);
initMapSlot(NormalDamageMap, i);
initMapSlot(CompositeDamageMap, i);
mParallaxScale[i] = 0.0f; mParallaxScale[i] = 0.0f;
mVertLit[i] = false; mVertLit[i] = false;
@ -194,9 +189,6 @@ Material::Material()
// Deferred Shading // Deferred Shading
mMatInfoFlags[i] = 0.0f; mMatInfoFlags[i] = 0.0f;
// Damage
mMaterialDamageMin[i] = 0.0f;
mAlbedoDamageMapSRGB[i] = true;
mGlowMul[i] = 0.0f; mGlowMul[i] = 0.0f;
} }
@ -243,10 +235,6 @@ Material::Material()
} }
#define assetText(x,suff) std::string(std::string(#x) + std::string(#suff)).c_str()
#define scriptBindMapSlot(name,arraySize) addField(#name, TypeImageFilename, Offset(m##name##Filename, Material), arraySize, assetText(name,texture map.)); \
addField(assetText(name,Asset), TypeImageAssetPtr, Offset(m##name##AssetId, Material), arraySize, assetText(name,asset reference.));
void Material::initPersistFields() void Material::initPersistFields()
{ {
addField("mapTo", TypeRealString, Offset(mMapTo, Material), addField("mapTo", TypeRealString, Offset(mMapTo, Material),
@ -258,18 +246,18 @@ void Material::initPersistFields()
"This color is multiplied against the diffuse texture color. If no diffuse texture " "This color is multiplied against the diffuse texture color. If no diffuse texture "
"is present this is the material color." ); "is present this is the material color." );
scriptBindMapSlot(DiffuseMap, MAX_STAGES); scriptBindMapArraySlot(DiffuseMap, MAX_STAGES, Material);
scriptBindMapSlot(OverlayMap, MAX_STAGES); scriptBindMapArraySlot(OverlayMap, MAX_STAGES, Material);
scriptBindMapSlot(LightMap, MAX_STAGES); scriptBindMapArraySlot(LightMap, MAX_STAGES, Material);
scriptBindMapSlot(ToneMap, MAX_STAGES); scriptBindMapArraySlot(ToneMap, MAX_STAGES, Material);
scriptBindMapSlot(DetailMap, MAX_STAGES); scriptBindMapArraySlot(DetailMap, MAX_STAGES, Material);
scriptBindMapSlot(NormalMap, MAX_STAGES); scriptBindMapArraySlot(NormalMap, MAX_STAGES, Material);
scriptBindMapSlot(PBRConfigMap, MAX_STAGES); scriptBindMapArraySlot(PBRConfigMap, MAX_STAGES, Material);
scriptBindMapSlot(RoughMap, MAX_STAGES); scriptBindMapArraySlot(RoughMap, MAX_STAGES, Material);
scriptBindMapSlot(AOMap, MAX_STAGES); scriptBindMapArraySlot(AOMap, MAX_STAGES, Material);
scriptBindMapSlot(MetalMap, MAX_STAGES); scriptBindMapArraySlot(MetalMap, MAX_STAGES, Material);
scriptBindMapSlot(GlowMap, MAX_STAGES); scriptBindMapArraySlot(GlowMap, MAX_STAGES, Material);
scriptBindMapSlot(DetailNormalMap, MAX_STAGES); scriptBindMapArraySlot(DetailNormalMap, MAX_STAGES, Material);
addField("diffuseMapSRGB", TypeBool, Offset(mDiffuseMapSRGB, Material), MAX_STAGES, addField("diffuseMapSRGB", TypeBool, Offset(mDiffuseMapSRGB, Material), MAX_STAGES,
"Enable sRGB for the diffuse color texture map."); "Enable sRGB for the diffuse color texture map.");
@ -422,22 +410,6 @@ void Material::initPersistFields()
endArray( "Stages" ); endArray( "Stages" );
addGroup("Damage");
//cogs
scriptBindMapSlot(AlbedoDamageMap, MAX_STAGES);
/// Damage blend maps (normal)
scriptBindMapSlot(NormalDamageMap, MAX_STAGES);
/// Damage blend maps (Roughness, AO, Metalness)
scriptBindMapSlot(CompositeDamageMap, MAX_STAGES);
addField("albedoDamageSRGB", TypeBool, Offset(mAlbedoDamageMapSRGB, Material), MAX_STAGES,
"Enable sRGB for the albedo damage map");
addField("minDamage", TypeF32, Offset(mMaterialDamageMin, Material), MAX_STAGES,
"The minimum ammount of blended damage.");
endGroup("Damage");
addField( "castShadows", TypeBool, Offset(mCastShadows, Material), addField( "castShadows", TypeBool, Offset(mCastShadows, Material),
"If set to false the lighting system will not cast shadows from this material." ); "If set to false the lighting system will not cast shadows from this material." );
@ -629,11 +601,6 @@ bool Material::onAdd()
bindMapSlot(MetalMap, i); bindMapSlot(MetalMap, i);
bindMapSlot(GlowMap, i); bindMapSlot(GlowMap, i);
bindMapSlot(DetailNormalMap, i); bindMapSlot(DetailNormalMap, i);
//cogs specific
bindMapSlot(AlbedoDamageMap, i);
bindMapSlot(NormalDamageMap, i);
bindMapSlot(CompositeDamageMap, i);
} }
_mapMaterial(); _mapMaterial();

View file

@ -61,10 +61,6 @@ class MaterialSoundProfile;
class MaterialPhysicsProfile; class MaterialPhysicsProfile;
class CustomShaderFeatureData; class CustomShaderFeatureData;
#define DECLARE_TEXTUREARRAY(name,max) FileName m##name##Filename[max];\
StringTableEntry m##name##AssetId[max];\
AssetPtr<ImageAsset> m##name##Asset[max];
/// The basic material definition. /// The basic material definition.
class Material : public BaseMaterialDefinition class Material : public BaseMaterialDefinition
{ {
@ -244,17 +240,6 @@ public:
F32 mAccuCoverage[MAX_STAGES]; F32 mAccuCoverage[MAX_STAGES];
F32 mAccuSpecular[MAX_STAGES]; F32 mAccuSpecular[MAX_STAGES];
//cogs specific
/// Damage blend maps (albedo)
DECLARE_TEXTUREARRAY(AlbedoDamageMap, MAX_STAGES);
bool mAlbedoDamageMapSRGB[MAX_STAGES];
/// Damage blend maps (normal)
DECLARE_TEXTUREARRAY(NormalDamageMap, MAX_STAGES);
/// Damage blend maps (Roughness, AO, Metalness)
DECLARE_TEXTUREARRAY(CompositeDamageMap, MAX_STAGES);
/// Damage blend minimum
F32 mMaterialDamageMin[MAX_STAGES];
/// This color is the diffuse color of the material /// This color is the diffuse color of the material
/// or if it has a texture it is multiplied against /// or if it has a texture it is multiplied against
/// the diffuse texture color. /// the diffuse texture color.

View file

@ -304,7 +304,7 @@ bool TerrainBlock::_setBaseTexFormat(void *obj, const char *index, const char *d
// If the cached base texture is older that the terrain file or // If the cached base texture is older that the terrain file or
// it doesn't exist then generate and cache it. // it doesn't exist then generate and cache it.
String baseCachePath = terrain->_getBaseTexCacheFileName(); String baseCachePath = terrain->_getBaseTexCacheFileName();
if (Platform::compareModifiedTimes(baseCachePath, terrain->mTerrFileName) < 0) if (Platform::compareModifiedTimes(baseCachePath, terrain->mTerrainAsset->getTerrainFilePath()) < 0)
terrain->_updateBaseTexture(true); terrain->_updateBaseTexture(true);
break; break;
} }
@ -337,7 +337,7 @@ bool TerrainBlock::_setLightMapSize( void *obj, const char *index, const char *d
bool TerrainBlock::setFile( const FileName &terrFileName ) bool TerrainBlock::setFile( const FileName &terrFileName )
{ {
if ( terrFileName == mTerrFileName ) if ( mTerrainAsset && mTerrainAsset->getTerrainFilePath() == terrFileName )
return mFile != NULL; return mFile != NULL;
Resource<TerrainFile> file = ResourceManager::get().load( terrFileName ); Resource<TerrainFile> file = ResourceManager::get().load( terrFileName );
@ -352,27 +352,104 @@ bool TerrainBlock::setFile( const FileName &terrFileName )
void TerrainBlock::setFile(const Resource<TerrainFile>& terr) void TerrainBlock::setFile(const Resource<TerrainFile>& terr)
{ {
if (mFile)
{
GFXTextureManager::removeEventDelegate(this, &TerrainBlock::_onTextureEvent);
MATMGR->getFlushSignal().remove(this, &TerrainBlock::_onFlushMaterials);
}
mFile = terr; mFile = terr;
mTerrFileName = terr.getPath();
if (!mFile)
{
Con::errorf("TerrainBlock::setFile() - No valid terrain file!");
return;
}
if (terr->mNeedsResaving)
{
if (Platform::messageBox("Update Terrain File", "You appear to have a Terrain file in an older format. Do you want Torque to update it?", MBOkCancel, MIQuestion) == MROk)
{
mFile->save(terr->mFilePath.getFullPath());
mFile->mNeedsResaving = false;
}
}
if (terr->mFileVersion != TerrainFile::FILE_VERSION || terr->mNeedsResaving)
{
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" PLEASE RESAVE THE TERRAIN FILE FOR THIS MISSION! THANKS!");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
}
_updateBounds();
resetWorldBox();
setRenderTransform(mObjToWorld);
if (isClientObject())
{
if (mCRC != terr.getChecksum())
{
NetConnection::setLastError("Your terrain file doesn't match the version that is running on the server.");
return;
}
clearLightMap();
// Init the detail layer rendering helper.
_updateMaterials();
_updateLayerTexture();
// If the cached base texture is older that the terrain file or
// it doesn't exist then generate and cache it.
String baseCachePath = _getBaseTexCacheFileName();
if (Platform::compareModifiedTimes(baseCachePath, mTerrainAsset->getTerrainFilePath()) < 0)
_updateBaseTexture(true);
// The base texture should have been cached by now... so load it.
mBaseTex.set(baseCachePath, &GFXStaticTextureSRGBProfile, "TerrainBlock::mBaseTex");
GFXTextureManager::addEventDelegate(this, &TerrainBlock::_onTextureEvent);
MATMGR->getFlushSignal().notify(this, &TerrainBlock::_onFlushMaterials);
// Build the terrain quadtree.
_rebuildQuadtree();
// Preload all the materials.
mCell->preloadMaterials();
mZoningDirty = true;
SceneZoneSpaceManager::getZoningChangedSignal().notify(this, &TerrainBlock::_onZoningChanged);
}
else
mCRC = terr.getChecksum();
} }
bool TerrainBlock::setTerrainAsset(const StringTableEntry terrainAssetId) bool TerrainBlock::setTerrainAsset(const StringTableEntry terrainAssetId)
{ {
mTerrainAssetId = terrainAssetId; if (TerrainAsset::getAssetById(terrainAssetId, &mTerrainAsset))
mTerrainAsset = mTerrainAssetId;
if (mTerrainAsset.isNull())
{ {
Con::errorf("[TerrainBlock] Failed to load terrain asset."); //Special exception case. If we've defaulted to the 'no shape' mesh, don't save it out, we'll retain the original ids/paths so it doesn't break
return false; //the TSStatic
if (!mTerrainAsset.isNull())
{
mTerrFileName = StringTable->EmptyString();
}
setFile(mTerrainAsset->getTerrainResource());
setMaskBits(-1);
return true;
} }
Resource<TerrainFile> file = mTerrainAsset->getTerrainResource(); return false;
if (!file)
return false;
setFile(file);
return true;
} }
bool TerrainBlock::save(const char *filename) bool TerrainBlock::save(const char *filename)
@ -425,19 +502,40 @@ bool TerrainBlock::saveAsset()
bool TerrainBlock::_setTerrainFile( void *obj, const char *index, const char *data ) bool TerrainBlock::_setTerrainFile( void *obj, const char *index, const char *data )
{ {
static_cast<TerrainBlock*>( obj )->setFile( FileName( data ) ); //TerrainBlock* terrain = static_cast<TerrainBlock*>( obj )->setFile( FileName( data ) );
return false; TerrainBlock* terrain = static_cast<TerrainBlock*>(obj);
StringTableEntry file = StringTable->insert(data);
if (file != StringTable->EmptyString())
{
StringTableEntry assetId = TerrainAsset::getAssetIdByFilename(file);
if (assetId != StringTable->EmptyString())
{
if (terrain->setTerrainAsset(assetId))
{
terrain->mTerrainAssetId = assetId;
terrain->mTerrFileName = StringTable->EmptyString();
return false;
}
}
else
{
terrain->mTerrainAsset = StringTable->EmptyString();
}
}
return true;
} }
bool TerrainBlock::_setTerrainAsset(void* obj, const char* index, const char* data) bool TerrainBlock::_setTerrainAsset(void* obj, const char* index, const char* data)
{ {
TerrainBlock* terr = static_cast<TerrainBlock*>(obj);// ->setFile(FileName(data)); TerrainBlock* terr = static_cast<TerrainBlock*>(obj);// ->setFile(FileName(data));
terr->setTerrainAsset(StringTable->insert(data)); terr->mTerrainAssetId = StringTable->insert(data);
terr->setMaskBits(FileMask | HeightMapChangeMask); return terr->setTerrainAsset(terr->mTerrainAssetId);
return false;
} }
void TerrainBlock::_updateBounds() void TerrainBlock::_updateBounds()
@ -868,6 +966,27 @@ void TerrainBlock::addMaterial( const String &name, U32 insertAt )
{ {
mFile->mMaterials.push_back( mat ); mFile->mMaterials.push_back( mat );
mFile->_initMaterialInstMapping(); mFile->_initMaterialInstMapping();
bool isSrv = isServerObject();
//now we update our asset
if (mTerrainAsset)
{
StringTableEntry terrMatName = StringTable->insert(name.c_str());
AssetQuery* aq = new AssetQuery();
U32 foundCount = AssetDatabase.findAssetType(aq, "TerrainMaterialAsset");
for (U32 i = 0; i < foundCount; i++)
{
TerrainMaterialAsset* terrMatAsset = AssetDatabase.acquireAsset<TerrainMaterialAsset>(aq->mAssetList[i]);
if (terrMatAsset && terrMatAsset->getMaterialDefinitionName() == terrMatName)
{
//Do iterative logic to find the next available slot and write to it with our new mat field
mTerrainAsset->setDataField(StringTable->insert("terrainMaterialAsset"), nullptr, aq->mAssetList[i]);
}
}
}
} }
else else
{ {
@ -991,101 +1110,9 @@ bool TerrainBlock::onAdd()
return false; return false;
} }
mFile = terr;
}
else
{
if (mTerrFileName.isEmpty())
{
mTerrFileName = Con::getVariable("$Client::MissionFile");
String terrainDirectory(Con::getVariable("$pref::Directories::Terrain"));
if (terrainDirectory.isEmpty())
{
terrainDirectory = "data/terrains/";
}
mTerrFileName.replace("tools/levels/", terrainDirectory);
mTerrFileName.replace("levels/", terrainDirectory);
Vector<String> materials;
materials.push_back("warning_material");
TerrainFile::create(&mTerrFileName, 256, materials);
}
terr = ResourceManager::get().load(mTerrFileName);
if (terr == NULL)
{
if (isClientObject())
NetConnection::setLastError("You are missing a file needed to play this mission: %s", mTerrFileName.c_str());
return false;
}
setFile(terr); setFile(terr);
} }
if ( terr->mNeedsResaving )
{
if (Platform::messageBox("Update Terrain File", "You appear to have a Terrain file in an older format. Do you want Torque to update it?", MBOkCancel, MIQuestion) == MROk)
{
terr->save(terr->mFilePath.getFullPath());
terr->mNeedsResaving = false;
}
}
if (terr->mFileVersion != TerrainFile::FILE_VERSION || terr->mNeedsResaving)
{
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" PLEASE RESAVE THE TERRAIN FILE FOR THIS MISSION! THANKS!");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
Con::errorf(" *********************************************************");
}
_updateBounds();
resetWorldBox();
setRenderTransform(mObjToWorld);
if (isClientObject())
{
if ( mCRC != terr.getChecksum() )
{
NetConnection::setLastError("Your terrain file doesn't match the version that is running on the server.");
return false;
}
clearLightMap();
// Init the detail layer rendering helper.
_updateMaterials();
_updateLayerTexture();
// If the cached base texture is older that the terrain file or
// it doesn't exist then generate and cache it.
String baseCachePath = _getBaseTexCacheFileName();
if ( Platform::compareModifiedTimes( baseCachePath, mTerrFileName ) < 0 )
_updateBaseTexture( true );
// The base texture should have been cached by now... so load it.
mBaseTex.set( baseCachePath, &GFXStaticTextureSRGBProfile, "TerrainBlock::mBaseTex" );
GFXTextureManager::addEventDelegate( this, &TerrainBlock::_onTextureEvent );
MATMGR->getFlushSignal().notify( this, &TerrainBlock::_onFlushMaterials );
// Build the terrain quadtree.
_rebuildQuadtree();
// Preload all the materials.
mCell->preloadMaterials();
mZoningDirty = true;
SceneZoneSpaceManager::getZoningChangedSignal().notify( this, &TerrainBlock::_onZoningChanged );
}
else
mCRC = terr.getChecksum();
addToScene(); addToScene();
_updatePhysics(); _updatePhysics();
@ -1095,7 +1122,7 @@ bool TerrainBlock::onAdd()
String TerrainBlock::_getBaseTexCacheFileName() const String TerrainBlock::_getBaseTexCacheFileName() const
{ {
Torque::Path basePath( mTerrFileName ); Torque::Path basePath( mTerrainAsset->getTerrainFilePath() );
basePath.setFileName( basePath.getFileName() + "_basetex" ); basePath.setFileName( basePath.getFileName() + "_basetex" );
basePath.setExtension( formatToExtension(mBaseTexFormat) ); basePath.setExtension( formatToExtension(mBaseTexFormat) );
return basePath.getFullPath(); return basePath.getFullPath();
@ -1222,7 +1249,7 @@ void TerrainBlock::initPersistFields()
{ {
addGroup( "Media" ); addGroup( "Media" );
addProtectedField("terrainAsset", TypeTerrainAssetPtr, Offset(mTerrainAsset, TerrainBlock), addProtectedField("terrainAsset", TypeTerrainAssetId, Offset(mTerrainAssetId, TerrainBlock),
&TerrainBlock::_setTerrainAsset, &defaultProtectedGetFn, &TerrainBlock::_setTerrainAsset, &defaultProtectedGetFn,
"The source terrain data asset."); "The source terrain data asset.");
@ -1289,8 +1316,9 @@ U32 TerrainBlock::packUpdate(NetConnection* con, U32 mask, BitStream *stream)
if ( stream->writeFlag( mask & FileMask ) ) if ( stream->writeFlag( mask & FileMask ) )
{ {
stream->write( mTerrFileName ); S32 idasdasdf = getId();
stream->write( mCRC ); stream->write(mCRC);
stream->writeString( mTerrainAsset.getAssetId() );
} }
if ( stream->writeFlag( mask & SizeMask ) ) if ( stream->writeFlag( mask & SizeMask ) )
@ -1328,14 +1356,11 @@ void TerrainBlock::unpackUpdate(NetConnection* con, BitStream *stream)
if ( stream->readFlag() ) // FileMask if ( stream->readFlag() ) // FileMask
{ {
FileName terrFile; stream->read(&mCRC);
stream->read( &terrFile );
stream->read( &mCRC );
if ( isProperlyAdded() ) char buffer[256];
setFile( terrFile ); stream->readString(buffer);
else bool validAsset = setTerrainAsset(StringTable->insert(buffer));
mTerrFileName = terrFile;
} }
if ( stream->readFlag() ) // SizeMask if ( stream->readFlag() ) // SizeMask

View file

@ -766,15 +766,15 @@ void TerrainFile::create( String *inOutFilename,
U32 newSize, U32 newSize,
const Vector<String> &materials ) const Vector<String> &materials )
{ {
// Determine the path and basename - first try using the input filename (mission name) // Determine the path and basename
Torque::Path basePath( *inOutFilename ); Torque::Path basePath( *inOutFilename );
if ( !basePath.getExtension().equal("mis") ) if ( !basePath.getExtension().equal("ter") )
{ {
// Use the default path and filename // Use the default path and filename
String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) ); String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) );
if ( terrainDirectory.isEmpty() ) if ( terrainDirectory.isEmpty() )
{ {
terrainDirectory = "art/terrains"; terrainDirectory = "data/terrains";
} }
basePath.setPath( terrainDirectory ); basePath.setPath( terrainDirectory );
basePath.setFileName( "terrain" ); basePath.setFileName( "terrain" );

View file

@ -46,14 +46,14 @@ DefineEngineStaticMethod( TerrainBlock, createNew, S32, (String terrainName, U32
// We create terrains based on level name. If the user wants to rename the terrain names; they have to // We create terrains based on level name. If the user wants to rename the terrain names; they have to
// rename it themselves in their file browser. The main reason for this is so we can easily increment for ourselves; // rename it themselves in their file browser. The main reason for this is so we can easily increment for ourselves;
// and because its too easy to rename the terrain object and forget to take care of the terrain filename afterwards. // and because its too easy to rename the terrain object and forget to take care of the terrain filename afterwards.
FileName terrFileName( Con::getVariable("$Client::MissionFile") );
String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) ); String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) );
if ( terrainDirectory.isEmpty() ) if ( terrainDirectory.isEmpty() )
{ {
terrainDirectory = "art/terrains/"; terrainDirectory = "data/terrains/";
} }
terrFileName.replace("tools/levels/", terrainDirectory);
terrFileName.replace("levels/", terrainDirectory); String terrFileName = terrainDirectory + "/" + terrainName + ".ter";
TerrainFile::create( &terrFileName, resolution, materials ); TerrainFile::create( &terrFileName, resolution, materials );
@ -273,18 +273,32 @@ bool TerrainBlock::import( const GBitmap &heightMap,
{ {
// Get a unique file name for the terrain. // Get a unique file name for the terrain.
String fileName( getName() ); String fileName( getName() );
if ( fileName.isEmpty() ) if (fileName.isEmpty())
fileName = "terrain"; {
mTerrFileName = FS::MakeUniquePath( "levels", fileName, "ter" ); fileName = Torque::Path(Con::getVariable("$Client::MissionFile")).getFileName();
// TODO: We have to save and reload the file to get if (fileName.isEmpty())
fileName = "terrain";
}
String terrainFileName = FS::MakeUniquePath( "levels", fileName, "ter" );
if (!TerrainAsset::getAssetByFilename(terrainFileName, &mTerrainAsset))
{
return false;
}
else
{
mFile = mTerrainAsset->getTerrainResource();
}
/*// TODO: We have to save and reload the file to get
// it into the resource system. This creates lots // it into the resource system. This creates lots
// of temporary unused files when the terrain is // of temporary unused files when the terrain is
// discarded because of undo or quit. // discarded because of undo or quit.
TerrainFile *file = new TerrainFile; TerrainFile *file = new TerrainFile;
file->save( mTerrFileName ); file->save( mTerrFileName );
delete file; delete file;
mFile = ResourceManager::get().load( mTerrFileName ); mFile = ResourceManager::get().load( mTerrFileName );*/
} }
// The file does a bunch of the work. // The file does a bunch of the work.

View file

@ -26,6 +26,8 @@
#include "gfx/gfxTextureManager.h" #include "gfx/gfxTextureManager.h"
#include "gfx/bitmap/gBitmap.h" #include "gfx/bitmap/gBitmap.h"
#include <string>
IMPLEMENT_CONOBJECT( TerrainMaterial ); IMPLEMENT_CONOBJECT( TerrainMaterial );
@ -77,7 +79,9 @@ TerrainMaterial::~TerrainMaterial()
void TerrainMaterial::initPersistFields() void TerrainMaterial::initPersistFields()
{ {
addField( "diffuseMap", TypeStringFilename, Offset( mDiffuseMap, TerrainMaterial ), "Base texture for the material" ); scriptBindMapSlot(DiffuseMap, TerrainMaterial);
//addField( "diffuseMap", TypeStringFilename, Offset( mDiffuseMap, TerrainMaterial ), "Base texture for the material" );
addField( "diffuseSize", TypeF32, Offset( mDiffuseSize, TerrainMaterial ), "Used to scale the diffuse map to the material square" ); addField( "diffuseSize", TypeF32, Offset( mDiffuseSize, TerrainMaterial ), "Used to scale the diffuse map to the material square" );
addField( "normalMap", TypeStringFilename, Offset( mNormalMap, TerrainMaterial ), "Bump map for the material" ); addField( "normalMap", TypeStringFilename, Offset( mNormalMap, TerrainMaterial ), "Bump map for the material" );
@ -154,7 +158,7 @@ TerrainMaterial* TerrainMaterial::findOrCreate( const char *nameOrPath )
{ {
mat = new TerrainMaterial(); mat = new TerrainMaterial();
mat->setInternalName( nameOrPath ); mat->setInternalName( nameOrPath );
mat->mDiffuseMap = nameOrPath; mat->mDiffuseMapFilename = nameOrPath;
mat->registerObject(); mat->registerObject();
Sim::getRootGroup()->addObject( mat ); Sim::getRootGroup()->addObject( mat );
return mat; return mat;
@ -169,7 +173,7 @@ TerrainMaterial* TerrainMaterial::findOrCreate( const char *nameOrPath )
// fallback here just in case it gets "lost". // fallback here just in case it gets "lost".
mat = new TerrainMaterial(); mat = new TerrainMaterial();
mat->setInternalName( "warning_material" ); mat->setInternalName( "warning_material" );
mat->mDiffuseMap = GFXTextureManager::getWarningTexturePath(); mat->mDiffuseMapFilename = GFXTextureManager::getWarningTexturePath();
mat->mDiffuseSize = 500; mat->mDiffuseSize = 500;
mat->mDetailMap = GFXTextureManager::getWarningTexturePath(); mat->mDetailMap = GFXTextureManager::getWarningTexturePath();
mat->mDetailSize = 5; mat->mDetailSize = 5;

View file

@ -27,6 +27,7 @@
#include "console/simBase.h" #include "console/simBase.h"
#endif #endif
#include "T3D/assets/ImageAsset.h"
/// The TerrainMaterial class orginizes the material settings /// The TerrainMaterial class orginizes the material settings
/// for a single terrain material layer. /// for a single terrain material layer.
@ -37,7 +38,11 @@ class TerrainMaterial : public SimObject
protected: protected:
/// ///
FileName mDiffuseMap; //FileName mDiffuseMap;
//AssetPtr<ImageAsset> mDiffuseAsset;
DECLARE_TEXTUREMAP(DiffuseMap);
/// The size of the diffuse base map in meters /// The size of the diffuse base map in meters
/// used to generate its texture coordinates. /// used to generate its texture coordinates.
@ -99,7 +104,7 @@ public:
/// a material is not found or defined. /// a material is not found or defined.
static TerrainMaterial* getWarningMaterial(); static TerrainMaterial* getWarningMaterial();
const String& getDiffuseMap() const { return mDiffuseMap; } const String& getDiffuseMap() const { return mDiffuseMapFilename; }
F32 getDiffuseSize() const { return mDiffuseSize; } F32 getDiffuseSize() const { return mDiffuseSize; }

View file

@ -85,6 +85,9 @@ void TerrainBlock::_onFlushMaterials()
void TerrainBlock::_updateMaterials() void TerrainBlock::_updateMaterials()
{ {
if (!mFile)
return;
mBaseTextures.setSize( mFile->mMaterials.size() ); mBaseTextures.setSize( mFile->mMaterials.size() );
mMaxDetailDistance = 0.0f; mMaxDetailDistance = 0.0f;
@ -363,6 +366,9 @@ void TerrainBlock::_renderBlock( SceneRenderState *state )
{ {
PROFILE_SCOPE( TerrainBlock_RenderBlock ); PROFILE_SCOPE( TerrainBlock_RenderBlock );
if (!mFile)
return;
// Prevent rendering shadows if feature is disabled // Prevent rendering shadows if feature is disabled
if ( !mCastShadows && state->isShadowPass() ) if ( !mCastShadows && state->isShadowPass() )
return; return;

View file

@ -38,20 +38,11 @@ function AssetBrowser::createTerrainAsset(%this)
AssetBrowser.refresh(); AssetBrowser.refresh();
//Save out a basic terrain block here
/*%terrBlock = new TerrainBlock() { terrainFile = %terPath; };
%terrBlock.save(%terPath);
%terrBlock.delete();*/
//the terrain block creation is...weird and does coded path stuff engine-side.
//this needs reworking, but this is a sidestep for now
%misFile = $Client::MissionFile;
$Client::MissionFile = %terPath;
// //
$createdTerrainBlock = TerrainBlock::createNew( %assetName, %this.newAssetSettings.resolution, "", %this.newAssetSettings.genWithNoise ); $createdTerrainBlock = TerrainBlock::createNew( %assetName, %this.newAssetSettings.resolution, "", %this.newAssetSettings.genWithNoise );
$Client::MissionFile = %misFile; $createdTerrainBlock.terrainAsset = %moduleName @ ":" @ %assetName;
$createdTerrainBlock.terrainFile = "";
return %tamlpath; return %tamlpath;
} }