Browse Source

Fixes issue where Regenerate Bounds button for SceneGroup/SubScenes wasn't displaying by moving it to Editing inspector group
Added mode toggle for if changing the transform influences the child objects of a SubScene or not
Added onSelected/onUnselected callbacks for SimObjects to allow contextual behavior in the editor
Added functionality of programmatic/dynamic Tool Button Palettes
Added logic so when selecting SubScenes the world editor palette has new buttons for letting the move/rotate actions influence the child objects

JeffR 10 tháng trước cách đây
mục cha
commit
e2d0cc1981

+ 1 - 1
Engine/source/T3D/SceneGroup.cpp

@@ -119,7 +119,7 @@ void SceneGroup::onInspect(GuiInspector* inspector)
    Parent::onInspect(inspector);
    
    //Put the SubScene group before everything that'd be SubScene-effecting, for orginazational purposes
-   GuiInspectorGroup* sceneGroupGrp = inspector->findExistentGroup(StringTable->insert("SceneGroup"));
+   GuiInspectorGroup* sceneGroupGrp = inspector->findExistentGroup(StringTable->insert("Editing"));
    if (!sceneGroupGrp)
       return;
 

+ 30 - 0
Engine/source/T3D/SubScene.cpp

@@ -10,6 +10,8 @@
 #include "gui/editor/inspector/group.h"
 #include "T3D/gameBase/gameBase.h"
 
+bool SubScene::smTransformChildren = false;
+
 IMPLEMENT_CO_NETOBJECT_V1(SubScene);
 
 S32 SubScene::mUnloadTimeoutMs = 5000;
@@ -86,6 +88,10 @@ void SubScene::consoleInit()
 
    Con::addVariable("$SubScene::UnloadTimeoutMS", TypeBool, &SubScene::mUnloadTimeoutMs, "The amount of time in milliseconds it takes for a SubScene to be unloaded if it's inactive.\n"
       "@ingroup Editors\n");
+
+   Con::addVariable("$SubScene::transformChildren", TypeBool, &SubScene::smTransformChildren,
+      "@brief If true, then transform manipulations modify child objects. If false, only triggering bounds is manipulated\n\n"
+      "@ingroup Editors");
 }
 
 void SubScene::addObject(SimObject* object)
@@ -163,6 +169,30 @@ void SubScene::inspectPostApply()
    setMaskBits(-1);
 }
 
