13c7b06308
EMotionFX has user-customizable hotkeys. These hotkeys are registered by individual plugins, and then the user can set what they want the hotkey to be. The way this was implemented was by reimplementing `keyPressEvent` and `keyReleaseEvent` for each widget that used customizable hotkeys, and in there call `KeyboardShortcutManager::Check` to see if key press matched any existing hotkey mapping. However, the main Editor has behavior that prevents events from reaching EMotionFX's `keyPressEvent` method, if a keypress matches a hotkey that is also used by the main Editor. This is due to the global event filter defined in `ShortcutDispatcher::eventFilter`. This event filter takes a Qt `Shortcut` event, and will re-dispatch that event to all parent widgets of a given receiver. So if a parent widget, like the main Editor, *does* have a QAction that matches a given key sequence, that widget will receive the event, the event is marked as processed, and no `KeyPress` event is ever sent to the original widget where the event occurred. All this means that processing hotkeys in a `keyPressEvent` won't work reliably. The main editor defines a hotkey for the `delete` key, so that can never be received in a `keyPressEvent` by any child widget of the Editor. This change removes all the hotkey logic from the `keyPressEvent` methods, and replaces them with `QAction` instances. Hotkeys are defined with `QAction::setShortcut`, and added to each widget that they apply to. In addition, the `KeyboardShortcutManager` class had to be adjusted to suit this new way of defining the hotkeys. It now has a pointer to each `QAction*` that can have a customizable hotkey. It has also been greatly simplified, since it can use a `QKeySequence` instead of separate variables for `int key; bool hasCtrlModifier; bool hasAltModifier`. Applying user-defined hotkeys now has to be done after the hotkeys are registered from a plugin. It is the plugin's responsibility to reload the user-defined hotkeys after registering all of its actions.
83 lines
4.1 KiB
C++
83 lines
4.1 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <QApplication>
|
|
#include <QAction>
|
|
#include <QtTest>
|
|
|
|
#include <Tests/UI/AnimGraphUIFixture.h>
|
|
#include <EMotionFX/Source/AnimGraphManager.h>
|
|
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
|
#include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
|
|
#include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h>
|
|
#include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h>
|
|
#include <EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h>
|
|
|
|
#include <EMotionFX/Source/AnimGraphBindPoseNode.h>
|
|
|
|
namespace EMotionFX {
|
|
|
|
#if AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS
|
|
TEST_F(AnimGraphUIFixture, DISABLED_CanDeleteAnimGraphNode)
|
|
#else
|
|
TEST_F(AnimGraphUIFixture, CanDeleteAnimGraphNode)
|
|
#endif // AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS
|
|
{
|
|
/*
|
|
Test Case: C22083484
|
|
Can Delete AnimGraph Node.
|
|
Tests the UI functionality for deleting an existing AnimGraph Node via the right-click context menu.
|
|
*/
|
|
|
|
RecordProperty("test_case_id", "C22083484");
|
|
|
|
AnimGraph* activeAnimGraph = CreateAnimGraph();
|
|
|
|
// Create a node to delete later
|
|
AnimGraphNode* node = CreateAnimGraphNode(azrtti_typeid<AnimGraphBindPoseNode>().ToString<AZStd::string>(), "-parentName Root -xPos 1 -yPos 1");
|
|
ASSERT_TRUE(node) << "Node was not created.";
|
|
|
|
// Verify no nodes are selecetd yet
|
|
EXPECT_EQ(m_blendGraphWidget->CalcNumSelectedNodes(), 0) << "Expected to have exactly zero (0) selected nodes";
|
|
EXPECT_EQ(m_blendGraphWidget->GetActiveGraph()->GetSelectedAnimGraphNodes().size(), 0) << "Expected to have zero (0) items selected in selection model";
|
|
|
|
// Select the new Graph Node (via left mouse click)
|
|
QRect nodeRect = m_blendGraphWidget->GetActiveGraph()->FindGraphNode(node)->GetRect();
|
|
QPoint localPoint = nodeRect.center();
|
|
QTest::mouseClick(m_blendGraphWidget, Qt::LeftButton, Qt::NoModifier, localPoint);
|
|
|
|
// Verify our node was selected
|
|
EXPECT_EQ(m_blendGraphWidget->CalcNumSelectedNodes(), 1) << "Expected to have exactly one (1) selected node";
|
|
EXPECT_EQ(m_blendGraphWidget->GetActiveGraph()->GetSelectedAnimGraphNodes().size(), 1) << "Not exactly one selection made";
|
|
|
|
// Open context menu
|
|
m_blendGraphWidget->OnContextMenuEvent(m_blendGraphWidget, localPoint, m_blendGraphWidget->LocalToGlobal(localPoint), m_animGraphPlugin, m_blendGraphWidget->GetActiveGraph()->GetSelectedAnimGraphNodes(), true, false, m_animGraphPlugin->GetActionFilter());
|
|
|
|
// Find Action for deleting node
|
|
QAction* deleteAction = GetNamedAction(m_animGraphPlugin->GetViewWidget(), FromStdString(EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName));
|
|
ASSERT_TRUE(deleteAction) << "Could not find the '" <<
|
|
std::string(EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName.data(), EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName.size())
|
|
<< "' action in the context menu";
|
|
|
|
// Trigger delete
|
|
const size_t nodeCount = activeAnimGraph->GetNumNodes();
|
|
deleteAction->trigger();
|
|
|
|
// Verify Result
|
|
EXPECT_EQ(nodeCount - 1, activeAnimGraph->GetNumNodes()) << "Delete Action from Context menu did not remove exactly 1 Node from AnimGraph";
|
|
EXPECT_EQ(m_blendGraphWidget->CalcNumSelectedNodes(), 0) << "BlendGraphWidget still has the deleted node selected";
|
|
EXPECT_EQ(m_blendGraphWidget->GetActiveGraph()->GetSelectedAnimGraphNodes().size(), 0) << "Selection model not cleared";
|
|
}
|
|
}
|