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/LandscapeCanvas/Code/Source/Editor/MainWindow.h

279 lines
15 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.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <CrySystemBus.h>
// AZ
#include <AzCore/Component/EntityBus.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzQtComponents/Components/StyledDockWidget.h>
#include <AzToolsFramework/API/EntityCompositionNotificationBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
#include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
// GraphModel
#include <GraphModel/Integration/EditorMainWindow.h>
// LandscapeCanvas
#include <LandscapeCanvas/LandscapeCanvasBus.h>
#endif
namespace LandscapeCanvasEditor
{
////////////////////////////////////////////////////////////////////////
// Temporary classes for using a custom Pinned Inspector as a Node Inspector
// that will use the selected nodes in the graph to drive the Node Inspector
// based on the corresponding Vegetation Entities. These will be removed
// once a generic Node Inspector has been implemented for the base EditorMainWindow.
class CustomEntityPropertyEditor
: public AzToolsFramework::EntityPropertyEditor
{
public:
AZ_CLASS_ALLOCATOR(CustomEntityPropertyEditor, AZ::SystemAllocator, 0);
CustomEntityPropertyEditor(QWidget* parent = nullptr);
protected:
void CloseInspectorWindow() override;
QString GetEntityDetailsLabelText() const override;
};
class CustomNodeInspectorDockWidget
: public AzQtComponents::StyledDockWidget
{
public:
AZ_CLASS_ALLOCATOR(CustomNodeInspectorDockWidget, AZ::SystemAllocator, 0);
CustomNodeInspectorDockWidget(QWidget* parent = nullptr);
CustomEntityPropertyEditor* GetEntityPropertyEditor();
private:
CustomEntityPropertyEditor* m_propertyEditor = nullptr;
};
////////////////////////////////////////////////////////////////////////
struct LandscapeCanvasConfig
: GraphCanvas::AssetEditorWindowConfig
{
GraphCanvas::GraphCanvasTreeItem* CreateNodePaletteRoot() override;
};
class MainWindow
: public GraphModelIntegration::EditorMainWindow
, protected LandscapeCanvas::LandscapeCanvasRequestBus::Handler
, private AZ::EntitySystemBus::Handler
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
, private AzToolsFramework::EditorPickModeNotificationBus::Handler
, private AzToolsFramework::EntityCompositionNotificationBus::Handler
, private AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler
, private AzToolsFramework::ToolsApplicationNotificationBus::Handler
, private AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
, private CrySystemEventBus::Handler
{
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow() override;
private:
GraphModel::IGraphContextPtr GetGraphContext() const override;
////////////////////////////////////////////////////////////////////////
// GraphModelIntegration::GraphControllerNotificationBus::Handler overrides
void OnGraphModelNodeAdded(GraphModel::NodePtr node) override;
void OnGraphModelNodeRemoved(GraphModel::NodePtr node) override;
void PreOnGraphModelNodeRemoved(GraphModel::NodePtr node) override;
void OnGraphModelConnectionAdded(GraphModel::ConnectionPtr connection) override;
void OnGraphModelConnectionRemoved(GraphModel::ConnectionPtr connection) override;
void OnGraphModelNodeWrapped(GraphModel::NodePtr wrapperNode, GraphModel::NodePtr node) override;
void OnGraphModelGraphModified(GraphModel::NodePtr node) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// GraphModelIntegration::EditorMainWindow overrides ...
void OnEditorOpened(GraphCanvas::EditorDockWidget* dockWidget) override;
void OnEditorClosing(GraphCanvas::EditorDockWidget* dockWidget) override;
QAction* AddFileNewAction(QMenu* menu) override;
QAction* AddFileOpenAction(QMenu* menu) override;
QAction* AddFileSaveAction(QMenu* menu) override;
QAction* AddFileSaveAsAction(QMenu* menu) override;
QMenu* AddEditMenu() override;
void HandleWrapperNodeActionWidgetClicked(GraphModel::NodePtr wrapperNode, const QRect& actionWidgetBoundingRect, const QPointF& scenePoint, const QPoint& screenPoint) override;
GraphCanvas::Endpoint CreateNodeForProposal(const AZ::EntityId& connectionId, const GraphCanvas::Endpoint& endpoint, const QPointF& scenePoint, const QPoint& screenPoint) override;
void OnSelectionChanged() override;
void OnEntitiesSerialized(GraphCanvas::GraphSerialization& serializationTarget) override;
void OnEntitiesDeserialized(const GraphCanvas::GraphSerialization&) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AZ::EntitySystemBus
void OnEntityActivated(const AZ::EntityId& entityId) override;
void OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) override;
////////////////////////////////////////////////////////////////////////
bool HandleGraphOpened(const AZ::EntityId& rootEntityId, const GraphCanvas::DockWidgetId& dockWidgetId);
////////////////////////////////////////////////////////////////////////
// AssetEditorRequestBus::Handler overrides
GraphCanvas::ContextMenuAction::SceneReaction ShowNodeContextMenu(const AZ::EntityId& nodeId, const QPoint& screenPoint, const QPointF& scenePoint) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// LandscapeCanvas::LandscapeCanvasRequestBus::Handler overrides
GraphCanvas::GraphId OnGraphEntity(const AZ::EntityId& entityId) override;
GraphModel::NodePtr GetNodeMatchingEntityInGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityId& entityId) override;
GraphModel::NodePtr GetNodeMatchingEntityComponentInGraph(const GraphCanvas::GraphId& graphId, const AZ::EntityComponentIdPair& entityComponentId) override;
GraphModel::NodePtrList GetAllNodesMatchingEntity(const AZ::EntityId& entityId) override;
GraphModel::NodePtrList GetAllNodesMatchingEntityComponent(const AZ::EntityComponentIdPair& entityComponentId) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// GraphCanvas::AssetEditorMainWindow overrides
bool ConfigureDefaultLayout() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorEntityContextNotificationBus overrides
void OnEditorEntityCreated(const AZ::EntityId& entityId) override;
void OnEditorEntityDeleted(const AZ::EntityId& entityId) override;
////////////////////////////////////////////////////////////////////////
void HandleEditorEntityCreated(const AZ::EntityId& entityId, GraphCanvas::GraphId graphId = GraphCanvas::GraphId());
void QueuedEditorEntityDeleted(const AZ::EntityId& entityId);
void HandleEditorEntityDeleted(const AZ::EntityId& entityId);
////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorPickModeNotificationBus overrides
void OnEntityPickModeStarted() override;
void OnEntityPickModeStopped() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EntityCompositionNotificationBus overrides
void OnEntityComponentAdded(const AZ::EntityId& entityId, const AZ::ComponentId& componentId) override;
void OnEntityComponentRemoved(const AZ::EntityId& entityId, const AZ::ComponentId& componentId) override;
void OnEntityComponentEnabled(const AZ::EntityId& entityId, const AZ::ComponentId& componentId) override;
void OnEntityComponentDisabled(const AZ::EntityId& entityId, const AZ::ComponentId& componentId) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AzToolsFramework::PropertyEditorEntityChangeNotificationBus overrides
void OnEntityComponentPropertyChanged(AZ::ComponentId changedComponentId) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AzToolsFramework::ToolsApplicationNotificationBus overrides
void EntityParentChanged(AZ::EntityId entityId, AZ::EntityId newParentId, AZ::EntityId oldParentId) override;
////////////////////////////////////////////////////////////////////////
//! PrefabPublicNotificationBus overrides
void OnPrefabInstancePropagationBegin() override;
void OnPrefabInstancePropagationEnd() override;
////////////////////////////////////////////////////////////////////////
// CrySystemEventBus overrides
void OnCryEditorEndCreate() override;
void OnCryEditorEndLoad() override;
void OnCryEditorCloseScene() override;
void OnCryEditorSceneClosed() override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// GraphCanvas::AssetEditorNotificationBus overrides
void PostOnActiveGraphChanged() override;
////////////////////////////////////////////////////////////////////////
void GetChildrenTree(const AZ::EntityId& rootEntityId, AzToolsFramework::EntityIdList& childrenList);
QString GetPropertyPathForSlot(GraphModel::SlotPtr slot, GraphModel::DataType::Enum dataType, int elementIndex = 0);
void UpdateConnectionData(GraphModel::ConnectionPtr connection, bool added);
AZ::u32 GetWrappedNodeLayoutOrder(GraphModel::NodePtr node);
AZ::EntityId GetRootEntityIdForGraphId(const GraphCanvas::GraphId& graphId);
AZ::ComponentId AddComponentTypeIdToEntity(const AZ::EntityId& entityId, AZ::TypeId componentToAddTypeId);
void AddComponentForNode(GraphModel::NodePtr node, const AZ::EntityId& entityId);
void HandleNodeCreated(GraphModel::NodePtr node);
void HandleNodeAdded(GraphModel::NodePtr node);
using EntityIdNodeMap = AZStd::unordered_map<AZ::EntityId, GraphModel::NodePtr>;
using EntityIdNodeMaps = AZStd::vector<EntityIdNodeMap>;
enum EntityIdNodeMapEnum
{
Invalid = -1,
Shapes = 0,
Gradients,
VegetationAreas,
Count
};
using EntityComponentCallback = AZStd::function<void(const AZ::EntityId& entityId, AZ::Component* component, bool isDisabled)>;
using NodeSlotPair = AZStd::pair<GraphModel::NodePtr, GraphModel::SlotPtr>;
using ConnectionsList = AZStd::vector<AZStd::pair<NodeSlotPair, NodeSlotPair>>;
void UpdateEntityIdNodeMap(GraphCanvas::GraphId, GraphModel::NodePtr node);
EntityIdNodeMap* GetEntityIdNodeMap(GraphCanvas::GraphId, GraphModel::NodePtr node);
void ParseNodeConnections(GraphCanvas::GraphId graphId, GraphModel::NodePtr node, ConnectionsList& connections);
void UpdateConnections(GraphModel::NodePtr node);
GraphCanvas::GraphId FindGraphContainingEntity(const AZ::EntityId& entityId);
void EnumerateEntityComponentTree(const AZ::EntityId& rootEntityId, EntityComponentCallback callback);
void InitialEntityGraph(const AZ::EntityId& entityId, GraphCanvas::GraphId graphId);
GraphModel::NodePtrList RefreshEntityComponentNodes(const AZ::EntityId& targetEntityId, GraphCanvas::GraphId graphId);
void PlaceNewNode(GraphCanvas::GraphId graphId, LandscapeCanvas::BaseNode::BaseNodePtr node);
int GetInboundDataSlotIndex(GraphModel::NodePtr node, GraphModel::DataTypePtr dataType, GraphModel::SlotPtr targetSlot);
//! Determines whether or not we should allow the user to interact with the graph
//! This should be disabled when there is no level currently loaded
void UpdateGraphEnabled();
//! Return the input data slot on the node that matches the specified data type for the specified index.
//! - If this is a normal slot, it will just return the appropriate slot that is found.
//! - If this is an extendable slot, then slot(s) may need to be added in order to satisfy the requested index.
GraphModel::SlotPtr EnsureInboundDataSlotWithIndex(GraphCanvas::GraphId graphId, GraphModel::NodePtr node, GraphModel::DataTypePtr dataType, int index);
AZ::SerializeContext* m_serializeContext = nullptr;
bool m_ignoreGraphUpdates = false;
bool m_prefabPropagationInProgress = false;
bool m_inObjectPickMode = false;
using DeletedNodePositionsMap = AZStd::unordered_map<AZ::EntityComponentIdPair, AZ::Vector2>;
AZStd::unordered_map<GraphCanvas::GraphId, DeletedNodePositionsMap> m_deletedNodePositions;
AzToolsFramework::EntityIdList m_queuedEntityDeletes;
AZStd::unordered_map<AZ::Uuid, AZ::u32> m_wrappedNodeLayoutOrderMap;
/// Keep track of the dock widget for the graph that represents the Vegetation Entity
AZStd::unordered_map<AZ::EntityId, GraphCanvas::DockWidgetId> m_dockWidgetsByEntity;
/// Keep track of the EntityId/Node mappings per graph for performance reasons so that we
/// don't have to parse through all the nodes in a graph to find right one when connecting
/// slots based on the EntityId fields in the component properties. The mappings are tracked
/// by type as well for faster lookup since the slot data types are separated (shape, gradient, area).
AZStd::unordered_map<GraphCanvas::GraphId, EntityIdNodeMaps> m_entityIdNodeMapsByGraph;
CustomNodeInspectorDockWidget* m_customNodeInspector = nullptr;
QAction* m_fileNewAction = nullptr;
};
}