Browse Source

Corrected profile for GameObjectAsset type field button
Initial implementation of changeable TSStatic materials via material slots and drag and drop of material assets onto world editor from AB
Updated Volumetric Fog to support ShapeAsset for it's model data
Added cmake option to hide literal filename fields if the class supports asset fields for the same input
Added light viz modes to see diffuse, specular and detail lighting modes(currently just sun)
New raycast console function to return back material of hit object
Moved GameObject logic to SceneObject and started fixing up of editor behavior to allow any SceneObject to be converted into a GO, along with all supported behavior such as instance-template management and spawning GO via drag-and-drop from AB
Fixed inspector field tooltip text to be positioned in inspector footer properly again
Drag and drop of shape asset attempts to drop at raycast position now, instead of just at the camera ray position

Areloch 5 years ago
parent
commit
09c651c26d
25 changed files with 570 additions and 33 deletions
  1. 2 2
      Engine/source/T3D/assets/GameObjectAsset.cpp
  2. 1 1
      Engine/source/T3D/assets/ShapeAsset.cpp
  3. 144 1
      Engine/source/T3D/tsStatic.cpp
  4. 17 2
      Engine/source/T3D/tsStatic.h
  5. 73 10
      Engine/source/environment/VolumetricFog.cpp
  6. 14 0
      Engine/source/environment/VolumetricFog.h
  7. 6 1
      Engine/source/gui/controls/guiTextEditCtrl.cpp
  8. 3 0
      Engine/source/gui/controls/guiTextEditCtrl.h
  9. 29 1
      Engine/source/lighting/advanced/advancedLightBinManager.cpp
  10. 5 0
      Engine/source/lighting/advanced/advancedLightBinManager.h
  11. 53 0
      Engine/source/scene/sceneContainer.cpp
  12. 20 1
      Engine/source/scene/sceneObject.cpp
  13. 15 0
      Engine/source/scene/sceneObject.h
  14. 32 0
      Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl
  15. 25 0
      Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl
  16. 0 1
      Templates/BaseGame/game/tools/assetBrowser/guis/GameObjectCreator.gui
  17. 28 0
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameObject.cs
  18. 26 0
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.cs
  19. 16 6
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.cs
  20. 1 1
      Templates/BaseGame/game/tools/worldEditor/gui/WorldEditorInspectorWindow.ed.gui
  21. 4 0
      Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs
  22. 46 1
      Templates/BaseGame/game/tools/worldEditor/scripts/visibility/lightViz.cs
  23. 1 0
      Templates/BaseGame/game/tools/worldEditor/scripts/visibility/probeViz.cs
  24. 2 5
      Templates/BaseGame/game/tools/worldEditor/scripts/visibility/visibilityLayer.ed.cs
  25. 7 0
      Tools/CMake/torque3d.cmake

+ 2 - 2
Engine/source/T3D/assets/GameObjectAsset.cpp

@@ -262,8 +262,8 @@ GuiControl* GuiInspectorTypeGameObjectAssetPtr::constructEditControl()
    dSprintf(szBuffer, sizeof(szBuffer), "%d.onClick(%s);", this->getId(), mCaption);
    dSprintf(szBuffer, sizeof(szBuffer), "%d.onClick(%s);", this->getId(), mCaption);
    mGameObjectEditButton->setField("Command", szBuffer);
    mGameObjectEditButton->setField("Command", szBuffer);
 
 
-   mGameObjectEditButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
-   mGameObjectEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+   mGameObjectEditButton->setDataField(StringTable->insert("Profile"), NULL, "ToolsGuiButtonProfile");
+   mGameObjectEditButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "ToolsGuiToolTipProfile");
    mGameObjectEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
    mGameObjectEditButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
 
 
    const char* assetId = getData();
    const char* assetId = getData();

+ 1 - 1
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -366,7 +366,7 @@ GuiControl* GuiInspectorTypeShapeAssetPtr::constructEditControl()
 
 
    // Change filespec
    // Change filespec
    char szBuffer[512];
    char szBuffer[512];
-   dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %d, %s);", 
+   dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %s, %s);", 
       mInspector->getInspectObject()->getIdString(), mCaption);
       mInspector->getInspectObject()->getIdString(), mCaption);
    mBrowseButton->setField("Command", szBuffer);
    mBrowseButton->setField("Command", szBuffer);
 
 

+ 144 - 1
Engine/source/T3D/tsStatic.cpp

@@ -171,8 +171,10 @@ void TSStatic::initPersistFields()
          &TSStatic::_setShapeAsset, &defaultProtectedGetFn,
          &TSStatic::_setShapeAsset, &defaultProtectedGetFn,
          "The source shape asset.");
          "The source shape asset.");
 
 
+#ifdef TORQUE_ALLOW_DIRECT_FILENAMES
       addField("shapeName",   TypeShapeFilename,  Offset( mShapeName, TSStatic ),
       addField("shapeName",   TypeShapeFilename,  Offset( mShapeName, TSStatic ),
          "%Path and filename of the model file (.DTS, .DAE) to use for this TSStatic." );
          "%Path and filename of the model file (.DTS, .DAE) to use for this TSStatic." );
+#endif
 
 
       addProtectedField( "skin", TypeRealString, Offset( mAppliedSkinName, TSStatic ), &_setFieldSkin, &_getFieldSkin,
       addProtectedField( "skin", TypeRealString, Offset( mAppliedSkinName, TSStatic ), &_setFieldSkin, &_getFieldSkin,
       "@brief The skin applied to the shape.\n\n"
       "@brief The skin applied to the shape.\n\n"
@@ -289,7 +291,7 @@ void TSStatic::inspectPostApply()
 
 
    if(isServerObject()) 
    if(isServerObject()) 
    {
    {
-      setMaskBits(AdvancedStaticOptionsMask);
+      setMaskBits(-1);
       prepCollision();
       prepCollision();
    }
    }
 
 
@@ -463,9 +465,74 @@ bool TSStatic::_createShape()
       Sim::findObject( cubeDescId, reflectorDesc );
       Sim::findObject( cubeDescId, reflectorDesc );
    }
    }
 
 
+   //Set up the material slot vars for easy manipulation
+   S32 materialCount = mShape->materialList->getMaterialNameList().size(); //mMeshAsset->getMaterialCount();
+
+   if (isServerObject())
+   {
+      char matFieldName[128];
+
+      for (U32 i = 0; i < materialCount; i++)
+      {
+         StringTableEntry materialname = StringTable->insert(mShape->materialList->getMaterialName(i).c_str());
+
+         dSprintf(matFieldName, 128, "MaterialSlot%d", i);
+         StringTableEntry matFld = StringTable->insert(matFieldName);
+
+         setDataField(matFld, NULL, materialname);
+      }
+   }
+
    return true;
    return true;
 }
 }
 
 
