Merge pull request #229 from Areloch/TerrainAssetFixup

Reworks the terrain loader code to work with the assets.
This commit is contained in:
Brian Roberts 2020-07-10 17:30:27 -05:00 committed by GitHub
commit 67dbe4dfe2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 510 additions and 283 deletions

View file

@ -123,5 +123,20 @@ DefineConsoleType(TypeImageAssetPtr, ImageAsset)
typedef ImageAsset::ImageTypes 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

View file

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

View file

@ -42,6 +42,8 @@
#include "T3D/assets/TerrainMaterialAsset.h"
#include "assetImporter.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(TerrainAsset);
@ -87,6 +89,37 @@ ConsoleSetType(TypeTerrainAssetPtr)
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()
@ -202,7 +235,192 @@ 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();
String assetName = terrFilePath.getFileName();
assetName.replace(" ", "_");
newTerrainAsset->setAssetName(assetName.c_str());
String terrainPathBind = 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() + "/" + assetName + ".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 += assetName.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();
String assetName = terrFilePath.getFileName();
assetName.replace(" ", "_");
newTerrainAsset->setAssetName(assetName.c_str());
String terrainPathBind = 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.getPath() + "/" + assetName + ".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 += assetName.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)
{
// Call to parent.
@ -231,68 +449,37 @@ void GuiInspectorTypeTerrainAssetPtr::consoleInit()
GuiControl* GuiInspectorTypeTerrainAssetPtr::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();
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);
GuiControl* retCtrl = Parent::constructEditControl();
if (retCtrl == NULL)
return retCtrl;
// Change filespec
char szBuffer[512];
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
mInspector->getComponentGroupTargetId(), mCaption);
mMatPreviewButton->setField("Command", szBuffer);
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"TerrainAsset\", \"AssetBrowser.changeAsset\", %s, %s);",
mInspector->getInspectObject()->getIdString(), mCaption);
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");
const char* id = mInspector->getInspectObject()->getIdString();
StringBuilder strbld;
/*strbld.append(matAsset->getMaterialDefinitionName());
strbld.append("\n");
strbld.append("Open this file in the Material Editor");*/
setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
mMatPreviewButton->setDataField(StringTable->insert("tooltip"), NULL, strbld.data());
// Create "Open in ShapeEditor" button
mShapeEdButton = new GuiBitmapButtonCtrl();
_registerEditControl(mMatPreviewButton);
//mMatPreviewButton->registerObject();
mMatEdContainer->addObject(mMatPreviewButton);
mShapeEdButton->setField("Command", "EditorGui.setEditor(TerrainEditorPlugin);");
mMatAssetIdTxt = new GuiTextEditCtrl();
mMatAssetIdTxt->registerObject();
mMatAssetIdTxt->setActive(false);
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
mShapeEdButton->setBitmap(bitmapName);
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);
mMatEdContainer->addObject(mMatAssetIdTxt);
mShapeEdButton->registerObject();
addObject(mShapeEdButton);
return mMatEdContainer;
return retCtrl;
}
bool GuiInspectorTypeTerrainAssetPtr::updateRects()
@ -306,21 +493,32 @@ bool GuiInspectorTypeTerrainAssetPtr::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 (mShapeEdButton != 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 |= mShapeEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
}
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();
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_CONOBJECT(TerrainAsset);
@ -94,18 +98,17 @@ protected:
};
DefineConsoleType(TypeTerrainAssetPtr, TerrainAsset)
DefineConsoleType(TypeTerrainAssetId, String)
//-----------------------------------------------------------------------------
// TypeAssetId GuiInspectorField Class
//-----------------------------------------------------------------------------
class GuiInspectorTypeTerrainAssetPtr : public GuiInspectorField
class GuiInspectorTypeTerrainAssetPtr : public GuiInspectorTypeFileName
{
typedef GuiInspectorField Parent;
typedef GuiInspectorTypeFileName Parent;
public:
GuiControl* mMatEdContainer;
GuiBitmapButtonCtrl *mMatPreviewButton;
GuiTextEditCtrl *mMatAssetIdTxt;
GuiBitmapButtonCtrl* mShapeEdButton;
DECLARE_CONOBJECT(GuiInspectorTypeTerrainAssetPtr);
static void consoleInit();
@ -114,5 +117,14 @@ public:
virtual bool updateRects();
};
class GuiInspectorTypeTerrainAssetId : public GuiInspectorTypeTerrainAssetPtr
{
typedef GuiInspectorTypeTerrainAssetPtr Parent;
public:
DECLARE_CONOBJECT(GuiInspectorTypeTerrainAssetId);
static void consoleInit();
};
#endif // _ASSET_BASE_H_

