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
This commit is contained in:
JeffR 2024-11-05 20:14:36 -06:00
parent 10d1aeca1f
commit e2d0cc1981
11 changed files with 318 additions and 25 deletions

View file

@ -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;

View file

@ -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())

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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 )

View file

@ -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 ---

View file

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

View file

@ -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 )

View file

@ -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 )

View file

@ -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;
}

View file

@ -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;
}