From bf5b26f7340348fb9732cd7fc59cec7e39d58af7 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 3 Jan 2021 08:58:53 -0600 Subject: [PATCH] Assetifies MeshRoad, Decal Road, and the material slot of GroundCover Creates a networked and non-networked variant of DECLARE_MATERIALASSET macro --- Engine/source/T3D/assets/MaterialAsset.cpp | 4 +- Engine/source/T3D/assets/MaterialAsset.h | 94 +++++++++++++++- .../source/T3D/examples/renderMeshExample.h | 2 +- Engine/source/T3D/fx/groundCover.cpp | 43 ++++--- Engine/source/T3D/fx/groundCover.h | 6 +- Engine/source/T3D/groundPlane.h | 2 +- Engine/source/environment/decalRoad.cpp | 60 +++++----- Engine/source/environment/decalRoad.h | 5 +- .../editors/guiMeshRoadEditorCtrl.cpp | 34 +++--- .../editors/guiMeshRoadEditorCtrl.h | 12 +- .../environment/editors/guiRoadEditorCtrl.cpp | 21 ++-- .../environment/editors/guiRoadEditorCtrl.h | 5 +- Engine/source/environment/meshRoad.cpp | 105 ++++++++++++------ Engine/source/environment/meshRoad.h | 8 +- .../assetBrowser/scripts/assetBrowser.cs | 5 +- .../game/tools/meshRoadEditor/main.cs | 4 + .../BaseGame/game/tools/roadEditor/main.cs | 8 +- 17 files changed, 301 insertions(+), 117 deletions(-) diff --git a/Engine/source/T3D/assets/MaterialAsset.cpp b/Engine/source/T3D/assets/MaterialAsset.cpp index c44c53937..be38e35e8 100644 --- a/Engine/source/T3D/assets/MaterialAsset.cpp +++ b/Engine/source/T3D/assets/MaterialAsset.cpp @@ -282,8 +282,8 @@ GuiControl* GuiInspectorTypeMaterialAssetPtr::constructEditControl() // Change filespec char szBuffer[512]; - dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %s, %s);", - mInspector->getInspectObject()->getIdString(), mCaption); + dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %s, \"\");", + getIdString()); mBrowseButton->setField("Command", szBuffer); setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString()); diff --git a/Engine/source/T3D/assets/MaterialAsset.h b/Engine/source/T3D/assets/MaterialAsset.h index 3c1c70720..4451d4515 100644 --- a/Engine/source/T3D/assets/MaterialAsset.h +++ b/Engine/source/T3D/assets/MaterialAsset.h @@ -126,23 +126,87 @@ public: #define assetText(x,suff) std::string(std::string(#x) + std::string(#suff)).c_str() -#define initMaterialAsset(name) m##name##Name = StringTable->EmptyString(); m##name##AssetId = StringTable->EmptyString(); m##name##Asset = NULL; +#define initMaterialAsset(name) m##name##Name = ""; m##name##AssetId = StringTable->EmptyString(); m##name##Asset = NULL; #define bindMaterialAsset(name) if (m##name##AssetId != StringTable->EmptyString()) m##name##Asset = m##name##AssetId; -#define scriptBindMaterialAsset(name, consoleClass, docs) addProtectedField(assetText(name, File), TypeMaterialName, Offset(m##name##Name, consoleClass), consoleClass::_set##name##Name, & defaultProtectedGetFn, assetText(name, docs)); \ - addProtectedField(assetText(name, Asset), TypeMaterialAssetId, Offset(m##name##AssetId, consoleClass), consoleClass::_set##name##Asset, & defaultProtectedGetFn, assetText(name, asset reference.)); +#define scriptBindMaterialAsset(name, consoleClass, docs)\ + addProtectedField(assetText(name, File), TypeMaterialName, Offset(m##name##Name, consoleClass), consoleClass::_set##name##Name, & defaultProtectedGetFn, assetText(name, docs), AbstractClassRep::FIELD_HideInInspectors); \ + addProtectedField(assetText(name, Asset), TypeMaterialAssetId, Offset(m##name##AssetId, consoleClass), consoleClass::_set##name##Asset, & defaultProtectedGetFn, assetText(name, asset reference.)); + +#define DECLARE_MATERIALASSET(className,name) protected: \ + String m##name##Name;\ + StringTableEntry m##name##AssetId;\ + AssetPtr m##name##Asset;\ + public: \ + const String& get##name() const { return m##name##Name; }\ + void set##name(FileName _in) { m##name##Name = _in; }\ + const AssetPtr & get##name##Asset() const { return m##name##Asset; }\ + void set##name##Asset(AssetPtr_in) { m##name##Asset = _in; }\ +static bool _set##name##Name(void* obj, const char* index, const char* data)\ +{\ + className* shape = static_cast(obj);\ + \ + StringTableEntry assetId = MaterialAsset::getAssetIdByMaterialName(StringTable->insert(data));\ + if (assetId != StringTable->EmptyString())\ + {\ + if (shape->_set##name##Asset(obj, index, assetId))\ + {\ + if (assetId == StringTable->insert("Core_Rendering:noMaterial"))\ + {\ + shape->m##name##Name = data;\ + shape->m##name##AssetId = StringTable->EmptyString();\ + \ + return true;\ + }\ + else\ + {\ + shape->m##name##AssetId = assetId;\ + shape->m##name##Name = StringTable->EmptyString();\ + \ + return false;\ + }\ + }\ + }\ + else\ + {\ + shape->m##name##Asset = StringTable->EmptyString();\ + }\ + \ + return true;\ +}\ +\ +static bool _set##name##Asset(void* obj, const char* index, const char* data)\ +{\ + className* shape = static_cast(obj);\ + shape->m##name##AssetId = StringTable->insert(data);\ + if (MaterialAsset::getAssetById(shape->m##name##AssetId, &shape->m##name##Asset))\ + {\ + if (shape->m##name##Asset.getAssetId() != StringTable->insert("Core_Rendering:noMaterial"))\ + shape->m##name##Name = StringTable->EmptyString();\ + \ + return true;\ + }\ + return false;\ +}\ +\ +static bool set##name##Asset(const char* assetId)\ +{\ + m##name##AssetId = StringTable->insert(assetId);\ + if (m##name##AssetId != StringTable->EmptyString())\ + m##name##Asset = m##name##AssetId;\ +} /// /// DECLARE_MATERIALASSET is a utility macro for MaterialAssets. It takes in the name of the class using it, the name of the field for the material, and a networking bitmask /// The first 2 are for setting up/filling out the fields and class member defines /// The bitmask is for when the material is changed, it can automatically kick a network update on the owner object to pass the changed asset to clients /// -#define DECLARE_MATERIALASSET(className,name,bitmask) protected: \ - StringTableEntry m##name##Name;\ +#define DECLARE_NET_MATERIALASSET(className,name,bitmask) protected: \ + String m##name##Name;\ StringTableEntry m##name##AssetId;\ AssetPtr m##name##Asset;\ public: \ - const StringTableEntry& get##name() const { return m##name##Name; }\ + const String& get##name() const { return m##name##Name; }\ void set##name(FileName _in) { m##name##Name = _in; }\ const AssetPtr & get##name##Asset() const { return m##name##Asset; }\ void set##name##Asset(AssetPtr_in) { m##name##Asset = _in; }\ @@ -189,11 +253,29 @@ static bool _set##name##Asset(void* obj, const char* index, const char* data)\ shape->m##name##Name = StringTable->EmptyString();\ \ shape->setMaskBits(bitmask);\ + shape->inspectPostApply();\ return true;\ }\ + shape->inspectPostApply();\ + return false;\ +}\ +\ +bool set##name##AssetId(const char* _assetId)\ +{\ + m##name##AssetId = StringTable->insert(_assetId);\ + if (m##name##AssetId != StringTable->EmptyString())\ + {\ + m##name##Asset = m##name##AssetId;\ + \ + setMaskBits(bitmask);\ + inspectPostApply();\ + return true;\ + }\ + \ return false;\ } + #define packMaterialAsset(netconn, name)\ if (stream->writeFlag(m##name##Asset.notNull()))\ {\ diff --git a/Engine/source/T3D/examples/renderMeshExample.h b/Engine/source/T3D/examples/renderMeshExample.h index 82a38a65b..611a2de65 100644 --- a/Engine/source/T3D/examples/renderMeshExample.h +++ b/Engine/source/T3D/examples/renderMeshExample.h @@ -67,7 +67,7 @@ class RenderMeshExample : public SceneObject //-------------------------------------------------------------------------- // Rendering variables //-------------------------------------------------------------------------- - DECLARE_MATERIALASSET(RenderMeshExample, Material, UpdateMask); + DECLARE_NET_MATERIALASSET(RenderMeshExample, Material, UpdateMask); // The actual Material instance BaseMatInstance* mMaterialInst; diff --git a/Engine/source/T3D/fx/groundCover.cpp b/Engine/source/T3D/fx/groundCover.cpp index 80c60142e..5fa81914e 100644 --- a/Engine/source/T3D/fx/groundCover.cpp +++ b/Engine/source/T3D/fx/groundCover.cpp @@ -458,7 +458,8 @@ GroundCover::GroundCover() mRandomSeed = 1; - mMaterial = NULL; + initMaterialAsset(Material); + mMatInst = NULL; mMatParams = NULL; mTypeRectsParam = NULL; @@ -537,8 +538,8 @@ IMPLEMENT_CO_NETOBJECT_V1(GroundCover); void GroundCover::initPersistFields() { addGroup( "GroundCover General" ); - - addField( "material", TypeMaterialName, Offset( mMaterialName, GroundCover ), "Material used by all GroundCover segments." ); + + scriptBindMaterialAsset(Material, GroundCover, "Material used by all GroundCover segments."); addField( "radius", TypeF32, Offset( mRadius, GroundCover ), "Outer generation radius from the current camera position." ); addField( "dissolveRadius",TypeF32, Offset( mFadeRadius, GroundCover ), "This is less than or equal to radius and defines when fading of cover elements begins." ); @@ -709,7 +710,7 @@ U32 GroundCover::packUpdate( NetConnection *connection, U32 mask, BitStream *str // TODO: We could probably optimize a few of these // based on reasonable units at some point. - stream->write( mMaterialName ); + packMaterialAsset(connection, Material); stream->write( mRadius ); stream->write( mZOffset ); @@ -780,7 +781,7 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream ) if (stream->readFlag()) { - stream->read( &mMaterialName ); + unpackMaterialAsset(connection, Material); stream->read( &mRadius ); stream->read( &mZOffset ); @@ -852,17 +853,29 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream ) } void GroundCover::_initMaterial() -{ - SAFE_DELETE( mMatInst ); - - if ( mMaterialName.isNotEmpty() ) - if ( !Sim::findObject( mMaterialName, mMaterial ) ) - Con::errorf( "GroundCover::_initMaterial - Material %s was not found.", mMaterialName.c_str() ); +{ + if (mMaterialAsset.notNull()) + { + if (mMatInst && String(mMaterialAsset->getMaterialDefinitionName()).equal(mMatInst->getMaterial()->getName(), String::NoCase)) + return; - if ( mMaterial ) - mMatInst = mMaterial->createMatInstance(); + SAFE_DELETE(mMatInst); + + if (!Sim::findObject(mMaterialAsset->getMaterialDefinitionName(), mMaterial)) + Con::errorf("GroundCover::_initMaterial - Material %s was not found.", mMaterialAsset->getMaterialDefinitionName()); + + if (mMaterial) + mMatInst = mMaterial->createMatInstance(); + else + mMatInst = MATMGR->createMatInstance("WarningMaterial"); + + if (!mMatInst) + Con::errorf("GroundCover::_initMaterial - no Material called '%s'", mMaterialAsset->getMaterialDefinitionName()); + } else - mMatInst = MATMGR->createMatInstance( "WarningMaterial" ); + { + return; + } // Add our special feature that makes it all work... FeatureSet features = MATMGR->getDefaultFeatures(); @@ -1567,6 +1580,8 @@ void GroundCover::_updateCoverGrid( const Frustum &culler ) void GroundCover::prepRenderImage( SceneRenderState *state ) { // Reset stats each time we hit the diffuse pass. + if (mMatInst == nullptr) + return; if( state->isDiffusePass() ) { diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index 6679777ca..cf9d2a4f4 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -45,6 +45,8 @@ #include "shaderGen/shaderFeature.h" #endif +#include "T3D/assets/MaterialAsset.h" + class TerrainBlock; class GroundCoverCell; class TSShapeInstance; @@ -264,8 +266,8 @@ protected: static F32 smDensityScale; static F32 smFadeScale; - String mMaterialName; - Material *mMaterial; + DECLARE_NET_MATERIALASSET(GroundCover, Material, InitialUpdateMask); + Material* mMaterial; BaseMatInstance *mMatInst; GroundCoverShaderConstData mShaderConstData; diff --git a/Engine/source/T3D/groundPlane.h b/Engine/source/T3D/groundPlane.h index c1f943dc0..1bcb59583 100644 --- a/Engine/source/T3D/groundPlane.h +++ b/Engine/source/T3D/groundPlane.h @@ -106,7 +106,7 @@ private: F32 mScaleV; ///< Scale factor for V texture coordinates. BaseMatInstance* mMaterial; ///< Instantiated material based on given material name. - DECLARE_MATERIALASSET(GroundPlane, Material, -1); + DECLARE_NET_MATERIALASSET(GroundPlane, Material, -1); PhysicsBody *mPhysicsRep; diff --git a/Engine/source/environment/decalRoad.cpp b/Engine/source/environment/decalRoad.cpp index 668bfcaae..a50792faa 100644 --- a/Engine/source/environment/decalRoad.cpp +++ b/Engine/source/environment/decalRoad.cpp @@ -287,7 +287,9 @@ DecalRoad::DecalRoad() { // Setup NetObject. mTypeMask |= StaticObjectType | StaticShapeObjectType; - mNetFlags.set(Ghostable); + mNetFlags.set(Ghostable); + + initMaterialAsset(Material); } DecalRoad::~DecalRoad() @@ -303,7 +305,8 @@ void DecalRoad::initPersistFields() { addGroup( "DecalRoad" ); - addField( "material", TypeMaterialName, Offset( mMaterialName, DecalRoad ), "Material used for rendering." ); + addProtectedField("materialAsset", TypeMaterialAssetId, Offset(mMaterialAssetId, DecalRoad), &DecalRoad::_setMaterialAsset, &defaultProtectedGetFn, "Material Asset used for rendering."); + addProtectedField( "material", TypeMaterialName, Offset( mMaterialName, DecalRoad ), &DecalRoad::_setMaterialName, &defaultProtectedGetFn, "Material used for rendering." ); addProtectedField( "textureLength", TypeF32, Offset( mTextureLength, DecalRoad ), &DecalRoad::ptSetTextureLength, &defaultProtectedGetFn, "The length in meters of textures mapped to the DecalRoad" ); @@ -489,7 +492,7 @@ U32 DecalRoad::packUpdate(NetConnection * con, U32 mask, BitStream * stream) if ( stream->writeFlag( mask & DecalRoadMask ) ) { // Write Texture Name. - stream->write( mMaterialName ); + packMaterialAsset(con, Material); stream->write( mBreakAngle ); @@ -578,24 +581,10 @@ void DecalRoad::unpackUpdate( NetConnection *con, BitStream *stream ) // DecalRoadMask if ( stream->readFlag() ) { - String matName; - stream->read( &matName ); - - if ( matName != mMaterialName ) - { - mMaterialName = matName; - Material *pMat = NULL; - if ( !Sim::findObject( mMaterialName, pMat ) ) - { - Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name %s!", mMaterialName.c_str() ); - } - else - { - mMaterial = pMat; - if ( isProperlyAdded() ) - _initMaterial(); - } - } + unpackMaterialAsset(con, Material); + + if (isProperlyAdded()) + _initMaterial(); stream->read( &mBreakAngle ); @@ -1056,12 +1045,31 @@ bool DecalRoad::addNodeFromField( void *object, const char *index, const char *d void DecalRoad::_initMaterial() { - SAFE_DELETE( mMatInst ); + if (mMaterialAsset.notNull()) + { + if (mMatInst && String(mMaterialAsset->getMaterialDefinitionName()).equal(mMatInst->getMaterial()->getName(), String::NoCase)) + return; - if ( mMaterial ) - mMatInst = mMaterial->createMatInstance(); - else - mMatInst = MATMGR->createMatInstance( "WarningMaterial" ); + SAFE_DELETE(mMatInst); + + Material* tMat = nullptr; + + if (!Sim::findObject(mMaterialAsset->getMaterialDefinitionName(), tMat)) + Con::errorf("DecalRoad::_initMaterial - Material %s was not found.", mMaterialAsset->getMaterialDefinitionName()); + + mMaterial = tMat; + + if (mMaterial) + mMatInst = mMaterial->createMatInstance(); + else + mMatInst = MATMGR->createMatInstance("WarningMaterial"); + + if (!mMatInst) + Con::errorf("DecalRoad::_initMaterial - no Material called '%s'", mMaterialAsset->getMaterialDefinitionName()); + } + + if (!mMatInst) + return; GFXStateBlockDesc desc; desc.setZReadWrite( true, false ); diff --git a/Engine/source/environment/decalRoad.h b/Engine/source/environment/decalRoad.h index 7b0987d27..771aa5975 100644 --- a/Engine/source/environment/decalRoad.h +++ b/Engine/source/environment/decalRoad.h @@ -36,6 +36,8 @@ #include "collision/clippedPolyList.h" #endif +#include "T3D/assets/MaterialAsset.h" + class Path; class TerrainBlock; struct ObjectRenderInst; @@ -237,7 +239,8 @@ protected: F32 mBreakAngle; U32 mSegmentsPerBatch; F32 mTextureLength; - String mMaterialName; + + DECLARE_NET_MATERIALASSET(DecalRoad, Material, DecalRoadMask); U32 mRenderPriority; // Static ConsoleVars for editor diff --git a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp index d1a75f40d..b9bb74c1c 100644 --- a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp @@ -96,10 +96,10 @@ GuiMeshRoadEditorCtrl::GuiMeshRoadEditorCtrl() mSelectedSplineColor( 0,255,0,255 ), mHoverNodeColor( 255,255,255,255 ), mHasCopied( false ) -{ - mMaterialName[Top] = StringTable->insert("DefaultRoadMaterialTop"); - mMaterialName[Bottom] = StringTable->insert("DefaultRoadMaterialOther"); - mMaterialName[Side] = StringTable->insert("DefaultRoadMaterialOther"); +{ + mTopMaterialAssetId = Con::getVariable("$MeshRoadEditor::defaultTopMaterialAsset"); + mBottomMaterialAssetId = Con::getVariable("$MeshRoadEditor::defaultBottomMaterialAsset"); + mSideMaterialAssetId = Con::getVariable("$MeshRoadEditor::defaultSideMaterialAsset"); } GuiMeshRoadEditorCtrl::~GuiMeshRoadEditorCtrl() @@ -205,6 +205,10 @@ bool GuiMeshRoadEditorCtrl::onAdd() desc.zEnable = true; mZEnableSB = GFX->createStateBlock(desc); + bindMaterialAsset(TopMaterial); + bindMaterialAsset(BottomMaterial); + bindMaterialAsset(SideMaterial); + return true; } @@ -217,12 +221,11 @@ void GuiMeshRoadEditorCtrl::initPersistFields() addField( "SelectedSplineColor", TypeColorI, Offset( mSelectedSplineColor, GuiMeshRoadEditorCtrl ) ); addField( "HoverNodeColor", TypeColorI, Offset( mHoverNodeColor, GuiMeshRoadEditorCtrl ) ); addField( "isDirty", TypeBool, Offset( mIsDirty, GuiMeshRoadEditorCtrl ) ); - addField( "topMaterialName", TypeString, Offset( mMaterialName[Top], GuiMeshRoadEditorCtrl ), - "Default Material used by the Mesh Road Editor on upper surface road creation." ); - addField( "bottomMaterialName", TypeString, Offset( mMaterialName[Bottom], GuiMeshRoadEditorCtrl ), - "Default Material used by the Mesh Road Editor on bottom surface road creation." ); - addField( "sideMaterialName", TypeString, Offset( mMaterialName[Side], GuiMeshRoadEditorCtrl ), - "Default Material used by the Mesh Road Editor on side surface road creation." ); + + addField("topMaterial", TypeMaterialAssetId, Offset(mTopMaterialAssetId, GuiMeshRoadEditorCtrl), "Default Material used by the Mesh Road Editor on upper surface road creation."); + addField("bottomMaterial", TypeMaterialAssetId, Offset(mBottomMaterialAssetId, GuiMeshRoadEditorCtrl), "Default Material used by the Mesh Road Editor on bottom surface road creation."); + addField("sideMaterial", TypeMaterialAssetId, Offset(mSideMaterialAssetId, GuiMeshRoadEditorCtrl), "Default Material used by the Mesh Road Editor on side surface road creation."); + //addField( "MoveNodeCursor", TYPEID< SimObject >(), Offset( mMoveNodeCursor, GuiMeshRoadEditorCtrl) ); //addField( "AddNodeCursor", TYPEID< SimObject >(), Offset( mAddNodeCursor, GuiMeshRoadEditorCtrl) ); //addField( "InsertNodeCursor", TYPEID< SimObject >(), Offset( mInsertNodeCursor, GuiMeshRoadEditorCtrl) ); @@ -622,10 +625,13 @@ void GuiMeshRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) } MeshRoad *newRoad = new MeshRoad; - - newRoad->mMaterialName[Top] = mMaterialName[Top]; - newRoad->mMaterialName[Bottom] = mMaterialName[Bottom]; - newRoad->mMaterialName[Side] = mMaterialName[Side]; + + if(mTopMaterialAsset.notNull()) + newRoad->setTopMaterialAssetId(mTopMaterialAssetId); + if (mBottomMaterialAsset.notNull()) + newRoad->setBottomMaterialAssetId(mBottomMaterialAssetId); + if (mSideMaterialAsset.notNull()) + newRoad->setSideMaterialAssetId(mSideMaterialAssetId); newRoad->registerObject(); diff --git a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.h b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.h index 31c0ddd33..ab3d132b6 100644 --- a/Engine/source/environment/editors/guiMeshRoadEditorCtrl.h +++ b/Engine/source/environment/editors/guiMeshRoadEditorCtrl.h @@ -36,6 +36,8 @@ #include "environment/meshRoad.h" #endif +#include "T3D/assets/MaterialAsset.h" + class GameBase; class GuiMeshRoadEditorCtrl : public EditTSCtrl @@ -156,8 +158,14 @@ class GuiMeshRoadEditorCtrl : public EditTSCtrl bool mHasCopied; public: - - StringTableEntry mMaterialName[SurfaceCount]; + + StringTableEntry mTopMaterialAssetId; + StringTableEntry mBottomMaterialAssetId; + StringTableEntry mSideMaterialAssetId; + + AssetPtr mTopMaterialAsset; + AssetPtr mBottomMaterialAsset; + AssetPtr mSideMaterialAsset; }; class GuiMeshRoadEditorUndoAction : public UndoAction diff --git a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp index cb8286ec8..487b35a24 100644 --- a/Engine/source/environment/editors/guiRoadEditorCtrl.cpp +++ b/Engine/source/environment/editors/guiRoadEditorCtrl.cpp @@ -85,7 +85,7 @@ GuiRoadEditorCtrl::GuiRoadEditorCtrl() mSavedDrag = false; mIsDirty = false; - mMaterialName = StringTable->insert("DefaultDecalRoadMaterial"); + mMaterialAssetId = Con::getVariable("$DecalRoadEditor::defaultMaterialAsset"); } GuiRoadEditorCtrl::~GuiRoadEditorCtrl() @@ -100,7 +100,7 @@ void GuiRoadEditorUndoAction::undo() return; // Temporarily save the roads current data. - String materialName = road->mMaterialName; + String materialAssetId = road->mMaterialAssetId; F32 textureLength = road->mTextureLength; F32 breakAngle = road->mBreakAngle; F32 segmentsPerBatch = road->mSegmentsPerBatch; @@ -108,7 +108,7 @@ void GuiRoadEditorUndoAction::undo() nodes.merge( road->mNodes ); // Restore the Road properties saved in the UndoAction - road->mMaterialName = materialName; + road->setMaterialAssetId(materialAssetId); road->mBreakAngle = breakAngle; road->mSegmentsPerBatch = segmentsPerBatch; road->mTextureLength = textureLength; @@ -130,7 +130,7 @@ void GuiRoadEditorUndoAction::undo() // Now save the previous Road data in this UndoAction // since an undo action must become a redo action and vice-versa - mMaterialName = materialName; + mMaterialAssetId = materialAssetId; mBreakAngle = breakAngle; mSegmentsPerBatch = segmentsPerBatch; mTextureLength = textureLength; @@ -153,6 +153,8 @@ bool GuiRoadEditorCtrl::onAdd() mZDisableSB = GFX->createStateBlock(desc); + bindMaterialAsset(Material); + return true; } @@ -163,8 +165,9 @@ void GuiRoadEditorCtrl::initPersistFields() addField( "SelectedSplineColor", TypeColorI, Offset( mSelectedSplineColor, GuiRoadEditorCtrl ) ); addField( "HoverNodeColor", TypeColorI, Offset( mHoverNodeColor, GuiRoadEditorCtrl ) ); addField( "isDirty", TypeBool, Offset( mIsDirty, GuiRoadEditorCtrl ) ); - addField( "materialName", TypeString, Offset( mMaterialName, GuiRoadEditorCtrl ), - "Default Material used by the Road Editor on road creation." ); + + addField("material", TypeMaterialAssetId, Offset(mMaterialAssetId, GuiRoadEditorCtrl), "Default Material used by the Road Editor on road creation."); + //addField( "MoveNodeCursor", TYPEID< SimObject >(), Offset( mMoveNodeCursor, GuiRoadEditorCtrl) ); //addField( "AddNodeCursor", TYPEID< SimObject >(), Offset( mAddNodeCursor, GuiRoadEditorCtrl) ); //addField( "InsertNodeCursor", TYPEID< SimObject >(), Offset( mInsertNodeCursor, GuiRoadEditorCtrl) ); @@ -405,8 +408,8 @@ void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) DecalRoad *newRoad = new DecalRoad; - - newRoad->mMaterialName = mMaterialName; + if (mMaterialAsset.notNull()) + newRoad->setMaterialAssetId(mMaterialAssetId); newRoad->registerObject(); @@ -1027,7 +1030,7 @@ void GuiRoadEditorCtrl::submitUndo( const UTF8 *name ) action->mObjId = mSelRoad->getId(); action->mBreakAngle = mSelRoad->mBreakAngle; - action->mMaterialName = mSelRoad->mMaterialName; + action->mMaterialAssetId = mSelRoad->mMaterialAssetId; action->mSegmentsPerBatch = mSelRoad->mSegmentsPerBatch; action->mTextureLength = mSelRoad->mTextureLength; action->mRoadEditor = this; diff --git a/Engine/source/environment/editors/guiRoadEditorCtrl.h b/Engine/source/environment/editors/guiRoadEditorCtrl.h index 5993f5e13..570f63fc2 100644 --- a/Engine/source/environment/editors/guiRoadEditorCtrl.h +++ b/Engine/source/environment/editors/guiRoadEditorCtrl.h @@ -103,7 +103,8 @@ class GuiRoadEditorCtrl : public EditTSCtrl public: - StringTableEntry mMaterialName; + StringTableEntry mMaterialAssetId; + AssetPtr mMaterialAsset; protected: void _drawRoadSpline( DecalRoad *road, const ColorI &color ); @@ -158,7 +159,7 @@ class GuiRoadEditorUndoAction : public UndoAction Vector mNodes; SimObjectId mObjId; - String mMaterialName; + StringTableEntry mMaterialAssetId; F32 mBreakAngle; U32 mSegmentsPerBatch; F32 mTextureLength; diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index cf15ef9ab..6c7aaf015 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -920,6 +920,10 @@ MeshRoad::MeshRoad() mTriangleCount[i] = 0; } + initMaterialAsset(TopMaterial); + initMaterialAsset(BottomMaterial); + initMaterialAsset(SideMaterial); + mSideProfile.mRoad = this; } @@ -933,14 +937,9 @@ void MeshRoad::initPersistFields() { addGroup( "MeshRoad" ); - addField( "topMaterial", TypeMaterialName, Offset( mMaterialName[Top], MeshRoad ), - "Material for the upper surface of the road." ); - - addField( "bottomMaterial", TypeMaterialName, Offset( mMaterialName[Bottom], MeshRoad ), - "Material for the bottom surface of the road." ); - - addField( "sideMaterial", TypeMaterialName, Offset( mMaterialName[Side], MeshRoad ), - "Material for the left, right, front, and back surfaces of the road." ); + scriptBindMaterialAsset(TopMaterial, MeshRoad, "Material for the upper surface of the road."); + scriptBindMaterialAsset(BottomMaterial, MeshRoad, "Material for the bottom surface of the road."); + scriptBindMaterialAsset(SideMaterial, MeshRoad, "Material for the left, right, front, and back surfaces of the road."); addField( "textureLength", TypeF32, Offset( mTextureLength, MeshRoad ), "The length in meters of textures mapped to the MeshRoad." ); @@ -1265,17 +1264,68 @@ void MeshRoad::prepRenderImage( SceneRenderState* state ) void MeshRoad::_initMaterial() { - for ( U32 i = 0; i < SurfaceCount; i++ ) + if (mTopMaterialAsset.notNull()) { - if ( mMatInst[i] ) - SAFE_DELETE( mMatInst[i] ); + if (!mMatInst[Top] || !String(mTopMaterialAsset->getMaterialDefinitionName()).equal(mMatInst[Top]->getMaterial()->getName(), String::NoCase)) + { + SAFE_DELETE(mMatInst[Top]); - if ( mMaterial[i] ) - mMatInst[i] = mMaterial[i]->createMatInstance(); - else - mMatInst[i] = MATMGR->createMatInstance( "WarningMaterial" ); + Material* tMat = nullptr; + if (!Sim::findObject(mTopMaterialAsset->getMaterialDefinitionName(), tMat)) + Con::errorf("MeshRoad::_initMaterial - Material %s was not found.", mTopMaterialAsset->getMaterialDefinitionName()); - mMatInst[i]->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat() ); + mMaterial[Top] = tMat; + + if (mMaterial[Top]) + mMatInst[Top] = mMaterial[Top]->createMatInstance(); + else + mMatInst[Top] = MATMGR->createMatInstance("WarningMaterial"); + + mMatInst[Top]->init(MATMGR->getDefaultFeatures(), getGFXVertexFormat()); + } + } + + if (mBottomMaterialAsset.notNull()) + { + if (!mMatInst[Bottom] || !String(mBottomMaterialAsset->getMaterialDefinitionName()).equal(mMatInst[Bottom]->getMaterial()->getName(), String::NoCase)) + { + + SAFE_DELETE(mMatInst[Bottom]); + + Material* tMat = nullptr; + if (!Sim::findObject(mBottomMaterialAsset->getMaterialDefinitionName(), tMat)) + Con::errorf("MeshRoad::_initMaterial - Material %s was not found.", mBottomMaterialAsset->getMaterialDefinitionName()); + + mMaterial[Bottom] = tMat; + + if (mMaterial[Bottom]) + mMatInst[Bottom] = mMaterial[Bottom]->createMatInstance(); + else + mMatInst[Bottom] = MATMGR->createMatInstance("WarningMaterial"); + + mMatInst[Bottom]->init(MATMGR->getDefaultFeatures(), getGFXVertexFormat()); + } + } + + if (mSideMaterialAsset.notNull()) + { + if (!mMatInst[Side] || !String(mSideMaterialAsset->getMaterialDefinitionName()).equal(mMatInst[Side]->getMaterial()->getName(), String::NoCase)) + { + SAFE_DELETE(mMatInst[Side]); + + Material* tMat = nullptr; + if (!Sim::findObject(mSideMaterialAsset->getMaterialDefinitionName(), tMat)) + Con::errorf("MeshRoad::_initMaterial - Material %s was not found.", mSideMaterialAsset->getMaterialDefinitionName()); + + mMaterial[Side] = tMat; + + if (mMaterial[Side]) + mMatInst[Side] = mMaterial[Side]->createMatInstance(); + else + mMatInst[Side] = MATMGR->createMatInstance("WarningMaterial"); + + mMatInst[Side]->init(MATMGR->getDefaultFeatures(), getGFXVertexFormat()); + } } } @@ -1365,10 +1415,10 @@ U32 MeshRoad::packUpdate(NetConnection * con, U32 mask, BitStream * stream) // Write Object Transform. stream->writeAffineTransform( mObjToWorld ); - // Write Materials - stream->write( mMaterialName[0] ); - stream->write( mMaterialName[1] ); - stream->write( mMaterialName[2] ); + // Write Materials + packMaterialAsset(con, TopMaterial); + packMaterialAsset(con, BottomMaterial); + packMaterialAsset(con, SideMaterial); stream->write( mTextureLength ); stream->write( mBreakAngle ); @@ -1465,18 +1515,9 @@ void MeshRoad::unpackUpdate(NetConnection * con, BitStream * stream) stream->readAffineTransform(&ObjectMatrix); Parent::setTransform(ObjectMatrix); - // Read Materials... - Material *pMat = NULL; - - for ( U32 i = 0; i < SurfaceCount; i++ ) - { - stream->read( &mMaterialName[i] ); - - if ( !Sim::findObject( mMaterialName[i], pMat ) ) - Con::printf( "DecalRoad::unpackUpdate, failed to find Material of name %s", mMaterialName[i].c_str() ); - else - mMaterial[i] = pMat; - } + unpackMaterialAsset(con, TopMaterial); + unpackMaterialAsset(con, BottomMaterial); + unpackMaterialAsset(con, SideMaterial); if ( isProperlyAdded() ) _initMaterial(); diff --git a/Engine/source/environment/meshRoad.h b/Engine/source/environment/meshRoad.h index b817d6b8d..2a6f97607 100644 --- a/Engine/source/environment/meshRoad.h +++ b/Engine/source/environment/meshRoad.h @@ -52,6 +52,8 @@ #include "math/util/decomposePoly.h" +#include "T3D/assets/MaterialAsset.h" + //extern U32 gIdxArray[6][2][3]; struct MeshRoadHitSegment @@ -619,7 +621,11 @@ protected: GFXVertexBufferHandle mVB[SurfaceCount]; GFXPrimitiveBufferHandle mPB[SurfaceCount]; - String mMaterialName[SurfaceCount]; + DECLARE_NET_MATERIALASSET(MeshRoad, TopMaterial, MeshRoadMask); + DECLARE_NET_MATERIALASSET(MeshRoad, BottomMaterial, MeshRoadMask); + DECLARE_NET_MATERIALASSET(MeshRoad, SideMaterial, MeshRoadMask); + + //String mMaterialName[SurfaceCount]; SimObjectPtr mMaterial[SurfaceCount]; BaseMatInstance *mMatInst[SurfaceCount]; diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs index 1269eab28..cd40caa40 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.cs @@ -1058,7 +1058,10 @@ function AssetBrowser::toggleTagFilterPopup(%this) function AssetBrowser::changeAsset(%this) { //alright, we've selectd an asset for a field, so time to set it! - %cmd = %this.fieldTargetObject @ "." @ %this.fieldTargetName @ "=\"" @ %this.selectedAsset @ "\";"; + if(%this.fieldTargetName $= "") + %cmd = %this.fieldTargetObject @ ".apply(\""@ %this.selectedAsset @ "\");"; + else + %cmd = %this.fieldTargetObject @ "." @ %this.fieldTargetName @ "=\"" @ %this.selectedAsset @ "\";"; echo("Changing asset via the " @ %cmd @ " command"); eval(%cmd); diff --git a/Templates/BaseGame/game/tools/meshRoadEditor/main.cs b/Templates/BaseGame/game/tools/meshRoadEditor/main.cs index d1dc613f7..af441d82a 100644 --- a/Templates/BaseGame/game/tools/meshRoadEditor/main.cs +++ b/Templates/BaseGame/game/tools/meshRoadEditor/main.cs @@ -23,6 +23,10 @@ function initializeMeshRoadEditor() { echo(" % - Initializing Mesh Road Editor"); + + $MeshRoadEditor::defaultTopMaterialAsset = "Prototyping:FloorGray"; + $MeshRoadEditor::defaultBottomMaterialAsset = "Prototyping:FloorGray"; + $MeshRoadEditor::defaultSideMaterialAsset = "Prototyping:WallOrange"; exec( "./meshRoadEditor.cs" ); exec( "./meshRoadEditorGui.gui" ); diff --git a/Templates/BaseGame/game/tools/roadEditor/main.cs b/Templates/BaseGame/game/tools/roadEditor/main.cs index 992d11164..9e678fa39 100644 --- a/Templates/BaseGame/game/tools/roadEditor/main.cs +++ b/Templates/BaseGame/game/tools/roadEditor/main.cs @@ -24,6 +24,8 @@ function initializeRoadEditor() { echo( " - Initializing Road and Path Editor" ); + $DecalRoadEditor::defaultMaterialAsset = "Prototyping:FloorGray"; + exec( "./roadEditor.cs" ); exec( "./RoadEditorGui.gui" ); exec( "./RoadEditorToolbar.gui"); @@ -183,7 +185,7 @@ function RoadEditorPlugin::initSettings( %this ) EditorSettings.setDefaultValue( "HoverSplineColor", "255 0 0 255" ); EditorSettings.setDefaultValue( "SelectedSplineColor", "0 255 0 255" ); EditorSettings.setDefaultValue( "HoverNodeColor", "255 255 255 255" ); //<-- Not currently used - EditorSettings.setDefaultValue( "MaterialName", "DefaultDecalRoadMaterial" ); + EditorSettings.setDefaultValue( "materialAsset", "Prototyping:FloorGray" ); EditorSettings.endGroup(); } @@ -196,7 +198,7 @@ function RoadEditorPlugin::readSettings( %this ) RoadEditorGui.HoverSplineColor = EditorSettings.value("HoverSplineColor"); RoadEditorGui.SelectedSplineColor = EditorSettings.value("SelectedSplineColor"); RoadEditorGui.HoverNodeColor = EditorSettings.value("HoverNodeColor"); - RoadEditorGui.materialName = EditorSettings.value("MaterialName"); + RoadEditorGui.materialAsset = EditorSettings.value("materialAsset"); EditorSettings.endGroup(); } @@ -209,7 +211,7 @@ function RoadEditorPlugin::writeSettings( %this ) EditorSettings.setValue( "HoverSplineColor", RoadEditorGui.HoverSplineColor ); EditorSettings.setValue( "SelectedSplineColor", RoadEditorGui.SelectedSplineColor ); EditorSettings.setValue( "HoverNodeColor", RoadEditorGui.HoverNodeColor ); - EditorSettings.setValue( "MaterialName", RoadEditorGui.materialName ); + EditorSettings.setValue( "materialAsset", RoadEditorGui.materialAsset ); EditorSettings.endGroup(); }