View file

@ -390,6 +390,8 @@ AssetImportObject* AssetImporter::addImportingAsset(String assetType, Torque::Pa
else
assetName = filePath.getFileName();
assetName.replace(" ", "_");
AssetImportObject* assetImportObj = new AssetImportObject();
assetImportObj->registerObject();
@ -1485,7 +1487,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
ModuleDefinition* targetModuleDef = getModuleFromPath(filePath);
ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(filePath);
if (targetModuleDef == nullptr)
{

View file

@ -603,7 +603,7 @@ public:
/// <para>@param filePath, File path to parse the the module from</para>
/// <para>@return ModuleDefinition that was found</para>
/// </summary>
ModuleDefinition* getModuleFromPath(Torque::Path filePath);
static ModuleDefinition* getModuleFromPath(Torque::Path filePath);
/// <summary>
/// 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(DetailNormalMap, i);
//cogs specific
initMapSlot(AlbedoDamageMap, i);
initMapSlot(NormalDamageMap, i);
initMapSlot(CompositeDamageMap, i);
mParallaxScale[i] = 0.0f;
mVertLit[i] = false;
@ -194,9 +189,6 @@ Material::Material()
// Deferred Shading
mMatInfoFlags[i] = 0.0f;
// Damage
mMaterialDamageMin[i] = 0.0f;
mAlbedoDamageMapSRGB[i] = true;
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()
{
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 "
"is present this is the material color." );
scriptBindMapSlot(DiffuseMap, MAX_STAGES);
scriptBindMapSlot(OverlayMap, MAX_STAGES);
scriptBindMapSlot(LightMap, MAX_STAGES);
scriptBindMapSlot(ToneMap, MAX_STAGES);
scriptBindMapSlot(DetailMap, MAX_STAGES);
scriptBindMapSlot(NormalMap, MAX_STAGES);
scriptBindMapSlot(PBRConfigMap, MAX_STAGES);
scriptBindMapSlot(RoughMap, MAX_STAGES);
scriptBindMapSlot(AOMap, MAX_STAGES);
scriptBindMapSlot(MetalMap, MAX_STAGES);
scriptBindMapSlot(GlowMap, MAX_STAGES);
scriptBindMapSlot(DetailNormalMap, MAX_STAGES);
scriptBindMapArraySlot(DiffuseMap, MAX_STAGES, Material);
scriptBindMapArraySlot(OverlayMap, MAX_STAGES, Material);
scriptBindMapArraySlot(LightMap, MAX_STAGES, Material);
scriptBindMapArraySlot(ToneMap, MAX_STAGES, Material);
scriptBindMapArraySlot(DetailMap, MAX_STAGES, Material);
scriptBindMapArraySlot(NormalMap, MAX_STAGES, Material);
scriptBindMapArraySlot(PBRConfigMap, MAX_STAGES, Material);
scriptBindMapArraySlot(RoughMap, MAX_STAGES, Material);
scriptBindMapArraySlot(AOMap, MAX_STAGES, Material);
scriptBindMapArraySlot(MetalMap, MAX_STAGES, Material);
scriptBindMapArraySlot(GlowMap, MAX_STAGES, Material);
scriptBindMapArraySlot(DetailNormalMap, MAX_STAGES, Material);
addField("diffuseMapSRGB", TypeBool, Offset(mDiffuseMapSRGB, Material), MAX_STAGES,
"Enable sRGB for the diffuse color texture map.");
@ -422,22 +410,6 @@ void Material::initPersistFields()
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),
"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(GlowMap, i);
bindMapSlot(DetailNormalMap, i);
//cogs specific
bindMapSlot(AlbedoDamageMap, i);
bindMapSlot(NormalDamageMap, i);
bindMapSlot(CompositeDamageMap, i);
}
_mapMaterial();