+void TSStatic::onDynamicModified(const char* slotName, const char* newValue)
+{
+   bool isSrv = isServerObject();
+
+   if (FindMatch::isMatch("materialslot*", slotName, false))
+   {
+      if (!getShape())
+         return;
+
+      S32 slot = -1;
+      String outStr(String::GetTrailingNumber(slotName, slot));
+
+      if (slot == -1)
+         return;
+
+      //Safe to assume the inbound value for the material will be a MaterialAsset, so lets do a lookup on the name
+      MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newValue);
+      if (!matAsset)
+         return;
+
+      bool found = false;
+      for (U32 i = 0; i < mChangingMaterials.size(); i++)
+      {
+         if (mChangingMaterials[i].slot == slot)
+         {
+            mChangingMaterials[i].matAsset = matAsset;
+            mChangingMaterials[i].assetId = newValue;
+            found = true;
+         }
+      }
+
+      if (!found)
+      {
+         matMap newMatMap;
+         newMatMap.slot = slot;
+         newMatMap.matAsset = matAsset;
+         newMatMap.assetId = newValue;
+
+         mChangingMaterials.push_back(newMatMap);
+      }
+
+      setMaskBits(MaterialMask);
+   }
+
+   Parent::onDynamicModified(slotName, newValue);
+}
+
 void TSStatic::prepCollision()
 void TSStatic::prepCollision()
 {
 {
    // Let the client know that the collision was updated
    // Let the client know that the collision was updated
@@ -918,6 +985,22 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
    }
    }
 
 
    stream->write(mOverrideColor);
    stream->write(mOverrideColor);
+
+   if (stream->writeFlag(mask & MaterialMask))
+   {
+      stream->writeInt(mChangingMaterials.size(), 16);
+
+      for (U32 i = 0; i < mChangingMaterials.size(); i++)
+      {
+         stream->writeInt(mChangingMaterials[i].slot, 16);
+
+         NetStringHandle matNameStr = mChangingMaterials[i].assetId.c_str();
+         con->packNetStringHandleU(stream, matNameStr);
+      }
+
+      mChangingMaterials.clear();
+   }
+
    return retMask;
    return retMask;
 }
 }
 
 
@@ -1019,6 +1102,26 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream)
 
 
    stream->read(&mOverrideColor);
    stream->read(&mOverrideColor);
 
 
+   if (stream->readFlag())
+   {
+      mChangingMaterials.clear();
+      U32 materialCount = stream->readInt(16);
+
+      for (U32 i = 0; i < materialCount; i++)
+      {
+         matMap newMatMap;
+         newMatMap.slot = stream->readInt(16);
+         newMatMap.assetId = String(con->unpackNetStringHandleU(stream).getString());
+
+         //do the lookup, now
+         newMatMap.matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newMatMap.assetId);
+
+         mChangingMaterials.push_back(newMatMap);
+      }
+
+      updateMaterials();
+   }
+
    if ( isProperlyAdded() )
    if ( isProperlyAdded() )
       _updateShouldTick();
       _updateShouldTick();
    set_special_typing();
    set_special_typing();
@@ -1458,6 +1561,46 @@ U32 TSStatic::getNumDetails()
 	return 0;
 	return 0;
 };
 };
 
 
+void TSStatic::updateMaterials()
+{
+   if (mChangingMaterials.empty() || !mShape)
+      return;
+
+   TSMaterialList* pMatList = mShapeInstance->getMaterialList();
+
+   String path;
+   if (mShapeAsset->isAssetValid())
+      path = mShapeAsset->getShapeFilename();
+   else
+      path = mShapeName;
+
+   pMatList->setTextureLookupPath(path);
+
+   bool found = false;
+   const Vector<String>& materialNames = pMatList->getMaterialNameList();
+   for (S32 i = 0; i < materialNames.size(); i++)
+   {
+      if (found)
+         break;
+
+      for (U32 m = 0; m < mChangingMaterials.size(); m++)
+      {
+         if (mChangingMaterials[m].slot == i)
+         {
+            //Fetch the actual material asset
+            pMatList->renameMaterial(i, mChangingMaterials[m].matAsset->getMaterialDefinitionName());
+            found = true;
+            break;
+         }
+      }
+   }
+
+   mChangingMaterials.clear();
+
+   // Initialize the material instances
+   mShapeInstance->initMaterialList();
+}
+
 //------------------------------------------------------------------------
 //------------------------------------------------------------------------
 //These functions are duplicated in tsStatic and shapeBase.
 //These functions are duplicated in tsStatic and shapeBase.
 //They each function a little differently; but achieve the same purpose of gathering
 //They each function a little differently; but achieve the same purpose of gathering

+ 17 - 2
Engine/source/T3D/tsStatic.h

@@ -108,8 +108,9 @@ class TSStatic : public SceneObject
       TransformMask              = Parent::NextFreeMask << 0,
       TransformMask              = Parent::NextFreeMask << 0,
       AdvancedStaticOptionsMask  = Parent::NextFreeMask << 1,
       AdvancedStaticOptionsMask  = Parent::NextFreeMask << 1,
       UpdateCollisionMask        = Parent::NextFreeMask << 2,
       UpdateCollisionMask        = Parent::NextFreeMask << 2,
-      SkinMask                   = Parent::NextFreeFlag << 3,
-      NextFreeMask               = Parent::NextFreeMask << 4
+      SkinMask                   = Parent::NextFreeMask << 3,
+      MaterialMask               = Parent::NextFreeMask << 4,
+      NextFreeMask               = Parent::NextFreeMask << 5
    };
    };
 
 
 public:
 public:
@@ -137,6 +138,16 @@ protected:
    F32  mAlphaFade;
    F32  mAlphaFade;
    bool mInvertAlphaFade;
    bool mInvertAlphaFade;
 
 
+   struct matMap
+   {
+      MaterialAsset* matAsset;
+      String assetId;
+      U32 slot;
+   };
+
+   Vector<matMap>  mChangingMaterials;
+   Vector<matMap>  mMaterials;
+
    bool onAdd();
    bool onAdd();
    void onRemove();
    void onRemove();
 
 
@@ -163,6 +174,8 @@ protected:
    virtual void interpolateTick( F32 delta );   
    virtual void interpolateTick( F32 delta );   
    virtual void advanceTime( F32 dt );
    virtual void advanceTime( F32 dt );
 
 
+   virtual void onDynamicModified(const char* slotName, const char* newValue);
+
    /// Start or stop processing ticks depending on our state.
    /// Start or stop processing ticks depending on our state.
    void _updateShouldTick();
    void _updateShouldTick();
 
 
@@ -261,6 +274,8 @@ public:
 
 
    virtual void onInspect(GuiInspector*);
    virtual void onInspect(GuiInspector*);
 
 
+   void updateMaterials();
+
 private:
 private:
    virtual void   onStaticModified(const char* slotName, const char*newValue = NULL);
    virtual void   onStaticModified(const char* slotName, const char*newValue = NULL);
 protected:
 protected:

+ 73 - 10
Engine/source/environment/VolumetricFog.cpp

@@ -138,6 +138,9 @@ VolumetricFog::VolumetricFog()
    mTexTiles = 1.0f;
    mTexTiles = 1.0f;
    mSpeed1.set(0.5f, 0.0f);
    mSpeed1.set(0.5f, 0.0f);
    mSpeed2.set(0.1f, 0.1f);
    mSpeed2.set(0.1f, 0.1f);
