You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/LyShine/Code/Editor/EditorWindow.h

426 lines
16 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
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include "EditorCommon.h"
#include "Animation/UiEditorAnimationBus.h"
#include <LyShine/UiEditorDLLBus.h>
#include "UiEditorInternalBus.h"
#include "UiEditorEntityContext.h"
#include "UiSliceManager.h"
#include "ViewportInteraction.h"
#include <QList>
#include <QMetaObject>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzQtComponents/Components/Widgets/TabWidget.h>
#include <LyShine/Bus/UiEditorChangeNotificationBus.h>
#include <IFont.h>
#include <IFileUtil.h>
#endif
QT_FORWARD_DECLARE_CLASS(QUndoGroup)
class AssetTreeEntry;
class EditorWindow
: public QMainWindow
, public IEditorNotifyListener
, public UiEditorDLLBus::Handler
, public UiEditorChangeNotificationBus::Handler
, public UiEditorInternalRequestBus::Handler
, public UiEditorInternalNotificationBus::Handler
, public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler
, public UiEditorEntityContextNotificationBus::Handler
, public AzToolsFramework::EditorEvents::Bus::Handler
, public FontNotificationBus::Handler
, public AZ::Debug::TraceMessageBus::Handler
{
Q_OBJECT
public: // types
struct UiCanvasTabMetadata
{
AZ::EntityId m_canvasEntityId;
};
public: // member functions
explicit EditorWindow(QWidget* parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
virtual ~EditorWindow();
// you are required to implement this to satisfy the unregister/registerclass requirements on "RegisterQtViewPane"
// make sure you pick a unique GUID
static const GUID& GetClassID()
{
// {E72CB9F3-DCB5-4525-AEAC-541A8CC778C5}
static const GUID guid =
{
0xe72cb9f3, 0xdcb5, 0x4525, { 0xae, 0xac, 0x54, 0x1a, 0x8c, 0xc7, 0x78, 0xc5 }
};
return guid;
}
void OnEditorNotifyEvent(EEditorNotifyEvent ev) override;
// UiEditorDLLInterface
LyShine::EntityArray GetSelectedElements() override;
AZ::EntityId GetActiveCanvasId() override;
UndoStack* GetActiveUndoStack() override;
void OpenSourceCanvasFile(QString absolutePathToFile) override;
// ~UiEditorDLLInterface
// UiEditorChangeNotificationBus
void OnEditorTransformPropertiesNeedRefresh() override;
void OnEditorPropertiesRefreshEntireTree() override;
// ~UiEditorChangeNotificationBus
// UiEditorInternalRequestBus
AzToolsFramework::EntityIdList GetSelectedEntityIds() override;
AZ::Entity::ComponentArrayType GetSelectedComponents() override;
AZ::EntityId GetActiveCanvasEntityId() override;
// ~UiEditorInternalRequestBus
// UiEditorInternalNotificationBus
void OnSelectedEntitiesPropertyChanged() override;
void OnBeginUndoableEntitiesChange() override;
void OnEndUndoableEntitiesChange(const AZStd::string& commandText) override;
// ~UiEditorInternalNotificationBus
// AssetBrowserModelNotificationBus
void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
void EntryRemoved(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
// ~AssetBrowserModelNotificationBus
// UiEditorEntityContextNotificationBus
void OnSliceInstantiated(const AZ::Data::AssetId& sliceAssetId, const AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& ticket) override;
void OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAssetId, const AzFramework::SliceInstantiationTicket& ticket) override;
// ~UiEditorEntityContextNotificationBus
// EditorEvents
void OnEscape() override;
// ~EditorEvents
// FontNotifications
void OnFontsReloaded() override;
// ~FontNotifications
// TraceMessageEvents
bool OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) override;
bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override;
// ~TraceMessageEvents
AZ::EntityId GetCanvas();
HierarchyWidget* GetHierarchy();
ViewportWidget* GetViewport();
PropertiesWidget* GetProperties();
MainToolbar* GetMainToolbar();
ModeToolbar* GetModeToolbar();
EnterPreviewToolbar* GetEnterPreviewToolbar();
PreviewToolbar* GetPreviewToolbar();
NewElementToolbarSection* GetNewElementToolbarSection();
CoordinateSystemToolbarSection* GetCoordinateSystemToolbarSection();
CanvasSizeToolbarSection* GetCanvasSizeToolbarSection();
const QCursor& GetEntityPickerCursor();
bool CanExitNow();
UndoStack* GetActiveStack();
AssetTreeEntry* GetSliceLibraryTree();
//! Returns the current mode of the editor (Edit or Preview)
UiEditorMode GetEditorMode() { return m_editorMode; }
//! Returns the UI canvas for the current mode (Edit or Preview)
AZ::EntityId GetCanvasForCurrentEditorMode();
//! Toggle the editor mode between Edit and Preview
void ToggleEditorMode();
//! Get the copy of the canvas that is used in Preview mode (will return invalid entity ID if not in preview mode)
AZ::EntityId GetPreviewModeCanvas() { return m_previewModeCanvasEntityId; }
//! Get the preview canvas size. (0,0) means use viewport size
AZ::Vector2 GetPreviewCanvasSize();
//! Set the preview canvas size. (0,0) means use viewport size
void SetPreviewCanvasSize(AZ::Vector2 previewCanvasSize);
void SaveEditorWindowSettings();
UiSliceManager* GetSliceManager();
UiEditorEntityContext* GetEntityContext();
void ReplaceEntityContext(UiEditorEntityContext* entityContext);
QMenu* createPopupMenu() override;
AZ::EntityId GetCanvasForEntityContext(const AzFramework::EntityContextId& contextId);
//! Open a new tab and instantiate the given slice asset for editing in a special slice editing mode
void EditSliceInNewTab(AZ::Data::AssetId sliceAssetId);
//! Called if an asset has changed and been reloaded (used to detect if slice being edited is different to the one on disk)
void UpdateChangedStatusOnAssetChange(const AzFramework::EntityContextId& contextId, const AZ::Data::Asset<AZ::Data::AssetData>& asset);
//! Called when any entities have been added to or removed from the active canvas
void EntitiesAddedOrRemoved();
//! Called when any font texture has changed since the last render.
//! Forces a render graph update for each loaded canvas
void FontTextureHasChanged();
void RefreshEditorMenu();
void ShowEntitySearchModal();
signals:
void EditorModeChanged(UiEditorMode mode);
void SignalCoordinateSystemCycle();
void SignalSnapToGridToggle();
protected:
void paintEvent(QPaintEvent* paintEvent) override;
void closeEvent(QCloseEvent* closeEvent) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override;
public slots:
void RestoreEditorWindowSettings();
private: // types
struct UiCanvasEditState
{
UiCanvasEditState();
// Viewport
ViewportInteraction::TranslationAndScale m_canvasViewportMatrixProps;
bool m_shouldScaleToFitOnViewportResize;
ViewportInteraction::InteractionMode m_viewportInteractionMode;
ViewportInteraction::CoordinateSystem m_viewportCoordinateSystem;
// Hierarchy
int m_hierarchyScrollValue;
EntityHelpers::EntityIdList m_selectedElements;
// Properties
float m_propertiesScrollValue;
// Animation
UiEditorAnimationStateInterface::UiEditorAnimationEditState m_uiAnimationEditState;
bool m_inited;
};
// Data for a loaded UI canvas
struct UiCanvasMetadata
{
UiCanvasMetadata();
~UiCanvasMetadata();
AZ::EntityId m_canvasEntityId;
AZStd::string m_canvasSourceAssetPathname;
AZStd::string m_canvasDisplayName;
UiEditorEntityContext* m_entityContext;
UndoStack* m_undoStack;
//! Specifies whether this canvas was automatically loaded or loaded by the user
bool m_autoLoaded;
//! Specified whether there were any errors on canvas load
bool m_errorsOnLoad;
//! Specifies whether a canvas has been modified and saved since it was loaded/created
bool m_canvasChangedAndSaved;
//! State of the viewport and other panes (zoom, pan, scroll, selection, ...)
UiCanvasEditState m_canvasEditState;
//! This is true when the canvas tab was opened in order to edit a slice
bool m_isSliceEditing;
//! If m_isSliceEditing is true this is the Asset ID of the slice instance that is being edited
AZ::Data::AssetId m_sliceAssetId;
//! If m_isSliceEditing is true this is the entityId of the one slice instance that is being edited
AZ::EntityId m_sliceEntityId;
};
private: // member functions
QUndoGroup* GetUndoGroup();
bool GetChangesHaveBeenMade(const UiCanvasMetadata& canvasMetadata);
//! Return true when ok.
//! forceAskingForFilename should only be true for "Save As...", not "Save".
bool SaveCanvasToXml(UiCanvasMetadata& canvasMetadata, bool forceAskingForFilename);
//! Saves a slice tab to its slice with a quick push
bool SaveSlice(UiCanvasMetadata& canvasMetadata);
//! Check whether a canvas save should occur even though there were errors on load
bool CanSaveWithErrors(const UiCanvasMetadata& canvasMetadata);
// Called from menu or shortcut key events
void NewCanvas();
void OpenCanvas(const QString& canvasFilename);
void OpenCanvases(const QStringList& canvasFilenames);
void CloseCanvas(AZ::EntityId canvasEntityId);
void CloseAllCanvases();
void CloseAllOtherCanvases(AZ::EntityId canvasEntityId);
bool LoadCanvas(const QString& canvasFilename, bool autoLoad, bool changeActiveCanvasToThis = true);
bool CanUnloadCanvas(UiCanvasMetadata& canvasMetadata);
void UnloadCanvas(AZ::EntityId canvasEntityId);
void UnloadCanvases(const AZStd::vector<AZ::EntityId>& canvasEntityIds);
bool CanChangeActiveCanvas();
void SetActiveCanvas(AZ::EntityId canvasEntityId);
void SaveActiveCanvasEditState();
void RestoreActiveCanvasEditState();
void RestoreActiveCanvasEditStatePostEvents();
void OnCanvasTabCloseButtonPressed(int index);
void OnCurrentCanvasTabChanged(int index);
void OnCanvasTabContextMenuRequested(const QPoint &point);
void UpdateActionsEnabledState();
void SetupShortcuts();
//! Check if the given toolbar should only be shown in preview mode
bool IsPreviewModeToolbar(const QToolBar* toolBar);
//! Check if the given dockwidget should only be shown in preview mode
bool IsPreviewModeDockWidget(const QDockWidget* dockWidget);
QAction* AddMenuAction(const QString& text, bool enabled, QMenu* menu, AZStd::function<void (bool)> function);
void AddMenu_File();
void AddMenuItems_Edit(QMenu* menu);
void AddMenu_Edit();
void AddMenu_View();
void AddMenu_View_LanguageSetting(QMenu* viewMenu);
void AddMenu_Preview();
void AddMenu_PreviewView();
void AddMenu_Help();
void EditorMenu_Open(QString optional_selectedFile);
QAction* CreateSaveCanvasAction(AZ::EntityId canvasEntityId, bool forContextMenu = false);
QAction* CreateSaveCanvasAsAction(AZ::EntityId canvasEntityId, bool forContextMenu = false);
QAction* CreateSaveSliceAction(UiCanvasMetadata *canvasMetadata, bool forContextMenu = false);
QAction* CreateSaveAllCanvasesAction(bool forContextMenu = false);
QAction* CreateCloseCanvasAction(AZ::EntityId canvasEntityId, bool forContextMenu = false);
QAction* CreateCloseAllOtherCanvasesAction(AZ::EntityId canvasEntityId, bool forContextMenu = false);
QAction* CreateCloseAllCanvasesAction(bool forContextMenu = false);
void SaveModeSettings(UiEditorMode mode, bool syncSettings);
void RestoreModeSettings(UiEditorMode mode);
int GetCanvasMaxHierarchyDepth(const LyShine::EntityArray& childElements);
void DeleteSliceLibraryTree();
void DestroyCanvas(const UiCanvasMetadata& canvasMetadata);
bool IsCanvasTabMetadataValidForTabIndex(int index);
AZ::EntityId GetCanvasEntityIdForTabIndex(int index);
int GetTabIndexForCanvasEntityId(AZ::EntityId canvasEntityId);
UiCanvasMetadata* GetCanvasMetadataForTabIndex(int index);
UiCanvasMetadata* GetCanvasMetadata(AZ::EntityId canvasEntityId);
UiCanvasMetadata* GetActiveCanvasMetadata();
AZStd::string GetCanvasDisplayNameFromAssetPath(const AZStd::string& canvasAssetPathname);
void HandleCanvasDisplayNameChanged(const UiCanvasMetadata& canvasMetadata);
void SetupCentralWidget();
void SetupTabbedViewportWidget(QWidget* parent);
void CheckForOrphanedChildren(AZ::EntityId canvasEntityId);
void AddTraceMessage(const char *message, AZStd::list<QString>& messageList);
void ShowTraceMessages(const AZStd::string& canvasName);
void ClearTraceMessages();
private slots:
// Called when the clean state of the active undo stack changes
void CleanChanged(bool clean);
private: // data
QUndoGroup* m_undoGroup;
UiSliceManager* m_sliceManager;
AzQtComponents::TabWidget* m_canvasTabWidget;
QWidget* m_canvasTabSectionWidget;
HierarchyWidget* m_hierarchy;
PropertiesWrapper* m_properties;
ViewportWidget* m_viewport;
CUiAnimViewDialog* m_animationWidget;
PreviewActionLog* m_previewActionLog;
PreviewAnimationList* m_previewAnimationList;
MainToolbar* m_mainToolbar;
ModeToolbar* m_modeToolbar;
EnterPreviewToolbar* m_enterPreviewToolbar;
PreviewToolbar* m_previewToolbar;
QDockWidget* m_hierarchyDockWidget;
QDockWidget* m_propertiesDockWidget;
QDockWidget* m_animationDockWidget;
QDockWidget* m_previewActionLogDockWidget;
QDockWidget* m_previewAnimationListDockWidget;
UiEditorMode m_editorMode;
//! This tree caches the folder view of all the slice assets under the slice library path
AssetTreeEntry* m_sliceLibraryTree = nullptr;
//! Values for setting up undoable canvas/entity changes
SerializeHelpers::SerializedEntryList m_preChangeState;
bool m_haveValidEntitiesPreChangeState = false;
AZStd::string m_canvasUndoXml;
bool m_haveValidCanvasPreChangeState = false;
//! This is used to change the enabled state
//! of these actions as the selection changes.
QList<QAction*> m_actionsEnabledWithSelection;
QAction* m_pasteAsSiblingAction;
QAction* m_pasteAsChildAction;
QList<QAction*> m_actionsEnabledWithAlignAllowed;
AZ::EntityId m_previewModeCanvasEntityId;
AZ::Vector2 m_previewModeCanvasSize;
QMetaObject::Connection m_clipboardConnection;
//! Local copy of QSetting value of startup location of localization folder
QString m_startupLocFolderName;
std::map< AZ::EntityId, UiCanvasMetadata* > m_canvasMetadataMap;
AZ::EntityId m_activeCanvasEntityId;
int m_newCanvasCount;
AZStd::list<QString> m_errors; // the list of errors that occured while loading a canvas
AZStd::list<QString> m_warnings; // the list of warnings that occured while loading a canvas
// Cursor used when picking an element in the hierarchy or viewport during object pick mode
QCursor m_entityPickerCursor;
};
Q_DECLARE_METATYPE(EditorWindow::UiCanvasTabMetadata);