View file

@ -61,10 +61,6 @@ class MaterialSoundProfile;
class MaterialPhysicsProfile;
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.
class Material : public BaseMaterialDefinition
{
@ -244,17 +240,6 @@ public:
F32 mAccuCoverage[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
/// or if it has a texture it is multiplied against
/// 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
// it doesn't exist then generate and cache it.
String baseCachePath = terrain->_getBaseTexCacheFileName();
if (Platform::compareModifiedTimes(baseCachePath, terrain->mTerrFileName) < 0)
if (Platform::compareModifiedTimes(baseCachePath, terrain->mTerrainAsset->getTerrainFilePath()) < 0)
terrain->_updateBaseTexture(true);
break;
}
@ -337,7 +337,7 @@ bool TerrainBlock::_setLightMapSize( void *obj, const char *index, const char *d
bool TerrainBlock::setFile( const FileName &terrFileName )
{
if ( terrFileName == mTerrFileName )
if ( mTerrainAsset && mTerrainAsset->getTerrainFilePath() == terrFileName )
return mFile != NULL;
Resource<TerrainFile> file = ResourceManager::get().load( terrFileName );
@ -352,27 +352,104 @@ bool TerrainBlock::setFile( const FileName &terrFileName )
void TerrainBlock::setFile(const Resource<TerrainFile>& terr)
{
if (mFile)
{
GFXTextureManager::removeEventDelegate(this, &TerrainBlock::_onTextureEvent);
MATMGR->getFlushSignal().remove(this, &TerrainBlock::_onFlushMaterials);
}
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)
{
mTerrainAssetId = terrainAssetId;
mTerrainAsset = mTerrainAssetId;
if (mTerrainAsset.isNull())
if (TerrainAsset::getAssetById(terrainAssetId, &mTerrainAsset))
{
Con::errorf("[TerrainBlock] Failed to load terrain asset.");
return false;
//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
//the TSStatic
if (!mTerrainAsset.isNull())
{
mTerrFileName = StringTable->EmptyString();
}
setFile(mTerrainAsset->getTerrainResource());
setMaskBits(-1);
return true;
}
Resource<TerrainFile> file = mTerrainAsset->getTerrainResource();
if (!file)
return false;
setFile(file);
return true;
return false;
}
bool TerrainBlock::save(const char *filename)
@ -425,19 +502,40 @@ bool TerrainBlock::saveAsset()
bool TerrainBlock::_setTerrainFile( void *obj, const char *index, const char *data )
{
static_cast<TerrainBlock*>( obj )->setFile( FileName( data ) );
return false;
//TerrainBlock* terrain = static_cast<TerrainBlock*>( obj )->setFile( FileName( data ) );
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)
{
TerrainBlock* terr = static_cast<TerrainBlock*>(obj);// ->setFile(FileName(data));
terr->setTerrainAsset(StringTable->insert(data));
terr->setMaskBits(FileMask | HeightMapChangeMask);
terr->mTerrainAssetId = StringTable->insert(data);
return false;
return terr->setTerrainAsset(terr->mTerrainAssetId);
}
void TerrainBlock::_updateBounds()
@ -870,6 +968,27 @@ void TerrainBlock::addMaterial( const String &name, U32 insertAt )
{
mFile->mMaterials.push_back( mat );
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
{
@ -993,101 +1112,9 @@ bool TerrainBlock::onAdd()
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);
}
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();
_updatePhysics();
@ -1097,7 +1124,7 @@ bool TerrainBlock::onAdd()
String TerrainBlock::_getBaseTexCacheFileName() const
{
Torque::Path basePath( mTerrFileName );
Torque::Path basePath( mTerrainAsset->getTerrainFilePath() );
basePath.setFileName( basePath.getFileName() + "_basetex" );
basePath.setExtension( formatToExtension(mBaseTexFormat) );
return basePath.getFullPath();
@ -1224,7 +1251,7 @@ void TerrainBlock::initPersistFields()
{
addGroup( "Media" );
addProtectedField("terrainAsset", TypeTerrainAssetPtr, Offset(mTerrainAsset, TerrainBlock),
addProtectedField("terrainAsset", TypeTerrainAssetId, Offset(mTerrainAssetId, TerrainBlock),
&TerrainBlock::_setTerrainAsset, &defaultProtectedGetFn,
"The source terrain data asset.");
@ -1291,8 +1318,9 @@ U32 TerrainBlock::packUpdate(NetConnection* con, U32 mask, BitStream *stream)
if ( stream->writeFlag( mask & FileMask ) )
{
stream->write( mTerrFileName );
stream->write( mCRC );
S32 idasdasdf = getId();
stream->write(mCRC);
stream->writeString( mTerrainAsset.getAssetId() );
}
if ( stream->writeFlag( mask & SizeMask ) )
@ -1330,14 +1358,11 @@ void TerrainBlock::unpackUpdate(NetConnection* con, BitStream *stream)
if ( stream->readFlag() ) // FileMask
{
FileName terrFile;
stream->read( &terrFile );
stream->read( &mCRC );
stream->read(&mCRC);
if ( isProperlyAdded() )
setFile( terrFile );
else
mTerrFileName = terrFile;
char buffer[256];
stream->readString(buffer);
bool validAsset = setTerrainAsset(StringTable->insert(buffer));
}
if ( stream->readFlag() ) // SizeMask

View file

@ -766,15 +766,15 @@ void TerrainFile::create( String *inOutFilename,
U32 newSize,
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 );
if ( !basePath.getExtension().equal("mis") )
if ( !basePath.getExtension().equal("ter") )
{
// Use the default path and filename
String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) );
if ( terrainDirectory.isEmpty() )
{
terrainDirectory = "art/terrains";
terrainDirectory = "data/terrains";
}
basePath.setPath( terrainDirectory );
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
// 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.
FileName terrFileName( Con::getVariable("$Client::MissionFile") );
String terrainDirectory( Con::getVariable( "$pref::Directories::Terrain" ) );
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 );
@ -273,18 +273,32 @@ bool TerrainBlock::import( const GBitmap &heightMap,
{
// Get a unique file name for the terrain.
String fileName( getName() );
if ( fileName.isEmpty() )
fileName = "terrain";
mTerrFileName = FS::MakeUniquePath( "levels", fileName, "ter" );
if (fileName.isEmpty())
{
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
// of temporary unused files when the terrain is
// discarded because of undo or quit.
TerrainFile *file = new TerrainFile;
file->save( mTerrFileName );
delete file;
mFile = ResourceManager::get().load( mTerrFileName );
mFile = ResourceManager::get().load( mTerrFileName );*/
}
// The file does a bunch of the work.

View file

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

View file

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

View file

@ -84,7 +84,10 @@ void TerrainBlock::_onFlushMaterials()
}
void TerrainBlock::_updateMaterials()
{
{
if (!mFile)
return;
mBaseTextures.setSize( mFile->mMaterials.size() );
mMaxDetailDistance = 0.0f;
@ -363,6 +366,9 @@ void TerrainBlock::_renderBlock( SceneRenderState *state )
{
PROFILE_SCOPE( TerrainBlock_RenderBlock );
if (!mFile)
return;
// Prevent rendering shadows if feature is disabled
if ( !mCastShadows && state->isShadowPass() )
return;
@ -529,4 +535,4 @@ void TerrainBlock::_renderDebug( ObjectRenderInst *ri,
mDebugCells[i]->renderBounds();
mDebugCells.clear();
}
}

View file

@ -38,20 +38,11 @@ function AssetBrowser::createTerrainAsset(%this)
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 );
$Client::MissionFile = %misFile;
$createdTerrainBlock.terrainAsset = %moduleName @ ":" @ %assetName;
$createdTerrainBlock.terrainFile = "";
return %tamlpath;
}