+
+   mShapeAsset = StringTable->EmptyString();
+   mShapeAssetId = StringTable->EmptyString();
 }
 }
 
 
 VolumetricFog::~VolumetricFog()
 VolumetricFog::~VolumetricFog()
@@ -165,8 +168,14 @@ VolumetricFog::~VolumetricFog()
 void VolumetricFog::initPersistFields()
 void VolumetricFog::initPersistFields()
 {
 {
    addGroup("VolumetricFogData");
    addGroup("VolumetricFogData");
+   addProtectedField("shapeAsset", TypeShapeAssetPtr, Offset(mShapeAsset, VolumetricFog),
+      &VolumetricFog::_setShapeAsset, &defaultProtectedGetFn, "The source shape asset.");
+
+#ifdef TORQUE_ALLOW_DIRECT_FILENAMES
    addField("shapeName", TypeShapeFilename, Offset(mShapeName, VolumetricFog),
    addField("shapeName", TypeShapeFilename, Offset(mShapeName, VolumetricFog),
       "Path and filename of the model file (.DTS, .DAE) to use for this Volume.");
       "Path and filename of the model file (.DTS, .DAE) to use for this Volume.");
+#endif
+
    addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog),
    addField("FogColor", TypeColorI, Offset(mFogColor, VolumetricFog),
       "Fog color RGBA (Alpha is ignored)");
       "Fog color RGBA (Alpha is ignored)");
    addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog), 
    addField("FogDensity", TypeF32, Offset(mFogDensity, VolumetricFog), 
@@ -212,6 +221,15 @@ void VolumetricFog::initPersistFields()
    Parent::initPersistFields();
    Parent::initPersistFields();
 }
 }
 
 
