/* * 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 #include // AZ #include #include #include #include #include #include #include #include #include #include // GraphModel #include // LandscapeCanvas #include 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 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(AzToolsFramework::PickModeConfiguration pickModeConfiguration) 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; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // CrySystemEventBus overrides void OnCryEditorEndCreate() override; void OnCryEditorEndLoad() 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; using EntityIdNodeMaps = AZStd::vector; enum EntityIdNodeMapEnum { Invalid = -1, Shapes = 0, Gradients, VegetationAreas, Count }; using EntityComponentCallback = AZStd::function; using NodeSlotPair = AZStd::pair; using ConnectionsList = AZStd::vector>; 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_inObjectPickMode = false; using DeletedNodePositionsMap = AZStd::unordered_map; AZStd::unordered_map m_deletedNodePositions; AzToolsFramework::EntityIdList m_queuedEntityDeletes; AZStd::unordered_map m_wrappedNodeLayoutOrderMap; /// Keep track of the dock widget for the graph that represents the Vegetation Entity AZStd::unordered_map 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 m_entityIdNodeMapsByGraph; CustomNodeInspectorDockWidget* m_customNodeInspector = nullptr; QAction* m_fileNewAction = nullptr; }; }