Integrating latest 47acbe8

This commit is contained in:
alexpete
2021-03-25 13:57:57 -07:00
parent 448c549698
commit 75dc720198
10312 changed files with 2711566 additions and 671451 deletions
@@ -0,0 +1,142 @@
/*
* 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 <QApplication>
#include <QKeyEvent>
#include <QtTest/qtest.h>
#include <QWidget>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
namespace ScriptCanvasDeveloper
{
//////////////////////
// SimulateKeyAction
//////////////////////
SimulateKeyAction::SimulateKeyAction(KeyAction keyAction, AZ::u32 keyValue)
: m_keyValue(keyValue)
, m_keyAction(keyAction)
{
}
bool SimulateKeyAction::Tick()
{
#if defined(AZ_COMPILER_MSVC)
INPUT osInput = { 0 };
osInput.type = INPUT_KEYBOARD;
osInput.ki.wVk = m_keyValue;
switch (m_keyAction)
{
case KeyAction::Press:
break;
case KeyAction::Release:
osInput.ki.dwFlags = KEYEVENTF_KEYUP;
break;
}
::SendInput(1, &osInput, sizeof(INPUT));
#endif
return true;
}
///////////////////
// TypeCharAction
///////////////////
TypeCharAction::TypeCharAction(QChar testCharacter)
{
#if defined(AZ_COMPILER_MSVC)
// This is a. Going to use this to manage most of my elements
AZ::u32 aOffset = 0x41;
AZ::u32 zeroOffset = 0x30;
ushort unicodeA = QChar('a').unicode();
ushort unicodeZero = QChar('0').unicode();
if (testCharacter.isLetterOrNumber())
{
ushort unicodeValue = testCharacter.unicode();
AZ::u32 offsetStart = 0;
ushort difference = 0;
if (testCharacter.isLetter())
{
offsetStart = aOffset;
difference = unicodeValue - unicodeA;
}
else if (testCharacter.isNumber())
{
offsetStart = zeroOffset;
difference = unicodeValue - unicodeZero;
}
AZ::u32 finalKey = offsetStart + difference;
AddAction(aznew TypeCharAction(finalKey));
}
else if (testCharacter == QChar(' '))
{
AddAction(aznew TypeCharAction(VK_SPACE));
}
else if (testCharacter == QChar('*'))
{
AddAction(aznew KeyPressAction(VK_SHIFT));
AddAction(aznew TypeCharAction(unicodeZero + 8));
AddAction(aznew KeyReleaseAction(VK_SHIFT));
}
else if (testCharacter == QChar('('))
{
AddAction(aznew KeyPressAction(VK_SHIFT));
AddAction(aznew TypeCharAction(unicodeZero + 9));
AddAction(aznew KeyReleaseAction(VK_SHIFT));
}
else if (testCharacter == QChar(')'))
{
AddAction(aznew KeyPressAction(VK_SHIFT));
AddAction(aznew TypeCharAction(unicodeZero + 0));
AddAction(aznew KeyReleaseAction(VK_SHIFT));
}
else if (testCharacter == QChar(':'))
{
AddAction(aznew KeyPressAction(VK_SHIFT));
AddAction(aznew TypeCharAction(VK_OEM_1));
AddAction(aznew KeyReleaseAction(VK_SHIFT));
}
else if (testCharacter == QChar('.'))
{
AddAction(aznew TypeCharAction(VK_OEM_PERIOD));
}
#endif
}
TypeCharAction::TypeCharAction(AZ::u32 keyValue)
{
AddAction(aznew KeyPressAction(keyValue));
AddAction(aznew KeyReleaseAction(keyValue));
}
/////////////////////
// TypeStringAction
/////////////////////
TypeStringAction::TypeStringAction(QString targetString)
{
for (int i = 0; i < targetString.size(); ++i)
{
QChar testCharacter = targetString.at(i).toLower();
AddAction(aznew TypeCharAction(testCharacter));
}
}
}
@@ -0,0 +1,209 @@
/*
* 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 <AzCore/PlatformIncl.h>
#include <QApplication>
#include <QCursor>
#include <QMainWindow>
#include <QMouseEvent>
#include <QtTest/qtest.h>
#include <QWidget>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/GenericActions.h>
namespace ScriptCanvasDeveloper
{
//////////////////////////////
// SimulateMouseButtonAction
//////////////////////////////
SimulateMouseButtonAction::SimulateMouseButtonAction(MouseAction mouseAction, Qt::MouseButton mouseButton)
: m_mouseAction(mouseAction)
, m_mouseButton(mouseButton)
{
}
void SimulateMouseButtonAction::SetTarget(QWidget* targetDispatch)
{
m_targetDispatch = targetDispatch;
}
bool SimulateMouseButtonAction::Tick()
{
#if defined(AZ_COMPILER_MSVC)
INPUT osInput = { 0 };
osInput.type = INPUT_MOUSE;
osInput.mi.mouseData = 0;
osInput.mi.time = 0;
switch (m_mouseAction)
{
case MouseAction::Press:
switch (m_mouseButton)
{
case Qt::MouseButton::LeftButton:
osInput.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
break;
case Qt::MouseButton::RightButton:
osInput.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
break;
}
break;
case MouseAction::Release:
switch (m_mouseButton)
{
case Qt::MouseButton::LeftButton:
osInput.mi.dwFlags = MOUSEEVENTF_LEFTUP;
break;
case Qt::MouseButton::RightButton:
osInput.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
break;
}
break;
default:
break;
}
::SendInput(1, &osInput, sizeof(INPUT));
#endif
return true;
}
/////////////////////
// MouseClickAction
/////////////////////
MouseClickAction::MouseClickAction(Qt::MouseButton mouseButton)
: CompoundAction()
, m_mouseButton(mouseButton)
, m_hasFixedTarget(false)
{
PopulateActionQueue();
}
MouseClickAction::MouseClickAction(Qt::MouseButton mouseButton, QPoint cursorPosition)
: CompoundAction()
, m_mouseButton(mouseButton)
, m_hasFixedTarget(true)
, m_cursorPosition(cursorPosition)
{
PopulateActionQueue();
}
bool MouseClickAction::IsMissingPrecondition()
{
if (m_hasFixedTarget)
{
QPoint screenPoint = QCursor::pos();
// Need to give this a little 'wiggle' room.
QRectF clickArea = QRectF(screenPoint, screenPoint);
clickArea.adjust(-2, -2, 2, 2);
return !clickArea.contains(m_cursorPosition);
}
return false;
}
EditorAutomationAction* MouseClickAction::GenerateMissingPreconditionAction()
{
return aznew MouseMoveAction(m_cursorPosition);
}
void MouseClickAction::PopulateActionQueue()
{
AddAction(aznew DelayAction(AZStd::chrono::milliseconds(500)));
AddAction(aznew PressMouseButtonAction(m_mouseButton));
AddAction(aznew DelayAction(AZStd::chrono::milliseconds(10)));
AddAction(aznew ReleaseMouseButtonAction(m_mouseButton));
AddAction(aznew ProcessUserEventsAction());
}
////////////////////
// MouseMoveAction
////////////////////
MouseMoveAction::MouseMoveAction(QPoint targetPosition, int ticks)
: m_tickDuration(ticks)
, m_targetPosition(targetPosition)
{
}
void MouseMoveAction::SetupAction()
{
m_tickCount = 0;
m_hasStartPosition = false;
}
bool MouseMoveAction::Tick()
{
++m_tickCount;
if (!m_hasStartPosition)
{
m_startPosition = QCursor::pos();
}
QPointF currentPosition = QCursor::pos();
QPointF targetPoint = m_targetPosition;
float percentage = aznumeric_cast<float>(m_tickCount)/aznumeric_cast<float>(m_tickDuration);
if (!AZ::IsClose(percentage, 1.0f, AZ::Constants::FloatEpsilon))
{
int lerpedX = aznumeric_cast<int>((m_targetPosition.x() - m_startPosition.x()) * percentage) + m_startPosition.x();
int lerpedY = aznumeric_cast<int>((m_targetPosition.y() - m_startPosition.y()) * percentage) + m_startPosition.y();
targetPoint = QPointF(lerpedX, lerpedY);
}
#if defined(AZ_COMPILER_MSVC)
INPUT osInput = { 0 };
osInput.type = INPUT_MOUSE;
osInput.mi.mouseData = 0;
osInput.mi.time = 0;
osInput.mi.dx = targetPoint.x() - currentPosition.x();
osInput.mi.dy = targetPoint.y() - currentPosition.y();
osInput.mi.dwFlags = MOUSEEVENTF_MOVE;
::SendInput(1, &osInput, sizeof(osInput));
#endif
return AZ::IsClose(percentage, 1.0f, AZ::Constants::FloatEpsilon);
}
////////////////////
// MouseDragAction
////////////////////
MouseDragAction::MouseDragAction(QPoint startPosition, QPoint endPosition, Qt::MouseButton holdButton)
: m_holdButton(holdButton)
, m_startPosition(startPosition)
, m_endPosition(endPosition)
{
AddAction(aznew MouseMoveAction(m_startPosition));
AddAction(aznew PressMouseButtonAction(m_holdButton));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew MouseMoveAction(m_endPosition));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew ReleaseMouseButtonAction(m_holdButton));
AddAction(aznew ProcessUserEventsAction());
}
}
@@ -0,0 +1,180 @@
/*
* 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 <QApplication>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/GenericActions.h>
namespace ScriptCanvasDeveloper
{
///////////////////
// CompoundAction
///////////////////
CompoundAction::CompoundAction()
{
}
CompoundAction::~CompoundAction()
{
ClearActionQueue();
}
void CompoundAction::SetupAction()
{
m_actionRunner.Reset();
for (EditorAutomationAction* action : m_actionQueue)
{
m_actionRunner.AddAction(action);
}
m_errorReports.clear();
}
bool CompoundAction::Tick()
{
if (m_actionRunner.Tick())
{
m_errorReports = m_actionRunner.GetErrors();
OnActionsComplete();
return true;
}
return false;
}
void CompoundAction::AddAction(EditorAutomationAction* action)
{
m_actionQueue.emplace_back(action);
}
ActionReport CompoundAction::GenerateReport() const
{
if (!m_errorReports.empty())
{
AZStd::string finalErrorString = "Compound Action Error: ";
bool firstAdd = false;
for (ActionReport errorReport : m_errorReports)
{
if (!firstAdd)
{
finalErrorString.append(", ");
}
firstAdd = false;
finalErrorString.append(errorReport.GetError());
}
return AZ::Failure(finalErrorString);
}
return AZ::Success();
}
void CompoundAction::ClearActionQueue()
{
m_actionRunner.Reset();
for (EditorAutomationAction* action : m_actionQueue)
{
delete action;
}
m_actionQueue.clear();
m_errorReports.clear();
}
////////////////
// DelayAction
////////////////
DelayAction::DelayAction(AZStd::chrono::milliseconds delayTime)
: m_delay(delayTime)
{
}
void DelayAction::SetupAction()
{
m_startPoint = AZStd::chrono::system_clock::now();
}
bool DelayAction::Tick()
{
auto currentTime = AZStd::chrono::system_clock::now();
auto elapsedTime = AZStd::chrono::duration_cast<AZStd::chrono::milliseconds>(currentTime - m_startPoint);
return elapsedTime >= m_delay;
}
////////////////////////////
// ProcessUserEventsAction
////////////////////////////
ProcessUserEventsAction::ProcessUserEventsAction(AZStd::chrono::milliseconds delayTime)
: DelayAction(delayTime)
{
}
void ProcessUserEventsAction::SetupAction()
{
DelayAction::SetupAction();
m_delayComplete = false;
m_processingComplete = false;
m_processingEventsSwitch = false;
}
bool ProcessUserEventsAction::Tick()
{
if (!m_delayComplete)
{
m_delayComplete = DelayAction::Tick();
}
if (m_delayComplete && !m_processingEventsSwitch)
{
m_processingEventsSwitch = true;
if (!m_processingComplete)
{
QApplication::processEvents();
m_processingComplete = true;
}
}
return m_delayComplete && m_processingComplete;
}
///////////////
// TraceEvent
///////////////
TraceEvent::TraceEvent(AZStd::string traceName)
: m_traceName(traceName)
{
}
bool TraceEvent::Tick()
{
AZ_TracePrintf("Testing", "TraceEvent::%s", m_traceName.c_str());
return true;
}
}
@@ -0,0 +1,191 @@
/*
* 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 <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ConnectionActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
namespace ScriptCanvasDeveloper
{
//////////////////////
// CoupleNodesAction
//////////////////////
CoupleNodesAction::CoupleNodesAction(GraphCanvas::NodeId nodeToPickUp, GraphCanvas::ConnectionType connectionType, GraphCanvas::NodeId coupleTarget)
: m_nodeToPickUp(nodeToPickUp)
, m_connectionType(connectionType)
, m_targetNode(coupleTarget)
{
}
bool CoupleNodesAction::IsMissingPrecondition()
{
QGraphicsItem* sourceGraphicsItem = nullptr;
GraphCanvas::VisualRequestBus::EventResult(sourceGraphicsItem, m_nodeToPickUp, &GraphCanvas::VisualRequests::AsGraphicsItem);
if (sourceGraphicsItem)
{
m_pickUpRect = sourceGraphicsItem->sceneBoundingRect();
}
QGraphicsItem* targetGraphicsItem = nullptr;
GraphCanvas::VisualRequestBus::EventResult(targetGraphicsItem, m_targetNode, &GraphCanvas::VisualRequests::AsGraphicsItem);
if (targetGraphicsItem)
{
m_targetRect = targetGraphicsItem->sceneBoundingRect();
}
m_sceneRect = m_pickUpRect;
m_sceneRect |= m_targetRect;
// Provide some extra spacing just to provide some safety
m_sceneRect = m_sceneRect.adjusted(-m_sceneRect.width() * 0.25f, -m_sceneRect.height() * 0.25f, m_sceneRect.width() * 0.25f, m_sceneRect.height() * 0.25f);
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, m_nodeToPickUp, &GraphCanvas::SceneMemberRequests::GetScene);
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, graphId, &GraphCanvas::SceneRequests::GetViewId);
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
return !viewableArea.contains(m_sceneRect);
}
EditorAutomationAction* CoupleNodesAction::GenerateMissingPreconditionAction()
{
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, m_nodeToPickUp, &GraphCanvas::SceneMemberRequests::GetScene);
return aznew EnsureSceneRectVisibleAction(graphId, m_sceneRect);
}
AZStd::vector< GraphCanvas::ConnectionId > CoupleNodesAction::GetConnectionIds() const
{
return m_connections;
}
void CoupleNodesAction::OnConnectionAdded(const AZ::EntityId& connectionId)
{
m_connections.emplace_back(connectionId);
}
void CoupleNodesAction::SetupAction()
{
ClearActionQueue();
QPointF mouseStartPoint = QPointF(m_pickUpRect.center().x(), m_pickUpRect.top() + 5);
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, m_nodeToPickUp, &GraphCanvas::SceneMemberRequests::GetScene);
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, graphId, &GraphCanvas::SceneRequests::GetViewId);
GraphCanvas::ViewRequests* viewRequests = GraphCanvas::ViewRequestBus::FindFirstHandler(viewId);
if (viewRequests)
{
QPoint initialMousePosition = GraphCanvas::ConversionUtils::AZToQPoint(viewRequests->MapToGlobal(GraphCanvas::ConversionUtils::QPointToVector(mouseStartPoint))).toPoint();
AddAction(aznew MouseMoveAction(initialMousePosition));
AddAction(aznew PressMouseButtonAction(Qt::MouseButton::LeftButton));
QPointF targetPoint = m_targetRect.center();
QPointF startPoint = m_pickUpRect.center();
// Depending on which side of the pick-up node we want to connect, we need to target a different edge of the target node.
if (m_connectionType == GraphCanvas::ConnectionType::CT_Input)
{
targetPoint = QPointF(m_targetRect.right(), targetPoint.y());
}
else if (m_connectionType == GraphCanvas::ConnectionType::CT_Output)
{
targetPoint = QPointF(m_targetRect.left(), targetPoint.y());
}
QPointF lineDelta = QPointF(targetPoint.x() - startPoint.x(), targetPoint.y() - startPoint.y());
QPointF targetMousePosition = QPointF(mouseStartPoint.x() + lineDelta.x(), mouseStartPoint.y() + lineDelta.y());
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(viewRequests->MapToGlobal(GraphCanvas::ConversionUtils::QPointToVector(targetMousePosition))).toPoint()));
GraphCanvas::EditorId editorId;
GraphCanvas::SceneRequestBus::EventResult(editorId, graphId, &GraphCanvas::SceneRequests::GetEditorId);
AZStd::chrono::milliseconds coupleDuration;
GraphCanvas::AssetEditorSettingsRequestBus::EventResult(coupleDuration, editorId, &GraphCanvas::AssetEditorSettingsRequests::GetDragCouplingTime);
// Double the couple duration to be safe.
coupleDuration = coupleDuration + coupleDuration;
AddAction(aznew DelayAction(coupleDuration));
AddAction(aznew MouseMoveAction(initialMousePosition));
AddAction(aznew ReleaseMouseButtonAction(Qt::MouseButton::LeftButton));
AddAction(aznew DelayAction(AZStd::chrono::milliseconds(250)));
}
m_connections.clear();
GraphCanvas::SceneNotificationBus::Handler::BusConnect(graphId);
CompoundAction::SetupAction();
}
void CoupleNodesAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
}
///////////////////////////
// ConnectEndpointsAction
///////////////////////////
ConnectEndpointsAction::ConnectEndpointsAction(GraphCanvas::Endpoint startEndpoint, GraphCanvas::Endpoint targetEndpoint)
: m_startEndpoint(startEndpoint)
, m_targetEndpoint(targetEndpoint)
{
QPointF startScenePoint;
GraphCanvas::SlotUIRequestBus::EventResult(startScenePoint, startEndpoint.m_slotId, &GraphCanvas::SlotUIRequests::GetPinCenter);
QPointF targetScenePoint;
GraphCanvas::SlotUIRequestBus::EventResult(targetScenePoint, targetEndpoint.m_slotId, &GraphCanvas::SlotUIRequests::GetPinCenter);
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, startEndpoint.m_nodeId, &GraphCanvas::SceneMemberRequests::GetScene);
AddAction(aznew SceneMouseDragAction(graphId, startScenePoint, targetScenePoint, Qt::MouseButton::LeftButton));
}
GraphCanvas::ConnectionId ConnectEndpointsAction::GetConnectionId() const
{
return m_connectionId;
}
void ConnectEndpointsAction::OnActionsComplete()
{
GraphCanvas::SlotRequestBus::EventResult(m_connectionId, m_startEndpoint.GetSlotId(), &GraphCanvas::SlotRequests::GetLastConnection);
}
}
@@ -0,0 +1,761 @@
/*
* 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 <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Editor/Automation/AutomationIds.h>
#include <GraphCanvas/Editor/Automation/AutomationUtils.h>
#include <GraphCanvas/Widgets/NodePalette/Model/NodePaletteSortFilterProxyModel.h>
#include <GraphCanvas/Widgets/NodePalette/NodePaletteTreeView.h>
#include <GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/WidgetActions.h>
namespace ScriptCanvasDeveloper
{
////////////////////////////////
// CreateNodeFromPaletteAction
////////////////////////////////
CreateNodeFromPaletteAction::CreateNodeFromPaletteAction(GraphCanvas::NodePaletteWidget* paletteWidget, GraphCanvas::GraphId graphId, QString nodeName, QPointF scenePoint)
: m_graphId(graphId)
, m_scenePoint(scenePoint)
, m_nodeName(nodeName)
, m_paletteWidget(paletteWidget)
{
}
CreateNodeFromPaletteAction::CreateNodeFromPaletteAction(GraphCanvas::NodePaletteWidget* paletteWidget, GraphCanvas::GraphId graphId, QString nodeName, GraphCanvas::ConnectionId connectionId)
: m_spliceTarget(connectionId)
, m_graphId(graphId)
, m_nodeName(nodeName)
, m_paletteWidget(paletteWidget)
{
if (GraphCanvas::GraphUtils::IsConnection(connectionId))
{
QPainterPath outlinePath;
GraphCanvas::SceneMemberUIRequestBus::EventResult(outlinePath, connectionId, &GraphCanvas::SceneMemberUIRequests::GetOutline);
m_scenePoint = outlinePath.pointAtPercent(0.5);
GraphCanvas::ConnectionRequestBus::EventResult(m_sourceEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetSourceEndpoint);
GraphCanvas::ConnectionRequestBus::EventResult(m_targetEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetTargetEndpoint);
}
else
{
m_scenePoint = QPointF(0, 0);
}
}
bool CreateNodeFromPaletteAction::IsMissingPrecondition()
{
if (!m_centerOnScene && !m_writeToSearchFilter)
{
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
AZ::Vector2 viewCenter;
GraphCanvas::ViewRequestBus::EventResult(viewCenter, viewId, &GraphCanvas::ViewRequests::GetViewSceneCenter);
QRectF viewRect = QRectF(GraphCanvas::ConversionUtils::AZToQPoint(viewCenter), GraphCanvas::ConversionUtils::AZToQPoint(viewCenter));
viewRect.adjust(-2, -2, 2, 2);
m_centerOnScene = !viewRect.contains(m_scenePoint);
m_writeToSearchFilter = (m_paletteWidget->GetSearchFilter()->text().compare(m_nodeName, Qt::CaseInsensitive) != 0);
return m_centerOnScene || m_writeToSearchFilter;
}
else
{
return false;
}
}
EditorAutomationAction* CreateNodeFromPaletteAction::GenerateMissingPreconditionAction()
{
CompoundAction* compoundAction = aznew CompoundAction();
if (m_centerOnScene)
{
compoundAction->AddAction(aznew CenterOnScenePointAction(m_graphId, m_scenePoint));
}
if (m_writeToSearchFilter)
{
compoundAction->AddAction(aznew WriteToLineEditAction(m_paletteWidget->GetSearchFilter(), m_nodeName));
#if defined(AZ_COMPILER_MSVC)
compoundAction->AddAction(aznew TypeCharAction(VK_RETURN));
#endif
compoundAction->AddAction(aznew DelayAction(AZStd::chrono::milliseconds(400)));
}
return compoundAction;
}
void CreateNodeFromPaletteAction::SetupAction()
{
ClearActionQueue();
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
m_createdNodeId.SetInvalid();
GraphCanvas::GraphCanvasTreeItem* paletteItem = m_paletteWidget->FindItemWithName(m_nodeName);
if (paletteItem)
{
QModelIndex modelIndex = paletteItem->GetIndexFromModel();
GraphCanvas::NodePaletteSortFilterProxyModel* proxyModel = m_paletteWidget->GetFilterModel();
QModelIndex filteredParentIndex = proxyModel->mapFromSource(paletteItem->GetParent()->GetIndexFromModel());
QModelIndex filteredElementIndex = proxyModel->mapFromSource(modelIndex);
AddAction(aznew MoveMouseToViewRowAction(m_paletteWidget->GetTreeView(), filteredElementIndex.row(), filteredParentIndex));
AddAction(aznew PressMouseButtonAction(Qt::MouseButton::LeftButton));
AddAction(aznew ProcessUserEventsAction());
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
AZ::Vector2 screenPoint;
GraphCanvas::ViewRequestBus::EventResult(screenPoint, viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(screenPoint).toPoint()));
AddAction(aznew ProcessUserEventsAction());
// If we are splicing, we need to hold a little bit before we release the button.
if (m_spliceTarget.IsValid())
{
AZStd::chrono::milliseconds connectionDelay;
GraphCanvas::AssetEditorSettingsRequestBus::EventResult(connectionDelay, ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorSettingsRequests::GetDropConnectionSpliceTime);
// Give it some buffer room on the delay before we release.
connectionDelay = connectionDelay + connectionDelay * 0.5f;
AddAction(aznew ProcessUserEventsAction(connectionDelay));
}
AddAction(aznew ReleaseMouseButtonAction(Qt::MouseButton::LeftButton));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(screenPoint + AZ::Vector2(1,1)).toPoint()));
AddAction(aznew ProcessUserEventsAction());
}
CompoundAction::SetupAction();
}
GraphCanvas::NodeId CreateNodeFromPaletteAction::GetCreatedNodeId() const
{
return GraphCanvas::GraphUtils::FindOutermostNode(m_createdNodeId);
}
void CreateNodeFromPaletteAction::OnNodeAdded(const AZ::EntityId& nodeId, bool)
{
if (!m_createdNodeId.IsValid())
{
m_createdNodeId = nodeId;
}
}
ActionReport CreateNodeFromPaletteAction::GenerateReport() const
{
if (!m_createdNodeId.IsValid())
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create %s", m_nodeName.toUtf8().data()));
}
else if (m_spliceTarget.IsValid())
{
GraphCanvas::NodeId nodeId = GetCreatedNodeId();
GraphCanvas::ConnectionId connectionId;
GraphCanvas::SlotRequestBus::EventResult(connectionId, m_sourceEndpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
GraphCanvas::Endpoint otherEndpoint;
GraphCanvas::ConnectionRequestBus::EventResult(otherEndpoint, connectionId, &GraphCanvas::ConnectionRequests::FindOtherEndpoint, m_sourceEndpoint);
if (!otherEndpoint.IsValid()
|| otherEndpoint.GetNodeId() != nodeId)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Spliced connection failed to create connection from source Endpoint to %s node", m_nodeName.toUtf8().data()));
}
connectionId.SetInvalid();
GraphCanvas::SlotRequestBus::EventResult(connectionId, m_targetEndpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
otherEndpoint = GraphCanvas::Endpoint();
GraphCanvas::ConnectionRequestBus::EventResult(otherEndpoint, connectionId, &GraphCanvas::ConnectionRequests::FindOtherEndpoint, m_targetEndpoint);
if (!otherEndpoint.IsValid()
|| otherEndpoint.GetNodeId() != nodeId)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Spliced connection failed to create connection from target Endpoint to %s node", m_nodeName.toUtf8().data()));
}
}
return CompoundAction::GenerateReport();
}
void CreateNodeFromPaletteAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
m_centerOnScene = false;
m_writeToSearchFilter = false;
}
////////////////////////////////////////
// CreateCategoryFromNodePaletteAction
////////////////////////////////////////
CreateCategoryFromNodePaletteAction::CreateCategoryFromNodePaletteAction(GraphCanvas::NodePaletteWidget* paletteWidget, GraphCanvas::GraphId graphId, QString category, QPointF scenePoint)
: m_graphId(graphId)
, m_scenePoint(scenePoint)
, m_categoryName(category)
, m_paletteWidget(paletteWidget)
{
}
bool CreateCategoryFromNodePaletteAction::IsMissingPrecondition()
{
return m_paletteWidget->GetSearchFilter()->text().compare(m_categoryName, Qt::CaseInsensitive) != 0;
}
EditorAutomationAction* CreateCategoryFromNodePaletteAction::GenerateMissingPreconditionAction()
{
CompoundAction* compoundAction = aznew CompoundAction();
compoundAction->AddAction(aznew WriteToLineEditAction(m_paletteWidget->GetSearchFilter(), m_categoryName));
#if defined(AZ_COMPILER_MSVC)
compoundAction->AddAction(aznew TypeCharAction(VK_RETURN));
#endif
compoundAction->AddAction(aznew ProcessUserEventsAction());
return compoundAction;
}
void CreateCategoryFromNodePaletteAction::SetupAction()
{
ClearActionQueue();
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
GraphCanvas::GraphCanvasTreeItem* rootItem = m_paletteWidget->FindItemWithName(m_categoryName);
AZStd::vector<AZStd::pair<int, QModelIndex>> creationIndexes;
if (rootItem)
{
AZStd::unordered_set< GraphCanvas::GraphCanvasTreeItem* > unexploredItems = { rootItem };
while (!unexploredItems.empty())
{
GraphCanvas::GraphCanvasTreeItem* currentItem = (*unexploredItems.begin());
unexploredItems.erase(unexploredItems.begin());
if (currentItem)
{
if (currentItem->GetChildCount() == 0)
{
QModelIndex currentRow = m_paletteWidget->GetFilterModel()->mapFromSource(currentItem->GetIndexFromModel());
QModelIndex parentIndex = m_paletteWidget->GetFilterModel()->mapFromSource(currentItem->GetParent()->GetIndexFromModel());
if (currentRow.isValid() && parentIndex.isValid())
{
creationIndexes.emplace_back(currentRow.row(), parentIndex);
}
}
else
{
for (int i = 0; i < currentItem->GetChildCount(); ++i)
{
unexploredItems.insert(currentItem->FindChildByRow(i));
}
}
}
}
m_expectedCreations = aznumeric_cast<int>(creationIndexes.size());
for (int i = 0; i < creationIndexes.size(); ++i)
{
if (i == 0)
{
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyPressAction(VK_CONTROL));
#endif
}
const auto& creationPair = creationIndexes[i];
AddAction(aznew MoveMouseToViewRowAction(m_paletteWidget->GetTreeView(), creationPair.first, creationPair.second));
AddAction(aznew ProcessUserEventsAction());
if (i + 1 >= creationIndexes.size())
{
AddAction(aznew PressMouseButtonAction(Qt::MouseButton::LeftButton));
}
else
{
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton));
}
AddAction(aznew ProcessUserEventsAction());
}
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
AZ::Vector2 screenPoint;
GraphCanvas::ViewRequestBus::EventResult(screenPoint, viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(screenPoint).toPoint()));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew ReleaseMouseButtonAction(Qt::MouseButton::LeftButton));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(screenPoint + AZ::Vector2(1, 1)).toPoint()));
AddAction(aznew ProcessUserEventsAction());
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyReleaseAction(VK_CONTROL));
#endif
AddAction(aznew ProcessUserEventsAction());
}
CompoundAction::SetupAction();
}
void CreateCategoryFromNodePaletteAction::OnNodeAdded(const AZ::EntityId& nodeId, bool)
{
m_createdNodeIds.emplace_back(nodeId);
}
AZStd::vector< GraphCanvas::NodeId > CreateCategoryFromNodePaletteAction::GetCreatedNodes() const
{
return m_createdNodeIds;
}
void CreateCategoryFromNodePaletteAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
AZStd::vector< GraphCanvas::NodeId > nodes = m_createdNodeIds;
AZStd::unordered_set< GraphCanvas::NodeId > rootNodes;
m_createdNodeIds.clear();
for (GraphCanvas::NodeId nodeId : nodes)
{
GraphCanvas::NodeId outermostNode = GraphCanvas::GraphUtils::FindOutermostNode(nodeId);
rootNodes.insert(outermostNode);
}
m_createdNodeIds.insert(m_createdNodeIds.begin(), rootNodes.begin(), rootNodes.end());
}
ActionReport CreateCategoryFromNodePaletteAction::GenerateReport() const
{
if (m_createdNodeIds.size() != m_expectedCreations)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create all nodes. %i expected, %i created", aznumeric_cast<int>(m_createdNodeIds.size()), m_expectedCreations));
}
return CompoundAction::GenerateReport();
}
////////////////////////////////////
// CreateNodeFromContextMenuAction
////////////////////////////////////
CreateNodeFromContextMenuAction::CreateNodeFromContextMenuAction(GraphCanvas::GraphId graphId, QString nodeName, QPointF scenePoint)
: m_graphId(graphId)
, m_scenePoint(scenePoint)
, m_nodeName(nodeName)
{
}
CreateNodeFromContextMenuAction::CreateNodeFromContextMenuAction(GraphCanvas::GraphId graphId, QString nodeName, AZ::EntityId connectionId)
: m_graphId(graphId)
, m_nodeName(nodeName)
{
if (GraphCanvas::GraphUtils::IsConnection(connectionId))
{
QPainterPath outlinePath;
GraphCanvas::SceneMemberUIRequestBus::EventResult(outlinePath, connectionId, &GraphCanvas::SceneMemberUIRequests::GetOutline);
m_scenePoint = outlinePath.pointAtPercent(0.5);
m_spliceTarget = connectionId;
GraphCanvas::ConnectionRequestBus::EventResult(m_sourceEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetSourceEndpoint);
GraphCanvas::ConnectionRequestBus::EventResult(m_targetEndpoint, connectionId, &GraphCanvas::ConnectionRequests::GetTargetEndpoint);
}
else
{
m_scenePoint = QPointF(0,0);
}
}
bool CreateNodeFromContextMenuAction::IsMissingPrecondition()
{
return m_centerOnScene;
}
EditorAutomationAction* CreateNodeFromContextMenuAction::GenerateMissingPreconditionAction()
{
m_centerOnScene = false;
return aznew CenterOnScenePointAction(m_graphId, m_scenePoint);
}
void CreateNodeFromContextMenuAction::SetupAction()
{
ClearActionQueue();
m_createdNodeId.SetInvalid();
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
AZ::Vector2 screenPoint;
GraphCanvas::ViewRequestBus::EventResult(screenPoint, viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(screenPoint).toPoint()));
AddAction(aznew MouseClickAction(Qt::MouseButton::RightButton));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew TypeStringAction(m_nodeName));
AddAction(aznew ProcessUserEventsAction());
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew TypeCharAction(VK_RETURN));
#endif
AddAction(aznew ProcessUserEventsAction());
CompoundAction::SetupAction();
}
void CreateNodeFromContextMenuAction::OnNodeAdded(const AZ::EntityId& nodeId, bool)
{
m_createdNodeId = nodeId;
}
AZ::EntityId CreateNodeFromContextMenuAction::GetCreatedNodeId() const
{
return m_createdNodeId;
}
void CreateNodeFromContextMenuAction::OnActionsComplete()
{
m_createdNodeId = GraphCanvas::GraphUtils::FindOutermostNode(m_createdNodeId);
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
m_centerOnScene = true;
}
ActionReport CreateNodeFromContextMenuAction::GenerateReport() const
{
if (!m_createdNodeId.IsValid())
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create Node %s.", m_nodeName.toUtf8().data()));
}
else if (m_spliceTarget.IsValid())
{
GraphCanvas::NodeId nodeId = GetCreatedNodeId();
GraphCanvas::ConnectionId connectionId;
GraphCanvas::SlotRequestBus::EventResult(connectionId, m_sourceEndpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
GraphCanvas::Endpoint otherEndpoint;
GraphCanvas::ConnectionRequestBus::EventResult(otherEndpoint, connectionId, &GraphCanvas::ConnectionRequests::FindOtherEndpoint, m_sourceEndpoint);
if (!otherEndpoint.IsValid()
|| otherEndpoint.GetNodeId() != nodeId)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Spliced connection failed to create connection from source Endpoint to %s node", m_nodeName.toUtf8().data()));
}
connectionId.SetInvalid();
GraphCanvas::SlotRequestBus::EventResult(connectionId, m_targetEndpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
otherEndpoint = GraphCanvas::Endpoint();
GraphCanvas::ConnectionRequestBus::EventResult(otherEndpoint, connectionId, &GraphCanvas::ConnectionRequests::FindOtherEndpoint, m_targetEndpoint);
if (!otherEndpoint.IsValid()
|| otherEndpoint.GetNodeId() != nodeId)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Spliced connection failed to create connection from target Endpoint to %s node", m_nodeName.toUtf8().data()));
}
}
return CompoundAction::GenerateReport();
}
/////////////////////////////////
// CreateNodeFromProposalAction
/////////////////////////////////
CreateNodeFromProposalAction::CreateNodeFromProposalAction(GraphCanvas::GraphId graphId, GraphCanvas::Endpoint endpoint, QString nodeName)
: m_graphId(graphId)
, m_endpoint(endpoint)
, m_nodeName(nodeName)
{
AZ::Vector2 stepSize = GraphCanvas::GraphUtils::FindMinorStep(graphId);
GraphCanvas::SlotUIRequestBus::EventResult(m_scenePoint, m_endpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetConnectionPoint);
QPointF jutDirection;
GraphCanvas::SlotUIRequestBus::EventResult(jutDirection, m_endpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetJutDirection);
AZ::Vector2 stepDirection = AZ::Vector2::CreateZero();
stepDirection.SetX(jutDirection.x() * stepSize.GetX());
stepDirection.SetY(jutDirection.y() * stepSize.GetY());
m_scenePoint.setX(m_scenePoint.x() + stepDirection.GetX() * 2);
}
CreateNodeFromProposalAction::CreateNodeFromProposalAction(GraphCanvas::GraphId graphId, GraphCanvas::Endpoint endpoint, QString nodeName, QPointF scenePoint)
: m_graphId(graphId)
, m_endpoint(endpoint)
, m_scenePoint(scenePoint)
, m_nodeName(nodeName)
{
}
bool CreateNodeFromProposalAction::IsMissingPrecondition()
{
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
QRectF viewableBounds;
GraphCanvas::ViewRequestBus::EventResult(viewableBounds, viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
QPointF pinCenter;
GraphCanvas::SlotUIRequestBus::EventResult(pinCenter, m_endpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetPinCenter);
QRectF sceneRect(pinCenter, m_scenePoint);
sceneRect.adjust(-10, -10, 10, 10);
return !viewableBounds.isEmpty() && !viewableBounds.contains(sceneRect);
}
EditorAutomationAction* CreateNodeFromProposalAction::GenerateMissingPreconditionAction()
{
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
QRectF viewableBounds;
GraphCanvas::ViewRequestBus::EventResult(viewableBounds, viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
QPointF pinCenter;
GraphCanvas::SlotUIRequestBus::EventResult(pinCenter, m_endpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetPinCenter);
QRectF sceneRect(pinCenter, m_scenePoint);
return aznew EnsureSceneRectVisibleAction(m_graphId, sceneRect);
}
void CreateNodeFromProposalAction::SetupAction()
{
ClearActionQueue();
m_createdNodeId.SetInvalid();
QPointF pinCenter;
GraphCanvas::SlotUIRequestBus::EventResult(pinCenter, m_endpoint.GetSlotId(), &GraphCanvas::SlotUIRequests::GetPinCenter);
AddAction(aznew SceneMouseDragAction(m_graphId, pinCenter, m_scenePoint));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew TypeStringAction(m_nodeName));
AddAction(aznew ProcessUserEventsAction());
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew TypeCharAction(VK_RETURN));
#endif
AddAction(aznew ProcessUserEventsAction());
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
CompoundAction::SetupAction();
}
void CreateNodeFromProposalAction::OnNodeAdded(const AZ::EntityId& nodeId, bool)
{
m_createdNodeId = nodeId;
}
AZ::EntityId CreateNodeFromProposalAction::GetCreatedNodeId() const
{
return GraphCanvas::GraphUtils::FindOutermostNode(m_createdNodeId);
}
AZ::EntityId CreateNodeFromProposalAction::GetConnectionId() const
{
GraphCanvas::ConnectionId lastConnectionId;
GraphCanvas::SlotRequestBus::EventResult(lastConnectionId, m_endpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
return lastConnectionId;
}
ActionReport CreateNodeFromProposalAction::GenerateReport() const
{
if (!m_createdNodeId.IsValid())
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create Node(%s)", m_nodeName.toUtf8().data()));
}
else
{
GraphCanvas::ConnectionId lastConnectionId;
GraphCanvas::SlotRequestBus::EventResult(lastConnectionId, m_endpoint.m_slotId, &GraphCanvas::SlotRequests::GetLastConnection);
GraphCanvas::Endpoint otherEndpoint;
GraphCanvas::ConnectionRequestBus::EventResult(otherEndpoint, lastConnectionId, &GraphCanvas::ConnectionRequests::FindOtherEndpoint, m_endpoint);
if (otherEndpoint.IsValid())
{
AZ::EntityId nodeId = GetCreatedNodeId();
if (otherEndpoint.GetNodeId() != nodeId)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create connection to Node(%s)", m_nodeName.toUtf8().data()));
}
}
else
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create connection to Node(%s)", m_nodeName.toUtf8().data()));
}
}
return CompoundAction::GenerateReport();
}
void CreateNodeFromProposalAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
}
//////////////////////
// CreateGroupAction
//////////////////////
CreateGroupAction::CreateGroupAction(GraphCanvas::EditorId editorId, GraphCanvas::GraphId graphId, CreationType creationType)
: m_editorId(editorId)
, m_graphId(graphId)
, m_creationType(creationType)
{
if (m_creationType == CreationType::Hotkey)
{
SetupHotkeyAction();
}
}
void CreateGroupAction::SetupAction()
{
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
m_createdGroup.SetInvalid();
if (m_creationType == CreationType::Toolbar)
{
SetupToolbarAction();
}
CompoundAction::SetupAction();
}
void CreateGroupAction::OnNodeAdded(const AZ::EntityId& groupId, bool)
{
m_createdGroup = groupId;
}
AZ::EntityId CreateGroupAction::GetCreatedGroupId() const
{
return m_createdGroup;
}
ActionReport CreateGroupAction::GenerateReport() const
{
if (!m_createdGroup.IsValid())
{
if (m_creationType == CreationType::Hotkey)
{
return AZ::Failure<AZStd::string>("Failed to create Group using HotKey");
}
else if (m_creationType == CreationType::Toolbar)
{
return AZ::Failure<AZStd::string>("Failed to create Group using Toolbar");
}
}
return CompoundAction::GenerateReport();
}
void CreateGroupAction::SetupToolbarAction()
{
QToolButton* createGroupButton = GraphCanvas::AutomationUtils::FindObjectById<QToolButton>(m_editorId, GraphCanvas::AutomationIds::GroupButton);
if (createGroupButton)
{
QPoint clickPoint = createGroupButton->mapToGlobal(createGroupButton->rect().center());
ClearActionQueue();
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, clickPoint));
}
AddAction(aznew ProcessUserEventsAction());
}
void CreateGroupAction::SetupHotkeyAction()
{
ClearActionQueue();
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyPressAction(VK_CONTROL));
AddAction(aznew KeyPressAction(VK_LSHIFT));
AddAction(aznew TypeCharAction('G'));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew KeyReleaseAction(VK_LSHIFT));
AddAction(aznew KeyReleaseAction(VK_CONTROL));
#endif
}
void CreateGroupAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
}
}
@@ -0,0 +1,188 @@
/*
* 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 <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
namespace ScriptCanvasDeveloper
{
/////////////////////////////
// CenterOnScenePointAction
/////////////////////////////
CenterOnScenePointAction::CenterOnScenePointAction(GraphCanvas::GraphId graphId, QPointF scenePoint)
: m_graphId(graphId)
, m_scenePoint(scenePoint)
{
}
bool CenterOnScenePointAction::Tick()
{
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
if (viewId.IsValid())
{
GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOn, m_scenePoint);
}
return true;
}
/////////////////////////////////
// EnsureSceneRectVisibleAction
/////////////////////////////////
EnsureSceneRectVisibleAction::EnsureSceneRectVisibleAction(GraphCanvas::GraphId graphId, QRectF sceneRect)
: DelayAction(AZStd::chrono::milliseconds(250))
, m_graphId(graphId)
, m_sceneRect(sceneRect)
{
}
void EnsureSceneRectVisibleAction::SetupAction()
{
DelayAction::SetupAction();
m_firstTick = true;
}
bool EnsureSceneRectVisibleAction::Tick()
{
if (m_firstTick)
{
m_firstTick = false;
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
if (viewId.IsValid())
{
GraphCanvas::ViewRequestBus::Event(viewId, &GraphCanvas::ViewRequests::CenterOnArea, m_sceneRect);
}
return false;
}
else
{
return DelayAction::Tick();
}
}
/////////////////////////
// SceneMouseMoveAction
/////////////////////////
SceneMouseMoveAction::SceneMouseMoveAction(GraphCanvas::GraphId graphId, QPointF scenePoint)
: m_graphId(graphId)
, m_scenePoint(scenePoint)
{
GraphCanvas::SceneRequestBus::EventResult(m_viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
}
bool SceneMouseMoveAction::IsMissingPrecondition()
{
QRectF viewableBounds = QRectF(m_scenePoint, m_scenePoint);
viewableBounds.adjust(-10, -10, 10, 10);
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, m_viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
return !viewableArea.isEmpty() && !viewableArea.contains(viewableBounds);
}
EditorAutomationAction* SceneMouseMoveAction::GenerateMissingPreconditionAction()
{
QRectF viewableBounds = QRectF(m_scenePoint, m_scenePoint);
viewableBounds.adjust(-10, -10, 10, 10);
return aznew EnsureSceneRectVisibleAction(m_graphId, viewableBounds);
}
void SceneMouseMoveAction::SetupAction()
{
ClearActionQueue();
AZ::Vector2 tempVector = AZ::Vector2::CreateZero();
QPoint screenPoint;
GraphCanvas::ViewRequestBus::EventResult(tempVector, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
screenPoint = GraphCanvas::ConversionUtils::AZToQPoint(tempVector).toPoint();
AddAction(aznew MouseMoveAction(screenPoint));
CompoundAction::SetupAction();
}
/////////////////////////
// SceneMouseDragAction
/////////////////////////
SceneMouseDragAction::SceneMouseDragAction(GraphCanvas::GraphId graphId, QPointF sceneStart, QPointF sceneEnd, Qt::MouseButton mouseButton)
: m_graphId(graphId)
, m_sceneStart(sceneStart)
, m_sceneEnd(sceneEnd)
, m_mouseButton(mouseButton)
{
GraphCanvas::SceneRequestBus::EventResult(m_viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
}
bool SceneMouseDragAction::IsMissingPrecondition()
{
QRectF viewableBounds = QRectF(m_sceneStart, m_sceneEnd);
viewableBounds.adjust(-10, -10, 10, 10);
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, m_viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
return !viewableArea.contains(viewableBounds);
}
EditorAutomationAction* SceneMouseDragAction::GenerateMissingPreconditionAction()
{
QRectF viewableBounds = QRectF(m_sceneStart, m_sceneEnd);
viewableBounds.adjust(-10, -10, 10, 10);
return aznew EnsureSceneRectVisibleAction(m_graphId, viewableBounds);
}
void SceneMouseDragAction::SetupAction()
{
AZ::Vector2 tempVector = AZ::Vector2::CreateZero();
QPoint screenStart;
GraphCanvas::ViewRequestBus::EventResult(tempVector, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_sceneStart));
screenStart = GraphCanvas::ConversionUtils::AZToQPoint(tempVector).toPoint();
tempVector = AZ::Vector2::CreateZero();
QPoint screenEnd;
GraphCanvas::ViewRequestBus::EventResult(tempVector, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_sceneEnd));
screenEnd = GraphCanvas::ConversionUtils::AZToQPoint(tempVector).toPoint();
AddAction(aznew MouseDragAction(screenStart, screenEnd, m_mouseButton));
CompoundAction::SetupAction();
}
}
@@ -0,0 +1,245 @@
/*
* 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 <AzCore/PlatformIncl.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
namespace ScriptCanvasDeveloper
{
/////////////////////////////
// SelectSceneElementAction
/////////////////////////////
SelectSceneElementAction::SelectSceneElementAction(AZ::EntityId sceneMemberId)
: m_sceneMemberId(sceneMemberId)
{
GraphCanvas::SceneMemberRequestBus::EventResult(m_graphId, m_sceneMemberId, &GraphCanvas::SceneMemberRequests::GetScene);
GraphCanvas::SceneRequestBus::EventResult(m_viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
if (!GraphCanvas::GraphUtils::IsConnection(sceneMemberId))
{
QRectF boundingRect;
QGraphicsItem* graphicsItem = nullptr;
GraphCanvas::VisualRequestBus::EventResult(graphicsItem, sceneMemberId, &GraphCanvas::VisualRequests::AsGraphicsItem);
if (graphicsItem)
{
boundingRect = graphicsItem->sceneBoundingRect();
}
m_scenePoint = boundingRect.topLeft();
m_scenePoint.setX(boundingRect.center().x());
m_scenePoint.setY(m_scenePoint.y() + 5);
}
else
{
QPainterPath outlinePath;
GraphCanvas::SceneMemberUIRequestBus::EventResult(outlinePath, sceneMemberId, &GraphCanvas::SceneMemberUIRequests::GetOutline);
m_scenePoint = outlinePath.pointAtPercent(0.5);
}
}
bool SelectSceneElementAction::IsMissingPrecondition()
{
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, m_viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
return m_sceneMemberId.IsValid() && m_graphId.IsValid() && !viewableArea.contains(m_scenePoint);
}
EditorAutomationAction* SelectSceneElementAction::GenerateMissingPreconditionAction()
{
CompoundAction* compoundAction = aznew CompoundAction();
QPoint startPoint(m_scenePoint.x() - 5, m_scenePoint.y() - 5);
QPoint endPoint(m_scenePoint.x() + 5, m_scenePoint.y() + 5);
QRect sceneRect = QRect(startPoint, endPoint);
compoundAction->AddAction(aznew EnsureSceneRectVisibleAction(m_graphId, sceneRect));
compoundAction->AddAction(aznew ProcessUserEventsAction());
return compoundAction;
}
void SelectSceneElementAction::SetupAction()
{
ClearActionQueue();
AZ::Vector2 screenPoint = AZ::Vector2::CreateZero();
GraphCanvas::ViewRequestBus::EventResult(screenPoint, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, GraphCanvas::ConversionUtils::AZToQPoint(screenPoint).toPoint()));
AddAction(aznew ProcessUserEventsAction());
CompoundAction::SetupAction();
}
///////////////////////////////
// AltClickSceneElementAction
///////////////////////////////
AltClickSceneElementAction::AltClickSceneElementAction(AZ::EntityId sceneMemberId)
: m_sceneMemberId(sceneMemberId)
{
GraphCanvas::SceneMemberRequestBus::EventResult(m_graphId, m_sceneMemberId, &GraphCanvas::SceneMemberRequests::GetScene);
GraphCanvas::SceneRequestBus::EventResult(m_viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
if (!GraphCanvas::GraphUtils::IsConnection(sceneMemberId))
{
QRectF boundingRect;
QGraphicsItem* graphicsItem = nullptr;
GraphCanvas::VisualRequestBus::EventResult(graphicsItem, sceneMemberId, &GraphCanvas::VisualRequests::AsGraphicsItem);
if (graphicsItem)
{
boundingRect = graphicsItem->sceneBoundingRect();
}
m_scenePoint = boundingRect.topLeft();
m_scenePoint.setX(boundingRect.center().x());
m_scenePoint.setY(m_scenePoint.y() + 5);
}
else
{
QPainterPath outlinePath;
GraphCanvas::SceneMemberUIRequestBus::EventResult(outlinePath, sceneMemberId, &GraphCanvas::SceneMemberUIRequests::GetOutline);
m_scenePoint = outlinePath.pointAtPercent(0.5);
}
}
bool AltClickSceneElementAction::IsMissingPrecondition()
{
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, m_viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
return !viewableArea.contains(m_scenePoint);
}
EditorAutomationAction* AltClickSceneElementAction::GenerateMissingPreconditionAction()
{
CompoundAction* compoundAction = aznew CompoundAction();
QPoint startPoint(m_scenePoint.x() - 5, m_scenePoint.y() - 5);
QPoint endPoint(m_scenePoint.x() + 5, m_scenePoint.y() + 5);
QRect sceneRect = QRect(startPoint, endPoint);
compoundAction->AddAction(aznew EnsureSceneRectVisibleAction(m_graphId, sceneRect));
compoundAction->AddAction(aznew ProcessUserEventsAction());
return compoundAction;
}
void AltClickSceneElementAction::SetupAction()
{
ClearActionQueue();
m_sceneMemberRemoved = false;
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyPressAction(VK_LMENU));
AZ::Vector2 screenPoint = AZ::Vector2::CreateZero();
GraphCanvas::ViewRequestBus::EventResult(screenPoint, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, GraphCanvas::ConversionUtils::AZToQPoint(screenPoint).toPoint()));
AddAction(aznew KeyReleaseAction(VK_LMENU));
AddAction(aznew ProcessUserEventsAction(AZStd::chrono::milliseconds(750)));
#endif
CompoundAction::SetupAction();
}
ActionReport AltClickSceneElementAction::GenerateReport() const
{
if (!m_sceneMemberRemoved)
{
return AZ::Failure<AZStd::string>("Failed to delete target scene element with Alt+Click");
}
return CompoundAction::GenerateReport();
}
void AltClickSceneElementAction::OnNodeRemoved(const AZ::EntityId& nodeId)
{
if (m_sceneMemberId == nodeId)
{
m_sceneMemberRemoved = true;
}
}
void AltClickSceneElementAction::OnConnectionRemoved(const AZ::EntityId& connectionId)
{
if (m_sceneMemberId == connectionId)
{
m_sceneMemberRemoved = true;
}
}
void AltClickSceneElementAction::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
}
////////////////////////////////////
// MouseToNodePropertyEditorAction
////////////////////////////////////
MouseToNodePropertyEditorAction::MouseToNodePropertyEditorAction(GraphCanvas::SlotId slotId)
: m_slotId(slotId)
{
}
void MouseToNodePropertyEditorAction::SetupAction()
{
ClearActionQueue();
GraphCanvas::NodeId nodeId;
GraphCanvas::SlotRequestBus::EventResult(nodeId, m_slotId, &GraphCanvas::SlotRequests::GetNode);
GraphCanvas::GraphId graphId;
GraphCanvas::SceneMemberRequestBus::EventResult(graphId, nodeId, &GraphCanvas::SceneMemberRequests::GetScene);
QRectF sceneBoundingRect;
GraphCanvas::SlotRequestBus::EventResult(nodeId, m_slotId, &GraphCanvas::SlotRequests::GetNode);
GraphCanvas::DataSlotLayoutRequestBus::EventResult(sceneBoundingRect, m_slotId, &GraphCanvas::DataSlotLayoutRequests::GetWidgetSceneBoundingRect);
AddAction(aznew SceneMouseMoveAction(graphId, sceneBoundingRect.center()));
CompoundAction::SetupAction();
}
}
@@ -0,0 +1,244 @@
/*
* 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 <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Editor/Automation/AutomationUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <Editor/GraphCanvas/AutomationIds.h>
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/GraphActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
namespace ScriptCanvasDeveloper
{
/////////////////////////
// CreateNewGraphAction
/////////////////////////
CreateNewGraphAction::CreateNewGraphAction()
{
}
void CreateNewGraphAction::SetupAction()
{
m_graphId.SetInvalid();
ClearActionQueue();
QToolButton* createNewGraphButton = GraphCanvas::AutomationUtils::FindObjectById<QToolButton>(ScriptCanvasEditor::AssetEditorId, ScriptCanvasEditor::AutomationIds::CreateScriptCanvasButton);
if (createNewGraphButton)
{
QPointF point = createNewGraphButton->mapToGlobal(createNewGraphButton->rect().center());
m_newGraphAction = aznew WaitForNewGraphAction();
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, point.toPoint()));
AddAction(m_newGraphAction);
}
CompoundAction::SetupAction();
}
GraphCanvas::GraphId CreateNewGraphAction::GetGraphId() const
{
return m_graphId;
}
ActionReport CreateNewGraphAction::GenerateReport() const
{
if (!m_graphId.IsValid())
{
return AZ::Failure<AZStd::string>("Failed to create New Runtime Graph");
}
else
{
GraphCanvas::GraphId activeGraphCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(activeGraphCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
if (activeGraphCanvasId != m_graphId)
{
return AZ::Failure<AZStd::string>("Active graph is not the newly created graph.");
}
else
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetScriptCanvasId, activeGraphCanvasId);
bool isRuntimeGraph = false;
ScriptCanvasEditor::EditorGraphRequestBus::EventResult(isRuntimeGraph, scriptCanvasId, &ScriptCanvasEditor::EditorGraphRequests::IsRuntimeGraph);
if (!isRuntimeGraph)
{
return AZ::Failure<AZStd::string>("Created a new Graph, but graph is not of type Runtime Graph.");
}
}
}
return CompoundAction::GenerateReport();
}
void CreateNewGraphAction::OnActionsComplete()
{
m_graphId = m_newGraphAction->GetGraphId();
}
////////////////////////////
// CreateNewFunctionAction
////////////////////////////
CreateNewFunctionAction::CreateNewFunctionAction()
: CreateNewGraphAction()
{
}
void CreateNewFunctionAction::SetupAction()
{
m_graphId.SetInvalid();
ClearActionQueue();
QToolButton* createNewFunctionButton = GraphCanvas::AutomationUtils::FindObjectById<QToolButton>(ScriptCanvasEditor::AssetEditorId, ScriptCanvasEditor::AutomationIds::CreateScriptCanvasFunctionButton);
if (createNewFunctionButton)
{
QPointF point = createNewFunctionButton->mapToGlobal(createNewFunctionButton->rect().center());
m_newGraphAction = aznew WaitForNewGraphAction();
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, point.toPoint()));
AddAction(m_newGraphAction);
}
CompoundAction::SetupAction();
}
ActionReport CreateNewFunctionAction::GenerateReport() const
{
if (!m_graphId.IsValid())
{
return AZ::Failure<AZStd::string>("Failed to create New Function");
}
else
{
GraphCanvas::GraphId activeGraphCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(activeGraphCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
if (activeGraphCanvasId != m_graphId)
{
return AZ::Failure<AZStd::string>("Active graph is not the newly created function.");
}
else
{
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetScriptCanvasId, activeGraphCanvasId);
bool isFunctionGraph = false;
ScriptCanvasEditor::EditorGraphRequestBus::EventResult(isFunctionGraph, scriptCanvasId, &ScriptCanvasEditor::EditorGraphRequests::IsFunctionGraph);
if (!isFunctionGraph)
{
return AZ::Failure<AZStd::string>("Created a new Graph, but graph is not of type Function.");
}
}
}
return CompoundAction::GenerateReport();
}
void CreateNewFunctionAction::OnActionsComplete()
{
m_graphId = m_newGraphAction->GetGraphId();
}
////////////////////////////////
// ForceCloseActiveGraphAction
////////////////////////////////
ForceCloseActiveGraphAction::ForceCloseActiveGraphAction()
: ProcessUserEventsAction(AZStd::chrono::milliseconds(500))
{
}
void ForceCloseActiveGraphAction::SetupAction()
{
ProcessUserEventsAction::SetupAction();
m_firstTick = true;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(m_activeGraphId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
}
bool ForceCloseActiveGraphAction::Tick()
{
if (m_firstTick)
{
ScriptCanvasEditor::AutomationRequestBus::Broadcast(&ScriptCanvasEditor::AutomationRequests::ForceCloseActiveAsset);
return true;
}
else
{
return ProcessUserEventsAction::Tick();
}
}
ActionReport ForceCloseActiveGraphAction::GenerateReport() const
{
GraphCanvas::GraphId activeGraphCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(activeGraphCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveGraphCanvasGraphId);
if (activeGraphCanvasId == m_activeGraphId
&& m_activeGraphId.IsValid())
{
return AZ::Failure<AZStd::string>("Failed to close down currently active graph");
}
return ProcessUserEventsAction::GenerateReport();
}
////////////////////////////////
// WaitForNewGraphAction
////////////////////////////////
WaitForNewGraphAction::WaitForNewGraphAction()
{
m_newGraphCreated = false;
GraphCanvas::AssetEditorNotificationBus::Handler::BusConnect(ScriptCanvasEditor::AssetEditorId);
}
WaitForNewGraphAction::~WaitForNewGraphAction()
{
GraphCanvas::AssetEditorNotificationBus::Handler::BusDisconnect();
}
bool WaitForNewGraphAction::Tick()
{
return m_newGraphCreated;
}
void WaitForNewGraphAction::OnActiveGraphChanged(const AZ::EntityId& graphId)
{
m_graphId = graphId;
m_newGraphCreated = true;
GraphCanvas::AssetEditorNotificationBus::Handler::BusDisconnect();
}
}
@@ -0,0 +1,444 @@
/*
* 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 <QApplication>
#include <QPushButton>
#include <QTableView>
#include <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Widgets/NodePalette/Model/NodePaletteSortFilterProxyModel.h>
#include <GraphCanvas/Widgets/NodePalette/NodePaletteTreeView.h>
#include <GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/WidgetActions.h>
#if !defined(AZ_COMPILER_MSVC)
#ifndef VK_RETURN
#define VK_RETURN 0x0D
#endif
#ifndef VK_ESCAPE
#define VK_ESCAPE 0x1B
#endif
#endif
namespace ScriptCanvasDeveloper
{
/////////////////////////
// CreateVariableAction
/////////////////////////
CreateVariableAction::CreateVariableAction(ScriptCanvas::Data::Type dataType, CreationType creationType)
: m_creationType(creationType)
, m_dataType(dataType)
, m_typeName(ScriptCanvas::Data::GetName(dataType).c_str())
{
}
CreateVariableAction::CreateVariableAction(ScriptCanvas::Data::Type dataType, QString variableName, CreationType creationType)
: m_creationType(creationType)
, m_variableName(variableName)
, m_dataType(dataType)
, m_typeName(ScriptCanvas::Data::GetName(dataType).c_str())
{
}
void CreateVariableAction::SetErrorOnNameMisMatch(bool enabled)
{
m_errorOnNameMismatch = enabled;
}
void CreateVariableAction::SetupAction()
{
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(m_scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetActiveScriptCanvasId);
ClearActionQueue();
if (m_creationType != CreationType::Programmatic)
{
bool isShowingCreatePalette = false;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(isShowingCreatePalette, &ScriptCanvasEditor::VariableAutomationRequests::IsShowingVariablePalette);
if (!isShowingCreatePalette)
{
QPushButton* targetButton = nullptr;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(targetButton, &ScriptCanvasEditor::VariableAutomationRequests::GetCreateVariableButton);
QPoint targetPoint = targetButton->mapToGlobal(targetButton->rect().center());
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, targetPoint));
AddAction(aznew ProcessUserEventsAction());
}
QLineEdit* searchFilter = nullptr;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(searchFilter, &ScriptCanvasEditor::VariableAutomationRequests::GetVariablePaletteFilter);
if (searchFilter)
{
AddAction(aznew WriteToLineEditAction(searchFilter, m_typeName));
}
}
switch (m_creationType)
{
case CreationType::Palette:
{
QTableView* variableView = nullptr;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(variableView, &ScriptCanvasEditor::VariableAutomationRequests::GetVariablePaletteTableView);
AddAction(aznew ProcessUserEventsAction(AZStd::chrono::milliseconds(500)));
AddAction(aznew MoveMouseToViewRowAction(variableView, 0));
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton));
}
break;
case CreationType::AutoComplete:
{
AddAction(aznew TypeCharAction(VK_RETURN));
}
break;
case CreationType::Programmatic:
{
bool nameAvailable = false;
AZStd::string variableName;
if (!m_variableName.isEmpty())
{
variableName = m_variableName.toUtf8().data();
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::IsNameAvailable, variableName);
}
if (!nameAvailable)
{
int variableCounter = 1;
do
{
ScriptCanvasEditor::SceneCounterRequestBus::EventResult(variableCounter, m_scriptCanvasId, &ScriptCanvasEditor::SceneCounterRequests::GetNewVariableCounter);
// Cribbed from VariableDockWidget. Shuld always be in sync with that.
variableName = AZStd::string::format("Variable %u", variableCounter);
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::IsNameAvailable, variableName);
} while (!nameAvailable);
}
ScriptCanvas::Datum datum(m_dataType, 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);
if (outcome)
{
m_variableId = outcome.GetValue();
}
}
break;
default:
break;
}
AddAction(aznew ProcessUserEventsAction());
if (m_creationType != CreationType::Programmatic)
{
if (!m_variableName.isEmpty())
{
AddAction(aznew TypeStringAction(m_variableName));
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew TypeCharAction(VK_RETURN));
AddAction(aznew ProcessUserEventsAction());
}
else
{
AddAction(aznew TypeCharAction(VK_ESCAPE));
AddAction(aznew ProcessUserEventsAction());
}
}
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusConnect(m_scriptCanvasId);
CompoundAction::SetupAction();
}
ScriptCanvas::VariableId CreateVariableAction::GetVariableId() const
{
return m_variableId;
}
void CreateVariableAction::OnVariableAddedToGraph(const ScriptCanvas::VariableId& variableId, AZStd::string_view /*variableName*/)
{
m_variableId = variableId;
}
ActionReport CreateVariableAction::GenerateReport() const
{
if (!m_variableId.IsValid())
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to create Variable with type %s", ScriptCanvas::Data::GetName(m_dataType).c_str()));
}
else if (!m_variableName.isEmpty() && m_errorOnNameMismatch)
{
ScriptCanvas::GraphVariable* graphVariable = nullptr;
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, m_variableId);
if (graphVariable)
{
if (m_variableName.compare(graphVariable->GetVariableName().data(), Qt::CaseInsensitive) != 0)
{
return AZ::Failure<AZStd::string>(AZStd::string::format("Failed to name Variable %s", m_variableName.toUtf8().data()));
}
}
}
return CompoundAction::GenerateReport();
}
void CreateVariableAction::OnActionsComplete()
{
ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect();
}
///////////////////////////////////////
// CreateVariableNodeFromGraphPalette
///////////////////////////////////////
CreateVariableNodeFromGraphPalette::CreateVariableNodeFromGraphPalette(const AZStd::string& variableName, const GraphCanvas::GraphId& graphId, QPoint scenePoint, Qt::KeyboardModifier modifier)
: m_variableName(variableName)
, m_graphId(graphId)
, m_modifier(modifier)
, m_scenePoint(scenePoint)
{
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(m_graphPalette, &ScriptCanvasEditor::VariableAutomationRequests::GetGraphPaletteTableView);
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(m_textFilter, &ScriptCanvasEditor::VariableAutomationRequests::GetGraphVariablesFilter);
GraphCanvas::SceneRequestBus::EventResult(m_viewId, m_graphId, &GraphCanvas::SceneRequests::GetViewId);
}
bool CreateVariableNodeFromGraphPalette::IsMissingPrecondition()
{
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(m_isShowingPalette, &ScriptCanvasEditor::VariableAutomationRequests::IsShowingGraphVariables);
if (m_textFilter)
{
m_isFiltered = (m_textFilter->text().compare(m_variableName.c_str(), Qt::CaseInsensitive) == 0);
}
else
{
m_isFiltered = true;
}
m_indexIsVisible = false;
m_displayIndex = QModelIndex();
if (m_isFiltered)
{
int rowCount = m_graphPalette->model()->rowCount();
for (int i = 0; i < rowCount; ++i)
{
m_displayIndex = m_graphPalette->model()->index(i, 0);
if (m_displayIndex.isValid())
{
QVariant variant = m_graphPalette->model()->data(m_displayIndex, Qt::DisplayRole);
QString name = variant.toString();
if (name.compare(m_variableName.c_str(), Qt::CaseInsensitive) == 0)
{
break;
}
}
}
QRegion region = m_graphPalette->visibleRegion();
QRect boundingRegion = region.boundingRect();
m_indexIsVisible = region.contains(m_graphPalette->visualRect(m_displayIndex).center());
}
m_scenePointVisible = false;
QRectF viewableArea;
GraphCanvas::ViewRequestBus::EventResult(viewableArea, m_viewId, &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
m_scenePointVisible = viewableArea.contains(m_scenePoint);
return !m_isShowingPalette || !m_isFiltered || !m_indexIsVisible || ! m_scenePointVisible;
}
EditorAutomationAction* CreateVariableNodeFromGraphPalette::GenerateMissingPreconditionAction()
{
CompoundAction* compoundAction = aznew CompoundAction();
if (!m_isShowingPalette)
{
QPushButton* pushButton = nullptr;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(pushButton, &ScriptCanvasEditor::VariableAutomationRequests::GetCreateVariableButton);
MouseClickAction* clickAction = aznew MouseClickAction(Qt::MouseButton::LeftButton, pushButton->mapToGlobal(pushButton->rect().center()));
compoundAction->AddAction(clickAction);
compoundAction->AddAction(aznew ProcessUserEventsAction());
}
else if (!m_isFiltered)
{
compoundAction->AddAction(aznew WriteToLineEditAction(m_textFilter, m_variableName.c_str()));
compoundAction->AddAction(aznew ProcessUserEventsAction());
}
else if (!m_indexIsVisible)
{
m_graphPalette->scrollTo(m_displayIndex);
compoundAction->AddAction(aznew ProcessUserEventsAction());
}
if (!m_scenePointVisible)
{
QRect sceneRect(m_scenePoint, m_scenePoint);
sceneRect.adjust(-5, -5, 5, 5);
compoundAction->AddAction(aznew EnsureSceneRectVisibleAction(m_graphId, sceneRect));
compoundAction->AddAction(aznew ProcessUserEventsAction());
}
return compoundAction;
}
void CreateVariableNodeFromGraphPalette::SetupAction()
{
m_createdNodeId.SetInvalid();
GraphCanvas::SceneNotificationBus::Handler::BusConnect(m_graphId);
ClearActionQueue();
QPoint screenPoint = m_graphPalette->mapToGlobal(m_graphPalette->visualRect(m_displayIndex).center());
AZ::Vector2 targetPoint;
GraphCanvas::ViewRequestBus::EventResult(targetPoint, m_viewId, &GraphCanvas::ViewRequests::MapToGlobal, GraphCanvas::ConversionUtils::QPointToVector(m_scenePoint));
AZ::Vector2 flushTarget = targetPoint + AZ::Vector2(1, 1);
if (m_modifier == Qt::ShiftModifier)
{
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyPressAction(VK_LSHIFT));
#endif
}
else if (m_modifier == Qt::AltModifier)
{
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyPressAction(VK_LMENU));
#endif
}
AddAction(aznew MouseDragAction(screenPoint, GraphCanvas::ConversionUtils::AZToQPoint(targetPoint).toPoint()));
AddAction(aznew ProcessUserEventsAction());
if (m_modifier == Qt::ShiftModifier)
{
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyReleaseAction(VK_LSHIFT));
#endif
}
else if (m_modifier == Qt::AltModifier)
{
#if defined(AZ_COMPILER_MSVC)
AddAction(aznew KeyReleaseAction(VK_LMENU));
#endif
}
AddAction(aznew ProcessUserEventsAction());
AddAction(aznew MouseMoveAction(GraphCanvas::ConversionUtils::AZToQPoint(flushTarget).toPoint()));
AddAction(aznew ProcessUserEventsAction());
CompoundAction::SetupAction();
}
void CreateVariableNodeFromGraphPalette::OnNodeAdded(const AZ::EntityId& nodeId, bool)
{
m_createdNodeId = nodeId;
}
void CreateVariableNodeFromGraphPalette::OnActionsComplete()
{
GraphCanvas::SceneNotificationBus::Handler::BusDisconnect();
}
AZ::EntityId CreateVariableNodeFromGraphPalette::GetCreatedNodeId() const
{
return GraphCanvas::GraphUtils::FindOutermostNode(m_createdNodeId);
}
ActionReport CreateVariableNodeFromGraphPalette::GenerateReport() const
{
if (!m_createdNodeId.IsValid())
{
AZStd::string errorString = AZStd::string::format("Failed to create a node for Variable(%s) from the Variable Palette", m_variableName.c_str());
return AZ::Failure(errorString);
}
return CompoundAction::GenerateReport();
}
/////////////////////////////
// ShowGraphVariablesAction
/////////////////////////////
void ShowGraphVariablesAction::SetupAction()
{
ClearActionQueue();
bool isShowingGraphPalette = false;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(isShowingGraphPalette, &ScriptCanvasEditor::VariableAutomationRequests::IsShowingGraphVariables);
if (!isShowingGraphPalette)
{
QPushButton* createButton = nullptr;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(createButton, &ScriptCanvasEditor::VariableAutomationRequests::GetCreateVariableButton);
AddAction(aznew MouseClickAction(Qt::MouseButton::LeftButton, createButton->mapToGlobal(createButton->rect().center())));
AddAction(aznew ProcessUserEventsAction());
}
CompoundAction::SetupAction();
}
ActionReport ShowGraphVariablesAction::GenerateReport() const
{
bool isShowingGraphPalette = false;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(isShowingGraphPalette, &ScriptCanvasEditor::VariableAutomationRequests::IsShowingGraphVariables);
if (!isShowingGraphPalette)
{
return AZ::Failure<AZStd::string>("Failed to Show Graph Variable");
}
return CompoundAction::GenerateReport();
}
}
@@ -0,0 +1,93 @@
/*
* 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 <QTableView>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/WidgetActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
namespace ScriptCanvasDeveloper
{
//////////////////////////
// WriteToLineEditAction
//////////////////////////
WriteToLineEditAction::WriteToLineEditAction(QLineEdit* targetEdit, QString targetText)
: m_targetEdit(targetEdit)
, m_targetText(targetText)
{
}
void WriteToLineEditAction::SetupAction()
{
ClearActionQueue();
QPoint targetPoint = m_targetEdit->mapToGlobal(QPoint(5, m_targetEdit->height() * 0.5f));
// Cheaty clear for right now.
m_targetEdit->clear();
AddAction(aznew ScriptCanvasDeveloper::MouseClickAction(Qt::MouseButton::LeftButton, targetPoint));
AddAction(aznew ScriptCanvasDeveloper::TypeStringAction(m_targetText));
CompoundAction::SetupAction();
}
/////////////////////////////
// MoveMouseToViewRowAction
/////////////////////////////
MoveMouseToViewRowAction::MoveMouseToViewRowAction(QAbstractItemView* itemView, int row, QModelIndex parentIndex)
: m_itemView(itemView)
, m_row(row)
, m_parentIndex(parentIndex)
{
}
void MoveMouseToViewRowAction::SetupAction()
{
ClearActionQueue();
QModelIndex index = m_itemView->model()->index(m_row, 0, m_parentIndex);
if (index.isValid())
{
QRect targetRect = m_itemView->visualRect(index);
int column = 1;
while (column < m_itemView->model()->columnCount())
{
targetRect |= m_itemView->visualRect(m_itemView->model()->index(m_row, column, m_parentIndex));
++column;
}
AddAction(aznew MouseMoveAction(m_itemView->mapToGlobal(targetRect.center())));
}
CompoundAction::SetupAction();
}
}
@@ -0,0 +1,131 @@
/*
* 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 <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/ConnectionStates.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ConnectionActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
namespace ScriptCanvasDeveloper
{
/////////////////////
// CoupleNodesState
/////////////////////
CoupleNodesState::CoupleNodesState(AutomationStateModelId pickUpNode, GraphCanvas::ConnectionType connectionType, AutomationStateModelId targetNode, AutomationStateModelId outputId)
: NamedAutomationState("CoupleNodesState")
, m_pickUpNode(pickUpNode)
, m_targetNode(targetNode)
, m_connectionType(connectionType)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("CoupleNodes::%s::%s", m_pickUpNode.c_str(), m_targetNode.c_str()));
}
void CoupleNodesState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::NodeId* pickUpNodeId = GetStateModel()->GetStateDataAs<GraphCanvas::NodeId>(m_pickUpNode);
const GraphCanvas::NodeId* targetNodeId = GetStateModel()->GetStateDataAs<GraphCanvas::NodeId>(m_targetNode);
if (pickUpNodeId && targetNodeId)
{
m_coupleNodesAction = aznew CoupleNodesAction((*pickUpNodeId), m_connectionType, (*targetNodeId));
actionRunner.AddAction(m_coupleNodesAction);
}
else
{
if (pickUpNodeId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_pickUpNode.c_str()));
}
if (targetNodeId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_targetNode.c_str()));
}
}
}
void CoupleNodesState::OnStateActionsComplete()
{
if (!m_outputId.empty())
{
AZStd::vector< GraphCanvas::ConnectionId > connectionId = m_coupleNodesAction->GetConnectionIds();
GetStateModel()->SetStateData(m_outputId, connectionId);
}
delete m_coupleNodesAction;
m_coupleNodesAction = nullptr;
}
//////////////////////////
// ConnectEndpointsState
//////////////////////////
ConnectEndpointsState::ConnectEndpointsState(AutomationStateModelId sourceEndpoint, AutomationStateModelId targetEndpoint, AutomationStateModelId outputId)
: NamedAutomationState("ConnectEndpointsState")
, m_sourceEndpoint(sourceEndpoint)
, m_targetEndpoint(targetEndpoint)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("ConnectEndpoints::%s::%s", sourceEndpoint.c_str(), targetEndpoint.c_str()));
}
void ConnectEndpointsState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::Endpoint* sourceEndpoint = GetStateModel()->GetStateDataAs<GraphCanvas::Endpoint>(m_sourceEndpoint);
const GraphCanvas::Endpoint* targetEndpoint = GetStateModel()->GetStateDataAs<GraphCanvas::Endpoint>(m_targetEndpoint);
if (sourceEndpoint && targetEndpoint)
{
m_connectEndpointsAction = aznew ConnectEndpointsAction((*sourceEndpoint), (*targetEndpoint));
actionRunner.AddAction(m_connectEndpointsAction);
}
else
{
if (sourceEndpoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::Endpoint", m_sourceEndpoint.c_str()));
}
if (targetEndpoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::Endpoint", m_targetEndpoint.c_str()));
}
}
}
void ConnectEndpointsState::OnStateActionsComplete()
{
if (!m_outputId.empty())
{
GraphCanvas::ConnectionId connectionId = m_connectEndpointsAction->GetConnectionId();
GetStateModel()->SetStateData(m_outputId, connectionId);
}
delete m_connectEndpointsAction;
m_connectEndpointsAction = nullptr;
}
}
@@ -0,0 +1,408 @@
/*
* 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 <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Editor/Automation/AutomationIds.h>
#include <GraphCanvas/Editor/Automation/AutomationUtils.h>
#include <GraphCanvas/Widgets/NodePalette/Model/NodePaletteSortFilterProxyModel.h>
#include <GraphCanvas/Widgets/NodePalette/NodePaletteTreeView.h>
#include <GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/CreateElementsStates.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/WidgetActions.h>
namespace ScriptCanvasDeveloper
{
///////////////////////////////
// CreateNodeFromPaletteState
///////////////////////////////
CreateNodeFromPaletteState::CreateNodeFromPaletteState(GraphCanvas::NodePaletteWidget* paletteWidget, const QString& nodeName, CreationType creationType, AutomationStateModelId creationDataId, AutomationStateModelId outputId)
: NamedAutomationState("CreateNodeFromPaletteState")
, m_nodePaletteWidget(paletteWidget)
, m_nodeName(nodeName)
, m_creationType(creationType)
, m_creationDataId(creationDataId)
, m_outputId(outputId)
, m_delayAction(AZStd::chrono::milliseconds(500))
{
AZStd::string nameString = AZStd::string::format("CreateNodeFromPaletteState::%s", nodeName.toUtf8().data());
SetStateName(nameString);
}
void CreateNodeFromPaletteState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
if (graphId != nullptr && m_nodePaletteWidget != nullptr)
{
switch (m_creationType)
{
case CreationType::ScenePosition:
{
const AZ::Vector2* dropPoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_creationDataId);
if (dropPoint)
{
QPointF qPoint = QPoint(dropPoint->GetX(), dropPoint->GetY());
m_createNodeAction = aznew CreateNodeFromPaletteAction(m_nodePaletteWidget, (*graphId), m_nodeName, qPoint);
}
break;
}
case CreationType::Splice:
{
const GraphCanvas::ConnectionId* connectionId = GetStateModel()->GetStateDataAs<GraphCanvas::ConnectionId>(m_creationDataId);
if (connectionId)
{
m_createNodeAction = aznew CreateNodeFromPaletteAction(m_nodePaletteWidget, (*graphId), m_nodeName, (*connectionId));
}
break;
}
default:
break;
}
if (m_createNodeAction)
{
actionRunner.AddAction(m_createNodeAction);
actionRunner.AddAction(&m_delayAction);
}
else
{
ReportError("Unknown creation type provided");
}
}
else
{
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
if (m_nodePaletteWidget == nullptr)
{
ReportError(AZStd::string::format("NodePaletteWidget not provided"));
}
}
}
void CreateNodeFromPaletteState::OnStateActionsComplete()
{
if (m_createNodeAction)
{
if (!m_outputId.empty())
{
GraphCanvas::NodeId nodeId = m_createNodeAction->GetCreatedNodeId();
GetStateModel()->SetStateData(m_outputId, nodeId);
}
delete m_createNodeAction;
m_createNodeAction = nullptr;
}
}
///////////////////////////////////////
// CreateCategoryFromNodePaletteState
///////////////////////////////////////
CreateCategoryFromNodePaletteState::CreateCategoryFromNodePaletteState(GraphCanvas::NodePaletteWidget* paletteWidget, AutomationStateModelId categoryId, AutomationStateModelId scenePoint, AutomationStateModelId outputId)
: NamedAutomationState("CreateCategoryFromNodePaletteState")
, m_paletteWidget(paletteWidget)
, m_categoryId(categoryId)
, m_scenePoint(scenePoint)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("CreateCategoryFromNodePaletteState::%s", m_categoryId.c_str()));
}
void CreateCategoryFromNodePaletteState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
const AZ::Vector2* scenePoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_scenePoint);
const AZStd::string* category = GetStateModel()->GetStateDataAs<AZStd::string>(m_categoryId);
if (graphId && scenePoint && category)
{
m_creationAction = aznew CreateCategoryFromNodePaletteAction(m_paletteWidget, (*graphId), category->c_str(), GraphCanvas::ConversionUtils::AZToQPoint((*scenePoint)));
actionRunner.AddAction(m_creationAction);
}
else
{
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
if (scenePoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid Vector2", m_scenePoint.c_str()));
}
if (category == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid string", m_categoryId.c_str()));
}
}
}
void CreateCategoryFromNodePaletteState::OnStateActionsComplete()
{
if (m_creationAction)
{
if (!m_outputId.empty())
{
auto createdNodeIds = m_creationAction->GetCreatedNodes();
GetStateModel()->SetStateData(m_outputId, createdNodeIds);
}
delete m_creationAction;
m_creationAction = nullptr;
}
}
///////////////////////////////////
// CreateNodeFromContextMenuState
///////////////////////////////////
CreateNodeFromContextMenuState::CreateNodeFromContextMenuState(const QString& nodeName, CreationType creationType, AutomationStateModelId creationDataId, AutomationStateModelId outputId)
: NamedAutomationState("CreateNodeFromContextMenuState")
, m_nodeName(nodeName)
, m_creationType(creationType)
, m_creationDataId(creationDataId)
, m_outputId(outputId)
, m_delayAction(AZStd::chrono::milliseconds(500))
{
AZStd::string nameString = AZStd::string::format("CreateNodeFromContextMenuState::%s", nodeName.toUtf8().data());
SetStateName(nameString);
}
void CreateNodeFromContextMenuState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
if (graphId != nullptr)
{
switch (m_creationType)
{
case CreationType::ScenePosition:
{
const AZ::Vector2* dropPoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_creationDataId);
if (dropPoint)
{
QPointF qPoint = QPoint(dropPoint->GetX(), dropPoint->GetY());
m_createNodeAction = aznew CreateNodeFromContextMenuAction((*graphId), m_nodeName, qPoint);
}
break;
}
case CreationType::Splice:
{
const GraphCanvas::ConnectionId* connectionId = GetStateModel()->GetStateDataAs<GraphCanvas::ConnectionId>(m_creationDataId);
if (connectionId)
{
m_createNodeAction = aznew CreateNodeFromContextMenuAction((*graphId), m_nodeName, (*connectionId));
}
break;
}
default:
break;
}
}
if (m_createNodeAction)
{
actionRunner.AddAction(m_createNodeAction);
actionRunner.AddAction(&m_delayAction);
}
else
{
ReportError(AZStd::string::format("Failed to configure CreateNodeFromContextMenuState::%s", m_nodeName.toUtf8().data()));
}
}
void CreateNodeFromContextMenuState::OnStateActionsComplete()
{
if (m_createNodeAction)
{
if (!m_outputId.empty())
{
GraphCanvas::NodeId nodeId = m_createNodeAction->GetCreatedNodeId();
GetStateModel()->SetStateData(m_outputId, nodeId);
}
delete m_createNodeAction;
m_createNodeAction = nullptr;
}
}
////////////////////////////////
// CreateNodeFromProposalState
////////////////////////////////
CreateNodeFromProposalState::CreateNodeFromProposalState(const QString& nodeName, AutomationStateModelId endpointId, AutomationStateModelId scenePointId, AutomationStateModelId nodeOutputId, AutomationStateModelId connectionOutputId)
: NamedAutomationState("CreateNodeFromProposalState")
, m_nodeName(nodeName)
, m_endpointId(endpointId)
, m_scenePointId(scenePointId)
, m_nodeOutputId(nodeOutputId)
, m_connectionOutputId(connectionOutputId)
, m_delayAction(AZStd::chrono::milliseconds(500))
{
AZStd::string stateId = AZStd::string::format("CreateNodeFromProposalState::%s", nodeName.toUtf8().data());
SetStateName(stateId);
}
void CreateNodeFromProposalState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
const GraphCanvas::Endpoint* endpoint = GetStateModel()->GetStateDataAs<GraphCanvas::Endpoint>(m_endpointId);
if (graphId && endpoint)
{
if (!m_scenePointId.empty())
{
const AZ::Vector2* scenePoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_scenePointId);
if (scenePoint)
{
m_createNodeAction = aznew CreateNodeFromProposalAction((*graphId), (*endpoint), m_nodeName, GraphCanvas::ConversionUtils::AZToQPoint((*scenePoint)));
}
else
{
ReportError(AZStd::string::format("%s is an invalid Vector2", m_scenePointId.c_str()));
}
}
else
{
m_createNodeAction = aznew CreateNodeFromProposalAction((*graphId), (*endpoint), m_nodeName);
}
}
else
{
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is an invalid GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
if (endpoint == nullptr)
{
ReportError(AZStd::string::format("%s is an invalid GraphCanvas::Endpoint", m_endpointId.c_str()));
}
}
if (m_createNodeAction)
{
actionRunner.AddAction(m_createNodeAction);
actionRunner.AddAction(&m_delayAction);
}
}
void CreateNodeFromProposalState::OnStateActionsComplete()
{
if (m_createNodeAction)
{
if (!m_nodeOutputId.empty())
{
GraphCanvas::NodeId nodeId = m_createNodeAction->GetCreatedNodeId();
GetStateModel()->SetStateData(m_nodeOutputId, nodeId);
}
if (!m_connectionOutputId.empty())
{
GraphCanvas::ConnectionId connectionId = m_createNodeAction->GetConnectionId();
GetStateModel()->SetStateData(m_connectionOutputId, connectionId);
}
delete m_createNodeAction;
m_createNodeAction = nullptr;
}
}
/////////////////////
// CreateGroupState
/////////////////////
CreateGroupState::CreateGroupState(GraphCanvas::EditorId editorId, CreateGroupAction::CreationType creationType, AutomationStateModelId outputId)
: NamedAutomationState("CreateGroupState")
, m_editorId(editorId)
, m_creationType(creationType)
, m_outputId(outputId)
, m_delayAction(AZStd::chrono::milliseconds(500))
{
AZStd::string stateName = "CreateGroupState::%s";
if (!m_outputId.empty())
{
stateName.append("::");
stateName.append(m_outputId);
}
switch (m_creationType)
{
case CreateGroupAction::CreationType::Hotkey:
stateName = AZStd::string::format(stateName.c_str(), "HotKey");
break;
case CreateGroupAction::CreationType::Toolbar:
stateName = AZStd::string::format(stateName.c_str(), "Toolbar");
break;
}
SetStateName(stateName);
}
void CreateGroupState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
m_createGroupAction = aznew CreateGroupAction(m_editorId, (*graphId), m_creationType);
actionRunner.AddAction(m_createGroupAction);
actionRunner.AddAction(&m_delayAction);
}
void CreateGroupState::OnStateActionsComplete()
{
if (!m_outputId.empty())
{
AZ::EntityId groupId = m_createGroupAction->GetCreatedGroupId();
GetStateModel()->SetStateData(m_outputId, groupId);
}
delete m_createGroupAction;
m_createGroupAction = nullptr;
}
}
@@ -0,0 +1,150 @@
/*
* 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 <QTableView>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/EditorViewStates.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasDeveloper
{
////////////////////////
// SceneMouseMoveState
////////////////////////
SceneMouseMoveState::SceneMouseMoveState(AutomationStateModelId targetPoint)
: NamedAutomationState("SceneMouseMoveState")
, m_targetPoint(targetPoint)
{
SetStateName(AZStd::string::format("SceneMouseMoveState::%s", targetPoint.c_str()));
}
void SceneMouseMoveState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
const AZ::Vector2* scenePoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_targetPoint);
if (scenePoint && graphId)
{
m_moveAction = aznew SceneMouseMoveAction((*graphId), GraphCanvas::ConversionUtils::AZToQPoint((*scenePoint)));
actionRunner.AddAction(m_moveAction);
}
else
{
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
if (scenePoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid AZ::Vector2", m_targetPoint.c_str()));
}
}
}
void SceneMouseMoveState::OnStateActionsComplete()
{
delete m_moveAction;
m_moveAction = nullptr;
}
////////////////////////
// SceneMouseDragState
////////////////////////
SceneMouseDragState::SceneMouseDragState(AutomationStateModelId startPoint, AutomationStateModelId endPoint, Qt::MouseButton mouseButton)
: NamedAutomationState("SceneMouseDragState")
, m_startPoint(startPoint)
, m_endPoint(endPoint)
, m_mouseButton(mouseButton)
{
SetStateName(AZStd::string::format("SceneMouseDragState::%s::%s", m_startPoint.c_str(), m_endPoint.c_str()));
}
void SceneMouseDragState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
const AZ::Vector2* startPoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_startPoint);
const AZ::Vector2* endPoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_endPoint);
if (startPoint && endPoint && graphId)
{
m_dragAction = aznew SceneMouseDragAction((*graphId), GraphCanvas::ConversionUtils::AZToQPoint((*startPoint)), GraphCanvas::ConversionUtils::AZToQPoint((*endPoint)), m_mouseButton);
actionRunner.AddAction(m_dragAction);
}
else
{
if (startPoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid AZ::Vector2", m_startPoint.c_str()));
}
if (endPoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid AZ::Vector2", m_endPoint.c_str()));
}
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
}
}
void SceneMouseDragState::OnStateActionsComplete()
{
delete m_dragAction;
m_dragAction = nullptr;
}
////////////////////////
// FindViewCenterState
////////////////////////
FindViewCenterState::FindViewCenterState(AutomationStateModelId outputId)
: CustomActionState("FindViewCenterState")
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("FindViewCenterState::%s", outputId.c_str()));
}
void FindViewCenterState::OnCustomAction()
{
if (!m_outputId.empty())
{
const GraphCanvas::ViewId* viewId = GetStateModel()->GetStateDataAs<GraphCanvas::ViewId>(StateModelIds::ViewId);
if (viewId)
{
QRectF viewableRect;
GraphCanvas::ViewRequestBus::EventResult(viewableRect, (*viewId), &GraphCanvas::ViewRequests::GetViewableAreaInSceneCoordinates);
AZ::Vector2 viewCenter = GraphCanvas::ConversionUtils::QPointToVector(viewableRect.center());
GetStateModel()->SetStateData(m_outputId, viewCenter);
}
}
}
}
@@ -0,0 +1,122 @@
/*
* 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 <platform.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/ElementInteractionStates.h>
namespace ScriptCanvasDeveloper
{
////////////////////////////
// SelectSceneElementState
////////////////////////////
SelectSceneElementState::SelectSceneElementState(AutomationStateModelId targetId)
: NamedAutomationState("SelectSceneElementState")
, m_targetId(targetId)
{
SetStateName(AZStd::string::format("SelectSceneElementState::%s", targetId.c_str()));
}
void SelectSceneElementState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const AZ::EntityId* targetId = GetStateModel()->GetStateDataAs<AZ::EntityId>(m_targetId);
if (targetId)
{
m_selectSceneElement = aznew SelectSceneElementAction((*targetId));
actionRunner.AddAction(m_selectSceneElement);
}
else
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_targetId.c_str()));
}
}
void SelectSceneElementState::OnStateActionsComplete()
{
if (m_selectSceneElement)
{
delete m_selectSceneElement;
m_selectSceneElement = nullptr;
}
}
//////////////////////////////
// AltClickSceneElementState
//////////////////////////////
AltClickSceneElementState::AltClickSceneElementState(AutomationStateModelId targetId)
: NamedAutomationState("AltClickSceneElementState")
, m_targetId(targetId)
{
SetStateName(AZStd::string::format("AltClickSceneElementState::%s", targetId.c_str()));
}
void AltClickSceneElementState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const AZ::EntityId* targetId = GetStateModel()->GetStateDataAs<AZ::EntityId>(m_targetId);
if (targetId)
{
m_altClickAction = aznew AltClickSceneElementAction((*targetId));
actionRunner.AddAction(m_altClickAction);
}
else
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_targetId.c_str()));
}
}
void AltClickSceneElementState::OnStateActionsComplete()
{
if (m_altClickAction)
{
delete m_altClickAction;
m_altClickAction = nullptr;
}
}
///////////////////////////////////
// MouseToNodePropertyEditorState
///////////////////////////////////
MouseToNodePropertyEditorState::MouseToNodePropertyEditorState(AutomationStateModelId slotId)
: NamedAutomationState("MouseToNodePropertyEditorState")
, m_slotId(slotId)
{
SetStateName(AZStd::string::format("MouseToNodePropertyEditorState::%s", slotId.c_str()));
}
void MouseToNodePropertyEditorState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::SlotId* slotId = GetStateModel()->GetStateDataAs<GraphCanvas::SlotId>(m_slotId);
if (slotId)
{
m_moveToPropertyAction = aznew MouseToNodePropertyEditorAction((*slotId));
actionRunner.AddAction(m_moveToPropertyAction);
actionRunner.AddAction(&m_processEvents);
}
else
{
ReportError(AZStd::string::format("%s is not a valid SlotId", m_slotId.c_str()));
}
}
void MouseToNodePropertyEditorState::OnStateActionsComplete()
{
delete m_moveToPropertyAction;
m_moveToPropertyAction = nullptr;
}
}
@@ -0,0 +1,108 @@
/*
* 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 <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Editor/Automation/AutomationUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <Editor/GraphCanvas/AutomationIds.h>
#include <Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/GraphStates.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
namespace ScriptCanvasDeveloper
{
////////////////////////////
// CreateRuntimeGraphState
////////////////////////////
CreateRuntimeGraphState::CreateRuntimeGraphState()
{
}
void CreateRuntimeGraphState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
actionRunner.AddAction(&m_createNewGraphAction);
}
void CreateRuntimeGraphState::OnStateActionsComplete()
{
GraphCanvas::GraphId graphId = m_createNewGraphAction.GetGraphId();
SetModelData(StateModelIds::GraphCanvasId, graphId);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetScriptCanvasId, graphId);
SetModelData(StateModelIds::ScriptCanvasId, scriptCanvasId);
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, graphId, &GraphCanvas::SceneRequests::GetViewId);
SetModelData(StateModelIds::ViewId, viewId);
AZ::Vector2 minorStep = GraphCanvas::GraphUtils::FindMinorStep(graphId);
SetModelData(StateModelIds::MinorStep, minorStep);
}
/////////////////////////////
// CreateFunctionGraphState
/////////////////////////////
CreateFunctionGraphState::CreateFunctionGraphState()
{
}
void CreateFunctionGraphState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
actionRunner.AddAction(&m_createNewFunctionAction);
}
void CreateFunctionGraphState::OnStateActionsComplete()
{
GraphCanvas::GraphId graphId = m_createNewFunctionAction.GetGraphId();
SetModelData(StateModelIds::GraphCanvasId, graphId);
ScriptCanvas::ScriptCanvasId scriptCanvasId;
ScriptCanvasEditor::GeneralRequestBus::BroadcastResult(scriptCanvasId, &ScriptCanvasEditor::GeneralRequests::GetScriptCanvasId, graphId);
SetModelData(StateModelIds::ScriptCanvasId, scriptCanvasId);
GraphCanvas::ViewId viewId;
GraphCanvas::SceneRequestBus::EventResult(viewId, graphId, &GraphCanvas::SceneRequests::GetViewId);
SetModelData(StateModelIds::ViewId, viewId);
AZ::Vector2 minorStep = GraphCanvas::GraphUtils::FindMinorStep(graphId);
SetModelData(StateModelIds::MinorStep, minorStep);
}
///////////////////////////////
// ForceCloseActiveGraphState
///////////////////////////////
ForceCloseActiveGraphState::ForceCloseActiveGraphState()
{
}
void ForceCloseActiveGraphState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
actionRunner.AddAction(&m_forceCloseActiveGraph);
}
}
@@ -0,0 +1,322 @@
/*
* 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 <QTableView>
#include <GraphCanvas/Components/Nodes/Group/NodeGroupBus.h>
#include <GraphCanvas/Components/Nodes/NodeBus.h>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/UtilityStates.h>
#include <Editor/Include/ScriptCanvas/Bus/RequestBus.h>
namespace ScriptCanvasDeveloper
{
/////////////////////
// FindNodePosition
/////////////////////
FindNodePosition::FindNodePosition(AutomationStateModelId nodeId, AutomationStateModelId outputId, FindPositionOffsets offsets)
: CustomActionState("FindNodePosition")
, m_offsets(offsets)
, m_nodeId(nodeId)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("FindNodePosition::%s::%s", m_nodeId.c_str(), m_outputId.c_str()));
}
void FindNodePosition::OnCustomAction()
{
const GraphCanvas::NodeId* nodeId = GetStateModel()->GetStateDataAs<GraphCanvas::NodeId>(m_nodeId);
if (nodeId)
{
QGraphicsItem* graphicsItem = nullptr;
GraphCanvas::VisualRequestBus::EventResult(graphicsItem, (*nodeId), &GraphCanvas::VisualRequests::AsGraphicsItem);
if (graphicsItem)
{
QRectF boundingRect = graphicsItem->sceneBoundingRect();
qreal horizontalPoint = boundingRect.left() + boundingRect.width() * m_offsets.m_horizontalPosition;
horizontalPoint += m_offsets.m_horizontalOffset;
qreal verticalPoint = boundingRect.top() + boundingRect.height() * m_offsets.m_verticalPosition;
verticalPoint += m_offsets.m_verticalOffset;
AZ::Vector2 scenePoint(horizontalPoint, verticalPoint);
GetStateModel()->SetStateData(m_outputId, scenePoint);
}
}
else
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_nodeId.c_str()));
}
}
//////////////////////
// FindGroupPosition
//////////////////////
FindGroupPosition::FindGroupPosition(AutomationStateModelId groupId, AutomationStateModelId outputId, FindPositionOffsets offsets)
: CustomActionState("FindGroupPosition")
, m_offsets(offsets)
, m_groupId(groupId)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("FindGroupPosition::%s::%s", m_groupId.c_str(), m_outputId.c_str()));
}
void FindGroupPosition::OnCustomAction()
{
const AZ::EntityId* groupId = GetStateModel()->GetStateDataAs<AZ::EntityId>(m_groupId);
if (groupId)
{
QRectF groupBoundingBox;
GraphCanvas::NodeGroupRequestBus::EventResult(groupBoundingBox, (*groupId), &GraphCanvas::NodeGroupRequests::GetGroupBoundingBox);
qreal horizontalPoint = groupBoundingBox.left() + groupBoundingBox.width() * m_offsets.m_horizontalPosition;
horizontalPoint += m_offsets.m_horizontalOffset;
qreal verticalPoint = groupBoundingBox.top() + groupBoundingBox.height() * m_offsets.m_verticalPosition;
verticalPoint += m_offsets.m_verticalPosition;
AZ::Vector2 scenePoint(horizontalPoint, verticalPoint);
GetStateModel()->SetStateData(m_outputId, scenePoint);
}
else
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_groupId.c_str()));
}
}
////////////////////////////
// FindEndpointOfTypeState
////////////////////////////
FindEndpointOfTypeState::FindEndpointOfTypeState(AutomationStateModelId targetNodeId, AutomationStateModelId outputId, GraphCanvas::ConnectionType connectionType, GraphCanvas::SlotType slotType, int slotNumber)
: CustomActionState("FindEndpointOfTypeState")
, m_targetNodeId(targetNodeId)
, m_outputId(outputId)
, m_slotNumber(slotNumber)
, m_connectionType(connectionType)
, m_slotType(slotType)
{
SetStateName(AZStd::string::format("FindEndpointOfType::%s::%s", targetNodeId.c_str(), outputId.c_str()));
}
void FindEndpointOfTypeState::OnCustomAction()
{
const GraphCanvas::NodeId* nodeId = GetStateModel()->GetStateDataAs<GraphCanvas::NodeId>(m_targetNodeId);
if (nodeId)
{
AZStd::vector< GraphCanvas::SlotId > slotIds;
GraphCanvas::NodeRequestBus::EventResult(slotIds, (*nodeId), &GraphCanvas::NodeRequests::FindVisibleSlotIdsByType, m_connectionType, m_slotType);
if (slotIds.size() <= m_slotNumber)
{
ReportError(AZStd::string::format("Slot Number %i is out of scope for the current node.", m_slotNumber));
return;
}
GraphCanvas::SlotId slotId = slotIds[m_slotNumber];
GraphCanvas::Endpoint endpoint = GraphCanvas::Endpoint((*nodeId), slotId);
GetStateModel()->SetStateData(m_outputId, endpoint);
}
else
{
ReportError(AZStd::string::format("%s is not a valid EntityId", m_targetNodeId.c_str()));
}
}
//////////////////////
// GetLastConnection
//////////////////////
GetLastConnection::GetLastConnection(AutomationStateModelId targetEndpoint, AutomationStateModelId outputId)
: CustomActionState("GetLastConnection")
, m_targetEndpoint(targetEndpoint)
, m_outputId(outputId)
{
SetStateName(AZStd::string::format("GetLastConnection::%s", targetEndpoint.c_str()));
}
void GetLastConnection::OnCustomAction()
{
const GraphCanvas::Endpoint* targetEndpoint = GetStateModel()->GetStateDataAs<GraphCanvas::Endpoint>(m_targetEndpoint);
if (targetEndpoint)
{
GraphCanvas::ConnectionId connectionId;
GraphCanvas::SlotRequestBus::EventResult(connectionId, targetEndpoint->GetSlotId(), &GraphCanvas::SlotRequests::GetLastConnection);
GetStateModel()->SetStateData(m_outputId, connectionId);
}
else
{
ReportError(AZStd::string::format("%s is not a valid GraphCanvas::Endpoint", m_targetEndpoint.c_str()));
}
}
//////////////////////////////////////
// DeleteVariableRowFromPaletteState
//////////////////////////////////////
#if !defined(AZ_COMPILER_MSVC)
#ifndef VK_DELETE
#define VK_DELETE 0x2E
#endif
#ifndef VK_CONTROL
#define VK_CONTROL 0x11
#endif
#endif
DeleteVariableRowFromPaletteState::DeleteVariableRowFromPaletteState(int row)
: NamedAutomationState("DeleteVariableRowFromPaletteState")
, m_row(row)
, m_clickAction(Qt::MouseButton::LeftButton)
, m_deleteAction(VK_DELETE)
{
SetStateName(AZStd::string::format("DeleteVariableRowState::%i", row));
}
void DeleteVariableRowFromPaletteState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
QTableView* graphPalette;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(graphPalette, &ScriptCanvasEditor::VariableAutomationRequests::GetGraphPaletteTableView);
m_rowCount = graphPalette->model()->rowCount();
m_mouseToRow = aznew MoveMouseToViewRowAction(graphPalette, 0);
actionRunner.AddAction(m_mouseToRow);
actionRunner.AddAction(&m_processEvents);
actionRunner.AddAction(&m_clickAction);
actionRunner.AddAction(&m_processEvents);
actionRunner.AddAction(&m_deleteAction);
}
void DeleteVariableRowFromPaletteState::OnStateActionsComplete()
{
delete m_mouseToRow;
m_mouseToRow = nullptr;
QTableView* graphPalette;
ScriptCanvasEditor::VariableAutomationRequestBus::BroadcastResult(graphPalette, &ScriptCanvasEditor::VariableAutomationRequests::GetGraphPaletteTableView);
if (graphPalette->model()->rowCount() >= m_rowCount)
{
ReportError("Failed to delete variable row from table.");
}
}
///////////////////
// CheckIsInGroup
///////////////////
CheckIsInGroup::CheckIsInGroup(AutomationStateModelId sceneMemberId, AutomationStateModelId groupId, bool expectResult, AZStd::string stateName)
: CustomActionState("CheckIsInGroup")
, m_sceneMemberId(sceneMemberId)
, m_groupId(groupId)
, m_expectResult(expectResult)
{
if (stateName.empty())
{
SetStateName(AZStd::string::format("CheckGroupStatus::%s::%s", sceneMemberId.c_str(), groupId.c_str()));
}
else
{
SetStateName(stateName);
}
}
void CheckIsInGroup::OnCustomAction()
{
const AZ::EntityId* sceneMemberTarget = GetStateModel()->GetStateDataAs<AZ::EntityId>(m_sceneMemberId);
const AZ::EntityId* targetGroupId = GetStateModel()->GetStateDataAs<AZ::EntityId>(m_groupId);
if (sceneMemberTarget && targetGroupId)
{
AZ::EntityId groupId;
GraphCanvas::GroupableSceneMemberRequestBus::EventResult(groupId, (*sceneMemberTarget), &GraphCanvas::GroupableSceneMemberRequests::GetGroupId);
bool groupMatch = groupId == (*targetGroupId);
if (groupMatch != m_expectResult)
{
ReportError(AZStd::string::format("Group Status of %s not in expected state.", m_sceneMemberId.c_str()));
}
}
else
{
AZStd::string errorString;
if (sceneMemberTarget == nullptr)
{
errorString = AZStd::string::format("%s is not a valid EntityId", m_sceneMemberId.c_str());
}
if (targetGroupId == nullptr)
{
if (!errorString.empty())
{
errorString += ", ";
}
errorString += AZStd::string::format("%s is not a valid EntityId", m_groupId.c_str());
}
ReportError(errorString);
}
}
//////////////////
// TriggerHotKey
//////////////////
TriggerHotKey::TriggerHotKey(QChar hotKey, AZStd::string stateId)
: NamedAutomationState("TriggerHotKey")
, m_typeAction(hotKey)
, m_pressCtrlAction(VK_CONTROL)
, m_releaseCtrlAction(VK_CONTROL)
{
if (stateId.empty())
{
QString name = hotKey;
SetStateName(AZStd::string::format("TriggerHotKey::%s", name.toUtf8().data()));
}
else
{
SetStateName(stateId);
}
}
void TriggerHotKey::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
actionRunner.AddAction(&m_pressCtrlAction);
actionRunner.AddAction(&m_processEvents);
actionRunner.AddAction(&m_typeAction);
actionRunner.AddAction(&m_processEvents);
actionRunner.AddAction(&m_releaseCtrlAction);
actionRunner.AddAction(&m_processEvents);
}
}
@@ -0,0 +1,186 @@
/*
* 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 <QApplication>
#include <QPushButton>
#include <QTableView>
#include <QToolButton>
#include <GraphCanvas/Components/SceneBus.h>
#include <GraphCanvas/Components/Slots/SlotBus.h>
#include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
#include <GraphCanvas/Components/ViewBus.h>
#include <GraphCanvas/Components/VisualBus.h>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <GraphCanvas/Widgets/NodePalette/Model/NodePaletteSortFilterProxyModel.h>
#include <GraphCanvas/Widgets/NodePalette/NodePaletteTreeView.h>
#include <GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h>
#include <GraphCanvas/Utils/ConversionUtils.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <ScriptCanvas/Bus/RequestBus.h>
#include <ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/VariableStates.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorMouseActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/EditorKeyActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/EditorViewActions.h>
#include <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/WidgetActions.h>
namespace ScriptCanvasDeveloper
{
////////////////////////
// CreateVariableState
////////////////////////
CreateVariableState::CreateVariableState(AutomationStateModelId dataTypeId, AutomationStateModelId nameId, bool errorOnNameMisMatch, CreateVariableAction::CreationType creationType, AutomationStateModelId outputId)
: NamedAutomationState("CreateVariableState")
, m_dataTypeId(dataTypeId)
, m_nameId(nameId)
, m_outputId(outputId)
, m_creationType(creationType)
, m_errorOnNameMismatch(errorOnNameMisMatch)
{
SetStateName(AZStd::string::format("CreateVariableState::%s", dataTypeId.c_str()));
}
void CreateVariableState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const ScriptCanvas::Data::Type* dataType = GetStateModel()->GetStateDataAs<ScriptCanvas::Data::Type>(m_dataTypeId);
if (dataType)
{
if (!m_nameId.empty())
{
const AZStd::string* variableName = GetStateModel()->GetStateDataAs<AZStd::string>(m_nameId);
if (variableName)
{
QString name = QString(variableName->c_str());
m_createVariableAction = aznew CreateVariableAction((*dataType), name, m_creationType);
}
else
{
ReportError(AZStd::string::format("%s is not a string value", m_nameId.c_str()));
}
}
else
{
m_createVariableAction = aznew CreateVariableAction((*dataType), m_creationType);
}
}
else
{
ReportError(AZStd::string::format("%s is not a valid ScriptCanvas::Data::DataType", m_dataTypeId.c_str()));
}
if (m_createVariableAction)
{
m_createVariableAction->SetErrorOnNameMisMatch(m_errorOnNameMismatch);
actionRunner.AddAction(m_createVariableAction);
}
}
void CreateVariableState::OnStateActionsComplete()
{
if (m_createVariableAction)
{
if (!m_outputId.empty())
{
ScriptCanvas::VariableId variableId = m_createVariableAction->GetVariableId();
GetStateModel()->SetStateData(m_outputId, variableId);
}
delete m_createVariableAction;
m_createVariableAction = nullptr;
}
}
////////////////////////////////////////////
// CreateVariableNodeFromGraphPaletteState
////////////////////////////////////////////
CreateVariableNodeFromGraphPaletteState::CreateVariableNodeFromGraphPaletteState(AutomationStateModelId variableNameId, AutomationStateModelId scenePoint, Qt::KeyboardModifier modifier, AutomationStateModelId outputId)
: NamedAutomationState("CreateVariableNodeFromGraphPaletteState")
, m_variableNameId(variableNameId)
, m_scenePoint(scenePoint)
, m_outputId(outputId)
, m_modifier(modifier)
{
AZStd::string keyModifier;
if (modifier == Qt::KeyboardModifier::AltModifier)
{
keyModifier = "Alt";
}
else if (modifier == Qt::KeyboardModifier::ShiftModifier)
{
keyModifier = "Shift";
}
else
{
keyModifier = "???";
}
SetStateName(AZStd::string::format("CreateVariableNodeFromGraphPaletteState::%s::%s", m_variableNameId.c_str(), keyModifier.c_str()));
}
void CreateVariableNodeFromGraphPaletteState::OnSetupStateActions(EditorAutomationActionRunner& actionRunner)
{
const GraphCanvas::GraphId* graphId = GetStateModel()->GetStateDataAs<GraphCanvas::GraphId>(StateModelIds::GraphCanvasId);
const AZStd::string* variableName = GetStateModel()->GetStateDataAs<AZStd::string>(m_variableNameId);
const AZ::Vector2* scenePoint = GetStateModel()->GetStateDataAs<AZ::Vector2>(m_scenePoint);
if (graphId && variableName && scenePoint)
{
m_createVariable = aznew CreateVariableNodeFromGraphPalette((*variableName), (*graphId), GraphCanvas::ConversionUtils::AZToQPoint((*scenePoint)).toPoint(), m_modifier);
actionRunner.AddAction(m_createVariable);
}
else
{
if (graphId == nullptr)
{
ReportError(AZStd::string::format("%s is not a GraphCanvas::GraphId", StateModelIds::GraphCanvasId));
}
if (variableName == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid string", m_variableNameId.c_str()));
}
if (scenePoint == nullptr)
{
ReportError(AZStd::string::format("%s is not a valid Vector2", m_scenePoint.c_str()));
}
}
}
void CreateVariableNodeFromGraphPaletteState::OnStateActionsComplete()
{
if (m_createVariable)
{
if (!m_outputId.empty())
{
AZ::EntityId nodeId = m_createVariable->GetCreatedNodeId();
GetStateModel()->SetStateData(m_outputId, nodeId);
}
delete m_createVariable;
m_createVariable = nullptr;
}
}
}
@@ -0,0 +1,357 @@
/*
* 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 <ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationTest.h>
namespace ScriptCanvasDeveloper
{
/////////////////////////////////
// EditorAutomationActionRunner
/////////////////////////////////
EditorAutomationActionRunner::~EditorAutomationActionRunner()
{
Reset();
}
void EditorAutomationActionRunner::Reset()
{
for (EditorAutomationAction* deleteAction : m_actionsToDelete)
{
delete deleteAction;
}
m_actionsToDelete.clear();
while (!m_executionStack.empty())
{
m_executionStack.erase(m_executionStack.begin());
}
m_errorReports.clear();
m_currentAction = nullptr;
}
bool EditorAutomationActionRunner::Tick()
{
if (m_currentAction == nullptr)
{
if (m_executionStack.empty())
{
return true;
}
else
{
m_currentAction = m_executionStack.front();
while (m_currentAction->IsMissingPrecondition())
{
if (m_currentAction->IsAtPreconditionLimit())
{
ActionReport failureReport;
failureReport = AZ::Failure<AZStd::string>("Action failed to setup its preconditions in a reasonable amount of iterations. Exiting test.");
m_errorReports.emplace_back(failureReport);
m_currentAction->ResetPreconditionAttempts();
// Leak elements, then we'll just exit through normal paths next tick.
m_executionStack.clear();
return false;
}
else
{
EditorAutomationAction* newAction = m_currentAction->GenerationPreconditionActions();
m_actionsToDelete.emplace(newAction);
if (newAction)
{
m_currentAction = newAction;
m_executionStack.insert(m_executionStack.begin(), newAction);
}
}
}
// Erase our current front of stack, as that is our current action.
m_executionStack.erase(m_executionStack.begin());
AZ_Assert(m_currentAction, "Current Action should not be null at this point.");
if (m_currentAction == nullptr)
{
// Leak all the memory. We'll just exit through the normal path next tick.
m_executionStack.clear();
return true;
}
else
{
m_currentAction->SignalActionBegin();
}
}
}
if (m_currentAction)
{
if (m_currentAction->Tick())
{
ActionReport errorReport = m_currentAction->GenerateReport();
if (!errorReport.IsSuccess())
{
m_errorReports.emplace_back(errorReport);
}
m_currentAction = nullptr;
}
}
return false;
}
void EditorAutomationActionRunner::AddAction(EditorAutomationAction* actionToRun)
{
m_executionStack.emplace_back(actionToRun);
}
bool EditorAutomationActionRunner::HasActions() const
{
return !m_executionStack.empty();
}
bool EditorAutomationActionRunner::HasErrors() const
{
return !m_errorReports.empty();
}
const AZStd::vector< ActionReport >& EditorAutomationActionRunner::GetErrors() const
{
return m_errorReports;
}
///////////////
// StateModel
///////////////
const AZStd::any* StateModel::FindStateData(const DataKey& dataId) const
{
auto dataIter = m_stateData.find(dataId);
if (dataIter != m_stateData.end())
{
return &dataIter->second;
}
return nullptr;
}
void StateModel::ClearModelData()
{
m_stateData.clear();
}
/////////////////////////
// EditorAutomationTest
/////////////////////////
EditorAutomationTest::EditorAutomationTest(QString testName)
: m_testName(testName)
{
}
EditorAutomationTest::~EditorAutomationTest()
{
for (const auto& statePair : m_states)
{
delete statePair.second;
}
m_states.clear();
}
void EditorAutomationTest::StartTest()
{
m_hasRun = true;
m_testErrors.clear();
OnTestStarting();
m_stateId = m_initialStateId;
m_actionRunner.Reset();
if (SetupState(m_stateId))
{
AZ::SystemTickBus::Handler::BusConnect();
}
else
{
OnTestComplete();
}
}
void EditorAutomationTest::OnSystemTick()
{
if (m_actionRunner.Tick())
{
if (!HasErrors())
{
if (m_actionRunner.HasErrors())
{
const AZStd::vector<ActionReport>& actionErrors = m_actionRunner.GetErrors();
for (const ActionReport& actionErrorReport : actionErrors)
{
AddError(actionErrorReport.GetError());
}
}
else
{
m_currentState->StateActionsComplete();
if (m_currentState->HasErrors())
{
AddError(m_currentState->GetError());
}
m_currentState = nullptr;
}
//++m_state;
m_actionRunner.Reset();
if (!HasErrors())
{
OnStateComplete(m_stateId);
int nextStateId = FindNextState(m_stateId);
if (!SetupState(nextStateId))
{
AZ::SystemTickBus::Handler::BusDisconnect();
OnTestComplete();
}
}
else
{
AZ::SystemTickBus::Handler::BusDisconnect();
OnTestComplete();
}
}
else
{
AZ::SystemTickBus::Handler::BusDisconnect();
OnTestComplete();
}
}
}
void EditorAutomationTest::AddState(EditorAutomationState* newState)
{
int stateId = newState->GetStateId();
if (stateId == EditorAutomationState::EXIT_STATE_ID)
{
AZ_Error("EditorAutomationTest", false, "Trying to use reserved exit state id");
delete newState;
return;
}
auto stateIter = m_states.find(stateId);
if (stateIter != m_states.end())
{
AZ_Error("EditorAutomationTest", false, "Collision on StateId %i found. Maintaining first state with id", stateId);
delete newState;
return;
}
m_registrationOrder.emplace_back(stateId);
m_states[stateId] = newState;
newState->SetStateModel(this);
if (m_initialStateId == EditorAutomationState::EXIT_STATE_ID)
{
m_initialStateId = stateId;
}
}
void EditorAutomationTest::SetHasCustomTransitions(bool hasCustomTransition)
{
m_hasCustomTransitions = hasCustomTransition;
}
bool EditorAutomationTest::HasRun() const
{
return m_hasRun;
}
bool EditorAutomationTest::IsRunning() const
{
return AZ::SystemTickBus::Handler::BusIsConnected();
}
bool EditorAutomationTest::SetupState(int stateId)
{
m_stateId = EditorAutomationState::EXIT_STATE_ID;
m_currentState = nullptr;
auto stateIter = m_states.find(stateId);
if (stateIter != m_states.end())
{
m_currentState = stateIter->second;
}
if (m_currentState)
{
m_stateId = stateId;
m_actionRunner.Reset();
m_currentState->SetupStateActions(m_actionRunner);
}
return m_currentState != nullptr;
}
int EditorAutomationTest::FindNextState(int stateId)
{
int nextStateId = EditorAutomationState::EXIT_STATE_ID;
if (m_hasCustomTransitions)
{
nextStateId = EvaluateTransition(stateId);
}
else
{
// Do a minus one here, so we can just blindly add 1 instead of needing to safety check it.
// We default to EXIT so the result is the same.
for (int i = 0; i < m_registrationOrder.size() - 1; ++i)
{
if (m_registrationOrder[i] == stateId)
{
nextStateId = m_registrationOrder[i + 1];
}
}
}
return nextStateId;
}
void EditorAutomationTest::AddError(AZStd::string error)
{
AZ_TracePrintf("EditorAutomationTestDialog", "Error in %s :: %s", m_testName.toUtf8().data(), error.c_str());
m_testErrors.emplace_back(error);
}
}