Browse Source

Merge pull request #1541 from Areloch/MiscFixes_20250825

Misc small fixes, improvements and QoL tweaks
Brian Roberts 2 weeks ago
parent
commit
e73efc13c4
37 changed files with 727 additions and 345 deletions
  1. 31 13
      Engine/source/T3D/assets/MaterialAsset.cpp
  2. 1 1
      Engine/source/T3D/assets/ShapeAsset.h
  3. 7 9
      Engine/source/T3D/tsStatic.cpp
  4. 4 1
      Engine/source/assets/assetBase.h
  5. 1 0
      Engine/source/assets/assetPtr.h
  6. 2 1
      Engine/source/console/consoleObject.h
  7. 1 1
      Engine/source/console/persistenceManager.cpp
  8. 1 1
      Engine/source/console/simObject.cpp
  9. 0 1
      Engine/source/gui/buttons/guiIconButtonCtrl.cpp
  10. 2 2
      Engine/source/gui/editor/guiInspector.cpp
  11. 5 10
      Templates/BaseGame/game/data/Prototyping/Prototyping.tscript
  12. 1 56
      Templates/BaseGame/game/data/Prototyping/scripts/managedData/managedDatablocks.tscript
  13. 16 40
      Templates/BaseGame/game/tools/assetBrowser/guis/assetBrowser.gui
  14. 15 5
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript
  15. 78 6
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/datablockObjects.tscript
  16. 72 2
      Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/prefab.tscript
  17. 6 6
      Templates/BaseGame/game/tools/datablockEditor/DatablockEditorCreatePrompt.ed.gui
  18. 8 4
      Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript
  19. 22 5
      Templates/BaseGame/game/tools/decalEditor/decalEditorGui.tscript
  20. 2 2
      Templates/BaseGame/game/tools/gui/compositeTextureEditor.tscript
  21. 46 0
      Templates/BaseGame/game/tools/gui/fieldTypes/toggleControlButton.tscript
  22. 1 0
      Templates/BaseGame/game/tools/gui/guiDialogs.ed.tscript
  23. 2 2
      Templates/BaseGame/game/tools/gui/saveChangesMBDlg.ed.gui
  24. 7 6
      Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui
  25. 2 2
      Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorToolbox.ed.tscript
  26. 1 0
      Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript
  27. 56 3
      Templates/BaseGame/game/tools/navEditor/NavEditorGui.gui
  28. 20 0
      Templates/BaseGame/game/tools/navEditor/navEditor.tscript
  29. 3 3
      Templates/BaseGame/game/tools/shapeEditor/main.tscript
  30. 1 1
      Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditor.ed.tscript
  31. 2 23
      Templates/BaseGame/game/tools/worldEditor/gui/EditorGui.ed.gui
  32. 1 1
      Templates/BaseGame/game/tools/worldEditor/gui/TerrainBrushSoftnessCurveDlg.ed.gui
  33. 222 111
      Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui
  34. 28 2
      Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript
  35. 5 5
      Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript
  36. 9 0
      Templates/BaseGame/game/tools/worldEditor/scripts/editors/worldEditor.ed.tscript
  37. 46 20
      Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript

+ 31 - 13
Engine/source/T3D/assets/MaterialAsset.cpp

@@ -599,20 +599,42 @@ void GuiInspectorTypeMaterialAssetPtr::updateValue()
 
 void GuiInspectorTypeMaterialAssetPtr::updatePreviewImage()
 {
-   const char* previewImage;
+   const char* matAssetId;
    if (mInspector->getInspectObject() != nullptr)
-      previewImage = mInspector->getInspectObject()->getDataField(mCaption, NULL);
+      matAssetId = mInspector->getInspectObject()->getDataField(mCaption, NULL);
    else
-      previewImage = Con::getVariable(mVariableName);
+      matAssetId = Con::getVariable(mVariableName);
 
    //if what we're working with isn't even a valid asset, don't present like we found a good one
-   if (!AssetDatabase.isDeclaredAsset(previewImage))
+   if (!AssetDatabase.isDeclaredAsset(matAssetId))
    {
-      mPreviewImage->_setBitmap(StringTable->EmptyString());
+      mPreviewImage->_setBitmap(StringTable->insert("Core_Rendering:NoMaterial"));
       return;
    }
 
-   String matPreviewAssetId = String(previewImage) + "_PreviewImage";
+   AssetPtr<MaterialAsset> matAssetDef = matAssetId;
+   if (matAssetDef.isNull() || matAssetDef->getStatus() != AssetBase::AssetErrCode::Ok ||
+      matAssetDef->getMaterialDefinitionName() == StringTable->EmptyString())
+   {
+      mPreviewImage->_setBitmap(StringTable->insert("Core_Rendering:WarningMaterial"));
+      return;
+   }
+
+   Material* matDef;
+   if (!Sim::findObject(matAssetDef->getMaterialDefinitionName(), matDef))
+   {
+      mPreviewImage->_setBitmap(StringTable->insert("Core_Rendering:WarningMaterial"));
+      return;
+   }
+
+   AssetPtr<ImageAsset> difMapAsset = matDef->getDiffuseMapAsset(0);
+   if (difMapAsset.isNull() || difMapAsset->getStatus() != AssetBase::AssetErrCode::Ok)
+   {
+      mPreviewImage->_setBitmap(StringTable->insert("Core_Rendering:WarningMaterial"));
+      return;
+   }
+
+   String matPreviewAssetId = String(difMapAsset->getAssetName()) + "_PreviewImage";
    matPreviewAssetId.replace(":", "_");
    matPreviewAssetId = "ToolsModule:" + matPreviewAssetId;
    if (AssetDatabase.isDeclaredAsset(matPreviewAssetId.c_str()))
@@ -621,18 +643,14 @@ void GuiInspectorTypeMaterialAssetPtr::updatePreviewImage()
    }
    else
    {
-      if (AssetDatabase.isDeclaredAsset(previewImage))
+      if (AssetDatabase.isDeclaredAsset(difMapAsset->getAssetId()))
       {
-         MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(previewImage);
-         if (matAsset && matAsset->getMaterialDefinition())
-         {
-            mPreviewImage->_setBitmap(matAsset->getMaterialDefinition()->_getDiffuseMap(0));
-         }
+         mPreviewImage->setBitmap(difMapAsset->getAssetId());
       }
    }
 
    if (mPreviewImage->getBitmapAsset().isNull())
-      mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
+      mPreviewImage->setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image"));
 }
 
 void GuiInspectorTypeMaterialAssetPtr::setPreviewImage(StringTableEntry assetId)

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

@@ -360,7 +360,7 @@ public:
 
 #define INITPERSISTFIELD_SHAPEASSET_REFACTOR(name, consoleClass, docs)                                                                                                        \
    addProtectedField(assetText(name, Asset), TypeShapeAssetPtr, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.)); \
-   addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, file docs.));
+   addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, file docs.), AbstractClassRep::FIELD_HideInInspectors);
 
 
 #define DECLARE_SHAPEASSET_ARRAY_REFACTOR(className, name, max)                                                                                                               \

+ 7 - 9
Engine/source/T3D/tsStatic.cpp

@@ -400,7 +400,7 @@ bool TSStatic::_createShape()
       mObjBox = getShape()->mBounds;
       resetWorldBox();
 
-      mShapeInstance = new TSShapeInstance(getShape(), isClientObject());
+      mShapeInstance = new TSShapeInstance(getShape(), true);
       mShapeInstance->resetMaterialList();
       mShapeInstance->cloneMaterialList();
 