+void SubScene::setTransform(const MatrixF& mat)
+{
+   if(SubScene::smTransformChildren)
+   {
+      Parent::setTransform(mat);
+   }
+   else
+   {
+      SceneObject::setTransform(mat);
+   }
+}
+
+void SubScene::setRenderTransform(const MatrixF& mat)
+{
+   if (SubScene::smTransformChildren)
+   {
+      Parent::setRenderTransform(mat);
+   }
+   else
+   {
+      SceneObject::setRenderTransform(mat);
+   }
+}
+
 bool SubScene::evaluateCondition()
 {
    if (!mLoadIf.isEmpty())

+ 7 - 0
Engine/source/T3D/SubScene.h

@@ -23,6 +23,9 @@ public:
 
    void onLevelChanged() {}
 
+protected:
+   static bool smTransformChildren;
+
 private:
    DECLARE_LEVELASSET(SubScene, Level, onLevelChanged);
 
@@ -47,6 +50,7 @@ private:
    U32 mCurrTick;
 
    bool mGlobalLayer;
+
 public:
    SubScene();
    virtual ~SubScene();
@@ -71,6 +75,9 @@ public:
    //void onEditorDisable() override;
    void inspectPostApply() override;
 
+   void setTransform(const MatrixF& mat) override;
+   void setRenderTransform(const MatrixF& mat) override;
+
    bool testBox(const Box3F& testBox);
    bool evaluateCondition();
    void _onSelected() override;

+ 12 - 0
Engine/source/console/simObject.cpp

@@ -101,6 +101,8 @@ SimObjectId SimObject::smForcedId = 0;
 bool SimObject::preventNameChanging = false;
 
 IMPLEMENT_CALLBACK(SimObject, onInspectPostApply, void, (SimObject* obj), (obj), "Generic callback for when an object is edited");
+IMPLEMENT_CALLBACK(SimObject, onSelected, void, (SimObject* obj), (obj), "Generic callback for when an object is selected");
+IMPLEMENT_CALLBACK(SimObject, onUnselected, void, (SimObject* obj), (obj), "Generic callback for when an object is un-selected");
 
 namespace Sim
 {
@@ -527,6 +529,14 @@ bool SimObject::save(const char *pcFileName, bool bOnlySelected, const char *pre
 
 }
 
+bool SimObject::saveAppend(const char* pcFileName, bool bOnlySelected, const char* preappend)
+{
+   
+
+   return true;
+
+}
+
 //-----------------------------------------------------------------------------
 
 SimPersistID* SimObject::getOrCreatePersistentId()
@@ -2207,11 +2217,13 @@ void SimObject::setSelected( bool sel )
    {
       mFlags.set( Selected );
       _onSelected();
+      onSelected_callback(this);
    }
    else
    {
       mFlags.clear( Selected );
       _onUnselected();
+      onUnselected_callback(this);
    }
 }
 

+ 3 - 0
Engine/source/console/simObject.h

@@ -579,6 +579,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
 
       /// Save object as a TorqueScript File.
       virtual bool save( const char* pcFilePath, bool bOnlySelected = false, const char *preappend = NULL );
+      virtual bool saveAppend(const char* pcFilePath, bool bOnlySelected = false, const char* preappend = NULL);
 
       /// Check if a method exists in the objects current namespace.
       virtual bool isMethod( const char* methodName );
@@ -981,6 +982,8 @@ class SimObject: public ConsoleObject, public TamlCallbacks
       
       DECLARE_CONOBJECT( SimObject );
       DECLARE_CALLBACK(void, onInspectPostApply, (SimObject* obj));
+      DECLARE_CALLBACK(void, onSelected, (SimObject* obj));
+      DECLARE_CALLBACK(void, onUnselected, (SimObject* obj));
       
       static SimObject* __findObject( const char* id ) { return Sim::findObject( id ); }
       static const char* __getObjectId( ConsoleObject* object )

+ 19 - 19
Templates/BaseGame/game/tools/levels/DefaultEditorLevel.mis

@@ -1,33 +1,20 @@
 //--- OBJECT WRITE BEGIN ---
 new Scene(EditorTemplateLevel) {
-   canSave = "1";
-   canSaveDynamicFields = "1";
-      Enabled = "1";
+   isEditing = "1";
+      enabled = "1";
 
    new LevelInfo(theLevelInfo) {
-      nearClip = "0.1";
-      visibleDistance = "1000";
-      visibleGhostDistance = "0";
-      decalBias = "0.0015";
-      fogColor = "0.6 0.6 0.7 1";
-      fogDensity = "0";
+      FogColor = "0.6 0.6 0.7 1";
       fogDensityOffset = "700";
-      fogAtmosphereHeight = "0";
       canvasClearColor = "0 0 0 255";
-      ambientLightBlendPhase = "1";
-      ambientLightBlendCurve = "0 0 -1 -1";
       soundAmbience = "AudioAmbienceDefault";
-      soundDistanceModel = "Linear";
-      canSave = "1";
-      canSaveDynamicFields = "1";
-         Enabled = "1";
+         enabled = "1";
    };
    new ScatterSky(DynamicSky) {
       sunScale = "0.991102 0.921582 0.83077 1";
       zOffset = "-3000";
       azimuth = "25";
       brightness = "5";
-      flareType = "LightFlareExample1";
       MoonMatAsset = "Core_Rendering:moon_wglow";
       useNightCubemap = "1";
       nightCubemap = "nightCubemap";
@@ -44,16 +31,29 @@ new Scene(EditorTemplateLevel) {
       persistentId = "289ad401-3140-11ed-aae8-c0cb519281fc";
          reflectionPath = "tools/levels/DefaultEditorLevel/probes/";
    };
-   
    new GroundPlane() {
       scaleU = "32";
       scaleV = "32";
       MaterialAsset = "Prototyping:FloorGray";
-         Enabled = "1";
+         enabled = "1";
          position = "0 0 0";
          rotation = "1 0 0 0";
          scale = "1 1 1";
    };
+   new SubScene() {
+      LevelAsset = "Prototyping:PrefabTestSubScene";
+      position = "4.38205 -5.66842 1.53303";
+      scale = "33.0705 24.1137 4.59909";
+   };
+   new Trigger() {
+      dataBlock = "DefaultTrigger";
+      position = "0 0 -7.19786";
+      scale = "15.3957 15.3957 15.3957";
+         firstDataCheck = "1";
+   };
+   new Prefab() {
+      fileName = "data/Prototyping/prefabs/testPrefab.prefab";
+   };
 };
 //--- OBJECT WRITE END ---
 

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

@@ -42,7 +42,7 @@ $guiContent = new GuiControl() {
       minSize = "50 50";
       EdgeSnap = false;
       text = "";
-      class = "EWToolsPaletteWindowClass";
+      class = "ButtonPalette"; 
       
       new GuiDynamicCtrlArrayControl(ToolsPaletteArray) {
          canSaveDynamicFields = "0";

+ 3 - 0
Templates/BaseGame/game/tools/worldEditor/main.tscript

@@ -69,6 +69,7 @@ function initializeWorldEditor()
    exec("./scripts/probeBake.ed." @ $TorqueScriptFileExtension);
    exec("./scripts/visibility/visibilityLayer.ed." @ $TorqueScriptFileExtension);
    exec("./scripts/visibility/probeViz." @ $TorqueScriptFileExtension);
+   exec("./scripts/buttonPalette." @ $TorqueScriptFileExtension);
    
    exec("tools/gui/postFxEditor." @ $TorqueScriptFileExtension );
    exec("tools/gui/renderTargetVisualizer.ed." @ $TorqueScriptFileExtension);
@@ -77,6 +78,8 @@ function initializeWorldEditor()
    loadDirectory(expandFilename("./scripts/editors"));
    loadDirectory(expandFilename("./scripts/interfaces"));
    
+   exec("./scripts/interfaces/subSceneEditing.tscript");
+   
    // Create the default editor plugins before calling buildMenus.
       
    new ScriptObject( WorldEditorPlugin )

+ 23 - 4
Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript

@@ -1069,11 +1069,13 @@ function WorldEditorInspectorPlugin::onWorldEditorStartup( %this )
    //connect editor windows
    GuiWindowCtrl::attach( EWInspectorWindow, EWTreeWindow);
    
-   %map = new ActionMap();   
+   %map = new ActionMap(); 
+   
+   /*   
    %map.bindCmd( keyboard, "1", "EWorldEditorNoneModeBtn.performClick();", "" );  // Select
    %map.bindCmd( keyboard, "2", "EWorldEditorMoveModeBtn.performClick();", "" );  // Move
    %map.bindCmd( keyboard, "3", "EWorldEditorRotateModeBtn.performClick();", "" );  // Rotate
-   %map.bindCmd( keyboard, "4", "EWorldEditorScaleModeBtn.performClick();", "" );  // Scale
+   %map.bindCmd( keyboard, "4", "EWorldEditorScaleModeBtn.performClick();", "" );  // Scale*/
    %map.bindCmd( keyboard, "f", "FitToSelectionBtn.performClick();", "" );// Fit Camera to Selection
    %map.bindCmd( keyboard, "z", "EditorGuiStatusBar.setCamera(\"Standard Camera\");", "" );// Free camera
    %map.bindCmd( keyboard, "n", "ToggleNodeBar->renderHandleBtn.performClick();", "" );// Render Node
@@ -1093,21 +1095,38 @@ function WorldEditorInspectorPlugin::onWorldEditorStartup( %this )
 function WorldEditorInspectorPlugin::onActivated( %this )
 {   
    Parent::onActivated( %this );
+   
+   //Clears the button pallete stack
+   EWToolsPaletteWindow.setStackCtrl(ToolsPaletteArray); //legacy ctrl adhereance
+   EWToolsPaletteWindow.clearButtons();
+   
+   EWToolsPaletteWindow.setActionMap(WorldEditorInspectorPlugin.map);
+   
+   //Adds a button to the pallete stack
+                          //Name     Icon                         Click Command                         Tooltip text    Keybind
+   EWToolsPaletteWindow.addButton("Select", "ToolsModule:arrow_n_image", "EWorldEditorNoneModeBtn::onClick();", "", "Select Arrow", "1");
+   EWToolsPaletteWindow.addButton("Move", "ToolsModule:translate_n_image", "EWorldEditorMoveModeBtn::onClick();", "", "Move Selection", "2");
+   EWToolsPaletteWindow.addButton("Rotate", "ToolsModule:rotate_n_image", "EWorldEditorRotateModeBtn::onClick();", "", "Rotate Selection", "3");
+   EWToolsPaletteWindow.addButton("Scale", "ToolsModule:Scale_n_image", "EWorldEditorScaleModeBtn::onClick();", "", "Scale Selection", "4");
+   
+   EWToolsPaletteWindow.refresh();
 
    EditorGui-->InspectorWindow.setVisible( true );   
    EditorGui-->TreeWindow.setVisible( true );
    EditorGui-->WorldEditorToolbar.setVisible( true );
-   %this.map.push();
+   //%this.map.push();
 }
 
 function WorldEditorInspectorPlugin::onDeactivated( %this )
 {   
    Parent::onDeactivated( %this );
+   
+   EWToolsPaletteWindow.popActionMap();
 
    EditorGui-->InspectorWindow.setVisible( false );  
    EditorGui-->TreeWindow.setVisible( false ); 
    EditorGui-->WorldEditorToolbar.setVisible( false );
-   %this.map.pop();
+   //%this.map.pop();
 }
 
 function WorldEditorInspectorPlugin::onEditMenuSelect( %this, %editMenu )

+ 160 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/buttonPalette.tscript

@@ -0,0 +1,160 @@
+function ButtonPalette::setStackCtrl(%this, %ctrl)
+{
+   %this.stackCtrl = %ctrl;
+}
+
+function ButtonPalette::getStackCtrl(%this)
+{
+   if(isObject(%this.stackCtrl))
+      return %this.stackCtrl;
+   else
+      return %this;
+}
+
+function ButtonPalette::setActionMap(%this, %actionMap)
+{
+   %this.actionMap = %actionMap;
+   %this.actionMap.push();
+}
+
+function ButtonPalette::getActionMap(%this)
+{
+   return %this.actionMap;
+}
+
+function ButtonPalette::popActionMap(%this, %actionMap)
+{
+   %this.actionMap.pop();
+}
+
+function ButtonPalette::clearButtons(%this)
+{
+   %stackCtrl = %this.getStackCtrl();
+   %stackCtrl.clear();
+   
+   for(%i=0; %i < %this.numButtons; %i++)
+   {
+      if(isObject(%this.actionMap))
+      {
+         %this.actionMap.unbind("keyboard", getField(%this.buttons[%i], 5));
+      }
+      
+      %this.buttons[%i] = "";
+   }
+   
+   %this.numButtons = 0;
+}
+
+ //Name, Icon, Click Command, Variable, Tooltip text, Keybind
+function ButtonPalette::addButton(%this, %name, %iconAsset, %command, %syncVariable, %toolTip, %keybind)
+{    
+   if(%this.numButtons $= "")
+      %this.numButtons = 0;
+      
+   for(%i=0; %i < %this.numButtons; %i++)
+   {
+      %buttonInfo = %this.buttons[%i];
+      
+      //echo("Testing button info: " @ getField(%buttonInfo, 0) @ " against new button name: " @ %name);
+      if(getField(%buttonInfo, 0) $= %name) //no duplicates
+         return;
+   }
+      
+   %this.buttons[%this.numButtons] = %name TAB %iconAsset TAB %command TAB %syncVariable TAB %toolTip TAB %keybind;
+
+   %this.numButtons++;
+}
+
+function ButtonPalette::removeButton(%this, %name)
+{
+   %found = false;
+   for(%i=0; %i < %this.numButtons; %i++)
+   {
+      if(getField(%this.buttons[%i], 0) $= %name)
+      {
+         %found = true;
+         
+         if(isObject(%this.actionMap))
+         {
+            %this.actionMap.unbind("keyboard", getField(%this.buttons[%i], 5));
+         }
+      }
+      
+      if(%found)
+      {
+         %this.buttons[%i] = %this.buttons[%i+1];
+      }
+   }
+   
+   if(%found)
+      %this.numButtons--;
+      
+   return %found;
+}
+
+function ButtonPalette::findButton(%this, %name)
+{
+   %stackCtrl = %this.getStackCtrl();
+   for(%i=0; %i < %stackCtrl.getCount(); %i++)
+   {
+      %btnObj = %stackCtrl.getObject(%i);
+      
+      if(%btnObj.buttonName $= %name)
+         return %btnObj; 
+   }
+   
+   return 0;
+}
+
+function ButtonPalette::refresh(%this)
+{
+   %stackCtrl = %this.getStackCtrl();
+   %stackCtrl.clear();
+   
+   %this.visible = true;
+   %extents = "25 25";
+   
+   if(%this.numButtons == 0)
+   {
+      %this.visible = false;
+      return;  
+   }
+   
+   for(%i=0; %i < %this.numButtons; %i++)
+   {
+      %buttonInfo = %this.buttons[%i];
+      
+      %paletteButton = new GuiBitmapButtonCtrl() {
+         canSaveDynamicFields = "0";
+         internalName = getField(%buttonInfo, 0) @ "_paletteButton";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "ToolsGuiButtonProfile";
+         HorizSizing = "right";
+         VertSizing = "bottom";
+         Position = "0 0";
+         Extent = "25 19";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         tooltipprofile = "ToolsGuiToolTipProfile";
+         ToolTip = getField(%buttonInfo, 4) SPC "(" @ getField(%buttonInfo, 5) @ ")";
+         hovertime = "1000";
+         bitmapAsset = getField(%buttonInfo, 1);
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         buttonName = getField(%buttonInfo, 0);
+         command = getField(%buttonInfo, 2);
+         variable = getField(%buttonInfo, 3);
+      };
+      
+      %extents.y += 23;
+      
+      if(isObject(%this.actionMap))
+         %this.actionMap.bindCmd( keyboard, getField(%buttonInfo, 5), %paletteButton @ ".performClick();", "" ); 
+      
+      %stackCtrl.add(%paletteButton);
+   }
+   
+   %this.extent.y = %extents.y;
+}

+ 59 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/subSceneEditing.tscript

@@ -0,0 +1,59 @@
+function SubScene::onSelected(%this)
+{
+   echo("SELECTED SUBSCENE");
+   
+   %moveButton = EWToolsPaletteWindow.findButton("Move");
+   %rotateButton = EWToolsPaletteWindow.findButton("Rotate");
+   
+   %moveButton.originalCommand = %moveButton.command;
+   %moveButton.command = "SubSceneMoveModeBtn::onClick();";
+   
+   %rotateButton.originalCommand = %rotateButton.command;
+   %rotateButton.command = "SubSceneRotateModeBtn::onClick();";
+   
+   EWToolsPaletteWindow.addButton("SubSceneMove", "ToolsModule:translate_n_image", "SubSceneChildMoveModeBtn::onClick();", "", "Move SubScene + Children", "1");
+   EWToolsPaletteWindow.addButton("SubSceneRotate", "ToolsModule:rotate_n_image", "SubSceneChildRotateModeBtn::onClick();", "", "Rotate SubScene + Children", "2");
+   
+   EWToolsPaletteWindow.refresh();
+}
+
+function SubScene::onUnselected(%this)
+{
+   echo("UN-SELECTED SUBSCENE");
+   EWToolsPaletteWindow.removeButton("SubSceneMove");
+   EWToolsPaletteWindow.removeButton("SubSceneRotate");
+   
+   %moveButton = EWToolsPaletteWindow.findButton("Move");
+   %rotateButton = EWToolsPaletteWindow.findButton("Rotate");
+   
+   %moveButton.command = %moveButton.originalCommand;
+   %rotateButton.command = %rotateButton.originalCommand;
+   
+   $SubScene::transformChildren = false;
+   
+   EWToolsPaletteWindow.refresh();
+}
+
+function SubSceneMoveModeBtn::onClick(%this)
+{
+   EWorldEditorMoveModeBtn::onClick();
+   $SubScene::transformChildren = false;
+}
+
+function SubSceneRotateModeBtn::onClick(%this)
+{
+   EWorldEditorRotateModeBtn::onClick();
+   $SubScene::transformChildren = false;
+}
+
+function SubSceneChildMoveModeBtn::onClick()
+{
+   EWorldEditorMoveModeBtn::onClick();
+   $SubScene::transformChildren = true;
+}
+
+function SubSceneChildRotateModeBtn::onClick()
+{
+   EWorldEditorRotateModeBtn::onClick();
+   $SubScene::transformChildren = true;
+}