Files
o3de/Code/Editor/EditorPanelUtils.cpp
T
amzn-phist d6b268e84e Remove ResourceSelectorHost and clean up/refactor related bits (#3050)
* Sever dependency on legacy resource selector host

Audio resource selectors (browse dialogs) no longer need to be
registered with the legacy IResourceSelectorHost system.  Set up a new
EBus specifically to handle browse button presses and directly invokes
the dialog.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Hook up legacy audio control selector to new EBus

Remaining use of legacy audio selectors (trackview) need to be able to
bypass ResourceSelectorHost now.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Removes ResourceSelectorHost and legacy selectors

This removes various Variable types that were tied to resource
selectors, such as GeomCache, Model, Animation, File.  Removes the
ResourceSelectorHost completely.  The two things that still appeared to
have selectors in TrackView are Audio Controls and Texture.  Fixed the
audio control selector to work via EBus and the Texture selector didn't
seem to work at all, but left it in as it was.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Make the default audio selector return old value

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Fix some signed/unsigned comparison warnings

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Remove deleted function from Editor Mock

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Change audio selector api to use string_view

Per feedback.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>
2021-08-16 12:41:24 -05:00

550 lines
18 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "EditorDefs.h"
#include "EditorPanelUtils.h"
#include <AzCore/Utils/Utils.h>
// Qt
#include <QInputDialog>
#include <QFileDialog>
#include <QXmlStreamReader>
// Editor
#include "IEditorPanelUtils.h"
#include "Objects/EntityObject.h"
#include "CryEditDoc.h"
#include "ViewManager.h"
#include "Controls/QToolTipWidget.h"
#include "Objects/SelectionGroup.h"
#ifndef PI
#define PI 3.14159265358979323f
#endif
struct ToolTip
{
bool isValid;
QString title;
QString content;
QString specialContent;
QString disabledContent;
};
// internal implementation for better compile times - should also never be used externally, use IParticleEditorUtils interface for that.
class CEditorPanelUtils_Impl
: public IEditorPanelUtils
{
#pragma region Drag & Drop
public:
void SetViewportDragOperation(void(* dropCallback)(CViewport* viewport, int dragPointX, int dragPointY, void* custom), void* custom) override
{
for (int i = 0; i < GetIEditor()->GetViewManager()->GetViewCount(); i++)
{
GetIEditor()->GetViewManager()->GetView(i)->SetGlobalDropCallback(dropCallback, custom);
}
}
#pragma endregion
#pragma region Preview Window
public:
int PreviewWindow_GetDisplaySettingsDebugFlags(CDisplaySettings* settings) override
{
CRY_ASSERT(settings);
return settings->GetDebugFlags();
}
void PreviewWindow_SetDisplaySettingsDebugFlags(CDisplaySettings* settings, int flags) override
{
CRY_ASSERT(settings);
settings->SetDebugFlags(flags);
}
#pragma endregion
#pragma region Shortcuts
protected:
QVector<HotKey> hotkeys;
bool m_hotkeysAreEnabled;
public:
bool HotKey_Import() override
{
QVector<QPair<QString, QString> > keys;
QString filepath = QFileDialog::getOpenFileName(nullptr, "Select shortcut configuration to load",
QString(), "HotKey Config Files (*.hkxml)");
QFile file(filepath);
if (!file.open(QIODevice::ReadOnly))
{
return false;
}
QXmlStreamReader stream(&file);
bool result = true;
while (!stream.isEndDocument())
{
if (stream.isStartElement())
{
if (stream.name() == "HotKey")
{
QPair<QString, QString> key;
QXmlStreamAttributes att = stream.attributes();
for (QXmlStreamAttribute attr : att)
{
if (attr.name().compare(QLatin1String("path"), Qt::CaseInsensitive) == 0)
{
key.first = attr.value().toString();
}
if (attr.name().compare(QLatin1String("sequence"), Qt::CaseInsensitive) == 0)
{
key.second = attr.value().toString();
}
}
if (!key.first.isEmpty())
{
keys.push_back(key); // we allow blank key sequences for unassigned shortcuts
}
else
{
result = false; //but not blank paths!
}
}
}
stream.readNext();
}
file.close();
if (result)
{
HotKey_BuildDefaults();
for (QPair<QString, QString> key : keys)
{
for (int j = 0; j < hotkeys.count(); j++)
{
if (hotkeys[j].path.compare(key.first, Qt::CaseInsensitive) == 0)
{
hotkeys[j].SetPath(key.first.toStdString().c_str());
hotkeys[j].SetSequenceFromString(key.second.toStdString().c_str());
}
}
}
}
return result;
}
void HotKey_Export() override
{
auto settingDir = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / "Editor" / "Plugins" / "ParticleEditorPlugin" / "settings";
QString filepath = QFileDialog::getSaveFileName(nullptr, "Select shortcut configuration to load", settingDir.c_str(), "HotKey Config Files (*.hkxml)");
QFile file(filepath);
if (!file.open(QIODevice::WriteOnly))
{
return;
}
QXmlStreamWriter stream(&file);
stream.setAutoFormatting(true);
stream.writeStartDocument();
stream.writeStartElement("HotKeys");
for (HotKey key : hotkeys)
{
stream.writeStartElement("HotKey");
stream.writeAttribute("path", key.path);
stream.writeAttribute("sequence", key.sequence.toString());
stream.writeEndElement();
}
stream.writeEndElement();
stream.writeEndDocument();
file.close();
}
QKeySequence HotKey_GetShortcut(const char* path) override
{
for (HotKey combo : hotkeys)
{
if (combo.IsMatch(path))
{
return combo.sequence;
}
}
return QKeySequence();
}
bool HotKey_IsPressed(const QKeyEvent* event, const char* path) override
{
if (!m_hotkeysAreEnabled)
{
return false;
}
unsigned int keyInt = 0;
//Capture any modifiers
Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
if (modifiers & Qt::ShiftModifier)
{
keyInt += Qt::SHIFT;
}
if (modifiers & Qt::ControlModifier)
{
keyInt += Qt::CTRL;
}
if (modifiers & Qt::AltModifier)
{
keyInt += Qt::ALT;
}
if (modifiers & Qt::MetaModifier)
{
keyInt += Qt::META;
}
//Capture any key
keyInt += event->key();
QString t0 = QKeySequence(keyInt).toString();
QString t1 = HotKey_GetShortcut(path).toString();
//if strings match then shortcut is pressed
if (t1.compare(t0, Qt::CaseInsensitive) == 0)
{
return true;
}
return false;
}
bool HotKey_IsPressed(const QShortcutEvent* event, const char* path) override
{
if (!m_hotkeysAreEnabled)
{
return false;
}
QString t0 = event->key().toString();
QString t1 = HotKey_GetShortcut(path).toString();
//if strings match then shortcut is pressed
if (t1.compare(t0, Qt::CaseInsensitive) == 0)
{
return true;
}
return false;
}
bool HotKey_LoadExisting() override
{
QSettings settings("O3DE", "O3DE");
QString group = "Hotkeys/";
HotKey_BuildDefaults();
int size = settings.beginReadArray(group);
for (int i = 0; i < size; i++)
{
settings.setArrayIndex(i);
QPair<QString, QString> hotkey;
hotkey.first = settings.value("name").toString();
hotkey.second = settings.value("keySequence").toString();
if (!hotkey.first.isEmpty())
{
for (int j = 0; j < hotkeys.count(); j++)
{
if (hotkeys[j].path.compare(hotkey.first, Qt::CaseInsensitive) == 0)
{
hotkeys[j].SetPath(hotkey.first.toStdString().c_str());
hotkeys[j].SetSequenceFromString(hotkey.second.toStdString().c_str());
}
}
}
}
settings.endArray();
if (hotkeys.isEmpty())
{
return false;
}
return true;
}
void HotKey_SaveCurrent() override
{
QSettings settings("O3DE", "O3DE");
QString group = "Hotkeys/";
settings.remove("Hotkeys/");
settings.sync();
settings.beginWriteArray(group);
int saveIndex = 0;
for (HotKey key : hotkeys)
{
if (!key.path.isEmpty())
{
settings.setArrayIndex(saveIndex++);
settings.setValue("name", key.path);
settings.setValue("keySequence", key.sequence.toString());
}
}
settings.endArray();
settings.sync();
}
void HotKey_BuildDefaults() override
{
m_hotkeysAreEnabled = true;
QVector<QPair<QString, QString> > keys;
while (hotkeys.count() > 0)
{
hotkeys.takeAt(0);
}
//MENU SELECTION SHORTCUTS////////////////////////////////////////////////
keys.push_back(QPair<QString, QString>("Menus.File Menu", "Alt+F"));
keys.push_back(QPair<QString, QString>("Menus.Edit Menu", "Alt+E"));
keys.push_back(QPair<QString, QString>("Menus.View Menu", "Alt+V"));
//FILE MENU SHORTCUTS/////////////////////////////////////////////////////
keys.push_back(QPair<QString, QString>("File Menu.Create new emitter", "Ctrl+N"));
keys.push_back(QPair<QString, QString>("File Menu.Create new library", "Ctrl+Shift+N"));
keys.push_back(QPair<QString, QString>("File Menu.Create new folder", ""));
keys.push_back(QPair<QString, QString>("File Menu.Import", "Ctrl+I"));
keys.push_back(QPair<QString, QString>("File Menu.Import level library", "Ctrl+Shift+I"));
keys.push_back(QPair<QString, QString>("File Menu.Save", "Ctrl+S"));
keys.push_back(QPair<QString, QString>("File Menu.Close", "Ctrl+Q"));
//EDIT MENU SHORTCUTS/////////////////////////////////////////////////////
keys.push_back(QPair<QString, QString>("Edit Menu.Copy", "Ctrl+C"));
keys.push_back(QPair<QString, QString>("Edit Menu.Paste", "Ctrl+V"));
keys.push_back(QPair<QString, QString>("Edit Menu.Duplicate", "Ctrl+D"));
keys.push_back(QPair<QString, QString>("Edit Menu.Undo", "Ctrl+Z"));
keys.push_back(QPair<QString, QString>("Edit Menu.Redo", "Ctrl+Shift+Z"));
keys.push_back(QPair<QString, QString>("Edit Menu.Group", "Ctrl+G"));
keys.push_back(QPair<QString, QString>("Edit Menu.Ungroup", "Ctrl+Shift+G"));
keys.push_back(QPair<QString, QString>("Edit Menu.Rename", "Ctrl+R"));
keys.push_back(QPair<QString, QString>("Edit Menu.Reset", ""));
keys.push_back(QPair<QString, QString>("Edit Menu.Edit Hotkeys", ""));
keys.push_back(QPair<QString, QString>("Edit Menu.Assign to selected", "Ctrl+Space"));
keys.push_back(QPair<QString, QString>("Edit Menu.Insert Comment", "Ctrl+Alt+M"));
keys.push_back(QPair<QString, QString>("Edit Menu.Enable/Disable Emitter", "Ctrl+E"));
keys.push_back(QPair<QString, QString>("File Menu.Enable All", ""));
keys.push_back(QPair<QString, QString>("File Menu.Disable All", ""));
keys.push_back(QPair<QString, QString>("Edit Menu.Delete", "Del"));
//VIEW MENU SHORTCUTS/////////////////////////////////////////////////////
keys.push_back(QPair<QString, QString>("View Menu.Reset Layout", ""));
//PLAYBACK CONTROL////////////////////////////////////////////////////////
keys.push_back(QPair<QString, QString>("Previewer.Play/Pause Toggle", "Space"));
keys.push_back(QPair<QString, QString>("Previewer.Step forward through time", "c"));
keys.push_back(QPair<QString, QString>("Previewer.Loop Toggle", "z"));
keys.push_back(QPair<QString, QString>("Previewer.Reset Playback", "x"));
keys.push_back(QPair<QString, QString>("Previewer.Focus", "Ctrl+F"));
keys.push_back(QPair<QString, QString>("Previewer.Zoom In", "w"));
keys.push_back(QPair<QString, QString>("Previewer.Zoom Out", "s"));
keys.push_back(QPair<QString, QString>("Previewer.Pan Left", "a"));
keys.push_back(QPair<QString, QString>("Previewer.Pan Right", "d"));
for (QPair<QString, QString> key : keys)
{
unsigned int index = hotkeys.count();
hotkeys.push_back(HotKey());
hotkeys[index].SetPath(key.first.toStdString().c_str());
hotkeys[index].SetSequenceFromString(key.second.toStdString().c_str());
}
}
void HotKey_SetKeys(QVector<HotKey> keys) override
{
hotkeys = keys;
}
QVector<HotKey> HotKey_GetKeys() override
{
return hotkeys;
}
QString HotKey_GetPressedHotkey(const QKeyEvent* event) override
{
if (!m_hotkeysAreEnabled)
{
return "";
}
for (HotKey key : hotkeys)
{
if (HotKey_IsPressed(event, key.path.toUtf8()))
{
return key.path;
}
}
return "";
}
QString HotKey_GetPressedHotkey(const QShortcutEvent* event) override
{
if (!m_hotkeysAreEnabled)
{
return "";
}
for (HotKey key : hotkeys)
{
if (HotKey_IsPressed(event, key.path.toUtf8()))
{
return key.path;
}
}
return "";
}
//building the default hotkey list re-enables hotkeys
//do not use this when rebuilding the default list is a possibility.
void HotKey_SetEnabled(bool val) override
{
m_hotkeysAreEnabled = val;
}
bool HotKey_IsEnabled() const override
{
return m_hotkeysAreEnabled;
}
#pragma endregion
#pragma region ToolTip
protected:
QMap<QString, ToolTip> m_tooltips;
void ToolTip_ParseNode(XmlNodeRef node)
{
if (QString(node->getTag()).compare("tooltip", Qt::CaseInsensitive) != 0)
{
unsigned int childCount = node->getChildCount();
for (unsigned int i = 0; i < childCount; i++)
{
ToolTip_ParseNode(node->getChild(i));
}
}
QString title = node->getAttr("title");
QString content = node->getAttr("content");
QString specialContent = node->getAttr("special_content");
QString disabledContent = node->getAttr("disabled_content");
QMap<QString, ToolTip>::iterator itr = m_tooltips.insert(node->getAttr("path"), ToolTip());
itr->isValid = true;
itr->title = title;
itr->content = content;
itr->specialContent = specialContent;
itr->disabledContent = disabledContent;
unsigned int childCount = node->getChildCount();
for (unsigned int i = 0; i < childCount; i++)
{
ToolTip_ParseNode(node->getChild(i));
}
}
ToolTip GetToolTip(QString path)
{
if (m_tooltips.contains(path))
{
return m_tooltips[path];
}
ToolTip temp;
temp.isValid = false;
return temp;
}
public:
void ToolTip_LoadConfigXML(QString filepath) override
{
XmlNodeRef node = GetIEditor()->GetSystem()->LoadXmlFromFile(filepath.toStdString().c_str());
ToolTip_ParseNode(node);
}
void ToolTip_BuildFromConfig(IQToolTip* tooltip, QString path, QString option, QString optionalData = "", bool isEnabled = true) override
{
AZ_Assert(tooltip, "tooltip cannot be null");
QString title = ToolTip_GetTitle(path, option);
QString content = ToolTip_GetContent(path, option);
QString specialContent = ToolTip_GetSpecialContentType(path, option);
QString disabledContent = ToolTip_GetDisabledContent(path, option);
// Even if these items are empty, we set them anyway to clear out any data that was left over from when the tooltip was used for a different object.
tooltip->SetTitle(title);
tooltip->SetContent(content);
//this only handles simple creation...if you need complex call this then add specials separate
if (!specialContent.contains("::"))
{
tooltip->AddSpecialContent(specialContent, optionalData);
}
if (!isEnabled) // If disabled, add disabled value
{
tooltip->AppendContent(disabledContent);
}
}
QString ToolTip_GetTitle(QString path, QString option) override
{
if (!option.isEmpty() && GetToolTip(path + "." + option).isValid)
{
return GetToolTip(path + "." + option).title;
}
if (!option.isEmpty() && GetToolTip("Options." + option).isValid)
{
return GetToolTip("Options." + option).title;
}
return GetToolTip(path).title;
}
QString ToolTip_GetContent(QString path, QString option) override
{
if (!option.isEmpty() && GetToolTip(path + "." + option).isValid)
{
return GetToolTip(path + "." + option).content;
}
if (!option.isEmpty() && GetToolTip("Options." + option).isValid)
{
return GetToolTip("Options." + option).content;
}
return GetToolTip(path).content;
}
QString ToolTip_GetSpecialContentType(QString path, QString option) override
{
if (!option.isEmpty() && GetToolTip(path + "." + option).isValid)
{
return GetToolTip(path + "." + option).specialContent;
}
if (!option.isEmpty() && GetToolTip("Options." + option).isValid)
{
return GetToolTip("Options." + option).specialContent;
}
return GetToolTip(path).specialContent;
}
QString ToolTip_GetDisabledContent(QString path, QString option) override
{
if (!option.isEmpty() && GetToolTip(path + "." + option).isValid)
{
return GetToolTip(path + "." + option).disabledContent;
}
if (!option.isEmpty() && GetToolTip("Options." + option).isValid)
{
return GetToolTip("Options." + option).disabledContent;
}
return GetToolTip(path).disabledContent;
}
#pragma endregion ToolTip
};
IEditorPanelUtils* CreateEditorPanelUtils()
{
return new CEditorPanelUtils_Impl();
}