You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
977 lines
36 KiB
C++
977 lines
36 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
#include <precompiled.h>
|
|
|
|
#include <QAction>
|
|
#include <QCompleter>
|
|
#include <QEvent>
|
|
#include <QGraphicsScene>
|
|
#include <QGraphicsView>
|
|
#include <QAction>
|
|
#include <QMenu>
|
|
#include <QMessageBox>
|
|
#include <QScopedValueRollback>
|
|
#include <QLineEdit>
|
|
#include <QTimer>
|
|
#include <QPushButton>
|
|
#include <QHeaderView>
|
|
|
|
#include <AzCore/Component/ComponentApplication.h>
|
|
#include <AzCore/RTTI/BehaviorContext.h>
|
|
#include <AzCore/UserSettings/UserSettings.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzToolsFramework/Entity/EditorEntityContextPickingBus.h>
|
|
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
|
|
|
#include <GraphCanvas/Components/VisualBus.h>
|
|
#include <GraphCanvas/Components/SceneBus.h>
|
|
#include <GraphCanvas/Components/StyleBus.h>
|
|
|
|
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
|
|
#include <Editor/View/Widgets/VariablePanel/ui_VariableDockWidget.h>
|
|
|
|
#include <Data/Data.h>
|
|
|
|
#include <Editor/Assets/ScriptCanvasAssetTrackerBus.h>
|
|
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
|
|
#include <Editor/QtMetaTypes.h>
|
|
#include <Editor/Settings.h>
|
|
#include <Editor/Translation/TranslationHelper.h>
|
|
#include <Editor/View/Widgets/DataTypePalette/DataTypePaletteModel.h>
|
|
#include <Editor/View/Widgets/NodePalette/VariableNodePaletteTreeItemTypes.h>
|
|
#include <Editor/View/Widgets/PropertyGridBus.h>
|
|
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
|
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
|
|
|
|
#include <ScriptCanvas/Core/NodeBus.h>
|
|
#include <ScriptCanvas/Data/DataRegistry.h>
|
|
#include <ScriptCanvas/Execution/RuntimeBus.h>
|
|
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
|
|
#include <ScriptCanvas/Asset/RuntimeAsset.h>
|
|
|
|
namespace ScriptCanvasEditor
|
|
{
|
|
////////////////////////////////
|
|
// VariablePropertiesComponent
|
|
////////////////////////////////
|
|
|
|
void VariablePropertiesComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
|
if (serializeContext)
|
|
{
|
|
serializeContext->Class<VariablePropertiesComponent, GraphCanvas::GraphCanvasPropertyComponent>()
|
|
->Version(1)
|
|
->Field("VariableName", &VariablePropertiesComponent::m_variableName)
|
|
->Field("VariableDatum", &VariablePropertiesComponent::m_variable)
|
|
;
|
|
|
|
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
|
if (editContext)
|
|
{
|
|
editContext->Class<VariablePropertiesComponent>("Variable Properties", "")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "Properties")
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
|
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &VariablePropertiesComponent::GetTitle)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &VariablePropertiesComponent::m_variableName, "Name", "")
|
|
->Attribute(AZ::Edit::Attributes::StringLineEditingCompleteNotify, &VariablePropertiesComponent::OnNameChanged)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &VariablePropertiesComponent::m_variable, "Datum", "")
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
AZ::Entity* VariablePropertiesComponent::CreateVariablePropertiesEntity()
|
|
{
|
|
AZ::Entity* entity = aznew AZ::Entity("VariablePropertiesHelper");
|
|
|
|
entity->CreateComponent<VariablePropertiesComponent>();
|
|
|
|
return entity;
|
|
}
|
|
|
|
VariablePropertiesComponent::VariablePropertiesComponent()
|
|
: m_variableName(AZStd::string())
|
|
, m_variable(nullptr)
|
|
, m_componentTitle("Variable")
|
|
{
|
|
}
|
|
|
|
const char* VariablePropertiesComponent::GetTitle()
|
|
{
|
|
return m_componentTitle.c_str();
|
|
}
|
|
|
|
void VariablePropertiesComponent::SetVariable(ScriptCanvas::GraphVariable* variable)
|
|
{
|
|
if (variable)
|
|
{
|
|
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
|
|
|
|
m_variable = variable;
|
|
m_componentTitle.clear();
|
|
m_variableName.clear();
|
|
|
|
m_variableName = m_variable->GetVariableName();
|
|
|
|
const AZStd::string variableTypeName = TranslationHelper::GetSafeTypeName(m_variable->GetDatum()->GetType());
|
|
m_variable->SetDisplayName(variableTypeName);
|
|
|
|
m_componentTitle = AZStd::string::format("%s Variable", variableTypeName.data());
|
|
|
|
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(m_variable->GetGraphScopedId());
|
|
|
|
m_scriptCanvasGraphId = m_variable->GetGraphScopedId().m_scriptCanvasId;
|
|
}
|
|
}
|
|
|
|
void VariablePropertiesComponent::OnNameChanged()
|
|
{
|
|
if (m_variable == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
|
|
|
|
AZ::Outcome<void, AZStd::string> outcome = AZ::Failure(AZStd::string());
|
|
AZStd::string_view oldVariableName = m_variable->GetVariableName();
|
|
|
|
if (oldVariableName != m_variableName)
|
|
{
|
|
ScriptCanvas::VariableRequestBus::EventResult(outcome, m_variable->GetGraphScopedId(), &ScriptCanvas::VariableRequests::RenameVariable, m_variableName);
|
|
|
|
AZ_Warning("VariablePropertiesComponent", outcome.IsSuccess(), "Could not rename variable: %s", outcome.GetError().c_str());
|
|
if (!outcome.IsSuccess())
|
|
{
|
|
// Revert the variable name if we couldn't rename it (e.g. not unique)
|
|
m_variableName = oldVariableName;
|
|
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
|
|
}
|
|
else
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
|
|
}
|
|
}
|
|
|
|
ScriptCanvas::VariableNotificationBus::Handler::BusConnect(m_variable->GetGraphScopedId());
|
|
}
|
|
|
|
void VariablePropertiesComponent::OnVariableRemoved()
|
|
{
|
|
ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect();
|
|
|
|
m_variableName = AZStd::string();
|
|
m_variable = nullptr;
|
|
}
|
|
|
|
void VariablePropertiesComponent::OnVariableValueChanged()
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
|
|
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
|
|
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues);
|
|
}
|
|
|
|
void VariablePropertiesComponent::OnVariableRenamed(AZStd::string_view variableName)
|
|
{
|
|
m_variableName = variableName;
|
|
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
|
|
}
|
|
|
|
void VariablePropertiesComponent::OnVariableScopeChanged()
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasGraphId);
|
|
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::RefreshPropertyGrid);
|
|
}
|
|
|
|
/////////////////////////////
|
|
// VariablePanelContextMenu
|
|
/////////////////////////////
|
|
|
|
VariablePanelContextMenu::VariablePanelContextMenu(VariableDockWidget* dockWidget, const ScriptCanvas::ScriptCanvasId& scriptCanvasId, ScriptCanvas::VariableId varId)
|
|
: QMenu()
|
|
{
|
|
AZ::EntityId graphCanvasGraphId;
|
|
GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &GeneralRequests::GetGraphCanvasGraphId, scriptCanvasId);
|
|
|
|
AZStd::string variableName;
|
|
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(variableName, scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::GetVariableName, varId);
|
|
|
|
QAction* getAction = new QAction(QObject::tr("Get %1").arg(variableName.c_str()), this);
|
|
getAction->setToolTip(QObject::tr("Adds a Get %1 variable node onto the active graph.").arg(variableName.c_str()));
|
|
getAction->setStatusTip(QObject::tr("Adds a Get %1 variable node onto the active graph.").arg(variableName.c_str()));
|
|
|
|
QObject::connect(getAction,
|
|
&QAction::triggered,
|
|
[graphCanvasGraphId, varId](bool)
|
|
{
|
|
CreateGetVariableNodeMimeEvent mimeEvent(varId);
|
|
|
|
AZ::EntityId viewId;
|
|
GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
|
|
|
|
AZ::Vector2 viewCenter;
|
|
GraphCanvas::ViewRequestBus::EventResult(viewCenter, viewId, &GraphCanvas::ViewRequests::GetViewSceneCenter);
|
|
|
|
mimeEvent.ExecuteEvent(viewCenter, viewCenter, graphCanvasGraphId);
|
|
});
|
|
|
|
QAction* setAction = new QAction(QObject::tr("Set %1").arg(variableName.c_str()), this);
|
|
setAction->setToolTip(QObject::tr("Adds a Set %1 variable node onto the active graph.").arg(variableName.c_str()));
|
|
setAction->setStatusTip(QObject::tr("Adds a Set %1 variable node onto the active graph.").arg(variableName.c_str()));
|
|
|
|
QObject::connect(setAction,
|
|
&QAction::triggered,
|
|
[graphCanvasGraphId, varId](bool)
|
|
{
|
|
CreateSetVariableNodeMimeEvent mimeEvent(varId);
|
|
|
|
AZ::EntityId viewId;
|
|
GraphCanvas::SceneRequestBus::EventResult(viewId, graphCanvasGraphId, &GraphCanvas::SceneRequests::GetViewId);
|
|
|
|
AZ::Vector2 viewCenter;
|
|
GraphCanvas::ViewRequestBus::EventResult(viewCenter, viewId, &GraphCanvas::ViewRequests::GetViewSceneCenter);
|
|
|
|
mimeEvent.ExecuteEvent(viewCenter, viewCenter, graphCanvasGraphId);
|
|
});
|
|
|
|
QAction* copyAction = new QAction(QObject::tr("Copy %1").arg(variableName.c_str()), this);
|
|
copyAction->setToolTip(QObject::tr("Copies the variable called - %1").arg(variableName.c_str()));
|
|
copyAction->setStatusTip(QObject::tr("Copies the variable called - %1").arg(variableName.c_str()));
|
|
|
|
QObject::connect(copyAction,
|
|
&QAction::triggered,
|
|
[dockWidget, varId](bool)
|
|
{
|
|
GraphVariablesTableView::CopyVariableToClipboard(dockWidget->GetActiveScriptCanvasId(), varId);
|
|
});
|
|
|
|
QAction* pasteAction = new QAction(QObject::tr("Paste").arg(variableName.c_str()), this);
|
|
pasteAction->setToolTip(QObject::tr("Pastes the variable currently on the clipboard").arg(variableName.c_str()));
|
|
pasteAction->setStatusTip(QObject::tr("Pastes the variable currently on the clipboard").arg(variableName.c_str()));
|
|
|
|
pasteAction->setEnabled(GraphVariablesTableView::HasCopyVariableData());
|
|
|
|
QObject::connect(pasteAction,
|
|
&QAction::triggered,
|
|
[dockWidget, varId](bool)
|
|
{
|
|
GraphVariablesTableView::HandleVariablePaste(dockWidget->GetActiveScriptCanvasId());
|
|
});
|
|
|
|
QAction* duplicateAction = new QAction(QObject::tr("Duplicate %1").arg(variableName.c_str()), this);
|
|
duplicateAction->setToolTip(QObject::tr("Duplicates the variable called - %1").arg(variableName.c_str()));
|
|
duplicateAction->setStatusTip(QObject::tr("Duplicates the variable called - %1").arg(variableName.c_str()));
|
|
|
|
QObject::connect(duplicateAction,
|
|
&QAction::triggered,
|
|
[dockWidget, varId](bool)
|
|
{
|
|
dockWidget->OnDuplicateVariable(varId);
|
|
});
|
|
|
|
QAction* deleteAction = new QAction(QObject::tr("Delete %1").arg(variableName.c_str()), this);
|
|
deleteAction->setToolTip(QObject::tr("Deletes the variable called - %1").arg(variableName.c_str()));
|
|
deleteAction->setStatusTip(QObject::tr("Deletes the variable called - %1").arg(variableName.c_str()));
|
|
|
|
QObject::connect(deleteAction,
|
|
&QAction::triggered,
|
|
[dockWidget, varId](bool)
|
|
{
|
|
AZStd::unordered_set< ScriptCanvas::VariableId > variableIds = { varId };
|
|
dockWidget->OnDeleteVariables(variableIds);
|
|
});
|
|
|
|
|
|
|
|
addAction(getAction);
|
|
addAction(setAction);
|
|
addSeparator();
|
|
addAction(copyAction);
|
|
addAction(pasteAction);
|
|
addAction(duplicateAction);
|
|
addAction(deleteAction);
|
|
}
|
|
|
|
///////////////////////
|
|
// VariableDockWidget
|
|
///////////////////////
|
|
|
|
AZStd::string VariableDockWidget::ConstructDefaultVariableName(AZ::u32 variableCounter)
|
|
{
|
|
return AZStd::string::format("Variable %u", variableCounter);
|
|
}
|
|
|
|
AZStd::string VariableDockWidget::FindDefaultVariableName(const ScriptCanvas::ScriptCanvasId& scriptCanvasExecutionId)
|
|
{
|
|
ScriptCanvas::VariableValidationOutcome nameAvailable = AZ::Failure(ScriptCanvas::GraphVariableValidationErrorCode::Unknown);
|
|
AZStd::string varName;
|
|
|
|
do
|
|
{
|
|
AZ::u32 varCounter = 0;
|
|
SceneCounterRequestBus::EventResult(varCounter, scriptCanvasExecutionId, &SceneCounterRequests::GetNewVariableCounter);
|
|
|
|
varName = ConstructDefaultVariableName(varCounter);
|
|
|
|
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, scriptCanvasExecutionId, &ScriptCanvas::GraphVariableManagerRequests::IsNameValid, varName);
|
|
} while (!nameAvailable);
|
|
|
|
return varName;
|
|
}
|
|
|
|
VariableDockWidget::VariableDockWidget(QWidget* parent /*= nullptr*/)
|
|
: AzQtComponents::StyledDockWidget(parent)
|
|
, m_manipulatingSelection(false)
|
|
, ui(new Ui::VariableDockWidget())
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
ui->graphVariables->setContentsMargins(0, 0, 0, 0);
|
|
ui->graphVariables->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
QObject::connect(ui->graphVariables, &GraphVariablesTableView::SelectionChanged, this, &VariableDockWidget::OnSelectionChanged);
|
|
QObject::connect(ui->graphVariables, &QWidget::customContextMenuRequested, this, &VariableDockWidget::OnContextMenuRequested);
|
|
|
|
ui->searchFilter->setClearButtonEnabled(true);
|
|
QObject::connect(ui->searchFilter, &QLineEdit::textChanged, this, &VariableDockWidget::OnQuickFilterChanged);
|
|
QObject::connect(ui->searchFilter, &QLineEdit::returnPressed, this, &VariableDockWidget::OnReturnPressed);
|
|
|
|
// Tell the widget to auto create our context menu, for now
|
|
setContextMenuPolicy(Qt::ActionsContextMenu);
|
|
|
|
// Add button is disabled by default, since we don't want to switch panels until we have an active scene.
|
|
connect(ui->addButton, &QPushButton::clicked, this, &VariableDockWidget::OnAddVariableButton);
|
|
|
|
ui->addButton->setEnabled(false);
|
|
ui->searchFilter->setEnabled(false);
|
|
|
|
QObject::connect(ui->variablePalette, &VariablePaletteTableView::CreateVariable, this, &VariableDockWidget::OnCreateVariable);
|
|
QObject::connect(ui->variablePalette, &VariablePaletteTableView::CreateNamedVariable, this, &VariableDockWidget::OnCreateNamedVariable);
|
|
QObject::connect(ui->graphVariables, &GraphVariablesTableView::DeleteVariables, this, &VariableDockWidget::OnDeleteVariables);
|
|
|
|
m_filterTimer.setInterval(250);
|
|
m_filterTimer.setSingleShot(true);
|
|
m_filterTimer.stop();
|
|
|
|
QObject::connect(&m_filterTimer, &QTimer::timeout, this, &VariableDockWidget::UpdateFilter);
|
|
|
|
GraphCanvas::AssetEditorNotificationBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
|
|
|
|
ShowGraphVariables();
|
|
|
|
VariableAutomationRequestBus::Handler::BusConnect();
|
|
}
|
|
|
|
VariableDockWidget::~VariableDockWidget()
|
|
{
|
|
GraphCanvas::AssetEditorNotificationBus::Handler::BusDisconnect();
|
|
VariableAutomationRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void VariableDockWidget::PopulateVariablePalette(const AZStd::unordered_set< AZ::Uuid >& objectTypes)
|
|
{
|
|
ui->variablePalette->PopulateVariablePalette(objectTypes);
|
|
}
|
|
|
|
void VariableDockWidget::OnActiveGraphChanged(const GraphCanvas::GraphId& graphCanvasGraphId)
|
|
{
|
|
ClearFilter();
|
|
|
|
m_graphCanvasGraphId = graphCanvasGraphId;
|
|
|
|
m_scriptCanvasId.SetInvalid();
|
|
GeneralRequestBus::BroadcastResult(m_scriptCanvasId, &GeneralRequests::GetScriptCanvasId, graphCanvasGraphId);
|
|
|
|
ui->graphVariables->SetActiveScene(m_scriptCanvasId);
|
|
ui->variablePalette->SetActiveScene(m_scriptCanvasId);
|
|
|
|
ui->addButton->setEnabled(m_scriptCanvasId.IsValid());
|
|
ui->searchFilter->setEnabled(m_scriptCanvasId.IsValid());
|
|
|
|
ShowGraphVariables();
|
|
}
|
|
|
|
AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetPrimitiveTypes() const
|
|
{
|
|
AZStd::vector< ScriptCanvas::Data::Type > primitiveTypes;
|
|
|
|
auto variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
|
|
|
|
for (auto variableType : variableTypes)
|
|
{
|
|
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(variableType);
|
|
if (ScriptCanvas::Data::IsValueType(dataType))
|
|
{
|
|
primitiveTypes.push_back(dataType);
|
|
}
|
|
}
|
|
|
|
return primitiveTypes;
|
|
}
|
|
|
|
AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetBehaviorContextObjectTypes() const
|
|
{
|
|
AZStd::vector< ScriptCanvas::Data::Type > bcoTypes;
|
|
|
|
auto variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
|
|
|
|
for (auto variableType : variableTypes)
|
|
{
|
|
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(variableType);
|
|
if (!ScriptCanvas::Data::IsValueType(dataType))
|
|
{
|
|
if (!ScriptCanvas::Data::IsContainerType(dataType))
|
|
{
|
|
bcoTypes.emplace_back(dataType);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bcoTypes;
|
|
}
|
|
|
|
AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetMapTypes() const
|
|
{
|
|
AZStd::vector< ScriptCanvas::Data::Type > variableDataTypes;
|
|
|
|
auto mapTypes = ui->variablePalette->GetMapTypes();
|
|
|
|
for (auto mapType : mapTypes)
|
|
{
|
|
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(mapType);
|
|
variableDataTypes.emplace_back(dataType);
|
|
}
|
|
|
|
return variableDataTypes;
|
|
}
|
|
|
|
AZStd::vector< ScriptCanvas::Data::Type > VariableDockWidget::GetArrayTypes() const
|
|
{
|
|
AZStd::vector< ScriptCanvas::Data::Type > variableDataTypes;
|
|
|
|
auto arrayTypes = ui->variablePalette->GetArrayTypes();
|
|
|
|
for (auto arrayType : arrayTypes)
|
|
{
|
|
ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(arrayType);
|
|
variableDataTypes.emplace_back(dataType);
|
|
}
|
|
|
|
return variableDataTypes;
|
|
}
|
|
|
|
bool VariableDockWidget::IsShowingVariablePalette() const
|
|
{
|
|
return ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->variablePalettePage);
|
|
}
|
|
|
|
bool VariableDockWidget::IsShowingGraphVariables() const
|
|
{
|
|
return ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->graphVariablesPage);
|
|
}
|
|
|
|
QPushButton* VariableDockWidget::GetCreateVariableButton() const
|
|
{
|
|
return ui->addButton;
|
|
}
|
|
|
|
QTableView* VariableDockWidget::GetGraphPaletteTableView() const
|
|
{
|
|
return ui->graphVariables;
|
|
}
|
|
|
|
QTableView* VariableDockWidget::GetVariablePaletteTableView() const
|
|
{
|
|
return ui->variablePalette;
|
|
}
|
|
|
|
QLineEdit* VariableDockWidget::GetVariablePaletteFilter() const
|
|
{
|
|
return ui->searchFilter;
|
|
}
|
|
|
|
QLineEdit* VariableDockWidget::GetGraphVariablesFilter() const
|
|
{
|
|
return ui->searchFilter;
|
|
}
|
|
|
|
void VariableDockWidget::OnEscape()
|
|
{
|
|
ShowGraphVariables();
|
|
}
|
|
|
|
void VariableDockWidget::focusOutEvent(QFocusEvent* focusEvent)
|
|
{
|
|
AzQtComponents::StyledDockWidget::focusOutEvent(focusEvent);
|
|
|
|
if (ui->stackedWidget->currentIndex() == ui->stackedWidget->indexOf(ui->variablePalettePage))
|
|
{
|
|
ShowGraphVariables();
|
|
}
|
|
}
|
|
|
|
const ScriptCanvas::ScriptCanvasId& VariableDockWidget::GetActiveScriptCanvasId() const
|
|
{
|
|
return m_scriptCanvasId;
|
|
}
|
|
|
|
bool VariableDockWidget::IsValidVariableType(const ScriptCanvas::Data::Type& dataType) const
|
|
{
|
|
bool isValid = false;
|
|
|
|
AZ::Uuid azType = ScriptCanvas::Data::ToAZType(dataType);
|
|
|
|
if (ScriptCanvas::Data::IsMapContainerType(dataType))
|
|
{
|
|
auto mapTypes = ui->variablePalette->GetMapTypes();
|
|
|
|
auto findIter = AZStd::find(mapTypes.begin(), mapTypes.end(), azType);
|
|
|
|
isValid = findIter != mapTypes.end();
|
|
}
|
|
else if (ScriptCanvas::Data::IsVectorContainerType(dataType))
|
|
{
|
|
auto arrayTypes = ui->variablePalette->GetArrayTypes();
|
|
|
|
auto findIter = AZStd::find(arrayTypes.begin(), arrayTypes.end(), azType);
|
|
|
|
isValid = findIter != arrayTypes.end();
|
|
}
|
|
else
|
|
{
|
|
const auto& variableTypes = ui->variablePalette->GetVariableTypePaletteModel()->GetVariableTypes();
|
|
|
|
auto findIter = AZStd::find(variableTypes.begin(), variableTypes.end(), azType);
|
|
|
|
isValid = findIter != variableTypes.end();
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
void VariableDockWidget::ShowVariablePalette()
|
|
{
|
|
ui->stackedWidget->setCurrentIndex(ui->stackedWidget->indexOf(ui->variablePalettePage));
|
|
ClearFilter();
|
|
|
|
ui->searchFilter->setPlaceholderText("Variable Type...");
|
|
FocusOnSearchFilter();
|
|
|
|
ui->searchFilter->setCompleter(ui->variablePalette->GetVariableCompleter());
|
|
|
|
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
|
|
}
|
|
|
|
void VariableDockWidget::ShowGraphVariables()
|
|
{
|
|
ui->stackedWidget->setCurrentIndex(ui->stackedWidget->indexOf(ui->graphVariablesPage));
|
|
ClearFilter();
|
|
|
|
ui->variablePalette->clearSelection();
|
|
|
|
ui->searchFilter->setPlaceholderText("Search...");
|
|
|
|
ui->searchFilter->setCompleter(nullptr);
|
|
|
|
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void VariableDockWidget::FocusOnSearchFilter()
|
|
{
|
|
ui->searchFilter->setFocus(Qt::FocusReason::MouseFocusReason);
|
|
}
|
|
|
|
void VariableDockWidget::ClearFilter()
|
|
{
|
|
{
|
|
QSignalBlocker blocker(ui->searchFilter);
|
|
ui->searchFilter->setText("");
|
|
}
|
|
|
|
UpdateFilter();
|
|
}
|
|
|
|
void VariableDockWidget::UpdateFilter()
|
|
{
|
|
if (IsShowingGraphVariables())
|
|
{
|
|
ui->graphVariables->SetFilter(ui->searchFilter->text());
|
|
}
|
|
else if (IsShowingVariablePalette())
|
|
{
|
|
ui->variablePalette->SetFilter(ui->searchFilter->userInputText());
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnReturnPressed()
|
|
{
|
|
if (IsShowingVariablePalette())
|
|
{
|
|
ui->variablePalette->TryCreateVariableByTypeName(ui->searchFilter->text().toStdString().c_str());
|
|
}
|
|
else if (IsShowingGraphVariables())
|
|
{
|
|
UpdateFilter();
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnQuickFilterChanged(const QString& text)
|
|
{
|
|
if(text.isEmpty())
|
|
{
|
|
//If field was cleared, update immediately
|
|
UpdateFilter();
|
|
return;
|
|
}
|
|
m_filterTimer.stop();
|
|
m_filterTimer.start();
|
|
}
|
|
|
|
void VariableDockWidget::RefreshModel()
|
|
{
|
|
ui->graphVariables->SetActiveScene(m_scriptCanvasId);
|
|
}
|
|
|
|
void VariableDockWidget::OnAddVariableButton()
|
|
{
|
|
int index = ui->stackedWidget->currentIndex();
|
|
|
|
// Switch between pages
|
|
if (index == ui->stackedWidget->indexOf(ui->graphVariablesPage))
|
|
{
|
|
ShowVariablePalette();
|
|
}
|
|
else if(index == ui->stackedWidget->indexOf(ui->variablePalettePage))
|
|
{
|
|
ShowGraphVariables();
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnContextMenuRequested(const QPoint& pos)
|
|
{
|
|
AzToolsFramework::EditorPickModeRequestBus::Broadcast(&AzToolsFramework::EditorPickModeRequests::StopEntityPickMode);
|
|
|
|
QModelIndex index = ui->graphVariables->indexAt(pos);
|
|
|
|
QActionGroup actionGroup(this);
|
|
actionGroup.setExclusive(true);
|
|
|
|
QAction* sortByName = actionGroup.addAction("Sort by name");
|
|
sortByName->setCheckable(true);
|
|
|
|
QAction* sortByType = actionGroup.addAction("Sort by type");
|
|
sortByType->setCheckable(true);
|
|
|
|
AZStd::intrusive_ptr<EditorSettings::ScriptCanvasEditorSettings> settings = AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
|
|
|
|
if (settings->m_variablePanelSorting == GraphVariablesModel::ColumnIndex::Name)
|
|
{
|
|
sortByName->setChecked(true);
|
|
}
|
|
else
|
|
{
|
|
sortByType->setChecked(true);
|
|
}
|
|
|
|
QAction* cleanupAction = new QAction(QObject::tr("Remove unused variables"), this);
|
|
|
|
QAction* actionResult = nullptr;
|
|
|
|
// Bring up the context menu if the item is valid
|
|
if (index.row() > -1)
|
|
{
|
|
ScriptCanvas::VariableId varId = index.data(GraphVariablesModel::VarIdRole).value<ScriptCanvas::VariableId>();
|
|
|
|
VariablePanelContextMenu menu(this, m_scriptCanvasId, varId);
|
|
|
|
menu.addSeparator();
|
|
menu.addAction(cleanupAction);
|
|
menu.addSeparator();
|
|
menu.addAction(sortByName);
|
|
menu.addAction(sortByType);
|
|
|
|
|
|
actionResult = menu.exec(ui->graphVariables->mapToGlobal(pos));
|
|
}
|
|
else
|
|
{
|
|
QMenu menu;
|
|
|
|
menu.addAction(cleanupAction);
|
|
menu.addSeparator();
|
|
menu.addAction(sortByName);
|
|
menu.addAction(sortByType);
|
|
|
|
actionResult = menu.exec(ui->graphVariables->mapToGlobal(pos));
|
|
}
|
|
|
|
// Very likely the actions are dangling pointers here. Do not dereference them.
|
|
if (actionResult == sortByName)
|
|
{
|
|
settings->m_variablePanelSorting = GraphVariablesModel::ColumnIndex::Name;
|
|
ui->graphVariables->ApplyPreferenceSort();
|
|
}
|
|
else if (actionResult == sortByType)
|
|
{
|
|
settings->m_variablePanelSorting = GraphVariablesModel::ColumnIndex::Type;
|
|
ui->graphVariables->ApplyPreferenceSort();
|
|
}
|
|
else if (actionResult == cleanupAction)
|
|
{
|
|
OnRemoveUnusedVariables();
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnSelectionChanged(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
|
|
{
|
|
if (!variableIds.empty())
|
|
{
|
|
GraphCanvas::SceneRequestBus::Event(m_graphCanvasGraphId, &GraphCanvas::SceneRequests::ClearSelection);
|
|
|
|
AZStd::vector<ScriptCanvas::VariableId> deselectedVariableIds;
|
|
for (auto pair : m_usedElements)
|
|
{
|
|
if (variableIds.count(pair.first) == 0)
|
|
{
|
|
deselectedVariableIds.emplace_back(pair.first);
|
|
m_unusedPool.emplace_back(pair.second);
|
|
}
|
|
}
|
|
|
|
for (auto variableId : deselectedVariableIds)
|
|
{
|
|
ReleaseComponent(variableId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResetPool();
|
|
}
|
|
|
|
AZStd::vector<AZ::EntityId> selection;
|
|
|
|
ScriptCanvas::RuntimeRequests* runtimeRequests = ScriptCanvas::RuntimeRequestBus::FindFirstHandler(m_scriptCanvasId);
|
|
|
|
if (runtimeRequests == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (const ScriptCanvas::VariableId& varId : variableIds)
|
|
{
|
|
VariablePropertiesComponent* propertiesComponent = AllocateComponent(varId);
|
|
|
|
if (propertiesComponent)
|
|
{
|
|
ScriptCanvas::GraphVariable* graphVariable = runtimeRequests->FindVariableById(varId);;
|
|
propertiesComponent->SetVariable(graphVariable);
|
|
|
|
selection.push_back(propertiesComponent->GetEntityId());
|
|
}
|
|
}
|
|
|
|
OnHighlightVariables(variableIds);
|
|
Q_EMIT OnVariableSelectionChanged(selection);
|
|
}
|
|
|
|
void VariableDockWidget::OnDuplicateVariable(const ScriptCanvas::VariableId& variableId)
|
|
{
|
|
ScriptCanvas::GraphVariable* graphVariable = nullptr;
|
|
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, variableId);
|
|
|
|
if (graphVariable == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ScriptCanvas::GraphVariableManagerRequestBus::Event(m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::CloneVariable, (*graphVariable));
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
|
|
}
|
|
|
|
void VariableDockWidget::OnCreateVariable(ScriptCanvas::Data::Type varType)
|
|
{
|
|
AZStd::string varName = FindDefaultVariableName(m_scriptCanvasId);
|
|
OnCreateNamedVariable(varName, varType);
|
|
}
|
|
|
|
void VariableDockWidget::OnCreateNamedVariable(const AZStd::string& variableName, ScriptCanvas::Data::Type varType)
|
|
{
|
|
ShowGraphVariables();
|
|
ScriptCanvas::Datum datum(varType, ScriptCanvas::Datum::eOriginality::Original);
|
|
|
|
AZ::Outcome<ScriptCanvas::VariableId, AZStd::string> outcome = AZ::Failure(AZStd::string());
|
|
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum, false);
|
|
|
|
AZ_Warning("VariablePanel", outcome.IsSuccess(), "Could not create new variable: %s", outcome.GetError().c_str());
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
|
|
|
|
// We already provide a naming hook for container types so we don't need to do re-force them into it.
|
|
if (outcome.IsSuccess() && !ScriptCanvas::Data::IsContainerType(varType))
|
|
{
|
|
ui->graphVariables->EditVariableName(outcome.GetValue());
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnDeleteVariables(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
|
|
{
|
|
PropertyGridRequestBus::Broadcast(&PropertyGridRequests::ClearSelection);
|
|
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate);
|
|
|
|
bool result = false;
|
|
for (const ScriptCanvas::VariableId& variableId : variableIds)
|
|
{
|
|
if (CanDeleteVariable(variableId))
|
|
{
|
|
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(result, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::RemoveVariable, variableId);
|
|
AZ_Warning("VariablePanel", result, "Could not delete Variable Id (%s).", variableId.ToString().data());
|
|
|
|
if (result)
|
|
{
|
|
ReleaseComponent(variableId);
|
|
}
|
|
}
|
|
}
|
|
|
|
ui->graphVariables->ResizeColumns();
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate);
|
|
|
|
if (result)
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId);
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::OnHighlightVariables(const AZStd::unordered_set< ScriptCanvas::VariableId>& variableIds)
|
|
{
|
|
EditorGraphRequestBus::Event(m_scriptCanvasId, &EditorGraphRequests::HighlightVariables, variableIds);
|
|
}
|
|
|
|
void VariableDockWidget::OnRemoveUnusedVariables()
|
|
{
|
|
EditorGraphRequestBus::Event(m_scriptCanvasId, &EditorGraphRequests::RemoveUnusedVariables);
|
|
}
|
|
|
|
bool VariableDockWidget::CanDeleteVariable(const ScriptCanvas::VariableId& variableId)
|
|
{
|
|
bool canDeleteVariable = false;
|
|
|
|
AZStd::vector< NodeIdPair > nodeIds;
|
|
EditorGraphRequestBus::EventResult(nodeIds, m_scriptCanvasId, &EditorGraphRequests::GetVariableNodes, variableId);
|
|
|
|
if (!nodeIds.empty())
|
|
{
|
|
AZStd::string variableName;
|
|
ScriptCanvas::VariableRequestBus::EventResult(variableName, ScriptCanvas::GraphScopedVariableId(m_scriptCanvasId, variableId), &ScriptCanvas::VariableRequests::GetName);
|
|
|
|
int result = QMessageBox::warning(this, QString("Delete %1 and References").arg(variableName.c_str()), QString("The variable \"%1\" has %2 active references.\nAre you sure you want to delete the variable and its references from the graph?").arg(variableName.c_str()).arg(nodeIds.size()), QMessageBox::StandardButton::Yes, QMessageBox::StandardButton::Cancel);
|
|
|
|
if (result == QMessageBox::StandardButton::Yes)
|
|
{
|
|
canDeleteVariable = true;
|
|
|
|
AZStd::unordered_set< AZ::EntityId > memberIds;
|
|
memberIds.reserve(nodeIds.size());
|
|
|
|
AZStd::unordered_set< ScriptCanvas::VariableId > variableIds = { variableId };
|
|
|
|
for (auto memberPair : nodeIds)
|
|
{
|
|
bool removedReferences = false;
|
|
|
|
ScriptCanvas::NodeRequestBus::EventResult(removedReferences, memberPair.m_scriptCanvasId, &ScriptCanvas::NodeRequests::RemoveVariableReferences, variableIds);
|
|
|
|
// If we didn't remove the references. Just delete the node.
|
|
if (!removedReferences)
|
|
{
|
|
memberIds.insert(memberPair.m_graphCanvasId);
|
|
}
|
|
}
|
|
|
|
GraphCanvas::SceneRequestBus::Event(m_graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, memberIds);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
canDeleteVariable = true;
|
|
}
|
|
|
|
return canDeleteVariable;
|
|
}
|
|
|
|
VariablePropertiesComponent* VariableDockWidget::AllocateComponent(const ScriptCanvas::VariableId& variableId)
|
|
{
|
|
auto elementIter = m_usedElements.find(variableId);
|
|
|
|
if (elementIter != m_usedElements.end())
|
|
{
|
|
return elementIter->second;
|
|
}
|
|
|
|
if (!m_unusedPool.empty())
|
|
{
|
|
VariablePropertiesComponent* component = m_unusedPool.back();
|
|
m_unusedPool.pop_back();
|
|
|
|
m_usedElements[variableId] = component;
|
|
|
|
return component;
|
|
}
|
|
else
|
|
{
|
|
m_propertyHelpers.emplace_back(AZStd::unique_ptr<AZ::Entity>(VariablePropertiesComponent::CreateVariablePropertiesEntity()));
|
|
|
|
AZ::Entity* entity = m_propertyHelpers.back().get();
|
|
|
|
entity->Init();
|
|
entity->Activate();
|
|
|
|
VariablePropertiesComponent* component = AZ::EntityUtils::FindFirstDerivedComponent<VariablePropertiesComponent>(entity);
|
|
|
|
if (component)
|
|
{
|
|
m_usedElements[variableId] = component;
|
|
return component;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void VariableDockWidget::ReleaseComponent(const ScriptCanvas::VariableId& variableId)
|
|
{
|
|
auto mapIter = m_usedElements.find(variableId);
|
|
|
|
if (mapIter != m_usedElements.end())
|
|
{
|
|
m_unusedPool.emplace_back(mapIter->second);
|
|
m_usedElements.erase(mapIter);
|
|
}
|
|
}
|
|
|
|
void VariableDockWidget::ResetPool()
|
|
{
|
|
for (auto pair : m_usedElements)
|
|
{
|
|
m_unusedPool.emplace_back(pair.second);
|
|
}
|
|
|
|
m_usedElements.clear();
|
|
}
|
|
|
|
#include <Editor/View/Widgets/VariablePanel/moc_VariableDockWidget.cpp>
|
|
}
|
|
|