1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
650 lines
24 KiB
C++
650 lines
24 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include "CommandLine.h"
|
|
|
|
#include <QString>
|
|
#include <QKeyEvent>
|
|
#include <QCompleter>
|
|
#include <QGraphicsItem>
|
|
#include <QGraphicsView>
|
|
|
|
#include "Editor/View/Widgets/ui_CommandLine.h"
|
|
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
|
|
#include <Core/Attributes.h>
|
|
#include <Core/Node.h>
|
|
#include <AzFramework/StringFunc/StringFunc.h>
|
|
|
|
#include <Editor/Nodes/NodeCreateUtils.h>
|
|
#include <Editor/QtMetaTypes.h>
|
|
|
|
#include <ScriptCanvas/Bus/RequestBus.h>
|
|
|
|
#include <GraphCanvas/Components/SceneBus.h>
|
|
#include <GraphCanvas/Components/ViewBus.h>
|
|
#include <GraphCanvas/Components/GeometryBus.h>
|
|
|
|
namespace
|
|
{
|
|
using namespace ScriptCanvasEditor;
|
|
using namespace ScriptCanvasEditor::Widget;
|
|
|
|
void CreateSelectedNodes(CommandLine* commandLine,
|
|
AZStd::unique_ptr<Ui::CommandLine>& ui,
|
|
AZ::SerializeContext* serializeContext)
|
|
{
|
|
if (!ui->commandList->selectionModel())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (ui->commandList->selectionModel()->selectedIndexes().empty())
|
|
{
|
|
// Nothing selected.
|
|
return;
|
|
}
|
|
|
|
CommandListDataProxyModel* dataModel = qobject_cast<CommandListDataProxyModel*>(ui->commandList->model());
|
|
if (!dataModel)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ScriptCanvas::ScriptCanvasId scriptCanvasId;
|
|
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveScriptCanvasId);
|
|
|
|
AZ::EntityId graphCanvasGraphId;
|
|
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
|
|
|
|
if (!(scriptCanvasId.IsValid() &&
|
|
graphCanvasGraphId.IsValid()))
|
|
{
|
|
// Nothing active.
|
|
return;
|
|
}
|
|
|
|
|
|
// Create the nodes in a horizontal list at the top of the canvas.
|
|
AZ::Vector2 pos(20.0f, 20.0f);
|
|
for (const auto& index : ui->commandList->selectionModel()->selectedIndexes())
|
|
{
|
|
if (index.column() != CommandListDataModel::ColumnIndex::CommandIndex)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
AZ::Uuid type = dataModel->data(index, CommandListDataModel::CustomRole::Types).value<AZ::Uuid>();
|
|
if (type.IsNull())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
[[maybe_unused]] const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(type);
|
|
AZ_Assert(classData, "Failed to find ClassData for ID: %s", type.ToString<AZStd::string>().data());
|
|
|
|
ScriptCanvasEditor::Nodes::StyleConfiguration styleConfiguration;
|
|
|
|
NodeIdPair nodePair = ScriptCanvasEditor::Nodes::CreateNode(type, scriptCanvasId, styleConfiguration);
|
|
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, nodePair.m_graphCanvasId, pos, false);
|
|
|
|
// The next position to create a node at.
|
|
// IMPORTANT: This SHOULD be using GraphCanvas::GeometryRequests::GetWidth, but
|
|
// GetWidth is currently returning zero, so we'll TEMPORARILY use a fixed value.
|
|
pos += AZ::Vector2(125.0f, 0.0f);
|
|
}
|
|
|
|
commandLine->hide();
|
|
}
|
|
} // anonymous namespace.
|
|
|
|
namespace ScriptCanvasEditor
|
|
{
|
|
namespace Widget
|
|
{
|
|
// CommandListDataModel
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
CommandListDataModel::CommandListDataModel([[maybe_unused]] QWidget* parent /*= nullptr*/)
|
|
{
|
|
ScriptCanvasCommandLineRequestBus::Handler::BusConnect();
|
|
|
|
AZ::SerializeContext* serializeContext = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
|
|
|
serializeContext->EnumerateDerived<ScriptCanvas::Node>(
|
|
[this](const AZ::SerializeContext::ClassData* classData, [[maybe_unused]] const AZ::Uuid& classUuid) -> bool
|
|
{
|
|
if (classData && classData->m_editData)
|
|
{
|
|
bool add = true;
|
|
if (auto editorElementData = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
|
|
{
|
|
if (auto excludeAttribute = editorElementData->FindAttribute(AZ::Script::Attributes::ExcludeFrom))
|
|
{
|
|
auto excludeAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<bool>*>(excludeAttribute);
|
|
if (excludeAttributeData)
|
|
{
|
|
add = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (add)
|
|
{
|
|
Entry entry;
|
|
entry.m_type = classData->m_typeId;
|
|
m_entries.emplace_back(entry);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
|
|
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::AddCommand, "add_node", "Adds the specified node to the graph",
|
|
[serializeContext](const AZStd::vector<AZStd::string>& nodes)
|
|
{
|
|
AZ::Uuid nodeTypeToAdd = AZ::Uuid::CreateNull();
|
|
if (nodes.size() > 0)
|
|
{
|
|
const AZStd::string& nodeName = *(nodes.begin());
|
|
|
|
serializeContext->EnumerateDerived<ScriptCanvas::Node>(
|
|
[&nodeName, &nodeTypeToAdd](const AZ::SerializeContext::ClassData* classData, [[maybe_unused]] const AZ::Uuid& classUuid) -> bool
|
|
{
|
|
if (classData && classData->m_editData)
|
|
{
|
|
if (nodeName.compare(classData->m_name) == 0)
|
|
{
|
|
nodeTypeToAdd = classData->m_typeId;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
|
|
if (!nodeTypeToAdd.IsNull())
|
|
{
|
|
ScriptCanvas::ScriptCanvasId scriptCanvasId;
|
|
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveScriptCanvasId);
|
|
|
|
AZ::EntityId graphCanvasGraphId;
|
|
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(graphCanvasGraphId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
|
|
|
|
if (scriptCanvasId.IsValid() && graphCanvasGraphId.IsValid())
|
|
{
|
|
ScriptCanvasEditor::Nodes::StyleConfiguration styleConfiguration;
|
|
|
|
AZ::Vector2 pos(100.0f, 20.0f);
|
|
NodeIdPair nodePair = ScriptCanvasEditor::Nodes::CreateNode(nodeTypeToAdd, scriptCanvasId, styleConfiguration);
|
|
GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, nodePair.m_graphCanvasId, pos, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
CommandListDataModel::~CommandListDataModel()
|
|
{
|
|
ScriptCanvasCommandLineRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
QModelIndex CommandListDataModel::index(int row, int column, const QModelIndex& parent /*= QModelIndex()*/) const
|
|
{
|
|
if (row >= rowCount(parent) || column >= columnCount(parent))
|
|
{
|
|
return QModelIndex();
|
|
}
|
|
return createIndex(row, column);
|
|
}
|
|
|
|
QModelIndex CommandListDataModel::parent([[maybe_unused]] const QModelIndex& child) const
|
|
{
|
|
return QModelIndex();
|
|
}
|
|
|
|
int CommandListDataModel::rowCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
|
|
{
|
|
return static_cast<int>(m_entries.size());
|
|
}
|
|
|
|
int CommandListDataModel::columnCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
|
|
{
|
|
return ColumnIndex::Count;
|
|
}
|
|
|
|
QVariant CommandListDataModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const
|
|
{
|
|
AZ::SerializeContext* serializeContext = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
|
|
|
if (role == Qt::DisplayRole)
|
|
{
|
|
if (index.row() == 0)
|
|
{
|
|
if (index.column() == 0)
|
|
{
|
|
return QVariant(QString(tr("No results found.")));
|
|
}
|
|
else
|
|
if (index.column() > 0)
|
|
{
|
|
return QVariant();
|
|
}
|
|
}
|
|
|
|
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
|
if (nodeType.IsNull())
|
|
{
|
|
if (index.column() == ColumnIndex::CommandIndex)
|
|
{
|
|
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
|
}
|
|
if (index.column() == ColumnIndex::DescriptionIndex)
|
|
{
|
|
AZStd::string command = m_entries[index.row()].m_command;
|
|
const auto& entry = m_commands.find(command);
|
|
if (entry != m_commands.end())
|
|
{
|
|
return QVariant(QString(entry->second->GetDescription().c_str()));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType))
|
|
{
|
|
if (index.column() == ColumnIndex::CommandIndex)
|
|
{
|
|
return QVariant(QString(classData->m_name));
|
|
}
|
|
if (index.column() == ColumnIndex::DescriptionIndex)
|
|
{
|
|
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
|
}
|
|
if (index.column() == ColumnIndex::TrailIndex)
|
|
{
|
|
return QVariant(QString(""));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (role)
|
|
{
|
|
case CustomRole::Types:
|
|
{
|
|
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
|
return QVariant::fromValue<AZ::Uuid>(nodeType);
|
|
}
|
|
break;
|
|
case CustomRole::Node:
|
|
{
|
|
AZ::Uuid nodeType = m_entries[index.row()].m_type;
|
|
if (nodeType.IsNull())
|
|
{
|
|
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
|
}
|
|
else
|
|
{
|
|
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(nodeType))
|
|
{
|
|
if (index.column() == ColumnIndex::CommandIndex)
|
|
{
|
|
return QVariant(QString(classData->m_name));
|
|
}
|
|
if (index.column() == ColumnIndex::DescriptionIndex)
|
|
{
|
|
return QVariant(QString(classData->m_editData ? classData->m_editData->m_description : tr("No description provided.")));
|
|
}
|
|
if (index.column() == ColumnIndex::TrailIndex)
|
|
{
|
|
return QVariant(QString(""));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case CustomRole::Commands:
|
|
{
|
|
if (index.column() == ColumnIndex::CommandIndex)
|
|
{
|
|
return QVariant(QString(m_entries[index.row()].m_command.c_str()));
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
Qt::ItemFlags CommandListDataModel::flags(const QModelIndex& index) const
|
|
{
|
|
return QAbstractTableModel::flags(index);
|
|
}
|
|
|
|
bool CommandListDataModel::HasMatches(const AZStd::string& input)
|
|
{
|
|
AZ::SerializeContext* serializeContext = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
|
|
|
for (const auto& entry : m_entries)
|
|
{
|
|
if (!entry.m_type.IsNull())
|
|
{
|
|
if (const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(entry.m_type))
|
|
{
|
|
QString name = QString(classData->m_name);
|
|
if (name.startsWith(input.c_str(), Qt::CaseSensitivity::CaseInsensitive))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QString commandName = entry.m_command.c_str();
|
|
return (commandName.startsWith(input.c_str(), Qt::CaseSensitivity::CaseInsensitive));
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
ScriptCanvasEditor::Widget::CommandRegistry CommandListDataModel::m_commands;
|
|
|
|
// CommandLineEdit
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace
|
|
{
|
|
QString s_defaultText = QStringLiteral("Press ? for help");
|
|
}
|
|
|
|
CommandLineEdit::CommandLineEdit(QWidget* parent /*= nullptr*/)
|
|
: QLineEdit(parent)
|
|
, m_empty(true)
|
|
, m_defaultText(s_defaultText)
|
|
{
|
|
ResetState();
|
|
|
|
connect(this, &QLineEdit::textChanged, this, &CommandLineEdit::onTextChanged);
|
|
connect(this, &QLineEdit::textEdited, this, &CommandLineEdit::onTextEdited);
|
|
connect(this, &QLineEdit::returnPressed, this, &CommandLineEdit::onReturnPressed);
|
|
}
|
|
|
|
void CommandLineEdit::onReturnPressed()
|
|
{
|
|
}
|
|
|
|
void CommandLineEdit::onTextChanged([[maybe_unused]] const QString& text)
|
|
{
|
|
}
|
|
|
|
void CommandLineEdit::onTextEdited(const QString& text)
|
|
{
|
|
// Execute the command
|
|
(void)text;
|
|
if (text.isEmpty())
|
|
{
|
|
ResetState();
|
|
}
|
|
}
|
|
|
|
|
|
void CommandLineEdit::focusInEvent(QFocusEvent* e)
|
|
{
|
|
QLineEdit::focusInEvent(e);
|
|
Q_EMIT(onFocusChange(true));
|
|
}
|
|
|
|
void CommandLineEdit::focusOutEvent(QFocusEvent* e)
|
|
{
|
|
QLineEdit::focusInEvent(e);
|
|
Q_EMIT(onFocusChange(true));
|
|
}
|
|
|
|
void CommandLineEdit::ResetState()
|
|
{
|
|
m_empty = true;
|
|
setText(m_defaultText);
|
|
}
|
|
|
|
void CommandLineEdit::keyReleaseEvent(QKeyEvent* event)
|
|
{
|
|
Q_EMIT(onKeyReleased(event));
|
|
}
|
|
|
|
void CommandLineEdit::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
switch (event->key())
|
|
{
|
|
case Qt::Key_Enter:
|
|
case Qt::Key_Return:
|
|
{
|
|
// Invoke the command
|
|
AZStd::string commandText = text().toStdString().c_str();
|
|
AZStd::vector<AZStd::string> tokens;
|
|
AZ::StringFunc::Tokenize(commandText, tokens, " ");
|
|
if (tokens.size() == 1)
|
|
{
|
|
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::Invoke, tokens.begin()->c_str());
|
|
}
|
|
else if (tokens.size() > 1)
|
|
{
|
|
AZStd::string command = *(tokens.begin());
|
|
AZStd::vector<AZStd::string> args;
|
|
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it)
|
|
{
|
|
args.push_back(*it);
|
|
}
|
|
ScriptCanvasCommandLineRequestBus::Broadcast(&ScriptCanvasCommandLineRequests::InvokeWithArguments, command.c_str(), args);
|
|
}
|
|
|
|
|
|
ResetState();
|
|
qobject_cast<QWidget*>(parent())->hide();
|
|
}
|
|
break;
|
|
|
|
case Qt::Key_Backspace:
|
|
if (m_empty)
|
|
{
|
|
break;
|
|
}
|
|
QLineEdit::keyPressEvent(event);
|
|
break;
|
|
|
|
case Qt::Key_Escape:
|
|
ResetState();
|
|
qobject_cast<QWidget*>(parent())->hide();
|
|
return;
|
|
|
|
default:
|
|
if (m_empty)
|
|
{
|
|
setText("");
|
|
m_empty = false;
|
|
}
|
|
QLineEdit::keyPressEvent(event);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CommandLineList
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
CommandLineList::CommandLineList(QWidget* parent /*= nullptr*/)
|
|
: QTableView(parent)
|
|
{
|
|
}
|
|
|
|
|
|
// CommandListDataProxyModel
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
CommandListDataProxyModel::CommandListDataProxyModel(CommandListDataModel* commandListData, QObject* parent /*= nullptr*/)
|
|
: QSortFilterProxyModel(parent)
|
|
{
|
|
setSourceModel(commandListData);
|
|
|
|
QStringList commandList;
|
|
|
|
for (int i = 0; i < commandListData->rowCount(); ++i)
|
|
{
|
|
QModelIndex index = commandListData->index(i, CommandListDataModel::ColumnIndex::CommandIndex);
|
|
QString command = commandListData->data(index, CommandListDataModel::CustomRole::Node).toString();
|
|
commandList.push_back(command);
|
|
}
|
|
|
|
ScriptCanvasCommandLineRequests::CommandNameList commands;
|
|
ScriptCanvasCommandLineRequestBus::BroadcastResult(commands, &ScriptCanvasCommandLineRequests::GetCommands);
|
|
for (auto& command : commands)
|
|
{
|
|
QString commandName = command.first.c_str();
|
|
commandList.push_back(commandName);
|
|
}
|
|
|
|
m_completer = new QCompleter(commandList);
|
|
m_completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
|
|
m_completer->setCaseSensitivity(Qt::CaseInsensitive);
|
|
}
|
|
|
|
|
|
bool CommandListDataProxyModel::filterAcceptsRow(int sourceRow, [[maybe_unused]] const QModelIndex& sourceParent) const
|
|
{
|
|
CommandListDataModel* dataModel = qobject_cast<CommandListDataModel*>(sourceModel());
|
|
|
|
if (sourceRow < 0 || sourceRow >= dataModel->rowCount())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (m_input.empty() || m_input.compare(s_defaultText.toStdString().c_str()) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (AzFramework::StringFunc::FirstCharacter(m_input.c_str()) == '?')
|
|
{
|
|
if (sourceRow > 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QModelIndex index = dataModel->index(sourceRow, CommandListDataModel::ColumnIndex::CommandIndex);
|
|
|
|
QString sourceStr = dataModel->data(index).toString();
|
|
if (sourceRow > 0 && sourceStr.startsWith(m_input.c_str(), Qt::CaseSensitivity::CaseInsensitive))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
if (sourceRow == 0)
|
|
{
|
|
if (!dataModel->HasMatches(m_input))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// CommandLine
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CommandLine::CommandLine(QWidget* parent /*= nullptr*/)
|
|
: QWidget(parent)
|
|
, ui(new Ui::CommandLine())
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
CommandListDataModel* commandListDataModel = new CommandListDataModel();
|
|
CommandListDataProxyModel* commandListDataProxyModel = new CommandListDataProxyModel(commandListDataModel);
|
|
|
|
ui->commandList->setModel(commandListDataProxyModel);
|
|
|
|
connect(ui->commandText, &QLineEdit::textChanged, this, &CommandLine::onTextChanged);
|
|
|
|
connect(ui->commandText, &CommandLineEdit::onKeyReleased, this, &CommandLine::onEditKeyReleaseEvent);
|
|
connect(ui->commandList, &CommandLineList::onKeyReleased, this, &CommandLine::onListKeyReleaseEvent);
|
|
|
|
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::CommandIndex, 250);
|
|
ui->commandList->setColumnWidth(CommandListDataModel::ColumnIndex::DescriptionIndex, 1000);
|
|
}
|
|
|
|
void CommandLine::onTextChanged(const QString& text)
|
|
{
|
|
CommandListDataProxyModel* model = qobject_cast<CommandListDataProxyModel*>(ui->commandList->model());
|
|
if (model)
|
|
{
|
|
model->SetInput(text.toStdString().c_str());
|
|
}
|
|
}
|
|
|
|
|
|
void CommandLine::onListKeyReleaseEvent(QKeyEvent* event)
|
|
{
|
|
AZ::SerializeContext* serializeContext = nullptr;
|
|
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
|
|
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
|
|
|
|
switch (event->key())
|
|
{
|
|
case Qt::Key_Up:
|
|
if (ui->commandList->selectionModel())
|
|
{
|
|
if (ui->commandList->selectionModel()->selectedIndexes().empty() || ui->commandList->selectionModel()->selectedIndexes().at(0).row() == 0)
|
|
{
|
|
ui->commandText->setFocus();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Qt::Key_Escape:
|
|
hide();
|
|
break;
|
|
|
|
case Qt::Key_Enter:
|
|
case Qt::Key_Return:
|
|
CreateSelectedNodes(this, ui, serializeContext);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CommandLine::onEditKeyReleaseEvent(QKeyEvent* event)
|
|
{
|
|
if (event->key() == Qt::Key_Down)
|
|
{
|
|
ui->commandList->setFocus();
|
|
ui->commandList->selectRow(0);
|
|
}
|
|
}
|
|
|
|
void CommandLine::showEvent(QShowEvent* event)
|
|
{
|
|
QWidget::showEvent(event);
|
|
|
|
ui->commandText->ResetState();
|
|
ui->commandText->setFocus(Qt::PopupFocusReason);
|
|
}
|
|
|
|
#include <Editor/View/Widgets/moc_CommandLine.cpp>
|
|
}
|
|
}
|