@@ -711,7 +711,7 @@ void TSStatic::_updateShouldTick()
 
 void TSStatic::prepRenderImage(SceneRenderState* state)
 {
-   if (!mShapeInstance)
+   if (!mShapeAsset.isValid() || !mShapeInstance)
       return;
 
    Point3F cameraOffset;
@@ -1326,27 +1326,25 @@ bool TSStatic::buildExportPolyList(ColladaUtils::ExportData* exportData, const B
    }
 
    //Next, process the LOD levels and materials.
-   if (isServerObject() && getClientObject())
+   if (isServerObject())
    {
-      TSStatic* clientShape = dynamic_cast<TSStatic*>(getClientObject());
-
       exportData->meshData.increment();
 
       //Prep a meshData for this shape in particular
       ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
 
       //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
-      meshData->shapeInst = clientShape->mShapeInstance;
+      meshData->shapeInst = mShapeInstance;
       meshData->originatingObject = this;
       meshData->meshTransform = mObjToWorld;
       meshData->scale = mObjScale;
 
       //Iterate over all our detail levels
-      for (U32 i = 0; i < clientShape->mShapeInstance->getNumDetails(); i++)
+      for (U32 i = 0; i < mShapeInstance->getNumDetails(); i++)
       {
-         TSShape::Detail detail = clientShape->mShapeInstance->getShape()->details[i];
+         TSShape::Detail detail = mShapeInstance->getShape()->details[i];
 
-         String detailName = String::ToLower(clientShape->mShapeInstance->getShape()->getName(detail.nameIndex));
+         String detailName = String::ToLower(mShapeInstance->getShape()->getName(detail.nameIndex));
 
          //Skip it if it's a collision or line of sight element
          if (detailName.startsWith("col") || detailName.startsWith("los"))

+ 4 - 1
Engine/source/assets/assetBase.h

@@ -123,7 +123,10 @@ public:
    StringTableEntry        expandAssetFilePath(const char* pAssetFilePath) const;
    StringTableEntry        collapseAssetFilePath(const char* pAssetFilePath) const;
 
-   virtual bool            isAssetValid(void) const                          { return true; }
+   virtual bool            isAssetValid(void) const
+   {
+      return mpOwningAssetManager != nullptr && mAssetInitialized && (mLoadedState == AssetErrCode::Ok || mLoadedState == AssetErrCode::UsingFallback);
+   }
 
    void                    refreshAsset(void);
 

+ 1 - 0
Engine/source/assets/assetPtr.h

@@ -179,6 +179,7 @@ public:
     /// Validity.
     bool isNull( void ) const override { return mpAsset.isNull(); }
     bool notNull( void ) const override { return !mpAsset.isNull(); }
+    bool isValid(void) const { return notNull() && static_cast<AssetBase*>(mpAsset.getObject())->isAssetValid(); }
 };
 
 #endif // _ASSET_PTR_H_

+ 2 - 1
Engine/source/console/consoleObject.h

@@ -498,7 +498,8 @@ public:
       FIELD_ComponentInspectors = BIT(1),       ///< Custom fields used by components. They are likely to be non-standard size/configuration, so 
                                                 ///< They are handled specially
       FIELD_CustomInspectors = BIT(2),          ///< Display as a button in inspectors.
-      FIELD_SpecialtyArrayField = BIT(3)
+      FIELD_SpecialtyArrayField = BIT(3),
+      FIELD_DontWriteToFile = BIT(4),
    };
 
    struct Field

+ 1 - 1
Engine/source/console/persistenceManager.cpp

@@ -1383,7 +1383,7 @@ void PersistenceManager::updateObject(SimObject* object, ParsedObject* parentObj
       const AbstractClassRep::Field* f = &list[i];
 
       // Skip the special field types.
-      if ( f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors))
+      if ( f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors) || f->flag.test(AbstractClassRep::FieldFlags::FIELD_DontWriteToFile))
          continue;
 
       if (f->flag.test(AbstractClassRep::FIELD_SpecialtyArrayField))

+ 1 - 1
Engine/source/console/simObject.cpp

@@ -372,7 +372,7 @@ void SimObject::writeFields(Stream &stream, U32 tabStop)
       const AbstractClassRep::Field* f = &list[i];
 
       // Skip the special field types.
-      if ( f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors))
+      if ( f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors) || f->flag.test(AbstractClassRep::FieldFlags::FIELD_DontWriteToFile))
          continue;
 
       for(U32 j = 0; S32(j) < f->elementCount; j++)

+ 0 - 1
Engine/source/gui/buttons/guiIconButtonCtrl.cpp

@@ -126,7 +126,6 @@ void GuiIconButtonCtrl::initPersistFields()
    docsURL;
    addField( "buttonMargin",     TypePoint2I,   Offset( mButtonMargin, GuiIconButtonCtrl ),"Margin area around the button.\n");
 
-   addProtectedField( "iconBitmap", TypeImageFilename,  Offset( mBitmapAsset, GuiIconButtonCtrl ), &_setBitmapData, &defaultProtectedGetFn, "Bitmap file for the icon to display on the button.\n", AbstractClassRep::FIELD_HideInInspectors);
    INITPERSISTFIELD_IMAGEASSET(Bitmap, GuiIconButtonCtrl, "Bitmap file for the icon to display on the button.\n");
 
    addField( "iconLocation",     TYPEID< IconLocation >(), Offset( mIconLocation, GuiIconButtonCtrl ),"Where to place the icon on the control. Options are 0 (None), 1 (Left), 2 (Right), 3 (Center).\n");

+ 2 - 2
Engine/source/gui/editor/guiInspector.cpp

@@ -501,7 +501,7 @@ bool GuiInspector::isGroupFiltered( const char *groupName ) const
 
    // Is this group explicitly show? Does it immediately follow a + char.
    searchStr = String::ToString( "+%s", groupName );
-   if ( mGroupFilters.find( searchStr ) != String::NPos )
+   if ( mGroupFilters.find( searchStr, 0, String::NoCase | String::Left) != String::NPos )
       return false;   
 
    // Were there any other + characters, if so, we are implicitly hidden.   
@@ -510,7 +510,7 @@ bool GuiInspector::isGroupFiltered( const char *groupName ) const
 
    // Is this group explicitly hidden? Does it immediately follow a - char.
    searchStr = String::ToString( "-%s", groupName );
-   if ( mGroupFilters.find( searchStr ) != String::NPos )
+   if ( mGroupFilters.find( searchStr, 0, String::NoCase | String::Left) != String::NPos )
       return true;   
 
    return false;

+ 5 - 10
Templates/BaseGame/game/data/Prototyping/Prototyping.tscript

@@ -17,16 +17,11 @@ function Prototyping::onCreateGameServer(%this)
     //These are common managed data files. For any datablock-based stuff that gets generated by the editors
     //(that doesn't have a specific associated file, like data for a player class) will go into these.
     //So we'll register them now if they exist.
-    if(isFile("./scripts/managedData/managedDatablocks." @ $TorqueScriptFileExtension))
-        %this.registerDatablock("./scripts/managedData/managedDatablocks");
-    if(isFile("./scripts/managedData/managedForestItemData." @ $TorqueScriptFileExtension))
-        %this.registerDatablock("./scripts/managedData/managedForestItemData");
-    if(isFile("./scripts/managedData/managedForestBrushData." @ $TorqueScriptFileExtension))
-        %this.registerDatablock("./scripts/managedData/managedForestBrushData");
-    if(isFile("./scripts/managedData/managedParticleEmitterData." @ $TorqueScriptFileExtension))
-        %this.registerDatablock("./scripts/managedData/managedParticleEmitterData");
-    if(isFile("./scripts/managedData/managedParticleData." @ $TorqueScriptFileExtension))
-        %this.registerDatablock("./scripts/managedData/managedParticleData");
+    %this.registerDatablock("./scripts/managedData/managedDatablocks");
+    %this.registerDatablock("./scripts/managedData/managedForestItemData");
+    %this.registerDatablock("./scripts/managedData/managedForestBrushData");
+    %this.registerDatablock("./scripts/managedData/managedParticleEmitterData");
+    %this.registerDatablock("./scripts/managedData/managedParticleData");
 }
 
 //This is called when the server is shut down due to the game/map being exited

+ 1 - 56
Templates/BaseGame/game/data/Prototyping/scripts/managedData/managedDatablocks.tscript

@@ -3,59 +3,4 @@ datablock ItemData(PrototypeItemData)
 {
    ShapeAsset = "Prototyping:TorusPrimitive_shape";
    cameraMaxDist = "0.75";
-};
-
-datablock PlayerData( ProtoPlayer ) {
-    // Third person shape
-   ShapeAsset = "Prototyping:Playerbot_shape";
-   controlMap = "playerKeyMap";
-   AIControllerData = "aiPlayerControl";
-};
-
-datablock WheeledVehicleTire(ProtoCarTire)
-{
-   // Tires act as springs and generate lateral and longitudinal
-   // forces to move the vehicle. These distortion/spring forces
-   // are what convert wheel angular velocity into forces that
-   // act on the rigid body.
-   shapeAsset = "Prototyping:carwheel_shape";
-   
-   staticFriction =  1;
-   kineticFriction = 4.2;
-
-   // Spring that generates lateral tire forces
-   lateralForce = 150000;
-   lateralDamping = 30000;
-   lateralRelaxation = 0.1;
-
-   // Spring that generates longitudinal tire forces
-   longitudinalForce = 600;
-   longitudinalDamping = 1600;
-   longitudinalRelaxation = 0.1;
-};
-
-datablock WheeledVehicleSpring(ProtoCarSpring)
-{
-   // Wheel suspension properties
-   length = "0.6";             // Suspension travel
-   force = 3600;              // Spring force
-   damping = 2800;             // Spring damping
-   antiSwayForce = 300;         // Lateral anti-sway force
-};
-
-datablock WheeledVehicleData(ProtoCar)
-{
-   category = "Vehicles";
-   shapeAsset = "Prototyping:car_shape";
-   
-   collisionMul = 0;
-   impactMul = 0;
-   controlMap = "vehicleKeyMap";
-   AIControllerData = "aiCarControl";
-   cameraMaxDist = "2.81993";
-   ShapeFile = "data/Prototyping/shapes/Vehicles/car.dae";
-   mass = "1000";
-   originalAssetName = "ProtoCar";
-   massCenter = "0 0.75 0";
-   dragForce = "0.1";
-};
+};