+bool VolumetricFog::_setShapeAsset(void* obj, const char* index, const char* data)
+{
+   VolumetricFog* fog = static_cast<VolumetricFog*>(obj);// ->setFile(FileName(data));
+
+   fog->setShapeAsset(StringTable->insert(data));
+
+   return false;
+}
+
 void VolumetricFog::inspectPostApply()
 void VolumetricFog::inspectPostApply()
 {
 {
    Parent::inspectPostApply();
    Parent::inspectPostApply();
@@ -328,19 +346,49 @@ void VolumetricFog::handleResize(VolumetricFogRTManager *RTM, bool resize)
 // Loadshape extracted from TSMesh and TSShapeInstance
 // Loadshape extracted from TSMesh and TSShapeInstance
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+bool VolumetricFog::setShapeAsset(const StringTableEntry shapeAssetId)
+{
+   mShapeAssetId = shapeAssetId;
+
+   LoadShape();
+   return true;
+}
+
 bool VolumetricFog::LoadShape()
 bool VolumetricFog::LoadShape()
 {
 {
    GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
    GFXPrimitiveType GFXdrawTypes[] = { GFXTriangleList, GFXTriangleStrip };
-   if (!mShapeName || mShapeName[0] == '\0')
+
+   Resource<TSShape> mShape;
+   if (mShapeAssetId != StringTable->EmptyString())
    {
    {
-      Con::errorf("VolumetricFog::LoadShape() - No shape name! Volumetric Fog will not be rendered!");
-      return false;
+      mShapeAsset = mShapeAssetId;
+
+      if (mShapeAsset.isNull())
+      {
+         Con::errorf("[TSStatic] Failed to load shape asset.");
+         return false;
+      }
+
+      mShape = mShapeAsset->getShapeResource();
+
+      if (!mShape)
+      {
+         Con::errorf("TSStatic::_createShape() - Shape Asset had no valid shape!");
+         return false;
+      }
    }
    }
+   else
+   {
+      if (!mShapeName || mShapeName[0] == '\0')
+      {
+         Con::errorf("VolumetricFog::LoadShape() - No shape name! Volumetric Fog will not be rendered!");
+         return false;
+      }
 
 
-   // Load shape, server side only reads bounds and radius
+      // Load shape, server side only reads bounds and radius
+      mShape = ResourceManager::get().load(mShapeName);
+   }
 
 
-   Resource<TSShape> mShape;
-   mShape = ResourceManager::get().load(mShapeName);
    if (bool(mShape) == false)
    if (bool(mShape) == false)
    {
    {
       Con::errorf("VolumetricFog::LoadShape() - Unable to load shape: %s", mShapeName);
       Con::errorf("VolumetricFog::LoadShape() - Unable to load shape: %s", mShapeName);
@@ -551,15 +599,25 @@ U32 VolumetricFog::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
    }
    }
    if (stream->writeFlag(mask & FogShapeMask))
    if (stream->writeFlag(mask & FogShapeMask))
    {
    {
+      stream->writeString(mShapeAssetId);
       stream->writeString(mShapeName);
       stream->writeString(mShapeName);
       mathWrite(*stream, getTransform());
       mathWrite(*stream, getTransform());
       mathWrite(*stream, getScale());
       mathWrite(*stream, getScale());
-      if (!mShapeName || mShapeName[0] == '\0')
-         return retMask;
+
       Resource<TSShape> mShape;
       Resource<TSShape> mShape;
-      mShape = ResourceManager::get().load(mShapeName);
+
+      if (mShapeAssetId != StringTable->EmptyString())
+      {
+         mShape = mShape = mShapeAsset->getShapeResource();
+      }
+      else if (mShapeName && mShapeName[0] != '\0')
+      {
+         mShape = ResourceManager::get().load(mShapeName);
+      }
+
       if (bool(mShape) == false)
       if (bool(mShape) == false)
          return retMask;
          return retMask;
+
       mObjBox = mShape->mBounds;
       mObjBox = mShape->mBounds;
       mRadius = mShape->mRadius;
       mRadius = mShape->mRadius;
       resetWorldBox();
       resetWorldBox();
@@ -577,6 +635,7 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
    VectorF scale;
    VectorF scale;
    VectorF mOldScale = getScale();
    VectorF mOldScale = getScale();
    String oldTextureName = mTextureName;
    String oldTextureName = mTextureName;
+   StringTableEntry oldShapeAsset = mShapeAssetId;
    StringTableEntry oldShape = mShapeName;
    StringTableEntry oldShape = mShapeName;
 
 
    if (stream->readFlag())// Fog color
    if (stream->readFlag())// Fog color
@@ -647,10 +706,14 @@ void VolumetricFog::unpackUpdate(NetConnection *con, BitStream *stream)
    }
    }
    if (stream->readFlag())//Fog shape
    if (stream->readFlag())//Fog shape
    {
    {
+      char buffer[256];
+      stream->readString(buffer);
+      mShapeAssetId = StringTable->insert(buffer);
+
       mShapeName = stream->readSTString();
       mShapeName = stream->readSTString();
       mathRead(*stream, &mat);
       mathRead(*stream, &mat);
       mathRead(*stream, &scale);
       mathRead(*stream, &scale);
-      if (strcmp(oldShape, mShapeName) != 0)
+      if (strcmp(oldShapeAsset, mShapeAssetId) != 0 || strcmp(oldShape, mShapeName) != 0)
       {
       {
          mIsVBDirty = true;
          mIsVBDirty = true;
          mShapeLoaded = LoadShape();
          mShapeLoaded = LoadShape();

+ 14 - 0
Engine/source/environment/VolumetricFog.h

@@ -46,6 +46,13 @@
 #endif
 #endif
    
    
 #include "gui/core/guiCanvas.h"
 #include "gui/core/guiCanvas.h"
+
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif 
+#ifndef SHAPEASSET_H
+#include "T3D/assets/ShapeAsset.h"
+#endif 
    
    
 class VolumetricFogRTManager;
 class VolumetricFogRTManager;
    
    
@@ -136,6 +143,9 @@ class VolumetricFog : public SceneObject
       GFXPrimitiveBufferHandle mPB;
       GFXPrimitiveBufferHandle mPB;
    
    
       // Fog volume data;
       // Fog volume data;
+      AssetPtr<ShapeAsset> mShapeAsset;
+      StringTableEntry mShapeAssetId;
+
       StringTableEntry mShapeName;
       StringTableEntry mShapeName;
       ColorI mFogColor;
       ColorI mFogColor;
       F32 mFogDensity;
       F32 mFogDensity;
@@ -209,6 +219,8 @@ class VolumetricFog : public SceneObject
       void processTick(const Move *move);
       void processTick(const Move *move);
       void _enterFog(ShapeBase *control);
       void _enterFog(ShapeBase *control);
       void _leaveFog(ShapeBase *control);
       void _leaveFog(ShapeBase *control);
+
+      static bool _setShapeAsset(void* obj, const char* index, const char* data);
    
    
    public:
    public:
       // Public methods
       // Public methods
@@ -234,6 +246,8 @@ class VolumetricFog : public SceneObject
       void setFogGlow(bool on_off, F32 strength);
       void setFogGlow(bool on_off, F32 strength);
       void setFogLightray(bool on_off, F32 strength);
       void setFogLightray(bool on_off, F32 strength);
       bool isInsideFog();
       bool isInsideFog();
+
+      bool setShapeAsset(const StringTableEntry shapeAssetId);
    
    
       DECLARE_CONOBJECT(VolumetricFog);
       DECLARE_CONOBJECT(VolumetricFog);
    
    

+ 6 - 1
Engine/source/gui/controls/guiTextEditCtrl.cpp

@@ -138,6 +138,9 @@ GuiTextEditCtrl::GuiTextEditCtrl()
    mHistoryIndex = 0;
    mHistoryIndex = 0;
    mHistoryBuf = NULL;
    mHistoryBuf = NULL;
 
 
+   mDoubleClickTimeMS = 50;
+   mMouseUpTime = 0;
+
 #if defined(__MACOSX__)
 #if defined(__MACOSX__)
    UTF8  bullet[4] = { 0xE2, 0x80, 0xA2, 0 };
    UTF8  bullet[4] = { 0xE2, 0x80, 0xA2, 0 };
    
    
@@ -382,7 +385,7 @@ void GuiTextEditCtrl::onMouseDown( const GuiEvent &event )
 
 
    // If we have a double click, select all text.  Otherwise
    // If we have a double click, select all text.  Otherwise
    // act as before by clearing any selection.
    // act as before by clearing any selection.
-   bool doubleClick = (event.mouseClickCount > 1);
+   bool doubleClick = (event.mouseClickCount > 1 && Platform::getRealMilliseconds() - mMouseUpTime > mDoubleClickTimeMS);
    if(doubleClick)
    if(doubleClick)
    {
    {
       selectAllText();
       selectAllText();
@@ -451,6 +454,8 @@ void GuiTextEditCtrl::onMouseUp(const GuiEvent &event)
    TORQUE_UNUSED(event);
    TORQUE_UNUSED(event);
    mDragHit = false;
    mDragHit = false;
    mScrollDir = 0;
    mScrollDir = 0;
+
+   mMouseUpTime = Platform::getRealMilliseconds();
    mouseUnlock();
    mouseUnlock();
 }
 }
 
 

+ 3 - 0
Engine/source/gui/controls/guiTextEditCtrl.h

@@ -85,6 +85,9 @@ protected:
    bool                 mPasswordText;
    bool                 mPasswordText;
    StringTableEntry     mPasswordMask;
    StringTableEntry     mPasswordMask;
 
 
+   S32                  mDoubleClickTimeMS;
+   S32                  mMouseUpTime;
+
    /// If set, any non-ESC key is handled here or not at all
    /// If set, any non-ESC key is handled here or not at all
    bool    mSinkAllKeyEvents;   
    bool    mSinkAllKeyEvents;   
    UTF16   **mHistoryBuf;
    UTF16   **mHistoryBuf;

+ 29 - 1
Engine/source/lighting/advanced/advancedLightBinManager.cpp

@@ -48,6 +48,9 @@ const String AdvancedLightBinManager::smBufferName( "specularLighting" );
 ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
 ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
 bool AdvancedLightBinManager::smPSSMDebugRender = false;
 bool AdvancedLightBinManager::smPSSMDebugRender = false;
 bool AdvancedLightBinManager::smUseSSAOMask = false;
 bool AdvancedLightBinManager::smUseSSAOMask = false;
+bool AdvancedLightBinManager::smDiffuseLightViz = false;
+bool AdvancedLightBinManager::smSpecularLightViz = false;
+bool AdvancedLightBinManager::smDetailLightingViz = false;
 
 
 ImplementEnumType( ShadowFilterMode,
 ImplementEnumType( ShadowFilterMode,
    "The shadow filtering modes for Advanced Lighting shadows.\n"
    "The shadow filtering modes for Advanced Lighting shadows.\n"
@@ -127,6 +130,9 @@ AdvancedLightBinManager::AdvancedLightBinManager( AdvancedLightManager *lm /* =
    Con::addVariableNotify( "$pref::Shadows::filterMode", callback );
    Con::addVariableNotify( "$pref::Shadows::filterMode", callback );
    Con::addVariableNotify( "$AL::PSSMDebugRender", callback );
    Con::addVariableNotify( "$AL::PSSMDebugRender", callback );
    Con::addVariableNotify( "$AL::UseSSAOMask", callback );
    Con::addVariableNotify( "$AL::UseSSAOMask", callback );
+   Con::addVariableNotify( "$AL::DiffuseLightViz", callback);
+   Con::addVariableNotify( "$AL::SpecularLightViz", callback);
+   Con::addVariableNotify( "$AL::DetailLightingViz", callback);
 }
 }
 
 
 
 
@@ -137,7 +143,10 @@ AdvancedLightBinManager::~AdvancedLightBinManager()
    Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials );
    Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials );
    Con::removeVariableNotify( "$pref::shadows::filterMode", callback );
    Con::removeVariableNotify( "$pref::shadows::filterMode", callback );
    Con::removeVariableNotify( "$AL::PSSMDebugRender", callback );
    Con::removeVariableNotify( "$AL::PSSMDebugRender", callback );
-   Con::removeVariableNotify( "$AL::UseSSAOMask", callback );  
+   Con::removeVariableNotify( "$AL::UseSSAOMask", callback );
+   Con::removeVariableNotify( "$AL::DiffuseLightViz", callback);
+   Con::removeVariableNotify( "$AL::SpecularLightViz", callback);
+   Con::removeVariableNotify( "$AL::DetailLightingViz", callback);
 }
 }
 
 
 void AdvancedLightBinManager::consoleInit()
 void AdvancedLightBinManager::consoleInit()
@@ -157,6 +166,18 @@ void AdvancedLightBinManager::consoleInit()
    Con::addVariable( "$AL::PSSMDebugRender", TypeBool, &smPSSMDebugRender,
    Con::addVariable( "$AL::PSSMDebugRender", TypeBool, &smPSSMDebugRender,
       "Enables debug rendering of the PSSM shadows.\n"
       "Enables debug rendering of the PSSM shadows.\n"
       "@ingroup AdvancedLighting\n" );
       "@ingroup AdvancedLighting\n" );
+
+   Con::addVariable("$AL::DiffuseLightViz", TypeBool, &smDiffuseLightViz,
+      "Enables debug rendering of the PSSM shadows.\n"
+      "@ingroup AdvancedLighting\n");
+
+   Con::addVariable("$AL::SpecularLightViz", TypeBool, &smSpecularLightViz,
+      "Enables debug rendering of the PSSM shadows.\n"
+      "@ingroup AdvancedLighting\n");
+
+   Con::addVariable("$AL::DetailLightingViz", TypeBool, &smDetailLightingViz,
+      "Enables debug rendering of the PSSM shadows.\n"
+      "@ingroup AdvancedLighting\n");
 }
 }
 
 
 bool AdvancedLightBinManager::setTargetSize(const Point2I &newTargetSize)
 bool AdvancedLightBinManager::setTargetSize(const Point2I &newTargetSize)
@@ -447,6 +468,13 @@ AdvancedLightBinManager::LightMaterialInfo* AdvancedLightBinManager::_getLightMa
       if ( smPSSMDebugRender )
       if ( smPSSMDebugRender )
          shadowMacros.push_back( GFXShaderMacro( "PSSM_DEBUG_RENDER" ) );
          shadowMacros.push_back( GFXShaderMacro( "PSSM_DEBUG_RENDER" ) );
 
 
+      if( smDiffuseLightViz )
+         shadowMacros.push_back(GFXShaderMacro("DIFFUSE_LIGHT_VIZ"));
+      else if (smSpecularLightViz)
+         shadowMacros.push_back(GFXShaderMacro("SPECULAR_LIGHT_VIZ"));
+      else if (smDetailLightingViz)
+         shadowMacros.push_back(GFXShaderMacro("DETAIL_LIGHTING_VIZ"));
+
       // Now create the material info object.
       // Now create the material info object.
       info = new LightMaterialInfo( lightMatName, smLightMatVertex[ lightType ], shadowMacros );
       info = new LightMaterialInfo( lightMatName, smLightMatVertex[ lightType ], shadowMacros );
    }
    }

+ 5 - 0
Engine/source/lighting/advanced/advancedLightBinManager.h

@@ -103,6 +103,11 @@ public:
    /// light to compile in the SSAO mask.
    /// light to compile in the SSAO mask.
    static bool smUseSSAOMask;
    static bool smUseSSAOMask;
 
 
+   //Used to toggle the visualization of diffuse and specular light contribution
+   static bool smDiffuseLightViz;
+   static bool smSpecularLightViz;
+   static bool smDetailLightingViz;
+
    // Used for console init
    // Used for console init
    AdvancedLightBinManager( AdvancedLightManager *lm = NULL, 
    AdvancedLightBinManager( AdvancedLightManager *lm = NULL, 
                             ShadowMapManager *sm = NULL,
                             ShadowMapManager *sm = NULL,

+ 53 - 0
Engine/source/scene/sceneContainer.cpp

@@ -1654,4 +1654,57 @@ DefineEngineFunction( containerRayCast, const char*,
    return(returnBuffer);
    return(returnBuffer);
 }
 }
 
 
+DefineEngineFunction(materialRayCast, const char*,
+(Point3F start, Point3F end, U32 mask, SceneObject* pExempt, bool useClientContainer), (nullAsType<SceneObject*>(), false),
+"@brief Cast a ray from start to end, checking for collision against items matching mask.\n\n"
+
+"If pExempt is specified, then it is temporarily excluded from collision checks (For "
+"instance, you might want to exclude the player if said player was firing a weapon.)\n"
+
+"@param start An XYZ vector containing the tail position of the ray.\n"
+"@param end An XYZ vector containing the head position of the ray\n"
+"@param mask A bitmask corresponding to the type of objects to check for\n"
+"@param pExempt An optional ID for a single object that ignored for this raycast\n"
+"@param useClientContainer Optionally indicates the search should be within the "
+"client container.\n"
+
+"@returns A string containing either null, if nothing was struck, or these fields:\n"
+"<ul><li>The ID of the object that was struck.</li>"
+"<li>The x, y, z position that it was struck.</li>"
+"<li>The x, y, z of the normal of the face that was struck.</li>"
+"<li>The distance between the start point and the position we hit.</li></ul>"
+
+"@ingroup Game")
+{
+   if (pExempt)
+      pExempt->disableCollision();
+
+   SceneContainer* pContainer = useClientContainer ? &gClientContainer : &gServerContainer;
+
+   RayInfo rinfo;
+   S32 ret = 0;
+   if (pContainer->castRayRendered(start, end, mask, &rinfo) == true)
+      ret = rinfo.object->getId();
+
+   if (pExempt)
+      pExempt->enableCollision();
+
+   // add the hit position and normal?
+   static const U32 bufSize = 512;
+   char* returnBuffer = Con::getReturnBuffer(bufSize);
+   if (ret)
+   {
+      dSprintf(returnBuffer, bufSize, "%d %g %g %g %g %g %g %g %g %g %s",
+         ret, rinfo.point.x, rinfo.point.y, rinfo.point.z,
+         rinfo.normal.x, rinfo.normal.y, rinfo.normal.z, rinfo.distance, rinfo.texCoord.x, rinfo.texCoord.y, rinfo.material ? rinfo.material->getMaterial()->getName() : "");
+   }
+   else
+   {
+      returnBuffer[0] = '0';
+      returnBuffer[1] = '\0';
+   }
+
+   return(returnBuffer);
+}
+
 ConsoleFunctionGroupEnd( Containers );
 ConsoleFunctionGroupEnd( Containers );

+ 20 - 1
Engine/source/scene/sceneObject.cpp

@@ -154,6 +154,10 @@ SceneObject::SceneObject()
    mAccuTex = NULL;
    mAccuTex = NULL;
    mSelectionFlags = 0;
    mSelectionFlags = 0;
    mPathfindingIgnore = false;
    mPathfindingIgnore = false;
+
+   mGameObjectAssetId = StringTable->insert("");
+
+   mDirtyGameObject = false;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -611,6 +615,13 @@ void SceneObject::setHidden( bool hidden )
 
 
 void SceneObject::initPersistFields()
 void SceneObject::initPersistFields()
 {
 {
+   addGroup("GameObject");
+   addField("GameObject", TypeGameObjectAssetPtr, Offset(mGameObjectAsset, SceneObject), "The asset Id used for the game object this entity is based on.");
+
+   addField("dirtyGameObject", TypeBool, Offset(mDirtyGameObject, SceneObject), "If this entity is a GameObject, it flags if this instance delinates from the template.",
+      AbstractClassRep::FieldFlags::FIELD_HideInInspectors);
+   endGroup("GameObject");
+
    addGroup( "Transform" );
    addGroup( "Transform" );
 
 
       addProtectedField( "position", TypeMatrixPosition, Offset( mObjToWorld, SceneObject ),
       addProtectedField( "position", TypeMatrixPosition, Offset( mObjToWorld, SceneObject ),
@@ -654,6 +665,14 @@ void SceneObject::initPersistFields()
    Parent::initPersistFields();
    Parent::initPersistFields();
 }
 }
 
 
+bool SceneObject::_setGameObject(void* object, const char* index, const char* data)
+{
+   // Sanity!
+   AssertFatal(data != NULL, "Cannot use a NULL asset Id.");
+
+   return true; //rbI->setMeshAsset(data);
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 bool SceneObject::_setFieldPosition( void *object, const char *index, const char *data )
 bool SceneObject::_setFieldPosition( void *object, const char *index, const char *data )
@@ -1532,4 +1551,4 @@ DefineEngineMethod(SceneObject, setForwardVector, void, (VectorF newForward, Vec
    "@param (Optional) The up vector to use to help orient the rotation.")
    "@param (Optional) The up vector to use to help orient the rotation.")
 {
 {
    object->setForwardVector(newForward, upVector);
    object->setForwardVector(newForward, upVector);
-}
+}

+ 15 - 0
Engine/source/scene/sceneObject.h

@@ -67,6 +67,13 @@
 #include "ts/collada/colladaUtils.h"
 #include "ts/collada/colladaUtils.h"
 #endif
 #endif
 
 
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif 
+#ifndef GAME_OBJECT_ASSET_H
+#include "T3D/assets/GameObjectAsset.h"
+#endif
+
 class SceneManager;
 class SceneManager;
 class SceneRenderState;
 class SceneRenderState;
 class SceneTraversalState;
 class SceneTraversalState;
@@ -204,6 +211,12 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
       ///
       ///
       SimPersistID* mMountPID;
       SimPersistID* mMountPID;
 
 
+      StringTableEntry		      mGameObjectAssetId;
+      AssetPtr<GameObjectAsset>  mGameObjectAsset;
+
+      //Marked if this entity is a GameObject and deliniates from the parent GO asset
+      bool mDirtyGameObject;
+
       /// @}
       /// @}
 
 
       /// @name Zoning
       /// @name Zoning
@@ -778,6 +791,8 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
 
 
       static void initPersistFields();
       static void initPersistFields();
 
 
+      static bool _setGameObject(void* object, const char* index, const char* data);
+
       DECLARE_CONOBJECT( SceneObject );
       DECLARE_CONOBJECT( SceneObject );
 
 
    private:
    private:

+ 32 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl

@@ -189,6 +189,38 @@ float3 BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
 	return diffuse;
 	return diffuse;
 }
 }
 
 
+float3 BRDF_GetDebugSpecular(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+   float3 neutralColor = float3(0.5,0.5,0.5);
+
+   float3 f0 = lerp(0.04.xxx, neutralColor, surface.metalness);
+	float f90 = saturate(50.0 * dot(f0, 0.33));
+	float3 F = F_Schlick(f0, f90, surfaceToLight.HdotV);
+	float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.roughness_brdf);
+	float D = D_GGX(surfaceToLight.NdotH, surface.roughness_brdf);
+	float3 Fr = D * F * Vis / M_PI_F;
+	return Fr;
+}
+
+float3 BRDF_GetDebugDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
+{
+   float3 neutralColor = float3(0.5,0.5,0.5);
+
+   //getting some banding with disney method, using lambert instead - todo futher testing
+	float Fd = 1.0 / M_PI_F;
+
+   float3 f0 = lerp(0.04.xxx, neutralColor, surface.metalness);
+
+   float f90 = saturate(50.0 * dot(f0, 0.33));
+   float3 F = F_Schlick(f0, f90, surface.NdotV);
+
+   //energy conservation - remove this if reverting back to disney method
+   float3 kD = 1.0.xxx - F;
+	kD *= 1.0 - surface.metalness;
+   float3 diffuse = kD * neutralColor * Fd;
+	return diffuse;
+}
+
 //attenuations functions from "moving frostbite to pbr paper"
 //attenuations functions from "moving frostbite to pbr paper"
 //https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
 //https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
 float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )
 float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )

+ 25 - 0
Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/vectorLightP.hlsl

@@ -230,6 +230,31 @@ float4 main(FarFrustumQuadConnectP IN) : SV_TARGET
 
 
    #endif //NO_SHADOW
    #endif //NO_SHADOW
    
    
+   #ifdef DIFFUSE_LIGHT_VIZ
+      float3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
+      float3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
+
+      float3 final = max(0.0f, diffuse);
+      return float4(final, 0);
+   #endif
+
+   #ifdef SPECULAR_LIGHT_VIZ
+      float3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
+      float3 spec = BRDF_GetDebugSpecular(surface, surfaceToLight) * factor;
+
+      float3 final = max(0.0f, factor);
+      return float4(final, 0);
+   #endif
+
+   #ifdef DETAIL_LIGHTING_VIZ
+      float3 factor = lightingColor.rgb * max(surfaceToLight.NdotL, 0) * shadow * lightBrightness;
+      float3 diffuse = BRDF_GetDebugDiffuse(surface,surfaceToLight) * factor;
+      float3 spec = BRDF_GetDebugSpecular(surface,surfaceToLight) * factor;
+
+      float3 final = max(0.0f, diffuse + spec);
+      return float4(final,0);
+   #endif
+
    //get directional light contribution   
    //get directional light contribution   
    float3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
    float3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
 
 

+ 0 - 1
Templates/BaseGame/game/tools/assetBrowser/guis/GameObjectCreator.gui

@@ -59,7 +59,6 @@
          profile = "ToolsGuiButtonProfile";
          profile = "ToolsGuiButtonProfile";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
-         command = "AssetBrowser_importAssetWindow.ImportAssets();";
          tooltipProfile = "ToolsGuiToolTipProfile";
          tooltipProfile = "ToolsGuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";

+ 28 - 0
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/gameObject.cs

@@ -123,6 +123,34 @@ function AssetBrowser::dragAndDropGameObjectAsset(%this, %assetDef, %dropTarget)
    }
    }
 }
 }
 
 
+function AssetBrowser::onGameObjectAssetEditorDropped(%this, %assetDef, %position)
+{
+   //echo("DROPPED A SHAPE ON THE EDITOR WINDOW!"); 
+
+   %targetPosition = EWorldEditor.unproject(%position SPC 1000);
+   %camPos = LocalClientConnection.camera.getPosition();
+   %rayResult = containerRayCast(%camPos, %targetPosition, -1);
+   
+   %pos = EWCreatorWindow.getCreateObjectPosition();
+
+   if(%rayResult != 0)
+   {
+      %pos = getWords(%rayResult, 1, 3);
+   }
+   
+   %gameObject = %assetDef.createObject(); 
+         
+   getScene(0).add(%gameObject);
+
+   %gameObject.position = %pos;
+   
+   EWorldEditor.clearSelection();
+   EWorldEditor.selectObject(%gameObject); 
+      
+   EWorldEditor.isDirty = true;
+   
+}
+
 function AssetBrowser::renameGameObjectAsset(%this, %assetDef, %newAssetId, %originalName, %newName)
 function AssetBrowser::renameGameObjectAsset(%this, %assetDef, %newAssetId, %originalName, %newName)
 {
 {
    %oldScriptFilePath = %assetDef.scriptFile;
    %oldScriptFilePath = %assetDef.scriptFile;

+ 26 - 0
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/material.cs

@@ -452,6 +452,32 @@ function AssetBrowser::buildMaterialAssetPreview(%this, %assetDef, %previewData)
    %previewData.tooltip = %assetDef.friendlyName @ "\n" @ %assetDef;
    %previewData.tooltip = %assetDef.friendlyName @ "\n" @ %assetDef;
 }
 }
 
 
+function AssetBrowser::onMaterialAssetEditorDropped(%this, %assetDef, %position)
+{
+   //echo("DROPPED A SHAPE ON THE EDITOR WINDOW!"); 
+   //first, see if we hit a static shape
+   %mask = $TypeMasks::StaticObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::TerrainObjectType;
+   
+   %targetPosition = EWorldEditor.unproject(%position SPC 1000);
+   %camPos = LocalClientConnection.camera.getPosition();
+   %rayResult = materialRayCast(%camPos, %targetPosition, -1, 0, false);
+   
+   %validTarget = false;
+   if(%rayResult != 0)
+   {
+      %obj = getWord(%rayResult, 0);
+      if(%obj.isMemberOfClass("TSStatic"))
+      {
+         //oh, cool a valid target! 
+         %obj.materialSlot0 = %assetDef.getAssetId();
+         echo("MaterialSlot0 set to " @ %assetDef.getAssetId());
+      }
+   }
+
+   EWorldEditor.isDirty = true;
+   
+}
+
 function GuiInspectorTypeMaterialAssetPtr::onControlDropped( %this, %payload, %position )
 function GuiInspectorTypeMaterialAssetPtr::onControlDropped( %this, %payload, %position )
 {
 {
    Canvas.popDialog(EditorDragAndDropLayer);
    Canvas.popDialog(EditorDragAndDropLayer);

+ 16 - 6
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/shape.cs

@@ -307,7 +307,7 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData)
    %previewData.assetName = %assetDef.assetName;
    %previewData.assetName = %assetDef.assetName;
    %previewData.assetPath = %assetDef.fileName;
    %previewData.assetPath = %assetDef.fileName;
 
 
-   %previewData.previewImage = fileName;
+   %previewData.previewImage = %assetDef.fileName;
    
    
    %previewData.assetFriendlyName = %assetDef.assetName;
    %previewData.assetFriendlyName = %assetDef.assetName;
    %previewData.assetDesc = %assetDef.description;
    %previewData.assetDesc = %assetDef.description;
@@ -317,11 +317,20 @@ function AssetBrowser::buildShapeAssetPreview(%this, %assetDef, %previewData)
 function AssetBrowser::onShapeAssetEditorDropped(%this, %assetDef, %position)
 function AssetBrowser::onShapeAssetEditorDropped(%this, %assetDef, %position)
 {
 {
    //echo("DROPPED A SHAPE ON THE EDITOR WINDOW!"); 
    //echo("DROPPED A SHAPE ON THE EDITOR WINDOW!"); 
-      
-   %assetId = %assetDef.getAssetId();
-      
+
+   %targetPosition = EWorldEditor.unproject(%position SPC 1000);
+   %camPos = LocalClientConnection.camera.getPosition();
+   %rayResult = containerRayCast(%camPos, %targetPosition, -1);
+   
    %pos = EWCreatorWindow.getCreateObjectPosition();
    %pos = EWCreatorWindow.getCreateObjectPosition();
-      
+
+   if(%rayResult != 0)
+   {
+      %pos = getWords(%rayResult, 1, 3);
+   }
+   
+   %assetId = %assetDef.getAssetId();
+   
    %newStatic = new TSStatic()
    %newStatic = new TSStatic()
    {
    {
       position = %pos;
       position = %pos;
@@ -332,8 +341,9 @@ function AssetBrowser::onShapeAssetEditorDropped(%this, %assetDef, %position)
    
    
    EWorldEditor.clearSelection();
    EWorldEditor.clearSelection();
    EWorldEditor.selectObject(%newStatic);
    EWorldEditor.selectObject(%newStatic);
-   
+      
    EWorldEditor.isDirty = true;
    EWorldEditor.isDirty = true;
+   
 }
 }
 
 
 function GuiInspectorTypeShapeAssetPtr::onControlDropped( %this, %payload, %position )
 function GuiInspectorTypeShapeAssetPtr::onControlDropped( %this, %payload, %position )

+ 1 - 1
Templates/BaseGame/game/tools/worldEditor/gui/WorldEditorInspectorWindow.ed.gui

@@ -126,7 +126,7 @@
          Profile = "GuiInspectorFieldInfoMLTextProfile";
          Profile = "GuiInspectorFieldInfoMLTextProfile";
          HorizSizing = "width";
          HorizSizing = "width";
          VertSizing = "top";
          VertSizing = "top";
-         Position = "6 205";
+         Position = 5 SPC EWInspectorWindow.extent.y - 40;
          Extent = "197 35";
          Extent = "197 35";
          MinExtent = "8 2";
          MinExtent = "8 2";
          canSave = "1";
          canSave = "1";

+ 4 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs

@@ -63,6 +63,7 @@ function EditorGui::init(%this)
          {
          {
             EWTreeWindow.position = %this.extent.x - EWTreeWindow.Extent.x SPC EditorGuiToolbar.extent.y;
             EWTreeWindow.position = %this.extent.x - EWTreeWindow.Extent.x SPC EditorGuiToolbar.extent.y;
             EWTreeWindow.extent = EWTreeWindow.extent.x SPC %this.extent.y - EditorGuiToolbar.extent.y - EditorGuiStatusBar.extent.y - 25;
             EWTreeWindow.extent = EWTreeWindow.extent.x SPC %this.extent.y - EditorGuiToolbar.extent.y - EditorGuiStatusBar.extent.y - 25;
+            FieldInfoControl.position = 5 SPC EWInspectorWindow.extent.y - 40;
          }
          }
       }
       }
    }
    }
@@ -81,6 +82,7 @@ function EditorGui::init(%this)
          {
          {
             EWInspectorWindow.position = EWTreeWindow.position.x SPC EWTreeWindow.extent.y;
             EWInspectorWindow.position = EWTreeWindow.position.x SPC EWTreeWindow.extent.y;
             EWInspectorWindow.extent = EWTreeWindow.extent.x SPC EWTreeWindow.extent.y;
             EWInspectorWindow.extent = EWTreeWindow.extent.x SPC EWTreeWindow.extent.y;
+            FieldInfoControl.position = 5 SPC EWInspectorWindow.extent.y - 40;
          }
          }
       }
       }
    }   
    }   
@@ -1455,6 +1457,8 @@ function EWorldEditor::onResize(%this, %newPosition, %newExtent)
       
       
       EWInspectorWindow.resize(%inspPos.x, %inspPos.y, %inspExt.x, %inspExt.y);
       EWInspectorWindow.resize(%inspPos.x, %inspPos.y, %inspExt.x, %inspExt.y);
    }
    }
+   
+   FieldInfoControl.position = 5 SPC EWInspectorWindow.extent.y - 40;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 46 - 1
Templates/BaseGame/game/tools/worldEditor/scripts/visibility/lightViz.cs

@@ -379,7 +379,7 @@ function setLightingMode(%mode)
          $Shadows::disable = true;
          $Shadows::disable = true;
          EVisibilityLightingModesOptions.checkItem(2, true);
          EVisibilityLightingModesOptions.checkItem(2, true);
       case "DetailLighting":
       case "DetailLighting":
-         //$Viz_ColorblindnessModeVar = "0";
+         $AL::DetailLightingViz = true;
          EVisibilityLightingModesOptions.checkItem(3, true);
          EVisibilityLightingModesOptions.checkItem(3, true);
       case "LightingOnly":
       case "LightingOnly":
          $Light::renderReflectionProbes = false;
          $Light::renderReflectionProbes = false;
@@ -388,6 +388,8 @@ function setLightingMode(%mode)
          $Light::disableLights = true;
          $Light::disableLights = true;
          EVisibilityLightingModesOptions.checkItem(5, true);
          EVisibilityLightingModesOptions.checkItem(5, true);
    }
    }
+   
+   reInitMaterials();
 }
 }
 
 
 function resetLightingMode()
 function resetLightingMode()
@@ -400,6 +402,7 @@ function resetLightingMode()
    $Light::renderReflectionProbes = true;
    $Light::renderReflectionProbes = true;
    $Light::disableLights = false;
    $Light::disableLights = false;
    $Shadows::disable = false;
    $Shadows::disable = false;
+   $AL::DetailLightingViz = false;
    EVisibilityLightingModesOptions.checkItem(0, true);
    EVisibilityLightingModesOptions.checkItem(0, true);
 }
 }
 
 
@@ -427,6 +430,48 @@ function disableLightFrustumViz()
    $Light::renderLightFrustums = false;
    $Light::renderLightFrustums = false;
 }
 }
 
 
+function toggleLightViz(%mode)
+{
+   setLightingMode("Lit");
+   
+   if($AL::DiffuseLightViz == 1)
+      %lastMode = "Diffuse";
+   else if($AL::SpecularLightViz == 1)
+      %lastMode = "Specular";
+   
+   $AL::DiffuseLightViz = 0;
+   $AL::SpecularLightViz = 0;
+   
+   EVisibilityLightsOptions.checkItem(2, false);
+   EVisibilityLightsOptions.checkItem(3, false);
+   
+   if(%mode $= %lastMode)
+   {
+      //forces the forward materials to get dis viz properly
+      reInitMaterials();
+   
+      return;
+   }
+         
+   switch$(%mode)
+   {
+      case "Diffuse":
+         $AL::DiffuseLightViz = 1;
+         EVisibilityLightsOptions.checkItem(2, true);
+      case "Specular":
+         $AL::SpecularLightViz = 1;
+         EVisibilityLightsOptions.checkItem(3, true);
+   }
+   
+   //forces the forward materials to get dis viz properly
+   reInitMaterials();
+}
+
+function disableLightViz()
+{
+   toggleLightViz(-1);
+}
+
 //Lighting Viz
 //Lighting Viz
 singleton Material( Viz_DetailLightingMat )
 singleton Material( Viz_DetailLightingMat )
 {
 {

+ 1 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/visibility/probeViz.cs

@@ -31,6 +31,7 @@ function toggleProbeViz(%mode)
    else
    else
    {
    {
       setLightingMode("ReflectionsOnly");  
       setLightingMode("ReflectionsOnly");  
+      toggleLightViz(-1);
    }
    }
          
          
    switch$(%mode)
    switch$(%mode)

+ 2 - 5
Templates/BaseGame/game/tools/worldEditor/scripts/visibility/visibilityLayer.ed.cs

@@ -132,13 +132,10 @@ function setupEditorVisibilityMenu()
       
       
       item[ 0 ] = "Show Light Frustums" TAB "" TAB "toggleLightFrustumViz();";
       item[ 0 ] = "Show Light Frustums" TAB "" TAB "toggleLightFrustumViz();";
       item[ 1 ] = "Show Shadowmap Cascades" TAB "" TAB "togglePSSMDebugViz();";
       item[ 1 ] = "Show Shadowmap Cascades" TAB "" TAB "togglePSSMDebugViz();";
-      item[ 2 ] = "Show Specular Light" TAB "" TAB "";
-      item[ 3 ] = "Show Diffuse Light" TAB "" TAB "";
+      item[ 2 ] = "Show Diffuse Light" TAB "" TAB "toggleLightViz(\"Diffuse\");";
+      item[ 3 ] = "Show Specular Light" TAB "" TAB "toggleLightViz(\"Specular\");";
    };
    };
    
    
-   %lightspopup.enableItem(2, false);
-   %lightspopup.enableItem(3, false);
-   
    //
    //
    //Probes
    //Probes
    %probespopup = new PopupMenu(EVisibilityProbesOptions)
    %probespopup = new PopupMenu(EVisibilityProbesOptions)

+ 7 - 0
Tools/CMake/torque3d.cmake

@@ -135,6 +135,13 @@ mark_as_advanced(TORQUE_HIFI)
 option(TORQUE_EXTENDED_MOVE "Extended move support" OFF)
 option(TORQUE_EXTENDED_MOVE "Extended move support" OFF)
 mark_as_advanced(TORQUE_EXTENDED_MOVE)
 mark_as_advanced(TORQUE_EXTENDED_MOVE)
 
 
+option(TORQUE_ALLOW_DIRECT_FILENAMES "Allows gameclasses to use direct filenames instead of assets" OFF)
+mark_as_advanced(TORQUE_ALLOW_DIRECT_FILENAMES)
+
+if(TORQUE_ALLOW_DIRECT_FILENAMES)
+    addDef(TORQUE_ALLOW_DIRECT_FILENAMES)
+endif()
+
 set(TORQUE_SDL ON) # we need sdl to do our platform interop
 set(TORQUE_SDL ON) # we need sdl to do our platform interop
 
 
 if(WIN32)
 if(WIN32)