From 4ce558f04266da8e27e01ced62b41a0d9712552d Mon Sep 17 00:00:00 2001 From: Areloch Date: Thu, 25 Jun 2020 23:33:01 -0500 Subject: [PATCH] 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. --- Engine/source/T3D/assets/ImageAsset.h | 15 + Engine/source/T3D/assets/ShapeAsset.cpp | 3 + Engine/source/T3D/assets/TerrainAsset.cpp | 312 ++++++++++++++---- Engine/source/T3D/assets/TerrainAsset.h | 22 +- Engine/source/T3D/assets/assetImporter.cpp | 2 +- Engine/source/T3D/assets/assetImporter.h | 2 +- .../source/materials/materialDefinition.cpp | 57 +--- Engine/source/materials/materialDefinition.h | 15 - Engine/source/terrain/terrData.cpp | 275 ++++++++------- Engine/source/terrain/terrFile.cpp | 6 +- Engine/source/terrain/terrImport.cpp | 32 +- Engine/source/terrain/terrMaterial.cpp | 10 +- Engine/source/terrain/terrMaterial.h | 9 +- Engine/source/terrain/terrRender.cpp | 10 +- .../scripts/assetTypes/terrain.cs | 13 +- 15 files changed, 500 insertions(+), 283 deletions(-) diff --git a/Engine/source/T3D/assets/ImageAsset.h b/Engine/source/T3D/assets/ImageAsset.h index 332020478..c02ebd99a 100644 --- a/Engine/source/T3D/assets/ImageAsset.h +++ b/Engine/source/T3D/assets/ImageAsset.h @@ -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 m##name##Asset; + +#define DECLARE_TEXTUREARRAY(name,max) FileName m##name##Filename[max];\ + StringTableEntry m##name##AssetId[max];\ + AssetPtr m##name##Asset[max]; + #endif diff --git a/Engine/source/T3D/assets/ShapeAsset.cpp b/Engine/source/T3D/assets/ShapeAsset.cpp index ef6abd354..f20239070 100644 --- a/Engine/source/T3D/assets/ShapeAsset.cpp +++ b/Engine/source/T3D/assets/ShapeAsset.cpp @@ -366,6 +366,9 @@ bool ShapeAsset::getAssetByFilename(StringTableEntry fileName, AssetPtrEmptyString()) + return StringTable->EmptyString(); + StringTableEntry shapeAssetId = StringTable->EmptyString(); AssetQuery query; diff --git a/Engine/source/T3D/assets/TerrainAsset.cpp b/Engine/source/T3D/assets/TerrainAsset.cpp index 04fa1a2ce..01b1ec5e1 100644 --- a/Engine/source/T3D/assets/TerrainAsset.cpp +++ b/Engine/source/T3D/assets/TerrainAsset.cpp @@ -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,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* 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* shapeAsset) +{ + (*shapeAsset) = assetId; + + if (!shapeAsset->isNull()) + return true; + + return false; +} + +//------------------------------------------------------------------------------ void TerrainAsset::copyTo(SimObject* object) { // Call to parent. @@ -231,68 +441,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 +485,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"); +} diff --git a/Engine/source/T3D/assets/TerrainAsset.h b/Engine/source/T3D/assets/TerrainAsset.h index 805779fe9..72b8ff0d1 100644 --- a/Engine/source/T3D/assets/TerrainAsset.h +++ b/Engine/source/T3D/assets/TerrainAsset.h @@ -82,6 +82,10 @@ public: bool loadTerrain(); + static bool getAssetByFilename(StringTableEntry fileName, AssetPtr* shapeAsset); + static StringTableEntry getAssetIdByFilename(StringTableEntry fileName); + static bool getAssetById(StringTableEntry assetId, AssetPtr* 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_ diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index b8ca4194d..6e10c4c0e 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -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 - ModuleDefinition* targetModuleDef = getModuleFromPath(filePath); + ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(filePath); if (targetModuleDef == nullptr) { diff --git a/Engine/source/T3D/assets/assetImporter.h b/Engine/source/T3D/assets/assetImporter.h index 9a04d21c8..41ed9c6b6 100644 --- a/Engine/source/T3D/assets/assetImporter.h +++ b/Engine/source/T3D/assets/assetImporter.h @@ -603,7 +603,7 @@ public: /// @param filePath, File path to parse the the module from /// @return ModuleDefinition that was found /// - ModuleDefinition* getModuleFromPath(Torque::Path filePath); + static ModuleDefinition* getModuleFromPath(Torque::Path filePath); /// /// Parses an asset's name to try and find if any of the import config's suffix lists match to it diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index 83a711343..753b86d0e 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/Engine/source/materials/materialDefinition.cpp @@ -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(); diff --git a/Engine/source/materials/materialDefinition.h b/Engine/source/materials/materialDefinition.h index b41c495dd..f7701a240 100644 --- a/Engine/source/materials/materialDefinition.h +++ b/Engine/source/materials/materialDefinition.h @@ -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 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. diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index 7abfbc867..8ed1fea05 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -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 file = ResourceManager::get().load( terrFileName ); @@ -352,27 +352,104 @@ bool TerrainBlock::setFile( const FileName &terrFileName ) void TerrainBlock::setFile(const Resource& 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 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( obj )->setFile( FileName( data ) ); - return false; + //TerrainBlock* terrain = static_cast( obj )->setFile( FileName( data ) ); + TerrainBlock* terrain = static_cast(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(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() @@ -868,6 +966,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(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 { @@ -991,101 +1110,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 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(); @@ -1095,7 +1122,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(); @@ -1222,7 +1249,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."); @@ -1289,8 +1316,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 ) ) @@ -1328,14 +1356,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 diff --git a/Engine/source/terrain/terrFile.cpp b/Engine/source/terrain/terrFile.cpp index 727074106..d4f320222 100644 --- a/Engine/source/terrain/terrFile.cpp +++ b/Engine/source/terrain/terrFile.cpp @@ -766,15 +766,15 @@ void TerrainFile::create( String *inOutFilename, U32 newSize, const Vector &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" ); diff --git a/Engine/source/terrain/terrImport.cpp b/Engine/source/terrain/terrImport.cpp index abdb1a6c2..9916e41e4 100644 --- a/Engine/source/terrain/terrImport.cpp +++ b/Engine/source/terrain/terrImport.cpp @@ -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. diff --git a/Engine/source/terrain/terrMaterial.cpp b/Engine/source/terrain/terrMaterial.cpp index 57ba0d6be..458ed3961 100644 --- a/Engine/source/terrain/terrMaterial.cpp +++ b/Engine/source/terrain/terrMaterial.cpp @@ -26,6 +26,8 @@ #include "gfx/gfxTextureManager.h" #include "gfx/bitmap/gBitmap.h" +#include + 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; diff --git a/Engine/source/terrain/terrMaterial.h b/Engine/source/terrain/terrMaterial.h index 573d1bf99..9462cc62e 100644 --- a/Engine/source/terrain/terrMaterial.h +++ b/Engine/source/terrain/terrMaterial.h @@ -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 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; } diff --git a/Engine/source/terrain/terrRender.cpp b/Engine/source/terrain/terrRender.cpp index a6bc3dfae..d75196778 100644 --- a/Engine/source/terrain/terrRender.cpp +++ b/Engine/source/terrain/terrRender.cpp @@ -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(); -} \ No newline at end of file +} diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.cs b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.cs index 069fc61a3..d980943c1 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.cs +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.cs @@ -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; }