+ 16 - 40
Templates/BaseGame/game/tools/assetBrowser/guis/assetBrowser.gui

@@ -972,57 +972,33 @@ $guiContent = new GuiControl(AssetBrowser) {
                      canSave = "1";
                      canSaveDynamicFields = "0";
                   };
-                  new GuiStackControl() {
-                     stackingType = "Vertical";
-                     horizStacking = "Left to Right";
-                     vertStacking = "Top to Bottom";
-                     padding = "0";
+
+                  new GuiDynamicCtrlArrayControl() {
+                     colCount = "4";
+                     colSize = "100";
+                     rowCount = "1";
+                     rowSize = "120";
+                     rowSpacing = "2";
+                     colSpacing = "2";
+                     frozen = "0";
+                     autoCellSize = "1";
+                     fillRowFirst = "1";
                      dynamicSize = "1";
-                     dynamicNonStackExtent = "0";
-                     dynamicPos = "0";
-                     changeChildSizeToFit = "1";
-                     changeChildPosition = "0";
-                     position = "2 2";
+                     padding = "0 0 0 0";
+                     position = "3 0";
                      extent = "414 120";
-                     minExtent = "16 16";
+                     minExtent = "8 8";
                      horizSizing = "width";
                      vertSizing = "bottom";
-                     profile = "ToolsGuiModelessDialogProfile";
+                     profile = "ToolsGuiDefaultNonModalProfile";
                      visible = "1";
                      active = "1";
                      tooltipProfile = "GuiToolTipProfile";
                      hovertime = "1000";
                      isContainer = "1";
+                     internalName = "assetList";
                      canSave = "1";
                      canSaveDynamicFields = "0";
-
-                     new GuiDynamicCtrlArrayControl() {
-                        colCount = "4";
-                        colSize = "100";
-                        rowCount = "1";
-                        rowSize = "120";
-                        rowSpacing = "2";
-                        colSpacing = "2";
-                        frozen = "0";
-                        autoCellSize = "1";
-                        fillRowFirst = "1";
-                        dynamicSize = "1";
-                        padding = "0 0 0 0";
-                        position = "3 0";
-                        extent = "414 120";
-                        minExtent = "8 8";
-                        horizSizing = "width";
-                        vertSizing = "bottom";
-                        profile = "ToolsGuiDefaultNonModalProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "1";
-                        internalName = "assetList";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
                   };
                };
                new GuiContainer() {

+ 15 - 5
Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript

@@ -778,9 +778,12 @@ function AssetBrowser::buildAssetPreview( %this, %asset, %moduleName )
       AssetPreviewArray.add( %previewButton );
 }
 
-function AssetBrowser::refresh(%this)
+function AssetBrowser::refresh(%this, %regenPreviews)
 {
-   if(!%this.dirty)
+   if(%regenPreviews $= "")
+      %regenPreviews = true;
+      
+   if(!%this.dirty && %regenPreviews)
    {
       %this.dirty = true;
       
@@ -839,7 +842,7 @@ function AssetPreviewButton::onDoubleClick(%this)
 function assetBrowserPreviewSlider::onMouseDragged(%this)
 {
    EditorSettings.setValue("Assets/Browser/previewTileSize", %this.getValue());
-   AssetBrowser.refresh();  
+   AssetBrowser.refresh(false);  
 }
 
 function AssetBrowser::loadDirectories( %this )
@@ -2417,7 +2420,7 @@ function AssetBrowserPreviewButton::onMouseDragged(%this)
    Canvas.repaint();
 }
 
-function AssetBrowserPreviewButton::onControlDragCancelled(%this)
+function AssetPreviewControlType_AssetDrop::onControlDragCancelled(%this)
 {
    Canvas.popDialog(EditorDragAndDropLayer);
 }
@@ -2852,8 +2855,15 @@ function AssetBrowserWindow::releasePanel(%this)
 function AssetBrowserWindow::onResize(%this, %posX, %posY, %width, %height)
 {
     if (%width>%height)
+    {
         AssetBrowser-->assetList.fillRowFirst = true;
+        AssetBrowser-->assetList.extent.x = AssetListPanel.extent.x;
+    }
     else
+    {
         AssetBrowser-->assetList.fillRowFirst = false;
-    AssetBrowser.rebuildAssetArray();
+        AssetBrowser-->assetList.extent.y = AssetListPanel.extent.y;
+    }
+        
+    //AssetBrowser.rebuildAssetArray();
 }

+ 78 - 6
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/datablockObjects.tscript

@@ -16,7 +16,6 @@ function DatablockObjectType::onEdit(%this, %className)
 
 function DatablockObjectType::buildBrowserElement(%this, %className, %previewData)
 {
-   echo("DatablockObjectType::buildBrowserElement() - " @ %this @ ", " @ %previewData);
    %previewData.assetName = %this.getName();
    %previewData.assetPath = %this.getFileName();
    
@@ -71,19 +70,92 @@ function DatablockObjectType::onShowActionMenu(%this, %className)
    $CurrentAssetBrowser.popupMenu = EditDatablockObjectTypePopup;
 }
 
-function spawnDatablockObject(%datablock)
+function spawnDatablockObject(%datablock, %position)
 {
    %name = %datablock.getName();
    %class = %datablock.getClassName();
    %cmd = %class @ "::create(" @ %name @ ");";
    
-   %shapePath = ( %datablock.shapeAsset !$= "" ) ? %datablock.shapeFile : %datablock.shapeName;
    %createCmd = "ObjectCreator.createObject( \"" @ %cmd @ "\" );";
-   return eval(%createCmd);//eval("showImportDialog( \"" @ %shapePath @ "\", \"" @ %createCmd @ "\" );");
+   %newObject = eval(%createCmd);
+   
+   if(%position !$= "")
+      %newObject.position = %position;
+      
+   return %newObject;
+}
+
+function spawnAIObject(%datablock, %position)
+{
+   %name = %datablock.getName();
+   
+   %class = %datablock.getClassName();
+   %class = strreplace(%class, "Data", "");
+   
+   %cmd = "AI" @ %class @ "::create(" @ %name @ ");";
+   
+   %createCmd = "ObjectCreator.createObject( \"" @ %cmd @ "\" );";
+   %newObject = eval(%createCmd);
+   
+   if(%position !$= "")
+      %newObject.position = %position;
+      
+   return %newObject;
+}
+
+function spawnSpawnMarker(%datablock, %position)
+{
+   %class = %datablock.getClassName();
+   %class = strreplace(%class, "Data", "");
+   
+   ObjectBuilderGui.newObjectCallback = "finishedSpawningSpawnMarker"; 
+   ObjectCreator.createObject( "ObjectBuilderGui.buildSpawnSphere(" @ %class @ ", " @ %datablock.getName() @ ");" );
+}
+
+function finishedSpawningSpawnMarker(%objId)
+{
+   %objId.position = SpawnDatablockObjectPopup.position;
 }
 
 function DatablockObjectType::onWorldEditorDropped(%this, %position)
 {
-   %newObj = spawnDatablockObject(%this);
-   %newObj.position = %position;
+   if( !isObject( SpawnDatablockObjectPopup ) )
+   {
+      new PopupMenu( SpawnDatablockObjectPopup )
+      {
+         superClass = "MenuBuilder";
+         class = "EditorWorldMenu";
+
+         jumpFileName = "";
+         jumpLineNumber = "";
+      };
+   }
+   
+   SpawnDatablockObjectPopup.objectData = %this;
+   SpawnDatablockObjectPopup.objectType = "DatablockObjectType";
+   SpawnDatablockObjectPopup.position = %position;
+   
+   //Regen the menu so we're fully up and current with options and references
+   SpawnDatablockObjectPopup.clearItems();
+   
+   %class = %this.getClassName();
+   %class = strreplace(%class, "Data", "");
+   
+   SpawnDatablockObjectPopup.appendItem("Create " @ %class @ " Object" TAB "" TAB "spawnDatablockObject(" @ %this @ ", " @ %position @ ");");
+   
+   %category = getCategoryOfClass(%class);
+   if(%class $= "Player")
+   {
+      SpawnDatablockObjectPopup.appendItem("Create AI" @ %class @ " Object" TAB "" TAB "spawnAIObject(" @ %this @ ", " @ %position @ ");");
+   }
+   
+   SpawnDatablockObjectPopup.appendItem("Create SpawnNode of " @ %class TAB "" TAB "spawnSpawnMarker(" @ %this @ "," @ %position @ ");");
+
+   SpawnDatablockObjectPopup.reloadItems();
+   
+   SpawnDatablockObjectPopup.showPopup(Canvas); 
+   
+   
+   //%newObj = spawnDatablockObject(%this);
+   //%newObj.position = %position;
 }

+ 72 - 2
Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/prefab.tscript

@@ -24,8 +24,6 @@ function PrefabFileType::buildBrowserElement(%filePath, %previewData)
    %previewData.assetName = fileName(%filePath);
    %previewData.assetPath = %filePath;
    
-   echo("PrefabFileType::buildBrowserElement() - name, path: " @ %previewData.assetName @ ", " @ %filePath);
-   
    %previewData.previewImage = "ToolsModule:prefabIcon_image";
    
    //%previewData.assetFriendlyName = %assetDef.assetName;
@@ -49,4 +47,76 @@ function PrefabFileType::onWorldEditorDropped(%filePath, %position)
    EWorldEditor.selectObject(%newPrefab);
       
    EWorldEditor.isDirty = true;
+}
+
+function EWorldEditor::restoreSelectedToPrefab(%this, %object)
+{
+   %assetDef = AssetDatabase.acquireAsset(%object.shapeAsset);
+   %assetFileName = %assetDef.getFilename();
+   
+   %assetFileBase = strreplace(fileBase(%assetFileName), ".asset", "");
+   %assetFileBase = strreplace(%assetFileBase, ".taml", "");
+   
+   %prefabFile = filePath(%assetFileName) @ "/" @ %assetFileBase @ ".prefab";
+   
+   %name = %object.getName();
+   
+   %prefab = new Prefab() {
+      fileName = %prefabFile;
+      position = %object.position;
+      rotation = %object.rotation;
+      scale = %object.scale;
+   };
+   
+   %object.getGroup().add(%prefab);
+   
+   %prefab.setName(%name);
+   
+   MECreateUndoAction::submit( %prefab );
+   
+   MEDeleteUndoAction::submit( %object );
+}
+
+function EWorldEditor::rebakeSelectedMesh(%this, %object)
+{
+   %assetDef = AssetDatabase.acquireAsset(%object.shapeAsset);
+   %assetFileName = %assetDef.getFilename();
+   
+   %assetFileBase = strreplace(fileBase(%assetFileName), ".asset", "");
+   %assetFileBase = strreplace(%assetFileBase, ".taml", "");
+   
+   %prefabFile = filePath(%assetFileName) @ "/" @ %assetFileBase @ ".prefab";
+   
+   %name = %object;
+   
+   %prefab = new Prefab() {
+      fileName = %prefabFile;
+      position = %object.position;
+      rotation = %object.rotation;
+      scale = %object.scale;
+   };
+   
+   %object.getGroup().add(%prefab);
+   
+   EWorldEditor.clearSelection();
+   EWorldEditor.selectObject(%prefab);
+   
+   EWorldEditor.explodeSelectedPrefab();
+   
+   //after the explode, we'll have the group selected
+   %prefabGroup = EWorldEditor.getSelectedObject(0);
+   
+   EWorldEditor.clearSelection();
+   for(%i=0; %i < %prefabGroup.getCount(); %i++)
+   {
+      %prefabObj = %prefabGroup.getObject(%i); 
+      EWorldEditor.getActiveSelection().add(%prefabObj);
+   }
+   
+   makeSelectedAMesh(%object.shapeAsset, false, false);
+   
+   EWorldEditor.clearSelection();
+   EWorldEditor.selectObject(%object);
+   
+   %prefabGroup.delete();
 }

+ 6 - 6
Templates/BaseGame/game/tools/datablockEditor/DatablockEditorCreatePrompt.ed.gui

@@ -32,11 +32,11 @@ $guiContent = new GuiControl(DatablockEditorCreatePrompt,EditorGuiGroup) {
       anchorBottom = "0";
       anchorLeft = "1";
       anchorRight = "0";
-      position = "374 252";
-      extent = "309 167";
+      position = "758 420";
+      extent = "400 167";
       minExtent = "8 2";
-      horizSizing = "right";
-      vertSizing = "bottom";
+      horizSizing = "center";
+      vertSizing = "center";
       profile = "ToolsGuiWindowProfile";
       visible = "1";
       active = "1";
@@ -57,7 +57,7 @@ $guiContent = new GuiControl(DatablockEditorCreatePrompt,EditorGuiGroup) {
          anchorLeft = "1";
          anchorRight = "0";
          position = "7 26";
-         extent = "190 15";
+         extent = "250 15";
          minExtent = "8 2";
          horizSizing = "right";
          vertSizing = "bottom";
@@ -76,7 +76,7 @@ $guiContent = new GuiControl(DatablockEditorCreatePrompt,EditorGuiGroup) {
          sinkAllKeyEvents = "0";
          password = "0";
          passwordMask = "*";
-         text = "Name";
+         placeholderText = "Name";
          maxLength = "1024";
          margin = "0 0 0 0";
          padding = "0 0 0 0";

+ 8 - 4
Templates/BaseGame/game/tools/datablockEditor/datablockEditor.tscript

@@ -647,8 +647,7 @@ function DatablockEditorPlugin::createDatablock(%this)
    if( %class !$= "" )
    {  
       // Need to prompt for a name.
-      
-      DatablockEditorCreatePrompt-->CreateDatablockName.setText("Name");
+      DatablockEditorCreatePrompt-->CreateDatablockName.setText("");
       DatablockEditorCreatePrompt-->CreateDatablockName.selectAllText();
       
       // Populate the copy source dropdown.
@@ -686,7 +685,7 @@ function DatablockEditorPlugin::createDatablock(%this)
       // Show the dialog.
       
       canvas.pushDialog( DatablockEditorCreatePrompt, 0, true );
-      DatablockEditorCreatePrompt-->promptWindow.text = "Create New Datablock in module: " @ DatablockEditorPlugin.targetCreationModule;
+      DatablockEditorCreatePrompt-->promptWindow.text = "Create New " @ %class @ " Datablock in module: " @ DatablockEditorPlugin.targetCreationModule;
    }
 }
 
@@ -717,7 +716,10 @@ function DatablockEditorPlugin::createPromptNameCheck(%this, %path)
 {
    %name = DatablockEditorCreatePrompt-->CreateDatablockName.getText();
    if( !Editor::validateObjectName( %name, true ) )
-      return;
+   {
+      toolsMessageBoxOK("Error", "Unable to validate new datablock name. Please make sure it's an alphanumeric value and that it is unique!");
+      return;  
+   }
       
    // Fetch the copy source and clear the list.
    
@@ -762,6 +764,8 @@ function DatablockEditorPlugin::createDatablockFinish( %this, %name, %copySource
       %this.submitUndo( %action );
       
       %action.redo();
+      
+      DatablockEditorPlugin.openDatablock(%name);
    }
    
    $DATABLOCK_EDITOR_NEWDB_CLASS = "";

+ 22 - 5
Templates/BaseGame/game/tools/decalEditor/decalEditorGui.tscript

@@ -585,18 +585,35 @@ function DecalEditorGui::updateDecalPreview( %this, %material )
    
    if( isObject( %material ) )
    {
-      %previewImage = %material.getDiffuseMap(0);
+      %previewImage = %material.getDiffuseMapAsset(0);
    }
-   else
+   else if(AssetDatabase.isDeclaredAsset(%material))
    {
-      if(AssetDatabase.isDeclaredAsset(%material))
+      if(AssetDatabase.getAssetType(%material) $= "MaterialAsset")
+      {
+         %matAsset = AssetDatabase.acquireAsset(%material);
+         
+         %previewImage = %matAsset.materialDefinitionName.getDiffuseMap(0);
+         //AssetDatabase.releaseAsset(%material);
+      }
+      else if(AssetDatabase.getAssetType(%material) $= "ImageAsset")
       {
          %previewImage = %material;
-         }
       }
+      else
+      {
+         error("DecalEditorGui::updateDecalPreview() - Tried to set an invalid asset type for the editor preview!");
+         return;
+      }
+   }
+   else
+   {
+      error("DecalEditorGui::updateDecalPreview() - Tried to set a non material, non asset value for the editor preview!");
+      return;  
+   }
    
    DecalPreviewWindow-->decalPreview.setBitmap( getAssetPreviewImage(%previewImage) );
-   }
+}
 
 function DecalEditorGui::updateInstancePreview( %this, %material )
 {

+ 2 - 2
Templates/BaseGame/game/tools/gui/compositeTextureEditor.tscript

@@ -34,7 +34,7 @@ function CompositeTextureSlotContainer::setChannelData(%this, %sourceValue, %sou
    {
       %this-->InputMode.setSelected(1);
       
-      %this-->bitmap.setBitmap(%sourceValue);
+      %this-->bitmap.setBitmap(getAssetPreviewImage(%sourceValue));
       
       if(%sourceChannel $= "")
          %sourceChannel = "Red";
@@ -74,7 +74,7 @@ function CompositeTextureEditor::setSourceTex(%this, %assetId)
       $CompTexSourceChannel = 0;
       
    %channelContainer = CompositeTextureEditorWindow.getObject($CompTexSourceChannel);
-   %channelContainer-->bitmap.setBitmap(%assetId);
+   %channelContainer-->bitmap.setBitmap(getAssetPreviewImage(%assetId));
 }
 
 function CompositeTextureEditor::saveComposite(%this)

+ 46 - 0
Templates/BaseGame/game/tools/gui/fieldTypes/toggleControlButton.tscript

@@ -0,0 +1,46 @@
+function GuiInspectorGroup::buildToggleControlButtonField(%this, %fieldName, %fieldLabel, %fieldDesc, 
+            %fieldDefaultVal, %fieldDataVals, %callback, %ownerObj)
+{
+   %extent = 200;
+   
+   %fieldCtrl = %this.createInspectorField();
+   
+   %extent = %this.stack.getExtent();
+   
+   %width = mRound(%extent/2);
+   %height = 20;
+   %inset = 10;
+
+   %editControl = new GuiButtonCtrl() {
+      maxPopupHeight = "200";
+      sbUsesNAColor = "0";
+      reverseTextList = "0";
+      bitmapBounds = "16 16";
+      maxLength = "1024";
+      Margin = "0 0 0 0";
+      Padding = "0 0 0 0";
+      AnchorTop = "1";
+      AnchorBottom = "0";
+      AnchorLeft = "1";
+      AnchorRight = "0";
+      isContainer = "0";
+      Profile = "ToolsGuiButtonProfile";
+      HorizSizing = "right";
+      VertSizing = "bottom";
+      Position = %fieldCtrl.edit.position;
+      Extent = %fieldCtrl.edit.extent;
+      MinExtent = "8 2";
+      canSave = "1";
+      Visible = "1";
+      tooltipprofile = "ToolsGuiToolTipProfile";
+      tooltip = "";// %tooltip;
+      text = "Toggle";
+      hovertime = "1000";
+      command = "EditorToggleControlOfEntity();";
+   };
+
+   %fieldCtrl.setCaption("Toggle Control");
+   %fieldCtrl.setEditControl(%editControl);
+
+   %this.addInspectorField(%fieldCtrl);
+}

+ 1 - 0
Templates/BaseGame/game/tools/gui/guiDialogs.ed.tscript

@@ -42,3 +42,4 @@ exec("./fieldTypes/listField." @ $TorqueScriptFileExtension);
 exec("./fieldTypes/range." @ $TorqueScriptFileExtension);
 exec("./fieldTypes/moduleDependencies." @ $TorqueScriptFileExtension);
 exec("./fieldTypes/buttonField." @ $TorqueScriptFileExtension);
+exec("./fieldTypes/toggleControlButton." @ $TorqueScriptFileExtension);

+ 2 - 2
Templates/BaseGame/game/tools/gui/saveChangesMBDlg.ed.gui

@@ -46,7 +46,7 @@ $guiContent = new GuiControl(toolsMessageBoxSaveChangesDlg, EditorGuiGroup) {
          text = "Save";
          groupNum = "-1";
          buttonType = "PushButton";
-         iconBitmap = "~/levelEditor/gui/images/iconAccept.png";
+         iconBitmapFile = "~/levelEditor/gui/images/iconAccept.png";
          sizeIconToButton = "0";
          textLocation = "Center";
          textMargin = "4";
@@ -66,7 +66,7 @@ $guiContent = new GuiControl(toolsMessageBoxSaveChangesDlg, EditorGuiGroup) {
          text = "Cancel";
          groupNum = "-1";
          buttonType = "PushButton";
-         iconBitmap = "~/levelEditor/gui/images/iconCancel.png";
+         iconBitmapFile = "~/levelEditor/gui/images/iconCancel.png";
          sizeIconToButton = "0";
          textLocation = "Center";
          textMargin = "4";

+ 7 - 6
Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui

@@ -273,12 +273,12 @@ $guiContent = new GuiControl(GuiEditorGui, EditorGuiGroup) {
                bitmapAsset = "ToolsModule:separator_xt_h_image";
                bitmapMode = "Centered";
             };
-            new GuiPopUpMenuCtrl(GuiEditorContentList) {
+            new GuiPopUpMenuCtrlEx(GuiEditorContentList) {
                maxPopupHeight = "200";
                sbUsesNAColor = "0";
                reverseTextList = "0";
                bitmapBounds = "16 16";
-               text = "NewGui - 8844";
+               text = "";
                maxLength = "1024";
                margin = "0 0 0 0";
                padding = "0 0 0 0";
@@ -291,13 +291,14 @@ $guiContent = new GuiControl(GuiEditorGui, EditorGuiGroup) {
                horizSizing = "right";
                vertSizing = "center";
                position = "8 0";
-               extent = "145 27";
+               extent = "300 27";
                minExtent = "8 2";
                canSave = "1";
                visible = "1";
                tooltipProfile = "ToolsGuiToolTipProfile";
                hovertime = "1000";
                canSaveDynamicFields = "0";
+               allowTextSearch = true;
             };
             new GuiPopUpMenuCtrl(GuiEditorResList) {
                maxPopupHeight = "200";
@@ -316,8 +317,8 @@ $guiContent = new GuiControl(GuiEditorGui, EditorGuiGroup) {
                profile = "ToolsGuiPopUpMenuProfile";
                horizSizing = "right";
                vertSizing = "center";
-               position = "161 0";
-               extent = "136 27";
+               position = "303 0";
+               extent = "250 27";
                minExtent = "8 2";
                canSave = "1";
                visible = "1";
@@ -333,7 +334,7 @@ $guiContent = new GuiControl(GuiEditorGui, EditorGuiGroup) {
                profile = "ToolsGuiDefaultProfile";
                horizSizing = "right";
                vertSizing = "center";
-               position = "307 3";
+               position = "556 3";
                extent = "9 26";
                minExtent = "1 1";
                canSave = "1";

+ 2 - 2
Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorToolbox.ed.tscript

@@ -91,7 +91,7 @@ function GuiEditorToolbox::setViewTypeAlphabetical( %this )
          profile = "ToolsGuiIconButtonSmallProfile";
          extent = "128 18";
          text = %className;
-         iconBitmap = EditorIconRegistry::findIconByClassName( %className );
+         iconBitmapFile = EditorIconRegistry::findIconByClassName( %className );
          buttonMargin = "2 2";
          iconLocation = "left";
          textLocation = "left";
@@ -174,7 +174,7 @@ function GuiEditorToolbox::setViewTypeCategorized( %this )
             profile = "ToolsGuiIconButtonSmallProfile";
             extent = "128 18";
             text = %className;
-            iconBitmap = EditorIconRegistry::findIconByClassName( %className );
+            iconBitmapFile = EditorIconRegistry::findIconByClassName( %className );
             buttonMargin = "2 2";
             iconLocation = "left";
             textLocation = "left";

+ 1 - 0
Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.tscript

@@ -1992,6 +1992,7 @@ function MaterialEditorGui::doSwapMaterial(%this, %materialAsset)
 function MaterialEditorPropInspector::onInspectorFieldModified(%this, %object, %fieldName, %arrayIndex, %oldValue, %newValue)
 {
    MaterialEditorPropInspector.saveScrollState();
+   MaterialEditorPropInspector.saveCollapseState();
    
    if(%arrayIndex !$= "" && %arrayIndex !$= "(null)")
       MaterialEditorGui.updateActiveMaterial(%fieldName @ "[" @ %arrayIndex @ "]", %newValue);

+ 56 - 3
Templates/BaseGame/game/tools/navEditor/NavEditorGui.gui

@@ -427,7 +427,8 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
          {
             internalName = "TestActions";
             position = "7 21";
-            extent = "190 136";
+            extent = "300 136";
+            
             new GuiControl() {
                profile = "GuiDefaultProfile";
                Extent = "190 20";
@@ -445,18 +446,70 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
             };
             new GuiControl() {
                profile = "GuiDefaultProfile";
-               Extent = "190 20";
+               Extent = "300 20";
                new GuiPopUpMenuCtrl(SpawnClassSelector) {
                   extent = "89 20";
                   profile = "ToolsGuiPopUpMenuProfile";
                   tooltipProfile = "GuiToolTipProfile";
                };
 
-               new GuiPopUpMenuCtrl(SpawnDatablockSelector) {
+               new GuiPopUpMenuCtrlEx(SpawnDatablockSelector) {
                   position = "100 0";
                   extent = "89 20";
                   profile = "ToolsGuiPopUpMenuProfile";
                   tooltipProfile = "GuiToolTipProfile";
+                  allowTextSearch = true;
+               };
+               
+               new GuiButtonCtrl(SpawnDatablockEditDBBtn) {
+                  text = "...";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "193 0";
+                  extent = "17 17";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "GuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+                  tooltip = "Edit Datablock";
+               };
+               
+               new GuiBitmapButtonCtrl(SpawnDatablockAddDBBtn) {
+                  bitmapAsset = "ToolsModule:iconAdd_image";
+                  bitmapMode = "Centered";
+                  autoFitExtents = "0";
+                  useModifiers = "0";
+                  useStates = "1";
+                  masked = "0";
+                  groupNum = "-1";
+                  buttonType = "PushButton";
+                  useMouseEvents = "0";
+                  position = "211 -2";
+                  extent = "22 22";
+                  minExtent = "8 2";
+                  horizSizing = "right";
+                  vertSizing = "bottom";
+                  profile = "ToolsGuiButtonProfile";
+                  visible = "1";
+                  active = "1";
+                  tooltipProfile = "GuiToolTipProfile";
+                  hovertime = "1000";
+                  isContainer = "0";
+                  canSave = "1";
+                  canSaveDynamicFields = "0";
+                  tooltip = "Create new Datablock";
                };
             };
 

+ 20 - 0
Templates/BaseGame/game/tools/navEditor/navEditor.tscript

@@ -575,6 +575,26 @@ function SpawnDatablockSelector::onSelect(%this, %id)
    NavMeshTools->TestTool.setSpawnDatablock(%className);
 }
 
+function SpawnDatablockEditDBBtn::onClick(%this)
+{
+   %dbName = SpawnDatablockSelector.getText();
+   DatablockEditorPlugin.openDatablock(%dbName);
+}
+
+function SpawnDatablockAddDBBtn::onClick(%this)
+{
+   %className = SpawnClassSelector.getText();
+   %classData = %className @ "Data";
+   if(%className $= "AIPlayer")
+   {
+      %classData = "PlayerData";
+   }
+   
+   %dbName = SpawnDatablockSelector.getText();
+   
+   DatablockEditorPlugin.createNewDatablockOfType(%classData, %dbName);
+}
+
 //------------------------------------------------------
 // TILETOOL
 //------------------------------------------------------

+ 3 - 3
Templates/BaseGame/game/tools/shapeEditor/main.tscript

@@ -151,8 +151,8 @@ function ShapeEditorPlugin::openShapeAsset(%this, %assetDef)
 function ShapeEditorPlugin::openShapeAssetId(%this, %assetId)
 {
    %this.selectedAssetDef = AssetDatabase.acquireAsset(%assetId);
-   //%this.selectedAssetDef = %assetDef;
-   %this.open(%this.selectedAssetDef);
+   EditorGui.setEditor( ShapeEditorPlugin );
+   ShapeEditorPlugin.openShapeAsset(%this.selectedAssetDef);
 }
 
 function ShapeEditorPlugin::open(%this, %shapeAsset)
@@ -323,7 +323,7 @@ function ShapeEditorPlugin::onExitMission( %this )
 {
    // unselect the current shape
    ShapeEdShapeView.setModel( "" );
-   if (ShapeEditor.shape != -1)
+   if (ShapeEditor.shape != 0 && ShapeEditor.shape != -1)
       ShapeEditor.shape.delete();
    ShapeEditor.shape = 0;
    ShapeEdUndoManager.clearAll();

+ 1 - 1
Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditor.ed.tscript

@@ -546,7 +546,7 @@ function ShapeEdSelectWindow::addObjectHint( %this, %type, %name, %desc, %presen
          autoSize = true;
          buttonType = "radioButton";
          groupNum = "-1";
-         iconBitmap = "tools/editorClasses/gui/images/iconCancel";
+         iconBitmapFile = "tools/editorClasses/gui/images/iconCancel";
          text = "hint";
          tooltip = "";
       };

+ 2 - 23
Templates/BaseGame/game/tools/worldEditor/gui/EditorGui.ed.gui

@@ -32,30 +32,11 @@ $guiContent = new GuiContainer(EditorGui,EditorGuiGroup) {
       isDecoy = "1";
    };
    
-   new GuiTabBookCtrl(EditorGuiMainTabBook) {
-      tabHeight = "20";
-      selectedPage = "0";
-      position = "0 5";
-      extent = "800 595";
-      horizSizing = "width";
-      vertSizing = "height";
-      profile = "ToolsGuiTabBookProfile";
-      tooltipProfile = "GuiToolTipProfile";
-
-      new GuiTabPageCtrl(MainSceneEditorTab) {
-         text = "Main Scene";
-         position = 0 SPC 20;
-         extent = 800 SPC 580;
-         horizSizing = "width";
-         vertSizing = "height";
-         profile = "ToolsGuiTabPageProfile";
-         tooltipProfile = "GuiToolTipProfile";
-         
          new GuiContainer(MainSceneTabPanel) {
             HorizSizing = "width";
             VertSizing = "height";
-            Position = "0 0";
-            Extent = "800 580";
+            Position = "0 5";
+            Extent = "800 595";
             
             new WorldEditor(EWorldEditor) {
                canSaveDynamicFields = "0";
@@ -1569,7 +1550,5 @@ $guiContent = new GuiContainer(EditorGui,EditorGuiGroup) {
                };
             };
          };
-      };
-   };
 };
 //--- OBJECT WRITE END ---

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

@@ -228,5 +228,5 @@ function TerrainBrushSoftnessCurveDlg::onOk( %this )
 function TerrainBrushSoftnessCurveDlg::resetCurve( %this )
 {
    %curve = %this-->FilterCurveCtrl;
-   %curve.identity();
+   %curve.resetFiltering();
 }

+ 222 - 111
Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui

@@ -1,106 +1,76 @@
 //--- OBJECT WRITE BEGIN ---
-$guiContent = new GuiControl(ObjectBuilderGui, EditorGuiGroup) {
-	profile = "ToolsGuiDefaultProfile";
-	horizSizing = "right";
-	vertSizing = "bottom";
-	position = "0 0";
-	extent = "800 600";
-	minExtent = "8 8";
-	visible = "1";
-	setFirstResponder = "0";
-	modal = "1";
-	helpTag = "0";
-
-	new GuiWindowCtrl(OBTargetWindow) {
-		profile = "ToolsGuiWindowProfile";
-		horizSizing = "center";
-		vertSizing = "center";
-		position = "384 205";
-		extent = "256 282";
-		minExtent = "256 8";
-		visible = "1";
-		setFirstResponder = "0";
-		modal = "1";
-		helpTag = "0";
-		resizeWidth = "1";
-		resizeHeight = "1";
-		canMove = "1";
-		canClose = "0";
-		canMinimize = "0";
-		canMaximize = "0";
-		minSize = "50 50";
-		text = "Create Object";
-
-		new GuiTextCtrl() {
-			profile = "ToolsGuiTextProfile";
-			horizSizing = "right";
-			vertSizing = "bottom";
-			position = "9 26";
-			extent = "84 16";
-			minExtent = "8 8";
-			visible = "1";
-			setFirstResponder = "0";
-			modal = "1";
-			helpTag = "0";
-			text = "Object Name:";
-		};
-		new GuiTextEditCtrl(OBObjectName) {
-		   class = ObjectBuilderGuiTextEditCtrl;
-			profile = "ToolsGuiTextEditProfile";
-			horizSizing = "width";
-			vertSizing = "bottom";
-			position = "78 26";
-			extent = "172 18";
-			minExtent = "8 8";
-			visible = "1";
-			setFirstResponder = "0";
-			modal = "1";
-			helpTag = "0";
-			historySize = "0";
-		};
-		new GuiBitmapBorderCtrl(OBContentWindow) {
-			profile = "ToolsGuiGroupBorderProfile";
-			horizSizing = "width";
-			vertSizing = "bottom";
-			position = "7 51";
-			extent = "243 193";
-			minExtent = "0 0";
-			visible = "1";
-			setFirstResponder = "0";
-			modal = "1";
-			helpTag = "0";
-		};
-		new GuiButtonCtrl(OBOKButton) {
-			profile = "ToolsGuiButtonProfile";
-			horizSizing = "width";
-			vertSizing = "bottom";
-			position = "7 250";
-			extent = "156 24";
-			minExtent = "8 8";
-			visible = "1";
-			setFirstResponder = "0";
-			modal = "1";
-			command = "ObjectBuilderGui.onOK();";
-			helpTag = "0";
-			text = "Create New";
-			Accelerator = "return";
-		};
-		new GuiButtonCtrl(OBCancelButton) {
-			profile = "ToolsGuiButtonProfile";
-			horizSizing = "left";
-			vertSizing = "bottom";
-			position = "170 250";
-			extent = "80 24";
-			minExtent = "8 8";
-			visible = "1";
-			setFirstResponder = "0";
-			modal = "1";
-			command = "ObjectBuilderGui.onCancel();";
-			helpTag = "0";
-			text = "Cancel";
-			Accelerator = "escape";
-		};
-	};
+$guiContent = new GuiControl(ObjectBuilderGui,EditorGuiGroup) {
+   extent = "1920 1080";
+   minExtent = "8 8";
+   profile = "ToolsGuiDefaultProfile";
+   tooltipProfile = "GuiToolTipProfile";
+   isContainer = "1";
+   canSaveDynamicFields = "1";
+      helpTag = "0";
+
+   new GuiWindowCtrl(OBTargetWindow) {
+      Text = "Create Object";
+      canClose = "0";
+      canMinimize = "0";
+      canMaximize = "0";
+      position = "735 399";
+      extent = "449 282";
+      minExtent = "256 8";
+      horizSizing = "center";
+      vertSizing = "center";
+      profile = "ToolsGuiWindowProfile";
+      tooltipProfile = "GuiToolTipProfile";
+
+      new GuiTextCtrl() {
+         Text = "Object Name:";
+         position = "9 26";
+         extent = "84 16";
+         minExtent = "8 8";
+         profile = "ToolsGuiTextProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiTextEditCtrl(OBObjectName) {
+         position = "102 26";
+         extent = "341 20";
+         minExtent = "8 8";
+         horizSizing = "width";
+         profile = "ToolsGuiTextEditProfile";
+         tooltipProfile = "GuiToolTipProfile";
+         class = "ObjectBuilderGuiTextEditCtrl";
+      };
+      new GuiBitmapBorderCtrl(OBContentWindow) {
+         position = "7 51";
+         extent = "437 193";
+         minExtent = "0 0";
+         horizSizing = "width";
+         profile = "ToolsGuiGroupBorderProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiButtonCtrl(OBOKButton) {
+         Text = "Create New";
+         position = "263 250";
+         extent = "97 24";
+         minExtent = "8 8";
+         horizSizing = "left";
+         vertSizing = "top";
+         profile = "ToolsGuiButtonProfile";
+         command = "ObjectBuilderGui.onOK();";
+         accelerator = "return";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiButtonCtrl(OBCancelButton) {
+         Text = "Cancel";
+         position = "364 250";
+         extent = "80 24";
+         minExtent = "8 8";
+         horizSizing = "left";
+         vertSizing = "top";
+         profile = "ToolsGuiButtonProfile";
+         command = "ObjectBuilderGui.onCancel();";
+         accelerator = "escape";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+   };
 };
 //--- OBJECT WRITE END ---
 
@@ -110,13 +80,13 @@ function ObjectBuilderGui::init(%this)
    %this.baseOffsetY       = 5;
    %this.defaultObjectName = "";
    %this.defaultFieldStep  = 22;
-   %this.columnOffset      = 110;
+   %this.columnOffset      = 140;
 
-   %this.fieldNameExtent   = "105 18";
-   %this.textEditExtent    = "122 18";
+   %this.fieldNameExtent   = "135 18";
+   %this.textEditExtent    = "280 18";
    %this.checkBoxExtent    = "13 18";
-   %this.popupMenuExtent   = "122 18";
-   %this.fileButtonExtent  = "122 18";
+   %this.popupMenuExtent   = "280 18";
+   %this.fileButtonExtent  = "280 18";
    %this.matButtonExtent   = "17 18";
 
    //
@@ -886,6 +856,50 @@ function ObjectBuilderGui::createStringType(%this, %index)
    %this.curYPos += %this.defaultFieldStep;
 }
 
+function ObjectBuilderGuiCommandCtrl::apply(%this, %text)
+{
+   %this.text = %text;
+}
+
+function ObjectBuilderGui::createCommandType(%this, %index)
+{
+   if(%index >= %this.numFields || %this.field[%index, name] $= "")
+   {
+      error("ObjectBuilderGui::createCommandType: invalid field");
+      return;
+   }
+   
+   //
+   if(%this.field[%index, text] $= "")
+      %name = %this.field[%index, name];
+   else
+      %name = %this.field[%index, text];
+
+   // 
+   %this.textControls[%this.numControls] = new GuiTextCtrl() {
+      profile = "ToolsGuiTextRightProfile";
+      text = %name;
+      extent = %this.fieldNameExtent;
+      position = %this.curXPos @ " " @ %this.curYPos;
+      modal = "1";
+   };
+   
+   // 
+   %this.controls[%this.numControls] = new GuiButtonCtrl() {
+      class = ObjectBuilderGuiCommandCtrl;
+      HorizSizing = "width";
+      profile = "ToolsGuiTextEditProfile";
+      extent = %this.textEditExtent;
+      text = %this.field[%index, value];
+      position = %this.curXPos + %this.columnOffset @ " " @ %this.curYPos;
+      modal = "1";
+      command = "TextPad($ThisControl.text, $ThisControl@\".apply\", $ThisControl.getRoot());";
+   };
+   
+   %this.numControls++;
+   %this.curYPos += %this.defaultFieldStep;
+}
+
 //------------------------------------------------------------------------------
 
 function ObjectBuilderGui::adjustSizes(%this)
@@ -940,6 +954,9 @@ function ObjectBuilderGui::process(%this)
 
          case "TypeMaterialName":
             %this.createMaterialNameType(%i);
+            
+         case "TypeCommand":
+            %this.createCommandType(%i);
 
          default:
             %this.createStringType(%i);
@@ -1502,18 +1519,18 @@ function ObjectBuilderGui::buildFlyingVehicle(%this)
    %this.process();
 }
 
-function ObjectBuilderGui::buildSpawnSphere(%this)
+function ObjectBuilderGui::buildSpawnSphere(%this, %spawnClass, %spawnDatablock)
 {
    %this.objectClassName = "SpawnSphere";
    %this.addField("dataBlock",    "TypeDataBlock", "dataBlock",   "MissionMarkerData SpawnSphereMarker");
    %this.addField("radius",       "TypeFloat",     "Radius",        1);
    %this.addField("sphereWeight", "TypeFloat",     "Sphere Weight", 1);
 
-   %this.addField("spawnClass",     "TypeString",    "Spawn Class", "");
-   %this.addField("spawnDatablock", "TypeString", "Spawn Data", "");
+   %this.addField("spawnClass",     "TypeString",    "Spawn Class", %spawnClass);
+   %this.addField("spawnDatablock", "TypeString", "Spawn Data", %spawnDatablock);
    %this.addField("spawnTransform", "TypeBool", "Spawn Here", "true");
    %this.addField("autoSpawn", "TypeBool", "Auto Spawn Objects", "false");
-   %this.addField("spawnScript", "TypeString", "spawnScript", "%this.spawned = $SpawnObject;");
+   %this.addField("spawnScript", "TypeCommand", "spawnScript", "%this.spawned = $SpawnObject;");
    %this.addField("canSaveDynamicFields", "TypeBool", "Save metadata", "false");
    %this.process();
 }
@@ -1768,4 +1785,98 @@ function TriggerData::create(%datablock)
       polyhedron = "-0.5 0.5 0.0 1.0 0.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0";
    };
    return %obj;
+}
+
+//
+function PlayerData::create(%datablock)
+{
+   %obj = new Player()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+function Player::create(%datablock)
+{
+   %obj = new Player()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+function AIPlayer::create(%datablock)
+{
+   %obj = new AIPlayer()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+//
+function WheeledVehicleData::create(%datablock)
+{
+   %obj = new WheeledVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+function WheeledVehicle::create(%datablock)
+{
+   %obj = new WheeledVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+//
+function FlyingVehicleData::create(%datablock)
+{
+   %obj = new FlyingVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+function FlyingVehicle::create(%datablock)
+{
+   %obj = new FlyingVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+//
+function HoverVehicleData::create(%datablock)
+{
+   %obj = new HoverVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
+}
+
+function HoverVehicle::create(%datablock)
+{
+   %obj = new HoverVehicle()
+   {
+      dataBlock = %datablock;
+      parentGroup = ObjectCreator.objectGroup;
+   };
+   return %obj;
 }

+ 28 - 2
Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript

@@ -1709,7 +1709,7 @@ function EWorldEditor::maxSize(%this, %window)
       
       %fixedWindow = EWTreeWindow;
       %fluidWindow = EWInspectorWindow;
-      %offset = 25; // tweak the vertical offset so that it aligns neatly
+      %offset = 0; // tweak the vertical offset so that it aligns neatly
       %top = EditorGuiToolbar.extent.y + %offset;
       %bottom = %top + 59;
       %maxHeight = Canvas.extent.y - %top - %bottom + 12;
@@ -2101,7 +2101,10 @@ function EditorTree::onRightMouseUp( %this, %itemId, %mouse, %obj )
       %popup.item[ 0 ] = "Delete" TAB "" TAB "EditorMenuEditDelete();";
       %popup.item[ 1 ] = "Group" TAB "" TAB "EWorldEditor.addSimGroup( true );";
       %popup.item[ 2 ] = "-";
-      %popup.item[ 3 ] = "Make selected a Sub-Level" TAB "" TAB "MakeSelectionASublevel();";
+      %popup.item[ 3 ] = "Make selected a Prefab" TAB "" TAB "EWorldEditor.makeSelectionPrefab();";
+      %popup.item[ 4 ] = "Bake selected into Mesh" TAB "" TAB "AssetBrowser.setupCreateNewAsset(\"ShapeAsset\", AssetBrowser.selectedModule, \"makeSelectedAMesh\");";
+      %popup.item[ 5 ] = "-";
+      %popup.item[ 6 ] = "Make selected a Sub-Level" TAB "" TAB "MakeSelectionASublevel();";
    }
    else
    {
@@ -2206,6 +2209,29 @@ function EditorTree::onRightMouseUp( %this, %itemId, %mouse, %obj )
                %popup.item[ 13 ] = "Convert to SubScene" TAB "" TAB "EWorldEditor.createSelectedAsSubScene( " @ %popup.object @ " );";
             }
          }  
+         else if(%obj.getClassName() $= "TSStatic")
+         {
+            if(AssetDatabase.isDeclaredAsset(%obj.shapeAsset))
+            {
+               %assetDef = AssetDatabase.acquireAsset(%obj.shapeAsset);
+               
+               %assetFileName = %assetDef.getFilename();
+               %assetFileBase = strreplace(fileBase(%assetFileName), ".asset", "");
+               %assetFileBase = strreplace(%assetFileBase, ".taml", "");
+               
+               %prefabFile = filePath(%assetFileName) @ "/" @ %assetFileBase @ ".prefab";
+               if(isFile(%prefabFile))
+               {
+                  %popup.item[ 8 ] = "-";
+                  %popup.item[ 9 ] = "Restore to Prefab" TAB "" TAB "EWorldEditor.restoreSelectedToPrefab( " @ %popup.object @ " );";
+                  %popup.item[ 10 ] = "Rebake Mesh" TAB "" TAB "EWorldEditor.rebakeSelectedMesh( " @ %popup.object @ " );";
+               }
+            }
+         }
+         else if( %obj.isMemberOfClass( "Prefab" ) )
+         {
+            %popup.item[ 8 ] = "Explode Prefab" TAB "" TAB "EWorldEditor.explodeSelectedPrefab();";
+         }
       }
    }
 

+ 5 - 5
Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.tscript

@@ -135,7 +135,7 @@ function ObjectCreator::createObject( %this, %cmd )
    if(startsWith(%cmd, "return "))
       %objId = eval(%cmd);
    else
-   %objId = eval("return " @ %cmd);
+      %objId = eval("return " @ %cmd);
    popInstantGroup();
    
    if( isObject( %objId ) )
@@ -246,7 +246,7 @@ function ObjectCreator::addMissionObjectIcon( %this, %class, %name, %buildfunc )
       %cmd = "ObjectBuilderGui." @ %method @ "();";
 
    %ctrl.altCommand = "ObjectBuilderGui.newObjectCallback = \"ObjectCreator.onFinishCreateObject\"; ObjectCreator.createObject( \"" @ %cmd @ "\" );";
-   %ctrl.iconBitmap = EditorIconRegistry::findIconByClassName( %class );
+   %ctrl.iconBitmapFile = EditorIconRegistry::findIconByClassName( %class );
    %ctrl.text = %name;
    %ctrl.class = "CreatorMissionObjectIconBtn";   
    %ctrl.tooltip = %class; 
@@ -270,7 +270,7 @@ function ObjectCreator::addShapeIcon( %this, %datablock )
    %createCmd = "ObjectCreator.createObject( \\\"" @ %cmd @ "\\\" );";
    %ctrl.altCommand = "showImportDialog( \"" @ %shapePath @ "\", \"" @ %createCmd @ "\" );";
 
-   %ctrl.iconBitmap = EditorIconRegistry::findIconByClassName( %class );
+   %ctrl.iconBitmapFile = EditorIconRegistry::findIconByClassName( %class );
    %ctrl.text = %name;
    %ctrl.class = "CreatorShapeIconBtn";
    %ctrl.tooltip = %name;
@@ -296,7 +296,7 @@ function ObjectCreator::addStaticIcon( %this, %fullPath )
    %createCmd = "ObjectCreator.createStatic( \\\"" @ %fullPath @ "\\\" );";
    %ctrl.altCommand = "showImportDialog( \"" @ %fullPath @ "\", \"" @ %createCmd @ "\" );";
 
-   %ctrl.iconBitmap = ( ( %ext $= ".dts" ) ? EditorIconRegistry::findIconByClassName( "TSStatic" ) : "tools/gui/images/iconCollada" );
+   %ctrl.iconBitmapFile = ( ( %ext $= ".dts" ) ? EditorIconRegistry::findIconByClassName( "TSStatic" ) : "tools/gui/images/iconCollada" );
    %ctrl.text = %file;
    %ctrl.class = "CreatorStaticIconBtn";
    %ctrl.tooltip = %tip;
@@ -320,7 +320,7 @@ function ObjectCreator::addPrefabIcon( %this, %fullPath )
           "Last Modified: " @ fileModifiedTime( %fullPath );
 
    %ctrl.altCommand = "ObjectCreator.createPrefab( \"" @ %fullPath @ "\" );";
-   %ctrl.iconBitmap = EditorIconRegistry::findIconByClassName( "Prefab" );
+   %ctrl.iconBitmapFile = EditorIconRegistry::findIconByClassName( "Prefab" );
    %ctrl.text = %file;
    %ctrl.class = "CreatorPrefabIconBtn";
    %ctrl.tooltip = %tip;

+ 9 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/editors/worldEditor.ed.tscript

@@ -516,6 +516,15 @@ function Inspector::inspect( %this, %obj )
       %name = %obj.getName();   
    else
       FieldInfoControl.setText( "" );
+      
+   %category = getCategoryOfClass(%obj.getClassName());
+   if(getFieldCount(%category > 1) && trim(getField(%category, 1)) $= "Controllable")
+   {
+      %genGroup = %this.findExistentGroup("General");
+      
+      if(isObject(%genGroup))
+         %genGroup.addField("ToggleControlBtn", "ToggleControlButton", "Takes control of the selected controllable object");
+   }
    
    //InspectorNameEdit.setValue( %name );
    Parent::inspect( %this, %obj );  

+ 46 - 20
Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript

@@ -455,7 +455,7 @@ function EditorAutoSaveMission()
    
    AssetBackupListArray.empty();
    
-   %scenePath = makeFullPath(getRootScene().getFileName());
+   %scenePath = getRootScene().getFileName();
    if(startsWith(%scenePath, "tools/levels/"))
       return false;
    
@@ -793,7 +793,7 @@ function EditorExplodePrefab()
    EditorTree.buildVisibleTree( true );
 }
 
-function makeSelectedAMesh(%assetId)
+function makeSelectedAMesh(%assetId, %createPrefab, %spawnNewStatic)
 {      
    %selectedCount = EWorldEditor.getSelectionSize();
    
@@ -803,6 +803,12 @@ function makeSelectedAMesh(%assetId)
       return;  
    }
    
+   if(%createPrefab $= "")
+      %createPrefab = true;
+      
+   if(%spawnNewStatic $= "")
+      %spawnNewStatic = true;
+   
    %assetDef = AssetDatabase.acquireAsset(%assetId);
    
    %assetPath = AssetDatabase.getAssetPath(%assetId);
@@ -836,31 +842,48 @@ function makeSelectedAMesh(%assetId)
          }
       }
       
-      %prefabPath = %assetPath @ "/" @ %assetDef.AssetName @ ".prefab";
-      EWorldEditor.makeSelectionPrefab(%prefabPath, false);
-      %selectionPos = EWorldEditor.getSelectedObject(0).getPosition();
-      //Next, nuke 'em
-      EditorMenuEditDelete();
+      if(%createPrefab)
+      {
+         %prefabPath = %assetPath @ "/" @ %assetDef.AssetName @ ".prefab";
+         EWorldEditor.makeSelectionPrefab(%prefabPath, false);
+      }
       
-      //now make a new static  
-      %newStatic = new TSStatic()
+      if(%spawnNewStatic)
       {
-         shapeAsset = %assetId;
-         position = %selectionPos;
-      };
-
-      if(%sameParent)
-         %firstParent.add(%newStatic);
-      else
-         getRootScene().add(%newStatic);
+         %selectionPos = EWorldEditor.getSelectedObject(0).getPosition();
+         
+         //Next, nuke 'em
+         EditorMenuEditDelete();
          
-      EWorldEditor.clearSelection();
-      EWorldEditor.selectObject(%newStatic);
+         //now make a new static  
+         %newStatic = new TSStatic()
+         {
+            shapeAsset = %assetId;
+            position = %selectionPos;
+         };
+
+         if(%sameParent)
+            %firstParent.add(%newStatic);
+         else
+            getRootScene().add(%newStatic);
+            
+         EWorldEditor.clearSelection();
+         EWorldEditor.selectObject(%newStatic);
+      }
    }
    
    EditorTree.buildVisibleTree( true );  
 }
 
+function EditorToggleControlOfEntity()
+{
+   %object = EWorldEditor.getSelectedObject(0);
+   if(%object == localClientConnection.getControlObject())
+      EditorReleaseControlOfEntity();
+   else
+      EditorTakeControlOfEntity();
+}
+
 function EditorTakeControlOfEntity()
 {
    %object = EWorldEditor.getSelectedObject(0);
@@ -868,8 +891,9 @@ function EditorTakeControlOfEntity()
    {
       $Editor::previousControlObject = localClientConnection.getControlObject(); 
       localClientConnection.setControlObject(%object);
-
    }
+   
+   Inspector.refresh();
 }
 
 function EditorReleaseControlOfEntity()
@@ -878,6 +902,8 @@ function EditorReleaseControlOfEntity()
    {
       localClientConnection.setControlObject($Editor::previousControlObject);
    }
+   
+   Inspector.refresh();
 }
 
 function EditorMount()